git.fiddlerwoaroof.com
derived/ast-builders.scm
4e987026
 ;;; These functions build non-trivial ast structure.
 
 ;;; Prelude functions: booleans
 
 (define (**== e1 e2)
   (**app (**var/def (core-symbol "==")) e1 e2))
 
 (define (**<= e1 e2)
   (**app (**var/def (core-symbol "<=")) e1 e2))
 
 (define (**< e1 e2)
   (**app (**var/def (core-symbol "<")) e1 e2))
 
 (define (**> e1 e2)
   (**app (**var/def (core-symbol ">")) e1 e2))
 
 (define (**and e1 e2)
   (**app (**var/def (core-symbol "&&")) e1 e2))
 
 (define (**or e1 e2)
   (**app (**var/def (core-symbol "||")) e1 e2))
 
 (define (**true) (**con/def (core-symbol "True")))
 
 (define (**false) (**con/def (core-symbol "False")))
 
 ;; Tuples
 
 (define (**tuple2 x y)
   (**app (**con/def (tuple-constructor 2)) x y))
 
 (define (**tupleN exps)
   (**app/l (**con/def (tuple-constructor (length exps))) exps))
 
 ;; Arithmetic
 
 (define (**+ x y)
   (**app (**var/def (core-symbol "+")) x y))
 
 (define (**+/Int x y)
   (**app (**var/def (core-symbol "primPlusInt")) x y))
 
 (define (**- x y)
   (**app (**var/def (core-symbol "-")) x y))
 
 (define (**1+ x)
   (**+ x (**int 1)))
 
 ;; Lists
 
 (define (**cons x y)
   (**app (**con/def (core-symbol ":")) x y))
 
 (define (**null)
   (**con/def (core-symbol "Nil")))
 
 (define (**list . args)
   (**list/l args))
 
 (define (**list/l args)
   (if (null? args)
       (**null)
       (**cons (car args)
 	      (**list/l (cdr args)))))
 
 (define (**list/pattern pats)
   (if (null? pats)
       (**pcon/def (core-symbol "Nil") '())
       (**pcon/def (core-symbol ":")
 		  (list (car pats) (**list/pattern (cdr pats))))))
 
 (define (**append . lists)
   (**append/l lists))
 
 (define (**append/l lists)
   (if (null? (cdr lists))
       (car lists)
       (**app (**var/def (core-symbol "++"))
 	     (car lists)
 	     (**append/l (cdr lists)))))
 
 (define (**take n l)
   (**app (**var/def (core-symbol "take")) n l))
 
 (define (**drop n l)
   (**app (**var/def (core-symbol "drop")) n l))
 
 ;; Functionals
 
 (define (**dot fn . args)
   (**dot/l fn args))
 
 (define (**dot/l fn args)
  (if (null? args)
      fn
      (**app (**var/def (core-symbol ".")) fn (**dot/l (car args) (cdr args)))))
 
 ;; Printing
 
 (define (**showChar x)
   (**app (**var/def (core-symbol "showChar")) x))
 
 (define (**space)
   (**showChar (**char #\ )))
 
 (define (**comma)
   (**showChar (**char #\,)))
 
 (define (**showsPrec x y)
   (**app (**var/def (core-symbol "showsPrec")) x y))
 
 (define (**shows x)
   (**app (**var/def (core-symbol "shows")) x))
 
 (define (**showString x)
   (**app (**var/def (core-symbol "showString")) x))
 
 (define (**showParen x y)
   (**app (**var/def (core-symbol "showParen")) x y))
 
 ;; Reading
 
 (define (**readsPrec x y)
   (**app (**var/def (core-symbol "readsPrec")) x y))
 
 (define (**lex x)
   (**app (**var/def (core-symbol "lex")) x))
 
 (define (**readParen bool fn r)
   (**app (**var/def (core-symbol "readParen")) bool fn r))
 
 (define (**reads s)
   (**app (**var/def (core-symbol "reads")) s))
 
 ;;; Binary
 
 (define (**showBinInt i b)
   (**app (**var/def (core-symbol "primShowBinInt")) i b))
 
 (define (**readBinSmallInt max b)
   (**app (**var/def (core-symbol "primReadBinSmallInt")) max b))
 
 (define (**showBin x b)
   (**app (**var/def (core-symbol "showBin")) x b))
 
 (define (**readBin b)
   (**app (**var/def (core-symbol "readBin")) b))
 
 ;;; Some higher level code generators
 
 ;;; foldr  (expanded inline)
 
 (define (**foldr build-fn terms init)
   (if (null? terms)
       init
       (funcall build-fn (car terms) (**foldr build-fn (cdr terms) init))))
 
 ;;; Unlike foldr, this uses two sets of args to avoid tupling
 
 (define (**foldr2 build-fn terms1 terms2 init-fn)
   (if (null? (cdr terms1))
       (funcall init-fn (car terms1) (car terms2))
       (funcall build-fn (car terms1) (car terms2)
 	      (**foldr2 build-fn (cdr terms1) (cdr terms2) init-fn))))
 
 ;;; Enum
 
 (define (**enumFrom x)
   (**app (**var/def (core-symbol "enumFrom")) x))
 
 (define (**enumFromThen from then)
   (**app (**var/def (core-symbol "enumFromThen")) from then))
 
 (define (**enumFromTo from to)
   (**app (**var/def (core-symbol "enumFromTo")) from to))
 
 (define (**enumFromThenTo from then to)
   (**app (**var/def (core-symbol "enumFromThenTo")) from then to))
 
 ;;; Cast overrides the type system
 
 (define (**cast x)
   (make cast (exp x)))
 
 ;;; Case.  This also generates the alts.  All variants of case generate
 ;;; an arm for each constructor in a datatype.  This arm can be selected
 ;;; by pattern matching a value of the type, with all fields bound to vars,
 ;;; or with numbered or named selections.
 
 ;;; The fn always generates the arms given the constructor.  In the /con case,
 ;;; the fn also gets the variable list of values bound in the fields.
 
 (define (**case/con alg exp fn)
   (**case exp
 	  (map (lambda (con)
 		 (let* ((arity (con-arity con))
 			(vars (temp-vars "x" arity)))
 		   (**alt/simple (**pat (cons con vars))
 				 (funcall fn con vars))))
 	       (algdata-constrs alg))))
 
 ;;; Selectors are integers (used for Bin)
 
 (define (**case/int alg exp fn)
   (**case exp
     (map (lambda (con)
 	   (**alt/simple
 	      (**pat (con-tag con))
 	      (funcall fn con)))
 	 (algdata-constrs alg))))
 
 ;;; Selectors are strings (Text)
 
 (define (**case/strings alg exp fn)
   (**case exp
     (map (lambda (con)
 	   (**alt/simple
 	    (**pat (remove-con-prefix (symbol->string (def-name con))))
 	    (funcall fn con)))
 	 (algdata-constrs alg))))
 
 ;;; Definitions containing multi-body
 
 (define (**multi-define fname alg nullary-fn single-fn
 			          combine-fn else-val)
   (**define/multiple fname
     (append
       (map (lambda (con) (**define/2 con nullary-fn single-fn combine-fn))
 	     (algdata-constrs alg))
       (if (not (eq? else-val '#f))
 	  `(((_ _) ,(funcall else-val)))
 	  '()))))
 
 (define (**define/2 con nullary-fn single-fn combine-fn)
   (let* ((arity (con-arity con))
 	 (vars1 (temp-vars "l" arity))
 	 (vars2 (temp-vars "r" arity)))
     `(((,con ,@vars1) (,con ,@vars2))
       ,(if (eqv? arity 0)
 	   (funcall nullary-fn)
 	   (**foldr2 combine-fn (suspend-vars vars1) (suspend-vars vars2)
 			   single-fn)))))
 
 (define (**define/multiple fn args)
   (make valdef
 	(lhs (**pat fn))
 	(definitions
           (map (lambda (arg)
 		 (make single-fun-def
 		       (args (map (function **pat) (car arg)))
 		       (rhs-list (list (make guarded-rhs
 					     (guard (**omitted-guard))
 					     (rhs (cadr arg)))))
 		       (where-decls '())
 		       (infix? '#f)))
 	       args))))
 
 (define (suspend-vars vars) (map (lambda (v) (lambda () (**var v))) vars))
 
 (define (temp-vars root arity)
   (temp-vars1 root 1 arity))
 
 (define (temp-vars1 root i arity)
   (if (> i arity)
       '()
       (cons (string->symbol (string-append root (number->string i)))
 	    (temp-vars1 root (1+ i) arity))))
        
 (define (tuple-con algdata)
   (car (algdata-constrs algdata)))
 
 (define (con-string x)
   (remove-con-prefix (symbol->string (def-name x))))