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))))
|