evaluator: closures work
This commit is contained in:
9
src/Phsyche.package/PEnv.class/instance/lookupAt.put..st
Normal file
9
src/Phsyche.package/PEnv.class/instance/lookupAt.put..st
Normal 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 ]
|
@@ -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'.
|
@@ -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)
|
3
src/Phsyche.package/PProc.class/instance/env..st
Normal file
3
src/Phsyche.package/PProc.class/instance/env..st
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
accessing
|
||||||
|
env: e
|
||||||
|
env := e
|
3
src/Phsyche.package/PProc.class/instance/env.st
Normal file
3
src/Phsyche.package/PProc.class/instance/env.st
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
accessing
|
||||||
|
env
|
||||||
|
^ env
|
@@ -7,7 +7,8 @@
|
|||||||
"commentStamp" : "<historical>",
|
"commentStamp" : "<historical>",
|
||||||
"instvars" : [
|
"instvars" : [
|
||||||
"params",
|
"params",
|
||||||
"body" ],
|
"body",
|
||||||
|
"env" ],
|
||||||
"name" : "PProc",
|
"name" : "PProc",
|
||||||
"pools" : [
|
"pools" : [
|
||||||
],
|
],
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
as yet unclassified
|
as yet unclassified
|
||||||
divBinding
|
divBinding
|
||||||
^ #+ -> [ :e :v | e / v asFloat ]
|
^ #/ -> [ :e :v | e / v asFloat ]
|
@@ -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"
|
||||||
]
|
]
|
@@ -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
|
@@ -0,0 +1,5 @@
|
|||||||
|
as yet unclassified
|
||||||
|
evalBegin: expr in: environ
|
||||||
|
| res |
|
||||||
|
expr allButFirst do: [ :each | res := self eval: each in: environ ].
|
||||||
|
^ res
|
@@ -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
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
as yet unclassified
|
||||||
|
evalSet: expr in: environ
|
||||||
|
environ lookupAt: expr second put: (self eval: expr third in: environ).
|
||||||
|
^ #undefined
|
@@ -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
|
@@ -1,3 +1,3 @@
|
|||||||
as yet unclassified
|
as yet unclassified
|
||||||
minusBinding
|
minusBinding
|
||||||
^ #+ -> [ :e :v | e - v ]
|
^ #- -> [ :e :v | e - v ]
|
@@ -0,0 +1,3 @@
|
|||||||
|
tests
|
||||||
|
testEvalBegin
|
||||||
|
self assert: (ph parseAndEval: '(begin 1 2 3)') equals: 3
|
@@ -0,0 +1,3 @@
|
|||||||
|
tests
|
||||||
|
testEvalBeginSet
|
||||||
|
self assert: (ph parseAndEval: '(begin (define x 1) (set x 2) x)') equals: 2
|
@@ -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
|
@@ -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.
|
@@ -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.
|
@@ -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)))'.
|
||||||
|
@@ -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
|
@@ -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
|
@@ -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.
|
Reference in New Issue
Block a user