skeem 0.0.23 → 0.0.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,10 @@
1
1
  require_relative 'primitive_procedure'
2
- require_relative '../convertible'
2
+ require_relative '../datum_dsl'
3
3
 
4
4
  module Skeem
5
5
  module Primitive
6
6
  module PrimitiveBuilder
7
- include Convertible
7
+ include DatumDSL
8
8
  def add_primitives(aRuntime)
9
9
  add_arithmetic(aRuntime)
10
10
  add_comparison(aRuntime)
@@ -73,6 +73,7 @@ module Skeem
73
73
  def add_string_procedures(aRuntime)
74
74
  create_object_predicate(aRuntime, 'string?')
75
75
  create_string_append(aRuntime)
76
+ create_string_length(aRuntime)
76
77
  create_string2symbol(aRuntime)
77
78
  end
78
79
 
@@ -105,13 +106,13 @@ module Skeem
105
106
  # arglist should be a Ruby Array
106
107
  primitive = ->(runtime, arglist) do
107
108
  if arglist.empty?
108
- to_skm(0)
109
+ integer(0)
109
110
  else
110
111
  first_one = arglist.first.evaluate(runtime)
111
112
  raw_result = first_one.value
112
113
  operands = evaluate_tail(arglist, runtime)
113
114
  operands.each { |elem| raw_result += elem.value }
114
- to_skm(raw_result)
115
+ to_datum(raw_result)
115
116
  end
116
117
  end
117
118
  define_primitive_proc(aRuntime, '+', zero_or_more, primitive)
@@ -127,7 +128,7 @@ module Skeem
127
128
  operands = evaluate_array(arglist, runtime)
128
129
  operands.each { |elem| raw_result -= elem.value }
129
130
  end
130
- to_skm(raw_result)
131
+ to_datum(raw_result)
131
132
  end
132
133
 
133
134
  define_primitive_proc(aRuntime, '-', one_or_more, primitive)
@@ -136,13 +137,13 @@ module Skeem
136
137
  def create_multiply(aRuntime)
137
138
  primitive = ->(runtime, arglist) do
138
139
  if arglist.empty?
139
- to_skm(1)
140
+ integer(1)
140
141
  else
141
142
  first_one = arglist.first.evaluate(runtime)
142
143
  raw_result = first_one.value
143
144
  operands = evaluate_tail(arglist, runtime)
144
145
  operands.each { |elem| raw_result *= elem.value }
145
- to_skm(raw_result)
146
+ to_datum(raw_result)
146
147
  end
147
148
  end
148
149
  define_primitive_proc(aRuntime, '*', zero_or_more, primitive)
@@ -166,7 +167,7 @@ module Skeem
166
167
  end
167
168
  end
168
169
  end
169
- to_skm(raw_result)
170
+ to_datum(raw_result)
170
171
  end
171
172
 
172
173
  define_primitive_proc(aRuntime, '/', one_or_more, primitive)
@@ -177,7 +178,7 @@ module Skeem
177
178
  operand_1 = argument1.evaluate(runtime)
178
179
  operand_2 = argument2.evaluate(runtime)
179
180
  raw_result = operand_1.value.modulo(operand_2.value)
180
- to_skm(raw_result)
181
+ to_datum(raw_result)
181
182
  end
182
183
 
183
184
  define_primitive_proc(aRuntime, 'floor-remainder', binary, primitive)
@@ -187,12 +188,12 @@ module Skeem
187
188
  primitive = ->(runtime, first_operand, arglist) do
188
189
  first_one = first_operand.evaluate(runtime)
189
190
  if arglist.empty?
190
- to_skm(true)
191
+ boolean(true)
191
192
  else
192
193
  operands = evaluate_array(arglist, runtime)
193
194
  first_value = first_one.value
194
195
  all_equal = operands.all? { |elem| first_value == elem.value }
