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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/bin/eleet +89 -0
  3. data/lib/eleetscript.rb +18 -0
  4. data/lib/engine/eleet_engine.rb +58 -0
  5. data/lib/engine/eleet_to_ruby_wrapper.rb +25 -0
  6. data/lib/engine/ruby_to_eleet_wrapper.rb +22 -0
  7. data/lib/engine/values.rb +55 -0
  8. data/lib/lang/grammar.y +350 -0
  9. data/lib/lang/interpreter.rb +400 -0
  10. data/lib/lang/lexer.rb +92 -0
  11. data/lib/lang/nodes.rb +197 -0
  12. data/lib/lang/parser.output +11953 -0
  13. data/lib/lang/parser.rb +2300 -0
  14. data/lib/lang/runtime/array.rb +23 -0
  15. data/lib/lang/runtime/base_classes.rb +31 -0
  16. data/lib/lang/runtime/bootstrap.rb +3 -0
  17. data/lib/lang/runtime/class.rb +113 -0
  18. data/lib/lang/runtime/class_instance.rb +53 -0
  19. data/lib/lang/runtime/class_skeleton.rb +57 -0
  20. data/lib/lang/runtime/context.rb +263 -0
  21. data/lib/lang/runtime/eleetscript/enumerable.es +36 -0
  22. data/lib/lang/runtime/eleetscript/falseclass.es +25 -0
  23. data/lib/lang/runtime/eleetscript/integer.es +11 -0
  24. data/lib/lang/runtime/eleetscript/list.es +44 -0
  25. data/lib/lang/runtime/eleetscript/nilclass.es +5 -0
  26. data/lib/lang/runtime/eleetscript/number.es +13 -0
  27. data/lib/lang/runtime/eleetscript/object.es +49 -0
  28. data/lib/lang/runtime/eleetscript/pair.es +12 -0
  29. data/lib/lang/runtime/eleetscript/que.es +13 -0
  30. data/lib/lang/runtime/eleetscript/stack.es +14 -0
  31. data/lib/lang/runtime/eleetscript/string.es +34 -0
  32. data/lib/lang/runtime/eleetscript/trueclass.es +25 -0
  33. data/lib/lang/runtime/memory.rb +553 -0
  34. data/lib/lang/runtime/method.rb +32 -0
  35. data/lib/lang/runtime/method_hash.rb +40 -0
  36. data/lib/util/processed_key_hash.rb +34 -0
  37. metadata +79 -0
