skeem 0.0.27 → 0.0.28

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: a462458401748edba53f3c95f80b56478d7cfeb0
4
- data.tar.gz: bca52ec89e55cfe23c95e644da601fd2557877c8
3
+ metadata.gz: 9c6cb859a4082620c599599f02f5948ee5608d79
4
+ data.tar.gz: 742acc6b351efce05a6d40f7c9b558368c734fd5
5
5
  SHA512:
6
- metadata.gz: fbcbaf830c1ba588cd34700f7ebc4f7815b0972efa8ddd496fbda977538e2d5921cdb88830e880ee2cc4c6a7ecb6f214d903ea945a970b46653d366de22b4fc0
7
- data.tar.gz: 959251339c07128dc76a7557761d915cacea326432bf4ab0e3728d894f63bf2fe609d743ea07b1b0753ca65d728528e2d4fe8b3b246bf381ddd0b74533aca1ca
6
+ metadata.gz: fc51a07506b30450c78fd538a9127926378d6fdc3d165a1a3e075424295876a2727734bc4b969895f6f6bc76ea3f7c6a5e5ea6cdaec9495556a34b3d8e7c8c80
7
+ data.tar.gz: 076b28ff2fc211ed0ae3e2bf3cdfa08f4d220f5682c72f8f59e98dfe84f2555aa9ebbb529e08d94c24349e3845aad836c64eb541c5c2f414f917678fc36f096b
@@ -47,19 +47,34 @@ module Skeem
47
47
 
48
48
  my_result
49
49
  end
50
-
51
- # The number of outer parents the current environment has.
50
+
51
+ # The number of outer parents the current environment has.
52
52
  # @return [Integer] The nesting levels
53
53
  def depth
54
54
  count = 0
55
-
55
+
56
56
  curr_env = self
57
57
  while curr_env.outer
58
58
  count += 1
59
59
  curr_env = curr_env.outer
60
60
  end
61
-
61
+
62
62
  count
63
63
  end
64
+
65
+ def inspect
66
+ result = ''
67
+ if outer
68
+ result << outer.inspect
69
+ else
70
+ return "\n"
71
+ end
72
+ result << "\n----\n"
73
+ bindings.each_pair do |key, expr|
74
+ result << "#{key.inspect} => #{expr.inspect}\n"
75
+ end
76
+
77
+ result
78
+ end
64
79
  end # class
65
80
  end # module
@@ -164,7 +164,14 @@ module Skeem
164
164
  first_one = arglist.first.evaluate(runtime)
165
165
  raw_result = first_one.value
166
166
  operands = evaluate_tail(arglist, runtime)
167
+ begin
167
168
  operands.each { |elem| raw_result *= elem.value }
169
+ rescue NoMethodError => exc
170
+ # $stderr.puts aRuntime.environment.inspect
171
+ # $stderr.puts first_one.inspect
172
+ # $stderr.puts operands.inspect
173
+ raise exc
174
+ end
168
175
  to_datum(raw_result)
169
176
  end
170
177
  end
data/lib/skeem/runtime.rb CHANGED
@@ -3,7 +3,10 @@ require_relative 'environment'
3
3
 
4
4
  module Skeem
5
5
  class Runtime
6
+ # @return [Environment]
6
7
  attr_reader(:environment)
8
+
9
+ # @return [Array<ProcedureCall>] The call stack
7
10
  attr_reader(:call_stack)
8
11
 
9
12
  def initialize(anEnvironment)
@@ -14,7 +17,7 @@ module Skeem
14
17
  def include?(anIdentifier)
15
18
  environment.include?(normalize_key(anIdentifier))
16
19
  end
17
-
20
+
18
21
  def fetch(aKey)
19
22
  key_value = normalize_key(aKey)
20
23
  include?(key_value) ? environment.fetch(key_value) : nil
@@ -28,14 +31,24 @@ module Skeem
28
31
  key_value = normalize_key(aKey)
29
32
  if include?(key_value)
30
33
  entry = environment.fetch(key_value)
31
- case entry
32
- when Primitive::PrimitiveProcedure
33
- entry
34
- when SkmDefinition
35
- entry.expression.evaluate(self)
36
- else
37
- raise StandardError, entry.inspect
34
+ result = nil
35
+ begin
36
+ case entry
37
+ when Primitive::PrimitiveProcedure
38
+ result = entry
39
+ when SkmDefinition
40
+ result = entry.expression.evaluate(self)
41
+ else
42
+ raise StandardError, entry.inspect
43
+ end
44
+ rescue NoMethodError => exc
45
+ # $stderr.puts 'In rescue block'
46
+ # $stderr.puts key_value.inspect
47
+ # $stderr.puts entry.inspect
48
+ # $stderr.puts entry.expression.inspect
49
+ raise exc
38
50
  end
51
+ result
39
52
  else
40
53
  err = StandardError
41
54
  key = aKey.kind_of?(SkmIdentifier) ? aKey.value : key_value
@@ -43,7 +56,7 @@ module Skeem
43
56
  raise err, err_msg
44
57
  end
45
58
  end
46
-
59
+
47
60
  # @param aList[SkmList] first member is an identifier.
