AmberVM 0.0.19
Sign up to get free protection for your applications and to get access to all the features.
- data/README +38 -0
- data/bin/ambervm +278 -0
- data/lib/amber/acts_as_rvm_type.rb +157 -0
- data/lib/amber/classes/association.rb +36 -0
- data/lib/amber/classes/block.rb +52 -0
- data/lib/amber/classes/boolean.rb +40 -0
- data/lib/amber/classes/class.rb +50 -0
- data/lib/amber/classes/error.rb +22 -0
- data/lib/amber/classes/list.rb +96 -0
- data/lib/amber/classes/null.rb +35 -0
- data/lib/amber/classes/number.rb +95 -0
- data/lib/amber/classes/object.rb +56 -0
- data/lib/amber/classes/string.rb +79 -0
- data/lib/amber/classes.rb +113 -0
- data/lib/amber/environment.rb +251 -0
- data/lib/amber/fukubukuro/ecma_core.rb +409 -0
- data/lib/amber/fukubukuro.rb +866 -0
- data/lib/amber/functions/all.rb +3 -0
- data/lib/amber/functions/array/append.rb +50 -0
- data/lib/amber/functions/array/at.rb +50 -0
- data/lib/amber/functions/array/set_at.rb +50 -0
- data/lib/amber/functions/array.rb +30 -0
- data/lib/amber/functions/association/assoc_get.rb +55 -0
- data/lib/amber/functions/association/assoc_set.rb +56 -0
- data/lib/amber/functions/bitwise/bitwise_and.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_not.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_or.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_xor.rb +41 -0
- data/lib/amber/functions/bitwise.rb +3 -0
- data/lib/amber/functions/collection/get.rb +66 -0
- data/lib/amber/functions/collection/set.rb +67 -0
- data/lib/amber/functions/collection/size.rb +54 -0
- data/lib/amber/functions/general/cmp.rb +43 -0
- data/lib/amber/functions/general/eq.rb +45 -0
- data/lib/amber/functions/general/gt.rb +45 -0
- data/lib/amber/functions/general/gte.rb +45 -0
- data/lib/amber/functions/general/lt.rb +45 -0
- data/lib/amber/functions/general/lte.rb +45 -0
- data/lib/amber/functions/general/neq.rb +45 -0
- data/lib/amber/functions/general/type.rb +43 -0
- data/lib/amber/functions/general.rb +3 -0
- data/lib/amber/functions/io/print.rb +45 -0
- data/lib/amber/functions/io.rb +3 -0
- data/lib/amber/functions/list/align.rb +73 -0
- data/lib/amber/functions/list/join.rb +45 -0
- data/lib/amber/functions/list/map.rb +58 -0
- data/lib/amber/functions/list/split.rb +55 -0
- data/lib/amber/functions/list.rb +3 -0
- data/lib/amber/functions/logic/and.rb +55 -0
- data/lib/amber/functions/logic/not.rb +40 -0
- data/lib/amber/functions/logic/or.rb +50 -0
- data/lib/amber/functions/logic.rb +3 -0
- data/lib/amber/functions/math/abs.rb +39 -0
- data/lib/amber/functions/math/acos.rb +39 -0
- data/lib/amber/functions/math/add.rb +40 -0
- data/lib/amber/functions/math/asin.rb +39 -0
- data/lib/amber/functions/math/atan.rb +39 -0
- data/lib/amber/functions/math/ceil.rb +39 -0
- data/lib/amber/functions/math/cos.rb +39 -0
- data/lib/amber/functions/math/dec.rb +39 -0
- data/lib/amber/functions/math/div.rb +44 -0
- data/lib/amber/functions/math/exp.rb +39 -0
- data/lib/amber/functions/math/floor.rb +39 -0
- data/lib/amber/functions/math/inc.rb +39 -0
- data/lib/amber/functions/math/log.rb +39 -0
- data/lib/amber/functions/math/mod.rb +41 -0
- data/lib/amber/functions/math/mul.rb +43 -0
- data/lib/amber/functions/math/neg.rb +43 -0
- data/lib/amber/functions/math/power.rb +43 -0
- data/lib/amber/functions/math/rand.rb +36 -0
- data/lib/amber/functions/math/round.rb +39 -0
- data/lib/amber/functions/math/shl.rb +41 -0
- data/lib/amber/functions/math/shr.rb +41 -0
- data/lib/amber/functions/math/sin.rb +39 -0
- data/lib/amber/functions/math/sub.rb +43 -0
- data/lib/amber/functions/math/tan.rb +39 -0
- data/lib/amber/functions/math.rb +3 -0
- data/lib/amber/functions/objects/send.rb +22 -0
- data/lib/amber/functions/rails/print.rb +44 -0
- data/lib/amber/functions/rails.rb +3 -0
- data/lib/amber/functions/string/ansi.rb +24 -0
- data/lib/amber/functions/string/capstr.rb +23 -0
- data/lib/amber/functions/string/center.rb +25 -0
- data/lib/amber/functions/string/chr.rb +16 -0
- data/lib/amber/functions/string/ljust.rb +26 -0
- data/lib/amber/functions/string/regmatch.rb +34 -0
- data/lib/amber/functions/string/rjust.rb +26 -0
- data/lib/amber/functions/string.rb +3 -0
- data/lib/amber/functions.rb +103 -0
- data/lib/amber/interpreter.rb +1380 -0
- data/lib/amber/languages/brainfuck.rb +153 -0
- data/lib/amber/languages/ecma/compiler.rb +1661 -0
- data/lib/amber/languages/ecma/core-math.js +67 -0
- data/lib/amber/languages/ecma/core-objects.js +57 -0
- data/lib/amber/languages/ecma.rb +9 -0
- data/lib/amber/languages/ecma_fuku/compiler.rb +1622 -0
- data/lib/amber/languages/ecma_fuku/core-math.js +67 -0
- data/lib/amber/languages/ecma_fuku/core-objects.js +56 -0
- data/lib/amber/languages/ecma_fuku.rb +13 -0
- data/lib/amber/languages/math/compiler.rb +70 -0
- data/lib/amber/languages/math/tokenizer.rb +69 -0
- data/lib/amber/languages/math/tree.rb +110 -0
- data/lib/amber/languages/math.rb +26 -0
- data/lib/amber/languages.rb +99 -0
- data/lib/amber/library.rb +79 -0
- data/lib/amber/optimisation.rb +299 -0
- data/lib/amber/plugin.rb +337 -0
- data/lib/amber/rails.rb +90 -0
- data/lib/amber.rb +106 -0
- data/spec/amber/class_spec.rb +27 -0
- data/spec/amber/enviroment_spec.rb +61 -0
- data/spec/amber/function_spec.rb +25 -0
- data/spec/amber/functions/association/assoc_get_spec.rb +41 -0
- data/spec/amber/functions/association/assoc_set_spec.rb +43 -0
- data/spec/amber/functions/collection/get_spec.rb +12 -0
- data/spec/amber/functions/collection/set_spec.rb +10 -0
- data/spec/amber/functions/collection/size_spec.rb +10 -0
- data/spec/amber/functions/list/split_spec.rb +47 -0
- data/spec/amber/functions/string/ansi_spec.rb +44 -0
- data/spec/amber/functions/string/capstr_spec.rb +42 -0
- data/spec/amber/functions/string/center_spec.rb +49 -0
- data/spec/amber/functions/string/ljust_spec.rb +49 -0
- data/spec/amber/functions/string/regmatch_spec.rb +52 -0
- data/spec/amber/functions/string/rjust_spec.rb +49 -0
- data/spec/amber/interpreter/assignment_spec.rb +22 -0
- data/spec/amber/interpreter/condition_spec.rb +103 -0
- data/spec/amber/interpreter/constant_spec.rb +31 -0
- data/spec/amber/interpreter/core_call_spec.rb +72 -0
- data/spec/amber/interpreter/interpreter_spec.rb +11 -0
- data/spec/amber/interpreter/parameter_spec.rb +24 -0
- data/spec/amber/interpreter/sequence_spec.rb +47 -0
- data/spec/amber/interpreter/variable_spec.rb +24 -0
- data/spec/amber/plugin_spec.rb +10 -0
- data/spec/classes/atom/association_spec.rb +39 -0
- data/spec/classes/atom/block_spec.rb +25 -0
- data/spec/classes/atom/boolean_spec.rb +67 -0
- data/spec/classes/atom/error_spec.rb +43 -0
- data/spec/classes/atom/list_spec.rb +68 -0
- data/spec/classes/atom/number_spec.rb +132 -0
- data/spec/classes/atom/string_spec.rb +175 -0
- data/spec/languages/ecma/ecma_array_spec.rb +79 -0
- data/spec/languages/ecma/ecma_closure_spec.rb +38 -0
- data/spec/languages/ecma/ecma_literals_spec.rb +71 -0
- data/spec/languages/ecma/ecma_objects_spec.rb +165 -0
- data/spec/languages/ecma/ecma_old_spec.rb +540 -0
- data/spec/languages/ecma/ecma_spec.rb +64 -0
- data/spec/languages/ecma_fuku/ecma_array_spec.rb +61 -0
- data/spec/languages/ecma_fuku/ecma_closure_spec.rb +33 -0
- data/spec/languages/ecma_fuku/ecma_function_spec.rb +84 -0
- data/spec/languages/ecma_fuku/ecma_literals_spec.rb +55 -0
- data/spec/languages/ecma_fuku/ecma_objects_spec.rb +133 -0
- data/spec/languages/ecma_fuku/ecma_old_spec.rb +415 -0
- data/spec/languages/ecma_fuku/ecma_operator_spec.rb +33 -0
- data/spec/languages/ecma_fuku/ecma_spec.rb +52 -0
- data/spec/languages/math/compiler_spec.rb +49 -0
- data/spec/languages/math/tokenizer_spec.rb +73 -0
- data/spec/languages/math/tree_spec.rb +153 -0
- metadata +225 -0
data/README
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= rVM
|
2
|
+
|
3
|
+
rVM is the implementation of a VirtualMachine in pure Ruby. To clarify, no virtual machine as in VMWare that lets you virtualize a computer. But rather like ruby 1.9 or JRuby that both implement a virtual machine (written in C or Java) to execute Ruby code.
|
4
|
+
Just that rVM takes it the other way around, it is written in ruby and lets you execute code within ruby.
|
5
|
+
|
6
|
+
= So what is so cool about that?
|
7
|
+
|
8
|
+
For once, the challenge to pull this off ;P. Then it has on huge advantage. It makes it pretty easy to give ruby programs a interface for scripting.
|
9
|
+
|
10
|
+
Now you might think 'wow cool but I could just use ruby!' that is right, and wrong. Imagine just short code snippets to make a query, perhaps you want to implement a SQL based language to let a user query data in your program? Also consider you want your website to allow user side scripts. I would not want to have ruby code executed for random visitors. Then again I might be more tempted to let them execute code within a VM that has no access to anything outside it's VM neither variables nor hardware nor memory.
|
11
|
+
|
12
|
+
= Example
|
13
|
+
|
14
|
+
|
15
|
+
The following example implements a pretty easy calculator using the the math language shipped with rVM. Set variables and are not used outside one line
|
16
|
+
|
17
|
+
require 'rubygems'
|
18
|
+
require 'amber' # This loads the rVM gem
|
19
|
+
require 'amber/languages/math' #This loads the math plugin as well as the math function library
|
20
|
+
s =''
|
21
|
+
compiler = AmberVM::Languages[:math].new #Lets get us the compiler
|
22
|
+
while s!= 'QUIT'
|
23
|
+
s=gets.chomp
|
24
|
+
puts compiler.compile(s).execute(compiler.env) # We pass an fresh environment as we don't need an environment.
|
25
|
+
end
|
26
|
+
|
27
|
+
Here one example that keeps set variables due to using one environment for all the calls.
|
28
|
+
|
29
|
+
require 'rubygems'
|
30
|
+
require 'amber' # This loads the rVM gem
|
31
|
+
require 'amber/languages/math' #This loads the math plugin as well as the math function library
|
32
|
+
s =''
|
33
|
+
compiler = AmberVM::Languages[:math].new #Lets get us the compiler
|
34
|
+
env = compiler.env
|
35
|
+
while s!= 'QUIT'
|
36
|
+
s=gets.chomp
|
37
|
+
puts compiler.compile(s).execute(env) # We pass an fresh environment as we don't need an environment.
|
38
|
+
end
|
data/bin/ambervm
ADDED
@@ -0,0 +1,278 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$: << "lib"
|
4
|
+
require 'optparse'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'pp'
|
7
|
+
require 'amber'
|
8
|
+
require 'rubygems'
|
9
|
+
|
10
|
+
|
11
|
+
rcfile = File.expand_path('~/.amberrc')
|
12
|
+
if File.exist?(rcfile)
|
13
|
+
File.new(rcfile).each do |line|
|
14
|
+
line.chomp!
|
15
|
+
ARGV << line.gsub(/\s.*$/,'')
|
16
|
+
ARGV << line.gsub(/^.*?\s/,'')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def v text
|
21
|
+
puts text if @options.verbose
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_compiler lang
|
25
|
+
begin
|
26
|
+
if require("amber/languages/#{lang}")
|
27
|
+
v "Loading Compiler: #{lang}" if @options
|
28
|
+
@compiler = AmberVM::Languages[lang].new
|
29
|
+
else
|
30
|
+
puts "ERROR: could not find compiler: #{lang}"
|
31
|
+
exit 2
|
32
|
+
end
|
33
|
+
rescue Exception => e
|
34
|
+
puts "ERROR: could not load compiler for: #{lang} #=> #{e}"
|
35
|
+
exit 3
|
36
|
+
end
|
37
|
+
@compiler
|
38
|
+
end
|
39
|
+
|
40
|
+
class AmberVMOptParser
|
41
|
+
#
|
42
|
+
# Return a structure describing the options.
|
43
|
+
#
|
44
|
+
LANGUAGES = %w[ecma ecma_fuku bf math]
|
45
|
+
LANGUAGES_ALIASES = { "js" => "ecma", "javascript" => "ecma" }
|
46
|
+
def self.parse(args)
|
47
|
+
# The options specified on the command line will be collected in *options*.
|
48
|
+
# We set default values here.
|
49
|
+
options = OpenStruct.new
|
50
|
+
options.library = []
|
51
|
+
options.amber_library = []
|
52
|
+
options.core_library = []
|
53
|
+
options.verbose = false
|
54
|
+
options.language = :ecma
|
55
|
+
options.code = nil
|
56
|
+
options.use_default_core_libs = true
|
57
|
+
options.run_as_core = false
|
58
|
+
options.only_compilation = false
|
59
|
+
|
60
|
+
|
61
|
+
o = OptionParser.new do |opts|
|
62
|
+
opts.banner = "Usage: amber [options]"
|
63
|
+
|
64
|
+
opts.separator ""
|
65
|
+
opts.separator "Specific options:"
|
66
|
+
|
67
|
+
# Mandatory argument.
|
68
|
+
opts.on("-r", "--require LIBRARY", "Require the LIBRARY before executing your script. This is for own libraries.") do |lib|
|
69
|
+
options.library << lib;
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on("-i", "--amber-require AmberVM_LIBRARY", "Require the AmberVM_LIBRARY before executing your script. This is for amber internal libraries.") do |lib|
|
73
|
+
options.amber_library << "amber/#{lib}"
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.on("-b", "--no-corelibs", "Used to disable standard core libraries to be imported automatically") do |b|
|
77
|
+
options.use_default_core_libs = !b
|
78
|
+
end
|
79
|
+
opts.on("-c", "--core-require CORE_LIBRARY", "Require an additional CORE_LIBRARY before executing your script. This is for libraries that allow access to AmberVM library functions.") do |lib|
|
80
|
+
options.core_library << "#{lib}"
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("-f", "--function NAMESPACE/FUNCTION", "Require the function before executing your script. This is for amber internal functions.") do |lib|
|
84
|
+
options.amber_library << "amber/functions/#{lib}"
|
85
|
+
end
|
86
|
+
|
87
|
+
language_list = (LANGUAGES_ALIASES.keys + LANGUAGES).join(',')
|
88
|
+
opts.on("-l", "--language LANGUAGE", LANGUAGES, LANGUAGES_ALIASES, "Select interpreter language", " (#{language_list})") do |language|
|
89
|
+
options.language = language
|
90
|
+
end
|
91
|
+
|
92
|
+
# Boolean switch.
|
93
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
94
|
+
options.verbose = v
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
opts.on("-d", "--[no-]debug", "Run in debug mode (attention spammy! Implies -v") do |d|
|
99
|
+
options.verbose = true if $DEBUG = options.debug = d
|
100
|
+
end
|
101
|
+
|
102
|
+
opts.on("-e", "--execute CODE", "Executes CODE directly.") do |code|
|
103
|
+
options.code = code
|
104
|
+
end
|
105
|
+
|
106
|
+
opts.on("-o", "--optimize", "Optimizes the code prior to execution") do |optimize|
|
107
|
+
options.optimize = optimize
|
108
|
+
end
|
109
|
+
|
110
|
+
opts.on_tail("-x", "--run-as-core", "Runs the code in core library mode (direct access to the rVM libraries)") do |c|
|
111
|
+
options.run_as_core = c
|
112
|
+
end
|
113
|
+
|
114
|
+
opts.separator ""
|
115
|
+
opts.separator "Common options:"
|
116
|
+
|
117
|
+
# No argument, shows at tail. This will print an options summary.
|
118
|
+
# Try it and see!
|
119
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
120
|
+
puts opts
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
|
124
|
+
opts.on("-s", "--source", "Shows the source before executing.") do
|
125
|
+
options.show_source = true
|
126
|
+
end
|
127
|
+
|
128
|
+
opts.on("-p", "--compilation", "Only show the result of the compiler without executing it.") do
|
129
|
+
options.compilation = true
|
130
|
+
end
|
131
|
+
|
132
|
+
opts.on("-n", "--dont-execute", "The code is only compiled but not executed.") do
|
133
|
+
options.dont_execute = true
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
# Another typical switch to print the version.
|
138
|
+
opts.on_tail("--version", "Show version") do
|
139
|
+
print "AmberVM version: #{AmberVM::VERSION}"
|
140
|
+
if options.language
|
141
|
+
puts ", #{options.language} compiler version: #{load_compiler(options.language).version}"
|
142
|
+
else
|
143
|
+
puts "."
|
144
|
+
end
|
145
|
+
exit
|
146
|
+
end
|
147
|
+
end
|
148
|
+
o.parse!(args)
|
149
|
+
options
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
@options = AmberVMOptParser.parse(ARGV)
|
155
|
+
@compiler = nil
|
156
|
+
@optvars = {}
|
157
|
+
|
158
|
+
v "Initializing environment."
|
159
|
+
|
160
|
+
@options.amber_library.each do |lib|
|
161
|
+
v "Loading AmberVM Library: #{lib}."
|
162
|
+
unless require(lib)
|
163
|
+
puts "ERROR: could not require internal library: #{lib}"
|
164
|
+
exit 1
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
load_compiler @options.language
|
169
|
+
|
170
|
+
if not @options.dont_execute
|
171
|
+
|
172
|
+
if @options.use_default_core_libs
|
173
|
+
if @options.optimize
|
174
|
+
@env = @compiler.optimized_env(@optvars)
|
175
|
+
else
|
176
|
+
@env = @compiler.env()
|
177
|
+
end
|
178
|
+
else
|
179
|
+
@env = AmberVM::Interpreter.env
|
180
|
+
end
|
181
|
+
|
182
|
+
@options.core_library.each do |lib|
|
183
|
+
v "Loading core library #{lib}."
|
184
|
+
if File.exist?(lib)
|
185
|
+
|
186
|
+
begin
|
187
|
+
v "Compiling core library #{lib}."
|
188
|
+
code = @compiler.compile(File.read(lib), true)
|
189
|
+
v "Optimizing library #{lib}" if @options.optimize
|
190
|
+
code = code.optimize(@optvars) if @options.optimize
|
191
|
+
begin
|
192
|
+
v "Executing library #{lib}."
|
193
|
+
code.execute(@env)
|
194
|
+
rescue Exception => e
|
195
|
+
puts "ERROR: could not execute core library: #{lib} #=> #{e}"
|
196
|
+
exit 4
|
197
|
+
end
|
198
|
+
rescue Exception => e
|
199
|
+
puts "ERROR: could not compile core library: #{lib} #=> #{e}"
|
200
|
+
exit 5
|
201
|
+
end
|
202
|
+
else
|
203
|
+
puts "ERROR: Could not load core library: #{lib}"
|
204
|
+
exit 6
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
@options.library.each do |lib|
|
209
|
+
v "Loading library #{lib}."
|
210
|
+
if File.exist?(lib)
|
211
|
+
begin
|
212
|
+
v "Compiling library #{lib}."
|
213
|
+
code = @compiler.compile(File.read(lib))
|
214
|
+
v "Optimizing library #{lib}" if @options.optimize
|
215
|
+
code = code.optimize(@optvars) if @options.optimize
|
216
|
+
begin
|
217
|
+
v "Executing library #{lib}."
|
218
|
+
code.execute(@env)
|
219
|
+
rescue Exception => e
|
220
|
+
puts "ERROR: could not execute library: #{lib} #=> #{e}"
|
221
|
+
exit 4
|
222
|
+
end
|
223
|
+
rescue Exception => e
|
224
|
+
puts "ERROR: could not compile library: #{lib} #=> #{e}"
|
225
|
+
exit 5
|
226
|
+
end
|
227
|
+
else
|
228
|
+
puts "ERROR: Could not load library: #{lib}"
|
229
|
+
exit 6
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
if @options.code
|
235
|
+
v "Executing: #{@options.code}."
|
236
|
+
@source = @options.code
|
237
|
+
else
|
238
|
+
if file = ARGV.first
|
239
|
+
if File.exist?(file)
|
240
|
+
@source = File.read(file)
|
241
|
+
else
|
242
|
+
puts "ERROR: Could not load source file: #{file}"
|
243
|
+
exit 7
|
244
|
+
end
|
245
|
+
else
|
246
|
+
puts "No files passed."
|
247
|
+
puts `#{$0} -h`
|
248
|
+
exit 8
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
begin
|
254
|
+
if @options.show_source
|
255
|
+
puts "\n### SOURCE ###"
|
256
|
+
i = 0; puts @source.gsub(/^/) { "%3d: " % [i += 1] }
|
257
|
+
end
|
258
|
+
v "Compiling program code."
|
259
|
+
code = @compiler.compile(@source, @options.run_as_core)
|
260
|
+
v "Optimizing code" if @options.optimize
|
261
|
+
code = code.optimize(@optvars) if @options.optimize
|
262
|
+
if @options.compilation
|
263
|
+
puts "\n### COMPILAT ###"
|
264
|
+
i = 0; puts code.pretty_inspect.gsub(/^/) { "%3d: " % [i += 1] }
|
265
|
+
end
|
266
|
+
unless @options.dont_execute
|
267
|
+
begin
|
268
|
+
v "Executing program code."
|
269
|
+
p code.execute(@env)
|
270
|
+
rescue Exception => e
|
271
|
+
puts "ERROR: could not execute program code #=> #{}"
|
272
|
+
raise e
|
273
|
+
end
|
274
|
+
end
|
275
|
+
rescue Exception => e
|
276
|
+
puts "ERROR: could not compile program code #=> #{e}"
|
277
|
+
raise e
|
278
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
=begin
|
2
|
+
The MIT License
|
3
|
+
|
4
|
+
Copyright (c) 2007 Heinz N. 'Licenser' Gies
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Ruby Mush"), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
14
|
+
all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
THE SOFTWARE.
|
23
|
+
=end
|
24
|
+
|
25
|
+
|
26
|
+
# AmberVM::ActsAsAmberVMType is a mixin that allows to quickly publish classes and types
|
27
|
+
# to the rVM interpreter without going through the hassle of defining each
|
28
|
+
# function on it's own and publisheing every varialbe that is watned.
|
29
|
+
#
|
30
|
+
# The function to call is ActsAsAmberVMTypeMethods::acts_as_amber_type.
|
31
|
+
#
|
32
|
+
# == Example
|
33
|
+
# class Test
|
34
|
+
# # Add the readers and writers for
|
35
|
+
# attr_accessor :var
|
36
|
+
# include AmberVM::ActsAsAmberVMType
|
37
|
+
# acts_as_amber_type
|
38
|
+
# register_variable :var
|
39
|
+
# register_function :to_s
|
40
|
+
# end
|
41
|
+
module AmberVM::ActsAsAmberVMType
|
42
|
+
|
43
|
+
# Called when included, loads the class methods and the instance methods needed.
|
44
|
+
def self.included(mod)
|
45
|
+
mod.extend(AmberVM::ActsAsAmberVMType::ActsAsAmberVMTypeMethods)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
module ActsAsAmberVMTypeMethods
|
50
|
+
# This function sets up the class to be a registerd class for rVM.
|
51
|
+
# It also sets it up to allow the use of +register_variable+ and
|
52
|
+
# +register_function+.
|
53
|
+
def acts_as_amber_type
|
54
|
+
# registering as class
|
55
|
+
extend AmberVM::Plugin
|
56
|
+
plugin_host AmberVM::Classes
|
57
|
+
register_for self.class.to_s.gsub(/(\w)([A-Z])/,"\1_" + "\2".downcase).to_sym
|
58
|
+
|
59
|
+
#initializing empty functions and variables hashes
|
60
|
+
@functions = {}
|
61
|
+
@variables = {}
|
62
|
+
|
63
|
+
#including DSL functions
|
64
|
+
extend AmberVM::ActsAsAmberVMType::ActsAsAmberVMTypeInstanceMethods
|
65
|
+
|
66
|
+
#including methods in class
|
67
|
+
include AmberVM::ActsAsAmberVMType::ActsAsAmberVMTypeSingeltonMethods
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module ActsAsAmberVMTypeSingeltonMethods
|
72
|
+
# This function will set up the variables for a rVM and replaces
|
73
|
+
# the current function with a shorter and faster one.
|
74
|
+
def variables
|
75
|
+
puts self.class
|
76
|
+
@variables = {}
|
77
|
+
#gets the variables hash from the Test class and maps it to a getter/setter Class
|
78
|
+
self.class.object_variables.each do |published_as, data|
|
79
|
+
name, writable = data
|
80
|
+
@variables[published_as.to_s] = AmberVM::Interpreter::VariableStorageCallback.new(self, name, writable)
|
81
|
+
end
|
82
|
+
#redefinces the variables method to remove overhead from mapping
|
83
|
+
instance_eval do
|
84
|
+
def variables
|
85
|
+
@variables
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Return the variables hash for the firs call.
|
90
|
+
@variables
|
91
|
+
end
|
92
|
+
|
93
|
+
# This function will set up the variables for a rVM and replaces
|
94
|
+
# the current function with a shorter and faster one.
|
95
|
+
def functions
|
96
|
+
# Copy the original functions hash so that changes to the instance
|
97
|
+
# wont't carry over to to other instances.
|
98
|
+
@functions = self.class.object_functions.dup
|
99
|
+
|
100
|
+
# Redefine the function method to speed up further accesses.
|
101
|
+
instance_eval do
|
102
|
+
def functions
|
103
|
+
@functions
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Return the functions hash for the first call.
|
108
|
+
@functions
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# This module hods the instance methods for classes that are supposed to
|
114
|
+
# act as a rVM type.
|
115
|
+
#
|
116
|
+
# It includes +register_variable+ and +register_function+ to help setting up
|
117
|
+
# the class quickly.
|
118
|
+
module ActsAsAmberVMTypeInstanceMethods
|
119
|
+
# This registers a variable for the rVM interface, it allows the scripts
|
120
|
+
# to read and write them. If +writable+ is set this will be a read only
|
121
|
+
# variable. It alls an be published to rVM under a different name,
|
122
|
+
# by passing +published_as+.
|
123
|
+
def register_variable name, writable = true, published_as = name
|
124
|
+
@variables[published_as.to_s] = [name.to_sym, writable]
|
125
|
+
end
|
126
|
+
|
127
|
+
# This registers a variable for the rVM interface, it allows the scripts
|
128
|
+
# to read and write them. If +writable+ is set this will be a read only
|
129
|
+
# variable. It alls an be published to rVM under a different name,
|
130
|
+
# by passing +published_as+.
|
131
|
+
def register_function name, published_as = name
|
132
|
+
@functions[published_as.to_s] = Class.new(AmberVM::Functions::Function) do @name = name; end
|
133
|
+
class << @functions[published_as.to_s]
|
134
|
+
def execute params, env
|
135
|
+
env.read_var_val(:self).send(@name, *params)
|
136
|
+
end
|
137
|
+
|
138
|
+
def signature
|
139
|
+
[:any]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Returns the hash of variables for to be used only internally by the
|
145
|
+
# ActsAsAmberVMTypeSingeltonMethods#variables function to set up the details.
|
146
|
+
def object_variables
|
147
|
+
@variables
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns the hash of variables for to be used only internally by the
|
151
|
+
# ActsAsAmberVMTypeSingeltonMethods#variables function to set up the details.
|
152
|
+
def object_functions
|
153
|
+
@functions
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module AmberVM
|
2
|
+
module Classes
|
3
|
+
class Association < Hash
|
4
|
+
extend Plugin
|
5
|
+
plugin_host Classes
|
6
|
+
register_for :association
|
7
|
+
@@type = :association
|
8
|
+
|
9
|
+
def data_type
|
10
|
+
:list
|
11
|
+
end
|
12
|
+
|
13
|
+
def variables
|
14
|
+
@variables ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def functions
|
19
|
+
@functions ||= {
|
20
|
+
'size' => AmberVM::Functions[:size],
|
21
|
+
'length' => AmberVM::Functions[:size],
|
22
|
+
'get' => AmberVM::Functions[:assoc_get],
|
23
|
+
'set' => AmberVM::Functions[:assoc_set],
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize source= {}, sepperator = ' '
|
28
|
+
super()
|
29
|
+
if source.is_a?(::Hash) # Okay we've to hack here to get sure we get the /real/ String
|
30
|
+
self.merge! source
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module AmberVM
|
2
|
+
module Classes
|
3
|
+
class Block < AmberVM::Classes::Class
|
4
|
+
attr_accessor :code
|
5
|
+
register_for :block
|
6
|
+
def initialize code
|
7
|
+
super()
|
8
|
+
@type = :any
|
9
|
+
@code = code
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute env
|
13
|
+
end
|
14
|
+
|
15
|
+
def execargs
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
class Variable_container
|
20
|
+
def initialize parent
|
21
|
+
@parent = parent
|
22
|
+
@data = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def [] k
|
26
|
+
@data[k] || @parent[k]
|
27
|
+
end
|
28
|
+
|
29
|
+
def []= k, v
|
30
|
+
@data[k] = v
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def optimize variables = {}
|
35
|
+
#old_keys = Set.new(variables.keys)
|
36
|
+
code = @code.optimize variables
|
37
|
+
#(Set.new(variables.keys) - old_keys).each do |key|
|
38
|
+
# variables.delete(key)
|
39
|
+
#end
|
40
|
+
Block.new(code)
|
41
|
+
end
|
42
|
+
|
43
|
+
def call params, env, pos = nil
|
44
|
+
AmberVM::debug "Calling Block at #{pos}...(evn: #{env.pretty_inspect}, params: #{params})" if $DEBUG
|
45
|
+
env = AmberVM::Interpreter::Environment.new({:params => params||[]}, env)
|
46
|
+
return (catch :return do
|
47
|
+
@code.execute(env)
|
48
|
+
end).val
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module AmberVM
|
2
|
+
module Classes
|
3
|
+
class Boolean < AmberVM::Classes::Class
|
4
|
+
register_for :boolean
|
5
|
+
|
6
|
+
def data_type
|
7
|
+
:boolean
|
8
|
+
end
|
9
|
+
|
10
|
+
def hash
|
11
|
+
@value.hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def eql?(o)
|
15
|
+
if o.is_a?(AmberVM::Classes::Boolean)
|
16
|
+
o.is_true? == is_true?
|
17
|
+
else
|
18
|
+
@value == o
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize value
|
23
|
+
super()
|
24
|
+
if value
|
25
|
+
if value.respond_to? :is_true?
|
26
|
+
@value = value.is_true?
|
27
|
+
else
|
28
|
+
@value = true
|
29
|
+
end
|
30
|
+
else
|
31
|
+
@value = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def is_true?
|
36
|
+
@value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module AmberVM
|
2
|
+
module Classes
|
3
|
+
class VMClass < AmberVM::Classes::Class
|
4
|
+
register_for :class
|
5
|
+
|
6
|
+
attr_reader :object_functions
|
7
|
+
attr_reader :functions
|
8
|
+
|
9
|
+
attr_reader :variables
|
10
|
+
attr_accessor :initializer
|
11
|
+
attr_accessor :parent
|
12
|
+
|
13
|
+
def data_type
|
14
|
+
:class
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(parent = nil, initialize_name = "create");
|
18
|
+
super()
|
19
|
+
@initializer = initialize_name
|
20
|
+
@functions = {}
|
21
|
+
@variables = {}
|
22
|
+
@object_functions = {}
|
23
|
+
@parent = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def obj_send(method, params, env)
|
27
|
+
if method == @initializer
|
28
|
+
instance params, env
|
29
|
+
else
|
30
|
+
m = @functions[method]
|
31
|
+
m = @parent.functions(method) if not m and @parent
|
32
|
+
raise "Unknown method #{method} for object #{self}" if not m
|
33
|
+
AmberVM::debug "Executing object method #{method}." if $DEBUG
|
34
|
+
params.unshift self
|
35
|
+
env = AmberVM::Interpreter::Environment.new({:params => params||[], :locals => @variables, :functions => @functions}, env)
|
36
|
+
m.call(params, env)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def instance params, env
|
41
|
+
o = AmberVM::Classes::Object.new self
|
42
|
+
env = AmberVM::Interpreter::Environment.new({:params => params||[], :locals => @variables, :functions => @functions}, env)
|
43
|
+
o.obj_send(@initializer, params, env) #if @object_functions[@initializer]
|
44
|
+
AmberVM::debug "Creating instance of #{self}: #{o.inspect}." if $DEBUG
|
45
|
+
o
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AmberVM
|
2
|
+
module Classes
|
3
|
+
class Error < AmberVM::Classes::Class
|
4
|
+
register_for :error
|
5
|
+
attr_accessor :value
|
6
|
+
@@type = :error
|
7
|
+
def initialize value, text = "This is an error!"
|
8
|
+
super()
|
9
|
+
@value = value.to_i
|
10
|
+
@text = text
|
11
|
+
end
|
12
|
+
|
13
|
+
def is_true?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
"##{@value} #{@text}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|