massaging the code so general apply should work
This commit is contained in:
parent
0e604a44ae
commit
a49269e2db
|
@ -47,8 +47,8 @@
|
||||||
|
|
||||||
;; Finally, do a tail call into f.
|
;; Finally, do a tail call into f.
|
||||||
(compile-general-procedure-call '()
|
(compile-general-procedure-call '()
|
||||||
'(?)
|
1 ;; the stack at this point holds a single argument
|
||||||
1
|
1 ;; and f needs to consume that single argument.
|
||||||
'val
|
'val
|
||||||
return-linkage)
|
return-linkage)
|
||||||
|
|
||||||
|
@ -152,4 +152,27 @@
|
||||||
(make-MakeCompiledProcedure call/cc-label 1 '() 'call/cc))
|
(make-MakeCompiledProcedure call/cc-label 1 '() 'call/cc))
|
||||||
,(make-GotoStatement (make-Label after-call/cc-code)))
|
,(make-GotoStatement (make-Label after-call/cc-code)))
|
||||||
(make-call/cc-code)
|
(make-call/cc-code)
|
||||||
`(,after-call/cc-code)))))
|
`(,after-call/cc-code)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;; As is apply:
|
||||||
|
(let ([after-apply-code (make-label 'afterApplyCode)]
|
||||||
|
[apply-entry (make-label 'applyEntry)])
|
||||||
|
(list
|
||||||
|
(make-GotoStatement (make-Label after-apply-code))
|
||||||
|
apply-entry
|
||||||
|
|
||||||
|
;; Push the procedure into proc.
|
||||||
|
(make-AssignImmediateStatement 'proc (make-EnvLexicalReference 0 #f))
|
||||||
|
(make-PopEnvironment 1 0)
|
||||||
|
;; Correct the number of arguments to be passed.
|
||||||
|
(make-AssignPrimOpStatement 'val
|
||||||
|
(make-CallKernelPrimitiveProcedure 'sub1
|
||||||
|
(list (make-Reg 'val))
|
||||||
|
(list 'number)
|
||||||
|
(list #f)))
|
||||||
|
|
||||||
|
after-apply-code
|
||||||
|
(make-AssignPrimOpStatement (make-PrimitivesReference 'apply)
|
||||||
|
(make-MakeCompiledProcedure apply-entry 1 '() 'apply))))))
|
40
compile.rkt
40
compile.rkt
|
@ -469,7 +469,7 @@
|
||||||
proc-code
|
proc-code
|
||||||
(juggle-operands operand-codes)
|
(juggle-operands operand-codes)
|
||||||
(compile-general-procedure-call cenv
|
(compile-general-procedure-call cenv
|
||||||
extended-cenv
|
(length extended-cenv)
|
||||||
(length (App-operands exp))
|
(length (App-operands exp))
|
||||||
target
|
target
|
||||||
linkage))))
|
linkage))))
|
||||||
|
@ -779,7 +779,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(: compile-general-procedure-call (CompileTimeEnvironment CompileTimeEnvironment
|
(: compile-general-procedure-call (CompileTimeEnvironment Natural
|
||||||
Natural Target Linkage
|
Natural Target Linkage
|
||||||
->
|
->
|
||||||
InstructionSequence))
|
InstructionSequence))
|
||||||
|
@ -787,7 +787,7 @@
|
||||||
;; n is the number of arguments passed in.
|
;; n is the number of arguments passed in.
|
||||||
;; cenv is the compile-time enviroment before arguments have been shifted in.
|
;; cenv is the compile-time enviroment before arguments have been shifted in.
|
||||||
;; extended-cenv is the compile-time environment after arguments have been shifted in.
|
;; extended-cenv is the compile-time environment after arguments have been shifted in.
|
||||||
(define (compile-general-procedure-call cenv extended-cenv n target linkage)
|
(define (compile-general-procedure-call cenv extended-cenv-length number-of-arguments target linkage)
|
||||||
(let: ([primitive-branch : LabelLinkage (make-LabelLinkage (make-label 'primitiveBranch))]
|
(let: ([primitive-branch : LabelLinkage (make-LabelLinkage (make-label 'primitiveBranch))]
|
||||||
[compiled-branch : LabelLinkage (make-LabelLinkage (make-label 'compiledBranch))]
|
[compiled-branch : LabelLinkage (make-LabelLinkage (make-label 'compiledBranch))]
|
||||||
[after-call : LabelLinkage (make-LabelLinkage (make-label 'afterCall))])
|
[after-call : LabelLinkage (make-LabelLinkage (make-label 'afterCall))])
|
||||||
|
@ -804,28 +804,34 @@
|
||||||
;; Compiled branch
|
;; Compiled branch
|
||||||
(LabelLinkage-label compiled-branch)
|
(LabelLinkage-label compiled-branch)
|
||||||
(make-instruction-sequence
|
(make-instruction-sequence
|
||||||
`(,(make-AssignImmediateStatement 'val (make-Const n))
|
`(,(make-AssignImmediateStatement 'val (make-Const number-of-arguments))
|
||||||
,(make-PerformStatement (make-CheckClosureArity!))))
|
,(make-PerformStatement (make-CheckClosureArity! (make-Reg 'val)))))
|
||||||
(compile-procedure-application extended-cenv (make-Reg 'val) n target compiled-linkage)
|
(compile-procedure-application extended-cenv-length
|
||||||
|
(make-Reg 'val)
|
||||||
|
number-of-arguments
|
||||||
|
target
|
||||||
|
compiled-linkage)
|
||||||
|
|
||||||
|
|
||||||
|
;; Primitive branch
|
||||||
(LabelLinkage-label primitive-branch)
|
(LabelLinkage-label primitive-branch)
|
||||||
(end-with-linkage
|
(end-with-linkage
|
||||||
linkage
|
linkage
|
||||||
cenv
|
cenv
|
||||||
(append-instruction-sequences
|
(append-instruction-sequences
|
||||||
(make-instruction-sequence
|
(make-instruction-sequence
|
||||||
`(,(make-AssignPrimOpStatement
|
`(,(make-PerformStatement (make-CheckPrimitiveArity! (make-Const number-of-arguments)))
|
||||||
|
,(make-AssignPrimOpStatement
|
||||||
;; Optimization: we put the result directly in the registers, or in
|
;; Optimization: we put the result directly in the registers, or in
|
||||||
;; the appropriate spot on the stack. This takes into account the popenviroment
|
;; the appropriate spot on the stack. This takes into account the popenviroment
|
||||||
;; that happens right afterwards.
|
;; that happens right afterwards.
|
||||||
(adjust-target-depth target n)
|
(adjust-target-depth target number-of-arguments)
|
||||||
(make-ApplyPrimitiveProcedure n))))
|
(make-ApplyPrimitiveProcedure number-of-arguments))))
|
||||||
(if (not (= n 0))
|
|
||||||
(make-instruction-sequence
|
(make-instruction-sequence
|
||||||
`(,(make-PopEnvironment n 0)))
|
`(,(make-PopEnvironment number-of-arguments 0)))
|
||||||
empty-instruction-sequence)
|
|
||||||
|
|
||||||
|
|
||||||
(LabelLinkage-label after-call)))))))
|
(LabelLinkage-label after-call)))))))
|
||||||
|
|
||||||
|
|
||||||
|
@ -837,7 +843,7 @@
|
||||||
linkage
|
linkage
|
||||||
after-call)])
|
after-call)])
|
||||||
(append-instruction-sequences
|
(append-instruction-sequences
|
||||||
(compile-procedure-application extended-cenv
|
(compile-procedure-application (length extended-cenv)
|
||||||
(make-Label (StaticallyKnownLam-entry-point static-knowledge))
|
(make-Label (StaticallyKnownLam-entry-point static-knowledge))
|
||||||
n
|
n
|
||||||
target
|
target
|
||||||
|
@ -849,19 +855,19 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(: compile-procedure-application (CompileTimeEnvironment (U Label Reg) Natural Target Linkage -> InstructionSequence))
|
(: compile-procedure-application (Natural (U Label Reg) Natural Target Linkage -> InstructionSequence))
|
||||||
;; Three fundamental cases for general compiled-procedure application.
|
;; Three fundamental cases for general compiled-procedure application.
|
||||||
;; 1. Tail calls.
|
;; 1. Tail calls.
|
||||||
;; 2. Non-tail calls (next/label linkage) that write to val
|
;; 2. Non-tail calls (next/label linkage) that write to val
|
||||||
;; 3. Calls in argument position (next/label linkage) that write to the stack.
|
;; 3. Calls in argument position (next/label linkage) that write to the stack.
|
||||||
(define (compile-procedure-application cenv-with-args entry-point n target linkage)
|
(define (compile-procedure-application cenv-length-with-args entry-point n target linkage)
|
||||||
(cond [(ReturnLinkage? linkage)
|
(cond [(ReturnLinkage? linkage)
|
||||||
(cond
|
(cond
|
||||||
[(eq? target 'val)
|
[(eq? target 'val)
|
||||||
;; This case happens when we're in tail position.
|
;; This case happens when we're in tail position.
|
||||||
;; We clean up the stack right before the jump, and do not add
|
;; We clean up the stack right before the jump, and do not add
|
||||||
;; to the control stack.
|
;; to the control stack.
|
||||||
(let: ([num-slots-to-delete : Natural (ensure-natural (- (length cenv-with-args) n))])
|
(let: ([num-slots-to-delete : Natural (ensure-natural (- cenv-length-with-args n))])
|
||||||
(append-instruction-sequences
|
(append-instruction-sequences
|
||||||
(make-instruction-sequence
|
(make-instruction-sequence
|
||||||
`(,(make-AssignPrimOpStatement 'val
|
`(,(make-AssignPrimOpStatement 'val
|
||||||
|
|
|
@ -233,8 +233,11 @@
|
||||||
|
|
||||||
;; Check the closure procedure value in 'proc and make sure it can accept the
|
;; Check the closure procedure value in 'proc and make sure it can accept the
|
||||||
;; # of arguments (stored as a number in the val register.).
|
;; # of arguments (stored as a number in the val register.).
|
||||||
(define-struct: CheckClosureArity! ()
|
(define-struct: CheckClosureArity! ([arity : OpArg])
|
||||||
#:transparent)
|
#:transparent)
|
||||||
|
(define-struct: CheckPrimitiveArity! ([arity : OpArg])
|
||||||
|
#:transparent)
|
||||||
|
|
||||||
|
|
||||||
;; Extends the environment with a prefix that holds
|
;; Extends the environment with a prefix that holds
|
||||||
;; lookups to the namespace.
|
;; lookups to the namespace.
|
||||||
|
@ -268,6 +271,7 @@
|
||||||
(define-type PrimitiveCommand (U
|
(define-type PrimitiveCommand (U
|
||||||
CheckToplevelBound!
|
CheckToplevelBound!
|
||||||
CheckClosureArity!
|
CheckClosureArity!
|
||||||
|
CheckPrimitiveArity!
|
||||||
ExtendEnvironment/Prefix!
|
ExtendEnvironment/Prefix!
|
||||||
InstallClosureValues!
|
InstallClosureValues!
|
||||||
FixClosureShellMap!
|
FixClosureShellMap!
|
||||||
|
@ -361,4 +365,13 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(define-type Arity (U Natural
|
||||||
|
ArityAtLeast
|
||||||
|
(Listof (U Natural ArityAtLeast))))
|
||||||
|
(define-struct: ArityAtLeast ([value : Natural])
|
||||||
|
#:transparent)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define-predicate OpArg? OpArg)
|
(define-predicate OpArg? OpArg)
|
|
@ -235,7 +235,7 @@
|
||||||
|
|
||||||
|
|
||||||
var ArityAtLeast = function(n) {
|
var ArityAtLeast = function(n) {
|
||||||
this.n = n;
|
this.value = n;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,19 @@
|
||||||
(hash-set! mutated-primitives n p))
|
(hash-set! mutated-primitives n p))
|
||||||
|
|
||||||
|
|
||||||
|
(define (extract-arity proc)
|
||||||
|
(let loop ([racket-arity (procedure-arity proc)])
|
||||||
|
(cond
|
||||||
|
[(number? racket-arity)
|
||||||
|
racket-arity]
|
||||||
|
[(arity-at-least? racket-arity)
|
||||||
|
(make-ArityAtLeast (arity-at-least-value racket-arity))]
|
||||||
|
[(list? racket-arity)
|
||||||
|
(map loop racket-arity)])))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define-syntax (make-lookup stx)
|
(define-syntax (make-lookup stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ #:functions (name ...)
|
[(_ #:functions (name ...)
|
||||||
|
@ -27,7 +40,9 @@
|
||||||
(syntax/loc stx
|
(syntax/loc stx
|
||||||
(let ([prim-name (make-primitive-proc
|
(let ([prim-name (make-primitive-proc
|
||||||
(lambda (machine . args)
|
(lambda (machine . args)
|
||||||
(apply name args)))]
|
(apply name args))
|
||||||
|
(extract-arity name)
|
||||||
|
'exported-name)]
|
||||||
...)
|
...)
|
||||||
(lambda (n)
|
(lambda (n)
|
||||||
(cond
|
(cond
|
||||||
|
@ -43,13 +58,6 @@
|
||||||
(make-undefined)]
|
(make-undefined)]
|
||||||
)))))]))
|
)))))]))
|
||||||
|
|
||||||
;(define call/cc
|
|
||||||
; (make-closure call/cc-label
|
|
||||||
; 1
|
|
||||||
; '()
|
|
||||||
; 'call/cc))
|
|
||||||
;(define call-with-current-continuation call/cc)
|
|
||||||
|
|
||||||
(define e (exp 1))
|
(define e (exp 1))
|
||||||
|
|
||||||
(define my-cons (lambda (x y)
|
(define my-cons (lambda (x y)
|
||||||
|
@ -173,8 +181,6 @@
|
||||||
|
|
||||||
|
|
||||||
symbol?)
|
symbol?)
|
||||||
#:constants (null pi e
|
#:constants (null pi e)))
|
||||||
#;call/cc
|
|
||||||
#;call-with-current-continuation)))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -88,11 +88,14 @@
|
||||||
|
|
||||||
|
|
||||||
;; Primitive procedure wrapper
|
;; Primitive procedure wrapper
|
||||||
(define-struct: primitive-proc ([f : (machine PrimitiveValue * -> PrimitiveValue)])
|
(define-struct: primitive-proc ([f : (machine PrimitiveValue * -> PrimitiveValue)]
|
||||||
|
[arity : Arity]
|
||||||
|
[display-name : (U Symbol False)])
|
||||||
#:transparent)
|
#:transparent)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; Compiled procedure closures
|
;; Compiled procedure closures
|
||||||
(define-struct: closure ([label : Symbol]
|
(define-struct: closure ([label : Symbol]
|
||||||
[arity : Natural]
|
[arity : Natural]
|
||||||
|
|
|
@ -226,15 +226,29 @@
|
||||||
(let: ([clos : SlotValue (machine-proc m)])
|
(let: ([clos : SlotValue (machine-proc m)])
|
||||||
(cond
|
(cond
|
||||||
[(closure? clos)
|
[(closure? clos)
|
||||||
(if (= (closure-arity clos)
|
(if (arity-match? (closure-arity clos)
|
||||||
(ensure-natural (ensure-primitive-value (machine-val m))))
|
(ensure-natural (evaluate-oparg m (CheckClosureArity!-arity op))))
|
||||||
'ok
|
'ok
|
||||||
(error 'check-closure-arity "arity mismatch: passed ~s args to ~s"
|
(error 'check-closure-arity "arity mismatch: passed ~s args to ~s"
|
||||||
(machine-val m)
|
(ensure-natural (evaluate-oparg m (CheckClosureArity!-arity op)))
|
||||||
(closure-display-name clos)))]
|
(closure-display-name clos)))]
|
||||||
[else
|
[else
|
||||||
(error 'check-closure-arity "not a closure: ~s" clos)]))]
|
(error 'check-closure-arity "not a closure: ~s" clos)]))]
|
||||||
|
|
||||||
|
[(CheckPrimitiveArity!? op)
|
||||||
|
(let: ([clos : SlotValue (machine-proc m)])
|
||||||
|
(cond
|
||||||
|
[(primitive-proc? clos)
|
||||||
|
(if (arity-match? (primitive-proc-arity clos)
|
||||||
|
(ensure-natural (evaluate-oparg m (CheckPrimitiveArity!-arity op))))
|
||||||
|
'ok
|
||||||
|
(error 'check-primitive-arity "arity mismatch: passed ~s args to ~s"
|
||||||
|
(ensure-natural (evaluate-oparg m (CheckPrimitiveArity!-arity op)))
|
||||||
|
(primitive-proc-display-name clos)))]
|
||||||
|
[else
|
||||||
|
(error 'check-primitive-arity "not a primitive: ~s" clos)]))]
|
||||||
|
|
||||||
|
|
||||||
[(ExtendEnvironment/Prefix!? op)
|
[(ExtendEnvironment/Prefix!? op)
|
||||||
(env-push! m
|
(env-push! m
|
||||||
(make-toplevel (ExtendEnvironment/Prefix!-names op)
|
(make-toplevel (ExtendEnvironment/Prefix!-names op)
|
||||||
|
@ -291,6 +305,23 @@
|
||||||
'ok])))
|
'ok])))
|
||||||
|
|
||||||
|
|
||||||
|
(: arity-match? (Arity Natural -> Boolean))
|
||||||
|
(define (arity-match? an-arity n)
|
||||||
|
(cond
|
||||||
|
[(natural? an-arity)
|
||||||
|
(= n an-arity)]
|
||||||
|
[(ArityAtLeast? an-arity)
|
||||||
|
(>= n (ArityAtLeast-value an-arity))]
|
||||||
|
[(list? an-arity)
|
||||||
|
(ormap (lambda: ([atomic-arity : (U Natural ArityAtLeast)])
|
||||||
|
(cond [(natural? atomic-arity)
|
||||||
|
(= n atomic-arity)]
|
||||||
|
[(ArityAtLeast? atomic-arity)
|
||||||
|
(>= n (ArityAtLeast-value atomic-arity))]))
|
||||||
|
an-arity)]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(: compose-continuation-frames ((Listof frame) (Listof frame) -> (Listof frame)))
|
(: compose-continuation-frames ((Listof frame) (Listof frame) -> (Listof frame)))
|
||||||
;; Stitch together the continuation. A PromptFrame must exist at the head of frames-2.
|
;; Stitch together the continuation. A PromptFrame must exist at the head of frames-2.
|
||||||
|
|
|
@ -1016,6 +1016,17 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(test '(begin (define (m f x y)
|
||||||
|
(f (f x y) y))
|
||||||
|
(m + 7 4))
|
||||||
|
15)
|
||||||
|
|
||||||
|
(test '(begin (define (m f x y)
|
||||||
|
(f (f x y) y))
|
||||||
|
(m - 7 4))
|
||||||
|
-1)
|
||||||
|
|
||||||
|
|
||||||
#;(test (read (open-input-file "tests/conform/program0.sch"))
|
#;(test (read (open-input-file "tests/conform/program0.sch"))
|
||||||
(port->string (open-input-file "tests/conform/expected0.txt")))
|
(port->string (open-input-file "tests/conform/expected0.txt")))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user