skeem 0.0.14 → 0.0.15

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: 4738bc3d483df0325cce143200b02e5c8cac7afe
4
- data.tar.gz: 8f4560eaa88c6e754bd423bdf3c1f62a35063b75
3
+ metadata.gz: 17793fa7c6e636874b0d7fe8515d745b7ff664af
4
+ data.tar.gz: f24f83ad056e1af1ecac866e2daa649c94e544e6
5
5
  SHA512:
6
- metadata.gz: 99e55d28f19fe7d4cb9a2d18a066a12fa43ffc2dfe59b1e5ac3e2795202c67b122e0fce2a9862871accb936eb58320870588c7eb622b4ee714c3e7bcb22eb5bc
7
- data.tar.gz: 12e216d00ceb2e16ca2d27711bc47449e0ff49438ad9b42d52ae677368624cf15c3c80babef8a70aa740e0cdee8b619697aae871fb2962767e87af2f633068c0
6
+ metadata.gz: 64d9feba80f8ac945161c326a8783cdd34babf4f46bbec94020192ad7643a408be059c72e922bf452387dff253708d2b855d7adbac93b9bb9fff0cf4f354bbce
7
+ data.tar.gz: 00f745fc5abeaa2f1f6d83007b21bc0cb7a4fbc3974d79f71be89c19324857a543339328d406a04ca5dd130e36c789c163e3b982c3be87b879b1978fbb277492
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.0.15] - 2018-09-30
2
+ Recursive functions are now supported.
3
+ Interpreter pre-loads a Scheme file with standard procedures (zero?, positive?, negative?, abs)
4
+
5
+ ### Added
6
+ - File `base.skm` with standard Scheme procedures `zero?`, `positive?`, `negative?`, `abs`
7
+
8
+ ### Changed
9
+ - Class `Interpreter#initialize` now execute a Scheme file containing a number of standard procedures.
10
+ - File `README.md` Added third demo snippet showing example of recursive lambda function.
11
+
12
+ ### Fixed
13
+ - Method `SkmLambda#bind_locals` now execute any procedure call in argument list before executing the lambda itself.
14
+
1
15
  ## [0.0.14] - 2018-09-23
2
16
  Added `lambda` (anonymous function). This is an initial implementation that doesn't support recursion yet.
3
17
 
data/README.md CHANGED
@@ -55,7 +55,6 @@ At this stage, the gem consists of a bare-bones interpreter.
55
55
  ```
56
56
 
57
57
  ### Example 2 (Defining a function)
58
- Remark: Skeem 0.0.14 doesn't support recursive functions yet.
59
58
 
60
59
  ```ruby
61
60
  require 'skeem'
@@ -79,6 +78,21 @@ Remark: Skeem 0.0.14 doesn't support recursive functions yet.
79
78
  result = schemer.run(scheme_code)
80
79
  puts result.value # => 3
