skeem 0.0.8 → 0.0.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e19432168939085384bceaf28be0364177ddf91b
4
- data.tar.gz: 1256c3c464d7edb6fcf7d3cf6c1d1fd1bd2446ab
3
+ metadata.gz: 6261d01a57850b9accad9ba2136b59625c37ea58
4
+ data.tar.gz: 7918e865cadb393e285bfdea1e722970b918549b
5
5
  SHA512:
6
- metadata.gz: 7817ca715480e6d21c46ba46da12bb6652592f258348968dc3e3c705c717542ddca63b63493758ba2a470e300a5d1263b61762ae21746fc81afede599eae36e7
7
- data.tar.gz: 948438de92a59ada9b5589a312df5c71fbd9e884328a6b4c8ad1422578ae0471dbdb170354499a4fa5cd7811809ca38f97785ec183b5c820edce1121b770a656
6
+ metadata.gz: 1a4efb9e1b96a298448c908e11c1df6a03b810586f7008e10eab9c7336705d3df8e4648155f42737f4fd4453e62ad258af031efc3a884019e42f81babc63b722
7
+ data.tar.gz: abd048ab5117289e788090947e142805183283b49f05bdd5f16ac491888c8a5f1c6857bc631d51b6db7dc5c9229ccd5b6f65962e7950cdd24bb30c2f761ebb98
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [0.0.9] - 2018-09-15
2
+ Added primitive procedures: 'number?', 'real?', 'integer?'.
3
+
4
+ ### Added
5
+ - Class `PrimitiveBuilder`. Added methods to implement the predicates number?, real?, integer?
6
+ ### Changed
7
+ - Class hierarchy `SExprElement`. Prefix `SExpr` in class names changed into 'Skm'
8
+
1
9
  ## [0.0.8] - 2018-09-13
2
10
  Added primitive operators: '-', '*', '/' operators.
3
11
 
data/lib/skeem/parser.rb CHANGED
@@ -10,7 +10,7 @@ module Skeem
10
10
  # Create a Rley facade object
11
11
  @engine = Rley::Engine.new do |cfg|
12
12
  cfg.diagnose = true
13
- cfg.repr_builder = SExprBuilder
13
+ cfg.repr_builder = SkmBuilder
14
14
  end
15
15
 
16
16
  # Step 1. Load Skeem grammar
@@ -1,19 +1,26 @@
1
- require_relative '../primitive_func'
1
+ require_relative '../primitive_procedure'
2
2
 
3
3
  module Skeem
4
4
  module Primitive
5
5
  module PrimitiveBuilder
6
6
  def add_primitives(aRuntime)
7
7
  add_arithmetic(aRuntime)
8
+ add_number_predicates(aRuntime)
8
9
  end
9
10
 
10
11
  private
11
12
 
12
13
  def add_arithmetic(aRuntime)
13
- def_func(aRuntime, create_plus)
14
- def_func(aRuntime, create_minus)
15
- def_func(aRuntime, create_multiply)
16
- def_func(aRuntime, create_divide)
14
+ def_procedure(aRuntime, create_plus)
15
+ def_procedure(aRuntime, create_minus)
16
+ def_procedure(aRuntime, create_multiply)
17
+ def_procedure(aRuntime, create_divide)
18
+ end
19
+
20
+ def add_number_predicates(aRuntime)
21
+ def_procedure(aRuntime, create_number?)
22
+ def_procedure(aRuntime, create_real?)
23
+ def_procedure(aRuntime, create_integer?)
17
24
  end
18
25
 
19
26
  def create_plus()
@@ -22,11 +29,7 @@ module Skeem
22
29
  operands = arglist.tail.to_eval_enum(runtime)
23
30
  raw_result = first_one.value
24
31
  operands.each { |elem| raw_result += elem.value }
25
- if raw_result.kind_of?(Float)
26
- SExprReal.create(raw_result)
27
- else
28
- SExprInteger.create(raw_result)
29
- end
32
+ to_skm(raw_result)
30
33
  end
31
34
 
32
35
  ['+', plus_code]
@@ -38,11 +41,7 @@ module Skeem
38
41
  operands = arglist.tail.to_eval_enum(runtime)
39
42
  raw_result = first_one.value
40
43
  operands.each { |elem| raw_result -= elem.value }
