template-ruby 0.1.0 → 0.2.0
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/.editorconfig +9 -0
- data/.gitignore +1 -0
- data/.prettierrc +3 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +10 -0
- data/bin/template +39 -0
- data/docs/euler/1.template +14 -0
- data/docs/euler/2.template +16 -0
- data/docs/euler/3.template +16 -0
- data/docs/euler/4.template +11 -0
- data/docs/euler/5.template +14 -0
- data/docs/precedence.template +94 -0
- data/lib/code/error.rb +15 -0
- data/lib/code/node/base_10_decimal.rb +12 -7
- data/lib/code/node/base_10_integer.rb +13 -4
- data/lib/code/node/base_10_number.rb +3 -3
- data/lib/code/node/base_16_number.rb +2 -2
- data/lib/code/node/base_2_number.rb +2 -2
- data/lib/code/node/base_8_number.rb +2 -2
- data/lib/code/node/block.rb +17 -0
- data/lib/code/node/boolean.rb +13 -4
- data/lib/code/node/call.rb +40 -8
- data/lib/code/node/call_argument.rb +37 -0
- data/lib/code/node/chained_call.rb +38 -0
- data/lib/code/node/code.rb +4 -7
- data/lib/code/node/defined.rb +19 -0
- data/lib/code/node/dictionnary.rb +11 -7
- data/lib/code/node/dictionnary_key_value.rb +3 -3
- data/lib/code/node/equal.rb +36 -0
- data/lib/code/node/function.rb +17 -0
- data/lib/code/node/function_argument.rb +45 -0
- data/lib/code/node/group.rb +13 -0
- data/lib/code/node/if.rb +55 -0
- data/lib/code/node/if_modifier.rb +48 -0
- data/lib/code/node/keyword_call_argument.rb +30 -0
- data/lib/code/node/keyword_function_argument.rb +33 -0
- data/lib/code/node/list.rb +10 -4
- data/lib/code/node/name.rb +37 -4
- data/lib/code/node/negation.rb +33 -0
- data/lib/code/node/not_keyword.rb +13 -0
- data/lib/code/node/nothing.rb +2 -2
- data/lib/code/node/number.rb +3 -3
- data/lib/code/node/operation.rb +33 -0
- data/lib/code/node/or_keyword.rb +34 -0
- data/lib/code/node/power.rb +16 -0
- data/lib/code/node/range.rb +31 -0
- data/lib/code/node/regular_call_argument.rb +34 -0
- data/lib/code/node/regular_function_argument.rb +36 -0
- data/lib/code/node/rescue.rb +16 -0
- data/lib/code/node/statement.rb +53 -3
- data/lib/code/node/string.rb +2 -2
- data/lib/code/node/ternary.rb +26 -0
- data/lib/code/node/unary_minus.rb +22 -0
- data/lib/code/node/while.rb +42 -0
- data/lib/code/node.rb +10 -0
- data/lib/code/object/argument.rb +41 -0
- data/lib/code/object/boolean.rb +8 -9
- data/lib/code/object/decimal.rb +32 -9
- data/lib/code/object/dictionnary.rb +33 -10
- data/lib/code/object/function.rb +64 -0
- data/lib/code/object/integer.rb +94 -7
- data/lib/code/object/list.rb +190 -10
- data/lib/code/object/nothing.rb +10 -9
- data/lib/code/object/number.rb +6 -0
- data/lib/code/object/range.rb +158 -0
- data/lib/code/object/string.rb +37 -7
- data/lib/code/object.rb +129 -2
- data/lib/code/parser/addition.rb +29 -0
- data/lib/code/parser/and_operator.rb +28 -0
- data/lib/code/parser/bitwise_and.rb +28 -0
- data/lib/code/parser/bitwise_or.rb +29 -0
- data/lib/code/parser/call.rb +77 -3
- data/lib/code/parser/defined.rb +20 -0
- data/lib/code/parser/equal.rb +42 -0
- data/lib/code/parser/equality.rb +36 -0
- data/lib/code/parser/function.rb +57 -0
- data/lib/code/parser/greater_than.rb +33 -0
- data/lib/code/parser/group.rb +17 -0
- data/lib/code/parser/if.rb +33 -0
- data/lib/code/parser/if_modifier.rb +28 -0
- data/lib/code/parser/multiplication.rb +30 -0
- data/lib/code/parser/name.rb +44 -4
- data/lib/code/parser/negation.rb +19 -0
- data/lib/code/parser/not_keyword.rb +21 -0
- data/lib/code/parser/nothing.rb +2 -2
- data/lib/code/parser/or_keyword.rb +29 -0
- data/lib/code/parser/or_operator.rb +28 -0
- data/lib/code/parser/power.rb +25 -0
- data/lib/code/parser/range.rb +25 -0
- data/lib/code/parser/rescue.rb +23 -0
- data/lib/code/parser/shift.rb +31 -0
- data/lib/code/parser/statement.rb +1 -4
- data/lib/code/parser/string.rb +7 -1
- data/lib/code/parser/ternary.rb +25 -0
- data/lib/code/parser/unary_minus.rb +13 -0
- data/lib/code/parser/while.rb +25 -0
- data/lib/code.rb +5 -7
- data/lib/template/node/code_part.rb +2 -2
- data/lib/template/node/part.rb +2 -2
- data/lib/template/node/template.rb +4 -2
- data/lib/template/node/text_part.rb +1 -1
- data/lib/template-ruby.rb +4 -0
- data/lib/template.rb +9 -4
- data/spec/call_spec.rb +22 -0
- data/spec/code/error/type_error_spec.rb +65 -0
- data/spec/code/parser/boolean_spec.rb +1 -1
- data/spec/code/parser/call_spec.rb +40 -11
- data/spec/code/parser/dictionnary_spec.rb +11 -11
- data/spec/code/parser/function_spec.rb +32 -0
- data/spec/code/parser/list_spec.rb +5 -5
- data/spec/code/parser/nothing_spec.rb +1 -1
- data/spec/code/parser/number_spec.rb +35 -35
- data/spec/code/parser/string_spec.rb +3 -2
- data/spec/code_spec.rb +75 -3
- data/spec/function_spec.rb +26 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/template/parser/template_spec.rb +1 -1
- data/spec/template_spec.rb +6 -6
- data/template-ruby.gemspec +6 -3
- metadata +76 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f42cd4f03c1c1bacdfdcc9e454cdc19411220aa407698bc63024f59311d0a23f
|
4
|
+
data.tar.gz: 59da1aed5e7e8e729c1c4a44c36c62fcaacc47780229e61b8606708e1414e4c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e56e63c45fce924c3b62571a58be48846be2a0348565713a2e5de6f6a33f07d15ce4e37fc0d48a3ef964ff3d8cb8810bff55ae6f2cc5bba184df2b14182d85c
|
7
|
+
data.tar.gz: 26ba43eea5b6d61a99fd358bdcded3bfcc52e0b0b57910c62f0773380f3777a4b29b8ff355937c0d716cdd5f4e7d29561d17c642de1476a06a32fdd798c3d6ad
|
data/.editorconfig
ADDED
data/.gitignore
CHANGED
data/.prettierrc
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## 0.2.0 / 2022-08-30
|
9
|
+
|
10
|
+
- Programming language capable of solving the first 5 Project Euler problems
|
11
|
+
|
12
|
+
## 0.1.0 / 2022-07-28
|
13
|
+
|
14
|
+
- Initial version with interpolation
|
15
|
+
|
data/Gemfile.lock
CHANGED
data/README.md
ADDED
data/bin/template
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require_relative "../lib/template-ruby"
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
10
|
+
|
11
|
+
opts.on("-i INPUT", "--input=INPUT", "Input in the template language") do |input|
|
12
|
+
if File.exists?(input)
|
13
|
+
input = File.read(input)
|
14
|
+
end
|
15
|
+
|
16
|
+
options[:input] = input
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-c CONTEXT", "--context=CONTEXT", "Context in the code language") do |context|
|
20
|
+
if File.exists?(context)
|
21
|
+
context = File.read(context)
|
22
|
+
end
|
23
|
+
|
24
|
+
options[:context] = context
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-p", "--parse", "Get parser results for input") do |parse|
|
28
|
+
options[:parse] = parse
|
29
|
+
end
|
30
|
+
end.parse!
|
31
|
+
|
32
|
+
input = options.fetch(:input, "")
|
33
|
+
context = options.fetch(:context, "")
|
34
|
+
|
35
|
+
if options[:parse]
|
36
|
+
pp ::Template::Parser::Template.new.parse(input)
|
37
|
+
else
|
38
|
+
Template.render(input, context, io: $stdout)
|
39
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
- Code
|
2
|
+
- {a = "Go" a += "od" a}
|
3
|
+
- Statement
|
4
|
+
- {a = "Good"}
|
5
|
+
- {
|
6
|
+
a = 0
|
7
|
+
while a < 10
|
8
|
+
a += 1
|
9
|
+
"Good"
|
10
|
+
end
|
11
|
+
}
|
12
|
+
- While
|
13
|
+
- {
|
14
|
+
a = 0
|
15
|
+
until a > 10
|
16
|
+
a += 1
|
17
|
+
"Good"
|
18
|
+
end
|
19
|
+
}
|
20
|
+
- {
|
21
|
+
a = 0
|
22
|
+
while
|
23
|
+
if a > 10
|
24
|
+
false
|
25
|
+
else
|
26
|
+
true
|
27
|
+
end
|
28
|
+
a += 1
|
29
|
+
"Good"
|
30
|
+
end
|
31
|
+
}
|
32
|
+
- If
|
33
|
+
- {if true "Good" end}
|
34
|
+
- {if true if false "Bad" else "Good" end}
|
35
|
+
- IfModifier
|
36
|
+
- {"Good" if true}
|
37
|
+
- OrKeyword
|
38
|
+
- {false or "Good"}
|
39
|
+
- NotKeyword
|
40
|
+
- {not false and "Good"}
|
41
|
+
- Defined
|
42
|
+
- {a = 1 "Good" if defined?(a)}
|
43
|
+
- Equal
|
44
|
+
- {a = "Good"}
|
45
|
+
- Rescue
|
46
|
+
- {0 > "String" rescue "Good"}
|
47
|
+
- Ternary
|
48
|
+
- {nothing ? "Bad" : "Good"}
|
49
|
+
- Range
|
50
|
+
- {("Good".."Bad").first}
|
51
|
+
- OrOperator
|
52
|
+
- {false || "Good"}
|
53
|
+
- AndOperator
|
54
|
+
- {"Bad" && "Good"}
|
55
|
+
- Equality
|
56
|
+
- {1 == 1 ? "Good"}
|
57
|
+
- GreaterThan
|
58
|
+
- {2 > 1 ? "Good"}
|
59
|
+
- BitwiseOr
|
60
|
+
- {2 | 1 == 3 ? "Good"}
|
61
|
+
- BitwiseAnd
|
62
|
+
- {2 & 1 == 0 ? "Good"}
|
63
|
+
- Shift
|
64
|
+
- {1 << 1 == 2 ? "Good"}
|
65
|
+
- Addition
|
66
|
+
- {1 + 1 == 2 ? "Good"}
|
67
|
+
- Multiplication
|
68
|
+
- {1 * 2 == 2 ? "Good"}
|
69
|
+
- UnaryMinus
|
70
|
+
- {-1 == 1 - 2 ? "Good"}
|
71
|
+
- Power
|
72
|
+
- {2 ** 2 == 4 ? "Good"}
|
73
|
+
- Negation
|
74
|
+
- {!false ? "Good"}
|
75
|
+
- Function
|
76
|
+
- {good = () => { "Good" } good}
|
77
|
+
- Call
|
78
|
+
- {["Good"].first}
|
79
|
+
- Dictionnary
|
80
|
+
- {{a: "Good"}.a}
|
81
|
+
- List
|
82
|
+
- {["Good", "Bad"].first}
|
83
|
+
- String
|
84
|
+
- {"Good"}
|
85
|
+
- Number
|
86
|
+
- {1 == 1 ? "Good"}
|
87
|
+
- Boolean
|
88
|
+
- {true ? "Good"}
|
89
|
+
- Nothing
|
90
|
+
- {nothing ? "Bad" : "Good"}
|
91
|
+
- Group
|
92
|
+
- {(a = 0 a += 1 a) == 1 ? "Good"}
|
93
|
+
- Name
|
94
|
+
- {a = "Good" a}
|
data/lib/code/error.rb
ADDED
@@ -1,6 +1,6 @@
|
|
1
1
|
class Code
|
2
2
|
class Node
|
3
|
-
class Base10Decimal
|
3
|
+
class Base10Decimal < Node
|
4
4
|
def initialize(number)
|
5
5
|
@sign = number[:sign]
|
6
6
|
@whole = number.fetch(:whole)
|
@@ -11,12 +11,17 @@ class Code
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def evaluate(
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
def evaluate(**args)
|
15
|
+
if @exponent
|
16
|
+
exponent = @exponent.evaluate(**args)
|
17
|
+
|
18
|
+
::Code::Object::Decimal.new(
|
19
|
+
"#{sign}#{whole}.#{decimal}",
|
20
|
+
exponent: exponent,
|
21
|
+
)
|
22
|
+
else
|
23
|
+
::Code::Object::Decimal.new("#{sign}#{whole}.#{decimal}")
|
24
|
+
end
|
20
25
|
end
|
21
26
|
|
22
27
|
private
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Code
|
2
2
|
class Node
|
3
|
-
class Base10Integer
|
3
|
+
class Base10Integer < Node
|
4
4
|
def initialize(number)
|
5
5
|
@sign = number[:sign]
|
6
6
|
@whole = number.fetch(:whole)
|
@@ -10,9 +10,18 @@ class Code
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
def evaluate(
|
14
|
-
|
15
|
-
|
13
|
+
def evaluate(**args)
|
14
|
+
if @exponent
|
15
|
+
exponent = @exponent.evaluate(**args)
|
16
|
+
|
17
|
+
if exponent.is_a?(::Code::Object::Decimal)
|
18
|
+
::Code::Object::Decimal.new("#{sign}#{whole}", exponent: exponent)
|
19
|
+
else
|
20
|
+
::Code::Object::Integer.new("#{sign}#{whole}", exponent: exponent)
|
21
|
+
end
|
22
|
+
else
|
23
|
+
::Code::Object::Integer.new("#{sign}#{whole}")
|
24
|
+
end
|
16
25
|
end
|
17
26
|
|
18
27
|
private
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Code
|
2
2
|
class Node
|
3
|
-
class Base10Number
|
3
|
+
class Base10Number < Node
|
4
4
|
def initialize(number)
|
5
5
|
if number.key?(:integer)
|
6
6
|
@number = ::Code::Node::Base10Integer.new(number[:integer])
|
@@ -11,8 +11,8 @@ class Code
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def evaluate(
|
15
|
-
@number.evaluate(
|
14
|
+
def evaluate(**args)
|
15
|
+
@number.evaluate(**args)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Code
|
2
|
+
class Node
|
3
|
+
class Block < Node
|
4
|
+
def initialize(block)
|
5
|
+
@body = ::Code::Node::Code.new(block.fetch(:body))
|
6
|
+
@arguments = block.fetch(:arguments, [])
|
7
|
+
@arguments.map! do |argument|
|
8
|
+
::Code::Node::FunctionArgument.new(argument)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def evaluate(**args)
|
13
|
+
::Code::Object::Function.new(arguments: @arguments, body: @body)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/code/node/boolean.rb
CHANGED
@@ -1,12 +1,21 @@
|
|
1
1
|
class Code
|
2
2
|
class Node
|
3
|
-
class Boolean
|
3
|
+
class Boolean < Node
|
4
|
+
TRUE = "true"
|
5
|
+
FALSE = "false"
|
6
|
+
|
4
7
|
def initialize(boolean)
|
5
|
-
@boolean = boolean
|
8
|
+
@boolean = boolean
|
6
9
|
end
|
7
10
|
|
8
|
-
def evaluate(
|
9
|
-
|
11
|
+
def evaluate(**args)
|
12
|
+
if @boolean == TRUE
|
13
|
+
::Code::Object::Boolean.new(true)
|
14
|
+
elsif @boolean == FALSE
|
15
|
+
::Code::Object::Boolean.new(false)
|
16
|
+
else
|
17
|
+
raise NotImplementedError, @boolean.inspect
|
18
|
+
end
|
10
19
|
end
|
11
20
|
end
|
12
21
|
end
|
data/lib/code/node/call.rb
CHANGED
@@ -1,19 +1,51 @@
|
|
1
1
|
class Code
|
2
2
|
class Node
|
3
|
-
class Call
|
3
|
+
class Call < Node
|
4
4
|
def initialize(call)
|
5
5
|
@left = ::Code::Node::Statement.new(call.fetch(:left))
|
6
|
-
@right = ::Code::Node::Statement.new(call.fetch(:right))
|
7
|
-
end
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
@arguments = call.fetch(:arguments, [])
|
8
|
+
@arguments.map! { |argument| ::Code::Node::CallArgument.new(argument) }
|
9
|
+
|
10
|
+
if call.key?(:right)
|
11
|
+
@right = call.fetch(:right).map do |right|
|
12
|
+
::Code::Node::ChainedCall.new(right)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if call.key?(:block)
|
17
|
+
@block = ::Code::Node::Block.new(call.fetch(:block))
|
18
|
+
end
|
12
19
|
end
|
13
20
|
|
14
|
-
|
21
|
+
def evaluate(**args)
|
22
|
+
if @right
|
23
|
+
left = @left.evaluate(**args)
|
24
|
+
@right.reduce(left) do |acc, element|
|
25
|
+
element.evaluate(**args.merge(object: acc))
|
26
|
+
end
|
27
|
+
else
|
28
|
+
arguments =
|
29
|
+
@arguments.map do |argument|
|
30
|
+
::Code::Object::Argument.new(
|
31
|
+
argument.evaluate(**args),
|
32
|
+
name: argument.name,
|
33
|
+
splat: argument.splat?,
|
34
|
+
keyword_splat: argument.keyword_splat?,
|
35
|
+
block: argument.block?,
|
36
|
+
)
|
37
|
+
end
|
15
38
|
|
16
|
-
|
39
|
+
if @block
|
40
|
+
arguments << ::Code::Object::Argument.new(
|
41
|
+
@block.evaluate(**args),
|
42
|
+
block: true,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
@left.evaluate(**args.merge(arguments: arguments))
|
47
|
+
end
|
48
|
+
end
|
17
49
|
end
|
18
50
|
end
|
19
51
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Code
|
2
|
+
class Node
|
3
|
+
class CallArgument < Node
|
4
|
+
def initialize(argument)
|
5
|
+
if argument.key?(:regular)
|
6
|
+
@argument =
|
7
|
+
::Code::Node::RegularCallArgument.new(argument.fetch(:regular))
|
8
|
+
elsif argument.key?(:keyword)
|
9
|
+
@argument =
|
10
|
+
::Code::Node::KeywordCallArgument.new(argument.fetch(:keyword))
|
11
|
+
else
|
12
|
+
raise NotImplementedError.new(argument.inspect)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def evaluate(**args)
|
17
|
+
@argument.evaluate(**args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
@argument.name
|
22
|
+
end
|
23
|
+
|
24
|
+
def block?
|
25
|
+
@argument.block?
|
26
|
+
end
|
27
|
+
|
28
|
+
def splat?
|
29
|
+
@argument.splat?
|
30
|
+
end
|
31
|
+
|
32
|
+
def keyword_splat?
|
33
|
+
@argument.keyword_splat?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Code
|
2
|
+
class Node
|
3
|
+
class ChainedCall < Node
|
4
|
+
def initialize(chained_call)
|
5
|
+
@name = ::Code::Node::Name.new(chained_call.fetch(:name))
|
6
|
+
|
7
|
+
@arguments = chained_call.fetch(:arguments, [])
|
8
|
+
@arguments.map! { |argument| ::Code::Node::CallArgument.new(argument) }
|
9
|
+
|
10
|
+
if chained_call.key?(:block)
|
11
|
+
@block = ::Code::Node::Block.new(chained_call.fetch(:block))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def evaluate(**args)
|
16
|
+
arguments =
|
17
|
+
@arguments.map do |argument|
|
18
|
+
::Code::Object::Argument.new(
|
19
|
+
argument.evaluate(**args.merge(object: nil)),
|
20
|
+
name: argument.name,
|
21
|
+
splat: argument.splat?,
|
22
|
+
keyword_splat: argument.keyword_splat?,
|
23
|
+
block: argument.block?,
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
if @block
|
28
|
+
arguments << ::Code::Object::Argument.new(
|
29
|
+
@block.evaluate(**args.merge(object: nil)),
|
30
|
+
block: true,
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
@name.evaluate(**args.merge(arguments: arguments))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/code/node/code.rb
CHANGED
@@ -1,18 +1,15 @@
|
|
1
|
-
require "active_support"
|
2
|
-
require "active_support/core_ext/object/blank"
|
3
|
-
|
4
1
|
class Code
|
5
2
|
class Node
|
6
|
-
class Code
|
3
|
+
class Code < Node
|
7
4
|
def initialize(statements)
|
8
|
-
statements = [] if statements.blank?
|
5
|
+
statements = [] if statements.to_s.blank?
|
9
6
|
|
10
7
|
@statements =
|
11
8
|
statements.map { |statement| ::Code::Node::Statement.new(statement) }
|
12
9
|
end
|
13
10
|
|
14
|
-
def evaluate(
|
15
|
-
@statements.map { |statement| statement.evaluate(
|
11
|
+
def evaluate(**args)
|
12
|
+
@statements.map { |statement| statement.evaluate(**args) }.last
|
16
13
|
end
|
17
14
|
end
|
18
15
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Code
|
2
|
+
class Node
|
3
|
+
class Defined < Node
|
4
|
+
def initialize(defined)
|
5
|
+
@name = defined.fetch(:name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def evaluate(**args)
|
9
|
+
::Code::Object::Boolean.new(args.fetch(:context).key?(name))
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def name
|
15
|
+
::Code::Object::String.new(@name.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
class Code
|
2
2
|
class Node
|
3
|
-
class Dictionnary
|
3
|
+
class Dictionnary < Node
|
4
4
|
def initialize(key_values)
|
5
|
-
|
6
|
-
key_values
|
7
|
-
|
8
|
-
|
5
|
+
if key_values.blank?
|
6
|
+
@key_values = []
|
7
|
+
else
|
8
|
+
@key_values =
|
9
|
+
key_values.map do |key_value|
|
10
|
+
::Code::Node::DictionnaryKeyValue.new(key_value)
|
11
|
+
end
|
12
|
+
end
|
9
13
|
end
|
10
14
|
|
11
|
-
def evaluate(
|
15
|
+
def evaluate(**args)
|
12
16
|
::Code::Object::Dictionnary.new(
|
13
|
-
@key_values.map { |key_value| key_value.evaluate(
|
17
|
+
@key_values.map { |key_value| key_value.evaluate(**args) }.to_h,
|
14
18
|
)
|
15
19
|
end
|
16
20
|
end
|