evaluator: closures work

This commit is contained in:
2018-04-30 20:26:54 +02:00
parent 127d2e4ad8
commit c9487eb1a5
23 changed files with 100 additions and 10 deletions

View File

@@ -0,0 +1,9 @@
dictionary access
lookupAt: key put: val
| found |
found := self at: key ifAbsent: nil.
found
ifNil: [ parent
ifNotNil: [ :arg | parent lookupAt: key put: val ]
ifNil: [ KeyNotFound signal: key , ' not found in the environment' ] ]
ifNotNil: [ :arg | self at: key put: val ]

View File

@@ -0,0 +1,9 @@
tests
testSetAtRightLevel
outer at: #dad put: 'donald'.
inner at: #son put: 'riri'.
self assert: (inner at: #son) = 'riri'.
inner lookupAt: #son put: 'fifi'.
self assert: (outer at: #dad) = 'donald'.
outer lookupAt: #dad put: 'piscou'.
self assert: (outer at: #dad) = 'piscou'.

View File

@@ -0,0 +1,9 @@
tests
testSetLookup
outer at: #dad put: 'donald'.
inner at: #son put: 'riri'.
self assert: (inner at: #dad) = 'donald'.
inner lookupAt: #dad put: 'picsou'.
self assert: (outer at: #dad) = 'picsou'.
self assert: (inner at: #dad) = 'picsou'.
self deny: (inner keys includes: #dad)

View File

@@ -0,0 +1,3 @@
accessing
env: e
env := e

View File

@@ -0,0 +1,3 @@
accessing
env
^ env

View File

@@ -7,7 +7,8 @@
"commentStamp" : "<historical>", "commentStamp" : "<historical>",
"instvars" : [ "instvars" : [
"params", "params",
"body" ], "body",
"env" ],
"name" : "PProc", "name" : "PProc",
"pools" : [ "pools" : [
], ],

View File

@@ -1,3 +1,3 @@
as yet unclassified as yet unclassified
divBinding divBinding
^ #+ -> [ :e :v | e / v asFloat ] ^ #/ -> [ :e :v | e / v asFloat ]

View File

@@ -12,6 +12,8 @@ eval: expr in: environ
fst = #define ifTrue: [ ^ self evalDefine: expr in: environ ]. "defines the value" fst = #define ifTrue: [ ^ self evalDefine: expr in: environ ]. "defines the value"
fst = #if ifTrue: [ ^ self evalIf: expr in: environ]. "evaluates if" fst = #if ifTrue: [ ^ self evalIf: expr in: environ]. "evaluates if"
fst = #lambda ifTrue: [ ^ self evalLambda: expr in: environ ]. "evaluates lambda" fst = #lambda ifTrue: [ ^ self evalLambda: expr in: environ ]. "evaluates lambda"
fst = #begin ifTrue: [ ^ self evalBegin: expr in: environ ]. "evaluates begin"
fst = #quote ifTrue: [ ^ expr second ]. "returns the value unevaluated" fst = #quote ifTrue: [ ^ expr second ]. "returns the value unevaluated"
^ self evalApp: expr in: environ fst = #set ifTrue: [ ^ self evalSet: expr in: environ ]. "evaluates set"
^ self evalApp: expr in: environ "everything else is treated as fn application"
] ]

View File

@@ -3,5 +3,5 @@ evalApp: expr in: environ
| proc newEnv | | proc newEnv |
proc := self eval: expr first in: environ. proc := self eval: expr first in: environ.
newEnv := proc setParamEnv: (expr allButFirst collect: [ :e | self eval: e in: environ ]) newEnv := proc setParamEnv: (expr allButFirst collect: [ :e | self eval: e in: environ ])
in: environ. in: proc env.
^ self eval: proc body in: newEnv ^ self eval: proc body in: newEnv

View File

@@ -0,0 +1,5 @@
as yet unclassified
evalBegin: expr in: environ
| res |
expr allButFirst do: [ :each | res := self eval: each in: environ ].
^ res

View File

@@ -1,3 +1,3 @@
as yet unclassified as yet unclassified
evalLambda: expr in: environ evalLambda: expr in: environ
^ PProc new params: expr second; body: expr third ^ PProc new params: expr second; body: expr third; env: environ

View File

@@ -0,0 +1,4 @@
as yet unclassified
evalSet: expr in: environ
environ lookupAt: expr second put: (self eval: expr third in: environ).
^ #undefined

View File

@@ -1,6 +1,6 @@
initialization initialization
initialize initialize
super initialize. super initialize.
env := Dictionary new. env := PEnv new.
prims := OrderedCollection new. prims := OrderedCollection new.
self initializeEnvBindings self initializeEnvBindings

View File

@@ -1,3 +1,3 @@
as yet unclassified as yet unclassified
minusBinding minusBinding
^ #+ -> [ :e :v | e - v ] ^ #- -> [ :e :v | e - v ]

View File

@@ -0,0 +1,3 @@
tests
testEvalBegin
self assert: (ph parseAndEval: '(begin 1 2 3)') equals: 3

View File

@@ -0,0 +1,3 @@
tests
testEvalBeginSet
self assert: (ph parseAndEval: '(begin (define x 1) (set x 2) x)') equals: 2

View File

@@ -0,0 +1,13 @@
tests
testEvalSetAtCorrectLevel
| proc |
ph parseAndEval: '
(define fy3
((lambda (x)
(lambda (y)
(begin
(set x (+ x 2))
(+ x y))))
3))'.
proc := ph eval: #fy3.
self assert: (ph parseAndEval: '(fy3 5)') equals: 10

View File

@@ -0,0 +1,5 @@
tests
testEvalSimpleSet
self assert: (ph parseAndEval: '(define x2 21') equals: #undefined.
self assert: (ph parseAndEval: '(set x2 22)') equals: #undefined.
self assert: (ph parseAndEval: 'x2') equals: 22.

View File

@@ -1,3 +1,3 @@
as yet unclassified tests
testLambdaProcedureExecution testLambdaProcedureExecution
self assert: (ph parseAndEval: '((lambda (x) (* x x)) 3)') equals: 9. self assert: (ph parseAndEval: '((lambda (x) (* x x)) 3)') equals: 9.

View File

@@ -1,4 +1,4 @@
as yet unclassified tests
testProcedureDefinition testProcedureDefinition
| proc | | proc |
ph parseAndEval: '(define squared (lambda (x) (* x x)))'. ph parseAndEval: '(define squared (lambda (x) (* x x)))'.

View File

@@ -1,4 +1,4 @@
as yet unclassified tests
testProcedureExecution testProcedureExecution
ph parseAndEval: '(define squared (lambda (x) (* x x)))'. ph parseAndEval: '(define squared (lambda (x) (* x x)))'.
self assert: (ph parseAndEval: '(squared 3)') equals: 9 self assert: (ph parseAndEval: '(squared 3)') equals: 9

View File

@@ -0,0 +1,10 @@
tests
testSimpleClosure
| res |
res := ph eval: (ph parse: '(
((lambda (x)
(lambda (y)
(+ x y)))
3)
7)').
self assert: res equals: 10

View File

@@ -0,0 +1,11 @@
tests
testSimpleClosureIntrospection
| proc |
ph parseAndEval: '(define fy3
((lambda (x)
(lambda (y)
x))
3))'.
proc := ph parseAndEval: '#fy3'.
self assert: proc params equals: #(y).
self assert: (proc env at: #x) equals: 3.