4e987026 |
;;; This file contains ast construction functions. These
;;; functions are supplied for commonly used ast structures to
;;; avoid the longer `make' normally required.
;;; Function names are the type names with a `**' prefix. For reference
;;; nodes, the /def for builds the node from a definition instead of a name.
;;; Note: maybe these should be made automagicly someday.
;;; from exp-structs:
(define (**lambda args body)
(**lambda/pat (map (function **pat) args) body))
(define (**lambda/pat pats body)
(if (null? pats)
body
(make lambda (pats pats) (body body))))
;;; Make a case expression.
(define (**case exp alts)
(make case (exp exp) (alts alts)))
(define (**alt/simple pat exp)
(**alt pat
(list (make guarded-rhs
(guard (make omitted-guard))
(rhs exp)))
'()))
(define (**alt pat rhs-list where-decls)
(make alt (pat pat) (rhs-list rhs-list) (where-decls where-decls)))
(define (**let decls body)
(if decls
(make let (decls decls) (body body))
body))
(define (**if test then-exp else-exp)
(make if (test-exp test) (then-exp then-exp) (else-exp else-exp)))
(define (**app fn . args) ; any number of args
(**app/l fn args))
(define (**app/l fn args) ; second args is a list
(if (null? args)
fn
(**app/l (make app (fn fn) (arg (car args)))
(cdr args))))
(define (**var name)
(make var-ref (name name) (var (dynamic *undefined-def*)) (infix? '#f)))
(define (**var/def def) ; arg is an entry
(make var-ref (var def) (name (def-name def)) (infix? '#f)))
(define (**con/def def)
(make con-ref (name (def-name def)) (con def) (infix? '#f)))
(define (**int x)
(make integer-const (value x)))
(define (**char x)
(make char-const (value x)))
(define (**string x)
(make string-const (value x)))
(define (**listcomp exp quals)
(make list-comp (exp exp) (quals quals)))
(define (**gen pat exp)
(make qual-generator (pat (**pat pat)) (exp exp)))
(define (**omitted-guard)
(make omitted-guard))
(define (**con-number exp algdata)
(make con-number (type algdata) (value exp)))
(define (**sel con exp i)
(make sel (constructor con) (value exp) (slot i)))
(define (**is-constructor exp con)
(make is-constructor (value exp) (constructor con)))
;;; From valdef-structs
(define (**signdecl vars type)
(make signdecl (vars (map (function **var) vars)) (signature type)))
(define (**signdecl/def vars type)
(make signdecl (vars (map (function **var/def) vars)) (signature type)))
(define (**define name args val)
(**valdef (**pat name) (map (function **pat) args) val))
(define (**valdef/def var exp)
(**valdef/pat (**var-pat/def var) exp))
(define (**valdef/pat pat exp)
(**valdef pat '() exp))
(define (**valdef lhs args rhs)
(make valdef
(lhs lhs)
(definitions
(list (make single-fun-def
(args args)
(rhs-list
(list (make guarded-rhs
(guard (**omitted-guard))
(rhs rhs))))
(where-decls '())
(infix? '#f))))))
;;; Patterns (still in valdef-structs)
;;; The **pat function converts a very simple lisp-style pattern representation
;;; into corresponding ast structure. The conversion:
;;; a) _ => wildcard
;;; b) a symbol => Var pattern
;;; c) an integer / string => const pattern
;;; d) a list of pats starting with 'tuple => Pcon
;;; e) a list of pats starting with a con definition => Pcon
(define (**pat v)
(cond ((eq? v '_) (**wildcard-pat))
((symbol? v)
(make var-pat (var (**var v))))
((var? v)
(make var-pat (var (**var/def v))))
((integer? v)
(make const-pat (value (**int v))))
((string? v)
(make const-pat (value (**string v))))
((and (pair? v) (eq? (car v) 'tuple))
(**pcon/tuple (map (function **pat) (cdr v))))
((and (pair? v) (con? (car v)))
(**pcon/def (car v) (map (function **pat) (cdr v))))
(else
(error "Bad pattern in **pat: ~A~%" v))))
(define (**pcon name pats)
(make pcon (name (add-con-prefix/symbol name))
(con (dynamic *undefined-def*)) (pats pats) (infix? '#f)))
(define (**pcon/def def pats)
(make pcon (name (def-name def)) (con def) (pats pats) (infix? '#f)))
(define (**pcon/tuple pats)
(**pcon/def (tuple-constructor (length pats)) pats))
;;; Make a variable pattern from the var
(define (**var-pat/def var)
(make var-pat
(var (**var/def var))))
(define (**wildcard-pat)
(make wildcard-pat))
;;; Either make a tuple, or return the single element of a list.
(define (**tuple-pat pats)
(cond ((null? pats)
(**pcon/def (core-symbol "UnitConstructor") '()))
((null? (cdr pats))
(car pats))
(else
(**pcon/tuple pats))))
;;; From type-structs.scm
(define (**tycon name args)
(make tycon (name name) (args args) (def (dynamic *undefined-def*))))
(define (**tycon/def def args)
(make tycon (name (def-name def)) (def def) (args args)))
(define (**tyvar name)
(make tyvar (name name)))
(define (**signature context type)
(make signature (context context) (type type)))
(define (**class/def def)
(make class-ref (name (def-name def)) (class def)))
(define (**context tycls tyvar)
(make context (class tycls) (tyvar tyvar)))
;;; From tc-structs
(define (**ntyvar)
(make ntyvar (value '#f) (context '()) (dict-params '())))
(define (**ntycon tycon args)
(make ntycon (tycon tycon) (args args)))
(define (**arrow . args)
(**arrow/l args))
(define (**arrow/l args)
(if (null? (cdr args))
(car args)
(**ntycon (core-symbol "Arrow")
(list (car args) (**arrow/l (cdr args))))))
(define (**arrow/l-2 args final-val)
(if (null? args)
final-val
(**ntycon (core-symbol "Arrow")
(list (car args) (**arrow/l-2 (cdr args) final-val)))))
(define (**list-of arg)
(**ntycon (core-symbol "List") (list arg)))
(define (**recursive-placeholder var edecls)
(make recursive-placeholder (var var) (exp '#f)
(enclosing-decls edecls)))
(define (**dict-placeholder class tyvar edecls var)
(make dict-placeholder
(class class) (exp '#f) (overloaded-var var)
(tyvar tyvar) (enclosing-decls edecls)))
(define (**method-placeholder method tyvar edecls var)
(make method-placeholder
(method method) (exp '#f) (overloaded-var var)
(tyvar tyvar) (enclosing-decls edecls)))
;;; Some less primitive stuff
(define (**tuple-sel n i exp) ;; 0 <= i < n
(if (eqv? n 1)
exp
(**sel (tuple-constructor n) exp i)))
(define (**abort msg)
(**app (**var/def (core-symbol "error"))
(**string msg)))
(define (**tuple/l args)
(cond ((null? args)
(**con/def (core-symbol "UnitConstructor")))
((null? (cdr args))
(car args))
(else
(**app/l (**con/def (tuple-constructor (length args)))
args))))
(define (**tuple . args)
(**tuple/l args))
(define (**tuple-type/l args)
(cond ((null? args)
(**tycon/def (core-symbol "UnitConstructor") '()))
((null? (cdr args))
(car args))
(else
(**tycon/def (tuple-tycon (length args)) args))))
(define (**tuple-type . args)
(**tuple-type/l args))
(define (**arrow-type . args)
(**arrow-type/l args))
(define (**arrow-type/l args)
(if (null? (cdr args))
(car args)
(**tycon/def (core-symbol "Arrow") (list (car args)
(**arrow-type/l (cdr args))))))
(define (**fromInteger x)
(**app (**var/def (core-symbol "fromInteger")) x))
(define (**fromRational x)
(**app (**var/def (core-symbol "fromRational")) x))
(define (**gtyvar n)
(make gtyvar (varnum n)))
(define (**gtype context type)
(make gtype (context context) (type type)))
(define (**fixity a p)
(make fixity (associativity a) (precedence p)))
(define (**ntycon/tuple . args)
(let ((arity (length args)))
(**ntycon (tuple-tycon arity) args)))
(define (**ntycon/arrow . args)
(**ntycon/arrow-l args))
(define (**ntycon/arrow-l args)
(let ((arg (if (integer? (car args))
(**gtyvar (car args))
(car args))))
(if (null? (cdr args))
arg
(**arrow arg (**ntycon/arrow-l (cdr args))))))
(define (**save-old-exp old new)
(make save-old-exp (old-exp old) (new-exp new)))
;;; These are used by the CFN.
(define (**case-block block-name exps)
(make case-block
(block-name block-name)
(exps exps)))
(define (**return-from block-name exp)
(make return-from
(block-name block-name)
(exp exp)))
(define (**and-exp . exps)
(cond ((null? exps)
(**con/def (core-symbol "True")))
((null? (cdr exps))
(car exps))
(else
(make and-exp (exps exps)))))
|