48
61
  def evaluate_form(aList)
49
62
  # TODO: manage the cases where first_member is a keyword
@@ -69,30 +82,35 @@ module Skeem
69
82
 
70
83
  def push(anEnvironment)
71
84
  @environment = anEnvironment
72
- end
73
-
85
+ end
86
+
74
87
  # Make the outer enviromnent thecurrent one inside the provided block
75
88
  def pop
76
89
  env = environment
77
90
  @environment = environment.outer
78
91
  env
79
92
  end
80
-
93
+
81
94
  def push_call(aProcCall)
82
95
  if aProcCall.kind_of?(ProcedureCall)
83
96
  call_stack.push(aProcCall)
84
97
  else
85
98
  raise StandardError, "Invalid call object #{aProcCall.inspect}"
86
99
  end
100
+ # $stderr.puts 'CALL STACK vvvv'
101
+ call_stack.each do |proc_call|
102
+ # $stderr.puts proc_call.inspect
103
+ end
104
+ # $stderr.puts 'CALL STACK ^^^^'
87
105
  end
88
-
106
+
89
107
  def pop_call()
90
108
  if call_stack.empty?
91
109
  raise StandardError, 'Skeem call stack empty!'
92
110
  end
93
111
  call_stack.pop
94
112
  end
95
-
113
+
96
114
  def caller(index = -1)
97
115
  call_stack[index]
98
116
  end
@@ -68,7 +68,7 @@ module Skeem
68
68
  end
69
69
  end
70
70
  else
71
- # INFINITE LOOP DANGER: definition of 'x' is a reference to 'x'!
71
+ # INFINITE LOOP DANGER: definition of 'x' has a reference to 'x'!
72
72
  # Way out: the lookup for the reference should start from outer
73
73
  # environment.
74
74
  env = aRuntime.pop
@@ -96,11 +96,14 @@ module Skeem
96
96
 
97
97
  # call method should only invoked when the expression is a SkmLambda
98
98
  def call(aRuntime, aProcedureCall)
99
- unless [SkmLambda, Primitive::PrimitiveProcedure].include?(expression.class)
100
- err_msg = "Expected a SkmLambda instead of #{expression.class}"
99
+ expr = expression
100
+ expr = expr.evaluate(aRuntime) if expr.kind_of?(SkmVariableReference)
101
+ unless [SkmLambda, Primitive::PrimitiveProcedure].include?(expr.class)
102
+ err_msg = "Expected a SkmLambda instead of #{expr.class}"
101
103
  raise StandardError, err_msg
102
104
  end
103
- expression.call(aRuntime, aProcedureCall)
105
+ # $stderr.puts "SkmDefinition#call #{aProcedureCall.inspect}"
106
+ expr.call(aRuntime, aProcedureCall)
104
107
  end
105
108
 
106
109
  def inspect
@@ -146,13 +149,14 @@ module Skeem
146
149
  end
147
150
  begin
148
151
  aRuntime.include?(var_key.value)
149
- rescue NoMethodError
150
- $stderr.puts "VVVVVVVVVVVVVVV"
151
- $stderr.puts 'var_key: ' + var_key.inspect
152
- $stderr.puts 'operator: ' + operator.inspect
153
- $stderr.puts 'operands: ' + operands.inspect
154
- $stderr.puts 'operands_consumed: ' + operands_consumed.inspect
155
- $stderr.puts "^^^^^^^^^^^^^^^"
152
+ rescue NoMethodError => exc
153
+ # $stderr.puts "VVVVVVVVVVVVVVV"
154
+ # $stderr.puts 'var_key: ' + var_key.inspect
155
+ # $stderr.puts 'operator: ' + operator.inspect
156
+ # $stderr.puts 'operands: ' + operands.inspect
157
+ # $stderr.puts 'operands_consumed: ' + operands_consumed.inspect
158
+ # $stderr.puts "^^^^^^^^^^^^^^^"
159
+ raise exc
156
160
  end
157
161
  unless aRuntime.include?(var_key.value)
158
162
  err = StandardError
@@ -162,11 +166,13 @@ module Skeem
162
166
  end
163
167
  procedure = aRuntime.environment.fetch(var_key.value)
164
168
  end
165
- # $stderr.puts "## In ProcCall #{var_key.value} #############"
166
- # $stderr.puts 'operator: ' + operator.inspect
167
- # $stderr.puts 'operands: ' + operands.inspect
168
- # $stderr.puts "## CALL(#{var_key.value}) ###################"
169
- # $stderr.puts 'callee: ' + procedure.inspect
169
+ unless var_key.nil?
170
+ # $stderr.puts "## In ProcCall #{var_key.value} #############"
171
+ # $stderr.puts 'operator: ' + operator.inspect
172
+ # $stderr.puts 'operands: ' + operands.inspect
173
+ # $stderr.puts "## CALL(#{var_key.value}) ###################"
174
+ # $stderr.puts 'callee: ' + procedure.inspect
175
+ end
170
176
  result = procedure.call(aRuntime, self)
171
177
  operands_consumed = true
172
178
  aRuntime.pop_call
