Skip to content

Commit 80d674c

Browse files
committed
extract expression evaluation from execution definitions
1 parent 86a4e65 commit 80d674c

2 files changed

Lines changed: 138 additions & 137 deletions

File tree

vibes/execution.go

Lines changed: 0 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -73,140 +73,3 @@ type callFrame struct {
7373
Function string
7474
Pos Position
7575
}
76-
77-
func (exec *Execution) evalExpression(expr Expression, env *Env) (Value, error) {
78-
return exec.evalExpressionWithAuto(expr, env, true)
79-
}
80-
81-
func (exec *Execution) evalExpressionWithAuto(expr Expression, env *Env, autoCall bool) (Value, error) {
82-
if err := exec.step(); err != nil {
83-
return NewNil(), err
84-
}
85-
switch e := expr.(type) {
86-
case *Identifier:
87-
val, ok := env.Get(e.Name)
88-
if !ok {
89-
// allow implicit self method lookup
90-
if self, hasSelf := env.Get("self"); hasSelf && (self.Kind() == KindInstance || self.Kind() == KindClass) {
91-
member, err := exec.getMember(self, e.Name, e.Pos())
92-
if err != nil {
93-
return NewNil(), err
94-
}
95-
if autoCall {
96-
return exec.autoInvokeIfNeeded(e, member, self)
97-
}
98-
return member, nil
99-
}
100-
return NewNil(), exec.errorAt(e.Pos(), "undefined variable %s", e.Name)
101-
}
102-
if autoCall {
103-
return exec.autoInvokeIfNeeded(e, val, NewNil())
104-
}
105-
return val, nil
106-
case *IntegerLiteral:
107-
return NewInt(e.Value), nil
108-
case *FloatLiteral:
109-
return NewFloat(e.Value), nil
110-
case *StringLiteral:
111-
return NewString(e.Value), nil
112-
case *BoolLiteral:
113-
return NewBool(e.Value), nil
114-
case *NilLiteral:
115-
return NewNil(), nil
116-
case *SymbolLiteral:
117-
return NewSymbol(e.Name), nil
118-
case *ArrayLiteral:
119-
elems := make([]Value, len(e.Elements))
120-
for i, el := range e.Elements {
121-
val, err := exec.evalExpressionWithAuto(el, env, true)
122-
if err != nil {
123-
return NewNil(), err
124-
}
125-
elems[i] = val
126-
}
127-
return NewArray(elems), nil
128-
case *HashLiteral:
129-
entries := make(map[string]Value, len(e.Pairs))
130-
for _, pair := range e.Pairs {
131-
keyVal, err := exec.evalExpressionWithAuto(pair.Key, env, true)
132-
if err != nil {
133-
return NewNil(), err
134-
}
135-
key, err := valueToHashKey(keyVal)
136-
if err != nil {
137-
return NewNil(), exec.errorAt(pair.Key.Pos(), "%s", err.Error())
138-
}
139-
val, err := exec.evalExpressionWithAuto(pair.Value, env, true)
140-
if err != nil {
141-
return NewNil(), err
142-
}
143-
entries[key] = val
144-
}
145-
return NewHash(entries), nil
146-
case *UnaryExpr:
147-
return exec.evalUnaryExpr(e, env)
148-
case *BinaryExpr:
149-
return exec.evalBinaryExpr(e, env)
150-
case *RangeExpr:
151-
return exec.evalRangeExpr(e, env)
152-
case *CaseExpr:
153-
return exec.evalCaseExpr(e, env)
154-
case *MemberExpr:
155-
obj, err := exec.evalExpressionWithAuto(e.Object, env, true)
156-
if err != nil {
157-
return NewNil(), err
158-
}
159-
if err := exec.checkMemoryWith(obj); err != nil {
160-
return NewNil(), err
161-
}
162-
member, err := exec.getMember(obj, e.Property, e.Pos())
163-
if err != nil {
164-
return NewNil(), err
165-
}
166-
if autoCall {
167-
return exec.autoInvokeIfNeeded(e, member, obj)
168-
}
169-
return member, nil
170-
case *IndexExpr:
171-
return exec.evalIndexExpr(e, env)
172-
case *IvarExpr:
173-
self, ok := env.Get("self")
174-
if !ok || self.Kind() != KindInstance {
175-
return NewNil(), exec.errorAt(e.Pos(), "no instance context for ivar")
176-
}
177-
val, ok := self.Instance().Ivars[e.Name]
178-
if !ok {
179-
return NewNil(), nil
180-
}
181-
return val, nil
182-
case *ClassVarExpr:
183-
self, ok := env.Get("self")
184-
if !ok {
185-
return NewNil(), exec.errorAt(e.Pos(), "no class context")
186-
}
187-
switch self.Kind() {
188-
case KindInstance:
189-
val, ok := self.Instance().Class.ClassVars[e.Name]
190-
if !ok {
191-
return NewNil(), nil
192-
}
193-
return val, nil
194-
case KindClass:
195-
val, ok := self.Class().ClassVars[e.Name]
196-
if !ok {
197-
return NewNil(), nil
198-
}
199-
return val, nil
200-
default:
201-
return NewNil(), exec.errorAt(e.Pos(), "no class context")
202-
}
203-
case *CallExpr:
204-
return exec.evalCallExpr(e, env)
205-
case *BlockLiteral:
206-
return exec.evalBlockLiteral(e, env)
207-
case *YieldExpr:
208-
return exec.evalYield(e, env)
209-
default:
210-
return NewNil(), exec.errorAt(expr.Pos(), "unsupported expression")
211-
}
212-
}

