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