195
- to_skm(all_equal)
196
+ boolean(all_equal)
196
197
  end
197
198
  end
198
199
 
@@ -202,7 +203,7 @@ module Skeem
202
203
  def create_lt(aRuntime)
203
204
  primitive = ->(runtime, first_operand, arglist) do
204
205
  if arglist.empty?
205
- to_skm(false)
206
+ boolean(false)
206
207
  else
207
208
  operands = [first_operand.evaluate(runtime)]
208
209
  operands.concat(evaluate_array(arglist, runtime))
@@ -210,7 +211,7 @@ module Skeem
210
211
  operands.each_cons(2) do |(elem1, elem2)|
211
212
  result &&= elem1.value < elem2.value
212
213
  end
213
- to_skm(result)
214
+ boolean(result)
214
215
  end
215
216
  end
216
217
 
@@ -220,7 +221,7 @@ module Skeem
220
221
  def create_gt(aRuntime)
221
222
  primitive = ->(runtime, first_operand, arglist) do
222
223
  if arglist.empty?
223
- to_skm(false)
224
+ boolean(false)
224
225
  else
225
226
  operands = [first_operand.evaluate(runtime)]
226
227
  operands.concat(evaluate_array(arglist, runtime))
@@ -228,7 +229,7 @@ module Skeem
228
229
  operands.each_cons(2) do |(elem1, elem2)|
229
230
  result &&= elem1.value > elem2.value
230
231
  end
231
- to_skm(result)
232
+ boolean(result)
232
233
  end
233
234
  end
234
235
 
@@ -238,7 +239,7 @@ module Skeem
238
239
  def create_lte(aRuntime)
239
240
  primitive = ->(runtime, first_operand, arglist) do
240
241
  if arglist.empty?
241
- to_skm(true)
242
+ boolean(true)
242
243
  else
243
244
  operands = [first_operand.evaluate(runtime)]
244
245
  operands.concat(evaluate_array(arglist, runtime))
@@ -246,7 +247,7 @@ module Skeem
246
247
  operands.each_cons(2) do |(elem1, elem2)|
247
248
  result &&= elem1.value <= elem2.value
248
249
  end
249
- to_skm(result)
250
+ boolean(result)
250
251
  end
251
252
  end
252
253
 
@@ -256,7 +257,7 @@ module Skeem
256
257
  def create_gte(aRuntime)
257
258
  primitive = ->(runtime, first_operand, arglist) do
258
259
  if arglist.empty?
259
- to_skm(true)
260
+ boolean(true)
260
261
  else
261
262
  operands = [first_operand.evaluate(runtime)]
262
263
  operands.concat(evaluate_array(arglist, runtime))
@@ -264,7 +265,7 @@ module Skeem
264
265
  operands.each_cons(2) do |(elem1, elem2)|
265
266
  result &&= elem1.value >= elem2.value
266
267
  end
267
- to_skm(result)
268
+ boolean(result)
268
269
  end
269
270
  end
270
271
 
@@ -276,7 +277,7 @@ module Skeem
276
277
  primitive = ->(runtime, arg) do
277
278
  arg_evaluated = arg.evaluate(runtime)
278
279
  check_argtype(arg_evaluated, SkmNumber, 'number', 'number->string')
279
- to_skm(arg_evaluated.value.to_s)
280
+ string(arg_evaluated.value)
280
281
  end
281
282
 
282
283
  define_primitive_proc(aRuntime, 'number->string', unary, primitive)
@@ -286,9 +287,9 @@ module Skeem
286
287
  primitive = ->(runtime, arg) do
287
288
  arg_evaluated = arg.evaluate(runtime)
288
289
  if arg_evaluated.boolean? && arg_evaluated.value == false
289
- to_skm(true)
290
+ boolean(true)
290
291
  else
291
- to_skm(false)
292
+ boolean(false)
292
293
  end
293
294
  end
294
295
 