vibes/execution_expressions.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package vibes
2+
3+
func (exec *Execution) evalExpression(expr Expression, env *Env) (Value, error) {
4+
return exec.evalExpressionWithAuto(expr, env, true)
5+
}
6+
7+
func (exec *Execution) evalExpressionWithAuto(expr Expression, env *Env, autoCall bool) (Value, error) {
8+
if err := exec.step(); err != nil {
9+
return NewNil(), err
10+
}
11+
switch e := expr.(type) {
12+
case *Identifier:
13+
val, ok := env.Get(e.Name)
14+
if !ok {
15+
// allow implicit self method lookup
16+
if self, hasSelf := env.Get("self"); hasSelf && (self.Kind() == KindInstance || self.Kind() == KindClass) {
17+
member, err := exec.getMember(self, e.Name, e.Pos())
18+
if err != nil {
19+
return NewNil(), err
20+
}
21+
if autoCall {
22+
return exec.autoInvokeIfNeeded(e, member, self)
23+
}
24+
return member, nil
25+
}
26+
return NewNil(), exec.errorAt(e.Pos(), "undefined variable %s", e.Name)
27+
}
28+
if autoCall {
29+
return exec.autoInvokeIfNeeded(e, val, NewNil())
30+
}
31+
return val, nil
32+
case *IntegerLiteral:
33+
return NewInt(e.Value), nil
34+
case *FloatLiteral:
35+
return NewFloat(e.Value), nil
36+
case *StringLiteral:
37+
return NewString(e.Value), nil
38+
case *BoolLiteral:
39+
return NewBool(e.Value), nil
40+
case *NilLiteral:
41+
return NewNil(), nil
42+
case *SymbolLiteral:
43+
return NewSymbol(e.Name), nil
44+
case *ArrayLiteral:
45+
elems := make([]Value, len(e.Elements))
46+
for i, el := range e.Elements {
47+
val, err := exec.evalExpressionWithAuto(el, env, true)
48+
if err != nil {
49+
return NewNil(), err
50+
}
51+
elems[i] = val
52+
}
53+
return NewArray(elems), nil
54+
case *HashLiteral:
55+
entries := make(map[string]Value, len(e.Pairs))
56+
for _, pair := range e.Pairs {
57+
keyVal, err := exec.evalExpressionWithAuto(pair.Key, env, true)
58+
if err != nil {
59+
return NewNil(), err
60+
}
61+
key, err := valueToHashKey(keyVal)
62+
if err != nil {
63+
return NewNil(), exec.errorAt(pair.Key.Pos(), "%s", err.Error())
64+
}
65+
val, err := exec.evalExpressionWithAuto(pair.Value, env, true)
66+
if err != nil {
67+
return NewNil(), err
68+
}
69+
entries[key] = val
70+
}
71+
return NewHash(entries), nil
72+
case *UnaryExpr:
73+
return exec.evalUnaryExpr(e, env)
74+
case *BinaryExpr:
75+
return exec.evalBinaryExpr(e, env)
76+
case *RangeExpr:
77+
return exec.evalRangeExpr(e, env)
78+
case *CaseExpr:
79+
return exec.evalCaseExpr(e, env)
80+
case *MemberExpr:
81+
obj, err := exec.evalExpressionWithAuto(e.Object, env, true)
82+
if err != nil {
83+
return NewNil(), err
84+
}
85+
if err := exec.checkMemoryWith(obj); err != nil {
86+
return NewNil(), err
87+
}
88+
member, err := exec.getMember(obj, e.Property, e.Pos())
89+
if err != nil {
90+
return NewNil(), err
91+
}
92+
if autoCall {
93+
return exec.autoInvokeIfNeeded(e, member, obj)
94+
}
95+
return member, nil
96+
case *IndexExpr:
97+
return exec.evalIndexExpr(e, env)
98+
case *IvarExpr:
99+
self, ok := env.Get("self")
100+
if !ok || self.Kind() != KindInstance {
101+
return NewNil(), exec.errorAt(e.Pos(), "no instance context for ivar")
102+
}
103+
val, ok := self.Instance().Ivars[e.Name]
104+
if !ok {
105+
return NewNil(), nil
106+
}
107+
return val, nil
108+
case *ClassVarExpr:
109+
self, ok := env.Get("self")
110+
if !ok {
111+
return NewNil(), exec.errorAt(e.Pos(), "no class context")
112+
}
113+
switch self.Kind() {
114+
case KindInstance:
115+
val, ok := self.Instance().Class.ClassVars[e.Name]
116+
if !ok {
117+
return NewNil(), nil
118+
}
119+
return val, nil
120+
case KindClass:
121+
val, ok := self.Class().ClassVars[e.Name]
122+
if !ok {
123+
return NewNil(), nil
124+
}
125+
return val, nil
126+
default:
127+
return NewNil(), exec.errorAt(e.Pos(), "no class context")
128+
}
129+
case *CallExpr:
130+
return exec.evalCallExpr(e, env)
131+
case *BlockLiteral:
132+
return exec.evalBlockLiteral(e, env)
133+
case *YieldExpr:
134+
return exec.evalYield(e, env)
135+
default:
136+
return NewNil(), exec.errorAt(expr.Pos(), "unsupported expression")
137+
}
138+
}

0 commit comments

Comments
 (0)