41
- if raw_result.kind_of?(Float)
42
- SExprReal.create(raw_result)
43
- else
44
- SExprInteger.create(raw_result)
45
- end
44
+ to_skm(raw_result)
46
45
  end
47
46
 
48
47
  ['-', minus_code]
@@ -54,11 +53,7 @@ module Skeem
54
53
  operands = arglist.tail.to_eval_enum(runtime)
55
54
  raw_result = first_one.value
56
55
  operands.each { |elem| raw_result *= elem.value }
57
- if raw_result.kind_of?(Float)
58
- SExprReal.create(raw_result)
59
- else
60
- SExprInteger.create(raw_result)
61
- end
56
+ to_skm(raw_result)
62
57
  end
63
58
 
64
59
  ['*', multiply_code]
@@ -70,24 +65,59 @@ module Skeem
70
65
  operands = arglist.tail.to_eval_enum(runtime)
71
66
  raw_result = first_one.value
72
67
  operands.each { |elem| raw_result /= elem.value }
73
- if raw_result.kind_of?(Float)
74
- SExprReal.create(raw_result)
75
- else
76
- SExprInteger.create(raw_result)
77
- end
68
+ to_skm(raw_result)
78
69
  end
79
70
 
80
71
  ['/', divide_code]
72
+ end
73
+
74
+ def create_number?()
75
+ pred_code = ->(runtime, arg) do
76
+ arg_evaluated = arg.evaluate(runtime)
77
+ to_skm(arg_evaluated.number?)
78
+ end
79
+
80
+ ['number?', pred_code]
81
+ end
82
+
83
+ def create_real?()
84
+ pred_code = ->(runtime, arg) do
85
+ arg_evaluated = arg.evaluate(runtime)
86
+ to_skm(arg_evaluated.real?)
87
+ end
88
+
89
+ ['real?', pred_code]
90
+ end
91
+
92
+ def create_integer?()
93
+ pred_code = ->(runtime, arg) do
94
+ arg_evaluated = arg.evaluate(runtime)
95
+ to_skm(arg_evaluated.integer?)
96
+ end
97
+
98
+ ['integer?', pred_code]
81
99
  end
82
100
 
83
- def def_func(aRuntime, aPair)
84
- func = PrimitiveFunc.new(aPair.first, aPair.last)
101
+ def def_procedure(aRuntime, aPair)
102
+ func = PrimitiveProcedure.new(aPair.first, aPair.last)
85
103
  define(aRuntime, func.identifier, func)
86
104
  end
87
105
 
88
106
  def define(aRuntime, aKey, anEntry)
89
107
  aRuntime.define(aKey, anEntry)
90
108
  end
109
+
110
+ # Convert Ruby object into its Skeem counterpart
111
+ def to_skm(native_obj)
112
+ case native_obj
113
+ when TrueClass, FalseClass
114
+ SkmBoolean.create(native_obj)
115
+ when Float
116
+ SkmReal.create(native_obj)
117
+ when Integer
118
+ SkmInteger.create(native_obj)
119
+ end
120
+ end
91
121
  end # module
92
122
  end # module
93
123
  end # module
@@ -1,12 +1,12 @@
1
1
  require_relative 's_expr_nodes'
2
2
 
3
3
  module Skeem
4
- class PrimitiveFunc
4
+ class PrimitiveProcedure
5
5
  attr_reader(:identifier)
6
6
  attr_reader(:code)
7
7
 
8
8
  def initialize(anId, aLambda)
9
- @identifier = anId.kind_of?(String) ? SExprIdentifier.create(anId) : anId
9
+ @identifier = anId.kind_of?(String) ? SkmIdentifier.create(anId) : anId
10
10
  @code = aLambda
11
11
  end
12
12
 
@@ -9,13 +9,13 @@ module Skeem
9
9
  # The Builder pattern creates a complex object
10
10
  # (say, a parse tree) from simpler objects (terminal and non-terminal
11
11
  # nodes) and using a step by step approach.
12
- class SExprBuilder < Rley::ParseRep::ASTBaseBuilder
12
+ class SkmBuilder < Rley::ParseRep::ASTBaseBuilder
13
13
  Terminal2NodeClass = {
14
- 'BOOLEAN' => SExprBoolean,
15
- 'IDENTIFIER' => SExprIdentifier,
16
- 'INTEGER' => SExprInteger,
17
- 'REAL' => SExprReal,
18
- 'STRING_LIT' => SExprString
14
+ 'BOOLEAN' => SkmBoolean,
15
+ 'IDENTIFIER' => SkmIdentifier,
16
+ 'INTEGER' => SkmInteger,
17
+ 'REAL' => SkmReal,
18
+ 'STRING_LIT' => SkmString
19
19
  }.freeze
