halunke 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d34373e62580207f15e635b87cbbba8187f43aa5
4
- data.tar.gz: '08eebf0cc515092ff533c44a271d7fc4b3c4a451'
3
+ metadata.gz: b621079e4a57b2e4911784de31327cff6fa30a9b
4
+ data.tar.gz: 3980f6df3d46e58cb6ee08f5a7b7654bb629dbbc
5
5
  SHA512:
6
- metadata.gz: 41960737ac425cc20b7183ab8a506e64e11c55a7dab81d00abfa120d32b9b770e1500f69e595b0d4a73c19d5442e96adb2cfaf06ddace218b71415ec9df66a58
7
- data.tar.gz: f00d5bae53b39ae1c26b7bcde7ad8c16917b7e04a94c358680fc98850ead5e40284ec72cb3d1a6fb8802306dcbcb4d645236369b76fd9917b29ce26af4dbe1b0
6
+ metadata.gz: 218389d784fd2ba9332c3c24b7cb18079d529dfda97f9cdfbd060ba0b1a3be6fd02418da2ae0c1483e038ca59e5fdeba047111c831c2d00817901cf48ec663b5
7
+ data.tar.gz: e16520427aca78a5277fce868353cd73d96f2e65653da777b403fda407957ae2099c0c00e10cedeeb11dc9ac4378f44457fe29ebd5c3a6cec26a9bfcd90683a1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- halunke (0.1.0)
4
+ halunke (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -7,6 +7,10 @@ interpreter = Halunke::Interpreter.new
7
7
 
8
8
  puts "Halunke REPL. Ctrl+d to quit"
9
9
  while (line = Readline.readline(">> ", true))
10
- value = interpreter.eval(line)
11
- puts "=> #{value}"
10
+ begin
11
+ value = interpreter.eval(line)
12
+ puts "=> #{value}"
13
+ rescue Exception => e
14
+ puts "An Error Occurred: #{e.message}"
15
+ end
12
16
  end
@@ -5,26 +5,43 @@ token STRING
5
5
  token BAREWORD
6
6
  token OPEN_PAREN
7
7
  token CLOSE_PAREN
8
+ token OPEN_CURLY
9
+ token CLOSE_CURLY
8
10
  token OPERATOR
11
+ token UNASSIGNED_BAREWORD
12
+ token OPEN_BRACKET
13
+ token CLOSE_BRACKET
14
+ token BAR
9
15
 
10
16
  rule
11
17
  Program:
12
- /* empty */ { result = Nodes.new }
13
- | Expressions { result = val[0] }
18
+ Expressions { result = val[0] }
14
19
  ;
15
20
 
16
21
  Expressions:
17
- Expression { result = Nodes.new(val) }
22
+ /* empty */ { result = Nodes.new }
23
+ | Expression Expressions { result = Nodes.new([val[0]]).concat(val[1]) }
18
24
  ;
19
25
 
20
26
  Expression:
21
27
  Literal
22
- | OPEN_PAREN Literal Literals CLOSE_PAREN { result = Halunke::MessageSendNode.new(val[1], MessageNode.new(val[2].nodes)) }
28
+ | OPEN_CURLY Expressions CLOSE_CURLY { result = Halunke::FunctionNode.new(Halunke::ArrayNode.new([]), val[1]) }
29
+ | OPEN_CURLY Args Expressions CLOSE_CURLY { result = Halunke::FunctionNode.new(val[1], val[2]) }
30
+ | OPEN_PAREN Expression Expressions CLOSE_PAREN { result = Halunke::MessageSendNode.new(val[1], MessageNode.new(val[2].nodes)) }
31
+ | OPEN_BRACKET Expressions CLOSE_BRACKET { result = ArrayNode.new(val[1].nodes) }
23
32
  ;
24
33
 
25
- Literals:
26
- /* empty */ { result = Nodes.new }
27
- | Literal Literals { result = Nodes.new([val[0]]).concat(val[1]) }
34
+ Args:
35
+ BAR UnassignedBarewords BAR { result = Halunke::ArrayNode.new(val[1].nodes) }
36
+ ;
37
+
38
+ UnassignedBarewords:
39
+ /* empty */ { result = Nodes.new }
40
+ | UnassignedBareword UnassignedBarewords { result = Nodes.new([val[0]]).concat(val[1]) }
41
+ ;
42
+
43
+ UnassignedBareword:
44
+ UNASSIGNED_BAREWORD { result = UnassignedNode.new(BarewordNode.new(val[0])) }
28
45
  ;
29
46
 
30
47
  Literal:
@@ -33,6 +50,7 @@ rule
33
50
  /* TODO: Are Operators just Barewords? */
34
51
  | BAREWORD { result = BarewordNode.new(val[0]) }
35
52
  | OPERATOR { result = BarewordNode.new(val[0]) }
53
+ | UNASSIGNED_BAREWORD { result = UnassignedNode.new(BarewordNode.new(val[0])) }
36
54
  ;
37
55
 
38
56
  end
@@ -4,25 +4,12 @@ module Halunke
4
4
  class Interpreter
5
5
  def initialize
6
6
  @parser = Parser.new
7
- @context = {}
8
- prelude
7
+ @context = HContext.root_context
9
8
  end
10
9
 
11
10
  def eval(str)
12
11
  nodes = @parser.parse(str)
13
- nodes.eval(@context)
14
- end
15
-
16
- private
17
-
18
- def prelude
19
- @context[:Number] = Halunke::NativeClass.new(
20
- "+" => Halunke::NativeFunction.new(->(receiver, args) { receiver.ruby_value + args.first.ruby_value })
21
- )
22
-
23
- @context[:String] = Halunke::NativeClass.new(
24
- "reverse" => Halunke::NativeFunction.new(->(receiver, _args) { receiver.ruby_value.reverse })
25
- )
12
+ nodes.eval(@context).inspect(@context)
26
13
  end
27
14
  end
28
15
  end
@@ -2,7 +2,7 @@
2
2
  # line 1 "lib/halunke/lexer.rl"
3
3
  =begin
4
4
 
5
- # line 24 "lib/halunke/lexer.rl"
5
+ # line 36 "lib/halunke/lexer.rl"
6
6
 
7
7
  =end
8
8
 
@@ -19,7 +19,10 @@ self._lexer_actions = [
19
19
  0, 1, 0, 1, 1, 1, 2, 1,
20
20
  5, 1, 6, 1, 7, 1, 8, 1,
21
21
  9, 1, 10, 1, 11, 1, 12, 1,
22
- 13, 2, 2, 3, 2, 2, 4
22
+ 13, 1, 14, 1, 15, 1, 16, 1,
23
+ 17, 1, 18, 1, 19, 1, 20, 1,
24
+ 21, 1, 22, 2, 2, 3, 2, 2,
25
+ 4
23
26
  ]
24
27
 
25
28
  class << self
@@ -27,7 +30,8 @@ class << self
27
30
  private :_lexer_key_offsets, :_lexer_key_offsets=
28
31
  end
29
32
  self._lexer_key_offsets = [
30
- 0, 1, 16, 17, 19
33
+ 0, 1, 3, 26, 27, 32, 34, 37,
34
+ 39
31
35
  ]
32
36
 
33
37
  class << self
@@ -35,10 +39,12 @@ class << self
35
39
  private :_lexer_trans_keys, :_lexer_trans_keys=
36
40
  end
37
41
  self._lexer_trans_keys = [
38
- 34, 32, 34, 40, 41, 43, 45, 95,
39
- 9, 13, 48, 57, 65, 90, 97, 122,
40
- 34, 48, 57, 95, 65, 90, 97, 122,
41
- 0
42
+ 34, 48, 57, 32, 34, 39, 40, 41,
43
+ 43, 45, 91, 93, 95, 123, 124, 125,
44
+ 9, 13, 48, 57, 60, 62, 65, 90,
45
+ 97, 122, 34, 95, 65, 90, 97, 122,
46
+ 48, 57, 46, 48, 57, 48, 57, 95,
47
+ 65, 90, 97, 122, 0
42
48
  ]
43
49
 
44
50
  class << self
@@ -46,7 +52,8 @@ class << self
46
52
  private :_lexer_single_lengths, :_lexer_single_lengths=
47
53
  end
48
54
  self._lexer_single_lengths = [
49
- 1, 7, 1, 0, 1
55
+ 1, 0, 13, 1, 1, 0, 1, 0,
56
+ 1
50
57
  ]
51
58
 
52
59
  class << self
@@ -54,7 +61,8 @@ class << self
54
61
  private :_lexer_range_lengths, :_lexer_range_lengths=
55
62
  end
56
63
  self._lexer_range_lengths = [
57
- 0, 4, 0, 1, 2
64
+ 0, 1, 5, 0, 2, 1, 1, 1,
65
+ 2
58
66
  ]
59
67
 
60
68
  class << self
@@ -62,7 +70,8 @@ class << self
62
70
  private :_lexer_index_offsets, :_lexer_index_offsets=
63
71
  end
64
72
  self._lexer_index_offsets = [
65
- 0, 2, 14, 16, 18
73
+ 0, 2, 4, 23, 25, 29, 31, 34,
74
+ 36
66
75
  ]
67
76
 
68
77
  class << self
@@ -70,10 +79,13 @@ class << self
70
79
  private :_lexer_trans_targs, :_lexer_trans_targs=
71
80
  end
72
81
  self._lexer_trans_targs = [
73
- 1, 0, 1, 2, 1, 1, 3, 3,
74
- 4, 1, 3, 4, 4, 1, 1, 0,
75
- 3, 1, 4, 4, 4, 1, 1, 1,
76
- 1, 1, 0
82
+ 2, 0, 7, 2, 2, 3, 4, 2,
83
+ 2, 5, 5, 2, 2, 8, 2, 2,
84
+ 2, 2, 6, 2, 8, 8, 2, 2,
85
+ 0, 4, 4, 4, 2, 6, 2, 1,
86
+ 6, 2, 7, 2, 8, 8, 8, 2,
87
+ 2, 2, 2, 2, 2, 2, 2, 2,
88
+ 0
77
89
  ]
78
90
 
79
91
  class << self
@@ -81,10 +93,13 @@ class << self
81
93
  private :_lexer_trans_actions, :_lexer_trans_actions=
82
94
  end
83
95
  self._lexer_trans_actions = [
84
- 7, 0, 13, 5, 9, 11, 28, 28,
85
- 0, 13, 25, 0, 0, 15, 7, 0,
86
- 25, 23, 0, 0, 0, 17, 21, 19,
87
- 23, 17, 0
96
+ 7, 0, 0, 37, 25, 5, 46, 9,
97
+ 11, 0, 0, 17, 19, 0, 13, 21,
98
+ 15, 25, 5, 23, 0, 0, 27, 7,
99
+ 0, 43, 43, 43, 41, 5, 33, 0,
100
+ 5, 29, 0, 29, 0, 0, 0, 31,
101
+ 39, 37, 35, 41, 33, 29, 29, 31,
102
+ 0
88
103
  ]
89
104
 
90
105
  class << self
@@ -92,7 +107,8 @@ class << self
92
107
  private :_lexer_to_state_actions, :_lexer_to_state_actions=
93
108
  end
94
109
  self._lexer_to_state_actions = [
95
- 0, 1, 0, 0, 0
110
+ 0, 0, 1, 0, 0, 0, 0, 0,
111
+ 0
96
112
  ]
97
113
 
98
114
  class << self
@@ -100,7 +116,8 @@ class << self
100
116
  private :_lexer_from_state_actions, :_lexer_from_state_actions=
101
117
  end
102
118
  self._lexer_from_state_actions = [
103
- 0, 3, 0, 0, 0
119
+ 0, 0, 3, 0, 0, 0, 0, 0,
120
+ 0
104
121
  ]
105
122
 
106
123
  class << self
@@ -108,17 +125,18 @@ class << self
108
125
  private :_lexer_eof_trans, :_lexer_eof_trans=
109
126
  end
110
127
  self._lexer_eof_trans = [
111
- 23, 0, 24, 25, 26
128
+ 41, 42, 0, 43, 44, 45, 47, 47,
129
+ 48
112
130
  ]
113
131
 
114
132
  class << self
115
133
  attr_accessor :lexer_start
116
134
  end
117
- self.lexer_start = 1;
135
+ self.lexer_start = 2;
118
136
  class << self
119
137
  attr_accessor :lexer_first_final
120
138
  end
121
- self.lexer_first_final = 1;
139
+ self.lexer_first_final = 2;
122
140
  class << self
123
141
  attr_accessor :lexer_error
124
142
  end
@@ -127,10 +145,10 @@ self.lexer_error = -1;
127
145
  class << self
128
146
  attr_accessor :lexer_en_main
129
147
  end
130
- self.lexer_en_main = 1;
148
+ self.lexer_en_main = 2;
131
149
 
132
150
 
133
- # line 31 "lib/halunke/lexer.rl"
151
+ # line 43 "lib/halunke/lexer.rl"
134
152
  @tokens = []
135
153
  end
136
154
 
@@ -139,7 +157,7 @@ self.lexer_en_main = 1;
139
157
  eof = data.length
140
158
 
141
159
 
142
- # line 143 "lib/halunke/lexer.rb"
160
+ # line 161 "lib/halunke/lexer.rb"
143
161
  begin
144
162
  p ||= 0
145
163
  pe ||= data.length
@@ -149,9 +167,9 @@ begin
149
167
  act = 0
150
168
  end
151
169
 
152
- # line 39 "lib/halunke/lexer.rl"
170
+ # line 51 "lib/halunke/lexer.rl"
153
171
 
154
- # line 155 "lib/halunke/lexer.rb"
172
+ # line 173 "lib/halunke/lexer.rb"
155
173
  begin
156
174
  _klen, _trans, _keys, _acts, _nacts = nil
157
175
  _goto_level = 0
@@ -181,7 +199,7 @@ begin
181
199
  begin
182
200
  ts = p
183
201
  end
184
- # line 185 "lib/halunke/lexer.rb"
202
+ # line 203 "lib/halunke/lexer.rb"
185
203
  end # from state action switch
186
204
  end
187
205
  if _trigger_goto
@@ -253,73 +271,127 @@ when 2 then
253
271
  te = p+1
254
272
  end
255
273
  when 3 then
256
- # line 14 "lib/halunke/lexer.rl"
274
+ # line 22 "lib/halunke/lexer.rl"
257
275
  begin
258
- act = 1; end
276
+ act = 3; end
259
277
  when 4 then
260
- # line 19 "lib/halunke/lexer.rl"
278
+ # line 33 "lib/halunke/lexer.rl"
261
279
  begin
262
- act = 6; end
280
+ act = 14; end
263
281
  when 5 then
264
- # line 15 "lib/halunke/lexer.rl"
282
+ # line 21 "lib/halunke/lexer.rl"
265
283
  begin
266
284
  te = p+1
267
285
  begin emit(:STRING, data[ts+1...te-1]) end
268
286
  end
269
287
  when 6 then
270
- # line 17 "lib/halunke/lexer.rl"
288
+ # line 24 "lib/halunke/lexer.rl"
271
289
  begin
272
290
  te = p+1
273
291
  begin emit(:OPEN_PAREN, data[ts...te]) end
274
292
  end
275
293
  when 7 then
276
- # line 18 "lib/halunke/lexer.rl"
294
+ # line 25 "lib/halunke/lexer.rl"
277
295
  begin
278
296
  te = p+1
279
297
  begin emit(:CLOSE_PAREN, data[ts...te]) end
280
298
  end
281
299
  when 8 then
282
- # line 20 "lib/halunke/lexer.rl"
300
+ # line 26 "lib/halunke/lexer.rl"
283
301
  begin
284
302
  te = p+1
303
+ begin emit(:OPEN_CURLY, data[ts...te]) end
285
304
  end
286
305
  when 9 then
287
- # line 21 "lib/halunke/lexer.rl"
306
+ # line 27 "lib/halunke/lexer.rl"
288
307
  begin
289
308
  te = p+1
290
- begin raise "Could not lex '#{ data[ts...te] }'" end
309
+ begin emit(:CLOSE_CURLY, data[ts...te]) end
291
310
  end
292
311
  when 10 then
293
- # line 16 "lib/halunke/lexer.rl"
312
+ # line 28 "lib/halunke/lexer.rl"
313
+ begin
314
+ te = p+1
315
+ begin emit(:OPEN_BRACKET, data[ts...te]) end
316
+ end
317
+ when 11 then
318
+ # line 29 "lib/halunke/lexer.rl"
319
+ begin
320
+ te = p+1
321
+ begin emit(:CLOSE_BRACKET, data[ts...te]) end
322
+ end
323
+ when 12 then
324
+ # line 30 "lib/halunke/lexer.rl"
325
+ begin
326
+ te = p+1
327
+ begin emit(:BAR, data[ts...te]) end
328
+ end
329
+ when 13 then
330
+ # line 31 "lib/halunke/lexer.rl"
331
+ begin
332
+ te = p+1
333
+ begin emit(:OPERATOR, data[ts ... te]) end
334
+ end
335
+ when 14 then
336
+ # line 32 "lib/halunke/lexer.rl"
337
+ begin
338
+ te = p+1
339
+ end
340
+ when 15 then
341
+ # line 33 "lib/halunke/lexer.rl"
342
+ begin
343
+ te = p+1
344
+ begin raise "Could not lex '#{ data[ts...te] }'" end
345
+ end
346
+ when 16 then
347
+ # line 20 "lib/halunke/lexer.rl"
348
+ begin
349
+ te = p
350
+ p = p - 1; begin emit(:NUMBER, data[ts...te].to_r) end
351
+ end
352
+ when 17 then
353
+ # line 23 "lib/halunke/lexer.rl"
294
354
  begin
295
355
  te = p
296
356
  p = p - 1; begin emit(:BAREWORD, data[ts...te]) end
297
357
  end
298
- when 11 then
299
- # line 21 "lib/halunke/lexer.rl"
358
+ when 18 then
359
+ # line 31 "lib/halunke/lexer.rl"
360
+ begin
361
+ te = p
362
+ p = p - 1; begin emit(:OPERATOR, data[ts ... te]) end
363
+ end
364
+ when 19 then
365
+ # line 33 "lib/halunke/lexer.rl"
300
366
  begin
301
367
  te = p
302
368
  p = p - 1; begin raise "Could not lex '#{ data[ts...te] }'" end
303
369
  end
304
- when 12 then
305
- # line 21 "lib/halunke/lexer.rl"
370
+ when 20 then
371
+ # line 20 "lib/halunke/lexer.rl"
372
+ begin
373
+ begin p = ((te))-1; end
374
+ begin emit(:NUMBER, data[ts...te].to_r) end
375
+ end
376
+ when 21 then
377
+ # line 33 "lib/halunke/lexer.rl"
306
378
  begin
307
379
  begin p = ((te))-1; end
308
380
  begin raise "Could not lex '#{ data[ts...te] }'" end
309
381
  end
310
- when 13 then
382
+ when 22 then
311
383
  # line 1 "NONE"
312
384
  begin
313
385
  case act
314
- when 1 then
386
+ when 3 then
315
387
  begin begin p = ((te))-1; end
316
- emit(:NUMBER, data[ts...te].to_i) end
317
- when 6 then
388
+ emit(:UNASSIGNED_BAREWORD, data[ts+1 ...te]) end
389
+ when 14 then
318
390
  begin begin p = ((te))-1; end
319
- emit(:OPERATOR, data[ts ... te]) end
391
+ raise "Could not lex '#{ data[ts...te] }'" end
320
392
  end
321
393
  end
322
- # line 323 "lib/halunke/lexer.rb"
394
+ # line 395 "lib/halunke/lexer.rb"
323
395
  end # action switch
324
396
  end
325
397
  end
@@ -339,7 +411,7 @@ when 0 then
339
411
  # line 1 "NONE"
340
412
  begin
341
413
  ts = nil; end
342
- # line 343 "lib/halunke/lexer.rb"
414
+ # line 415 "lib/halunke/lexer.rb"
343
415
  end # to state action switch
344
416
  end
345
417
  if _trigger_goto
@@ -366,7 +438,7 @@ end
366
438
  end
367
439
  end
368
440
 
369
- # line 40 "lib/halunke/lexer.rl"
441
+ # line 52 "lib/halunke/lexer.rl"
370
442
 
371
443
  @tokens
372
444
  end
@@ -2,20 +2,32 @@
2
2
  %%{
3
3
  machine lexer;
4
4
 
5
- number = ('+'|'-')?[0-9]+;
5
+ number = ('+'|'-')?[0-9]+('.'[0-9]+)?;
6
6
  string = '"' [^"]* '"';
7
+ unassigned_bareword = "'" [a-zA-Z_]+;
7
8
  bareword = [a-zA-Z_]+;
8
9
  open_paren = '(';
9
10
  close_paren = ')';
10
- operator = '+' | '-';
11
+ open_curly = '{';
12
+ close_curly = '}';
13
+ open_bracket = '[';
14
+ close_bracket = ']';
15
+ bar = "|";
16
+ operator = '+' | '-' | '<' | '>' | '=';
11
17
 
12
18
  main := |*
13
19
 
14
- number => { emit(:NUMBER, data[ts...te].to_i) };
20
+ number => { emit(:NUMBER, data[ts...te].to_r) };
15
21
  string => { emit(:STRING, data[ts+1...te-1]) };
22
+ unassigned_bareword => { emit(:UNASSIGNED_BAREWORD, data[ts+1 ...te]) };
16
23
  bareword => { emit(:BAREWORD, data[ts...te]) };
17
24
  open_paren => { emit(:OPEN_PAREN, data[ts...te]) };
18
25
  close_paren => { emit(:CLOSE_PAREN, data[ts...te]) };
26
+ open_curly => { emit(:OPEN_CURLY, data[ts...te]) };
27
+ close_curly => { emit(:CLOSE_CURLY, data[ts...te]) };
28
+ open_bracket => { emit(:OPEN_BRACKET, data[ts...te]) };
29
+ close_bracket => { emit(:CLOSE_BRACKET, data[ts...te]) };
30
+ bar => { emit(:BAR, data[ts...te]) };
19
31
  operator => { emit(:OPERATOR, data[ts ... te]) };
20
32
  space;
21
33
  any => { raise "Could not lex '#{ data[ts...te] }'" };
@@ -25,31 +25,69 @@ module Halunke
25
25
 
26
26
  class NumberNode < LiteralNode
27
27
  def eval(context)
28
- context[:Number].create_instance(value)
28
+ context["Number"].create_instance(value)
29
29
  end
30
30
  end
31
31
 
32
32
  class StringNode < LiteralNode
33
33
  def eval(context)
34
- context[:String].create_instance(value)
34
+ context["String"].create_instance(value)
35
35
  end
36
36
  end
37
37
 
38
38
  class BarewordNode < LiteralNode
39
+ def eval(context)
40
+ context[value]
41
+ end
42
+ end
43
+
44
+ UnassignedNode = Struct.new(:node) do
45
+ def eval(context)
46
+ raise "Not unassigned: #{node.value} has value #{context[node.value].inspect}" if context.key? node.value
47
+ context["UnassignedBareword"].create_instance(node.value)
48
+ end
49
+ end
50
+
51
+ FunctionNode = Struct.new(:params, :body) do
52
+ def eval(_context)
53
+ signature = params.nodes.map(&:node).map(&:value)
54
+
55
+ HFunction.new(signature, lambda { |context|
56
+ body.eval(context)
57
+ })
58
+ end
59
+ end
60
+
61
+ ArrayNode = Struct.new(:nodes) do
62
+ def initialize(nodes = [])
63
+ super(nodes)
64
+ end
65
+
66
+ def eval(context)
67
+ context["Array"].create_instance(nodes.map { |node| node.eval(context) })
68
+ end
39
69
  end
40
70
 
41
71
  MessageSendNode = Struct.new(:receiver, :message) do
42
72
  def eval(context)
43
- receiver.eval(context).receive_message(*message.eval(context))
73
+ receiver.eval(context).receive_message(context, *message.eval(context))
44
74
  end
45
75
  end
46
76
 
47
77
  MessageNode = Struct.new(:nodes) do
48
78
  def eval(context)
49
- case nodes.length
50
- when 1 then [nodes[0].value, []]
51
- when 2 then [nodes[0].value, [nodes[1].eval(context)]]
52
- else raise "Not implemented"
79
+ if nodes.length == 1
80
+ [nodes[0].value, []]
81
+ elsif nodes.length.even?
82
+ name = []
83
+ message = []
84
+ nodes.each_slice(2) do |name_part, value|
85
+ name.push(name_part.value)
86
+ message.push(value.eval(context))
87
+ end
88
+ [name.join(" "), message]
89
+ else
90
+ raise "Parse Error"
53
91
  end
54
92
  end
55
93
  end
@@ -13,7 +13,7 @@ require "halunke/nodes"
13
13
  module Halunke
14
14
  class Parser < Racc::Parser
15
15
 
16
- module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 46)
16
+ module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 64)
17
17
 
18
18
  def parse(code)
19
19
  @tokens = Lexer.new.tokenize(code)
@@ -27,52 +27,74 @@ end
27
27
  ##### State transition tables begin ###
28
28
 
29
29
  racc_action_table = [
30
- 6, 7, 8, 5, 10, 9, 6, 7, 8, 12,
31
- 15, 9, 6, 7, 8, nil, nil, 9, 6, 7,
32
- 8, nil, nil, 9 ]
30
+ 8, 9, 10, 6, 13, 5, 20, 11, 12, 7,
31
+ 21, 17, 8, 9, 10, 6, 25, 5, 27, 11,
32
+ 12, 7, 8, 9, 10, 6, 28, 5, 29, 11,
33
+ 12, 7, 8, 9, 10, 6, 25, 5, 31, 11,
34
+ 12, 7, 8, 9, 10, 6, nil, 5, nil, 11,
35
+ 12, 7, 8, 9, 10, 6, nil, 5, nil, 11,
36
+ 12, 7, 8, 9, 10, 6, nil, 5, nil, 11,
37
+ 12, 7 ]
33
38
 
