halunke 0.2.0 → 0.3.0

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.
@@ -1,222 +1,11 @@
1
- # This file is not tested directly right now,
2
- # because I'm not sure if this structure is good
3
- # They are all prefixed with H to prevent collisions with Ruby's equivalents
4
- module Halunke
5
- class HClass
6
- def initialize(name, methods)
7
- @name = name
8
- @runtime_methods = methods
9
- end
10
-
11
- def create_instance(ruby_value = nil)
12
- HObject.new(self, ruby_value)
13
- end
14
-
15
- def lookup(message)
16
- @runtime_methods.fetch(message)
17
- rescue KeyError
18
- raise "Class #{@name} has no method to respond to message '#{message}'"
19
- end
20
- end
21
-
22
- class HObject
23
- attr_reader :ruby_value
24
-
25
- def initialize(runtime_class, ruby_value = nil)
26
- @runtime_class = runtime_class
27
- @ruby_value = ruby_value
28
- end
29
-
30
- def receive_message(context, message_name, message_value)
31
- m = @runtime_class.lookup(message_name)
32
- m.call(context, [self].concat(message_value))
33
- end
34
-
35
- def inspect(context)
36
- receive_message(context, "inspect", []).ruby_value
37
- end
38
- end
39
-
40
- class HFunction
41
- def initialize(signature, fn)
42
- @signature = signature
43
- @fn = fn
44
- end
45
-
46
- # TODO: This is a little bit of duplication that could probably be cleaned up by making functions proper objects
47
- def receive_message(context, message_name, message_value)
48
- raise "Class Function has no method to respond to message '#{message_name}'" unless message_name == "call"
49
- call(context, message_value[0].ruby_value)
50
- end
51
-
52
- def call(parent_context, args)
53
- context = parent_context.create_child
54
- @signature.zip(args).each do |name, value|
55
- context[name.to_s] = value
56
- end
57
- @fn.call(context)
58
- end
59
- end
60
-
61
- class HContext
62
- def initialize(parent_context = nil)
63
- @parent_context = parent_context
64
- @context = {}
65
- end
66
-
67
- def []=(name, value)
68
- @context[name] = value
69
- end
70
-
71
- def [](name)
72
- @context.fetch(name)
73
- rescue KeyError
74
- raise "Undefined bareword '#{name}'" if @parent_context.nil?
75
- @parent_context[name]
76
- end
77
-
78
- def parent
79
- @parent_context
80
- end
81
-
82
- def key?(name)
83
- @context.key?(name)
84
- end
85
-
86
- def create_child
87
- HContext.new(self)
88
- end
89
-
90
- def self.root_context
91
- context = new
92
-
93
- context["Number"] = HNumber
94
- context["String"] = HString
95
- context["Array"] = HArray
96
- context["UnassignedBareword"] = HUnassignedBareword
97
- context["True"] = HTrue
98
- context["False"] = HFalse
99
- context["true"] = HTrue.create_instance
100
- context["false"] = HFalse.create_instance
101
-
102
- context
103
- end
104
- end
105
-
106
- HNumber = HClass.new(
107
- "Number",
108
- "+" => HFunction.new([:self, :other], lambda { |context|
109
- HNumber.create_instance(context["self"].ruby_value + context["other"].ruby_value)
110
- }),
111
- "<" => HFunction.new([:self, :other], lambda { |context|
112
- if context["self"].ruby_value < context["other"].ruby_value
113
- HTrue.create_instance
114
- else
115
- HFalse.create_instance
116
- end
117
- }),
118
- ">" => HFunction.new([:self, :other], lambda { |context|
119
- if context["self"].ruby_value > context["other"].ruby_value
120
- HTrue.create_instance
121
- else
122
- HFalse.create_instance
123
- end
124
- }),
125
- "=" => HFunction.new([:self, :other], lambda { |context|
126
- if context["self"].ruby_value == context["other"].ruby_value
127
- HTrue.create_instance
128
- else
129
- HFalse.create_instance
130
- end
131
- }),
132
- "inspect" => HFunction.new([:self], lambda { |context|
133
- float_value = context["self"].ruby_value.to_f
134
- float_value = float_value.to_i if float_value.to_i == float_value
135
- HString.create_instance(float_value.to_s)
136
- })
137
- )
138
-
139
- HString = HClass.new(
140
- "String",
141
- "reverse" => HFunction.new([:self], lambda { |context|
142
- HString.create_instance(context["self"].ruby_value.reverse)
143
- }),
144
- "replace with" => HFunction.new([:self, :searchword, :replacement], lambda { |context|
145
- result = context["self"].ruby_value.gsub(
146
- context["searchword"].ruby_value,
147
- context["replacement"].ruby_value
148
- )
149
- HString.create_instance(result)
150
- }),
151
- "=" => HFunction.new([:self, :other], lambda { |context|
152
- if context["self"].ruby_value == context["other"].ruby_value
153
- HTrue.create_instance
154
- else
155
- HFalse.create_instance
156
- end
157
- }),
158
- "inspect" => HFunction.new([:self], lambda { |context|
159
- HString.create_instance(context["self"].ruby_value.inspect)
160
- })
161
- )
162
-
163
- HArray = HClass.new(
164
- "Array",
165
- "inspect" => HFunction.new([:self], lambda { |context|
166
- inspected_members = context["self"].ruby_value.map { |member| member.inspect(context) }
167
- HString.create_instance("[#{inspected_members.join(' ')}]")
168
- }),
169
- "=" => HFunction.new([:self, :other], lambda { |context|
170
- return HFalse.create_instance if context["self"].ruby_value.length != context["other"].ruby_value.length
171
-
172
- context["self"].ruby_value.zip(context["other"].ruby_value).map do |a, b|
173
- a.receive_message(context.parent, "=", [b])
174
- end.reduce(HTrue.create_instance) do |memo, value|
175
- memo.receive_message(context, "and", [value])
176
- end
177
- })
178
- )
179
-
180
- HUnassignedBareword = HClass.new(
181
- "UnassignedBareword",
182
- "=" => HFunction.new([:self, :other], lambda { |context|
183
- context.parent[context["self"].ruby_value] = context["other"]
184
- HTrue.create_instance
185
- }),
186
- "inspect" => HFunction.new([:self], lambda { |context|
187
- HString.create_instance("'#{context["self"].ruby_value}")
188
- })
189
- )
190
-
191
- HTrue = HClass.new(
192
- "True",
193
- "and" => HFunction.new([:self, :other], lambda { |context|
194
- context["other"]
195
- }),
196
- "or" => HFunction.new([:self, :other], lambda { |context|
197
- context["self"]
198
- }),
199
- "then else" => HFunction.new([:self, :true_branch, :false_branch], lambda { |context|
200
- context["true_branch"].receive_message(context, "call", [HArray.create_instance([])])
201
- }),
202
- "inspect" => HFunction.new([:self], lambda {|context|
203
- HString.create_instance("true")
204
- })
205
- )
206
-
207
- HFalse = HClass.new(
208
- "False",
209
- "and" => HFunction.new([:self, :other], lambda { |context|
210
- context["self"]
211
- }),
212
- "or" => HFunction.new([:self, :other], lambda { |context|
213
- context["other"]
214
- }),
215
- "then else" => HFunction.new([:self, :true_branch, :false_branch], lambda { |context|
216
- context["false_branch"].receive_message(context, "call", [HArray.create_instance([])])
217
- }),
218
- "inspect" => HFunction.new([:self], lambda {|context|
219
- HString.create_instance("false")
220
- })
221
- )
222
- end
1
+ require "halunke/runtime/hclass"
2
+ require "halunke/runtime/hobject"
3
+ require "halunke/runtime/hnative_object"
4
+ require "halunke/runtime/hfunction"
5
+ require "halunke/runtime/hnumber"
6
+ require "halunke/runtime/hstring"
7
+ require "halunke/runtime/harray"
8
+ require "halunke/runtime/hdictionary"
9
+ require "halunke/runtime/hunassigned_bareword"
10
+ require "halunke/runtime/hstdout"
11
+ require "halunke/runtime/hweb"
@@ -0,0 +1,18 @@
1
+ (Class new 'False
2
+ methods @[
3
+ "and" { |'self 'other|
4
+ self
5
+ }
6
+ "or" { |'self 'other|
7
+ other
8
+ }
9
+ "then else" { |'self 'true_branch 'false_branch|
10
+ (false_branch call [])
11
+ }
12
+ "inspect" { |'self 'other|
13
+ "false"
14
+ }
15
+ ]
16
+ )
17
+
18
+ ('false = (False new))
@@ -0,0 +1,30 @@
1
+ module Halunke
2
+ module Runtime
3
+ HArray = HClass.new(
4
+ "Array",
5
+ [],
6
+ {
7
+ "inspect" => HFunction.new([:self], lambda { |context|
8
+ inspected_members = context["self"].ruby_value.map { |member| member.inspect(context) }
9
+ HString.create_instance("[#{inspected_members.join(' ')}]")
10
+ }),
11
+ "=" => HFunction.new([:self, :other], lambda { |context|
12
+ return context["false"] if context["self"].ruby_value.length != context["other"].ruby_value.length
13
+
14
+ context["self"].ruby_value.zip(context["other"].ruby_value).map do |a, b|
15
+ a.receive_message(context.parent, "=", [b])
16
+ end.reduce(context["true"]) do |memo, value|
17
+ memo.receive_message(context, "and", [value])
18
+ end
19
+ }),
20
+ "map" => HFunction.new([:self, :fn], lambda { |context|
21
+ return HArray.create_instance(context["self"].ruby_value.map do |x|
22
+ context["fn"].receive_message(context, "call", [HArray.create_instance([x])])
23
+ end)
24
+ })
25
+ },
26
+ {},
27
+ true
28
+ )
29
+ end
30
+ end
@@ -0,0 +1,96 @@
1
+ module Halunke
2
+ module Runtime
3
+ class HClass
4
+ attr_reader :name
5
+
6
+ def initialize(name, allowed_attributes, instance_methods, class_methods, native)
7
+ @name = name
8
+ @allowed_attributes = allowed_attributes
9
+ @instance_methods = instance_methods
10
+ @class_methods = class_methods
11
+ @native = native
12
+ end
13
+
14
+ class << self
15
+ def receive_message(context, message_name, message_value)
16
+ case message_name
17
+ when "new attributes methods class_methods"
18
+ name = determine_name(message_value[0])
19
+ allowed_attributes = determine_allowed_attributes(message_value[1])
20
+ instance_methods = determine_methods(message_value[2])
21
+ class_methods = determine_methods(message_value[3])
22
+ when "new attributes methods"
23
+ name = determine_name(message_value[0])
24
+ allowed_attributes = determine_allowed_attributes(message_value[1])
25
+ instance_methods = determine_methods(message_value[2])
26
+ class_methods = {}
27
+ when "new methods"
28
+ name = determine_name(message_value[0])
29
+ allowed_attributes = []
30
+ instance_methods = determine_methods(message_value[1])
31
+ class_methods = {}
32
+ else
33
+ raise "Class Class has no method to respond to message '#{message_name}'"
34
+ end
35
+
36
+ context[name] = HClass.new(name, allowed_attributes, instance_methods, class_methods, false)
37
+ end
38
+
39
+ private
40
+
41
+ def determine_name(hstring)
42
+ hstring.ruby_value
43
+ end
44
+
45
+ def determine_allowed_attributes(harray)
46
+ harray.ruby_value.map(&:ruby_value)
47
+ end
48
+
49
+ def determine_methods(hdictionary)
50
+ instance_methods = {}
51
+ hdictionary.ruby_value.each_pair do |method_name, fn|
52
+ instance_methods[method_name.ruby_value] = fn
53
+ end
54
+ instance_methods
55
+ end
56
+ end
57
+
58
+ def receive_message(context, message_name, message_value)
59
+ if message_name == "new"
60
+ create_instance(message_value[0])
61
+ elsif @class_methods.keys.include? message_name
62
+ m = @class_methods[message_name]
63
+ m.receive_message(context, "call", [HArray.create_instance([self].concat(message_value))])
64
+ else
65
+ raise "Class #{@name} has no method to respond to message '#{message_name}'"
66
+ end
67
+ end
68
+
69
+ def allowed_attribute?(attribute_name)
70
+ @allowed_attributes.include? attribute_name
71
+ end
72
+
73
+ def create_instance(value = nil)
74
+ if native?
75
+ HNativeObject.new(self, value)
76
+ else
77
+ HObject.new(self, value ? value.ruby_value : {})
78
+ end
79
+ end
80
+
81
+ def lookup(message)
82
+ @instance_methods.fetch(message)
83
+ rescue KeyError
84
+ raise "Class #{@name} has no method to respond to message '#{message}'"
85
+ end
86
+
87
+ def inspect(_context)
88
+ "#<Class #{@name}>"
89
+ end
90
+
91
+ def native?
92
+ @native
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,26 @@
1
+ module Halunke
2
+ module Runtime
3
+ HDictionary = HClass.new(
4
+ "Dictionary",
5
+ [],
6
+ {
7
+ "inspect" => HFunction.new([:self], lambda { |context|
8
+ x = []
9
+ context["self"].ruby_value.each_pair do |key, value|
10
+ x.push(key.inspect(context))
11
+ x.push(value.inspect(context))
12
+ end
13
+ HString.create_instance("@[#{x.join(' ')}]")
14
+ }),
15
+ "@ else" => HFunction.new([:self, :search, :fallback], lambda { |context|
16
+ result = context["self"].ruby_value.find do |key, _value|
17
+ key.receive_message(context, "=", [context["search"]]).inspect(context) == "true"
18
+ end
19
+ result ? result[1] : context["fallback"]
20
+ })
21
+ },
22
+ {},
23
+ true
24
+ )
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ module Halunke
2
+ module Runtime
3
+ class HFunction
4
+ def initialize(signature, fn)
5
+ @signature = signature
6
+ @fn = fn
7
+ end
8
+
9
+ def receive_message(parent_context, message_name, message_value)
10
+ raise "Class Function has no method to respond to message '#{message_name}'" unless message_name == "call"
11
+
12
+ context = parent_context.create_child
13
+ args = message_value[0].ruby_value
14
+
15
+ @signature.zip(args).each do |name, value|
16
+ context[name.to_s] = value
17
+ end
18
+
19
+ @fn.call(context)
20
+ end
21
+
22
+ def inspect(_context)
23
+ "#<Function (#{@signature.length})>"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module Halunke
2
+ module Runtime
3
+ class HNativeObject
4
+ attr_reader :ruby_value
5
+
6
+ def initialize(runtime_class, ruby_value = nil)
7
+ @runtime_class = runtime_class
8
+ @ruby_value = ruby_value
9
+ end
10
+
11
+ def receive_message(context, message_name, message_value)
12
+ m = @runtime_class.lookup(message_name)
13
+ m.receive_message(context, "call", [HArray.create_instance([self].concat(message_value))])
14
+ end
15
+
16
+ def inspect(context)
17
+ receive_message(context, "inspect", []).ruby_value
18
+ end
19
+ end
20
+ end
21
+ end