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,23 @@
1
+ module EleetScript
2
+ class EleetScriptArray < EleetScriptClass
3
+ attr_reader :hash, :array
4
+
5
+ def initialize(memory, super_class = nil)
6
+ super(memory, super_class)
7
+ @hash = {}
8
+ @array = []
9
+ end
10
+
11
+ def to_s
12
+ str = "<EleetScriptArray"
13
+ hash_data = @hash.map do |key, value|
14
+ "#{key}=#{value}"
15
+ end
16
+ data = @array.dup.concat(hash_data)
17
+ if data.length > 0
18
+ str += "[" + data.join(", ") + "]"
19
+ end
20
+ str + ">"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module EleetScript
2
+ class ListBase
3
+ attr_reader :array_value, :hash_value
4
+
5
+ def initialize(nil_val)
6
+ @array_value = []
7
+ @hash_value = Hash.new(nil_val)
8
+ end
9
+
10
+ def merge!(o)
11
+ @array_value.concat(o.array_value)
12
+ @hash_value.merge!(o.hash_value)
13
+ end
14
+
15
+ def clone
16
+ dup
17
+ end
18
+
19
+ def dup
20
+ lst = ListBase.new
21
+ lst.array_value = @array_value.dup
22
+ lst.hash_value = @hash_value.dup
23
+ lst
24
+ end
25
+
26
+ def clear
27
+ @array_value.clear
28
+ @hash_value.clear
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module EleetScript
2
+
3
+ end
@@ -0,0 +1,113 @@
1
+ require "lang/runtime/class_skeleton"
2
+ require "lang/runtime/class_instance"
3
+ require "lang/runtime/method_hash"
4
+ require "util/processed_key_hash"
5
+
6
+ module EleetScript
7
+ class EleetScriptClass < EleetScriptClassSkeleton
8
+ attr_accessor :methods, :class_vars, :context, :name
9
+ attr_reader :super_class
10
+ set_is_class
11
+
12
+ class << self
13
+ def create(namespace, name, super_class = nil)
14
+ cls = EleetScriptClass.new(namespace, super_class)
15
+ cls.name = name
16
+ cls
17
+ end
18
+ end
19
+
20
+ def initialize(namespace, super_class = nil)
21
+ @methods = MethodHash.new
22
+ @class_vars = ProcessedKeyHash.new
23
+ @class_vars.set_key_preprocessor do |key|
24
+ key[0..1] == "@@" ? key[2..-1] : key
25
+ end
26
+ @context = namespace.new_class_context(self, self)
27
+ @super_class = super_class
28
+ @ruby_value = self
29
+ end
30
+ alias :class_name :name
31
+
32
+ def call(method_name, arguments = [])
33
+ method = lookup(method_name.to_s)
34
+ if method
35
+ if method.arity == 3
36
+ method.call(self, arguments, @context)
37
+ else
38
+ method.call(self, arguments)
39
+ end
40
+ else
41
+ es_method_name = @context["String"].new_with_value(method_name.to_s)
42
+ call(NO_METHOD, arguments.dup.unshift(es_method_name))
43
+ end
44
+ end
45
+
46
+ def lookup(method_name)
47
+ method_name = method_name[0..1] == "@@" ? method_name : "@@#{method_name}"
48
+ method = @methods[method_name]
49
+ if method.nil? && has_super_class?
50
+ return super_class.lookup(method_name)
51
+ end
52
+ method
53
+ end
54
+
55
+ def instance_lookup(method_name)
56
+ method = @methods[method_name]
57
+ if method.nil? && has_super_class?
58
+ return super_class.instance_lookup(method_name)
59
+ end
60
+ method
61
+ end
62
+
63
+ def super_class
64
+ @super_class || @context["Object"]
65
+ end
66
+
67
+ def def(method_name, es_block = nil, &block)
68
+ method_name = method_name.to_s
69
+ if block_given?
70
+ @methods[method_name] = block
71
+ else
72
+ @methods[method_name] = es_method
73
+ end
74
+ end
75
+
76
+ def class_def(method_name, es_block = nil, &block)
77
+ method_name = "@@#{method_name}"
78
+ if block_given?
79
+ @methods[method_name] = block
80
+ else
81
+ @methods[method_name] = es_method
82
+ end
83
+ end
84
+
85
+ def new
86
+ EleetScriptClassInstance.new(@context, self)
87
+ end
88
+
89
+ def new_with_value(value)
90
+ cls = EleetScriptClassInstance.new(@context, self)
91
+ cls.ruby_value = value
92
+ cls
93
+ end
94
+
95
+ def to_s
96
+ "<EleetScriptClass \"#{name || "Unnamed"}\">"
97
+ end
98
+
99
+ def inspect
100
+ to_s[0..-2] + " @methods(#{@methods.keys.join(", ")})>"
101
+ end
102
+
103
+ def is_a?(value)
104
+ false
105
+ end
106
+
107
+ private
108
+
109
+ def has_super_class?
110
+ @super_class || (@super_class.nil? && name != "Object")
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,53 @@
1
+ module EleetScript
2
+ class EleetScriptClassInstance < EleetScriptClassSkeleton
3
+ attr_accessor :instance_vars, :runtime_class, :context
4
+ set_is_instance
5
+
6
+ def initialize(class_context, runtime_class)
7
+ @instance_vars = ProcessedKeyHash.new
8
+ @instance_vars.set_key_preprocessor do |key|
9
+ key[0] == "@" ? key[1..-1] : key
10
+ end
11
+ @runtime_class = runtime_class
12
+ @context = class_context.new_instance_context(self)
13
+ @ruby_value = self
14
+ end
15
+
16
+ def call(method_name, arguments = [])
17
+ # puts "Calling #{method_name} on #{self}"
18
+ method = @runtime_class.instance_lookup(method_name.to_s)
19
+ if method
20
+ if method.arity == 3
21
+ method.call(self, arguments, @context)
22
+ else
23
+ method.call(self, arguments)
24
+ end
25
+ else
26
+ es_method_name = @context["String"].new_with_value(method_name.to_s)
27
+ call(NO_METHOD, arguments.dup.unshift(es_method_name))
28
+ end
29
+ end
30
+
31
+ def to_s
32
+ "<EleetScriptClassInstance @instance_of=\"#{runtime_class.name || "Unnamed"}\">"
33
+ end
34
+
35
+ def inspect
36
+ to_s
37
+ end
38
+
39
+ def is_a?(value)
40
+ names = ["Object", runtime_class.name]
41
+ cur_class = runtime_class
42
+ while cur_class.super_class.name != "Object"
43
+ names << cur_class.super_class.name
44
+ cur_class = cur_class.super_class
45
+ end
46
+ names.include?(value)
47
+ end
48
+
49
+ def class_name
50
+ @runtime_class.name
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,57 @@
1
+ module EleetScript
2
+ NO_METHOD = "no_method"
3
+
4
+ class EleetScriptClassSkeleton
5
+ attr_accessor :ruby_value
6
+ attr_reader :memory
7
+
8
+ class << self
9
+ def set_is_instance
10
+ self.class_eval do
11
+ def instance?
12
+ true
13
+ end
14
+ end
15
+ end
16
+
17
+ def set_is_class
18
+ self.class_eval do
19
+ def class?
20
+ true
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def instance?
27
+ false
28
+ end
29
+
30
+ def class?
31
+ false
32
+ end
33
+
34
+ def is_a?(name)
35
+ false
36
+ end
37
+
38
+ def hash
39
+ if instance?
40
+ ruby_value.hash
41
+ else
42
+ name.hash
43
+ end
44
+ end
45
+
46
+ def eql?(other)
47
+ if other.kind_of?(EleetScriptClassSkeleton)
48
+ if instance?
49
+ return call(:is, [other]).ruby_value
50
+ elsif class? && other.class?
51
+ return name == other.name
52
+ end
53
+ end
54
+ false
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,263 @@
1
+ require "util/processed_key_hash"
2
+
3
+ module EleetScript
4
+ class BaseContext
5
+ @@_init_funcs = []
6
+
7
+ attr_reader :constants, :local_vars, :global_vars, :namespaces
8
+ attr_accessor :current_self, :current_class
9
+
10
+ class << self
11
+ def init_with(*func_symbols)
12
+ @@_init_funcs += func_symbols
13
+ end
14
+ end
15
+
16
+ def initialize(*args)
17
+ init(args)
18
+ self
19
+ end
20
+
21
+ def es_nil
22
+ @_es_nil ||= self["nil"]
23
+ end
24
+
25
+ def root_ns
26
+ @parent_context ? @parent_context.root_ns : nil
27
+ end
28
+
29
+ def namespaces
30
+ @parent_context ? @parent_context.namespaces : {}
31
+ end
32
+
33
+ def global_vars
34
+ @parent_context ? @parent_context.global_vars : {}
35
+ end
36
+
37
+ def instance_vars
38
+ @current_self.instance_vars
39
+ end
40
+
41
+ def class_vars
42
+ @current_self.class_vars
43
+ end
44
+
45
+ def local_var(name, value = nil)
46
+ if value
47
+ local_vars[name] = value
48
+ else
49
+ local_vars[name] || es_nil
50
+ end
51
+ end
52
+
53
+ def [](key)
54
+ store = fetch_var_store(key)
55
+ if store[key]
56
+ store[key]
57
+ elsif @parent_context
58
+ @parent_context[key]
59
+ else
60
+ es_nil
61
+ end
62
+ end
63
+
64
+ def []=(key, value)
65
+ store = fetch_var_store(key)
66
+ store[key] = value
67
+ end
68
+
69
+ def respond_to_missing?(name, incl_priv = false)
70
+ @parent_context && @parent_context.respond_to?(name, incl_priv)
71
+ end
72
+
73
+ def method_missing(name, *args)
74
+ if @parent_context && @parent_context.respond_to?(name)
75
+ @parent_context.send(name, *args)
76
+ else
77
+ super(name, *args)
78
+ end
79
+ end
80
+
81
+ protected
82
+
83
+ def fetch_var_store(key)
84
+ if key[0] =~ /[A-Z]/
85
+ constants
86
+ elsif key[0] =~ /[a-z_]/
87
+ local_vars
88
+ elsif key[0] == "$"
89
+ global_vars
90
+ elsif key[0..1] == "@@"
91
+ class_vars
92
+ elsif key[0] == "@"
93
+ instance_vars
94
+ else
95
+ {}
96
+ end
97
+ end
98
+
99
+ def parent_context=(context)
100
+ @parent_context = context
101
+ end
102
+
103
+ private
104
+
105
+ def init(args)
106
+ throw "Arguments for new context should contain a current self and current class (even if both are nil)." if args.length < 2
107
+ @current_self = args.shift
108
+ cc = if args.length > 0
109
+ args.shift
110
+ else
111
+ nil
112
+ end
113
+ @current_class = if cc.nil?
114
+ if @current_self
115
+ if @current_self.class?
116
+ @current_self
117
+ else
118
+ @current_self.runtime_class
119
+ end
120
+ else
121
+ nil
122
+ end
123
+ else
124
+ cc
125
+ end
126
+ @parent_context = nil
127
+ @local_vars = ProcessedKeyHash.new
128
+ @constants = ProcessedKeyHash.new
129
+ @global_vars = {}
130
+ @namespaces = {}
131
+ @@_init_funcs.each do |symbol|
132
+ send(symbol, *args) if respond_to?(symbol, true)
133
+ end
134
+ end
135
+ end
136
+
137
+ class NamespaceContext < BaseContext
138
+ attr_reader :global_vars
139
+
140
+ init_with :init_namespace
141
+
142
+ def namespace(name)
143
+ ns = @namespaces[name]
144
+ if ns.nil? && @parent_context
145
+ ns = @parent_context.namespaces[ns]
146
+ end
147
+ ns
148
+ end
149
+
150
+ def add_namespace(name, value)
151
+ @namespaces[name] = value
152
+ end
153
+
154
+ def global_vars
155
+ if @root_ns == self
156
+ @global_vars
157
+ else
158
+ @root_ns.global_vars
159
+ end
160
+ end
161
+
162
+ def es_nil
163
+ @root_ns["nil"]
164
+ end
165
+
166
+ def root_ns
167
+ @root_ns
168
+ end
169
+
170
+ def new_class_context(current_self, current_class = nil)
171
+ ctx = ClassContext.new(current_self, current_class)
172
+ ctx.parent_context = self
173
+ ctx
174
+ end
175
+
176
+ def new_namespace_context
177
+ ctx = NamespaceContext.new(@current_self, @current_class, @root_ns)
178
+ ctx.parent_context = self
179
+ ctx
180
+ end
181
+
182
+ private
183
+
184
+ def init_namespace(root = nil)
185
+ if @root_ns == nil
186
+ @root_ns = self
187
+ @global_vars = ProcessedKeyHash.new
188
+ @global_vars.set_key_preprocessor do |key|
189
+ key[0] == "$" ? key[1..-1] : key
190
+ end
191
+ else
192
+ @root_ns = root
193
+ end
194
+ end
195
+ end
196
+
197
+ class ClassContext < BaseContext
198
+ def class_vars
199
+ @current_class.class_vars
200
+ end
201
+
202
+ def instance_vars
203
+ @parent_context ? @parent_context.instance_vars : {}
204
+ end
205
+
206
+ def new_instance_context(instance_self)
207
+ ctx = ClassInstanceContext.new(instance_self, current_class)
208
+ ctx.parent_context = self
209
+ ctx
210
+ end
211
+
212
+ def new_method_context(lambda_context = nil)
213
+ ctx = MethodContext.new(current_self, current_class, lambda_context)
214
+ ctx.parent_context = self
215
+ ctx
216
+ end
217
+ end
218
+
219
+ class ClassInstanceContext < BaseContext
220
+ def current_class
221
+ @parent_context.current_class
222
+ end
223
+
224
+ def local_vars
225
+ {}
226
+ end
227
+
228
+ def new_method_context(lambda_context = nil)
229
+ ctx = MethodContext.new(current_self, current_class, lambda_context)
230
+ ctx.parent_context = self
231
+ ctx
232
+ end
233
+ end
234
+
235
+ class MethodContext < BaseContext
236
+ init_with :handle_lambda_context
237
+
238
+ def local_var(name, value = nil)
239
+ if value
240
+ if @lambda_context && (val = @lambda_context.local_var(name))
241
+ @lambda_context.local_var(name, value)
242
+ else
243
+ local_vars[name] = value
244
+ end
245
+ else
246
+ val = super
247
+ if val == es_nil && @lambda_context
248
+ @lambda_context.local_var(name)
249
+ elsif val
250
+ val
251
+ else
252
+ es_nil
253
+ end
254
+ end
255
+ end
256
+
257
+ private
258
+
259
+ def handle_lambda_context(lambda_context)
260
+ @lambda_context = lambda_context
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,36 @@
1
+ class Enumerable
2
+ [] do |name|
3
+ cname = class_name
4
+ Errors < "Class %cname has not implemented [] which is required for Enumerable"
5
+ end
6
+
7
+ []= do |name, value|
8
+ cname = class_name
9
+ Errors < "Class %cname has not implemented []= which is required for Enumerable"
10
+ end
11
+
12
+ length do |name, value|
13
+ cname = class_name
14
+ Errors < "Class %cname has not implemented length which is required for Enumerable"
15
+ end
16
+
17
+ each do |iter|
18
+ if lambda? and iter.kind_of?(Lambda)
19
+ i = 0
20
+ while i < self.length
21
+ iter.call(self[i], i)
22
+ i += 1
23
+ end
24
+ end
25
+ end
26
+
27
+ map do |iter|
28
+ if lambda? and iter.kind_of?(Lambda)
29
+ arr = []
30
+ each -> { |item, key|
31
+ arr < iter.call(item, key)
32
+ }
33
+ end
34
+ arr
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ class FalseClass
2
+ to_string do
3
+ "false"
4
+ end
5
+
6
+ not do
7
+ true
8
+ end
9
+
10
+ and do
11
+ false
12
+ end
13
+
14
+ or do |o|
15
+ if o
16
+ o
17
+ else
18
+ false
19
+ end
20
+ end
21
+
22
+ to_string do
23
+ "false"
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ class Integer
2
+ times do |iter|
3
+ if lambda? and iter.kind_of?(Lambda)
4
+ i = 0
5
+ while i < self
6
+ iter.call(i)
7
+ i += 1
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,44 @@
1
+ class List
2
+ < do |value|
3
+ self.push(value)
4
+ end
5
+
6
+ + do |other|
7
+ if other.kind_of?(List)
8
+ self.merge!(other)
9
+ else
10
+ self
11
+ end
12
+ end
13
+
14
+ each do
15
+ if lambda?
16
+ keys = self.keys
17
+ i = 0
18
+ while i < keys.length
19
+ key = keys[i]
20
+ lambda.call(self[key], key)
21
+ i += 1
22
+ end
23
+ end
24
+ end
25
+
26
+ inject do |val, iter|
27
+ if lambda?
28
+ self.each -> { |item, key|
29
+ val = lambda.call(val, item, key)
30
+ }
31
+ end
32
+ val
33
+ end
34
+
35
+ sum do
36
+ inject(0) -> { |sum, val|
37
+ if val.kind_of?(Number)
38
+ sum + val
39
+ else
40
+ sum
41
+ end
42
+ }
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ class NilClass
2
+ to_string do
3
+ "nil"
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class Number
2
+ isnt do |val|
3
+ not self is val
4
+ end
5
+
6
+ >= do |val|
7
+ self > val or self is val
8
+ end
9
+
10
+ <= do |val|
11
+ self < val or self is val
12
+ end
13
+ end