34
39
  racc_action_check = [
35
- 0, 0, 0, 0, 1, 0, 5, 5, 5, 10,
36
- 13, 5, 11, 11, 11, nil, nil, 11, 14, 14,
37
- 14, nil, nil, 14 ]
40
+ 5, 5, 5, 5, 1, 5, 13, 5, 5, 5,
41
+ 15, 5, 0, 0, 0, 0, 17, 0, 19, 0,
42
+ 0, 0, 3, 3, 3, 3, 22, 3, 23, 3,
43
+ 3, 3, 6, 6, 6, 6, 24, 6, 26, 6,
44
+ 6, 6, 7, 7, 7, 7, nil, 7, nil, 7,
45
+ 7, 7, 16, 16, 16, 16, nil, 16, nil, 16,
46
+ 16, 16, 18, 18, 18, 18, nil, 18, nil, 18,
47
+ 18, 18 ]
38
48
 
39
49
  racc_action_pointer = [
40
- -2, 4, nil, nil, nil, 4, nil, nil, nil, nil,
41
- 9, 10, nil, 4, 16, nil, nil ]
50
+ 10, 4, nil, 20, nil, -2, 30, 40, nil, nil,
51
+ nil, nil, nil, 6, nil, 2, 50, 6, 60, 6,
52
+ nil, nil, 18, 15, 26, nil, 32, nil, nil, nil,
53
+ nil, nil ]
42
54
 
