eleetscript 0.0.2a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/eleet +89 -0
- data/lib/eleetscript.rb +18 -0
- data/lib/engine/eleet_engine.rb +58 -0
- data/lib/engine/eleet_to_ruby_wrapper.rb +25 -0
- data/lib/engine/ruby_to_eleet_wrapper.rb +22 -0
- data/lib/engine/values.rb +55 -0
- data/lib/lang/grammar.y +350 -0
- data/lib/lang/interpreter.rb +400 -0
- data/lib/lang/lexer.rb +92 -0
- data/lib/lang/nodes.rb +197 -0
- data/lib/lang/parser.output +11953 -0
- data/lib/lang/parser.rb +2300 -0
- data/lib/lang/runtime/array.rb +23 -0
- data/lib/lang/runtime/base_classes.rb +31 -0
- data/lib/lang/runtime/bootstrap.rb +3 -0
- data/lib/lang/runtime/class.rb +113 -0
- data/lib/lang/runtime/class_instance.rb +53 -0
- data/lib/lang/runtime/class_skeleton.rb +57 -0
- data/lib/lang/runtime/context.rb +263 -0
- data/lib/lang/runtime/eleetscript/enumerable.es +36 -0
- data/lib/lang/runtime/eleetscript/falseclass.es +25 -0
- data/lib/lang/runtime/eleetscript/integer.es +11 -0
- data/lib/lang/runtime/eleetscript/list.es +44 -0
- data/lib/lang/runtime/eleetscript/nilclass.es +5 -0
- data/lib/lang/runtime/eleetscript/number.es +13 -0
- data/lib/lang/runtime/eleetscript/object.es +49 -0
- data/lib/lang/runtime/eleetscript/pair.es +12 -0
- data/lib/lang/runtime/eleetscript/que.es +13 -0
- data/lib/lang/runtime/eleetscript/stack.es +14 -0
- data/lib/lang/runtime/eleetscript/string.es +34 -0
- data/lib/lang/runtime/eleetscript/trueclass.es +25 -0
- data/lib/lang/runtime/memory.rb +553 -0
- data/lib/lang/runtime/method.rb +32 -0
- data/lib/lang/runtime/method_hash.rb +40 -0
- data/lib/util/processed_key_hash.rb +34 -0
- metadata +79 -0
@@ -0,0 +1,400 @@
|
|
1
|
+
require "lang/parser"
|
2
|
+
require "lang/runtime/memory"
|
3
|
+
|
4
|
+
module EleetScript
|
5
|
+
class Interpreter
|
6
|
+
attr_reader :memory
|
7
|
+
def initialize(memory = nil)
|
8
|
+
@parser = Parser.new
|
9
|
+
@memory = memory || Memory.new
|
10
|
+
@memory.bootstrap(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
def eval(code, show_nodes = false)
|
14
|
+
nodes = @parser.parse(code)
|
15
|
+
puts nodes if show_nodes
|
16
|
+
nodes.eval(@memory.root_namespace)
|
17
|
+
end
|
18
|
+
|
19
|
+
def load(file_name)
|
20
|
+
if File.exists?(file_name)
|
21
|
+
eval(File.read(file_name))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Helpers
|
27
|
+
def self.throw_eleet_error(context, error)
|
28
|
+
context["Errors"].call("<", [context["String"].new_with_value(error)])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module Returnable
|
33
|
+
def returned
|
34
|
+
@returned = true
|
35
|
+
end
|
36
|
+
|
37
|
+
def returned?
|
38
|
+
@returned
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset_returned
|
42
|
+
@returned = false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module Nextable
|
47
|
+
def nexted
|
48
|
+
@nexted = true
|
49
|
+
end
|
50
|
+
|
51
|
+
def nexted?
|
52
|
+
@nexted
|
53
|
+
end
|
54
|
+
|
55
|
+
def reset_nexted
|
56
|
+
@nexted = false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module NodeMethods
|
61
|
+
def returnable?
|
62
|
+
self.class.included_modules.include?(Returnable)
|
63
|
+
end
|
64
|
+
|
65
|
+
def nextable?
|
66
|
+
self.class.included_modules.include?(Nextable)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Nodes
|
71
|
+
include Returnable
|
72
|
+
include Nextable
|
73
|
+
|
74
|
+
def eval(context)
|
75
|
+
return_value = nil
|
76
|
+
nodes.each do |node|
|
77
|
+
if node.kind_of?(ReturnNode)
|
78
|
+
returned
|
79
|
+
break return_value = node.eval(context)
|
80
|
+
elsif node.kind_of?(NextNode)
|
81
|
+
nexted
|
82
|
+
break
|
83
|
+
else
|
84
|
+
return_value = node.eval(context)
|
85
|
+
end
|
86
|
+
if node.returnable? && node.returned?
|
87
|
+
returned
|
88
|
+
node.reset_returned
|
89
|
+
break
|
90
|
+
elsif node.nextable? && node.nexted?
|
91
|
+
node.reset_nexted
|
92
|
+
nexted
|
93
|
+
break
|
94
|
+
end
|
95
|
+
end
|
96
|
+
return_value || context.es_nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class StringNode
|
101
|
+
INTERPOLATE_RX = /[\\]?%(?:@|@@|\$)?[\w]+?(?=\W|$)/
|
102
|
+
|
103
|
+
def eval(context)
|
104
|
+
context["String"].new_with_value(interpolate(context))
|
105
|
+
end
|
106
|
+
|
107
|
+
def interpolate(context)
|
108
|
+
new_val = value.dup
|
109
|
+
matches = value.scan(INTERPOLATE_RX)
|
110
|
+
matches.each do |match|
|
111
|
+
next if match.nil? || match == "%" || match == ""
|
112
|
+
if match.start_with?("\\")
|
113
|
+
next new_val.sub!(match, match[1..-1])
|
114
|
+
end
|
115
|
+
var = match[1..-1]
|
116
|
+
new_val.sub!(match, context[var].call(:to_string).ruby_value)
|
117
|
+
end
|
118
|
+
new_val
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class IntegerNode
|
123
|
+
def eval(context)
|
124
|
+
context["Integer"].new_with_value(value)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class FloatNode
|
129
|
+
def eval(context)
|
130
|
+
context["Float"].new_with_value(value)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class SetGlobalNode
|
135
|
+
def eval(context)
|
136
|
+
context[name] = value.eval(context)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class GetGlobalNode
|
141
|
+
def eval(context)
|
142
|
+
context[name]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class GetLocalNode
|
147
|
+
def eval(context)
|
148
|
+
val = context.local_var(name)
|
149
|
+
val != context.es_nil ? val : context.current_self.call(name, [])
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class SetLocalNode
|
154
|
+
def eval(context)
|
155
|
+
if Lexer::RESERVED_WORDS.include?(name)
|
156
|
+
context["Errors"].call("<", [context["String"].new_with_value("Cannot assign a value to reserved word \"name\"")])
|
157
|
+
else
|
158
|
+
context.local_var(name, value.eval(context))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class GetConstantNode
|
164
|
+
def eval(context)
|
165
|
+
context.constants[name] || context[name]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
class SetConstantNode
|
170
|
+
def eval(context)
|
171
|
+
if !context.constants.has_key?(name)
|
172
|
+
context[name] = value.eval(context)
|
173
|
+
else
|
174
|
+
Helpers.throw_eleet_error(context, "Cannot reassign constant \"#{name}\" after it's already been defined!")
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class SetInstanceVarNode
|
180
|
+
def eval(context)
|
181
|
+
context.instance_vars[name] = value.eval(context)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class GetInstanceVarNode
|
186
|
+
def eval(context)
|
187
|
+
context.current_self.instance_vars[name]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class SetClassVarNode
|
192
|
+
def eval(context)
|
193
|
+
context.current_class.class_vars[name] = value.eval(context)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class GetClassVarNode
|
198
|
+
def eval(context)
|
199
|
+
context.current_class.class_vars[name]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
class TrueNode
|
204
|
+
def eval(context)
|
205
|
+
context["true"]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class FalseNode
|
210
|
+
def eval(context)
|
211
|
+
context["false"]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
class NilNode
|
216
|
+
def eval(context)
|
217
|
+
context.es_nil
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
class ClassNode
|
222
|
+
def eval(context)
|
223
|
+
cls = context[name]
|
224
|
+
if cls == context.es_nil
|
225
|
+
cls = if parent
|
226
|
+
parent_cls = context[parent]
|
227
|
+
throw "Cannot extend undefined class \"#{parent}\"." if parent_cls == context.es_nil
|
228
|
+
EleetScriptClass.create(context, name, parent_cls)
|
229
|
+
else
|
230
|
+
EleetScriptClass.create(context, name)
|
231
|
+
end
|
232
|
+
context[name] = cls
|
233
|
+
end
|
234
|
+
|
235
|
+
body.eval(cls.context)
|
236
|
+
cls
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
class PropertyNode
|
241
|
+
def eval(context)
|
242
|
+
cls = context.current_class
|
243
|
+
properties.each do |prop_name|
|
244
|
+
cls.def "#{prop_name}=" do |receiver, arguments|
|
245
|
+
receiver.instance_vars[prop_name] = arguments.first
|
246
|
+
end
|
247
|
+
|
248
|
+
cls.def prop_name do |receiver, arguments|
|
249
|
+
receiver.instance_vars[prop_name]
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
class CallNode
|
256
|
+
def eval(context)
|
257
|
+
value = if receiver
|
258
|
+
receiver.eval(context)
|
259
|
+
else
|
260
|
+
context.current_self
|
261
|
+
end
|
262
|
+
evaled_args = arguments.map { |a| a.eval(context) }
|
263
|
+
evaled_args << lambda.eval(context) if lambda
|
264
|
+
value.call(method_name, evaled_args)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
class LambdaNode
|
269
|
+
def eval(context)
|
270
|
+
context["Lambda"].new_with_value(EleetScriptMethod.new(params, body, context))
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
class DefMethodNode
|
275
|
+
def eval(context)
|
276
|
+
method_obj = EleetScriptMethod.new(method.params, method.body)
|
277
|
+
context.current_class.methods[method_name] = method_obj
|
278
|
+
context.es_nil
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
class SelfNode
|
283
|
+
def eval(context)
|
284
|
+
context.current_self
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
class IfNode
|
289
|
+
include Returnable
|
290
|
+
include Nextable
|
291
|
+
|
292
|
+
def eval(context)
|
293
|
+
cond = condition.eval(context)
|
294
|
+
cond = (cond.class? ? cond : cond.ruby_value)
|
295
|
+
if cond
|
296
|
+
ret = body.eval(context)
|
297
|
+
if body.returnable? && body.returned?
|
298
|
+
body.reset_returned
|
299
|
+
returned
|
300
|
+
elsif body.nextable? && body.nexted?
|
301
|
+
body.reset_nexted
|
302
|
+
nexted
|
303
|
+
return context.es_nil
|
304
|
+
end
|
305
|
+
ret
|
306
|
+
else
|
307
|
+
unless else_node.nil?
|
308
|
+
ret = else_node.eval(context)
|
309
|
+
if else_node.returned?
|
310
|
+
else_node.reset_returned
|
311
|
+
returned
|
312
|
+
elsif else_node.nexted?
|
313
|
+
else_node.reset_nexted
|
314
|
+
nexted
|
315
|
+
return context.es_nil
|
316
|
+
end
|
317
|
+
ret
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
class ElseNode
|
324
|
+
include Returnable
|
325
|
+
include Nextable
|
326
|
+
|
327
|
+
def eval(context)
|
328
|
+
ret = body.eval(context)
|
329
|
+
if body.returnable? and body.returned?
|
330
|
+
body.reset_returned
|
331
|
+
returned
|
332
|
+
elsif body.nextable? && body.nexted?
|
333
|
+
body.reset_nexted
|
334
|
+
nexted
|
335
|
+
return context.es_nil
|
336
|
+
end
|
337
|
+
ret
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
class ReturnNode
|
342
|
+
def eval(context)
|
343
|
+
if expression
|
344
|
+
expression.eval(context)
|
345
|
+
else
|
346
|
+
context.es_nil
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
class WhileNode
|
352
|
+
include Returnable
|
353
|
+
|
354
|
+
def eval(context)
|
355
|
+
val = condition.eval(context)
|
356
|
+
ret = nil
|
357
|
+
while val.ruby_value
|
358
|
+
ret = body.eval(context)
|
359
|
+
if body.returnable? && body.returned?
|
360
|
+
body.reset_returned
|
361
|
+
returned
|
362
|
+
return ret
|
363
|
+
elsif body.nextable? && body.nexted?
|
364
|
+
body.reset_nexted
|
365
|
+
next
|
366
|
+
end
|
367
|
+
val = condition.eval(context)
|
368
|
+
end
|
369
|
+
ret || context.es_nil
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
class NamespaceNode
|
374
|
+
def eval(context)
|
375
|
+
ns_ctx = context.namespace(name)
|
376
|
+
if ns_ctx
|
377
|
+
body.eval(ns_ctx)
|
378
|
+
else
|
379
|
+
ns_ctx = context.new_namespace_context
|
380
|
+
context.add_namespace(name, ns_ctx)
|
381
|
+
body.eval(ns_ctx)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
class NamespaceAccessNode
|
387
|
+
def eval(context)
|
388
|
+
ns_ctx = if namespace.nil?
|
389
|
+
context.root_ns
|
390
|
+
else
|
391
|
+
context.namespace(namespace)
|
392
|
+
end
|
393
|
+
if ns_ctx
|
394
|
+
expression.eval(ns_ctx)
|
395
|
+
else
|
396
|
+
Helpers.throw_eleet_error(context, "Namespace \"#{namespace}\" does not exist.")
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
data/lib/lang/lexer.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "eleetscript"
|
2
|
+
|
3
|
+
module EleetScript
|
4
|
+
class Lexer
|
5
|
+
RESERVED_WORDS = [
|
6
|
+
"lambda?", "lambda", "self", "nil", "true", "yes", "on", "false", "no",
|
7
|
+
"off", "next", "break", "return"
|
8
|
+
]
|
9
|
+
|
10
|
+
KEYWORDS = [
|
11
|
+
"do", "end", "class", "load", "if", "while", "namespace", "else", "elsif",
|
12
|
+
"return", "break", "next", "true", "yes", "on", "false", "no", "off",
|
13
|
+
"nil", "self", "defined?", "property"
|
14
|
+
]
|
15
|
+
|
16
|
+
TOKEN_RX = {
|
17
|
+
identifiers: /\A([a-z_][\w\d]*[?!]?)/,
|
18
|
+
constants: /\A([A-Z][\w\d]*[?!]?)/,
|
19
|
+
globals: /\A(\$[a-z][\w\d]*[?!]?)/i,
|
20
|
+
class_var: /\A(\@\@[a-z][\w\d]*[!?]?)/i,
|
21
|
+
instance_var: /\A(\@[a-z][\w\d]*[!?]?)/i,
|
22
|
+
operator: /\A(->|=>|[.+\-\*\/%<>=!]=|\*\*=|\*\*|[+\-\*\/%=><]|or|and|not|isnt|is|\||\(|\)|\[|\]|\{|\}|::|[.,])/,
|
23
|
+
whitespace: /\A([ \t]+)/,
|
24
|
+
terminator: /\A([;\n])/,
|
25
|
+
integer: /\A([\d_]+)/,
|
26
|
+
float: /\A([\d_]*?\.[\d_]+)/,
|
27
|
+
string: /\A\"(.*?)(?<!\\)\"/m,
|
28
|
+
comment: /\A#.*?(?=\n|$)/m
|
29
|
+
}
|
30
|
+
|
31
|
+
def tokenize(code)
|
32
|
+
tokens = []
|
33
|
+
if code.length == 0
|
34
|
+
return tokens
|
35
|
+
end
|
36
|
+
line = 1
|
37
|
+
i = 0
|
38
|
+
while i < code.length
|
39
|
+
chunk = code[i..-1]
|
40
|
+
if operator = chunk[TOKEN_RX[:operator]]
|
41
|
+
tokens << [operator, operator]
|
42
|
+
i += operator.length
|
43
|
+
elsif constant = chunk[TOKEN_RX[:constants]]
|
44
|
+
tokens << [:CONSTANT, constant]
|
45
|
+
i += constant.length
|
46
|
+
elsif global = chunk[TOKEN_RX[:globals]]
|
47
|
+
tokens << [:GLOBAL, $1]
|
48
|
+
i += global.length
|
49
|
+
elsif class_var = chunk[TOKEN_RX[:class_var]]
|
50
|
+
tokens << [:CLASS_IDENTIFIER, $1]
|
51
|
+
i += class_var.length
|
52
|
+
elsif instance_var = chunk[TOKEN_RX[:instance_var]]
|
53
|
+
tokens << [:INSTANCE_IDENTIFIER, $1]
|
54
|
+
i += instance_var.length
|
55
|
+
elsif identifier = chunk[TOKEN_RX[:identifiers]]
|
56
|
+
if KEYWORDS.include? identifier
|
57
|
+
tokens << [identifier.upcase.gsub(/\?\!/, "").to_sym, identifier]
|
58
|
+
else
|
59
|
+
tokens << [:IDENTIFIER, identifier]
|
60
|
+
end
|
61
|
+
i += identifier.length
|
62
|
+
elsif float = chunk[TOKEN_RX[:float]]
|
63
|
+
tokens << [:FLOAT, float.to_f]
|
64
|
+
i += float.length
|
65
|
+
elsif integer = chunk[TOKEN_RX[:integer]]
|
66
|
+
tokens << [:NUMBER, integer.to_i]
|
67
|
+
i += integer.length
|
68
|
+
elsif string = chunk[TOKEN_RX[:string]]
|
69
|
+
tokens << [:STRING, $1.gsub('\"', '"')]
|
70
|
+
i += string.length
|
71
|
+
elsif comment = chunk[TOKEN_RX[:comment]]
|
72
|
+
i += comment.length # Ignore comments
|
73
|
+
elsif terminator = chunk[TOKEN_RX[:terminator]]
|
74
|
+
tokens << [:TERMINATOR, terminator]
|
75
|
+
if terminator == "\n"
|
76
|
+
line += 1
|
77
|
+
end
|
78
|
+
i += 1
|
79
|
+
elsif space = chunk[TOKEN_RX[:whitespace]]
|
80
|
+
i += space.length # ignore spaces and tab characters
|
81
|
+
else
|
82
|
+
raise LexicalError.new(code[i], line)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
if tokens.length > 0 && tokens.last != [:TERMINATOR, "\n"]
|
86
|
+
tokens << [:TERMINATOR, "\n"]
|
87
|
+
end
|
88
|
+
tokens << [:EOF, :eof] if tokens.length > 0
|
89
|
+
tokens
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/lang/nodes.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
require "eleetscript"
|
2
|
+
|
3
|
+
module EleetScript
|
4
|
+
module NodeMethods
|
5
|
+
def spaces(level)
|
6
|
+
" " * level
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s(level = 0)
|
10
|
+
"#{spaces(level)}<#{self.class.name}>\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
def is_node?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Node < Struct
|
19
|
+
include NodeMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
class NodeType
|
23
|
+
include NodeMethods
|
24
|
+
end
|
25
|
+
|
26
|
+
class Nodes < Node.new(:nodes)
|
27
|
+
def <<(node)
|
28
|
+
nodes << node
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s(level = 0)
|
33
|
+
str = "#{spaces(level)}<EleetScript::Nodes\n"
|
34
|
+
nodes.each do |node|
|
35
|
+
str += node.to_s(level + 1)
|
36
|
+
end
|
37
|
+
str + "#{spaces(level)}>\n"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class LiteralNode < Node.new(:value)
|
42
|
+
def to_s(level = 0)
|
43
|
+
"#{spaces(level)}<#{self.class.name} #{value}>\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class IntegerNode < LiteralNode; end
|
48
|
+
class FloatNode < LiteralNode; end
|
49
|
+
class StringNode < LiteralNode; end
|
50
|
+
|
51
|
+
class TrueNode < LiteralNode
|
52
|
+
def value
|
53
|
+
true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class FalseNode < LiteralNode
|
58
|
+
def value
|
59
|
+
false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class NilNode < LiteralNode
|
64
|
+
def value
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class CallNode < Node.new(:receiver, :method_name, :arguments, :lambda)
|
70
|
+
def to_s(level = 0)
|
71
|
+
tabs = spaces(level)
|
72
|
+
str = "#{tabs}<EleetScript::CallNode\n"
|
73
|
+
if receiver.nil?
|
74
|
+
str += "#{tabs} @receiver=nil\n"
|
75
|
+
else
|
76
|
+
str += "#{tabs} @receiver=#{receiver.to_s[0..-2]}\n"
|
77
|
+
end
|
78
|
+
str += "#{tabs} @method_name=#{method_name}\n"
|
79
|
+
if arguments.empty?
|
80
|
+
str += "#{tabs} @arguemtns=empty\n"
|
81
|
+
else
|
82
|
+
str += "#{tabs} @arguments=(\n"
|
83
|
+
arguments.each do |arg|
|
84
|
+
str += arg.to_s(level + 2)
|
85
|
+
end
|
86
|
+
str += "#{tabs} )\n"
|
87
|
+
end
|
88
|
+
if lambda.nil?
|
89
|
+
str + "#{tabs} @lambda=nil\n>\n"
|
90
|
+
else
|
91
|
+
str += "#{tabs} @lambda=(\n"
|
92
|
+
str += lambda.to_s(level + 2)
|
93
|
+
end
|
94
|
+
str + "#{tabs}>\n"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class SetVarNode < Node.new(:name, :value)
|
99
|
+
def to_s(level = 0)
|
100
|
+
tabs = spaces(level)
|
101
|
+
str = "#{tabs}<#{self.class.name}\n"
|
102
|
+
str += "#{tabs} @name=#{name}\n"
|
103
|
+
str += "#{tabs} @value=(\n"
|
104
|
+
str += value.to_s(level + 2)
|
105
|
+
str += "#{tabs}>\n"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class GetVarNode < Node.new(:name)
|
110
|
+
def to_s(level = 0)
|
111
|
+
str = "<#{self.class.name} \"#{name}\">\n"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class SetConstantNode < SetVarNode; end
|
116
|
+
class GetConstantNode < GetVarNode; end
|
117
|
+
class SetGlobalNode < SetVarNode; end
|
118
|
+
class GetGlobalNode < GetVarNode; end
|
119
|
+
class SetClassVarNode < SetVarNode; end
|
120
|
+
class GetClassVarNode < GetVarNode; end
|
121
|
+
class SetInstanceVarNode < SetVarNode; end
|
122
|
+
class GetInstanceVarNode < GetVarNode; end
|
123
|
+
class SetLocalNode < SetVarNode; end
|
124
|
+
class GetLocalNode < GetVarNode; end
|
125
|
+
|
126
|
+
class DefMethodNode < Node.new(:method_name, :method)
|
127
|
+
def to_s(level = 0)
|
128
|
+
tabs = spaces(level)
|
129
|
+
str = "#{tabs}<EleetScript::DefMethodNode \"#{method_name}\"\n"
|
130
|
+
str += "#{tabs} @method=(\n"
|
131
|
+
str += method.to_s(level + 2)
|
132
|
+
str + "#{tabs} )\n#{tabs}>\n"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class LambdaNode < Node.new(:params, :body)
|
137
|
+
def to_s(level = 0)
|
138
|
+
tabs = spaces(level)
|
139
|
+
str = "#{tabs}<EleetScript::LambdaNode\n"
|
140
|
+
str += "#{tabs} @params=#{params.inspect}\n"
|
141
|
+
if body.nodes.length > 0
|
142
|
+
str += "#{tabs} @body=(\n"
|
143
|
+
str += body.to_s(level + 2)
|
144
|
+
str += "#{tabs} )\n#{tabs}>\n"
|
145
|
+
else
|
146
|
+
str += "#{tabs} @body=nil\n#{tabs}>\n"
|
147
|
+
end
|
148
|
+
str
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class MethodNode < Node.new(:params, :body)
|
153
|
+
def to_s(level = 0)
|
154
|
+
tabs = spaces(level)
|
155
|
+
str = "#{tabs}<EleetScript::MethodNode\n"
|
156
|
+
str += "#{tabs} @params=#{params.inspect}\n"
|
157
|
+
if body.nodes.length > 0
|
158
|
+
str += "#{tabs} @body=(\n"
|
159
|
+
str += body.to_s(level + 2)
|
160
|
+
str += "#{tabs} )\n#{tabs}>\n"
|
161
|
+
else
|
162
|
+
str += "#{tabs} @body=nil\n#{tabs}>\n"
|
163
|
+
end
|
164
|
+
str
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
class IfNode < Node.new(:condition, :body, :else_node); end
|
169
|
+
class ElseNode < Node.new(:body); end
|
170
|
+
class NotNode < Node.new(:value); end
|
171
|
+
class WhileNode < Node.new(:condition, :body); end
|
172
|
+
class SelfNode < NodeType; end
|
173
|
+
class DefinedNode < Node.new(:value); end
|
174
|
+
class NamespaceNode < Node.new(:name, :body); end
|
175
|
+
class NamespaceAccessNode < Node.new(:namespace, :expression); end
|
176
|
+
|
177
|
+
class ClassNode < Node.new(:name, :parent, :body)
|
178
|
+
def to_s(level = 0)
|
179
|
+
tabs = spaces(level)
|
180
|
+
str = "#{tabs}<EleetScript::ClassNode \"#{name}\"\n"
|
181
|
+
str += "#{tabs} @extends=\"#{parent || "Object"}\"\n"
|
182
|
+
str += "#{tabs} @body=(\n"
|
183
|
+
str += body.to_s(level + 2)
|
184
|
+
str + "#{tabs} )\n#{tabs}>\n"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class ReturnNode < Node.new(:expression); end
|
189
|
+
class PropertyNode < Node.new(:properties); end
|
190
|
+
|
191
|
+
class NextNode < NodeType
|
192
|
+
def eval(context, memory); end
|
193
|
+
def ==(o)
|
194
|
+
o.kind_of?(NextNode)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|