Merge remote branch 'origin/master'

This commit is contained in:
Danny Yoo 2011-05-22 20:33:41 -04:00
commit 8a7971e19c
16 changed files with 264 additions and 74 deletions

View File

@ -4,11 +4,13 @@
"il-structs.rkt" "il-structs.rkt"
"compiler.rkt" "compiler.rkt"
"compiler-structs.rkt" "compiler-structs.rkt"
"typed-parse.rkt") "typed-parse.rkt"
"where-is-collects.rkt")
(require/typed "parameters.rkt" (require/typed "parameters.rkt"
(current-defined-name (Parameterof (U Symbol LamPositionalName)))) (current-defined-name (Parameterof (U Symbol LamPositionalName))))
(require/typed "parse-bytecode.rkt"
(parse-bytecode (Path -> Expression)))
@ -17,6 +19,17 @@
;; We'll hardcode the compilation of some Racket modules here.
(: hardcoded-modules-to-compile (Listof Path))
(define hardcoded-modules-to-compile
(list
(build-path collects-path "racket" "private" "modbeg.rkt")
))
;; The primitive code necessary to do call/cc ;; The primitive code necessary to do call/cc
(: call/cc-label Symbol) (: call/cc-label Symbol)
@ -85,7 +98,16 @@
(define (get-bootstrapping-code) (define (get-bootstrapping-code)
(append (append
;; module code
(apply append (map (lambda: ([p : Path])
(compile (parse-bytecode p)
'val
next-linkage/drop-multiple))
hardcoded-modules-to-compile))
;; Other primitives
(make-bootstrapped-primitive-code (make-bootstrapped-primitive-code
'map 'map
'(letrec ([map (lambda (f l) '(letrec ([map (lambda (f l)

View File

@ -382,7 +382,7 @@
(make-IsModuleInvoked a-module-name)) (make-IsModuleInvoked a-module-name))
already-loaded) already-loaded)
,(make-PushControlFrame/Call on-return) ,(make-PushControlFrame/Call on-return)
,(make-GotoStatement (make-ModuleEntry a-module-name)) ,(make-GotoStatement (ModuleEntry a-module-name))
,on-return-multiple ,on-return-multiple
,(make-PopEnvironment (make-SubtractArg (make-Reg 'argcount) ,(make-PopEnvironment (make-SubtractArg (make-Reg 'argcount)
(make-Const 1)) (make-Const 1))

View File

@ -204,7 +204,10 @@
(define-struct: GotoStatement ([target : OpArg]) (define-struct: GotoStatement ([target : (U Label
Reg
ModuleEntry
CompiledProcedureEntry)])
#:transparent) #:transparent)
(define-struct: PerformStatement ([op : PrimitiveCommand]) (define-struct: PerformStatement ([op : PrimitiveCommand])

View File

@ -59,6 +59,11 @@
'values 'values
'call-with-values 'call-with-values
'apply 'apply
'printf
'map
'for-each
'current-print
)) ))
(define-predicate KernelPrimitiveName? KernelPrimitiveName) (define-predicate KernelPrimitiveName? KernelPrimitiveName)

View File

@ -63,12 +63,13 @@
#%app #%app
#%top-interaction #%top-interaction
#%top #%top
define module
define
define-values define-values
let-values let-values
let*-values let*-values
define-struct define-struct
if if
cond cond
else else
case case

View File

@ -6,6 +6,7 @@
"language-namespace.rkt" "language-namespace.rkt"
"il-structs.rkt" "il-structs.rkt"
"bootstrapped-primitives.rkt" "bootstrapped-primitives.rkt"
"get-module-bytecode.rkt"
"get-dependencies.rkt" "get-dependencies.rkt"
"js-assembler/assemble.rkt" "js-assembler/assemble.rkt"
"js-assembler/get-runtime.rkt" "js-assembler/get-runtime.rkt"
@ -23,34 +24,21 @@
(define-runtime-path kernel-language-path (define-runtime-path kernel-language-path
"lang/kernel.rkt") "lang/kernel.rkt")
;; Use Racket's compiler, and then parse the resulting bytecode
;; to our own AST structures.
(define (parse stx)
(parameterize ([current-namespace (lookup-language-namespace
`(file ,(path->string kernel-language-path))
#;'racket/base)]
;; We want to disable some optimizations for the moment.
;; See: http://docs.racket-lang.org/drracket/module.html
[compile-context-preservation-enabled #t])
(let ([bc (racket:compile stx)]
[op (open-output-bytes)])
(write bc op)
(parse-bytecode
(open-input-bytes (get-output-bytes op))))))
;; package: s-expression output-port -> void ;; package: s-expression output-port -> void
(define (package source-code op) (define (package source-code op)
(fprintf op "var invoke = ") (let ([source-code-op (open-output-bytes)])
(assemble/write-invoke (append (get-bootstrapping-code) (write source-code source-code-op)
(compile (parse source-code) (let ([source-code-ip (open-input-bytes (get-output-bytes source-code-op))])
'val (fprintf op "var invoke = ")
next-linkage/drop-multiple)) (assemble/write-invoke (append (get-bootstrapping-code)
op) (compile (parse-bytecode
(fprintf op ";\n")) (open-input-bytes (get-module-bytecode source-code-ip)))
'val
next-linkage/drop-multiple))
op)
(fprintf op ";\n"))))
(define (package-anonymous source-code op) (define (package-anonymous source-code op)

View File

@ -30,9 +30,9 @@
(lambda (mpi relative-to) (lambda (mpi relative-to)
(cond (cond
[(eq? mpi #f) [(eq? mpi #f)
'self] (current-module-path)]
[(self-module-path-index? mpi) [(self-module-path-index? mpi)
'self] (current-module-path)]
[else [else
(resolve-module-path-index mpi relative-to)])))) (resolve-module-path-index mpi relative-to)]))))
@ -121,6 +121,11 @@
(parameterize ([seen-closures (make-hasheq)]) (parameterize ([seen-closures (make-hasheq)])
(let ([compilation-top (zo-parse in)]) (let ([compilation-top (zo-parse in)])
(parse-top compilation-top)))] (parse-top compilation-top)))]
[(compiled-expression? in)
(let ([op (open-output-bytes)])
(write in op)
(parse-bytecode (open-input-bytes (get-output-bytes op))))]
[(path? in) [(path? in)
(let*-values ([(normal-path) (normalize-path in)] (let*-values ([(normal-path) (normalize-path in)]
@ -144,8 +149,32 @@
(define (parse-top a-top) (define (parse-top a-top)
(match a-top (match a-top
[(struct compilation-top (max-let-depth prefix code)) [(struct compilation-top (max-let-depth prefix code))
(make-Top (parse-prefix prefix) (maybe-fix-module-name
(parse-top-code code))])) (make-Top (parse-prefix prefix)
(parse-top-code code)))]))
;; maybe-fix-module-name: expression -> expression
;; When we're compiling a module directly from memory, it doesn't have a file path.
;; We rewrite the ModuleName to its given name.
(define (maybe-fix-module-name exp)
(match exp
[(struct Top (top-prefix
(struct Module ((and name (? symbol?))
(struct ModuleName ('self 'self))
module-prefix
module-requires
module-code))))
(make-Top top-prefix
(make-Module name
(make-ModuleName name name) (current-module-path)
module-prefix
module-requires
module-code))]
[else
exp]))
(define (parse-prefix a-prefix) (define (parse-prefix a-prefix)
@ -197,7 +226,8 @@
(make-ModuleName (rewrite-path resolved-path-name) (make-ModuleName (rewrite-path resolved-path-name)
(normalize-path resolved-path-name))] (normalize-path resolved-path-name))]
[else [else
(error 'wrap-module-name "Unable to resolve module path ~s" resolved-path-name)]))])) (error 'wrap-module-name "Unable to resolve module path ~s."
resolved-path-name)]))]))

View File

@ -1,11 +1,32 @@
#lang racket/base #lang racket/base
(require "version-case/version-case.rkt" (require "version-case/version-case.rkt"
racket/file
(prefix-in whalesong: "version.rkt")
(for-syntax racket/base)) (for-syntax racket/base))
(version-case (version-case
[(version>= (version) "5.1.1") [(version>= (version) "5.1.1")
(begin (begin
(require "parse-bytecode-5.1.1.rkt") (require "parse-bytecode-5.1.1.rkt")
(provide (all-from-out "parse-bytecode-5.1.1.rkt")))] (provide (except-out (all-from-out "parse-bytecode-5.1.1.rkt")
parse-bytecode)))]
[else [else
(error 'parse-bytecode "Whalesong doesn't have a compatible parser for Racket ~a" (version))]) (error 'parse-bytecode "Whalesong doesn't have a compatible parser for Racket ~a" (version))])
(provide (rename-out [my-parse-bytecode parse-bytecode]))
(define (my-parse-bytecode x)
(cond
[(path? x)
(parse-bytecode x)]
[else
(parse-bytecode x)]))
(define cache-dir (build-path (find-system-path 'pref-dir)
"whalesong"
whalesong:version))
(unless (directory-exists? cache-dir)
(make-directory* cache-dir))

View File

@ -1,6 +1,7 @@
#lang racket/base #lang racket/base
(require "parameters.rkt" (require "parameters.rkt"
"where-is-collects.rkt"
racket/path racket/path
racket/contract racket/contract
racket/list racket/list
@ -34,7 +35,7 @@
(string->symbol (string->symbol
(string-append "collects/" (string-append "collects/"
(path->string (path->string
(find-relative-path collects a-path))))] (find-relative-path collects-path a-path))))]
[(within-this-project-path? a-path) [(within-this-project-path? a-path)
(string->symbol (string->symbol
(string-append "whalesong/" (string-append "whalesong/"
@ -49,24 +50,14 @@
#f]))) #f])))
(define collects
(normalize-path
(let ([p (find-system-path 'collects-dir)])
(cond
[(relative-path? p)
(find-executable-path (find-system-path 'exec-file)
(find-system-path 'collects-dir))]
[else
p]))))
(define (within-root? a-path) (define (within-root? a-path)
(within? (current-root-path) a-path)) (within? (current-root-path) a-path))
(define (within-collects? a-path) (define (within-collects? a-path)
(within? collects a-path)) (within? collects-path a-path))
(define (within-this-project-path? a-path) (define (within-this-project-path? a-path)

View File

@ -1,6 +1,7 @@
#lang racket/base #lang racket/base
(require "simulator-structs.rkt" (require "simulator-structs.rkt"
"../il-structs.rkt" "../il-structs.rkt"
"simulator-helpers.rkt"
racket/math racket/math
racket/list racket/list
(for-syntax racket/base)) (for-syntax racket/base))
@ -170,6 +171,11 @@
(error 'member "not a list: ~s" l)])))) (error 'member "not a list: ~s" l)]))))
(define my-printf (lambda (fmt args)
(apply printf fmt (map (lambda (x)
(PrimitiveValue->racket x))
args))))
(define current-continuation-marks (define current-continuation-marks
@ -258,11 +264,11 @@
equal? equal?
symbol?
(my-printf printf)
)
symbol?)
#:constants (null pi e #:constants (null pi e
current-continuation-marks current-continuation-marks
continuation-mark-set->list))) continuation-mark-set->list)))

View File

@ -7,6 +7,14 @@
"../lexical-structs.rkt") "../lexical-structs.rkt")
;; A special "label" in the system that causes evaluation to stop.
(define-struct: halt ())
(define HALT (make-halt))
(define-type PrimitiveValue (Rec PrimitiveValue (U String Number Symbol Boolean (define-type PrimitiveValue (Rec PrimitiveValue (U String Number Symbol Boolean
Null VoidValue Null VoidValue
undefined undefined
@ -79,7 +87,7 @@
#:transparent) #:transparent)
(define-struct: CallFrame ([return : LinkedLabel] (define-struct: CallFrame ([return : (U LinkedLabel halt)]
;; The procedure being called. Used to optimize self-application ;; The procedure being called. Used to optimize self-application
[proc : (U closure #f)] [proc : (U closure #f)]
;; TODO: add continuation marks ;; TODO: add continuation marks
@ -89,7 +97,7 @@
#:mutable) ;; mutable because we want to allow mutation of proc. #:mutable) ;; mutable because we want to allow mutation of proc.
(define-struct: PromptFrame ([tag : ContinuationPromptTagValue] (define-struct: PromptFrame ([tag : ContinuationPromptTagValue]
[return : LinkedLabel] [return : (U LinkedLabel halt)]
[env-depth : Natural] [env-depth : Natural]
[temps : (HashTable Symbol PrimitiveValue)] [temps : (HashTable Symbol PrimitiveValue)]
[marks : (HashTable PrimitiveValue PrimitiveValue)]) [marks : (HashTable PrimitiveValue PrimitiveValue)])

View File

@ -27,14 +27,22 @@
[racket->PrimitiveValue (Any -> PrimitiveValue)]) [racket->PrimitiveValue (Any -> PrimitiveValue)])
(provide new-machine can-step? step! current-instruction (provide new-machine
can-step?
step!
current-instruction
current-simulated-output-port current-simulated-output-port
machine-control-size) machine-control-size
invoke-module-as-main)
(define current-simulated-output-port (make-parameter (current-output-port))) (define current-simulated-output-port (make-parameter (current-output-port)))
(define end-of-program-text 'end-of-program-text)
(: new-machine (case-lambda [(Listof Statement) -> machine] (: new-machine (case-lambda [(Listof Statement) -> machine]
[(Listof Statement) Boolean -> machine])) [(Listof Statement) Boolean -> machine]))
(define new-machine (define new-machine
@ -45,11 +53,12 @@
[with-bootstrapping-code? : Boolean]) [with-bootstrapping-code? : Boolean])
(let*: ([after-bootstrapping : Symbol (make-label 'afterBootstrapping)] (let*: ([after-bootstrapping : Symbol (make-label 'afterBootstrapping)]
[program-text : (Listof Statement) [program-text : (Listof Statement)
(cond [with-bootstrapping-code? (append (cond [with-bootstrapping-code?
(append (get-bootstrapping-code) (append (get-bootstrapping-code)
program-text)] program-text)]
[else [else
program-text])]) program-text])
(list end-of-program-text))])
(let: ([m : machine (make-machine (make-undefined) (let: ([m : machine (make-machine (make-undefined)
(make-undefined) (make-undefined)
(make-undefined) (make-undefined)
@ -79,6 +88,25 @@
(: invoke-module-as-main (machine Symbol -> 'ok))
;; Assuming the module has been loaded in, sets the machine
;; up to invoke its body.
(define (invoke-module-as-main m module-name)
(let ([frame (make-PromptFrame
default-continuation-prompt-tag-value
HALT
(length (machine-env m))
(make-hasheq)
(make-hasheq))]
[module-record (hash-ref (machine-modules m) module-name)])
(control-push! m frame)
(jump! m (module-record-label module-record))))
(: can-step? (machine -> Boolean)) (: can-step? (machine -> Boolean))
;; Produces true if we can make a further step in the simulation. ;; Produces true if we can make a further step in the simulation.
(define (can-step? m) (define (can-step? m)
@ -425,6 +453,9 @@
[(InstallModuleEntry!? op) [(InstallModuleEntry!? op)
(printf "installing module ~s\n"
(ModuleName-name
(InstallModuleEntry!-path op)))
(hash-set! (machine-modules m) (hash-set! (machine-modules m)
(ModuleName-name (InstallModuleEntry!-path op)) (ModuleName-name (InstallModuleEntry!-path op))
(make-module-record (InstallModuleEntry!-name op) (make-module-record (InstallModuleEntry!-name op)
@ -771,10 +802,17 @@
(error 'GetControlStackLabel)] (error 'GetControlStackLabel)]
[(PromptFrame? frame) [(PromptFrame? frame)
(let ([label (PromptFrame-return frame)]) (let ([label (PromptFrame-return frame)])
(LinkedLabel-label label))] (cond [(halt? label)
end-of-program-text]
[else
(LinkedLabel-label label)]))]
[(CallFrame? frame) [(CallFrame? frame)
(let ([label (CallFrame-return frame)]) (let ([label (CallFrame-return frame)])
(LinkedLabel-label label))]))] (cond
[(halt? label)
end-of-program-text]
[else
(LinkedLabel-label label)]))]))]
[(ControlStackLabel/MultipleValueReturn? an-oparg) [(ControlStackLabel/MultipleValueReturn? an-oparg)
(let ([frame (ensure-frame (first (machine-control m)))]) (let ([frame (ensure-frame (first (machine-control m)))])
@ -783,11 +821,19 @@
(error 'GetControlStackLabel/MultipleValueReturn)] (error 'GetControlStackLabel/MultipleValueReturn)]
[(PromptFrame? frame) [(PromptFrame? frame)
(let ([label (PromptFrame-return frame)]) (let ([label (PromptFrame-return frame)])
(LinkedLabel-linked-to label))] (cond
[(halt? label)
end-of-program-text]
[else
(LinkedLabel-linked-to label)]))]
[(CallFrame? frame) [(CallFrame? frame)
(let ([label (CallFrame-return frame)]) (let ([label (CallFrame-return frame)])
(LinkedLabel-linked-to label))]))] (cond
[(halt? label)
end-of-program-text]
[else
(LinkedLabel-linked-to label)]))]))]
[(ControlFrameTemporary? an-oparg) [(ControlFrameTemporary? an-oparg)
(let ([ht (frame-temps (control-top m))]) (let ([ht (frame-temps (control-top m))])
(hash-ref ht (hash-ref ht

View File

@ -3,7 +3,11 @@
(require "../simulator/simulator.rkt" (require "../simulator/simulator.rkt"
"../simulator/simulator-structs.rkt" "../simulator/simulator-structs.rkt"
"../simulator/simulator-helpers.rkt" "../simulator/simulator-helpers.rkt"
"test-helpers.rkt") "../parameters.rkt"
"test-helpers.rkt"
racket/runtime-path)
(define-runtime-path this-test-path ".")
@ -54,7 +58,8 @@
#:debug? (debug? false) #:debug? (debug? false)
#:stack-limit (stack-limit false) #:stack-limit (stack-limit false)
#:control-limit (control-limit false) #:control-limit (control-limit false)
#:with-bootstrapping? (with-bootstrapping? false)) #:with-bootstrapping? (with-bootstrapping? false)
#:as-main-module (as-main-module #f))
(let ([m (new-machine (run-compiler code) with-bootstrapping?)]) (let ([m (new-machine (run-compiler code) with-bootstrapping?)])
(let loop ([steps 0]) (let loop ([steps 0])
(when debug? (when debug?
@ -76,7 +81,15 @@
(step! m) (step! m)
(loop (add1 steps))] (loop (add1 steps))]
[else [else
(values m steps)])))) (cond
[as-main-module
;; Set the pc to the module's entry point
;; Set the return point to halt on exit.
(invoke-module-as-main m as-main-module)
(set! as-main-module #f)
(loop (add1 steps))]
[else
(values m steps)])]))))
;; Atomic expressions ;; Atomic expressions
@ -1326,12 +1339,20 @@
#:with-bootstrapping? #t) #:with-bootstrapping? #t)
(parameterize ([current-module-path (build-path this-test-path "foo.rkt")])
(test '(module foo racket/base
(printf "hello world"))
(make-undefined)
#:as-main-module 'whalesong/tests/foo.rkt
#:with-bootstrapping? #t))
;; begin0 is still broken. ;; begin0 is still broken.
#;(test '(letrec ([f (lambda (x) (test '(letrec ([f (lambda (x)
(if (= x 0) (if (= x 0)
0 0
(+ x (f (sub1 x)))))]) (+ x (f (sub1 x)))))])
@ -1341,14 +1362,14 @@
#;(test '(let () (define (f x y z) (test '(let () (define (f x y z)
(values y x z)) (values y x z))
(call-with-values (lambda () (f 3 1 4)) (call-with-values (lambda () (f 3 1 4))
(lambda args (list args)))) (lambda args (list args))))
'((1 3 4)) '((1 3 4))
#:with-bootstrapping? #t) #:with-bootstrapping? #t)
#;(test '(let () (define (f x y z) (test '(let () (define (f x y z)
(begin0 (values y x z) (begin0 (values y x z)
(display ""))) (display "")))
(call-with-values (lambda () (f 3 1 4)) (call-with-values (lambda () (f 3 1 4))

View File

@ -3,12 +3,15 @@
(require compiler/zo-parse (require compiler/zo-parse
rackunit rackunit
racket/match racket/match
racket/path
"../parameters.rkt" "../parameters.rkt"
"../parse-bytecode.rkt" "../parse-bytecode.rkt"
"../lexical-structs.rkt" "../lexical-structs.rkt"
"../expression-structs.rkt" "../expression-structs.rkt"
racket/runtime-path
(for-syntax racket/base)) (for-syntax racket/base))
(define-runtime-path this-test-path ".")
(define (run-zo-parse stx) (define (run-zo-parse stx)
(parameterize ([current-namespace (make-base-namespace)] (parameterize ([current-namespace (make-base-namespace)]
@ -398,7 +401,30 @@
(#%provide f)))) (#%provide f))))
(check-true (parameterize ([current-root-path this-test-path]
[current-module-path (build-path this-test-path "foo.rkt")])
(check-true
(match (run-my-parse #'(module foo racket/base))
[(struct Top ((? Prefix?)
(struct Module ('foo
(struct ModuleName
('whalesong/tests/foo.rkt
(? (lambda (p)
(and (path? p)
(equal? (normalize-path p)
(normalize-path
(build-path this-test-path "foo.rkt"))))))))
(struct Prefix (list))
(list (struct ModuleName ('collects/racket/base.rkt
_)))
(struct Splice ('()))))))
#t]
[else
#f])))
#;(check-true
(match (parameterize ([current-root-path (build-path "/blah")] (match (parameterize ([current-root-path (build-path "/blah")]
[current-module-path (build-path "/blah" "foo" "bar.rkt")]) [current-module-path (build-path "/blah" "foo" "bar.rkt")])
(run-my-parse '(module foo '#%kernel (run-my-parse '(module foo '#%kernel

4
version.rkt Normal file
View File

@ -0,0 +1,4 @@
#lang typed/racket/base
(provide version)
(: version String)
(define version "1.0")

18
where-is-collects.rkt Normal file
View File

@ -0,0 +1,18 @@
#lang typed/racket/base
(require/typed racket/path
(normalize-path (Path -> Path)))
(require/typed typed/racket/base
(relative-path? (Any -> Boolean))
(find-executable-path (Path Path -> Path)))
(provide collects-path)
(define collects-path
(normalize-path
(let ([p (find-system-path 'collects-dir)])
(cond
[(relative-path? p)
(find-executable-path (find-system-path 'exec-file)
(find-system-path 'collects-dir))]
[else
p]))))