20
20
 
21
21
  # Create a new AST builder instance.
@@ -5,19 +5,31 @@ require 'forwardable'
5
5
 
6
6
  module Skeem
7
7
  # Abstract class. Generalization of any S-expr element.
8
- SExprElement = Struct.new(:position) do
8
+ SkmElement = Struct.new(:position) do
9
9
  def initialize(aPosition)
10
10
  self.position = aPosition
11
11
  end
12
12
 
13
13
  def evaluate(_runtime)
14
- raise NotImplementedError
14
+ raise NotImplementedError, "Missing implementation of #{self.class.name}"
15
15
  end
16
16
 
17
17
  def done!()
18
18
  # Do nothing
19
19
  end
20
20
 
21
+ def number?
22
+ false
23
+ end
24
+
25
+ def real?
26
+ false
27
+ end
28
+
29
+ def integer?
30
+ false
31
+ end
32
+
21
33
  # Abstract method.
22
34
  # Part of the 'visitee' role in Visitor design pattern.
23
35
  # @param _visitor[ParseTreeVisitor] the visitor
@@ -28,7 +40,7 @@ module Skeem
28
40
 
29
41
  # Abstract class. Root of class hierarchy needed for Interpreter
30
42
  # design pattern
31
- class SExprTerminal < SExprElement
43
+ class SkmTerminal < SkmElement
32
44
  attr_reader :token
33
45
  attr_reader :value
34
46
 
@@ -68,37 +80,46 @@ module Skeem
68
80
  end
69
81
  end # class
70
82
 
71
- class SExprBoolean < SExprTerminal
83
+ class SkmBoolean < SkmTerminal
72
84
  end # class
73
85
 
74
- class SExprNumber < SExprTerminal
86
+ class SkmNumber < SkmTerminal
87
+ def number?
88
+ true
89
+ end
75
90
  end # class
76
91
 
77
- class SExprReal < SExprTerminal
92
+ class SkmReal < SkmNumber
93
+ def real?
94
+ true
95
+ end
78
96
  end # class
79
97
 
80
- class SExprInteger < SExprReal
98
+ class SkmInteger < SkmReal
99
+ def integer?
100
+ true
101
+ end
81
102
  end # class
82
103
 
83
- class SExprString < SExprTerminal
104
+ class SkmString < SkmTerminal
84
105
  # Override
85
106
  def init_value(aValue)
86
107
  super(aValue.dup)
87
108
  end
88
109
  end # class
89
110
 
90
- class SExprIdentifier < SExprTerminal
111
+ class SkmIdentifier < SkmTerminal
91
112
  # Override
92
113
  def init_value(aValue)
93
114
  super(aValue.dup)
94
115
  end
95
116
  end # class
96
117
 
97
- class SExprReserved < SExprIdentifier
118
+ class SkmReserved < SkmIdentifier
98
119
  end # class
99
120
 
100
121
 
101
- class SExprList < SExprElement
122
+ class SkmList < SkmElement
102
123
  attr_accessor(:members)
103
124
  extend Forwardable
104
125
 
@@ -112,9 +133,19 @@ module Skeem
112
133
  def head()
113
134
  return members.first
114
135
  end
115
-
136
+
116
137
  def tail()
117
- SExprList.new(members.slice(1..-1))
138
+ SkmList.new(members.slice(1..-1))
139
+ end
140
+
141
+ def evaluate(aRuntime)
142
+ result = nil
143
+
144
+ members.each do |elem|
145
+ result = elem.evaluate(aRuntime)
146
+ end
147
+
148
+ result
118
149
  end
119
150
 
120
151
  # Factory method.
@@ -145,21 +176,21 @@ module Skeem
145
176
  alias subnodes members
146
177
  end # class
147
178
 
148
- class ProcedureCall < SExprElement
179
+ class ProcedureCall < SkmElement
149
180
  attr_reader :operator
150
181
  attr_reader :operands
151
182
 
152
183
  def initialize(aPosition, anOperator, theOperands)
153
184
  super(aPosition)
154
185
  @operator = anOperator
155
- @operands = SExprList.new(theOperands)
186
+ @operands = SkmList.new(theOperands)
156
187
  end
