skeem 0.0.23 → 0.0.24

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,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