43
55
  racc_action_default = [
44
- -1, -12, -2, -3, -4, -12, -8, -9, -10, -11,
45
- -12, -6, 17, -12, -6, -5, -7 ]
56
+ -2, -18, -1, -2, -4, -2, -18, -2, -13, -14,
57
+ -15, -16, -17, -18, -3, -18, -2, -10, -2, -18,
58
+ 32, -5, -18, -18, -10, -12, -18, -8, -6, -9,
59
+ -11, -7 ]
46
60
 
47
61
  racc_goto_table = [
48
- 4, 13, 1, 2, 16, 11, 3 ]
62
+ 2, 23, 1, 14, 18, 15, 16, 19, 30, nil,
63
+ nil, nil, nil, nil, nil, nil, 22, nil, 26 ]
49
64
 
50
65
  racc_goto_check = [
51
- 4, 5, 1, 2, 5, 4, 3 ]
66
+ 2, 6, 1, 2, 3, 2, 5, 2, 6, nil,
67
+ nil, nil, nil, nil, nil, nil, 2, nil, 2 ]
52
68
 
53
69
  racc_goto_pointer = [
54
- nil, 2, 3, 6, 0, -10 ]
70
+ nil, 2, 0, -2, nil, 1, -16, nil ]
55
71
 
56
72
  racc_goto_default = [
57
- nil, nil, nil, nil, 14, nil ]
73
+ nil, nil, nil, 3, 4, nil, nil, 24 ]
58
74
 
59
75
  racc_reduce_table = [
60
76
  0, 0, :racc_error,
61
- 0, 9, :_reduce_1,
62
- 1, 9, :_reduce_2,
63
- 1, 10, :_reduce_3,
64
- 1, 11, :_reduce_none,
65
- 4, 11, :_reduce_5,
66
- 0, 13, :_reduce_6,
67
- 2, 13, :_reduce_7,
68
- 1, 12, :_reduce_8,
69
- 1, 12, :_reduce_9,
70
- 1, 12, :_reduce_10,
71
- 1, 12, :_reduce_11 ]
72
-
73
- racc_reduce_n = 12
74
-
75
- racc_shift_n = 17
77
+ 1, 15, :_reduce_1,
78
+ 0, 16, :_reduce_2,
79
+ 2, 16, :_reduce_3,
80
+ 1, 17, :_reduce_none,
81
+ 3, 17, :_reduce_5,
82
+ 4, 17, :_reduce_6,
83
+ 4, 17, :_reduce_7,
84
+ 3, 17, :_reduce_8,
85
+ 3, 19, :_reduce_9,
86
+ 0, 20, :_reduce_10,
87
+ 2, 20, :_reduce_11,
88
+ 1, 21, :_reduce_12,
89
+ 1, 18, :_reduce_13,
90
+ 1, 18, :_reduce_14,
91
+ 1, 18, :_reduce_15,
92
+ 1, 18, :_reduce_16,
93
+ 1, 18, :_reduce_17 ]
94
+
95
+ racc_reduce_n = 18
96
+
97
+ racc_shift_n = 32
76
98
 