81
80
  ```
81
+ ### Example 3 (Defining a recursive function)
82
+ ```ruby
83
+ require 'skeem'
84
+
85
+ schemer = Skeem::Interpreter.new
86
+ scheme_code = <<-SKEEM
87
+ ; Compute the factorial of 100
88
+ (define fact (lambda (n)
89
+ (if (<= n 1) 1 (* n (fact (- n 1))))))
90
+ (fact 100)
91
+ SKEEM
92
+
93
+ result = schemer.run(scheme_code)
94
+ puts result.value # => 9332621544394415268169923885626670049071596826438162146859296389521759999322991560894146397615651828625369792082722375825118521091686400000000000000000000000
95
+ ```
82
96
 
83
97
  Roadmap:
84
98
  - Extend language support
@@ -12,6 +12,7 @@ module Skeem
12
12
  def initialize()
13
13
  @runtime = Runtime.new(Environment.new)
14
14
  add_primitives(runtime)
15
+ add_standard(runtime)
15
16
  end
16
17
 
17
18
  def run(source)
@@ -19,5 +20,20 @@ module Skeem
19
20
  @ptree = parser.parse(source)
20
21
  return @ptree.root.evaluate(runtime)
21
22
  end
23
+
24
+ private
25
+
26
+ def add_standard(aRuntime)
27
+ std_pathname = File.dirname(__FILE__) + '/standard/base.skm'
28
+ load_lib(std_pathname)
29
+ end
30
+
31
+ def load_lib(aPathname)
32
+ lib_source = nil
33
+ File.open(aPathname, 'r') do |lib|
34
+ lib_source = lib.read
35
+ run(lib_source)
36
+ end
37
+ end
22
38
  end # class
23
39
  end # module
@@ -85,8 +85,6 @@ module Skeem
85
85
  # rule('lambda_expression' => 'LPAREN LAMBDA formals body RPAREN').as 'lambda_expression'
86
86
  def reduce_lambda_expression(_production, _range, _tokens, theChildren)
87
87
  lmbd = SkmLambda.new(_range, theChildren[2], theChildren[3])
88
- # puts lmbd.inspect
89
- lmbd
90
88
  end
91
89
 
92
90
  # rule('formals' => 'LPAREN identifier_star RPAREN').as 'identifiers_as_formals'
@@ -325,7 +325,11 @@ module Skeem
325
325
  raise err, err_msg
326
326
  end
327
327
  procedure = aRuntime.environment.fetch(var_key.value)
328
+ # puts "## CALL(#{var_key.value}) ###################"
329
+ # puts operands.inspect
328
330
  result = procedure.call(aRuntime, self)
331
+ # puts "## RETURN #{result.inspect}"
332
+ result
329
333
  end
330
334
 
331
335
  def inspect
@@ -367,21 +371,6 @@ module Skeem
367
371
  result
368
372
  end
369
373
  end # class
370
-
371
- =begin
372
- <Skeem::SkmLambda:
373
- @formals [<Skeem::SkmIdentifier: x>]
374
- @definitions nil
375
- @sequence <Skeem::SkmList:
376
- <Skeem::SkmCondition:
377
- @test <Skeem::ProcedureCall: <Skeem::SkmIdentifier: <>,
378
- <Skeem::SkmList: <Skeem::SkmVariableReference: <Skeem::SkmIdentifier: x>>,
379
- <Skeem::SkmInteger: 0>>>,
380
- @consequent <Skeem::ProcedureCall:
381
- <Skeem::SkmIdentifier: ->,
382
- <Skeem::SkmList: <Skeem::SkmVariableReference: <Skeem::SkmIdentifier: x>>>>,
383
- @alternate <Skeem::SkmVariableReference: <Skeem::SkmIdentifier: x>>>>>
384
- =end
385
374
 
386
375
  class SkmLambda < SkmElement
387
376
  # @!attribute [r] formals
@@ -427,12 +416,14 @@ module Skeem
427
416
  formals.each_with_index do |arg_name, index|
428
417
  arg = arguments[index]
429
418
  if arg.nil?
430
- p aProcedureCall.operands.members
431
419
  raise StandardError, "Unbound variable: '#{arg_name.value}'"
432
420
  end
433
-
421
+
422
+ # IMPORTANT: execute procedure call in argument list now
423
+ arg = arg.evaluate(aRuntime) if arg.kind_of?(ProcedureCall)
434
424
  a_def = SkmDefinition.new(position, arg_name, arg)
435
425
  a_def.evaluate(aRuntime)
426
+ # puts "LOCAL #{a_def.inspect}"
436
427
  end
437
428
  end
438
429
 
@@ -0,0 +1,25 @@
1
+ ; Standard R7RS procedures from section 6.2.6
2
+ (define zero?
3
+ (lambda (z)
4
+ (if (= z 0)
5
+ #t
6
+ #f)))
7
+
8
+ ; Return true if x greater or equal to zero; false otherwise
9
+ (define positive?
10
+ (lambda (x)
11
+ (if (>= x 0)
12
+ #t
13
+ #f)))
14
+
15
+ (define negative?
16
+ (lambda (x)
17
+ (if (< x 0)
18
+ #t
19
+ #f)))
20
+
21
+ (define abs
22
+ (lambda (x)
23
+ (if (>= x 0)
24
+ x
25
+ (- x))))
data/lib/skeem/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Skeem
2
- VERSION = '0.0.14'.freeze
2
+ VERSION = '0.0.15'.freeze
3
3
  end
data/skeem.gemspec CHANGED
@@ -19,6 +19,7 @@ module PkgExtending
19
19
  'bin/*.rb',
20
20
  'lib/*.*',
21
21
  'lib/**/*.rb',
22
+ 'lib/**/*.skm',
22
23
  'spec/**/*.rb',
23
24
  ]
24
25
  aPackage.files = file_list
@@ -8,8 +8,8 @@ module Skeem
8
8
  expect { Interpreter.new() }.not_to raise_error
9
9
  end
10
10
 
11
- it 'should not have a parser' do
12
- expect(subject.parser).to be_nil
11
+ it 'should have a parser' do
12
+ expect(subject.parser).not_to be_nil
13
13
  end
14
14
 
15
15
  it 'should have a runtime object' do
@@ -154,17 +154,17 @@ SKEEM
154
154
  result = subject.run('(min 2 2)')
155
155
  expect(result.value).to eq(2)
156
156
  end
157
-
158
- # it 'should implement recursive functions' do
159
- # source = <<-SKEEM
160
- # ; Example from R7RS section 4.1.5
161
- # (define fact (lambda (n)
162
- # (if (<= n 1) 1 (* n (fact (- n 1))))))
163
- # (fact 10)
164
- # SKEEM
165
- # subject.run(source)
166
- # expect(result.value).to eq(3628800)
167
- # end
157
+
158
+ it 'should implement recursive functions' do
159
+ source = <<-SKEEM
160
+ ; Example from R7RS section 4.1.5
161
+ (define fact (lambda (n)
162
+ (if (<= n 1) 1 (* n (fact (- n 1))))))
163
+ (fact 10)
164
+ SKEEM
165
+ result = subject.run(source)
166
+ expect(result.value).to eq(3628800)
167
+ end
168
168
  end # context
169
169
 
170
170
  context 'Built-in primitive procedures' do
@@ -377,5 +377,82 @@ SKEEM
377
377
  end
378
378
  end
379
379
  end # context
380
+
381
+ context 'Built-in standard procedures' do
382
+ it 'should implement the zero? predicate' do
383
+ checks = [
384
+ ['(zero? 3.1)', false],
385
+ ['(zero? -3.1)', false],
386
+ ['(zero? 0)', true],
387
+ ['(zero? 0.0)', true],
388
+ ['(zero? 3)', false],
389
+ ['(zero? -3)', false]
390
+ ]
391
+ checks.each do |(skeem_expr, expectation)|
392
+ result = subject.run(skeem_expr)
393
+ expect(result.value).to eq(expectation)
394
+ end
395
+ end
396
+
397
+ it 'should implement the positive? predicate' do
398
+ checks = [
399
+ ['(positive? 3.1)', true],
400
+ ['(positive? -3.1)', false],
401
+ ['(positive? 0)', true],
402
+ ['(positive? 0.0)', true],
403
+ ['(positive? 3)', true],
404
+ ['(positive? -3)', false]
405
+ ]
406
+ checks.each do |(skeem_expr, expectation)|
407
+ result = subject.run(skeem_expr)
408
+ expect(result.value).to eq(expectation)
409
+ end
410
+ end
411
+
412
+ it 'should implement the positive? predicate' do
413
+ checks = [
414
+ ['(positive? 3.1)', true],
415
+ ['(positive? -3.1)', false],
416
+ ['(positive? 0)', true],
417
+ ['(positive? 0.0)', true],
418
+ ['(positive? 3)', true],
419
+ ['(positive? -3)', false]
420
+ ]
421
+ checks.each do |(skeem_expr, expectation)|
422
+ result = subject.run(skeem_expr)
423
+ expect(result.value).to eq(expectation)
424
+ end
425
+ end
426
+
427
+ it 'should implement the negative? predicate' do
428
+ checks = [
429
+ ['(negative? 3.1)', false],
430
+ ['(negative? -3.1)', true],
431
+ ['(negative? 0)', false],
432
+ ['(negative? 0.0)', false],
433
+ ['(negative? 3)', false],
434
+ ['(negative? -3)', true]
435
+ ]
436
+ checks.each do |(skeem_expr, expectation)|
437
+ result = subject.run(skeem_expr)
438
+ expect(result.value).to eq(expectation)
439
+ end
440
+ end
441
+
442
+ it 'should implement the abs function' do
443
+ checks = [
444
+ ['(abs 3.1)', 3.1],
445
+ ['(abs -3.1)', 3.1],
446
+ ['(abs 0)', 0],
447
+ ['(abs 0.0)', 0],
448
+ ['(abs 3)', 3],
449
+ ['(abs -7)', 7]
450
+ ]
451
+ checks.each do |(skeem_expr, expectation)|
452
+ result = subject.run(skeem_expr)
453
+ expect(result.value).to eq(expectation)
454
+ end
455
+ end
456
+ end # context
380
457
  end # describe
381
458
  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.14
4
+ version: 0.0.15
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-09-23 00:00:00.000000000 Z
11
+ date: 2018-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -95,6 +95,7 @@ files:
95
95
  - lib/skeem/runtime.rb
96
96
  - lib/skeem/s_expr_builder.rb
97
97
  - lib/skeem/s_expr_nodes.rb
98
+ - lib/skeem/standard/base.skm
98
99
  - lib/skeem/stoken.rb
99
100
  - lib/skeem/tokenizer.rb
100
101
  - lib/skeem/version.rb