@@ -299,7 +300,7 @@ module Skeem
299
300
  # arglist should be a Ruby Array
300
301
  primitive = ->(runtime, arglist) do
301
302
  if arglist.empty?
302
- to_skm(true) # in conformance with 4.2.1
303
+ boolean(true) # in conformance with 4.2.1
303
304
  else
304
305
  raw_result = true
305
306
  last_result = nil
@@ -310,7 +311,7 @@ module Skeem
310
311
  break unless raw_result
311
312
  end
312
313
  raw_result = last_result if raw_result
313
- to_skm(raw_result)
314
+ to_datum(raw_result)
314
315
  end
315
316
  end
316
317
  define_primitive_proc(aRuntime, 'and', zero_or_more, primitive)
@@ -320,7 +321,7 @@ module Skeem
320
321
  # arglist should be a Ruby Array
321
322
  primitive = ->(runtime, arglist) do
322
323
  if arglist.empty?
323
- to_skm(false) # in conformance with 4.2.1
324
+ boolean(false) # in conformance with 4.2.1
324
325
  else
325
326
  raw_result = false
326
327
  last_result = nil
@@ -331,12 +332,12 @@ module Skeem
331
332
  break if raw_result
332
333
  end
333
334
  raw_result = last_result if raw_result
334
- to_skm(raw_result)
335
+ to_datum(raw_result)
335
336
  end
336
337
  end
337
338
  define_primitive_proc(aRuntime, 'or', zero_or_more, primitive)
338
339
  end
339
-
340
+
340
341
  def create_string_append(aRuntime)
341
342
  primitive = ->(runtime, arglist) do
342
343
  if arglist.empty?
@@ -346,17 +347,27 @@ module Skeem
346
347
  value = parts.reduce('') { |interim, substr| interim << substr.value }
347
348
  end
348
349
 
349
- SkmString.create(value)
350
+ string(value)
351
+ end
352
+
353
+ define_primitive_proc(aRuntime, 'string-append', zero_or_more, primitive)
354
+ end
355
+
356
+ def create_string_length(aRuntime)
357
+ primitive = ->(runtime, arg) do
358
+ arg_evaluated = arg.evaluate(runtime)
359
+ check_argtype(arg_evaluated, SkmString, 'string', 'string-length')
360
+ integer(arg_evaluated.length)
350
361
  end
351
362
 
352
- define_primitive_proc(aRuntime, 'string-append', zero_or_more, primitive)
363
+ define_primitive_proc(aRuntime, 'string-length', unary, primitive)
353
364
  end
354
365
 
355
366
  def create_string2symbol(aRuntime)
356
367
  primitive = ->(runtime, arg) do
357
368
  arg_evaluated = arg.evaluate(runtime)
358
369
  check_argtype(arg_evaluated, SkmString, 'string', 'string->symbol')
359
- SkmIdentifier.create(arg_evaluated.value)
370
+ identifier(arg_evaluated)
360
371
  end
361
372
 
362
373
  define_primitive_proc(aRuntime, 'string->symbol', unary, primitive)
@@ -366,7 +377,7 @@ module Skeem
366
377
  primitive = ->(runtime, arg) do
367
378
  arg_evaluated = arg.evaluate(runtime)
368
379
  check_argtype(arg_evaluated, SkmList, 'list', 'length')
369
- to_skm(arg_evaluated.length)
380
+ integer(arg_evaluated.length)
370
381
  end
371
382
 
372
383
  define_primitive_proc(aRuntime, 'length', unary, primitive)
@@ -380,7 +391,7 @@ module Skeem
380
391
  elements = evaluate_array(arglist, aRuntime)
381
392
  end
382
393
 
383
- SkmVector.new(elements)
394
+ vector(elements)
384
395
  end
385
396
 
386
397
  define_primitive_proc(aRuntime, 'vector', zero_or_more, primitive)
@@ -390,7 +401,7 @@ module Skeem
390
401
  primitive = ->(runtime, arg) do