77
99
  racc_token_table = {
78
100
  false => 0,
@@ -82,9 +104,15 @@ racc_token_table = {
82
104
  :BAREWORD => 4,
83
105
  :OPEN_PAREN => 5,
84
106
  :CLOSE_PAREN => 6,
85
- :OPERATOR => 7 }
107
+ :OPEN_CURLY => 7,
108
+ :CLOSE_CURLY => 8,
109
+ :OPERATOR => 9,
110
+ :UNASSIGNED_BAREWORD => 10,
111
+ :OPEN_BRACKET => 11,
112
+ :CLOSE_BRACKET => 12,
113
+ :BAR => 13 }
86
114
 
87
- racc_nt_base = 8
115
+ racc_nt_base = 14
88
116
 
89
117
  racc_use_result_var = true
90
118
 
@@ -112,13 +140,21 @@ Racc_token_to_s_table = [
112
140
  "BAREWORD",
113
141
  "OPEN_PAREN",
114
142
  "CLOSE_PAREN",
143
+ "OPEN_CURLY",
144
+ "CLOSE_CURLY",
115
145
  "OPERATOR",
146
+ "UNASSIGNED_BAREWORD",
147
+ "OPEN_BRACKET",
148
+ "CLOSE_BRACKET",
149
+ "BAR",
116
150
  "$start",
117
151
  "Program",
118
152
  "Expressions",
119
153
  "Expression",
120
154
  "Literal",
121
- "Literals" ]
155
+ "Args",
156
+ "UnassignedBarewords",
157
+ "UnassignedBareword" ]
122
158
 
