jaina 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +19 -0
- data/README.md +160 -1
- data/jaina.gemspec +2 -1
- data/lib/jaina/parser/ast/context.rb +98 -0
- data/lib/jaina/parser/ast/evaluator.rb +17 -0
- data/lib/jaina/parser/ast/tree.rb +35 -0
- data/lib/jaina/parser/ast/tree_builder.rb +129 -0
- data/lib/jaina/parser/ast.rb +62 -0
- data/lib/jaina/parser/code_converter/to_postfix_form.rb +167 -0
- data/lib/jaina/parser/code_converter/to_prefix_form.rb +122 -0
- data/lib/jaina/parser/code_converter.rb +28 -0
- data/lib/jaina/parser/expression/operator/abstract/dsl.rb +256 -0
- data/lib/jaina/parser/expression/operator/abstract.rb +67 -0
- data/lib/jaina/parser/expression/operator/and.rb +12 -0
- data/lib/jaina/parser/expression/operator/grouping/dsl.rb +100 -0
- data/lib/jaina/parser/expression/operator/grouping.rb +12 -0
- data/lib/jaina/parser/expression/operator/left_corner.rb +10 -0
- data/lib/jaina/parser/expression/operator/non_terminal.rb +25 -0
- data/lib/jaina/parser/expression/operator/not.rb +12 -0
- data/lib/jaina/parser/expression/operator/or.rb +12 -0
- data/lib/jaina/parser/expression/operator/right_corner.rb +10 -0
- data/lib/jaina/parser/expression/operator/terminal.rb +25 -0
- data/lib/jaina/parser/expression/operator.rb +15 -0
- data/lib/jaina/parser/expression/registry/access_interface_mixin.rb +49 -0
- data/lib/jaina/parser/expression/registry.rb +127 -0
- data/lib/jaina/parser/expression.rb +87 -0
- data/lib/jaina/parser/tokenizer.rb +37 -0
- data/lib/jaina/parser.rb +44 -0
- data/lib/jaina/version.rb +5 -1
- data/lib/jaina.rb +58 -4
- metadata +29 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b071350b636b4d475d51836639fa20c3b62f5518eddd4d0e71aa70cf9a9a1f9
|
4
|
+
data.tar.gz: eec63665a26dc9de484fd162795332e79762e2b4da24a637753468b06c5cfd8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56422133b95ab2bbfdcb720aea41a320d0c147e26ffca1de3fcf1a7cc013af2bb2cc9462634eee9dc4f1296584a6488b9fc63555aafc6bd37814e01d000c6f35
|
7
|
+
data.tar.gz: e5127b38022694809fd58644d86b9434bd4e368d1467b2a13d36ebe22103b5117a29bc2aaa11b6298dae0109f1ae6dea9f0d11983db52e45c3f1b447000ee54b
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
matrix:
|
3
|
+
fast_finish: true
|
4
|
+
include:
|
5
|
+
- rvm: 2.3
|
6
|
+
- rvm: 2.4
|
7
|
+
- rvm: 2.5
|
8
|
+
- rvm: 2.6
|
9
|
+
- rvm: ruby-head
|
10
|
+
- rvm: jruby-head
|
11
|
+
allow_failures:
|
12
|
+
- rvm: ruby-head
|
13
|
+
- rvm: jruby-head
|
14
|
+
sudo: false
|
15
|
+
cache: bundler
|
16
|
+
before_install: gem install bundler
|
17
|
+
script:
|
18
|
+
- bundke exec rubocop
|
19
|
+
- bundle exec rspec
|
data/README.md
CHANGED
@@ -1 +1,160 @@
|
|
1
|
-
# Jaina
|
1
|
+
# Jaina · [![Gem Version](https://badge.fury.io/rb/jaina.svg)](https://badge.fury.io/rb/jaina) [![Build Status](https://travis-ci.org/0exp/jaina.svg?branch=master)](https://travis-ci.org/0exp/jaina) [![Coverage Status](https://coveralls.io/repos/github/0exp/jaina/badge.svg?branch=master)](https://coveralls.io/github/0exp/jaina?branch=master)
|
2
|
+
|
3
|
+
Simple programming language builder inspired by interpreter pattern.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'jaina'
|
9
|
+
```
|
10
|
+
|
11
|
+
```shell
|
12
|
+
$ bundle install
|
13
|
+
# --- or ---
|
14
|
+
$ gem install 'jaina'
|
15
|
+
```
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'jaina'
|
19
|
+
```
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
- [Registered operators](#registered-operators)
|
24
|
+
- [Register your own operator](#register-your-own-operator)
|
25
|
+
- [Register your own operand](#register-your-own-operand)
|
26
|
+
- [Context API](#context-api)
|
27
|
+
- [Parse your code (build AST)](#parse-your-code-build-ast)
|
28
|
+
- [Evaluate your code](#evaluate-your-code)
|
29
|
+
- [List registered operands and operators](#list-and-fetch-registered-operands-and-operators)
|
30
|
+
|
31
|
+
---
|
32
|
+
|
33
|
+
### Registered operators
|
34
|
+
|
35
|
+
- `AND`
|
36
|
+
- `OR`
|
37
|
+
- `NOT`
|
38
|
+
- `(`, `)` (grouping operators)
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
### Register your own operator
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# step 1: define new operator
|
46
|
+
class But < Jaina::NonTerminalExpr
|
47
|
+
token 'BUT' # use it in your program :)
|
48
|
+
associativity_direction :left # associativity (left or right)
|
49
|
+
acts_as_binary_term # binar or unary
|
50
|
+
precedence_level 4 # for example: AND > OR, NOT > AND, and etc...
|
51
|
+
end
|
52
|
+
|
53
|
+
# step 2: regsiter your operator
|
54
|
+
Jaina.register_expression(But)
|
55
|
+
```
|
56
|
+
|
57
|
+
---
|
58
|
+
|
59
|
+
### Register your own operand
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
# step 1: define new operand
|
63
|
+
class A < Jaina::TerminalExpr
|
64
|
+
token 'A'
|
65
|
+
|
66
|
+
# NOTE: context is a custom data holder that passed from expression to expression
|
67
|
+
def evaluate(context)
|
68
|
+
# your custom evaluation code
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# step 2: regsiter your operand
|
73
|
+
Jaina.register_expression(A)
|
74
|
+
```
|
75
|
+
|
76
|
+
---
|
77
|
+
|
78
|
+
### Context API
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class A < Jaina::TerminalExpr
|
82
|
+
# ... some code
|
83
|
+
|
84
|
+
def evaluate(context)
|
85
|
+
... your code ...
|
86
|
+
# ... context ???
|
87
|
+
... your code ...
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# NOTE: context api
|
92
|
+
|
93
|
+
context.keys # => []
|
94
|
+
context.set(:a, 1) # => 1
|
95
|
+
context.get(:a) # => 1
|
96
|
+
context.keys # => [:a]
|
97
|
+
context.get(:b) # => Jaina::Parser::AST::Contex::UndefinedContextKeyError
|
98
|
+
```
|
99
|
+
|
100
|
+
---
|
101
|
+
|
102
|
+
### Parse your code (build AST)
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
Jaina.parse('A AND B AND (C OR D) OR A AND (C OR E)')
|
106
|
+
# => #<Jaina::Parser::AST:0x00007fd6f424a2e8>
|
107
|
+
```
|
108
|
+
|
109
|
+
---
|
110
|
+
|
111
|
+
### Evaluate your code
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
ast = Jaina.parse('A AND B AND (C OR D) OR A AND (C OR E)')
|
115
|
+
ast.evaluate
|
116
|
+
|
117
|
+
# --- or ---
|
118
|
+
Jaina.evaluate('A AND B AND (C OR D) OR A AND (C OR E)')
|
119
|
+
```
|
120
|
+
|
121
|
+
---
|
122
|
+
|
123
|
+
### List and fetch registered operands and operators
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
A = Class.new(Jaina::TerminalExpr) { token 'A' }
|
127
|
+
B = Class.new(Jaina::TerminalExpr) { token 'B' }
|
128
|
+
C = Class.new(Jaina::TerminalExpr) { token 'C' }
|
129
|
+
|
130
|
+
Jaina.register_expression(A)
|
131
|
+
Jaina.register_expression(B)
|
132
|
+
Jaina.register_expression(C)
|
133
|
+
|
134
|
+
Jaina.expressions
|
135
|
+
# => ["AND", "OR", "NOT", "(", ")", "A", "B", "C"]
|
136
|
+
|
137
|
+
Jaina.fetch_expression("AND") # => Jaina::Parser::Expression::Operator::And
|
138
|
+
Jaina.fetch_expression("A") # => A
|
139
|
+
|
140
|
+
Jaina.fetch_expression("KEK")
|
141
|
+
# => raises Jaina::Parser::Expression::Registry::UnregisteredExpressionError
|
142
|
+
```
|
143
|
+
|
144
|
+
---
|
145
|
+
|
146
|
+
## Contributing
|
147
|
+
|
148
|
+
- Fork it ( https://github.com/0exp/jaina/fork )
|
149
|
+
- Create your feature branch (`git checkout -b feature/my-new-feature`)
|
150
|
+
- Commit your changes (`git commit -am 'Add some feature'`)
|
151
|
+
- Push to the branch (`git push origin feature/my-new-feature`)
|
152
|
+
- Create new Pull Request
|
153
|
+
|
154
|
+
## License
|
155
|
+
|
156
|
+
Released under MIT License.
|
157
|
+
|
158
|
+
## Authors
|
159
|
+
|
160
|
+
[Rustam Ibragimov](https://github.com/0exp)
|
data/jaina.gemspec
CHANGED
@@ -13,7 +13,8 @@ Gem::Specification.new do |spec|
|
|
13
13
|
|
14
14
|
spec.homepage = 'https://github.com/0exp/jaina'
|
15
15
|
spec.summary = 'Simple programming language builder inspired by interpreter pattern.'
|
16
|
-
spec.description = 'Simple programming language builder inspired by interpreter pattern.'
|
16
|
+
spec.description = 'Simple programming language builder inspired by interpreter pattern. ' \
|
17
|
+
'You can build your own langs for any project purposes.'
|
17
18
|
|
18
19
|
spec.bindir = 'bin'
|
19
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST::Context
|
6
|
+
# @since 0.1.0
|
7
|
+
Error = Class.new(StandardError)
|
8
|
+
# @since 0.1.0
|
9
|
+
UndefinedContextKeyError = Class.new(Error)
|
10
|
+
|
11
|
+
# @return [void]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
def initialize
|
16
|
+
@data = {}
|
17
|
+
@access_lock = Mutex.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param key [Any]
|
21
|
+
# @param value [Any]
|
22
|
+
# @return [Any]
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
# @since 0.1.0
|
26
|
+
def set(key, value)
|
27
|
+
thread_safe { apply(key, value) }
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param key [Any]
|
31
|
+
# @return [Any]
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
# @since 0.1.0
|
35
|
+
def get(key)
|
36
|
+
thread_safe { get(key) }
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array<Any>]
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
# @since 0.1.0
|
43
|
+
def keys
|
44
|
+
thread_safe { registered_data }
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# @return [Hash<Any,Any>]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.1.0
|
53
|
+
attr_reader :data
|
54
|
+
|
55
|
+
# @return [Mutex]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
attr_reader :access_lock
|
60
|
+
|
61
|
+
# @param block [Proc]
|
62
|
+
# @return [Any]
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
# @since 0.1.0
|
66
|
+
def thread_safe(&block)
|
67
|
+
access_lock.synchronize { yield }
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param key [Any]
|
71
|
+
# @param value [Any]
|
72
|
+
# @return [Any]
|
73
|
+
#
|
74
|
+
# @api private
|
75
|
+
# @since 0.1.0
|
76
|
+
def apply(key, value)
|
77
|
+
value.tap { data[key] = value }
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Array<Any>]
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
# @since 0.1.0
|
84
|
+
def registered_data
|
85
|
+
data.keys
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param key [String]
|
89
|
+
# @return [Any]
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
# @since 0.1.0
|
93
|
+
def fetch(key)
|
94
|
+
data.fetch(key)
|
95
|
+
rescue KeyError
|
96
|
+
raise UndefinedContextKeyError, "Data with `#{key}` key does not exist"
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
module Jaina::Parser::AST::Evaluator
|
6
|
+
class << self
|
7
|
+
# @param ast [Jaina::Parser::AST]
|
8
|
+
# @return [Any]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
def evaluate(ast)
|
13
|
+
context = Jaina::Parser::AST::Context.new
|
14
|
+
# TODO: traverse the abstract syntax tree
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST::Tree
|
6
|
+
# @return [String]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.1.0
|
10
|
+
attr_reader :initial_program
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.1.0
|
16
|
+
attr_reader :ast_oriented_program
|
17
|
+
|
18
|
+
# @return [Jaina::Parser::Expression::Operator::Abstract]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.1.0
|
22
|
+
attr_reader :expression
|
23
|
+
|
24
|
+
# @param initial_program [String]
|
25
|
+
# @param expression [Jaina::Parser::Expression::Operator::Abstract]
|
26
|
+
# @return [void]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
# @since 0.1.0
|
30
|
+
def initialize(initial_program:, ast_oriented_program:, expression:)
|
31
|
+
@initial_program = initial_program
|
32
|
+
@ast_oriented_program = ast_oriented_program
|
33
|
+
@expression = expression
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST::TreeBuilder
|
6
|
+
# @since 0.1.0
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# @param program [String]
|
11
|
+
# @return [Jaina::Parser::AST::Tree]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
def build(program)
|
16
|
+
new(program).build
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @since 0.1.0
|
21
|
+
def_delegators Jaina::Parser::Expression,
|
22
|
+
:terminal?,
|
23
|
+
:non_terminal?,
|
24
|
+
:acts_as_unary_term?,
|
25
|
+
:acts_as_binary_term?
|
26
|
+
|
27
|
+
# @param progrm [String]
|
28
|
+
# @return [void]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
# @since 0.1.0
|
32
|
+
def initialize(program)
|
33
|
+
@program = program.dup.tap(&:freeze)
|
34
|
+
@prefix_form = Jaina::Parser::CodeConverter.to_prefix_form(@program)
|
35
|
+
@tokens = Jaina::Parser::Tokenizer.tokenize(@prefix_form)
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [Jaina::Parser::AST:Tree]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
def build
|
43
|
+
token_series = tokens.map(&:dup)
|
44
|
+
expression_tree = build_expression_tree(token_series)
|
45
|
+
|
46
|
+
Jaina::Parser::AST::Tree.new(
|
47
|
+
initial_program: program,
|
48
|
+
ast_oriented_program: prefix_form,
|
49
|
+
expression: expression_tree
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# @return [String]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
attr_reader :program
|
60
|
+
|
61
|
+
# @return [String]
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
# @since 0.1.0
|
65
|
+
attr_reader :prefix_form
|
66
|
+
|
67
|
+
# @return [Array<String>]
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
# @since 0.1.0
|
71
|
+
attr_reader :tokens
|
72
|
+
|
73
|
+
# @param token_series [Array<String>]
|
74
|
+
# @return [Array<Jaina::Parser::Expression::Operator::Abstract>]
|
75
|
+
#
|
76
|
+
# @api private
|
77
|
+
# @since 0.1.0
|
78
|
+
def build_expression_tree(token_series)
|
79
|
+
current_token = extract_second_token(token_series)
|
80
|
+
return if current_token.nil?
|
81
|
+
|
82
|
+
case
|
83
|
+
when terminal?(current_token)
|
84
|
+
build_terminal_expression(current_token)
|
85
|
+
when non_terminal?(current_token)
|
86
|
+
build_non_terminal_expression(current_token, token_series)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param token_series [Array<String>]
|
91
|
+
# @return [String, NilClass]
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
# @since 0.1.0
|
95
|
+
def extract_second_token(token_series)
|
96
|
+
token_series.shift
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param current_token [String]
|
100
|
+
# @return [Jaina::Parser::Expression::Operator::Abstract]
|
101
|
+
#
|
102
|
+
# @api private
|
103
|
+
# @since 0.1.0
|
104
|
+
def build_terminal_expression(current_token)
|
105
|
+
Jaina::Parser::Expression.build(current_token)
|
106
|
+
end
|
107
|
+
|
108
|
+
# @param current_token [String]
|
109
|
+
# @param token_series [Array<String>]
|
110
|
+
# @return [Jaina::Parser::Expression::Operator::Abstract]
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
# @since 0.1.0
|
114
|
+
def build_non_terminal_expression(current_token, token_series)
|
115
|
+
case
|
116
|
+
when acts_as_unary_term?(current_token)
|
117
|
+
Jaina::Parser::Expression.build(
|
118
|
+
current_token,
|
119
|
+
build_expression_tree(token_series)
|
120
|
+
)
|
121
|
+
when acts_as_binary_term?(current_token)
|
122
|
+
Jaina::Parser::Expression.build(
|
123
|
+
current_token,
|
124
|
+
build_expression_tree(token_series),
|
125
|
+
build_expression_tree(token_series)
|
126
|
+
)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.1.0
|
5
|
+
class Jaina::Parser::AST
|
6
|
+
require_relative './ast/tree'
|
7
|
+
require_relative './ast/tree_builder'
|
8
|
+
require_relative './ast/evaluator'
|
9
|
+
require_relative './ast/context'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# @param program [String] Program string in prefix form
|
13
|
+
# @return [Jaina::Parser::AST]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
# @since 0.1.0
|
17
|
+
def build(program)
|
18
|
+
ast_tree = Jaina::Parser::AST::TreeBuilder.build(program)
|
19
|
+
new(program, ast_tree)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param program [String] Program string in prefix form
|
23
|
+
# @return [Any]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
# @since 0.1.0
|
27
|
+
def evaluate(program)
|
28
|
+
build(program).evaluate
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Jaina::Pasrer::AST::Tree]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.1.0
|
36
|
+
attr_reader :ast_tree
|
37
|
+
|
38
|
+
# @return [String]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.1.0
|
42
|
+
attr_reader :program
|
43
|
+
|
44
|
+
# @param program [String]
|
45
|
+
# @param ast_tree [Jaina::Parser::AST::Tree]
|
46
|
+
# @return [void]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @since 0.1.0
|
50
|
+
def initialize(program, ast_tree)
|
51
|
+
@program = program.dup.tap(&:freeze)
|
52
|
+
@ast_tree = ast_tree
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Any]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.1.0
|
59
|
+
def evaluate
|
60
|
+
Jaina::Parser::AST::Evaluator.evaluate(self)
|
61
|
+
end
|
62
|
+
end
|