skeem 0.0.8 → 0.0.9

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