391
402
  arg_evaluated = arg.evaluate(runtime)
392
403
  check_argtype(arg_evaluated, SkmVector, 'vector', 'vector-length')
393
- to_skm(arg_evaluated.length)
404
+ integer(arg_evaluated.length)
394
405
  end
395
406
 
396
407
  define_primitive_proc(aRuntime, 'vector-length', unary, primitive)
@@ -404,8 +415,8 @@ module Skeem
404
415
  index = anIndex.evaluate(runtime)
405
416
  check_argtype(index, SkmInteger, 'integer', 'vector-ref')
406
417
  # TODO: index checking
407
- raw_result = vector.elements[index.value]
408
- to_skm(raw_result)
418
+ raw_result = vector.members[index.value]
419
+ to_datum(raw_result) # What if non-datum result?
409
420
  end
410
421
 
411
422
  define_primitive_proc(aRuntime, 'vector-ref', binary, primitive)
@@ -432,13 +443,12 @@ module Skeem
432
443
  msg_name = predicate_name if msg_name.nil?
433
444
  primitive = ->(runtime, arg) do
434
445
  arg_evaluated = arg.evaluate(runtime)
435
- to_skm(arg_evaluated.send(msg_name))
446
+ to_datum(arg_evaluated.send(msg_name))
436
447
  end
437
448
 
438
449
  define_primitive_proc(aRuntime, predicate_name, unary, primitive)
439
450
  end
440
451
 
441
-
442
452
  def def_procedure(aRuntime, pairs)
443
453
  pairs.each_slice(2) do |(name, code)|
444
454
  func = PrimitiveProcedure.new(name, code)
data/lib/skeem/runtime.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require_relative 's_expr_nodes'
2
+ require_relative 'environment'
3
+
1
4
  module Skeem
2
5
  class Runtime
3
6
  attr_reader(:environment)
@@ -13,29 +16,50 @@ module Skeem
13
16
  def define(aKey, anEntry)
14
17
  environment.define(normalize_key(aKey), anEntry)
15
18
  end
19
+
20
+ def evaluate(aKey)
21
+ key_value = normalize_key(aKey)
22
+ if include?(key_value)
23
+ definition = environment.fetch(key_value)
24
+ definition.expression.evaluate(self)
25
+ else
26
+ err = StandardError
27
+ key = aKey.kind_of?(SkmIdentifier) ? aKey.value : key_value
28
+ err_msg = "Unbound variable: '#{key}'"
29
+ raise err, err_msg
30
+ end
31
+ end
16
32
 
33
+ # @param aList[SkmList] first member is an identifier.
34
+ def evaluate_form(aList)
35
+ # TODO: manage the cases where first_member is a keyword
36
+ first_member = aList.first
37
+ invokation = ProcedureCall.new(nil, first_member, aList.tail.members)
38
+ invokation.evaluate(self)
39
+ end
40
+
17
41
  def nest()
18
42
  nested = Environment.new(environment)
19
43
  @environment = nested
20
44
  end
21
-
45
+
22
46
  def unnest()
23
47
  raise StandardError, 'Cannot unnest environment' unless environment.outer
24
48
  environment.bindings.clear
25
49
  @environment = environment.outer
26
50
  end
27
-
51
+
28
52
  def depth()
29
53
  return environment.depth
30
54
  end
31
-
55
+
32
56
  # Make the outer enviromnent thecurrent one inside the provided block
33
57
  def pop
34
58
  env = environment
35
59
  @environment = environment.outer
36
60
  env
37
61
  end
38
-
62
+
39
63
  def push(anEnvironment)
40
64
  @environment = anEnvironment
41
65
  end
@@ -74,37 +74,37 @@ module Skeem
74
74
  def reduce_variable_reference(_production, aRange, _tokens, theChildren)
75
75
  SkmVariableReference.new(aRange, theChildren[0])
