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 +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/skeem/parser.rb +1 -1
- data/lib/skeem/primitive/primitive_builder.rb +57 -27
- data/lib/skeem/{primitive_func.rb → primitive_procedure.rb} +2 -2
- data/lib/skeem/s_expr_builder.rb +6 -6
- data/lib/skeem/s_expr_nodes.rb +47 -16
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/interpreter_spec.rb +62 -22
- data/spec/skeem/parser_spec.rb +5 -5
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6261d01a57850b9accad9ba2136b59625c37ea58
|
4
|
+
data.tar.gz: 7918e865cadb393e285bfdea1e722970b918549b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
@@ -1,19 +1,26 @@
|
|
1
|
-
require_relative '../
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
84
|
-
func =
|
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
|
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) ?
|
9
|
+
@identifier = anId.kind_of?(String) ? SkmIdentifier.create(anId) : anId
|
10
10
|
@code = aLambda
|
11
11
|
end
|
12
12
|
|
data/lib/skeem/s_expr_builder.rb
CHANGED
@@ -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
|
12
|
+
class SkmBuilder < Rley::ParseRep::ASTBaseBuilder
|
13
13
|
Terminal2NodeClass = {
|
14
|
-
'BOOLEAN' =>
|
15
|
-
'IDENTIFIER' =>
|
16
|
-
'INTEGER' =>
|
17
|
-
'REAL' =>
|
18
|
-
'STRING_LIT' =>
|
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.
|
data/lib/skeem/s_expr_nodes.rb
CHANGED
@@ -5,19 +5,31 @@ require 'forwardable'
|
|
5
5
|
|
6
6
|
module Skeem
|
7
7
|
# Abstract class. Generalization of any S-expr element.
|
8
|
-
|
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
|
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
|
83
|
+
class SkmBoolean < SkmTerminal
|
72
84
|
end # class
|
73
85
|
|
74
|
-
class
|
86
|
+
class SkmNumber < SkmTerminal
|
87
|
+
def number?
|
88
|
+
true
|
89
|
+
end
|
75
90
|
end # class
|
76
91
|
|
77
|
-
class
|
92
|
+
class SkmReal < SkmNumber
|
93
|
+
def real?
|
94
|
+
true
|
95
|
+
end
|
78
96
|
end # class
|
79
97
|
|
80
|
-
class
|
98
|
+
class SkmInteger < SkmReal
|
99
|
+
def integer?
|
100
|
+
true
|
101
|
+
end
|
81
102
|
end # class
|
82
103
|
|
83
|
-
class
|
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
|
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
|
118
|
+
class SkmReserved < SkmIdentifier
|
98
119
|
end # class
|
99
120
|
|
100
121
|
|
101
|
-
class
|
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
|
-
|
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 <
|
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 =
|
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?(
|
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
@@ -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(
|
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(
|
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(
|
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(
|
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(
|
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
|
94
|
-
it 'should
|
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(
|
96
|
+
expect(result).to be_kind_of(SkmInteger)
|
97
97
|
expect(result.value).to eq(4)
|
98
98
|
end
|
99
99
|
|
100
|
-
it 'should
|
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(
|
102
|
+
expect(result).to be_kind_of(SkmReal)
|
103
103
|
expect(result.value).to eq(4.34)
|
104
104
|
end
|
105
|
-
|
106
|
-
it 'should
|
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(
|
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
|
112
|
+
it 'should implement the division of numbers' do
|
113
113
|
result = subject.run('(/ 24 3)')
|
114
|
-
expect(result).to be_kind_of(
|
115
|
-
expect(result.value).to eq(8)
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'should
|
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(
|
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
|
data/spec/skeem/parser_spec.rb
CHANGED
@@ -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(
|
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(
|
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(
|
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(
|
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(
|
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.
|
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-
|
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/
|
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
|