157
188
 
158
189
  def evaluate(aRuntime)
159
190
  proc_key = operator.evaluate(aRuntime)
160
191
  unless aRuntime.include?(proc_key.value)
161
192
  err = StandardError
162
- key = proc_key.kind_of?(SExprIdentifier) ? proc_key.value : proc_key
193
+ key = proc_key.kind_of?(SkmIdentifier) ? proc_key.value : proc_key
163
194
  err_msg = "Unknown function '#{key}'"
164
195
  raise err, err_msg
165
196
  end
data/lib/skeem/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Skeem
2
- VERSION = '0.0.8'.freeze
2
+ VERSION = '0.0.9'.freeze
3
3
  end
@@ -31,7 +31,7 @@ module Skeem
31
31
  ]
32
32
  samples.each do |source, predicted|
33
33
  result = subject.run(source)
34
- expect(result).to be_kind_of(SExprBoolean)
34
+ expect(result).to be_kind_of(SkmBoolean)
35
35
  expect(result.value).to eq(predicted)
36
36
  end
37
37
  end
@@ -46,7 +46,7 @@ module Skeem
46
46
  ]
47
47
  samples.each do |source, predicted|
48
48
  result = subject.run(source)
49
- expect(result).to be_kind_of(SExprInteger)
49
+ expect(result).to be_kind_of(SkmInteger)
50
50
  expect(result.value).to eq(predicted)
51
51
  end
52
52
  end
@@ -61,7 +61,7 @@ module Skeem
61
61
  ]
62
62
  samples.each do |source, predicted|
63
63
  result = subject.run(source)
64
- expect(result).to be_kind_of(SExprReal)
64
+ expect(result).to be_kind_of(SkmReal)
65
65
  expect(result.value).to eq(predicted)
66
66
  end
67
67
  end
@@ -72,7 +72,7 @@ module Skeem
72
72
  ]
73
73
  samples.each do |source, predicted|
74
74
  result = subject.run(source)
75
- expect(result).to be_kind_of(SExprString)
75
+ expect(result).to be_kind_of(SkmString)
76
76
  expect(result.value).to eq(predicted)
77
77
  end
78
78
  end
@@ -84,41 +84,81 @@ module Skeem
84
84
  ]
85
85
  samples.each do |source, predicted|
86
86
  result = subject.run(source)
87
- expect(result).to be_kind_of(SExprIdentifier)
87
+ expect(result).to be_kind_of(SkmIdentifier)
88
88
  expect(result.value).to eq(predicted)
89
89
  end
90
90
  end
91
91
  end # context
92
92
 
93
- context 'Built-in primitive functions' do
94
- it 'should support the addition of integers' do
93
+ context 'Built-in primitive procedures' do
94
+ it 'should implement the addition of integers' do
95
95
  result = subject.run('(+ 2 2)')
96
- expect(result).to be_kind_of(SExprInteger)
96
+ expect(result).to be_kind_of(SkmInteger)
97
97
  expect(result.value).to eq(4)
98
98
  end
99
99
 
100
- it 'should support the addition of real numbers' do
100
+ it 'should implement the addition of real numbers' do
101
101
  result = subject.run('(+ 2 2.34)')
102
- expect(result).to be_kind_of(SExprReal)
102
+ expect(result).to be_kind_of(SkmReal)
103
103
  expect(result.value).to eq(4.34)
104
104
  end
105
-
106
- it 'should support the product of numbers' do
105
+
106
+ it 'should implement the product of numbers' do
107
107
  result = subject.run('(* 2 3 4)')
108
- expect(result).to be_kind_of(SExprInteger)
109
- expect(result.value).to eq(24)
110
- end
108
+ expect(result).to be_kind_of(SkmInteger)
109
+ expect(result.value).to eq(24)
110
+ end
111
111
 
112
- it 'should support the division of numbers' do
112
+ it 'should implement the division of numbers' do
113
113
  result = subject.run('(/ 24 3)')
114
- expect(result).to be_kind_of(SExprInteger)
115
- expect(result.value).to eq(8)
116
- end
117
-
118
- it 'should support the arithmetic expressions' do
114
+ expect(result).to be_kind_of(SkmInteger)
115
+ expect(result.value).to eq(8)
116
+ end
117
+
118
+ it 'should implement the arithmetic expressions' do
119
119
  result = subject.run('(+ (* 2 100) (* 1 10))')