76
76
  end
77
-
78
- # rule('quotation' => 'APOSTROPHE datum').as 'quotation_abbrev'
79
- def reduce_quotation_abbrev(_production, aRange, _tokens, theChildren)
77
+
78
+ # rule('quotation' => 'APOSTROPHE datum').as 'quotation_short'
79
+ def reduce_quotation_short(_production, aRange, _tokens, theChildren)
80
80
  SkmQuotation.new(theChildren[1])
81
- end
81
+ end
82
82
 
83
83
  # rule('quotation' => 'LPAREN QUOTE datum RPAREN').as 'quotation'
84
84
  def reduce_quotation(_production, aRange, _tokens, theChildren)
85
85
  SkmQuotation.new(theChildren[2])
86
86
  end
87
-
87
+
88
88
  # rule('list' => 'LPAREN datum_star RPAREN').as 'list'
89
89
  def reduce_list(_production, aRange, _tokens, theChildren)
90
90
  SkmList.new(theChildren[1])
91
- end
92
-
91
+ end
92
+
93
93
  # rule('vector' => 'VECTOR_BEGIN datum_star RPAREN').as 'vector'
94
94
  def reduce_vector(_production, aRange, _tokens, theChildren)
95
95
  SkmVector.new(theChildren[1])
96
- end
97
-
96
+ end
97
+
98
98
  # rule('datum_star' => 'datum_star datum').as 'datum_star'
99
99
  def reduce_datum_star(_production, aRange, _tokens, theChildren)
100
100
  theChildren[0] << theChildren[1]
101
- end
102
-
101
+ end
102
+
103
103
  # rule('datum_star' => []).as 'no_datum_yet'
104
104
  def reduce_no_datum_yet(_production, aRange, _tokens, theChildren)
105
105
  []
106
106
  end
107
-
107
+
108
108
  # rule('procedure_call' => 'LPAREN operator RPAREN').as 'proc_call_nullary'
109
109
  def reduce_proc_call_nullary(_production, aRange, _tokens, theChildren)
110
110
  ProcedureCall.new(aRange, theChildren[1], [])
@@ -129,24 +129,24 @@ module Skeem
129
129
  def reduce_last_operand(_production, _range, _tokens, theChildren)
130
130
  [theChildren.last]
131
131
  end
132
-
132
+
133
133
  # rule('def_formals' => 'identifier_star').as 'def_formals'
134
134
  def reduce_def_formals(_production, _range, _tokens, theChildren)
135
135
  SkmFormals.new(theChildren[0], :fixed)
136
- end
137
-
136
+ end
137
+
138
138
  # rule('def_formals' => 'identifier_star PERIOD identifier').as 'pair_formals'
139
139
  def reduce_pair_formals(_production, _range, _tokens, theChildren)
140
140
  formals = theChildren[0] << theChildren[2]
141
- SkmFormals.new(formals, :variadic)
142
- end
143
-
141
+ SkmFormals.new(formals, :variadic)
142
+ end
143
+
144
144
  # rule('lambda_expression' => 'LPAREN LAMBDA formals body RPAREN').as 'lambda_expression'
145
145
  def reduce_lambda_expression(_production, aRange, _tokens, theChildren)
146
146
  lmbd = SkmLambda.new(aRange, theChildren[2], theChildren[3])
147
147
  # $stderr.puts lmbd.inspect
148
148
  lmbd
149
- end
149
+ end
150
150
 
151
151
  # rule('formals' => 'LPAREN identifier_star RPAREN').as 'fixed_arity_formals'
152
152
  def reduce_fixed_arity_formals(_production, _range, _tokens, theChildren)
@@ -157,12 +157,12 @@ module Skeem
157
157
  def reduce_variadic_formals(_production, _range, _tokens, theChildren)
158
158
  SkmFormals.new([theChildren[0]], :variadic)
159
159
  end
