cloudrail_si 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +3 -0
- data/examples/README.md +3 -0
- data/examples/simple/index.rb +11 -0
- data/lib/cloudrail_si.rb +41 -0
- data/lib/cloudrail_si/RedirectReceivers.rb +40 -0
- data/lib/cloudrail_si/Settings.rb +12 -0
- data/lib/cloudrail_si/errors/DetailErrors.rb +13 -0
- data/lib/cloudrail_si/errors/InternalError.rb +10 -0
- data/lib/cloudrail_si/errors/UserError.rb +11 -0
- data/lib/cloudrail_si/helpers/Helper.rb +151 -0
- data/lib/cloudrail_si/helpers/LimitedReadableStream.rb +55 -0
- data/lib/cloudrail_si/helpers/SequenceReadableStream.rb +59 -0
- data/lib/cloudrail_si/servicecode/InitSelfTest.rb +92 -0
- data/lib/cloudrail_si/servicecode/Interpreter.rb +213 -0
- data/lib/cloudrail_si/servicecode/Sandbox.rb +361 -0
- data/lib/cloudrail_si/servicecode/VarAddress.rb +11 -0
- data/lib/cloudrail_si/servicecode/commands/AwaitCodeRedirect.rb +48 -0
- data/lib/cloudrail_si/servicecode/commands/Break.rb +16 -0
- data/lib/cloudrail_si/servicecode/commands/CallFunc.rb +26 -0
- data/lib/cloudrail_si/servicecode/commands/Clone.rb +18 -0
- data/lib/cloudrail_si/servicecode/commands/Concat.rb +22 -0
- data/lib/cloudrail_si/servicecode/commands/Conditional.rb +27 -0
- data/lib/cloudrail_si/servicecode/commands/Create.rb +56 -0
- data/lib/cloudrail_si/servicecode/commands/Delete.rb +21 -0
- data/lib/cloudrail_si/servicecode/commands/Get.rb +25 -0
- data/lib/cloudrail_si/servicecode/commands/GetMimeType.rb +1005 -0
- data/lib/cloudrail_si/servicecode/commands/JumpRel.rb +18 -0
- data/lib/cloudrail_si/servicecode/commands/Pull.rb +34 -0
- data/lib/cloudrail_si/servicecode/commands/Push.rb +32 -0
- data/lib/cloudrail_si/servicecode/commands/Return.rb +16 -0
- data/lib/cloudrail_si/servicecode/commands/Set.rb +23 -0
- data/lib/cloudrail_si/servicecode/commands/Size.rb +26 -0
- data/lib/cloudrail_si/servicecode/commands/ThrowError.rb +17 -0
- data/lib/cloudrail_si/servicecode/commands/array/Uint8ToBase64.rb +25 -0
- data/lib/cloudrail_si/servicecode/commands/debug/Out.rb +24 -0
- data/lib/cloudrail_si/servicecode/commands/hash/md5.rb +29 -0
- data/lib/cloudrail_si/servicecode/commands/hash/sha1.rb +30 -0
- data/lib/cloudrail_si/servicecode/commands/http/RequestCall.rb +51 -0
- data/lib/cloudrail_si/servicecode/commands/json/Parse.rb +40 -0
- data/lib/cloudrail_si/servicecode/commands/json/Stringify.rb +21 -0
- data/lib/cloudrail_si/servicecode/commands/math/Floor.rb +27 -0
- data/lib/cloudrail_si/servicecode/commands/math/MathCombine.rb +35 -0
- data/lib/cloudrail_si/servicecode/commands/object/GetKeyArray.rb +21 -0
- data/lib/cloudrail_si/servicecode/commands/object/GetKeyValueArrays.rb +29 -0
- data/lib/cloudrail_si/servicecode/commands/stream/MakeJoinedStream.rb +38 -0
- data/lib/cloudrail_si/servicecode/commands/stream/MakeLimitedStream.rb +23 -0
- data/lib/cloudrail_si/servicecode/commands/stream/StreamToString.rb +25 -0
- data/lib/cloudrail_si/servicecode/commands/stream/StringToStream.rb +20 -0
- data/lib/cloudrail_si/servicecode/commands/string/Base64Encode.rb +42 -0
- data/lib/cloudrail_si/servicecode/commands/string/Format.rb +43 -0
- data/lib/cloudrail_si/servicecode/commands/string/IndexOf.rb +29 -0
- data/lib/cloudrail_si/servicecode/commands/string/LastIndexOf.rb +29 -0
- data/lib/cloudrail_si/servicecode/commands/string/Split.rb +29 -0
- data/lib/cloudrail_si/servicecode/commands/string/StringTransform.rb +29 -0
- data/lib/cloudrail_si/servicecode/commands/string/Substr.rb +30 -0
- data/lib/cloudrail_si/servicecode/commands/string/Substring.rb +30 -0
- data/lib/cloudrail_si/services/Facebook.rb +528 -0
- data/lib/cloudrail_si/services/FacebookPage.rb +310 -0
- data/lib/cloudrail_si/services/Foursquare.rb +314 -0
- data/lib/cloudrail_si/services/GitHub.rb +354 -0
- data/lib/cloudrail_si/services/GooglePlaces.rb +309 -0
- data/lib/cloudrail_si/services/GooglePlus.rb +367 -0
- data/lib/cloudrail_si/services/Instagram.rb +342 -0
- data/lib/cloudrail_si/services/LinkedIn.rb +363 -0
- data/lib/cloudrail_si/services/MicrosoftLive.rb +346 -0
- data/lib/cloudrail_si/services/Nexmo.rb +173 -0
- data/lib/cloudrail_si/services/Slack.rb +318 -0
- data/lib/cloudrail_si/services/Twilio.rb +173 -0
- data/lib/cloudrail_si/services/Twitter.rb +795 -0
- data/lib/cloudrail_si/services/Yahoo.rb +408 -0
- data/lib/cloudrail_si/services/Yelp.rb +389 -0
- data/lib/cloudrail_si/statistics/Statistics.rb +125 -0
- data/lib/cloudrail_si/types/Address.rb +9 -0
- data/lib/cloudrail_si/types/Charge.rb +33 -0
- data/lib/cloudrail_si/types/CloudMetaData.rb +19 -0
- data/lib/cloudrail_si/types/CreditCard.rb +76 -0
- data/lib/cloudrail_si/types/Date.rb +49 -0
- data/lib/cloudrail_si/types/DateOfBirth.rb +16 -0
- data/lib/cloudrail_si/types/Error.rb +21 -0
- data/lib/cloudrail_si/types/Location.rb +8 -0
- data/lib/cloudrail_si/types/POI.rb +17 -0
- data/lib/cloudrail_si/types/Refund.rb +25 -0
- data/lib/cloudrail_si/types/SandboxObject.rb +20 -0
- data/lib/cloudrail_si/types/SpaceAllocation.rb +13 -0
- data/lib/cloudrail_si/types/Subscription.rb +27 -0
- data/lib/cloudrail_si/types/SubscriptionPlan.rb +26 -0
- data/lib/cloudrail_si/types/Types.rb +43 -0
- data/lib/cloudrail_si/version.rb +3 -0
- metadata +205 -0
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require_relative '../Helpers/helper'
|
4
|
+
require_relative '../servicecode/VarAddress'
|
5
|
+
|
6
|
+
require_relative './commands/AwaitCodeRedirect'
|
7
|
+
require_relative './commands/CallFunc'
|
8
|
+
require_relative './commands/Break'
|
9
|
+
require_relative './commands/Clone'
|
10
|
+
require_relative './commands/Concat'
|
11
|
+
require_relative './commands/Conditional'
|
12
|
+
require_relative './commands/Create'
|
13
|
+
require_relative './commands/Delete'
|
14
|
+
require_relative './commands/Get'
|
15
|
+
require_relative './commands/GetMimeType'
|
16
|
+
require_relative './commands/JumpRel'
|
17
|
+
require_relative './commands/Pull'
|
18
|
+
require_relative './commands/Push'
|
19
|
+
require_relative './commands/Return'
|
20
|
+
require_relative './commands/Set'
|
21
|
+
require_relative './commands/Size'
|
22
|
+
require_relative './commands/ThrowError'
|
23
|
+
require_relative './commands/array/Uint8ToBase64'
|
24
|
+
require_relative './commands/debug/Out'
|
25
|
+
require_relative './commands/hash/Sha1'
|
26
|
+
require_relative './commands/hash/Md5'
|
27
|
+
require_relative './commands/json/Parse'
|
28
|
+
require_relative './commands/json/Stringify'
|
29
|
+
require_relative './commands/http/RequestCall'
|
30
|
+
require_relative './commands/math/Floor'
|
31
|
+
require_relative './commands/math/MathCombine'
|
32
|
+
require_relative './commands/object/GetKeyArray'
|
33
|
+
require_relative './commands/object/GetKeyValueArrays'
|
34
|
+
require_relative './commands/string/Base64Encode'
|
35
|
+
require_relative './commands/string/Format'
|
36
|
+
require_relative './commands/string/IndexOf'
|
37
|
+
require_relative './commands/string/LastIndexOf'
|
38
|
+
require_relative './commands/string/Split'
|
39
|
+
require_relative './commands/string/StringTransform'
|
40
|
+
require_relative './commands/string/Substr'
|
41
|
+
require_relative './commands/string/Substring'
|
42
|
+
require_relative './commands/stream/StreamToString'
|
43
|
+
require_relative './commands/stream/StringToStream'
|
44
|
+
require_relative './commands/stream/MakeJoinedStream'
|
45
|
+
require_relative './commands/stream/MakeLimitedStream'
|
46
|
+
|
47
|
+
module CloudRailSi
|
48
|
+
module ServiceCode
|
49
|
+
class Interpreter
|
50
|
+
attr_reader :sandbox
|
51
|
+
|
52
|
+
def initialize(sandbox)
|
53
|
+
@sandbox = sandbox
|
54
|
+
|
55
|
+
@COMMAND_LIST = [
|
56
|
+
CallFunc.new,
|
57
|
+
Break.new,
|
58
|
+
Clone.new,
|
59
|
+
Create.new,
|
60
|
+
Delete.new,
|
61
|
+
Get.new,
|
62
|
+
JumpRel.new,
|
63
|
+
Pull.new,
|
64
|
+
Push.new,
|
65
|
+
Return.new,
|
66
|
+
Set.new,
|
67
|
+
Size.new,
|
68
|
+
Uint8ToBase64.new,
|
69
|
+
Sha1.new,
|
70
|
+
Md5.new,
|
71
|
+
Base64Encode.new,
|
72
|
+
StreamToString.new,
|
73
|
+
StringToStream.new,
|
74
|
+
MakeJoinedStream.new,
|
75
|
+
MakeLimitedStream.new,
|
76
|
+
RequestCall.new,
|
77
|
+
Out.new,
|
78
|
+
AwaitCodeRedirect.new,
|
79
|
+
GetMimeType.new,
|
80
|
+
Conditional.new('if==than', lambda { |c| (c == 0) }, false),
|
81
|
+
Conditional.new('if>=than', lambda { |c| (c >= 0) }, true),
|
82
|
+
Conditional.new('if>than', lambda { |c| (c > 0) }, true),
|
83
|
+
Conditional.new('if<=than', lambda { |c| (c <= 0) }, true),
|
84
|
+
Conditional.new('if<than', lambda { |c| (c < 0) }, true),
|
85
|
+
Conditional.new('if!=than', lambda { |c| (c != 0) }, false),
|
86
|
+
ThrowError.new,
|
87
|
+
Parse.new,
|
88
|
+
Stringify.new,
|
89
|
+
MathCombine.new('math.add', lambda { |elems| elems.reduce(0, :+) }),
|
90
|
+
MathCombine.new('math.multiply', lambda { |elems| elems.reduce(1, :*) }),
|
91
|
+
MathCombine.new('math.max', lambda { |elems | elems.max }),
|
92
|
+
MathCombine.new('math.min', lambda{ |elems | elems | elems.min }),
|
93
|
+
Floor.new,
|
94
|
+
GetKeyArray.new,
|
95
|
+
GetKeyValueArrays.new,
|
96
|
+
Concat.new,
|
97
|
+
Format.new,
|
98
|
+
IndexOf.new,
|
99
|
+
LastIndexOf.new,
|
100
|
+
Split.new,
|
101
|
+
Substr.new,
|
102
|
+
Substring.new,
|
103
|
+
StringTransform.new('string.lowerCase', lambda { |str| str.downcase }),
|
104
|
+
StringTransform.new('string.upperCase', lambda { |str| str.upcase }),
|
105
|
+
StringTransform.new('string.urlEncode', lambda { |str| URI::encode_www_form_component(str) }),
|
106
|
+
StringTransform.new('string.urlDecode', lambda { |str| URI::decode_www_form_component(str, Encoding::UTF_8) })
|
107
|
+
]
|
108
|
+
@COMMANDS = {}
|
109
|
+
@COMMAND_LIST.each { |command|
|
110
|
+
@COMMANDS[command.get_identifier()] = command
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def call_function(function_name, *parameters)
|
115
|
+
@sandbox.create_new_stack_level(function_name, 0)
|
116
|
+
Helper.add_all(@sandbox.current_parameters(), parameters)
|
117
|
+
if (@sandbox.current_function_code().nil?)
|
118
|
+
error_message = "Service code error: function #{function_name} not found"
|
119
|
+
raise Errors::InternalError.new(error_message)
|
120
|
+
end
|
121
|
+
return run_sync() # this was an async run
|
122
|
+
end
|
123
|
+
|
124
|
+
def call_function_sync(function_name, *parameters)
|
125
|
+
@sandbox.create_new_stack_level(function_name, 0)
|
126
|
+
Helper.add_all(@sandbox.current_parameters(), parameters)
|
127
|
+
if (@sandbox.current_function_code().nil?)
|
128
|
+
error_message = "Service code error: function #{function_name} not found"
|
129
|
+
raise Errors::InternalError.new(error_message)
|
130
|
+
end
|
131
|
+
return run_sync()
|
132
|
+
end
|
133
|
+
|
134
|
+
def run
|
135
|
+
raise Errors::InternalError.new('interpreter.run not supported.')
|
136
|
+
end
|
137
|
+
|
138
|
+
def run_sync
|
139
|
+
begin
|
140
|
+
while (@sandbox.current_service_code_line() < @sandbox.current_function_code().length && @sandbox.current_service_code_line() >= 0)
|
141
|
+
command = @sandbox.current_function_code()[@sandbox.current_service_code_line()]
|
142
|
+
Helper.log "\n\n\n#{command}"
|
143
|
+
if (@COMMANDS[command[0]].nil?)
|
144
|
+
raise Errors::InternalError.new("Unknown command: #{command[0]}")
|
145
|
+
end
|
146
|
+
command_parameters = Interpreter.decode_command_parameters(command)
|
147
|
+
@COMMANDS[command[0]].execute(@sandbox, command_parameters)
|
148
|
+
return if !@sandbox.thrown_error.nil?
|
149
|
+
@sandbox.increment_current_service_code_line(1)
|
150
|
+
while ((@sandbox.current_service_code_line() >= @sandbox.current_function_code().length ||
|
151
|
+
@sandbox.current_service_code_line() < 0) && @sandbox.code_function_name_stack.length > 1)
|
152
|
+
@sandbox.return_from_function()
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
rescue => e
|
157
|
+
raise e if (e.class.name == CloudRailSi::Errors::UserError)
|
158
|
+
error_message = 'Service code error in function ' + @sandbox.current_function_name() + ' at line ' + @sandbox.current_service_code_line().to_s + ' with message: ' + e.message
|
159
|
+
raise CloudRailSi::Errors::InternalError.new(error_message)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.decode_command_parameters(command)
|
164
|
+
command_parameters = command.clone[1..-1] # first param was function name
|
165
|
+
(0..command_parameters.length).each do |i|
|
166
|
+
if (Helper.is_string(command_parameters[i]))
|
167
|
+
if (command_parameters[i].index('$') === 0)
|
168
|
+
command_parameters[i] = VarAddress.new(command_parameters[i][1..-1])
|
169
|
+
elsif (command_parameters[i].index('\\$') === 0)
|
170
|
+
command_parameters[i] = command_parameters[i][1..-1]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
return command_parameters
|
175
|
+
end
|
176
|
+
|
177
|
+
def get_parameter(idx)
|
178
|
+
@sandbox.get_parameter(idx, 0)
|
179
|
+
end
|
180
|
+
|
181
|
+
def save_as_string
|
182
|
+
@sandbox.peristent_storage.to_json
|
183
|
+
end
|
184
|
+
|
185
|
+
def load_as_string(saved_state)
|
186
|
+
@sandbox.persistent_storage = JSON.parse(saved_state)
|
187
|
+
end
|
188
|
+
|
189
|
+
def resume_function(function_name, *parameters)
|
190
|
+
if (@sandbox.parameters_stack.length === 0)
|
191
|
+
first_parameters = []
|
192
|
+
@sandbox.parameters_stack.push(first_parameters)
|
193
|
+
else
|
194
|
+
first_parameters = @sandbox.parameters_stack[0]
|
195
|
+
end
|
196
|
+
(0..parameters.length).each do |i|
|
197
|
+
if (Helper.is_object(parameters[i]))
|
198
|
+
m = parameters[i]
|
199
|
+
Helper.clear(m)
|
200
|
+
Helper.put_all(m, first_parameters[i])
|
201
|
+
else
|
202
|
+
if (i >= first_parameters.length)
|
203
|
+
first_parameters.push(parameters[i])
|
204
|
+
else
|
205
|
+
first_parameters[i] = parameters[i]
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
return run_sync()
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,361 @@
|
|
1
|
+
require_relative './Interpreter'
|
2
|
+
require_relative '../errors/InternalError'
|
3
|
+
require_relative '../helpers/Helper'
|
4
|
+
|
5
|
+
module CloudRailSi
|
6
|
+
module ServiceCode
|
7
|
+
class Sandbox
|
8
|
+
attr_reader :thrown_error
|
9
|
+
attr_reader :code_function_name_stack
|
10
|
+
attr_reader :local_variables_stack
|
11
|
+
attr_reader :instance_dependency_storage
|
12
|
+
attr_reader :code_line_stack
|
13
|
+
|
14
|
+
def is_sandbox
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(service_code, persistent_storage, instance_dependency_storage)
|
19
|
+
@local_variables_stack = []
|
20
|
+
@parameters_stack = []
|
21
|
+
@code_function_name_stack = []
|
22
|
+
@code_line_stack = []
|
23
|
+
@persistent_storage = []
|
24
|
+
@service_code = service_code
|
25
|
+
@persistent_storage = persistent_storage
|
26
|
+
@instance_dependency_storage = instance_dependency_storage
|
27
|
+
@LIST_MAX_ADD_JUMP_ALLOWED = 32
|
28
|
+
@thrown_error = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_thrown_error(thrown_error)
|
32
|
+
Helper.debug
|
33
|
+
@thrown_error = thrown_error
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_new_stack_level(function_name, code_line)
|
37
|
+
@local_variables_stack.push([])
|
38
|
+
@parameters_stack.push([])
|
39
|
+
@code_function_name_stack.push(function_name)
|
40
|
+
@code_line_stack.push(code_line)
|
41
|
+
end
|
42
|
+
|
43
|
+
def current_parameters
|
44
|
+
return nil if (@parameters_stack.length === 0)
|
45
|
+
@parameters_stack[-1]
|
46
|
+
end
|
47
|
+
|
48
|
+
def current_function_name
|
49
|
+
return nil if (@code_function_name_stack.length === 0)
|
50
|
+
@code_function_name_stack[-1]
|
51
|
+
end
|
52
|
+
|
53
|
+
def current_function_code
|
54
|
+
@service_code[current_function_name()]
|
55
|
+
end
|
56
|
+
|
57
|
+
def current_service_code_line
|
58
|
+
return -1 if (@code_line_stack.length === 0)
|
59
|
+
return @code_line_stack[-1]
|
60
|
+
end
|
61
|
+
|
62
|
+
def increment_current_service_code_line(amount)
|
63
|
+
@code_line_stack[-1] += amount if @code_line_stack.length
|
64
|
+
end
|
65
|
+
def return_from_function
|
66
|
+
return if (@code_function_name_stack.length <= 1)
|
67
|
+
|
68
|
+
call_function_command_parameters = Interpreter.decode_command_parameters(@service_code[@code_function_name_stack[-2]][@code_line_stack[-2]])
|
69
|
+
|
70
|
+
(0..call_function_command_parameters.length - 1).each do |i|
|
71
|
+
parameter_var = call_function_command_parameters[i]
|
72
|
+
if Helper.is_var_address(parameter_var)
|
73
|
+
value = @parameters_stack[-1][i - 1]
|
74
|
+
set_variable(parameter_var, value, -2)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@code_function_name_stack.pop()
|
78
|
+
@code_line_stack.pop()
|
79
|
+
@local_variables_stack.pop()
|
80
|
+
@parameters_stack.pop()
|
81
|
+
increment_current_service_code_line(1)
|
82
|
+
end
|
83
|
+
def set_variable(var_address, value, stacklevel=-1)
|
84
|
+
if Helper.is_var_address(var_address)
|
85
|
+
var_address_parts = decode_variable_address(var_address)
|
86
|
+
else
|
87
|
+
var_address_parts = var_address
|
88
|
+
end
|
89
|
+
|
90
|
+
variables = get_stack_for_address_part(var_address_parts[0], stacklevel)
|
91
|
+
var_idx = var_address_parts[1]
|
92
|
+
if (var_address_parts.length <= 2)
|
93
|
+
if (variables.length == var_idx)
|
94
|
+
variables.push(value)
|
95
|
+
elsif (variables.length > var_idx)
|
96
|
+
variables[var_idx] = value
|
97
|
+
elsif (variables.length + @LIST_MAX_ADD_JUMP_ALLOWED > var_idx)
|
98
|
+
(0..var_idx - variables.length + 1).each do |i|
|
99
|
+
variables.push(nil)
|
100
|
+
end
|
101
|
+
variables[var_idx] = value
|
102
|
+
else
|
103
|
+
raise Errors::InternalError.new("Could not decode variable #{var_address_parts.join(':')}")
|
104
|
+
end
|
105
|
+
return true
|
106
|
+
end
|
107
|
+
|
108
|
+
return set_entry(variables[var_idx], var_address_parts[2..-1], value)
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_variable(var_address, stacklevel=-1, empty_is_null=false)
|
112
|
+
if Helper.is_var_address(var_address)
|
113
|
+
var_address_parts = decode_variable_address(var_address)
|
114
|
+
else
|
115
|
+
var_address_parts = var_address
|
116
|
+
end
|
117
|
+
variables = get_stack_for_address_part(var_address_parts[0], stacklevel)
|
118
|
+
|
119
|
+
return nil if (empty_is_null && var_address_parts[1] >= variables.length)
|
120
|
+
|
121
|
+
local_entry = variables[var_address_parts[1]]
|
122
|
+
return local_entry if (var_address_parts.length <= 2)
|
123
|
+
get_entry(local_entry, var_address_parts[2..-1], empty_is_null)
|
124
|
+
end
|
125
|
+
|
126
|
+
def delete_variable(var_address_parts, stacklevel=-1)
|
127
|
+
variables = get_stack_for_address_part(var_address_parts[0], stacklevel)
|
128
|
+
var_idx = var_address_parts[1]
|
129
|
+
if (var_address_parts.length <= 2)
|
130
|
+
variables[var_idx] = nil if (var_idx < variables.length)
|
131
|
+
return true
|
132
|
+
end
|
133
|
+
delete_entry(variables[var_idx], var_address_parts[2..-1])
|
134
|
+
end
|
135
|
+
def get_stack_for_address_part(part, stacklevel)
|
136
|
+
if (part == 'L')
|
137
|
+
variables = @local_variables_stack[stacklevel]
|
138
|
+
elsif (part == 'P')
|
139
|
+
variables = @parameters_stack[stacklevel]
|
140
|
+
elsif (part == 'S')
|
141
|
+
variables = @persistent_storage
|
142
|
+
else
|
143
|
+
raise Errors::InternalError.new("Could not attribute variable part #{part}")
|
144
|
+
end
|
145
|
+
return variables
|
146
|
+
end
|
147
|
+
|
148
|
+
def decode_variable_address(var_address)
|
149
|
+
dec_adr = []
|
150
|
+
adr = var_address.instance_variable_get(:@address_string)
|
151
|
+
Helper.assert(adr[0] != '$')
|
152
|
+
if (adr[0] < '0' || adr[0] > '9')
|
153
|
+
dec_adr.push(adr[0])
|
154
|
+
adr = adr[1..-1]
|
155
|
+
end
|
156
|
+
adr_parts = adr.split('.')
|
157
|
+
(0..adr_parts.length - 1).each do |i|
|
158
|
+
part = adr_parts[i]
|
159
|
+
if (Helper.is_number_string(part))
|
160
|
+
dec_adr.push(Integer(part))
|
161
|
+
else
|
162
|
+
dec_adr.push(part)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
return dec_adr
|
166
|
+
end
|
167
|
+
|
168
|
+
def set_entry(container, var_address, value)
|
169
|
+
if (var_address.length > 1)
|
170
|
+
next_container = get_entry(container, var_address[0..-2], false)
|
171
|
+
|
172
|
+
return set_entry(next_container, var_address[1..-1], value)
|
173
|
+
end
|
174
|
+
var_address_part = var_address[0]
|
175
|
+
|
176
|
+
if (Helper.is_array(container))
|
177
|
+
if (Helper.is_number_string(var_address_part))
|
178
|
+
var_address_part = Integer(var_address_part)
|
179
|
+
end
|
180
|
+
if (!Helper.is_number(var_address_part) || var_address_part >= container.length)
|
181
|
+
raise Errors::InternalError.new('Invalid index while indexing into an array')
|
182
|
+
end
|
183
|
+
idx = var_address_part
|
184
|
+
list = container
|
185
|
+
if (list.length + @LIST_MAX_ADD_JUMP_ALLOWED <= idx)
|
186
|
+
(idx - list.length + 1).times do |i|
|
187
|
+
list.push(nil)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
list[idx] = value
|
191
|
+
elsif (Helper.is_object(container))
|
192
|
+
if (!Helper.is_string(var_address_part))
|
193
|
+
var_address_part = var_address_part.to_s
|
194
|
+
end
|
195
|
+
|
196
|
+
#There are three ways to interpret an address; we try them all
|
197
|
+
begin
|
198
|
+
container.instance_variable_set('@' + var_address_part, value)
|
199
|
+
rescue
|
200
|
+
end
|
201
|
+
begin
|
202
|
+
container.send(Helper.to_snake_case(var_address_part) + "=", value)
|
203
|
+
rescue
|
204
|
+
end
|
205
|
+
begin
|
206
|
+
container[var_address_part] = value
|
207
|
+
rescue
|
208
|
+
end
|
209
|
+
elsif Helper.is_sandbox(container)
|
210
|
+
if (!Helper.is_string(var_address_part))
|
211
|
+
var_address_part = var_address_part.to_s
|
212
|
+
end
|
213
|
+
container.set(var_address_part, value)
|
214
|
+
end
|
215
|
+
return false
|
216
|
+
end
|
217
|
+
def get_entry(container, var_address, empty_is_null)
|
218
|
+
entry = ''
|
219
|
+
var_address_part = var_address[0]
|
220
|
+
if (Helper.is_array(container) || Helper.is_string(container))
|
221
|
+
if (Helper.is_number_string(var_address_part))
|
222
|
+
var_address_part = Integer(var_address_part)
|
223
|
+
end
|
224
|
+
if (!Helper.is_number(var_address_part))
|
225
|
+
var_address_part = 0 #TODO: for paypal, transactions is missing if the count is zero; this "fixes" it but might break other things.
|
226
|
+
# raise Errors::InternalError.new('Invalid index while indexing into an array or string')
|
227
|
+
end
|
228
|
+
if (!(empty_is_null && var_address_part >= container.length))
|
229
|
+
entry = container[var_address_part]
|
230
|
+
end
|
231
|
+
elsif (Helper.is_object(container))
|
232
|
+
if (!Helper.is_string(var_address_part))
|
233
|
+
var_address_part = var_address_part.to_s
|
234
|
+
end
|
235
|
+
if (container.nil? && (!empty_is_null))
|
236
|
+
entry = {}
|
237
|
+
else
|
238
|
+
begin
|
239
|
+
entry = container.instance_variable_get('@' + var_address_part) # will fail if var_address_part starts with a number; set to nil if doesn't exist
|
240
|
+
rescue
|
241
|
+
end
|
242
|
+
if !entry
|
243
|
+
begin
|
244
|
+
entry = container[var_address_part]
|
245
|
+
rescue
|
246
|
+
begin
|
247
|
+
entry = container.send(Helper.to_snake_case(var_address_part))
|
248
|
+
rescue
|
249
|
+
entry = {}
|
250
|
+
Helper.debug
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
elsif Helper.is_sandbox(container)
|
256
|
+
if (!Helper.is_string(var_address_part))
|
257
|
+
var_address_part = var_address_part.to_s
|
258
|
+
end
|
259
|
+
entry = container.get(var_address_part)
|
260
|
+
end
|
261
|
+
if (var_address.length > 1)
|
262
|
+
return get_entry( entry, var_address[1..-1], empty_is_null)
|
263
|
+
end
|
264
|
+
return entry
|
265
|
+
end
|
266
|
+
def delete_entry(container, var_address)
|
267
|
+
if (var_address.length > 1)
|
268
|
+
next_container = get_entry(container, var_address, false)
|
269
|
+
return delete_entry(next_container, var_address[1..-1])
|
270
|
+
end
|
271
|
+
var_address_part = var_address[0]
|
272
|
+
if (Helper.is_array(container))
|
273
|
+
if (Helper.is_number_string(var_address_part))
|
274
|
+
var_address_part = Integer(var_address_part)
|
275
|
+
end
|
276
|
+
if (!Helper.is_number(var_address_part) || var_address_part >= container.length)
|
277
|
+
raise Errors::InternalError.new('Invalid index while indexing into an array')
|
278
|
+
end
|
279
|
+
idx = var_address_part
|
280
|
+
list = container
|
281
|
+
if (idx < list.length)
|
282
|
+
list.delete_at(idx)
|
283
|
+
end
|
284
|
+
while (list.length && list[-1].nil?)
|
285
|
+
list.pop()
|
286
|
+
end
|
287
|
+
elsif (Helper.is_object(container))
|
288
|
+
var_address_part = var_address_part.to_s
|
289
|
+
container.delete(var_address_part)
|
290
|
+
elsif Helper.is_sandbox(container)
|
291
|
+
var_address_part = var_address_part.to_s
|
292
|
+
container.set(var_address_part, nil)
|
293
|
+
end
|
294
|
+
return false
|
295
|
+
end
|
296
|
+
def call_function(function_name, parameters)
|
297
|
+
create_new_stack_level(function_name, -1)
|
298
|
+
parameter_stack = current_parameters()
|
299
|
+
Helper.add_all(parameter_stack, parameters)
|
300
|
+
end
|
301
|
+
def compare_variables(a_obj, b_obj, command_id, type_check)
|
302
|
+
a_obj = Helper.resolve(self, a_obj, false)
|
303
|
+
b_obj = Helper.resolve(self, b_obj, false)
|
304
|
+
if (!type_check && (a_obj.nil? || b_obj.nil?))
|
305
|
+
return 0 if (a_obj.nil? && b_obj.nil?)
|
306
|
+
return -1
|
307
|
+
end
|
308
|
+
|
309
|
+
if ((a_obj.is_a? Numeric) && (b_obj.is_a? Numeric))
|
310
|
+
# doesn't matter if one is int and other is float
|
311
|
+
elsif (a_obj.class != b_obj.class)
|
312
|
+
Helper.debug
|
313
|
+
return -1 if !type_check
|
314
|
+
raise Errors::InternalError.new("Command #{command_id} compares arguments of different types")
|
315
|
+
end
|
316
|
+
|
317
|
+
return Helper.compare(a_obj, b_obj)
|
318
|
+
end
|
319
|
+
def save_state_to_string
|
320
|
+
savelist = []
|
321
|
+
savelist.push(@code_function_name_stack)
|
322
|
+
savelist.push(@code_line_stack)
|
323
|
+
savelist.push(@local_variables_stack)
|
324
|
+
savelist.push(@parameters_stack)
|
325
|
+
savelist.push(@persistent_storage)
|
326
|
+
as_json = savelist.to_json
|
327
|
+
# TODO: Add support for objects such as CustomDate
|
328
|
+
|
329
|
+
return as_json
|
330
|
+
end
|
331
|
+
def load_state_from_string(saved_state)
|
332
|
+
savelist = JSON.parse(saved_state)
|
333
|
+
|
334
|
+
# TODO: Add support for objects such as CustomDate
|
335
|
+
@code_function_name_stack = savelist[0]
|
336
|
+
@code_line_stack = savelist[1]
|
337
|
+
@local_variables_stack = savelist[2]
|
338
|
+
merge_stacks = lambda { |json_stack, stack|
|
339
|
+
(json_stack.length).times do |i|
|
340
|
+
if (i >= stack.length)
|
341
|
+
stack.push(json_stack[i])
|
342
|
+
else
|
343
|
+
stack[i] = json_stack[i]
|
344
|
+
end
|
345
|
+
end
|
346
|
+
}
|
347
|
+
json_parameters_stack = savelist[3]
|
348
|
+
json_persistent_storage = savelist[4]
|
349
|
+
merge_stacks(json_parameters_stack, @parameters_stack)
|
350
|
+
merge_stacks(json_persistent_storage, @persistent_storage)
|
351
|
+
end
|
352
|
+
def get_parameter(idx, stacklevel)
|
353
|
+
return nil if (@parameters_stack.length === 0 || stacklevel >= @parameters_stack.length || idx >= @parameters_stack[stacklevel].length)
|
354
|
+
@parameters_stack[stacklevel][idx]
|
355
|
+
end
|
356
|
+
def get_params_stack
|
357
|
+
@parameters_stack
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|