@@ -0,0 +1,49 @@
1
+ class Object
2
+ @@kind_of? do
3
+ no
4
+ end
5
+
6
+ @@no_method do
7
+ cls_name = class_name
8
+ Errors < "Undefined method \"%name\" called on %cls_name."
9
+ nil
10
+ end
11
+
12
+ @@inspect do
13
+ class_name
14
+ end
15
+
16
+ @@println do |msg|
17
+ IO.println(msg)
18
+ end
19
+
20
+ @@print do |msg|
21
+ IO.print(msg)
22
+ end
23
+
24
+ to_string do
25
+ class_name
26
+ end
27
+
28
+ println do |msg|
29
+ IO.println(msg)
30
+ end
31
+
32
+ print do |msg|
33
+ IO.print(msg)
34
+ end
35
+
36
+ inspect do
37
+ to_string
38
+ end
39
+
40
+ no_method do |name|
41
+ cls_name = class_name
42
+ Errors < "Undefined method \"%name\" called on instance of %cls_name."
43
+ nil
44
+ end
45
+
46
+ not do
47
+ self
48
+ end
49
+ end
@@ -0,0 +1,12 @@
1
+ class Pair
2
+ property key value
3
+ init do |@key, @value| end
4
+
5
+ clone do
6
+ Pair.new(@key.clone, @value.clone)
7
+ end
8
+
9
+ to_string do
10
+ "<Pair " + @key.inspect + " => " + @value.inspect + ">"
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ class Que < List
2
+ front do
3
+ first
4
+ end
5
+
6
+ back do
7
+ last
8
+ end
9
+
10
+ pop do
11
+ shift
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ class Stack < List
2
+ top do
3
+ last
4
+ end
5
+
6
+ shift do |val|
7
+ pop
8
+ nil
9
+ end
10
+
11
+ unshift do |val|
12
+ push(val)
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ class String
2
+ * do |num|
3
+ if arguments.length > 0
4
+ new_str = []
5
+ str = self
6
+ num.times -> {
7
+ new_str < str
8
+ }
9
+ new_str.join("")
10
+ else
11
+ ""
12
+ end
13
+ end
14
+
15
+ reverse do
16
+ rev = []
17
+ each -> { |v|
18
+ rev.unshift(v)
19
+ }
20
+ rev.join("")
21
+ end
22
+
23
+ isnt do |value|
24
+ not self is value
25
+ end
26
+
27
+ to_string do
28
+ self
29
+ end
30
+
31
+ inspect do
32
+ "\"" + self + "\""
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ class TrueClass
2
+ to_string do
3
+ "true"
4
+ end
5
+
6
+ not do
7
+ false
8
+ end
9
+
10
+ and do |o|
11
+ if o is true
12
+ o
13
+ else
14
+ false
15
+ end
16
+ end
17
+
18
+ or do
19
+ true
20
+ end
21
+
22
+ to_string do
23
+ "true"
24
+ end
25
+ end
@@ -0,0 +1,553 @@
1
+ require "lang/runtime/class"
2
+ require "lang/runtime/context"
3
+ require "lang/runtime/method"
4
+ require "lang/runtime/array"
5
+ require "lang/runtime/base_classes"
6
+
7
+ module EleetScript
8
+ class Memory
9
+ attr_reader :root, :root_context, :root_namespace
10
+
11
+ ROOT_OBJECTS = {
12
+ "Object" => nil,
13
+ "Number" => nil,
14
+ "Integer" => "Number",
15
+ "Float" => "Number",
16
+ "Enumerable" => nil,
17
+ "List" => "Enumerable",
18
+ "String" => "Enumerable",
19
+ "IO" => nil,
20
+ "Lambda" => nil,
21
+ "TrueClass" => nil,
22
+ "FalseClass" => nil,
23
+ "NilClass" => nil
24
+ }
25
+
26
+ def initialize
27
+ @root_namespace = NamespaceContext.new(nil, nil)
28
+ @root_path = File.join(File.dirname(__FILE__), "eleetscript")
29
+ end
30
+
31
+ def bootstrap(loader)
32
+ return if @bootstrapped
33
+ @bootstrapped = true
34
+
35
+ ROOT_OBJECTS.each do |obj_name, parent_class|
36
+ if parent_class.nil?
37
+ @root_namespace[obj_name] = EleetScriptClass.create(@root_namespace, obj_name)
38
+ else
39
+ @root_namespace[obj_name] = EleetScriptClass.create(@root_namespace, obj_name, @root_namespace[parent_class])
40
+ end
41
+ end
42
+
43
+ @root = @root_namespace["Object"].new
44
+ @root_namespace.current_self = @root
45
+ @root_namespace.current_class = @root.runtime_class
46
+
47
+ @root_namespace["true"] = @root_namespace["TrueClass"].new_with_value(true)
48
+ @root_namespace["false"] = @root_namespace["FalseClass"].new_with_value(false)
49
+ @root_namespace["nil"] = @root_namespace["NilClass"].new_with_value(nil)
50
+
51
+ # Global Errors Object
52
+ @root_namespace["Errors"] = @root_namespace["List"].new_with_value(ListBase.new(@root_namespace.es_nil))
53
+
54
+ load_object_methods
55
+ load_io_methods
56
+ load_string_methods
57
+ load_number_methods
58
+ load_boolean_methods
59
+ load_nil_methods
60
+ load_list_methods
61
+ load_lambda_methods
62
+
63
+ files = Dir.glob(File.join(@root_path, "**", "*.es"))
64
+ files.each do |file|
65
+ loader.load(file)
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ def load_object_methods
72
+ object = @root_namespace["Object"]
73
+
74
+ object.class_def :new do |receiver, arguments|
75
+ ins = receiver.new
76
+ ins.call("init", arguments)
77
+ ins
78
+ end
79
+
80
+ object.def :kind_of? do |receiver, arguments|
81
+ t = @root_namespace["true"]
82
+ f = @root_namespace["false"]
83
+ if arguments.length == 0 || !arguments.first.class?
84
+ f
85
+ else
86
+ names = []
87
+ names << receiver.runtime_class.name
88
+ cur_class = receiver.runtime_class
89
+ while @root_namespace["Object"] != cur_class.super_class
90
+ names << cur_class.super_class.name
91
+ cur_class = cur_class.super_class
92
+ end
93
+ names << "Object" # Base of everything
94
+ name = arguments.first.name
95
+ names.include?(name) ? t : f
96
+ end
97
+ end
98
+
99
+ object.def :class_name do |receiver, arguments|
100
+ @root_namespace["String"].new_with_value(receiver.runtime_class.name)
101
+ end
102
+
103
+ object.class_def :class_name do |receiver, arguments|
104
+ @root_namespace["String"].new_with_value(receiver.name)
105
+ end
106
+
107
+ object.def :is do |receiver, arguments|
108
+ if receiver == arguments.first
109
+ @root_namespace["true"]
110
+ else
111
+ @root_namespace["false"]
112
+ end
113
+ end
114
+
115
+ object.def :clone do |receiver, arguments|
116
+ cls_name = receiver.runtime_class.name
117
+ if ["Integer", "Float", "String", "List"].include?(cls_name)
118
+ receiver.runtime_class.new_with_value(receiver.ruby_value.dup)
119
+ else
120
+ ins = receiver.runtime_class.call(:new)
121
+ ins.ruby_value = receiver.ruby_value.dup
122
+ end
123
+ end
124
+ end
125
+
126
+ def load_io_methods
127
+ io = @root_namespace["IO"]
128
+
129
+ io.class_def :print do |receiver, arguments|
130
+ print arguments.first.call(:to_string).ruby_value
131
+ @root_namespace.es_nil
132
+ end
133
+
134
+ io.class_def :println do |receiver, arguments|
135
+ puts arguments.first.call(:to_string).ruby_value
136
+ @root_namespace.es_nil
137
+ end
138
+
139
+ io.class_def :new do |receiver, arguments|
140
+ io
141
+ end
142
+ end
143
+
144
+ def load_string_methods
145
+ string = @root_namespace["String"]
146
+
147
+ string.def :+ do |receiver, arguments|
148
+ arg = arguments.first
149
+ arg_str = if arg.class?
150
+ arg.name
151
+ elsif arg.instance? && arg.runtime_class.name == "String"
152
+ arg.ruby_value
153
+ else
154
+ arg.call(:to_string).ruby_value
155
+ end
156
+ receiver.ruby_value += arg_str
157
+ receiver
158
+ end
159
+
160
+ string.def :is do |receiver, arguments|
161
+ compare_to = arguments.first.ruby_value
162
+ if compare_to == receiver.ruby_value
163
+ @root_namespace["true"]
164
+ else
165
+ @root_namespace["false"]
166
+ end
167
+ end
168
+
169
+ string.def :substr do |receiver, arguments|
170
+ if arguments.length < 2
171
+ @root_namespace["nil"]
172
+ else
173
+ s, e = arguments
174
+ if s.is_a?("Integer") && e.is_a?("Integer")
175
+ range = if e.ruby_value < 0
176
+ (s.ruby_value..e.ruby_value)
177
+ else
178
+ (s.ruby_value...e.ruby_value)
179
+ end
180
+ @root_namespace["String"].new_with_value(receiver.ruby_value[range])
181
+ else
182
+ @root_namespace["nil"]
183
+ end
184
+ end
185
+ end
186
+
187
+ string.def :length do |receiver, arguments|
188
+ @root_namespace["Integer"].new_with_value(receiver.ruby_value.length)
189
+ end
190
+
191
+ string.def :upper_case do |receiver, arguments|
192
+ string.new_with_value(receiver.ruby_value.upcase)
193
+ end
194
+
195
+ string.def :lower_case do |receiver, arguments|
196
+ string.new_with_value(receiver.ruby_value.downcase)
197
+ end
198
+
199
+ string.def :[] do |receiver, arguments|
200
+ index = arguments.first
201
+ if index.is_a?("Integer")
202
+ index = index.ruby_value
203
+ if index < 0 || index >= receiver.ruby_value.length
204
+ @root_namespace.es_nil
205
+ else
206
+ string.new_with_value(receiver.ruby_value[index])
207
+ end
208
+ else
209
+ @root_namespace.es_nil
210
+ end
211
+ end
212
+
213
+ string.def :[]= do |receiver, arguments|
214
+ index, value = arguments
215
+ if index.is_a?("Integer")
216
+ index = index.ruby_value
217
+ if index < 0 && index >= receiver.ruby_value.length
218
+ @root_namespace.es_nil
219
+ else
220
+ value_str = value.call(:to_string)
221
+ receiver.ruby_value[index] = value_str.ruby_value
222
+ receiver
223
+ end
224
+ else
225
+ @root_namespace.es_nil
226
+ end
227
+ end
228
+ end
229
+
230
+ def load_number_methods
231
+ number = @root_namespace["Number"]
232
+ int = @root_namespace["Integer"]
233
+ float = @root_namespace["Float"]
234
+
235
+ number.def :+ do |receiver, arguments|
236
+ arg = arguments.first
237
+ if arg.is_a?("Number")
238
+ val = receiver.ruby_value + arg.ruby_value
239
+ if val.kind_of?(Fixnum)
240
+ int.new_with_value(val)
241
+ else
242
+ float.new_with_value(val)
243
+ end
244
+ elsif arg.is_a?("String")
245
+ str = receiver.ruby_value.to_s + arg.ruby_value
246
+ @root_namespace["String"].new_with_value(str)
247
+ else
248
+ receiver
249
+ end
250
+ end
251
+
252
+ number.def :- do |receiver, arguments|
253
+ arg = arguments.first
254
+ if arg.is_a?("Number")
255
+ val = receiver.ruby_value - arg.ruby_value
256
+ if val.kind_of?(Fixnum)
257
+ int.new_with_value(val)
258
+ else
259
+ float.new_with_value(float)
260
+ end
261
+ else
262
+ receiver
263
+ end
264
+ end
265
+
266
+ number.def :* do |receiver, arguments|
267
+ arg = arguments.first
268
+ if arg.is_a?("Number")
269
+ val = receiver.ruby_value * arg.ruby_value
270
+ if val.kind_of?(Fixnum)
271
+ int.new_with_value(val)
272
+ else
273
+ float.new_with_value(float)
274
+ end
275
+ else
276
+ receiver
277
+ end
278
+ end
279
+
280
+ number.def :/ do |receiver, arguments|
281
+ arg = arguments.first
282
+ if arg.is_a?("Number")
283
+ if arg.ruby_value == 0
284
+ int.new_with_value(0)
285
+ else
286
+ val = receiver.ruby_value / arg.ruby_value
287
+ if val.kind_of?(Fixnum)
288
+ int.new_with_value(val)
289
+ else
290
+ float.new_with_value(float)
291
+ end
292
+ end
293
+ else
294
+ receiver
295
+ end
296
+ end
297
+
298
+ number.def :% do |receiver, arguments|
299
+ arg = arguments.first
300
+ if arg.is_a?("Number")
301
+ if arg.ruby_value == 0
302
+ int.new_with_value(0)
303
+ else
304
+ val = receiver.ruby_value % arg.ruby_value
305
+ if val.kind_of?(Fixnum)
306
+ int.new_with_value(val)
307
+ else
308
+ float.new_with_value(float)
309
+ end
310
+ end
311
+ else
312
+ receiver
313
+ end
314
+ end
315
+
316
+ number.def :< do |receiver, arguments|
317
+ arg = arguments.first
318
+ if arg.is_a?("Number")
319
+ if receiver.ruby_value < arg.ruby_value
320
+ @root_namespace["true"]
321
+ else
322
+ @root_namespace["false"]
323
+ end
324
+ else
325
+ @root_namespace["false"]
326
+ end
327
+ end
328
+
329
+ number.def :> do |receiver, arguments|
330
+ arg = arguments.first
331
+ if arg.is_a?("Number")
332
+ if receiver.ruby_value > arg.ruby_value
333
+ @root_namespace["true"]
334
+ else
335
+ @root_namespace["false"]
336
+ end
337
+ else
338
+ @root_namespace["false"]
339
+ end
340
+ end
341
+
342
+ number.def :is do |receiver, arguments|
343
+ arg = arguments.first
344
+ if arg.is_a?("Number")
345
+ if receiver.ruby_value == arg.ruby_value
346
+ @root_namespace["true"]
347
+ else
348
+ @root_namespace["false"]
349
+ end
350
+ else
351
+ @root_namespace["false"]
352
+ end
353
+ end
354
+
355
+ number.def :negate do |receiver, arguments|
356
+ receiver.ruby_value = -receiver.ruby_value
357
+ receiver
358
+ end
359
+
360
+ number.def :to_string do |receiver, arguments|
361
+ @root_namespace["String"].new_with_value(receiver.ruby_value.to_s)
362
+ end
363
+
364
+ number.def :clone do |receiver, arguments|
365
+ if receiver.is_a?("Integer")
366
+ int.new_with_value(receiver.ruby_value)
367
+ elsif receiver.is_a?("Float")
368
+ float.new_with_value(receiver.ruby_value)
369
+ else
370
+ @root_namespace.es_nil
371
+ end
372
+ end
373
+ end
374
+
375
+ def load_boolean_methods
376
+ true_cls = @root_namespace["TrueClass"]
377
+ false_cls = @root_namespace["FalseClass"]
378
+
379
+ true_cls.def :clone do |receiver, arguments|
380
+ true_cls.new_with_value(true)
381
+ end
382
+
383
+ false_cls.def :clone do |receiver, arguments|
384
+ false_cls.new_with_value(false)
385
+ end
386
+ end
387
+
388
+ def load_nil_methods
389
+ nil_cls = @root_namespace["NilClass"]
390
+
391
+ nil_cls.def :clone do |receiver, arguments|
392
+ nil_cls.new_with_value(nil)
393
+ end
394
+ end
395
+
396
+ def load_list_methods
397
+ list = @root_namespace["List"]
398
+ list.class_def :new do |receiver, arguments|
399
+ new_list = list.new_with_value(ListBase.new(@root_namespace.es_nil))
400
+ arguments.each do |arg|
401
+ if arg.instance? && arg.runtime_class.name == "Pair"
402
+ new_list.ruby_value.hash_value[arg.call(:key)] = arg.call(:value)
403
+ else
404
+ new_list.ruby_value.array_value << arg
405
+ end
406
+ end
407
+ new_list
408
+ end
409
+
410
+ list.def :[] do |receiver, arguments|
411
+ lst = receiver.ruby_value
412
+ arg = arguments.first
413
+ if arg.instance? && arg.runtime_class.name == "Integer"
414
+ index = arg.ruby_value
415
+ if index < lst.array_value.length
416
+ lst.array_value[index]
417
+ else
418
+ lst.hash_value[arg.ruby_value]
419
+ end
420
+ else
421
+ lst.hash_value[arg]
422
+ end
423
+ end
424
+
425
+ list.def :[]= do |receiver, arguments|
426
+ lst = receiver.ruby_value
427
+ key = arguments.first
428
+ value = arguments[1]
429
+ if key.instance? && key.runtime_class.name == "Integer"
430
+ index = key.ruby_value
431
+ if index < lst.array_value.length
432
+ lst.array_value[index] = value
433
+ else
434
+ lst.hash_value[key.ruby_value] = value
435
+ end
436
+ else
437
+ lst.hash_value[key] = value
438
+ end
439
+ value
440
+ end
441
+
442
+ list.def :merge! do |receiver, arguments|
443
+ lst = receiver.ruby_value
444
+ arg = arguments.first
445
+ if arg.is_a?("List")
446
+ lst.merge!(arg.ruby_value)
447
+ end
448
+ receiver
449
+ end
450
+
451
+ list.def :push do |receiver, arguments|
452
+ receiver.ruby_value.array_value << arguments.first
453
+ arguments.first
454
+ end
455
+
456
+ list.def :pop do |receiver, arguments|
457
+ val = receiver.ruby_value.array_value.pop
458
+ val.nil? ? @root_namespace.es_nil : val
459
+ end
460
+
461
+ list.def :shift do |receiver, arguments|
462
+ val = receiver.ruby_value.array_value.shift
463
+ val.nil? ? @root_namespace.es_nil : val
464
+ end
465
+
466
+ list.def :unshift do |receiver, arguments|
467
+ receiver.ruby_value.array_value.unshift(arguments.first)
468
+ arguments.first
469
+ end
470
+
471
+ list.def :keys do |receiver, arguments|
472
+ lst = receiver.ruby_value
473
+ keys = (lst.array_value.length > 0 ? (0...lst.array_value.length).to_a : []).map { |v| @root_namespace["Integer"].new_with_value(v) }
474
+ keys.concat(lst.hash_value.keys)
475
+ list.call(:new, keys)
476
+ end
477
+
478
+ list.def :values do |receiver, arguments|
479
+ lst = receiver.ruby_value
480
+ vals = (lst.array_value.length > 0 ? lst.array_value.dup : [])
481
+ vals.concat(lst.hash_value.values)
482
+ list.call(:new, vals)
483
+ end
484
+
485
+ list.def :delete do |receiver, arguments|
486
+ val = receiver.ruby_value.hash_value.delete(arguments.first)
487
+ val.nil? ? @root_namespace.es_nil : val
488
+ end
489
+
490
+ list.def :length do |receiver, arguments|
491
+ ruby_val = receiver.ruby_value
492
+ length = ruby_val.array_value.length + ruby_val.hash_value.length
493
+ @root_namespace["Integer"].new_with_value(length)
494
+ end
495
+
496
+ list.def :first do |receiver, arguments|
497
+ receiver.ruby_value.array_value.first
498
+ end
499
+
500
+ list.def :last do |receiver, arguments|
501
+ receiver.ruby_value.array_value.last
502
+ end
503
+
504
+ list.def :clear do |receiver, arguments|
505
+ receiver.ruby_value.clear
506
+ receiver
507
+ end
508
+
509
+ list.def :join do |receiver, arguments|
510
+ str = if arguments.length > 0
511
+ arguments.first.call(:to_string).ruby_value
512
+ else
513
+ ", "
514
+ end
515
+ values = receiver.call(:values).ruby_value.array_value.map { |v| v.call(:to_string).ruby_value }
516
+ @root_namespace["String"].new_with_value(values.join(str))
517
+ end
518
+
519
+ list.def :to_string do |receiver, arguments|
520
+ arr_vals = receiver.ruby_value.array_value.map do |val|
521
+ val.call(:inspect).ruby_value
522
+ end
523
+ arr_str = arr_vals.join(", ")
524
+ hash_vals = receiver.ruby_value.hash_value.map do |k, v|
525
+ if k.kind_of?(EleetScriptClassSkeleton)
526
+ k = k.call(:inspect).ruby_value
527
+ else
528
+ k = k.inspect
529
+ end
530
+ "#{k}=>#{v.call(:inspect).ruby_value}"
531
+ end
532
+ hash_str = hash_vals.join(", ")
533
+ str = if arr_str.length > 0 && hash_str.length > 0
534
+ arr_str + ", " + hash_str
535
+ elsif arr_str.length > 0
536
+ arr_str
537
+ elsif hash_str.length > 0
538
+ hash_str
539
+ else
540
+ ""
541
+ end
542
+ @root_namespace["String"].new_with_value("[#{str}]")
543
+ end
544
+ end
545
+
546
+ def load_lambda_methods
547
+ lambda = @root_namespace["Lambda"]
548
+ lambda.def :call do |receiver, arguments, context|
549
+ receiver.ruby_value.call(nil, arguments, context)
550
+ end
551
+ end
552
+ end
553
+ end