#lang typed/racket/base
(require "expression-structs.rkt"
"lexical-structs.rkt"
"il-structs.rkt"
"compiler.rkt"
"compiler-structs.rkt")
(require/typed "../parameters.rkt"
(current-defined-name (Parameterof (U Symbol LamPositionalName))))
(require/typed "../parser/parse-bytecode.rkt"
(parse-bytecode (Path -> Expression)))
(require/typed "../parser/baby-parser.rkt"
[parse (Any -> Expression)])
(provide get-bootstrapping-code)
(: call/cc-label Symbol)
(define call/cc-label 'callCCEntry)
(define call/cc-closure-entry 'callCCClosureEntry)
(define (make-call/cc-code)
(statements
(append-instruction-sequences
(make-instruction-sequence
`(,call/cc-label
,(make-AssignImmediateStatement 'proc (make-EnvLexicalReference 0 #f))
,(make-PushEnvironment 2 #f)
,(make-AssignPrimOpStatement (make-EnvLexicalReference 0 #f)
(make-CaptureControl 0 default-continuation-prompt-tag))
,(make-AssignPrimOpStatement (make-EnvLexicalReference 1 #f)
(make-CaptureEnvironment 3 default-continuation-prompt-tag))
,(make-AssignPrimOpStatement (make-EnvLexicalReference 2 #f)
(make-MakeCompiledProcedure call/cc-closure-entry
1 (list 0 1)
'call/cc))
,(make-PopEnvironment (make-Const 2)
(make-Const 0))))
(make-instruction-sequence `(,(make-AssignImmediateStatement 'argcount (make-Const 1))))
(compile-general-procedure-call '()
(make-Const 1) 'val
return-linkage)
(make-instruction-sequence `(,call/cc-closure-entry
,(make-AssignImmediateStatement 'val (make-EnvLexicalReference 0 #f))
,(make-PerformStatement (make-InstallClosureValues!))
,(make-PerformStatement
(make-RestoreControl! default-continuation-prompt-tag))
,(make-PerformStatement (make-RestoreEnvironment!))
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel))
,(make-PopControlFrame)
,(make-GotoStatement (make-Reg 'proc)))))))
(: make-bootstrapped-primitive-code (Symbol Any -> (Listof Statement)))
(define (make-bootstrapped-primitive-code name src)
(parameterize ([current-defined-name name])
(append
(compile (parse src) (make-PrimitivesReference name) next-linkage/drop-multiple))))
(: get-bootstrapping-code (-> (Listof Statement)))
(define (get-bootstrapping-code)
(append
(make-bootstrapped-primitive-code
'map
'(letrec ([map (lambda (f l)
(if (null? l)
null
(cons (f (car l))
(map f (cdr l)))))])
map))
(make-bootstrapped-primitive-code
'for-each
'(letrec ([for-each (lambda (f l)
(if (null? l)
null
(begin (f (car l))
(for-each f (cdr l)))))])
for-each))
(make-bootstrapped-primitive-code
'caar
'(lambda (x)
(car (car x))))
(make-bootstrapped-primitive-code
'memq
'(letrec ([memq (lambda (x l)
(if (null? l)
#f
(if (eq? x (car l))
l
(memq x (cdr l)))))])
memq))
(make-bootstrapped-primitive-code
'assq
'(letrec ([assq (lambda (x l)
(if (null? l)
#f
(if (eq? x (caar l))
(car l)
(assq x (cdr l)))))])
assq))
(make-bootstrapped-primitive-code
'length
'(letrec ([length-iter (lambda (l i)
(if (null? l)
i
(length-iter (cdr l) (add1 i))))])
(lambda (l) (length-iter l 0))))
(make-bootstrapped-primitive-code
'append
'(letrec ([append-many (lambda (lsts)
(if (null? lsts)
null
(if (null? (cdr lsts))
(car lsts)
(append-2 (car lsts)
(append-many (cdr lsts))))))]
[append-2 (lambda (l1 l2)
(if (null? l1)
l2
(cons (car l1) (append-2 (cdr l1) l2))))])
(lambda args (append-many args))))
(make-bootstrapped-primitive-code
'call-with-values
'(lambda (producer consumer)
(call-with-values (lambda () (producer)) consumer)))
(let ([after-call/cc-code (make-label 'afterCallCCImplementation)])
(append
`(,(make-AssignPrimOpStatement (make-PrimitivesReference 'call/cc)
(make-MakeCompiledProcedure call/cc-label 1 '() 'call/cc))
,(make-AssignPrimOpStatement (make-PrimitivesReference 'call-with-current-continuation)
(make-MakeCompiledProcedure call/cc-label 1 '() 'call/cc))
,(make-GotoStatement (make-Label after-call/cc-code)))
(make-call/cc-code)
`(,after-call/cc-code)))
(let ([after-values-body-defn (make-label 'afterValues)]
[values-entry (make-label 'valuesEntry)]
[on-zero-values (make-label 'onZeroValues)]
[on-single-value (make-label 'onSingleValue)])
`(,(make-GotoStatement (make-Label after-values-body-defn))
,values-entry
,(make-TestAndJumpStatement (make-TestOne (make-Reg 'argcount)) on-single-value)
,(make-TestAndJumpStatement (make-TestZero (make-Reg 'argcount)) on-zero-values)
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel/MultipleValueReturn))
,(make-AssignImmediateStatement 'val (make-EnvLexicalReference 0 #f))
,(make-PopEnvironment (make-Const 1) (make-Const 0))
,(make-PopControlFrame)
,(make-GotoStatement (make-Reg 'proc))
,on-single-value
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel))
,(make-AssignImmediateStatement 'val (make-EnvLexicalReference 0 #f))
,(make-PopEnvironment (make-Const 1) (make-Const 0))
,(make-PopControlFrame)
,(make-GotoStatement (make-Reg 'proc))
,on-zero-values
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel/MultipleValueReturn))
,(make-PopControlFrame)
,(make-GotoStatement (make-Reg 'proc))
,after-values-body-defn
,(make-AssignPrimOpStatement (make-PrimitivesReference 'values)
(make-MakeCompiledProcedure values-entry
(make-ArityAtLeast 0)
'()
'values))))
(let ([after-apply-code (make-label 'afterApplyCode)]
[apply-entry (make-label 'applyEntry)])
`(,(make-GotoStatement (make-Label after-apply-code))
,apply-entry
,(make-AssignImmediateStatement 'proc (make-EnvLexicalReference 0 #f))
,(make-PopEnvironment (make-Const 1) (make-Const 0))
,(make-AssignImmediateStatement 'argcount (make-SubtractArg (make-Reg 'argcount)
(make-Const 1)))
,(make-PerformStatement (make-SpliceListIntoStack! (make-SubtractArg (make-Reg 'argcount)
(make-Const 1))))
,@(statements (compile-general-procedure-call '()
(make-Reg 'argcount) 'val
return-linkage))
,after-apply-code
,(make-AssignPrimOpStatement (make-PrimitivesReference 'apply)
(make-MakeCompiledProcedure apply-entry (make-ArityAtLeast 2) '() 'apply))))))