@@ -321,7 +327,8 @@ module Skeem
321
327
  end
322
328
 
323
329
  def evaluate(aRuntime)
324
- formals.evaluate(aRuntime)
330
+ # formals.evaluate(aRuntime)
331
+ self
325
332
  end
326
333
  =begin
327
334
  TODO
@@ -336,7 +343,9 @@ module Skeem
336
343
  def call(aRuntime, aProcedureCall)
337
344
  aRuntime.nest
338
345
  bind_locals(aRuntime, aProcedureCall)
346
+ # $stderr.puts 'LOCALS vvvvvvvvvvv'
339
347
  # $stderr.puts aRuntime.environment.inspect
348
+ # $stderr.puts 'LOCALS ^^^^^^^^^^^'
340
349
  result = evaluate_defs(aRuntime)
341
350
  result = evaluate_sequence(aRuntime)
342
351
  aRuntime.unnest
@@ -391,6 +400,7 @@ module Skeem
391
400
  a_def = SkmDefinition.new(position, variadic_arg_name, args_coll)
392
401
  a_def.evaluate(aRuntime)
393
402
  end
403
+ aProcedureCall.operands_consumed = true
394
404
  end
395
405
 
396
406
  def evaluate_defs(aRuntime)
@@ -402,8 +412,16 @@ module Skeem
402
412
  if sequence
403
413
  sequence.each do |cmd|
404
414
  if cmd.kind_of?(SkmLambda)
405
- aRuntime.caller(-2).operands_consumed = true
406
- result = cmd.call(aRuntime, aRuntime.caller(-2))
415
+ caller_index = -2
416
+ loop do
417
+ raise StandardError, "Missing argument" unless aRuntime.caller(caller_index)
418
+ unless aRuntime.caller(caller_index).operands_consumed
419
+ aRuntime.caller(caller_index).operands_consumed = true
420
+ result = cmd.call(aRuntime, aRuntime.caller(caller_index))
421
+ break
422
+ end
423
+ caller_index -= 1
424
+ end
407
425
  else
408
426
  result = cmd.evaluate(aRuntime)
409
427
  end
@@ -413,9 +431,11 @@ module Skeem
413
431
  result
414
432
  end
415
433
 
434
+ # Purpose: bind each formal from lambda to an actual value from the call
416
435
  def bind_required_locals(aRuntime, aProcedureCall)
417
436
  max_index = required_arity - 1
418
437
  actuals = aProcedureCall.operands.members
438
+ formal_names = formals.formals.map(&:value)
419
439
 
420
440
  formals.formals.each_with_index do |arg_name, index|
421
441
  arg = actuals[index]
@@ -430,8 +450,13 @@ module Skeem
430
450
  # IMPORTANT: execute procedure call in argument list now
431
451
  arg = arg.evaluate(aRuntime) if arg.kind_of?(ProcedureCall)
432
452
  a_def = SkmDefinition.new(position, arg_name, arg)
433
- a_def.evaluate(aRuntime)
434
- # $stderr.puts "LOCAL #{a_def.inspect}"
453
+ # $stderr.puts "Procedure call #{aProcedureCall.operator.inspect}"
454
+ # $stderr.puts "LOCAL #{arg_name.value} #{arg.inspect}"
455
+ if arg.kind_of?(SkmVariableReference) && !formal_names.include?(arg.value)
456
+ aRuntime.define(arg_name, a_def)
457
+ else
458
+ a_def.evaluate(aRuntime)
459
+ end
435
460
  break if index >= max_index
436
461
  end
437
462
  end
@@ -88,13 +88,14 @@ module Skeem
88
88
 
89
89
  class SkmVariableReference < SkmUnaryExpression
90
90
  alias variable child
91
-
91
+
92
92
  def eqv?(other)
93
93
  child == other.child
94
94
  end
95
95
 
96
96
  def evaluate(aRuntime)
97
97
  var_key = variable.evaluate(aRuntime)
98
+ # $stderr.puts "Variable #{variable.inspect}"
98
99
  aRuntime.evaluate(var_key)
99
100
  end
100
101
 
data/lib/skeem/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Skeem
2
- VERSION = '0.0.27'.freeze
2
+ VERSION = '0.0.28'.freeze
3
3
  end
@@ -621,6 +621,24 @@ SKEEM
621
621
  result = subject.run(source)
622
622
  expect(result.last.members).to eq([25])
623
623
  end
624
+
625
+ it 'should implement lambda that calls second-order functions' do
626
+ source = <<-SKEEM
627
+ (define twice
628
+ (lambda (x)
629
+ (* 2 x)))
630
+ (define compose
631
+ (lambda (f g)
632
+ (lambda (x)
633
+ (f (g x)))))
634
+ (define repeat
635
+ (lambda (f)
636
+ (compose f f)))
637
+ ((repeat twice) 5)
638
+ SKEEM
639
+ result = subject.run(source)
640
+ expect(result.members.last).to eq(20)
641
+ end
624
642
  end # context
625
643
  end # describe
626
644
  end # module
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skeem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.27
4
+ version: 0.0.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-03 00:00:00.000000000 Z
11
+ date: 2018-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley