racket/collects/honu/tenv.ss
Carl Eastlund 728f65e9af Honu:
- test.ss
  - Special case, short error messages if test files not found
- parsers/parse.ss
  - Removed make-struct-type-decls and make-struct-exports
    (at Stevie's instruction: functionality duplicated elsewhere)
- tenv.ss, ast.ss, compile.ss
  - linewrapped code and comments to 100 columns or less

svn: r928
2005-09-28 19:56:44 +00:00

242 lines
11 KiB
Scheme

(module tenv mzscheme
(require (all-except (lib "list.ss" "srfi" "1") any)
(lib "boundmap.ss" "syntax")
(lib "contract.ss")
"ast.ss"
"parameters.ss"
"readerr.ss")
(provide (struct tenv:entry (stx))
(struct tenv:init (name type optional?))
(struct tenv:member (stx name type))
(struct tenv:type (supers members inherited))
(struct tenv:class (sub-type impls inits final? super))
(struct tenv:mixin (arg-type sub-type impls inits
withs final?))
(struct tenv:value (type)))
(define-struct tenv:entry (stx) #f)
(define-struct tenv:init (name type optional?) #f)
(define-struct tenv:member (stx name type) #f)
;; members will be a hashtable from member names to types
;; -- if I ever get around to it
(define-struct (tenv:type tenv:entry) (supers members inherited) #f)
(define-struct (tenv:class tenv:entry) (sub-type impls inits final? super) #f)
(define-struct (tenv:mixin tenv:entry) (arg-type sub-type impls inits
withs final?) #f)
;; this is for top-level function and value bindings
(define-struct (tenv:value tenv:entry) (type) #f)
(define builtin-list
(list (cons #'error (make-honu:type-func #f
(make-honu:type-prim #f 'string)
(make-honu:type-bot #f)))
(cons #'printString (make-honu:type-func #f
(make-honu:type-prim #f 'string)
(make-honu:type-tuple #f '())))
(cons #'printLine (make-honu:type-func #f
(make-honu:type-prim #f 'string)
(make-honu:type-tuple #f '())))
(cons #'readChar (make-honu:type-func #f
(make-honu:type-tuple #f '())
(make-honu:type-prim #f 'char)))
(cons #'readLine (make-honu:type-func #f
(make-honu:type-tuple #f '())
(make-honu:type-prim #f 'string)))
(cons #'intToString (make-honu:type-func #f
(make-honu:type-prim #f 'int)
(make-honu:type-prim #f 'string)))
(cons #'floatToString (make-honu:type-func #f
(make-honu:type-prim #f 'float)
(make-honu:type-prim #f 'string)))
(cons #'charToString (make-honu:type-func #f
(make-honu:type-prim #f 'char)
(make-honu:type-prim #f 'string)))
(cons #'stringToInt (make-honu:type-func #f
(make-honu:type-prim #f 'string)
(make-honu:type-prim #f 'int)))
(cons #'stringToFloat (make-honu:type-func #f
(make-honu:type-prim #f 'string)
(make-honu:type-prim #f 'float)))
(cons #'strlen (make-honu:type-func #f
(make-honu:type-prim #f 'string)
(make-honu:type-prim #f 'int)))
(cons #'substr (make-honu:type-func #f
(make-honu:type-tuple #f
(list (make-honu:type-prim #f 'string)
(make-honu:type-prim #f 'int)
(make-honu:type-prim #f 'int)))
(make-honu:type-prim #f 'string)))
(cons #'charAt (make-honu:type-func #f
(make-honu:type-tuple #f
(list (make-honu:type-prim #f 'string)
(make-honu:type-prim #f 'int)))
(make-honu:type-prim #f 'char)))
(cons #'sqrt (make-honu:type-func #f
(make-honu:type-prim #f 'float)
(make-honu:type-prim #f 'float)))
))
(provide tenv?)
(define tenv? bound-identifier-mapping?)
(provide/contract [printable-key (identifier? . -> . symbol?)]
[tenv-key=? (identifier? identifier? . -> . any)]
[tenv-key<? (identifier? identifier? . -> . any)]
[tenv-map (tenv?
(identifier? tenv:entry? . -> . any)
. -> .
list?)]
[tenv-for-each (tenv?
(identifier? tenv:entry? . -> . void?)
. -> .
void?)])
(define printable-key syntax-e)
(define tenv-key=? bound-identifier=?)
(define (tenv-key<? k1 k2)
(string<? (symbol->string (syntax-e k1))
(symbol->string (syntax-e k2))))
(define tenv-map bound-identifier-mapping-map)
(define tenv-for-each bound-identifier-mapping-for-each)
(provide/contract [empty-tenv (-> tenv?)]
[get-builtin-lenv (-> tenv?)]
[extend-tenv (identifier? tenv:entry? . -> . void?)]
[extend-lenv (identifier? tenv:value? . -> . void?)]
[extend-tenv-without-checking (identifier? tenv:entry? . -> . void?)])
(define (empty-tenv) (make-bound-identifier-mapping))
(define (get-builtin-lenv)
(create-tenv (map car builtin-list)
(map (lambda (p)
(make-tenv:value (car p) (cdr p))) builtin-list)))
(define (extend-tenv key val)
(extend-tenv/checks key val (current-type-environment)))
(define (extend-lenv key val)
(extend-tenv/checks key val (current-lexical-environment)))
(define (extend-tenv-without-checking key val)
(extend-tenv/no-checks key val (current-type-environment)))
(define (extend-tenv/checks key val tenv)
(if (bound-identifier-mapping-get tenv key (lambda () #f))
(if (eqv? (string-ref (symbol->string (printable-key key)) 0) #\$)
(raise-read-error-with-stx
(format "~a already bound by a subclass or substruct"
(substring (symbol->string (printable-key key)) 1))
key)
(raise-read-error-with-stx
(format "~a already bound by top-level definition" (printable-key key))
key))
(bound-identifier-mapping-put! tenv key val)))
(define (extend-tenv/no-checks key val tenv)
(bound-identifier-mapping-put! tenv key val))
(define (create-tenv keys vals)
(let ((table (empty-tenv)))
(begin (for-each (lambda (k v)
(extend-tenv/checks k v table))
keys vals)
table)))
;; only use this if you a) don't want an error or b) don't know what you should get.
(provide/contract [get-tenv-entry (identifier? . -> . (union tenv:entry? false/c))]
[get-lenv-entry (identifier? . -> . (union tenv:entry? false/c))])
(define (get-tenv-entry key)
(bound-identifier-mapping-get (current-type-environment) key (lambda () #f)))
(define (get-lenv-entry key)
(bound-identifier-mapping-get (current-lexical-environment) key (lambda () #f)))
(provide/contract [get-type-entry ((union honu:type-iface?
honu:type-iface-top?) . -> . tenv:type?)]
[get-class-entry (identifier? . -> . tenv:class?)]
[get-mixin-entry (identifier? . -> . tenv:mixin?)]
[get-member-type ((union honu:type-iface?
honu:type-iface-top?)
identifier? . -> . honu:type?)]
[get-value-entry (identifier? . -> . tenv:value?)])
(define (get-type-entry type)
(if (honu:type-iface-top? type)
(make-tenv:type #f (list) (list) (list))
(let* ([name (honu:type-iface-name type)]
[entry (get-tenv-entry name)])
(cond
[(not entry)
(raise-read-error-with-stx
(format "No type defined with name ~a" (printable-key name))
name)]
[(not (tenv:type? entry))
(raise-read-error-with-stx
(format "Definition of ~a is not a type" (printable-key name))
name)]
[else entry]))))
(define (get-class-entry name)
(let ([entry (get-tenv-entry name)])
(cond
[(not entry)
(raise-read-error-with-stx
(format "No class defined with name ~a" (printable-key name))
name)]
[(not (tenv:class? entry))
(raise-read-error-with-stx
(format "Definition of ~a is not a class" (printable-key name))
name)]
[else entry])))
(define (get-mixin-entry name)
(let ([entry (get-tenv-entry name)])
(cond
[(not entry)
(raise-read-error-with-stx
(format "No mixin defined with name ~a" (printable-key name))
name)]
[(not (tenv:mixin? entry))
(raise-read-error-with-stx
(format "Definition of ~a is not a mixin" (printable-key name))
name)]
[else entry])))
(define (get-member-type type name)
(let* ([entry (get-type-entry type)]
[mtype (find (lambda (m)
(tenv-key=? (tenv:member-name m) name))
(append (tenv:type-members entry)
(tenv:type-inherited entry)))])
(if mtype
(tenv:member-type mtype)
(raise-read-error-with-stx
(format "No member named ~a found for type ~a"
(printable-key name)
(if (honu:type-iface-top? type)
'Any
(printable-key (honu:type-iface-name type))))
name))))
(define (get-value-entry name)
(let ([entry (get-lenv-entry name)])
(cond
[(not entry)
(raise-read-error-with-stx
(format "No function or top-level binding defined with name ~a" (printable-key name))
name)]
[(not (tenv:value? entry))
(raise-read-error-with-stx
(format "Definition of ~a is not a function definition or value binding" (printable-key name))
name)]
[else entry])))
(provide wrap-lenv extend-fenv)
(define (wrap-lenv) (wrap-as-function (current-lexical-environment)))
(define (wrap-as-function tenv)
(lambda (name)
(let ([entry (bound-identifier-mapping-get tenv name (lambda () #f))])
(if entry (tenv:value-type entry) #f))))
(define (extend-fenv key value fenv)
(lambda (name)
(if (tenv-key=? key name)
value
(fenv name))))
)