diff --git a/assemble.rkt b/assemble.rkt index 7c3e7b4..54ccd85 100644 --- a/assemble.rkt +++ b/assemble.rkt @@ -238,7 +238,7 @@ EOF (format "return ~a();" (assemble-location (GotoStatement-target stmt)))] [(PushControlFrame? stmt) - (format "MACHINE.control.push(~a);" (PushControlFrame-label stmt))] + (format "MACHINE.control.push(new Frame(~a));" (PushControlFrame-label stmt))] [(PopControlFrame? stmt) "MACHINE.control.pop();"] [(PushEnvironment? stmt) @@ -356,8 +356,9 @@ EOF (symbol->string (CheckToplevelBound!-name op)))] [(CheckClosureArity!? op) - ;; fixme - (error 'assemble-op-statement)] + (format "if (! (MACHINE.proc instanceof Closure && MACHINE.proc.arity === ~a)) { if (! (MACHINE.proc instanceof Closure)) { throw new Error(\"not a closure\"); } else { throw new Error(\"arity failure\"); } }" + (CheckClosureArity!-arity op) + )] [(ExtendEnvironment/Prefix!? op) (let: ([names : (Listof Symbol) (ExtendEnvironment/Prefix!-names op)]) diff --git a/test-assemble.rkt b/test-assemble.rkt index d3b1910..96cb826 100644 --- a/test-assemble.rkt +++ b/test-assemble.rkt @@ -227,6 +227,49 @@ "function,true") +;; check-closure-arity. This should succeed. +(void (E-many (list (make-GotoStatement (make-Label 'afterLambdaBody)) + + 'closureStart + (make-PerformStatement (make-InstallClosureValues!)) + (make-GotoStatement (make-Label 'theEnd)) + + 'afterLambdaBody + (make-PushEnvironment 2) + (make-AssignImmediateStatement (make-EnvLexicalReference 0) + (make-Const "hello")) + (make-AssignImmediateStatement (make-EnvLexicalReference 1) + (make-Const "world")) + (make-AssignPrimOpStatement 'proc (make-MakeCompiledProcedure 'closureStart 5 + (list (make-EnvLexicalReference 0) + (make-EnvLexicalReference 1)))) + (make-PopEnvironment 2 0) + (make-PerformStatement (make-CheckClosureArity! 5))))) + +;; this should fail, since the check is for 1, but the closure expects 5. +(let/ec return + (with-handlers ([void + (lambda (exn) (return))]) + (E-many (list (make-GotoStatement (make-Label 'afterLambdaBody)) + + 'closureStart + (make-PerformStatement (make-InstallClosureValues!)) + (make-GotoStatement (make-Label 'theEnd)) + + 'afterLambdaBody + (make-PushEnvironment 2) + (make-AssignImmediateStatement (make-EnvLexicalReference 0) + (make-Const "hello")) + (make-AssignImmediateStatement (make-EnvLexicalReference 1) + (make-Const "world")) + (make-AssignPrimOpStatement 'proc (make-MakeCompiledProcedure 'closureStart 5 + (list (make-EnvLexicalReference 0) + (make-EnvLexicalReference 1)))) + (make-PopEnvironment 2 0) + (make-PerformStatement (make-CheckClosureArity! 1))))) + (error 'expected-failure)) + +