-
Notifications
You must be signed in to change notification settings - Fork 1
/
interpreter.rb
135 lines (109 loc) · 2.55 KB
/
interpreter.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
require_relative "parser"
require_relative "runtime"
class Interpreter
def initialize(debug=false)
@parser = BlangParser.new
@debug = debug
end
def eval(code)
results = @parser.parse(code,@debug)
if @debug
print results
end
results.eval(RootContext)
end
end
class Nodes
def eval(context)
return_value = nil
nodes.each do |node|
return_value = node.eval(context)
end
return_value || Boot["nil"]
end
end
class NumberNode
def eval(context)
Boot["Number"].new_with_value(value)
end
end
class StringNode
def eval(context)
Boot["String"].new_with_value(value)
end
end
class TrueNode
def eval(context)
Boot["true"]
end
end
class FalseNode
def eval(context)
Boot["false"]
end
end
class NilNode
def eval(context)
Boot["nil"]
end
end
class GetLocalNode
def eval(context)
context.locals[name]
end
end
class SetLocalNode
def eval(context)
context.locals[name] = value.eval(context)
end
end
class DefNode
def eval(context)
method = BaseMethod.new(params, body)
context.current_class.runtime_methods[name.to_s] = method
end
end
class CallNode
def eval(context)
puts context.to_s
puts method.to_s
puts arguments
if receiver
value = receiver.eval(context)
else
value = context.current_self # Default to `self` if no receiver.
end
evaluated_arguments = arguments.map { |arg| arg.eval(context) }
# p context.current_self.runtime_class
value.call(method.to_s, evaluated_arguments)
end
end
class ClassNode
def eval(context)
new_class = Boot[name]
unless new_class
new_class = Boot["Class"]
Boot[name] = new_class
end
class_context = Context.new(new_class,new_class)
body.eval(class_context)
new_class
end
end
class IfNode
def eval(context)
if condition.eval(context).ruby_value
body.eval(context)
else # If no body is evaluated, we return nil.
Constants["nil"]
end
end
end
class WhileNode
def eval(context)
while condition.eval(context).ruby_value
body.eval(context)
end
Constants["nil"]
end
end