git.fiddlerwoaroof.com
util/constructors.scm
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)))))