123
159
  Racc_debug_parser = false
124
160
 
@@ -126,78 +162,120 @@ Racc_debug_parser = false
126
162
 
127
163
  # reduce 0 omitted
128
164
 
129
- module_eval(<<'.,.,', 'grammar.y', 11)
165
+ module_eval(<<'.,.,', 'grammar.y', 17)
130
166
  def _reduce_1(val, _values, result)
131
- result = Nodes.new
167
+ result = val[0]
132
168
  result
133
169
  end
134
170
  .,.,
135
171
 
136
- module_eval(<<'.,.,', 'grammar.y', 12)
172
+ module_eval(<<'.,.,', 'grammar.y', 21)
137
173
  def _reduce_2(val, _values, result)
138
- result = val[0]
174
+ result = Nodes.new
139
175
  result
140
176
  end
141
177
  .,.,
142
178
 
143
- module_eval(<<'.,.,', 'grammar.y', 16)
179
+ module_eval(<<'.,.,', 'grammar.y', 22)
144
180
  def _reduce_3(val, _values, result)
145
- result = Nodes.new(val)
181
+ result = Nodes.new([val[0]]).concat(val[1])
146
182
  result
147
183
  end
148
184
  .,.,
149
185
 
150
186
  # reduce 4 omitted
151
187
 
