#lang racket
(require "../compiler/il-structs.rkt"
"../compiler/lexical-structs.rkt"
"../simulator/simulator-structs.rkt"
"../simulator/simulator-primitives.rkt"
"../simulator/simulator.rkt")
(printf "test-simulator.rkt\n")
(define-syntax (test stx)
(syntax-case stx ()
[(_ actual exp)
(with-syntax ([stx stx])
(syntax/loc #'stx
(begin
(printf "Running ~s ..." (syntax->datum #'stx))
(let ([results actual])
(unless (equal? results exp)
(raise-syntax-error #f (format "Expected ~s, got ~s" exp results)
#'stx)))
(printf "ok\n\n"))))]))
(define (step-n m n)
(cond
[(= n 0)
m]
[else
(step! m)
(step-n m (sub1 n))]))
(define (run! m)
(cond
[(can-step? m)
(step! m)
(run! m)]
[else
m]))
(let ([m (new-machine `(hello world ,(make-GotoStatement (make-Label 'hello)))
#f)])
(test (machine-pc (step-n m 0)) 0)
(test (machine-pc (step-n m 1)) 1)
(test (machine-pc (step-n m 1)) 2)
(test (machine-pc (step-n m 1)) 1)
(test (machine-pc (step-n m 1)) 2)
(test (machine-pc (step-n m 1)) 1))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'val (make-Const 42)))
#f)])
(test (machine-val m) (make-undefined))
(step! m)
(test (machine-val m) 42))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const 42)))
#f)])
(test (machine-proc m) (make-undefined))
(step! m)
(test (machine-proc m) 42))
(let* ([m (new-machine `(,(make-PushEnvironment 1 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const 42)))
#f)]
[m (run! m)])
(test (machine-env m) '(42)))
(let* ([m (new-machine `(,(make-PushEnvironment 1 #t)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #t) (make-Const 42))))]
[m (run! m)])
(test (machine-env m) (list (box 42))))
(let* ([m (new-machine `(,(make-PushEnvironment 1 #t)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #t) (make-Const 42))
,(make-PushEnvironment 1 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f)
(make-EnvLexicalReference 1 #t))))]
[m (run! m)])
(test (machine-env m) (list 42 (box 42))))
(let* ([m (new-machine `(,(make-PushEnvironment 1 #t)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #t) (make-Const 42))
,(make-PushEnvironment 1 #f)))]
[m (run! m)])
(test (machine-env m) (list (make-undefined)
(box 42))))
(let* ([m (new-machine `(,(make-PushEnvironment 1 #t)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #t) (make-Const 42))
,(make-PushEnvironment 1 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f)
(make-EnvLexicalReference 1 #f))))]
[m (run! m)])
(test (machine-env m) (list (box 42)
(box 42))))
(let* ([m (new-machine `(,(make-PushEnvironment 2 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const 42))))]
[m (run! m)])
(test (machine-env m) `(,(make-undefined) 42)))
(let* ([m (new-machine `(,(make-PushEnvironment 2 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const 42))))]
[m (run! m)])
(test (machine-env m) `(42 ,(make-undefined))))
(let ([m (new-machine `(,(make-PushEnvironment 20 #f)))])
(test (machine-env (run! m)) (build-list 20 (lambda (i) (make-undefined)))))
(let ([m (new-machine `(,(make-PushEnvironment 20 #f)
,(make-PopEnvironment (make-Const 20) (make-Const 0))))])
(test (machine-env (run! m)) '()))
(let* ([m (new-machine `(,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const "hewie"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const "dewey"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const "louie"))
,(make-PopEnvironment (make-Const 1) (make-Const 0))))])
(test (machine-env (run! m)) '("dewey" "louie")))
(let* ([m (new-machine `(,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const "hewie"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const "dewey"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const "louie"))
,(make-PopEnvironment (make-Const 1) (make-Const 1))))])
(test (machine-env (run! m)) '("hewie" "louie")))
(let* ([m (new-machine `(,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const "hewie"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const "dewey"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const "louie"))
,(make-PopEnvironment (make-Const 1) (make-Const 2))))])
(test (machine-env (run! m)) '("hewie" "dewey")))
(let* ([m (new-machine `(,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const "hewie"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const "dewey"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const "louie"))
,(make-PopEnvironment (make-Const 2) (make-Const 1))))])
(test (machine-env (run! m)) '("hewie")))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
foo
,(make-PushControlFrame/Call (make-LinkedLabel 'foo 'foo))
bar
,(make-PushControlFrame/Call (make-LinkedLabel 'bar 'bar))
baz
))])
(test (machine-control (run! m))
(list (make-CallFrame (make-LinkedLabel 'bar 'bar) #f (make-hasheq) (make-hasheq))
(make-CallFrame (make-LinkedLabel 'foo 'foo) #f (make-hasheq) (make-hasheq)))))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
foo
,(make-PushControlFrame/Call (make-LinkedLabel 'foo 'foo))
bar
,(make-PushControlFrame/Call (make-LinkedLabel 'bar 'bar))
baz
,(make-PopControlFrame)
))])
(test (machine-control (run! m))
(list (make-CallFrame (make-LinkedLabel 'foo 'foo) #f (make-hasheq) (make-hasheq)))))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
foo
,(make-PushControlFrame/Call (make-LinkedLabel 'foo 'foo))
bar
,(make-PushControlFrame/Call (make-LinkedLabel 'bar 'bar))
baz
,(make-PopControlFrame)
,(make-PopControlFrame)))])
(test (machine-control (run! m))
(list)))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'val (make-Const 42))
,(make-TestAndBranchStatement (make-TestFalse (make-Reg 'val)) 'on-false)
,(make-AssignImmediateStatement 'val (make-Const 'ok))
,(make-GotoStatement (make-Label 'end))
on-false
,(make-AssignImmediateStatement 'val (make-Const 'not-ok))
end))])
(test (machine-val (run! m))
'ok))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'val (make-Const #f))
,(make-TestAndBranchStatement (make-TestFalse (make-Reg 'val)) 'on-false)
,(make-AssignImmediateStatement 'val (make-Const 'not-ok))
,(make-GotoStatement (make-Label 'end))
on-false
,(make-AssignImmediateStatement 'val (make-Const 'ok))
end))])
(test (machine-val (run! m))
'ok))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'val (make-Const '+))
,(make-TestAndBranchStatement (make-TestPrimitiveProcedure (make-Reg 'val)) 'on-true)
,(make-AssignImmediateStatement 'val (make-Const 'ok))
,(make-GotoStatement (make-Label 'end))
on-true
,(make-AssignImmediateStatement 'val (make-Const 'not-ok))
end))])
(test (machine-val (run! m))
'ok))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'val (make-Const (lookup-primitive '+)))
,(make-TestAndBranchStatement (make-TestPrimitiveProcedure (make-Reg 'val)) 'on-true)
,(make-AssignImmediateStatement 'val (make-Const 'not-ok))
,(make-GotoStatement (make-Label 'end))
on-true
,(make-AssignImmediateStatement 'val (make-Const 'ok))
end))])
(test (machine-val (run! m))
'ok))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const (lookup-primitive '+)))
,(make-TestAndBranchStatement (make-TestPrimitiveProcedure (make-Reg 'val)) 'on-true)
,(make-AssignImmediateStatement 'val (make-Const 'not-a-procedure))
,(make-GotoStatement (make-Label 'end))
on-true
,(make-AssignImmediateStatement 'val (make-Const 'a-procedure))
end))])
(test (machine-val (run! m))
'not-a-procedure))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const (lookup-primitive '+)))
,(make-TestAndBranchStatement (make-TestPrimitiveProcedure (make-Reg 'proc)) 'on-true)
,(make-AssignImmediateStatement 'val (make-Const 'not-a-procedure))
,(make-GotoStatement (make-Label 'end))
on-true
,(make-AssignImmediateStatement 'val (make-Const 'a-procedure))
end))])
(test (machine-val (run! m))
'a-procedure))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(+ - * =)))))])
(test (first (machine-env (run! m)))
(make-toplevel '(+ - * =)
(list (lookup-primitive '+)
(lookup-primitive '-)
(lookup-primitive '*)
(lookup-primitive '=)))))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(some-variable)))
,(make-AssignImmediateStatement 'val (make-Const "Danny"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 0) (make-Reg 'val))))])
(test (machine-env (run! m))
(list (make-toplevel '(some-variable) (list "Danny")))))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(some-variable another)))
,(make-AssignImmediateStatement 'val (make-Const "Danny"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 1) (make-Reg 'val))))])
(test (machine-env (run! m))
(list (make-toplevel '(some-variable another) (list (make-undefined) "Danny")))))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(some-variable)))
,(make-AssignImmediateStatement 'val (make-Const "Danny"))
,(make-PushEnvironment 5 #f)
,(make-AssignImmediateStatement (make-EnvPrefixReference 5 0) (make-Reg 'val))))])
(test (machine-env (run! m))
(list (make-undefined) (make-undefined) (make-undefined) (make-undefined) (make-undefined)
(make-toplevel '(some-variable) (list "Danny")))))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(some-variable)))
,(make-PerformStatement (make-CheckToplevelBound! 0 0))))])
(with-handlers ((exn:fail? (lambda (exn)
(void))))
(run! m)
(raise "I expected an error")))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(some-variable)))
,(make-AssignImmediateStatement 'val (make-Const "Danny"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 0) (make-Reg 'val))
,(make-PerformStatement (make-CheckToplevelBound! 0 0))))])
(void (run! m)))
(let ([m
(make-machine (make-undefined)
(make-closure 'procedure-entry
0
(list 1 2 3)
'procedure-entry)
(make-undefined)
(list true false) '()
0
(list->vector `(,(make-PerformStatement (make-InstallClosureValues!))
procedure-entry))
(make-hash)
0
(make-hash))])
(test (machine-env (run! m))
(list 1 2 3 true false)))
(let ([m
(make-machine (make-undefined)
(make-closure 'procedure-entry 0 (list 1 2 3) 'procedure-entry)
(make-undefined)
(list true false) '()
0
(list->vector `(,(make-AssignPrimOpStatement 'val (make-GetCompiledProcedureEntry))))
(make-hash)
0
(make-hash))])
(test (machine-val (run! m))
'procedure-entry))
(let ([m (new-machine `(,(make-AssignPrimOpStatement
'val
(make-MakeCompiledProcedure 'procedure-entry 0 (list) 'procedure-entry))
,(make-GotoStatement (make-Label 'end))
procedure-entry
end
))])
(test (machine-val (run! m))
(make-closure 'procedure-entry 0 (list) 'procedure-entry)))
(let ([m (new-machine `(,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const 'larry))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const 'curly))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const 'moe))
,(make-AssignPrimOpStatement
'val
(make-MakeCompiledProcedure 'procedure-entry
0
(list 0 2)
'procedure-entry))
,(make-GotoStatement (make-Label 'end))
procedure-entry
end
))])
(test (machine-val (run! m))
(make-closure 'procedure-entry 0 (list 'larry 'moe)
'procedure-entry)))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(x y z)))
,(make-AssignImmediateStatement 'val (make-Const "x"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 0) (make-Reg 'val))
,(make-AssignImmediateStatement 'val (make-Const "y"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 1) (make-Reg 'val))
,(make-AssignImmediateStatement 'val (make-Const "z"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 2) (make-Reg 'val))
,(make-AssignPrimOpStatement
'val
(make-MakeCompiledProcedure 'procedure-entry
0
(list 0)
'procedure-entry))
,(make-GotoStatement (make-Label 'end))
procedure-entry
end
))])
(test (machine-val (run! m))
(make-closure 'procedure-entry 0 (list (make-toplevel '(x y z) (list "x" "y" "z")))
'procedure-entry)))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(x y z)))
,(make-AssignImmediateStatement 'val (make-Const "x"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 0) (make-Reg 'val))
,(make-AssignImmediateStatement 'val (make-Const "y"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 1) (make-Reg 'val))
,(make-AssignImmediateStatement 'val (make-Const "z"))
,(make-AssignImmediateStatement (make-EnvPrefixReference 0 2) (make-Reg 'val))
,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const 'larry))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const 'curly))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const 'moe))
,(make-AssignPrimOpStatement
'val
(make-MakeCompiledProcedure 'procedure-entry
0
(list 3 0 2)
'procedure-entry))
,(make-PopEnvironment (make-Const 3) (make-Const 0))
,(make-GotoStatement (make-Label 'end))
procedure-entry
end
))])
(test (machine-val (run! m))
(make-closure 'procedure-entry
0
(list (make-toplevel '(x y z) (list "x" "y" "z"))
'larry
'moe)
'procedure-entry)))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(+)))
,(make-AssignImmediateStatement 'val (make-EnvPrefixReference 0 0))))])
(test (machine-val (run! m))
(lookup-primitive '+)))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(+)))
,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const 'larry))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const 'curly))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const 'moe))
,(make-AssignImmediateStatement 'val (make-EnvLexicalReference 0 #f))))])
(test (machine-val (run! m))
'larry))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(+)))
,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const 'larry))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const 'curly))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f) (make-Const 'moe))
,(make-AssignImmediateStatement 'val (make-EnvLexicalReference 1 #f))))])
(test (machine-val (run! m))
'curly))
(let ([m (new-machine `(,(make-PerformStatement (make-ExtendEnvironment/Prefix! '(+)))
,(make-AssignImmediateStatement 'proc (make-EnvPrefixReference 0 0))
,(make-PushEnvironment 2 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f) (make-Const 126389))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f) (make-Const 42))
,(make-AssignImmediateStatement 'argcount (make-Const 2))
,(make-AssignPrimOpStatement 'val (make-ApplyPrimitiveProcedure))
after))])
(test (machine-val (run! m))
(+ 126389 42))
(test (machine-env (run! m))
(list 126389 42 (make-toplevel '(+) (list (lookup-primitive '+))))))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
foo
,(make-PushControlFrame/Call (make-LinkedLabel 'foo 'foo))
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel))))])
(test (machine-proc (run! m))
'foo))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
,(make-PushControlFrame/Call (make-LinkedLabel 'foo-single 'foo-multiple))
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel))
,(make-GotoStatement (make-Reg 'proc))
foo-single
,(make-AssignImmediateStatement 'val (make-Const "single"))
,(make-GotoStatement (make-Label 'end))
foo-multiple
,(make-AssignImmediateStatement 'val (make-Const "multiple"))
,(make-GotoStatement (make-Label 'end))
end))])
(test (machine-val (run! m))
"single"))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
,(make-PushControlFrame/Call (make-LinkedLabel 'foo-single 'foo-multiple))
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel/MultipleValueReturn))
,(make-GotoStatement (make-Reg 'proc))
foo-single
,(make-AssignImmediateStatement 'val (make-Const "single"))
,(make-GotoStatement (make-Label 'end))
foo-multiple
,(make-AssignImmediateStatement 'val (make-Const "multiple"))
,(make-GotoStatement (make-Label 'end))
end))])
(test (machine-val (run! m))
"multiple"))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
,(make-PushControlFrame/Prompt default-continuation-prompt-tag
(make-LinkedLabel 'foo-single 'foo-multiple))
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel))
,(make-GotoStatement (make-Reg 'proc))
foo-single
,(make-AssignImmediateStatement 'val (make-Const "single"))
,(make-GotoStatement (make-Label 'end))
foo-multiple
,(make-AssignImmediateStatement 'val (make-Const "multiple"))
,(make-GotoStatement (make-Label 'end))
end))])
(test (machine-val (run! m))
"single"))
(let ([m (new-machine `(,(make-AssignImmediateStatement 'proc (make-Const #f))
,(make-PushControlFrame/Prompt default-continuation-prompt-tag
(make-LinkedLabel 'foo-single 'foo-multiple))
,(make-AssignImmediateStatement 'proc (make-ControlStackLabel/MultipleValueReturn))
,(make-GotoStatement (make-Reg 'proc))
foo-single
,(make-AssignImmediateStatement 'val (make-Const "single"))
,(make-GotoStatement (make-Label 'end))
foo-multiple
,(make-AssignImmediateStatement 'val (make-Const "multiple"))
,(make-GotoStatement (make-Label 'end))
end))])
(test (machine-val (run! m))
"multiple"))
(let ([m (new-machine `(,(make-PushEnvironment 1 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f)
(make-Const '(1 2 3)))
,(make-AssignImmediateStatement 'argcount (make-Const 1))
,(make-PerformStatement (make-SpliceListIntoStack! (make-Const 0)))))])
(run! m)
(test (machine-argcount m)
3)
(test (machine-env m)
'(1 2 3)))
(let ([m (new-machine `(,(make-PushEnvironment 3 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f)
(make-Const "hello"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f)
(make-Const "world"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f)
(make-Const '(1 2 3)))
,(make-AssignImmediateStatement 'argcount (make-Const 3))
,(make-PerformStatement (make-SpliceListIntoStack! (make-Const 2)))))])
(run! m)
(test (machine-argcount m)
5)
(test (machine-env m)
'("hello" "world" 1 2 3)))
(let ([m (new-machine `(,(make-PushImmediateOntoEnvironment (make-Const "this is a message")
#f)))])
(run! m)
(test (machine-env m)
'("this is a message")))
(let ([m (new-machine `(,(make-PushImmediateOntoEnvironment (make-Const "this is a message")
#t)))])
(run! m)
(test (machine-env m)
`(,(box "this is a message"))))
(let ([m (new-machine `(,(make-PushImmediateOntoEnvironment (make-Const "this is a message")
#f)
,(make-PushImmediateOntoEnvironment (make-Const "again")
#f)
))])
(run! m)
(test (machine-env m)
'("again" "this is a message")))
(let ([m (new-machine `(,(make-PushImmediateOntoEnvironment (make-Const "this is a message")
#f)
,(make-PushImmediateOntoEnvironment (make-Const "again")
#t)
))])
(run! m)
(test (machine-env m)
`(,(box "again") "this is a message")))
(let ([m (new-machine `(,(make-PushEnvironment 1 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f)
(make-Const "hello"))
,(make-AssignImmediateStatement 'argcount (make-Const 1))
,(make-PerformStatement (make-UnspliceRestFromStack! (make-Const 0)
(make-Const 1)))))])
(run! m)
(test (machine-argcount m)
1)
(test (machine-env m)
(list (make-MutablePair "hello" null))))
(let ([m (new-machine
`(,(make-PushEnvironment 5 #f)
,(make-AssignImmediateStatement (make-EnvLexicalReference 0 #f)
(make-Const "hello"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 1 #f)
(make-Const "world"))
,(make-AssignImmediateStatement (make-EnvLexicalReference 2 #f)
(make-Const 'x))
,(make-AssignImmediateStatement (make-EnvLexicalReference 3 #f)
(make-Const 'y))
,(make-AssignImmediateStatement (make-EnvLexicalReference 4 #f)
(make-Const 'z))
,(make-AssignImmediateStatement 'argcount (make-Const 5))
,(make-PerformStatement (make-UnspliceRestFromStack! (make-Const 2) (make-Const 3)))))])
(run! m)
(test (machine-argcount m)
3)
(test (machine-env m)
(list "hello"
"world"
(make-MutablePair 'x (make-MutablePair 'y (make-MutablePair 'z null))))))
(let ([m (new-machine `(procedure-entry
,(make-AssignPrimOpStatement
'proc
(make-MakeCompiledProcedure 'procedure-entry 0 (list) 'procedure-entry))
,(make-TestAndBranchStatement
(make-TestClosureArityMismatch (make-Reg 'proc) (make-Const 0))
'bad)
,(make-AssignImmediateStatement 'val (make-Const 'ok))
,(make-GotoStatement (make-Label 'end))
bad
,(make-AssignImmediateStatement 'val (make-Const 'bad))
end))])
(test (machine-val (run! m))
'ok))
(let ([m (new-machine `(procedure-entry
,(make-AssignPrimOpStatement
'proc
(make-MakeCompiledProcedure 'procedure-entry 0 (list) 'procedure-entry))
,(make-TestAndBranchStatement
(make-TestClosureArityMismatch (make-Reg 'proc) (make-Const 1))
'ok)
,(make-AssignImmediateStatement 'val (make-Const 'bad))
,(make-GotoStatement (make-Label 'end))
ok
,(make-AssignImmediateStatement 'val (make-Const 'ok))
end))])
(test (machine-val (run! m))
'ok))
(let ([m (new-machine `(procedure-entry
,(make-AssignPrimOpStatement
'proc
(make-MakeCompiledProcedure 'procedure-entry (make-ArityAtLeast 2) (list) 'procedure-entry))
,(make-TestAndBranchStatement
(make-TestClosureArityMismatch (make-Reg 'proc) (make-Const 0))
'ok)
,(make-AssignImmediateStatement 'val (make-Const 'bad))
,(make-GotoStatement (make-Label 'end))
ok
,(make-AssignImmediateStatement 'val (make-Const 'ok))
end))])
(test (machine-val (run! m))
'ok))
(let ([m (new-machine `(procedure-entry
,(make-AssignPrimOpStatement
'proc
(make-MakeCompiledProcedure 'procedure-entry (make-ArityAtLeast 2) (list) 'procedure-entry))
,(make-TestAndBranchStatement
(make-TestClosureArityMismatch (make-Reg 'proc) (make-Const 2))
'bad)
,(make-AssignImmediateStatement 'val (make-Const 'ok))
,(make-GotoStatement (make-Label 'end))
bad
,(make-AssignImmediateStatement 'val (make-Const 'bad))
end))])
(test (machine-val (run! m))
'ok))