rox-rollout 4.7.3 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +34 -13
- data/.editorconfig +12 -0
- data/.github/workflows/ruby.yml +20 -0
- data/.rubocop.yml +17 -0
- data/Gemfile +2 -2
- data/README.md +32 -0
- data/Rakefile +12 -9
- data/bin/console +3 -4
- data/e2e-server/run_server.sh +12 -0
- data/e2e-server/server.rb +158 -0
- data/e2e/container.rb +11 -14
- data/e2e/custom_props.rb +9 -9
- data/e2e/rox_e2e_test.rb +17 -19
- data/e2e/test_vars.rb +3 -6
- data/example/local.rb +40 -0
- data/lib/rox/core/analytics.rb +18 -0
- data/lib/rox/core/client/buid.rb +8 -8
- data/lib/rox/core/client/device_properties.rb +7 -1
- data/lib/rox/core/client/dynamic_api.rb +53 -15
- data/lib/rox/core/client/internal_flags.rb +14 -2
- data/lib/rox/core/client/sdk_settings.rb +1 -1
- data/lib/rox/core/configuration/configuration.rb +1 -1
- data/lib/rox/core/configuration/configuration_fetched_args.rb +2 -2
- data/lib/rox/core/configuration/configuration_fetched_invoker.rb +8 -3
- data/lib/rox/core/configuration/configuration_parser.rb +38 -37
- data/lib/rox/core/configuration/fetcher_error.rb +1 -1
- data/lib/rox/core/configuration/fetcher_status.rb +1 -1
- data/lib/rox/core/configuration/models/experiment_model.rb +1 -1
- data/lib/rox/core/configuration/models/target_group_model.rb +1 -1
- data/lib/rox/core/consts/build.rb +2 -2
- data/lib/rox/core/consts/environment.rb +10 -8
- data/lib/rox/core/consts/property_type.rb +16 -17
- data/lib/rox/core/context/merged_context.rb +2 -1
- data/lib/rox/core/core.rb +88 -38
- data/lib/rox/core/entities/default_flag_values.rb +10 -0
- data/lib/rox/core/entities/flag.rb +22 -7
- data/lib/rox/core/entities/flag_setter.rb +6 -6
- data/lib/rox/core/entities/rox_double.rb +11 -0
- data/lib/rox/core/entities/rox_int.rb +11 -0
- data/lib/rox/core/entities/{variant.rb → rox_string.rb} +20 -13
- data/lib/rox/core/error_handling/exception_trigger.rb +10 -0
- data/lib/rox/core/error_handling/userspace_handler_exception.rb +12 -0
- data/lib/rox/core/error_handling/userspace_unhandled_error_invoker.rb +41 -0
- data/lib/rox/core/impression/impression_args.rb +2 -2
- data/lib/rox/core/impression/impression_invoker.rb +41 -7
- data/lib/rox/core/impression/models/experiment.rb +1 -1
- data/lib/rox/core/impression/models/reporting_value.rb +10 -2
- data/lib/rox/core/logging/logging.rb +3 -3
- data/lib/rox/core/logging/no_op_logger.rb +1 -1
- data/lib/rox/core/network/configuration_fetcher.rb +2 -2
- data/lib/rox/core/network/configuration_fetcher_roxy.rb +2 -2
- data/lib/rox/core/network/configuration_fetcher_self_managed.rb +30 -0
- data/lib/rox/core/network/configuration_source.rb +1 -1
- data/lib/rox/core/network/request.rb +1 -1
- data/lib/rox/core/network/request_configuration_builder.rb +5 -5
- data/lib/rox/core/network/request_data.rb +1 -1
- data/lib/rox/core/network/response.rb +6 -8
- data/lib/rox/core/network/state_sender.rb +61 -18
- data/lib/rox/core/notifications/notification_listener.rb +4 -4
- data/lib/rox/core/properties/custom_property.rb +1 -1
- data/lib/rox/core/properties/custom_property_type.rb +1 -1
- data/lib/rox/core/properties/device_property.rb +2 -2
- data/lib/rox/core/properties/property_factory.rb +132 -0
- data/lib/rox/core/register/registerer.rb +13 -12
- data/lib/rox/core/reporting/error_reporter.rb +14 -13
- data/lib/rox/core/repositories/experiment_repository.rb +2 -4
- data/lib/rox/core/repositories/flag_repository.rb +7 -7
- data/lib/rox/core/repositories/roxx/experiments_extensions.rb +8 -8
- data/lib/rox/core/repositories/roxx/properties_extensions.rb +32 -7
- data/lib/rox/core/repositories/target_group_repository.rb +2 -4
- data/lib/rox/core/roxx/evaluation_result.rb +2 -0
- data/lib/rox/core/roxx/node.rb +1 -1
- data/lib/rox/core/roxx/parser.rb +35 -21
- data/lib/rox/core/roxx/regular_expression_extensions.rb +6 -3
- data/lib/rox/core/roxx/string_tokenizer.rb +3 -1
- data/lib/rox/core/roxx/symbols.rb +1 -1
- data/lib/rox/core/roxx/token_type.rb +1 -1
- data/lib/rox/core/roxx/tokenized_expression.rb +16 -12
- data/lib/rox/core/roxx/value_compare_extensions.rb +49 -29
- data/lib/rox/core/security/signature_verifier.rb +3 -3
- data/lib/rox/core/security/signature_verifier_mock.rb +12 -0
- data/lib/rox/core/utils/type_utils.rb +1 -1
- data/lib/rox/server/client/server_properties.rb +1 -1
- data/lib/rox/server/flags/normalize_flag_type.rb +25 -0
- data/lib/rox/server/flags/rox_double.rb +8 -0
- data/lib/rox/server/flags/rox_flag.rb +1 -1
- data/lib/rox/server/flags/rox_int.rb +8 -0
- data/lib/rox/server/flags/rox_string.rb +8 -0
- data/lib/rox/server/flags/server_entities_provider.rb +14 -4
- data/lib/rox/server/logging/server_logger.rb +2 -2
- data/lib/rox/server/rox_options.rb +39 -8
- data/lib/rox/server/rox_server.rb +80 -59
- data/lib/rox/version.rb +1 -1
- data/rox.gemspec +11 -9
- metadata +66 -37
- data/CODEOWNERS +0 -1
- data/README_DEVELOP.md +0 -25
- data/_archive/.document +0 -5
- data/_archive/.rspec +0 -1
- data/_archive/Gemfile +0 -15
- data/_archive/README.md +0 -32
- data/_archive/README.rdoc +0 -19
- data/_archive/Rakefile +0 -50
- data/_archive/lib/expr_function_definition.rb +0 -52
- data/_archive/lib/function_definition.rb +0 -48
- data/_archive/lib/function_token.rb +0 -12
- data/_archive/lib/object_extends.rb +0 -12
- data/_archive/lib/ruby_interpreter.rb +0 -292
- data/_archive/lib/stack.rb +0 -48
- data/_archive/lib/string_extends.rb +0 -14
- data/_archive/spec/ruby_interpreter_spec.rb +0 -203
- data/_archive/spec/spec_helper.rb +0 -30
- data/_archive/spec/stack_spec.rb +0 -77
- data/lib/rox/server/flags/rox_variant.rb +0 -8
data/CODEOWNERS
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
* @joshpuetz
|
data/README_DEVELOP.md
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# Developer Guide
|
2
|
-
|
3
|
-
Ruby versions supported: 2.3.x, 2.4.x, 2.5.x, 2.6.x
|
4
|
-
|
5
|
-
## Run tests on current Ruby version
|
6
|
-
|
7
|
-
```
|
8
|
-
// Run unit tests (folder 'tests')
|
9
|
-
rake test
|
10
|
-
|
11
|
-
// Run E2E tests (folder 'e2e')
|
12
|
-
rake e2e
|
13
|
-
```
|
14
|
-
|
15
|
-
## Publish new version
|
16
|
-
|
17
|
-
### Steps
|
18
|
-
|
19
|
-
1. Increment version in ```lib/rox/version.rb```, open a PR and wait for CI to clear
|
20
|
-
2. Merge to master, wait for CI to clear
|
21
|
-
2. Generate the gem package: ```gem build rox.gemspec```
|
22
|
-
3. Install gem locally, and test with a sample project
|
23
|
-
4. Upload to RubyGems: ```gem push rox-rollout-VERSION.gem```
|
24
|
-
5. Update documentation at https://support.rollout.io/docs/ruby-changelog
|
25
|
-
6. Celebrate! 🎉
|
data/_archive/.document
DELETED
data/_archive/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|
data/_archive/Gemfile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
# Add dependencies required to use your gem here.
|
3
|
-
# Example:
|
4
|
-
# gem "activesupport", ">= 2.3.5"
|
5
|
-
|
6
|
-
# Add dependencies to develop your gem here.
|
7
|
-
# Include everything needed to run rake, tests, features, etc.
|
8
|
-
group :development do
|
9
|
-
gem 'pry'
|
10
|
-
gem "rspec", "~> 3.5.0"
|
11
|
-
gem "rdoc", "~> 3.12"
|
12
|
-
gem "bundler", "~> 1.0"
|
13
|
-
gem "jeweler", "~> 2.0.1"
|
14
|
-
gem "simplecov", ">= 0"
|
15
|
-
end
|
data/_archive/README.md
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
![Rollout](https://1ko9923xosh2dsbjsxpwqp45-wpengine.netdna-ssl.com/wp-content/themes/rollout/images/rollout_white_logo1.png)
|
2
|
-
|
3
|
-
Rollout is a Secure Feature Managment Solution for the Enterprise.
|
4
|
-
|
5
|
-
> Accelerate development and minimize the risk of deploying new code with simple to create feature flags, controlled rollouts, advanced target groups & deployment rules.
|
6
|
-
|
7
|
-
## Getting Started
|
8
|
-
|
9
|
-
Please see the detailed instructions in our docs how to [add Rollout to your project](https://support.rollout.io/docs/installing-the-sdk).
|
10
|
-
|
11
|
-
## Documentation
|
12
|
-
|
13
|
-
Getting started guide, use cases, examples and videos can be found in [Rollout support site](https://support.rollout.io)
|
14
|
-
|
15
|
-
# Rollout Ruby SDK
|
16
|
-
|
17
|
-
Rollout Ruby SDK. Define and use simple and advanced feature flags, remote configuration variables, static and computed custom properties in code. Control your application features via Rollout's dashboard.
|
18
|
-
|
19
|
-
## Installation
|
20
|
-
```
|
21
|
-
gem install rox-rollout
|
22
|
-
```
|
23
|
-
|
24
|
-
## LICENSE
|
25
|
-
|
26
|
-
Rollout is free-to-use, proprietary software. Please see the full license (found in LICENSE in this distribution) for details on its license and the licenses of its dependencies.
|
27
|
-
|
28
|
-
Rollout Ruby SDK is free-to-use, proprietary software. Please see the full license found under the LICENSE file for more details.
|
29
|
-
|
30
|
-
## Feedback
|
31
|
-
|
32
|
-
Feedback is always welcomed support@rollout.io
|
data/_archive/README.rdoc
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
= ruby-interpreter
|
2
|
-
|
3
|
-
Description goes here.
|
4
|
-
|
5
|
-
== Contributing to ruby-interpreter
|
6
|
-
|
7
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
-
* Fork the project.
|
10
|
-
* Start a feature/bugfix branch.
|
11
|
-
* Commit and push until you are happy with your contribution.
|
12
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
-
|
15
|
-
== Copyright
|
16
|
-
|
17
|
-
Copyright (c) 2018 stoarch. See LICENSE.txt for
|
18
|
-
further details.
|
19
|
-
|
data/_archive/Rakefile
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
begin
|
6
|
-
Bundler.setup(:default, :development)
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts e.message
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
require 'rake'
|
13
|
-
|
14
|
-
require 'jeweler'
|
15
|
-
Jeweler::Tasks.new do |gem|
|
16
|
-
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
17
|
-
gem.name = "ruby-interpreter"
|
18
|
-
gem.homepage = "http://github.com/stoarch/ruby-interpreter"
|
19
|
-
gem.license = "MIT"
|
20
|
-
gem.summary = %Q{TODO: one-line summary of your gem}
|
21
|
-
gem.description = %Q{TODO: longer description of your gem}
|
22
|
-
gem.email = "stormarchitextor@gmail.com"
|
23
|
-
gem.authors = ["stoarch"]
|
24
|
-
# dependencies defined in Gemfile
|
25
|
-
end
|
26
|
-
Jeweler::RubygemsDotOrgTasks.new
|
27
|
-
|
28
|
-
require 'rspec/core'
|
29
|
-
require 'rspec/core/rake_task'
|
30
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
-
end
|
33
|
-
|
34
|
-
desc "Code coverage detail"
|
35
|
-
task :simplecov do
|
36
|
-
ENV['COVERAGE'] = "true"
|
37
|
-
Rake::Task['spec'].execute
|
38
|
-
end
|
39
|
-
|
40
|
-
task :default => :spec
|
41
|
-
|
42
|
-
require 'rdoc/task'
|
43
|
-
Rake::RDocTask.new do |rdoc|
|
44
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
-
|
46
|
-
rdoc.rdoc_dir = 'rdoc'
|
47
|
-
rdoc.title = "ruby-interpreter #{version}"
|
48
|
-
rdoc.rdoc_files.include('README*')
|
49
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
|
2
|
-
module ExprFunctionDefinition
|
3
|
-
def add_func(name)
|
4
|
-
@func_list ||= []
|
5
|
-
@func_list << name unless @func_list.include? name
|
6
|
-
end
|
7
|
-
|
8
|
-
def unary_bool_func(name, operator)
|
9
|
-
add_func(name.to_s)
|
10
|
-
|
11
|
-
define_method("evaluate_#{name.to_s}") do
|
12
|
-
|
13
|
-
a = @stack.pop
|
14
|
-
|
15
|
-
res = a.evaluate.to_boolean.send(operator.to_sym)
|
16
|
-
|
17
|
-
@stack.push BooleanValue.new(res, @stack)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def bool_func(name, operator)
|
22
|
-
add_func(name.to_s)
|
23
|
-
|
24
|
-
define_method("evaluate_#{name.to_s}") do
|
25
|
-
|
26
|
-
a = @stack.pop
|
27
|
-
b = @stack.pop
|
28
|
-
|
29
|
-
res = a.evaluate.send(operator.to_sym, b.evaluate)
|
30
|
-
@stack.push BooleanValue.new(res, @stack)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def comp_func(name, operator)
|
35
|
-
add_func(name.to_s)
|
36
|
-
|
37
|
-
define_method("evaluate_#{name.to_s}") do
|
38
|
-
a = @stack.pop
|
39
|
-
b = @stack.pop
|
40
|
-
|
41
|
-
aval = a.evaluate
|
42
|
-
bval = b.evaluate
|
43
|
-
|
44
|
-
if( aval.class == bval.class ) #we can compare string with string and numeric with numeric only
|
45
|
-
|
46
|
-
@stack.push BooleanValue.new(aval.send(operator.to_sym, bval), @stack)
|
47
|
-
else
|
48
|
-
@stack.push BooleanValue.new(false, @stack)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
|
2
|
-
module FunctionDefinition
|
3
|
-
def add_func(name)
|
4
|
-
@func_list ||= []
|
5
|
-
@func_list << name unless @func_list.include? name
|
6
|
-
end
|
7
|
-
|
8
|
-
def unary_bool_func(name, operator)
|
9
|
-
add_func(name.to_s)
|
10
|
-
|
11
|
-
define_method("evaluate#{name[0].upcase}#{name[1..-1]}") do |stack_index|
|
12
|
-
|
13
|
-
a = @operands_stack.pop
|
14
|
-
|
15
|
-
res = a.to_boolean.send(operator.to_sym).to_s
|
16
|
-
|
17
|
-
@operands_stack.push res
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def bool_func(name, operator)
|
22
|
-
add_func(name.to_s)
|
23
|
-
|
24
|
-
define_method("evaluate#{name[0].upcase}#{name[1..-1]}") do |stack_index|
|
25
|
-
|
26
|
-
a = @operands_stack.pop
|
27
|
-
b = @operands_stack.pop
|
28
|
-
|
29
|
-
res = a.to_boolean.send(operator.to_sym, b.to_boolean).to_s
|
30
|
-
@operands_stack.push res
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def comp_func(name, operator)
|
35
|
-
add_func(name.to_s)
|
36
|
-
|
37
|
-
define_method("evaluate#{name[0].upcase}#{name[1..-1]}") do |stack_index|
|
38
|
-
a = @operands_stack.pop
|
39
|
-
b = @operands_stack.pop
|
40
|
-
|
41
|
-
if( a.class == b.class ) #we can compare string with string and numeric with numeric only
|
42
|
-
@operands_stack.push b.send(operator.to_sym, a).to_s
|
43
|
-
else
|
44
|
-
@operands_stack.push 'false'
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,292 +0,0 @@
|
|
1
|
-
require 'pry'
|
2
|
-
require_relative 'object_extends'
|
3
|
-
require_relative 'string_extends'
|
4
|
-
require_relative 'function_token'
|
5
|
-
require_relative 'function_definition'
|
6
|
-
require_relative 'expr_function_definition'
|
7
|
-
|
8
|
-
class Expression
|
9
|
-
attr :expr, :stack
|
10
|
-
|
11
|
-
def initialize(expr_val, stack)
|
12
|
-
@expr = expr_val
|
13
|
-
@stack = stack
|
14
|
-
end
|
15
|
-
|
16
|
-
def evaluate
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
@expr
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class ValueExpression < Expression
|
25
|
-
def evaluate
|
26
|
-
@expr
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class UndefinedValue < ValueExpression
|
31
|
-
end
|
32
|
-
|
33
|
-
class StringValue < ValueExpression
|
34
|
-
end
|
35
|
-
|
36
|
-
class BooleanValue < ValueExpression
|
37
|
-
def evaluate
|
38
|
-
@expr.to_boolean
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class FloatValue < ValueExpression
|
43
|
-
def evaluate
|
44
|
-
@expr
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class FunctionExpression < Expression
|
49
|
-
extend ExprFunctionDefinition
|
50
|
-
|
51
|
-
attr :evaluators
|
52
|
-
|
53
|
-
unary_bool_func :not, '!'
|
54
|
-
|
55
|
-
bool_func :and, '&'
|
56
|
-
bool_func :or, '|'
|
57
|
-
|
58
|
-
comp_func :eq, '=='
|
59
|
-
comp_func :ne, '!='
|
60
|
-
comp_func :lt, '<'
|
61
|
-
comp_func :lte, '<='
|
62
|
-
comp_func :gt, '>'
|
63
|
-
comp_func :gte, '>='
|
64
|
-
|
65
|
-
def initialize(expr_val, stack)
|
66
|
-
super(expr_val, stack)
|
67
|
-
|
68
|
-
@functions = ['isUndefined', 'now']
|
69
|
-
@functions << self.class.instance_variable_get('@func_list')
|
70
|
-
@functions.flatten!
|
71
|
-
|
72
|
-
prepare_evaluators()
|
73
|
-
end
|
74
|
-
|
75
|
-
def evaluate
|
76
|
-
ev = @evaluators[@expr]
|
77
|
-
return ev.call unless ev.nil?
|
78
|
-
|
79
|
-
#todo log invalid function
|
80
|
-
@stack.push BooleanValue.new(false, @stack) if ev.nil?
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
def prepare_evaluators()
|
86
|
-
@evaluators = @functions.map{|f| [f, ->{ self.send("evaluate_#{f}")}]}.to_h
|
87
|
-
end
|
88
|
-
|
89
|
-
def evaluate_isUndefined
|
90
|
-
a = @stack.pop
|
91
|
-
@stack.push BooleanValue.new(a.evaluate == :undefined, @stack)
|
92
|
-
end
|
93
|
-
|
94
|
-
def evaluate_now
|
95
|
-
Time.now.to_f.round(3)*1000
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
## RubyInterpreter ##
|
101
|
-
#
|
102
|
-
# goal: Interpret expression in forward polish notation with some functions
|
103
|
-
#
|
104
|
-
class RubyInterpreter
|
105
|
-
extend FunctionDefinition
|
106
|
-
|
107
|
-
attr_reader :func_stack, :operands_stack
|
108
|
-
attr_reader :expr_stack
|
109
|
-
|
110
|
-
#operators
|
111
|
-
unary_bool_func :not, '!'
|
112
|
-
|
113
|
-
bool_func :and, '&'
|
114
|
-
bool_func :or, '|'
|
115
|
-
|
116
|
-
comp_func :eq, '=='
|
117
|
-
comp_func :ne, '!='
|
118
|
-
|
119
|
-
comp_func :lt, '<'
|
120
|
-
comp_func :lte, '<='
|
121
|
-
comp_func :gt, '>'
|
122
|
-
comp_func :gte, '>='
|
123
|
-
|
124
|
-
def initialize
|
125
|
-
@func_stack = Stack.new
|
126
|
-
@operands_stack = Stack.new
|
127
|
-
@expr_stack = Stack.new
|
128
|
-
|
129
|
-
@func_list ||= []
|
130
|
-
@func_list << self.class.instance_variable_get('@func_list')
|
131
|
-
@func_list << ['isUndefined', 'now']
|
132
|
-
@func_list.flatten!
|
133
|
-
|
134
|
-
@funcs_re ||= Regexp.new(@func_list.join('|') )
|
135
|
-
end
|
136
|
-
#todo make unary/2ry functions by define_method (dry code)
|
137
|
-
|
138
|
-
def prepare_expr_stack(tokens)
|
139
|
-
is_string_token = false
|
140
|
-
string_token = ''
|
141
|
-
|
142
|
-
tokens.each do |tkn, i|
|
143
|
-
|
144
|
-
if is_string_token && tkn != '"'
|
145
|
-
string_token += tkn
|
146
|
-
next
|
147
|
-
end
|
148
|
-
|
149
|
-
case tkn
|
150
|
-
when 'undefined'
|
151
|
-
@expr_stack.push( UndefinedValue.new(tkn.to_sym, @expr_stack) )
|
152
|
-
when '"'
|
153
|
-
if( is_string_token ) #todo check pair "
|
154
|
-
is_string_token = false
|
155
|
-
@expr_stack.push StringValue.new(string_token, @expr_stack)
|
156
|
-
string_token = ''
|
157
|
-
else
|
158
|
-
is_string_token = true
|
159
|
-
end
|
160
|
-
when ',' , '(', ')', ' '
|
161
|
-
#do nothing
|
162
|
-
when @funcs_re
|
163
|
-
@expr_stack.push( FunctionExpression.new( tkn , @expr_stack) )
|
164
|
-
when 'true', 'false'
|
165
|
-
@expr_stack.push BooleanValue.new(tkn, @expr_stack)
|
166
|
-
else
|
167
|
-
fval, is_float = tkn.to_float
|
168
|
-
if(is_float)
|
169
|
-
@expr_stack.push FloatValue.new(fval, @expr_stack)
|
170
|
-
else
|
171
|
-
#todo show error message 'unknown token'
|
172
|
-
return 'false'
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def evaluate_expr_stack()
|
179
|
-
@func_evaluators = @func_list.map{|f| [f, ->(){ self.send("evaluate_func_#{f}")}]}.to_h
|
180
|
-
|
181
|
-
value = false
|
182
|
-
|
183
|
-
while !@expr_stack.empty? do
|
184
|
-
expr = @expr_stack.pop
|
185
|
-
value = expr.evaluate unless expr.nil?
|
186
|
-
|
187
|
-
return false if expr.nil? #todo show error message
|
188
|
-
end
|
189
|
-
|
190
|
-
value
|
191
|
-
end
|
192
|
-
|
193
|
-
|
194
|
-
def evaluateExpression2(expr)
|
195
|
-
@expr_stack.clear
|
196
|
-
|
197
|
-
tokens = expr.scan(/\d+\.?\d*|\s+|,|\(|"|\)|\w+|\W+/)
|
198
|
-
|
199
|
-
prepare_expr_stack(tokens)
|
200
|
-
expr_stack.invert()
|
201
|
-
evaluate_expr_stack()
|
202
|
-
end
|
203
|
-
|
204
|
-
# Evaluate expression
|
205
|
-
#
|
206
|
-
# info:
|
207
|
-
# 1. Language is polish forward notation with custom functions
|
208
|
-
# 2. Function list:
|
209
|
-
# a. and(a,b)
|
210
|
-
#
|
211
|
-
def evaluateExpression(expr)
|
212
|
-
@func_stack.clear
|
213
|
-
@operands_stack.clear
|
214
|
-
|
215
|
-
|
216
|
-
tokens = expr.scan(/\d+\.?\d*|\s+|,|\(|"|\)|\w+|\W+/)
|
217
|
-
|
218
|
-
is_string_token = false
|
219
|
-
string_token = ''
|
220
|
-
|
221
|
-
@funcs_re ||= Regexp.new(@func_list.join('|') )
|
222
|
-
|
223
|
-
#prepare stack
|
224
|
-
tokens.each do |tkn, i|
|
225
|
-
if is_string_token && tkn != '"'
|
226
|
-
string_token += tkn
|
227
|
-
next
|
228
|
-
end
|
229
|
-
|
230
|
-
case tkn
|
231
|
-
when 'undefined'
|
232
|
-
@operands_stack.push( tkn.to_sym )
|
233
|
-
when '"'
|
234
|
-
if( is_string_token ) #todo check pair "
|
235
|
-
is_string_token = false
|
236
|
-
@operands_stack.push string_token
|
237
|
-
string_token = ''
|
238
|
-
else
|
239
|
-
is_string_token = true
|
240
|
-
end
|
241
|
-
when ',' , '(', ')', ' '
|
242
|
-
#do nothing
|
243
|
-
when @funcs_re
|
244
|
-
@func_stack.push( FunctionToken.new( tkn, @operands_stack.size ) )
|
245
|
-
when 'true', 'false'
|
246
|
-
@operands_stack.push tkn
|
247
|
-
else
|
248
|
-
fval, is_float = tkn.to_float
|
249
|
-
if(is_float)
|
250
|
-
@operands_stack.push(fval)
|
251
|
-
else
|
252
|
-
#todo show error message 'unknown token'
|
253
|
-
return 'false'
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
#evaluate stack
|
259
|
-
@func_evals ||= prepare_func_evaluators()
|
260
|
-
|
261
|
-
while !@func_stack.empty? do
|
262
|
-
|
263
|
-
token = @func_stack.pop
|
264
|
-
|
265
|
-
feval = @func_evals[token.name]
|
266
|
-
|
267
|
-
feval.call(token.stack_index) unless feval.nil?
|
268
|
-
end
|
269
|
-
|
270
|
-
@operands_stack.pop
|
271
|
-
end
|
272
|
-
|
273
|
-
private
|
274
|
-
|
275
|
-
def prepare_func_evaluators()
|
276
|
-
# make hash with functors: 'or' => ->(stack_index){ self.send('evaluateOr', stack_index) }
|
277
|
-
return @func_list.map{|f| [f, ->(stack_index){ self.send("evaluate#{f[0].upcase}#{f[1..-1]}", stack_index) }]}.to_h
|
278
|
-
end
|
279
|
-
|
280
|
-
#evaluators
|
281
|
-
|
282
|
-
def evaluateIsUndefined(stack_index)
|
283
|
-
a = @operands_stack.pop
|
284
|
-
@operands_stack.push (a == :undefined).to_s
|
285
|
-
end
|
286
|
-
|
287
|
-
def evaluateNow(stack_index)
|
288
|
-
@operands_stack.insert Time.now().tv_sec.to_f, stack_index
|
289
|
-
end
|
290
|
-
|
291
|
-
|
292
|
-
end
|