160
-
160
+
161
161
  # rule('formals' => 'LPAREN identifier_plus PERIOD IDENTIFIER RPAREN').as 'dotted_formals'
162
162
  def reduce_dotted_formals(_production, _range, _tokens, theChildren)
163
163
  formals = theChildren[1] << theChildren[3]
164
164
  SkmFormals.new(formals, :variadic)
165
- end
165
+ end
166
166
 
167
167
  # rule('identifier_star' => 'identifier_star IDENTIFIER').as 'identifier_star'
168
168
  def reduce_identifier_star(_production, _range, _tokens, theChildren)
@@ -173,16 +173,16 @@ module Skeem
173
173
  def reduce_no_identifier_yet(_production, _range, _tokens, theChildren)
174
174
  []
175
175
  end
176
-
176
+
177
177
  # rule('identifier_plus' => 'identifier_plus IDENTIFIER').as 'multiple_identifiers'
178
178
  def reduce_multiple_identifiers(_production, _range, _tokens, theChildren)
179
179
  theChildren[0] << theChildren[1]
180
- end
181
-
180
+ end
181
+
182
182
  # rule('identifier_plus' => 'IDENTIFIER').as 'last_identifier'
183
183
  def reduce_last_identifier(_production, _range, _tokens, theChildren)
184
184
  [theChildren[0]]
185
- end
185
+ end
186
186
 
187
187
  # rule('body' => 'definition_star sequence').as 'body'
188
188
  def reduce_body(_production, _range, _tokens, theChildren)
@@ -209,6 +209,45 @@ module Skeem
209
209
  def reduce_conditional(_production, aRange, _tokens, theChildren)
210
210
  SkmCondition.new(aRange, theChildren[2], theChildren[3], theChildren[4])
211
211
  end
212
+
213
+ # rule('quasiquotation' => 'LPAREN QUASIQUOTE qq_template RPAREN').as 'quasiquotation'
214
+ def reduce_quasiquotation(_production, aRange, _tokens, theChildren)
215
+ SkmQuasiquotation.new(theChildren[2])
216
+ end
217
+
218
+ # rule('quasiquotation' => 'GRAVE_ACCENT qq_template').as 'quasiquotation_short'
219
+ def reduce_quasiquotation_short(_production, aRange, _tokens, theChildren)
220
+ # $stderr.puts theChildren[1].inspect
221
+ SkmQuasiquotation.new(theChildren[1])
222
+ end
223
+
224
+ # rule('list_qq_template' => 'LPAREN qq_template_or_splice_star RPAREN').as 'list_qq'
225
+ def reduce_list_qq(_production, _range, _tokens, theChildren)
226
+ SkmList.new(theChildren[1])
227
+ end
228
+
229
+ # rule('vector_qq_template' => 'VECTOR_BEGIN qq_template_or_splice_star RPAREN').as 'vector_qq'
230
+ def reduce_vector_qq(_production, _range, _tokens, theChildren)
231
+ SkmVector.new(theChildren[1])
232
+ end
233
+
234
+ # rule('unquotation' => 'COMMA qq_template').as 'unquotation_short'
235
+ def reduce_unquotation_short(_production, aRange, _tokens, theChildren)
236
+ SkmUnquotation.new(theChildren[1])
237
+ end
238
+
239
+
240
+ # rule('qq_template_or_splice_star' => 'qq_template_or_splice_star qq_template_or_splice').as 'multiple_template_splice'
241
+ def reduce_multiple_template_splice(_production, _range, _tokens, theChildren)
242
+ theChildren[0] << theChildren[1]
243
+ end
244
+
245
+ # rule('qq_template_or_splice_star' => []).as 'no_template_splice_yet'
246
+ def reduce_no_template_splice_yet(_production, _range, _tokens, theChildren)
247
+ []
248
+ end
249
+
250
+
212
251
  end # class
213
252
  end # module
214
253
  # End of file