120
- expect(result).to be_kind_of(SExprInteger)
120
+ expect(result).to be_kind_of(SkmInteger)
121
121
  expect(result.value).to eq(210)
122
+ end
123
+
124
+ it 'should implement the number? predicate' do
125
+ checks = [
126
+ ['(number? 3.1)', true],
127
+ ['(number? 3)', true],
128
+ ['(number? "3")', false],
129
+ ['(number? #t)', false]
130
+ ]
131
+ checks.each do |(skeem_expr, expectation)|
132
+ result = subject.run(skeem_expr)
133
+ expect(result.value).to eq(expectation)
134
+ end
135
+ end
136
+
137
+ it 'should implement the real? predicate' do
138
+ checks = [
139
+ ['(real? 3.1)', true],
140
+ ['(real? 3)', true],
141
+ ['(real? "3")', false],
142
+ ['(real? #t)', false]
143
+ ]
144
+ checks.each do |(skeem_expr, expectation)|
145
+ result = subject.run(skeem_expr)
146
+ expect(result.value).to eq(expectation)
147
+ end
148
+ end
149
+
150
+ it 'should implement the integer? predicate' do
151
+ checks = [
152
+ ['(integer? 3.1)', false],
153
+ # ['(integer? 3.0)', true], TODO: should pass when exact? will be implemented
154
+ ['(integer? 3)', true],
155
+ ['(integer? "3")', false],
156
+ ['(integer? #t)', false]
157
+ ]
158
+ checks.each do |(skeem_expr, expectation)|
159
+ result = subject.run(skeem_expr)
160
+ expect(result.value).to eq(expectation)
161
+ end
122
162
  end
123
163
  end # context
124
164
  end # describe
@@ -23,7 +23,7 @@ module Skeem
23
23
  ]
24
24
  samples.each do |source, predicted|
25
25
  ptree = subject.parse(source)
26
- expect(ptree.root).to be_kind_of(SExprBoolean)
26
+ expect(ptree.root).to be_kind_of(SkmBoolean)
27
27
  expect(ptree.root.value).to eq(predicted)
28
28
  end
29
29
  end
@@ -38,7 +38,7 @@ module Skeem
38
38
  ]
39
39
  samples.each do |source, predicted|
40
40
  ptree = subject.parse(source)
41
- expect(ptree.root).to be_kind_of(SExprInteger)
41
+ expect(ptree.root).to be_kind_of(SkmInteger)
42
42
  expect(ptree.root.value).to eq(predicted)
43
43
  end
44
44
  end
@@ -53,7 +53,7 @@ module Skeem
53
53
  ]
54
54
  samples.each do |source, predicted|
55
55
  ptree = subject.parse(source)
56
- expect(ptree.root).to be_kind_of(SExprReal)
56
+ expect(ptree.root).to be_kind_of(SkmReal)
57
57
  expect(ptree.root.value).to eq(predicted)
58
58
  end
59
59
  end
@@ -64,7 +64,7 @@ module Skeem
64
64
  ]
65
65
  samples.each do |source, predicted|
66
66
  ptree = subject.parse(source)
67
- expect(ptree.root).to be_kind_of(SExprString)
67
+ expect(ptree.root).to be_kind_of(SkmString)
68
68
  expect(ptree.root.value).to eq(predicted)
69
69
  end
70
70
  end
@@ -75,7 +75,7 @@ module Skeem
75
75
  ]
76
76
  samples.each do |source, predicted|
77
77
  ptree = subject.parse(source)
78
- expect(ptree.root).to be_kind_of(SExprIdentifier)
78
+ expect(ptree.root).to be_kind_of(SkmIdentifier)
79
79
  expect(ptree.root.value).to eq(predicted)
80
80
  end
81
81
  end
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.8
4
+ version: 0.0.9
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-13 00:00:00.000000000 Z
11
+ date: 2018-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -90,7 +90,7 @@ files:
90
90
  - lib/skeem/interpreter.rb
91
91
  - lib/skeem/parser.rb
92
92
  - lib/skeem/primitive/primitive_builder.rb
93
- - lib/skeem/primitive_func.rb
93
+ - lib/skeem/primitive_procedure.rb
94
94
  - lib/skeem/runtime.rb
95
95
  - lib/skeem/s_expr_builder.rb
96
96
  - lib/skeem/s_expr_nodes.rb