152
- module_eval(<<'.,.,', 'grammar.y', 21)
188
+ module_eval(<<'.,.,', 'grammar.y', 27)
153
189
  def _reduce_5(val, _values, result)
154
- result = Halunke::MessageSendNode.new(val[1], MessageNode.new(val[2].nodes))
190
+ result = Halunke::FunctionNode.new(Halunke::ArrayNode.new([]), val[1])
155
191
  result
156
192
  end
157
193
  .,.,
158
194
 
159
- module_eval(<<'.,.,', 'grammar.y', 25)
195
+ module_eval(<<'.,.,', 'grammar.y', 28)
160
196
  def _reduce_6(val, _values, result)
161
- result = Nodes.new
197
+ result = Halunke::FunctionNode.new(val[1], val[2])
162
198
  result
163
199
  end
164
200
  .,.,
165
201
 
166
- module_eval(<<'.,.,', 'grammar.y', 26)
202
+ module_eval(<<'.,.,', 'grammar.y', 29)
167
203
  def _reduce_7(val, _values, result)
168
- result = Nodes.new([val[0]]).concat(val[1])
204
+ result = Halunke::MessageSendNode.new(val[1], MessageNode.new(val[2].nodes))
169
205
  result
170
206
  end
171
207
  .,.,
172
208
 
