git.fiddlerwoaroof.com
Raw Blame History
;;; 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)))))