@@ -4,24 +4,24 @@ import (
4
4
"fmt"
5
5
"strconv"
6
6
7
- "golox/pkg/ast"
8
7
"golox/pkg/fault"
8
+ "golox/pkg/parser"
9
9
"golox/pkg/scanner"
10
10
)
11
11
12
-
13
- type interpreter struct {
14
- global * environment
15
- env * environment
12
+ type Interpreter struct {
13
+ global * environment
14
+ current * environment
15
+ locals map [parser. Expr ] int
16
16
}
17
17
18
- func NewInterpreter () * interpreter {
18
+ func NewInterpreter () * Interpreter {
19
19
global := & environment {nil , make (map [string ]interface {})}
20
20
global .define ("clock" , & clock {})
21
- return & interpreter {global , global }
21
+ return & Interpreter {global , global , make ( map [parser. Expr ] int ) }
22
22
}
23
23
24
- func (i * interpreter ) Interpret (stmts []ast .Stmt ) (err error ) {
24
+ func (i * Interpreter ) Interpret (stmts []parser .Stmt ) (err error ) {
25
25
defer func () {
26
26
if r := recover (); r != nil {
27
27
err = r .(error )
@@ -35,12 +35,16 @@ func (i *interpreter) Interpret(stmts []ast.Stmt) (err error) {
35
35
return
36
36
}
37
37
38
- func (i * interpreter ) VisitExprStmt (e * ast.ExprStmt ) interface {} {
38
+ func (i * Interpreter ) Resolve (expr parser.Expr , depth int ) {
39
+ i .locals [expr ] = depth
40
+ }
41
+
42
+ func (i * Interpreter ) VisitExprStmt (e * parser.ExprStmt ) interface {} {
39
43
e .Expression .Accept (i )
40
44
return nil
41
45
}
42
46
43
- func (i * interpreter ) VisitPrintStmt (p * ast .PrintStmt ) interface {} {
47
+ func (i * Interpreter ) VisitPrintStmt (p * parser .PrintStmt ) interface {} {
44
48
value := p .Expression .Accept (i )
45
49
switch v := value .(type ) {
46
50
case float64 :
@@ -54,31 +58,31 @@ func (i *interpreter) VisitPrintStmt(p *ast.PrintStmt) interface{} {
54
58
return nil
55
59
}
56
60
57
- func (i * interpreter ) VisitVarStmt (v * ast .VarStmt ) interface {} {
61
+ func (i * Interpreter ) VisitVarStmt (v * parser .VarStmt ) interface {} {
58
62
var value interface {}
59
63
if v .Initializer != nil {
60
64
value = v .Initializer .Accept (i )
61
65
}
62
66
63
- i .env .define (v .Name .Lexeme , value )
67
+ i .current .define (v .Name .Lexeme , value )
64
68
return nil
65
69
}
66
70
67
- func (i * interpreter ) VisitBlockStmt (b * ast .BlockStmt ) interface {} {
68
- prev := i .env
71
+ func (i * Interpreter ) VisitBlockStmt (b * parser .BlockStmt ) interface {} {
72
+ prev := i .current
69
73
defer func () {
70
- i .env = prev
74
+ i .current = prev
71
75
}()
72
76
73
- i .env = & environment {prev , make (map [string ]interface {})}
77
+ i .current = & environment {prev , make (map [string ]interface {})}
74
78
for _ , stmt := range b .Statements {
75
79
stmt .Accept (i )
76
80
}
77
81
78
82
return nil
79
83
}
80
84
81
- func (i * interpreter ) VisitIfStmt (i_ * ast .IfStmt ) interface {} {
85
+ func (i * Interpreter ) VisitIfStmt (i_ * parser .IfStmt ) interface {} {
82
86
value := i_ .Condition .Accept (i )
83
87
if isTruthy (value ) {
84
88
i_ .ThenBranch .Accept (i )
@@ -89,20 +93,20 @@ func (i *interpreter) VisitIfStmt(i_ *ast.IfStmt) interface{} {
89
93
return nil
90
94
}
91
95
92
- func (i * interpreter ) VisitWhileStmt (w * ast .WhileStmt ) interface {} {
96
+ func (i * Interpreter ) VisitWhileStmt (w * parser .WhileStmt ) interface {} {
93
97
for isTruthy (w .Condition .Accept (i )) {
94
98
w .Body .Accept (i )
95
99
}
96
100
97
101
return nil
98
102
}
99
103
100
- func (i * interpreter ) VisitFunStmt (f * ast .FunStmt ) interface {} {
101
- i .env .define (f .Name .Lexeme , & function {f })
104
+ func (i * Interpreter ) VisitFunStmt (f * parser .FunStmt ) interface {} {
105
+ i .current .define (f .Name .Lexeme , & function {f , i . current })
102
106
return nil
103
107
}
104
108
105
- func (i * interpreter ) VisitReturnStmt (v * ast .ReturnStmt ) interface {} {
109
+ func (i * Interpreter ) VisitReturnStmt (v * parser .ReturnStmt ) interface {} {
106
110
var value interface {}
107
111
if v .Value != nil {
108
112
value = v .Value .Accept (i )
@@ -111,7 +115,7 @@ func (i *interpreter) VisitReturnStmt(v *ast.ReturnStmt) interface{} {
111
115
panic (value )
112
116
}
113
117
114
- func (i * interpreter ) VisitBinaryExpr (b * ast .BinaryExpr ) interface {} {
118
+ func (i * Interpreter ) VisitBinaryExpr (b * parser .BinaryExpr ) interface {} {
115
119
left := b .Left .Accept (i )
116
120
right := b .Right .Accept (i )
117
121
@@ -160,15 +164,15 @@ func (i *interpreter) VisitBinaryExpr(b *ast.BinaryExpr) interface{} {
160
164
return nil
161
165
}
162
166
163
- func (i * interpreter ) VisitGroupingExpr (g * ast .GroupingExpr ) interface {} {
167
+ func (i * Interpreter ) VisitGroupingExpr (g * parser .GroupingExpr ) interface {} {
164
168
return g .Expression .Accept (i )
165
169
}
166
170
167
- func (i * interpreter ) VisitLiteralExpr (l * ast .LiteralExpr ) interface {} {
171
+ func (i * Interpreter ) VisitLiteralExpr (l * parser .LiteralExpr ) interface {} {
168
172
return l .Value
169
173
}
170
174
171
- func (i * interpreter ) VisitUnaryExpr (u * ast .UnaryExpr ) interface {} {
175
+ func (i * Interpreter ) VisitUnaryExpr (u * parser .UnaryExpr ) interface {} {
172
176
right := u .Right .Accept (i )
173
177
174
178
if u .Operator .TokenType == scanner .MINUS {
@@ -193,17 +197,27 @@ func (i *interpreter) VisitUnaryExpr(u *ast.UnaryExpr) interface{} {
193
197
return nil
194
198
}
195
199
196
- func (i * interpreter ) VisitVariableExpr (v * ast.VariableExpr ) interface {} {
197
- return i .env .get (v .Name )
200
+ func (i * Interpreter ) VisitVariableExpr (v * parser.VariableExpr ) interface {} {
201
+ if dist , ok := i .locals [v ]; ok {
202
+ return i .current .getAt (v .Name .Lexeme , dist )
203
+ }
204
+
205
+ return i .global .get (v .Name )
198
206
}
199
207
200
- func (i * interpreter ) VisitAssignExpr (a * ast .AssignExpr ) interface {} {
208
+ func (i * Interpreter ) VisitAssignExpr (a * parser .AssignExpr ) interface {} {
201
209
value := a .Value .Accept (i )
202
- i .env .assign (a .Name , value )
210
+
211
+ if dist , ok := i .locals [a ]; ok {
212
+ i .current .assignAt (a .Name .Lexeme , value , dist )
213
+ } else {
214
+ i .global .assign (a .Name , value )
215
+ }
216
+
203
217
return value
204
218
}
205
219
206
- func (i * interpreter ) VisitLogicalExpr (l * ast .LogicalExpr ) interface {} {
220
+ func (i * Interpreter ) VisitLogicalExpr (l * parser .LogicalExpr ) interface {} {
207
221
left := l .Left .Accept (i )
208
222
209
223
if (l .Operator .TokenType == scanner .OR && isTruthy (left )) || ! isTruthy (left ) {
@@ -213,7 +227,7 @@ func (i *interpreter) VisitLogicalExpr(l *ast.LogicalExpr) interface{} {
213
227
return l .Right .Accept (i )
214
228
}
215
229
216
- func (i * interpreter ) VisitCallExpr (c * ast .CallExpr ) interface {} {
230
+ func (i * Interpreter ) VisitCallExpr (c * parser .CallExpr ) interface {} {
217
231
callee := c .Callee .Accept (i )
218
232
args := []interface {}{}
219
233
for _ , arg := range c .Arguments {
@@ -232,7 +246,7 @@ func (i *interpreter) VisitCallExpr(c *ast.CallExpr) interface{} {
232
246
panic (fault .NewFault (c .Paren .Line , "can only call functions and classes" ))
233
247
}
234
248
235
- func (i * interpreter ) checkNumberOperands (operator * scanner.Token , left interface {}, right interface {}) (float64 , float64 ) {
249
+ func (i * Interpreter ) checkNumberOperands (operator * scanner.Token , left interface {}, right interface {}) (float64 , float64 ) {
236
250
if leftValue , leftOk := left .(float64 ); leftOk {
237
251
if rightValue , rightOk := right .(float64 ); rightOk {
238
252
return leftValue , rightValue
0 commit comments