173
209
  module_eval(<<'.,.,', 'grammar.y', 30)
174
210
  def _reduce_8(val, _values, result)
175
- result = NumberNode.new(val[0])
211
+ result = ArrayNode.new(val[1].nodes)
176
212
  result
177
213
  end
178
214
  .,.,
179
215
 
180
- module_eval(<<'.,.,', 'grammar.y', 31)
216
+ module_eval(<<'.,.,', 'grammar.y', 34)
181
217
  def _reduce_9(val, _values, result)
182
- result = StringNode.new(val[0])
218
+ result = Halunke::ArrayNode.new(val[1].nodes)
183
219
  result
184
220
  end
185
221
  .,.,
186
222
 
187
- module_eval(<<'.,.,', 'grammar.y', 33)
223
+ module_eval(<<'.,.,', 'grammar.y', 38)
188
224
  def _reduce_10(val, _values, result)
189
- result = BarewordNode.new(val[0])
225
+ result = Nodes.new
190
226
  result
191
227
  end
192
228
  .,.,
193
229
 
194
- module_eval(<<'.,.,', 'grammar.y', 34)
230
+ module_eval(<<'.,.,', 'grammar.y', 39)
195
231
  def _reduce_11(val, _values, result)
232
+ result = Nodes.new([val[0]]).concat(val[1])
233
+ result
234
+ end
235
+ .,.,
236
+
237
+ module_eval(<<'.,.,', 'grammar.y', 43)
238
+ def _reduce_12(val, _values, result)
239
+ result = UnassignedNode.new(BarewordNode.new(val[0]))
240
+ result
241
+ end
242
+ .,.,
243
+
244
+ module_eval(<<'.,.,', 'grammar.y', 47)
245
+ def _reduce_13(val, _values, result)
246
+ result = NumberNode.new(val[0])
247
+ result
248
+ end
249
+ .,.,
250
+
251
+ module_eval(<<'.,.,', 'grammar.y', 48)
252
+ def _reduce_14(val, _values, result)
253
+ result = StringNode.new(val[0])
254
+ result
255
+ end
256
+ .,.,
257
+
258
+ module_eval(<<'.,.,', 'grammar.y', 50)
259
+ def _reduce_15(val, _values, result)
196
260
  result = BarewordNode.new(val[0])
197
261
  result
198
262
  end
199
263
  .,.,
200
264
 
265
+ module_eval(<<'.,.,', 'grammar.y', 51)
266
+ def _reduce_16(val, _values, result)
267
+ result = BarewordNode.new(val[0])
268
+ result
269
+ end
270
+ .,.,
271
+
272
+ module_eval(<<'.,.,', 'grammar.y', 52)
273
+ def _reduce_17(val, _values, result)
274
+ result = UnassignedNode.new(BarewordNode.new(val[0]))
275
+ result
276
+ end
277
+ .,.,
278
+
201
279
  def _reduce_none(val, _values, result)
202
280
  val[0]
203
281
  end
@@ -1,41 +1,222 @@
1
1
  # This file is not tested directly right now,
2
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
3
4
  module Halunke
4
- class NativeClass
5
- def initialize(methods)
5
+ class HClass
6
+ def initialize(name, methods)
7
+ @name = name
6
8
  @runtime_methods = methods
7
9
  end
8
10
 
9
- def create_instance(ruby_value)
10
- NativeObject.new(self, ruby_value)
11
+ def create_instance(ruby_value = nil)
12
+ HObject.new(self, ruby_value)
11
13
  end
12
14
 
13
15
  def lookup(message)
14
- @runtime_methods[message]
16
+ @runtime_methods.fetch(message)
17
+ rescue KeyError
18
+ raise "Class #{@name} has no method to respond to message '#{message}'"
15
19
  end
16
20
  end
17
21
 
18
- class NativeObject
22
+ class HObject
19
23
  attr_reader :ruby_value
20
24
 
21
- def initialize(runtime_class, ruby_value)
25
+ def initialize(runtime_class, ruby_value = nil)
22
26
  @runtime_class = runtime_class
23
27
  @ruby_value = ruby_value
24
28
  end
25
29
 
26
- def receive_message(message_name, message_value)
30
+ def receive_message(context, message_name, message_value)
27
31
  m = @runtime_class.lookup(message_name)
28
- m.call(self, message_value)
32
+ m.call(context, [self].concat(message_value))
33
+ end
34
+
35
+ def inspect(context)
36
+ receive_message(context, "inspect", []).ruby_value
29
37
  end
30
38
  end
31
39
 
32
- class NativeFunction
33
- def initialize(fn)
40
+ class HFunction
41
+ def initialize(signature, fn)
42
+ @signature = signature
34
43
  @fn = fn
35
44
  end
36
45
 
37
- def call(receiver, args)
38
- @fn.call(receiver, args)
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
39
103
  end
40
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
+ )
41
222
  end
@@ -1,3 +1,3 @@
1
1
  module Halunke
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: halunke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Dohmen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-03 00:00:00.000000000 Z
11
+ date: 2018-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler