(module resolve-source mzscheme
(require (lib "etc.ss")
(lib "class.ss"))
(require (prefix ast: "../syntax/ast.ss"))
(require "../syntax/parser.ss")
(require "semantic-object.ss")
(define resolve-source
(lambda (type-name path)
(find-type type-name (parse-file path))))
(define find-type
(lambda (type-name compilation-unit)
(recur loop ([types (ast:compilation-unit-classes compilation-unit)])
(cond
[(null? types) #f]
[(not (car types)) (loop (cdr types))]
[(eq? (type-name-type type-name)
(ast:id-name (ast:decl-name (car types))))
(build-type type-name (car types))]
[else (loop (cdr types))]))))
(define build-type
(lambda (name decl)
(cond
[(ast:class-decl? decl) (build-class name decl)]
[(ast:interface-decl? decl) (build-interface name decl)]
[else (error 'build-type "unsupported declaration: ~v" decl)])))
(define build-class
(lambda (class-name class-decl)
(new class%
[package null] [name class-name]
[modifiers (extract-modifiers class-decl)]
[interfaces (extract-interfaces class-decl)]
[elements (extract-elements class-decl)]
[superclass
(let ([super-name (ast:class-decl-super class-decl)])
(if super-name
(ast-name->type-name super-name)
#f))])))
(define build-interface
(lambda (ifc-name ifc-decl)
(new interface%
[package null] [name ifc-name]
[modifiers (extract-modifiers ifc-decl)]
[interfaces (extract-interfaces ifc-decl)]
[elements (extract-elements ifc-decl)])))
(define extract-modifiers
(lambda (type-decl)
(map ast:modifier-modifier (ast:decl-modifiers type-decl))))
(define extract-interfaces
(lambda (type-decl)
(map ast-name->type-name (ast:type-decl-interfaces type-decl))))
(define extract-elements
(lambda (type-decl)
(map class-element->type-element
(flatten-elements (ast:type-decl-body type-decl)))))
(define flatten-elements
(lambda (elts)
(cond
[(null? elts) null]
[(not (car elts)) (flatten-elements (cdr elts))]
[(pair? (car elts)) (append (car elts) (flatten-elements (cdr elts)))]
[else (cons (car elts) (flatten-elements (cdr elts)))])))
(define class-element->type-element
(lambda (elt)
(cond
[(ast:initializer? elt) (new initializer%)]
[(ast:type-decl? elt)
(error 'class-element->type-element
"inner classes and interfaces not supported")]
[(ast:variable-decl? elt)
(new field%
[name (ast:id->string (ast:decl-name elt))]
[modifiers (map ast:modifier-modifier (ast:decl-modifiers elt))]
[type (ast:type-spec->type-name (ast:variable-decl-type elt))])]
[(ast:constructor-decl? elt)
(new constructor%
[name (ast:id->string (ast:decl-name elt))]
[formals (map ast:variable-decl->type-name
(ast:behavior-decl-formals elt))]
[exceptions (map ast-name->type-name
(ast:behavior-decl-throws elt))]
[modifiers (map ast:modifier-modifier (ast:decl-modifiers elt))])]
[(ast:method-decl? elt)
(new method%
[name (ast:id->string (ast:decl-name elt))]
[formals (map ast:variable-decl->type-name
(ast:behavior-decl-formals elt))]
[exceptions (map ast-name->type-name
(ast:behavior-decl-throws elt))]
[modifiers (map ast:modifier-modifier (ast:decl-modifiers elt))]
[return-type (ast:type-spec->type-name
(ast:method-decl-return-type elt))])])))
(define ast-name->type-name
(lambda (ast-name)
(make-type-name (ast:name-path ast-name)
(ast:name-id ast-name))))
(define ast:id->string
(lambda (id)
(symbol->string (ast:id-name id))))
(define ast:type-spec->type-name
(lambda (type-spec)
(let ([type-name (ast:type-spec-base-type type-spec)] [dimension (ast:type-spec-dimension type-spec)]) (cond
[(ast:primitive-type? type-name)
(if (eq? type-name 'void)
#f
(make-type-name null type-name dimension))]
[else
(make-type-name (map ast:id-name (ast:name-path type-name))
(ast:id-name (ast:name-id type-name))
dimension)]))))
(define ast:variable-decl->type-name
(lambda (decl)
(ast:type-spec->type-name (ast:variable-decl-type decl)))))