AmberVM 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. data/README +38 -0
  2. data/bin/ambervm +278 -0
  3. data/lib/amber/acts_as_rvm_type.rb +157 -0
  4. data/lib/amber/classes/association.rb +36 -0
  5. data/lib/amber/classes/block.rb +52 -0
  6. data/lib/amber/classes/boolean.rb +40 -0
  7. data/lib/amber/classes/class.rb +50 -0
  8. data/lib/amber/classes/error.rb +22 -0
  9. data/lib/amber/classes/list.rb +96 -0
  10. data/lib/amber/classes/null.rb +35 -0
  11. data/lib/amber/classes/number.rb +95 -0
  12. data/lib/amber/classes/object.rb +56 -0
  13. data/lib/amber/classes/string.rb +79 -0
  14. data/lib/amber/classes.rb +113 -0
  15. data/lib/amber/environment.rb +251 -0
  16. data/lib/amber/fukubukuro/ecma_core.rb +409 -0
  17. data/lib/amber/fukubukuro.rb +866 -0
  18. data/lib/amber/functions/all.rb +3 -0
  19. data/lib/amber/functions/array/append.rb +50 -0
  20. data/lib/amber/functions/array/at.rb +50 -0
  21. data/lib/amber/functions/array/set_at.rb +50 -0
  22. data/lib/amber/functions/array.rb +30 -0
  23. data/lib/amber/functions/association/assoc_get.rb +55 -0
  24. data/lib/amber/functions/association/assoc_set.rb +56 -0
  25. data/lib/amber/functions/bitwise/bitwise_and.rb +41 -0
  26. data/lib/amber/functions/bitwise/bitwise_not.rb +41 -0
  27. data/lib/amber/functions/bitwise/bitwise_or.rb +41 -0
  28. data/lib/amber/functions/bitwise/bitwise_xor.rb +41 -0
  29. data/lib/amber/functions/bitwise.rb +3 -0
  30. data/lib/amber/functions/collection/get.rb +66 -0
  31. data/lib/amber/functions/collection/set.rb +67 -0
  32. data/lib/amber/functions/collection/size.rb +54 -0
  33. data/lib/amber/functions/general/cmp.rb +43 -0
  34. data/lib/amber/functions/general/eq.rb +45 -0
  35. data/lib/amber/functions/general/gt.rb +45 -0
  36. data/lib/amber/functions/general/gte.rb +45 -0
  37. data/lib/amber/functions/general/lt.rb +45 -0
  38. data/lib/amber/functions/general/lte.rb +45 -0
  39. data/lib/amber/functions/general/neq.rb +45 -0
  40. data/lib/amber/functions/general/type.rb +43 -0
  41. data/lib/amber/functions/general.rb +3 -0
  42. data/lib/amber/functions/io/print.rb +45 -0
  43. data/lib/amber/functions/io.rb +3 -0
  44. data/lib/amber/functions/list/align.rb +73 -0
  45. data/lib/amber/functions/list/join.rb +45 -0
  46. data/lib/amber/functions/list/map.rb +58 -0
  47. data/lib/amber/functions/list/split.rb +55 -0
  48. data/lib/amber/functions/list.rb +3 -0
  49. data/lib/amber/functions/logic/and.rb +55 -0
  50. data/lib/amber/functions/logic/not.rb +40 -0
  51. data/lib/amber/functions/logic/or.rb +50 -0
  52. data/lib/amber/functions/logic.rb +3 -0
  53. data/lib/amber/functions/math/abs.rb +39 -0
  54. data/lib/amber/functions/math/acos.rb +39 -0
  55. data/lib/amber/functions/math/add.rb +40 -0
  56. data/lib/amber/functions/math/asin.rb +39 -0
  57. data/lib/amber/functions/math/atan.rb +39 -0
  58. data/lib/amber/functions/math/ceil.rb +39 -0
  59. data/lib/amber/functions/math/cos.rb +39 -0
  60. data/lib/amber/functions/math/dec.rb +39 -0
  61. data/lib/amber/functions/math/div.rb +44 -0
  62. data/lib/amber/functions/math/exp.rb +39 -0
  63. data/lib/amber/functions/math/floor.rb +39 -0
  64. data/lib/amber/functions/math/inc.rb +39 -0
  65. data/lib/amber/functions/math/log.rb +39 -0
  66. data/lib/amber/functions/math/mod.rb +41 -0
  67. data/lib/amber/functions/math/mul.rb +43 -0
  68. data/lib/amber/functions/math/neg.rb +43 -0
  69. data/lib/amber/functions/math/power.rb +43 -0
  70. data/lib/amber/functions/math/rand.rb +36 -0
  71. data/lib/amber/functions/math/round.rb +39 -0
  72. data/lib/amber/functions/math/shl.rb +41 -0
  73. data/lib/amber/functions/math/shr.rb +41 -0
  74. data/lib/amber/functions/math/sin.rb +39 -0
  75. data/lib/amber/functions/math/sub.rb +43 -0
  76. data/lib/amber/functions/math/tan.rb +39 -0
  77. data/lib/amber/functions/math.rb +3 -0
  78. data/lib/amber/functions/objects/send.rb +22 -0
  79. data/lib/amber/functions/rails/print.rb +44 -0
  80. data/lib/amber/functions/rails.rb +3 -0
  81. data/lib/amber/functions/string/ansi.rb +24 -0
  82. data/lib/amber/functions/string/capstr.rb +23 -0
  83. data/lib/amber/functions/string/center.rb +25 -0
  84. data/lib/amber/functions/string/chr.rb +16 -0
  85. data/lib/amber/functions/string/ljust.rb +26 -0
  86. data/lib/amber/functions/string/regmatch.rb +34 -0
  87. data/lib/amber/functions/string/rjust.rb +26 -0
  88. data/lib/amber/functions/string.rb +3 -0
  89. data/lib/amber/functions.rb +103 -0
  90. data/lib/amber/interpreter.rb +1380 -0
  91. data/lib/amber/languages/brainfuck.rb +153 -0
  92. data/lib/amber/languages/ecma/compiler.rb +1661 -0
  93. data/lib/amber/languages/ecma/core-math.js +67 -0
  94. data/lib/amber/languages/ecma/core-objects.js +57 -0
  95. data/lib/amber/languages/ecma.rb +9 -0
  96. data/lib/amber/languages/ecma_fuku/compiler.rb +1622 -0
  97. data/lib/amber/languages/ecma_fuku/core-math.js +67 -0
  98. data/lib/amber/languages/ecma_fuku/core-objects.js +56 -0
  99. data/lib/amber/languages/ecma_fuku.rb +13 -0
  100. data/lib/amber/languages/math/compiler.rb +70 -0
  101. data/lib/amber/languages/math/tokenizer.rb +69 -0
  102. data/lib/amber/languages/math/tree.rb +110 -0
  103. data/lib/amber/languages/math.rb +26 -0
  104. data/lib/amber/languages.rb +99 -0
  105. data/lib/amber/library.rb +79 -0
  106. data/lib/amber/optimisation.rb +299 -0
  107. data/lib/amber/plugin.rb +337 -0
  108. data/lib/amber/rails.rb +90 -0
  109. data/lib/amber.rb +106 -0
  110. data/spec/amber/class_spec.rb +27 -0
  111. data/spec/amber/enviroment_spec.rb +61 -0
  112. data/spec/amber/function_spec.rb +25 -0
  113. data/spec/amber/functions/association/assoc_get_spec.rb +41 -0
  114. data/spec/amber/functions/association/assoc_set_spec.rb +43 -0
  115. data/spec/amber/functions/collection/get_spec.rb +12 -0
  116. data/spec/amber/functions/collection/set_spec.rb +10 -0
  117. data/spec/amber/functions/collection/size_spec.rb +10 -0
  118. data/spec/amber/functions/list/split_spec.rb +47 -0
  119. data/spec/amber/functions/string/ansi_spec.rb +44 -0
  120. data/spec/amber/functions/string/capstr_spec.rb +42 -0
  121. data/spec/amber/functions/string/center_spec.rb +49 -0
  122. data/spec/amber/functions/string/ljust_spec.rb +49 -0
  123. data/spec/amber/functions/string/regmatch_spec.rb +52 -0
  124. data/spec/amber/functions/string/rjust_spec.rb +49 -0
  125. data/spec/amber/interpreter/assignment_spec.rb +22 -0
  126. data/spec/amber/interpreter/condition_spec.rb +103 -0
  127. data/spec/amber/interpreter/constant_spec.rb +31 -0
  128. data/spec/amber/interpreter/core_call_spec.rb +72 -0
  129. data/spec/amber/interpreter/interpreter_spec.rb +11 -0
  130. data/spec/amber/interpreter/parameter_spec.rb +24 -0
  131. data/spec/amber/interpreter/sequence_spec.rb +47 -0
  132. data/spec/amber/interpreter/variable_spec.rb +24 -0
  133. data/spec/amber/plugin_spec.rb +10 -0
  134. data/spec/classes/atom/association_spec.rb +39 -0
  135. data/spec/classes/atom/block_spec.rb +25 -0
  136. data/spec/classes/atom/boolean_spec.rb +67 -0
  137. data/spec/classes/atom/error_spec.rb +43 -0
  138. data/spec/classes/atom/list_spec.rb +68 -0
  139. data/spec/classes/atom/number_spec.rb +132 -0
  140. data/spec/classes/atom/string_spec.rb +175 -0
  141. data/spec/languages/ecma/ecma_array_spec.rb +79 -0
  142. data/spec/languages/ecma/ecma_closure_spec.rb +38 -0
  143. data/spec/languages/ecma/ecma_literals_spec.rb +71 -0
  144. data/spec/languages/ecma/ecma_objects_spec.rb +165 -0
  145. data/spec/languages/ecma/ecma_old_spec.rb +540 -0
  146. data/spec/languages/ecma/ecma_spec.rb +64 -0
  147. data/spec/languages/ecma_fuku/ecma_array_spec.rb +61 -0
  148. data/spec/languages/ecma_fuku/ecma_closure_spec.rb +33 -0
  149. data/spec/languages/ecma_fuku/ecma_function_spec.rb +84 -0
  150. data/spec/languages/ecma_fuku/ecma_literals_spec.rb +55 -0
  151. data/spec/languages/ecma_fuku/ecma_objects_spec.rb +133 -0
  152. data/spec/languages/ecma_fuku/ecma_old_spec.rb +415 -0
  153. data/spec/languages/ecma_fuku/ecma_operator_spec.rb +33 -0
  154. data/spec/languages/ecma_fuku/ecma_spec.rb +52 -0
  155. data/spec/languages/math/compiler_spec.rb +49 -0
  156. data/spec/languages/math/tokenizer_spec.rb +73 -0
  157. data/spec/languages/math/tree_spec.rb +153 -0
  158. metadata +225 -0
@@ -0,0 +1,67 @@
1
+ Math = {
2
+ sin: function(x) {
3
+ return __AmberVM__.sin(x);
4
+ },
5
+ cos: function(x) {
6
+ return __AmberVM__.cos(x);
7
+ },
8
+ pow: function(x,y) {
9
+ return __AmberVM__.power(x, y);
10
+ },
11
+ abs: function(x) {
12
+ return __AmberVM__.abs(x);
13
+ },
14
+ acos: function(x) {
15
+ return __AmberVM__.acos(x);
16
+ },
17
+ asin: function(x) {
18
+ return __AmberVM__.asin(x);
19
+ },
20
+ atan: function(x) {
21
+ return __AmberVM__.atan(x);
22
+ },
23
+ atan2: function(x, y) {
24
+ return __AmberVM__.atan(x, y);
25
+ },
26
+ ceil: function(x) {
27
+ return __AmberVM__.ceil(x);
28
+ },
29
+ exp: function(x) {
30
+ return __AmberVM__.exp(x);
31
+ },
32
+ floor: function(x) {
33
+ return __AmberVM__.floor(x);
34
+ },
35
+ log: function(x) {
36
+ return __AmberVM__.log(x);
37
+ },
38
+ random: function() {
39
+ return __AmberVM__.rand();
40
+ //return 4;
41
+ },
42
+ round: function(x) {
43
+ return __AmberVM__.round(x);
44
+ },
45
+ sqrt: function(x) {
46
+ //return __AmberVM__.sqrt(x); //Do we want that or do we just use power?
47
+ return __AmberVM__.power(x, 0.5);
48
+ },
49
+ tan: function(x) {
50
+ return __AmberVM__.tan(x);
51
+ },
52
+ /*NOT IMPLEMENTED! TODO: Implement functions with a variable number of arguments, or rather how to handle them.
53
+ max: function(*x) {
54
+ return __AmberVM__.max(x);
55
+ },
56
+ min: function(*x) {
57
+ return __AmberVM__.min(x);
58
+ }*/
59
+ E: 2.7182818284590452354,
60
+ LN10: 2.302585092994046,
61
+ LN2: 0.6931471805599453,
62
+ LOG2E: 1.4426950408889634,
63
+ LOG10E: 0.4342944819032518,
64
+ PI: 3.1415926535897932,
65
+ SQRT1_2: 0.7071067811865476,
66
+ SQRT2: 1.4142135623730951
67
+ };
@@ -0,0 +1,56 @@
1
+ function Array(n) {
2
+ a = [];
3
+ if (n && (n >= 1)) {
4
+ a = a + [null];
5
+ while (n > 1) {
6
+ if ((n % 2) == 0) {
7
+ a = a + a;
8
+ n = n/2;
9
+ } else {
10
+ a = a + [null];
11
+ n--;
12
+ };
13
+ };
14
+ };
15
+ return a;
16
+ };
17
+
18
+ function print(x) {
19
+ __AmberVM__.print(x, "\n");
20
+ }
21
+
22
+ Core = {
23
+ inc: function(x) {
24
+ return __AmberVM__.add(1, x);
25
+ },
26
+ dec: function(x) {
27
+ return __AmberVM__.add(-1, x);
28
+ },
29
+ type: function(x) {
30
+ t = __AmberVM__.type(x);
31
+ if (t == "AmberVM::Classes::String")
32
+ return "string";
33
+ else if (t == "AmberVM::Classes::Number")
34
+ return "number";
35
+ else if (t == "AmberVM::Classes::Boolen")
36
+ return "boolean";
37
+ else if (t == "AmberVM::Classes::List")
38
+ return "array";
39
+ else if (t == "AmberVM::Classes::Object")
40
+ return "object";
41
+ else
42
+ return t;
43
+ },
44
+ plus: function(a,b) {
45
+ if (__AmberVM__.type(a) == "AmberVM::Classes::String" || __AmberVM__.type(b) == "AmberVM::Classes::String")
46
+ return __AmberVM__.add("", a,b);
47
+ else
48
+ return __AmberVM__.add(a,b);
49
+ }
50
+ };
51
+
52
+ Undefined = {
53
+ undefined: null
54
+ };
55
+
56
+ Null = null;
@@ -0,0 +1,13 @@
1
+ module AmberVM
2
+ module Languages
3
+ # A compiler for JavaScript.
4
+ class ECMA_Fuku < AmberVM::Languages::Language
5
+ register_for :'ecma_fuku'
6
+ plugin_id
7
+ helper :compiler
8
+ def default_env
9
+ @compiler.env
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,70 @@
1
+ module AmberVM
2
+ module Languages
3
+ class Math
4
+ class Compiler
5
+ include AmberVM::Interpreter
6
+ FUNCTION_MAP = {
7
+ '+' => :add,
8
+ '-' => :sub,
9
+ '/' => :div,
10
+ '*' => :mul,
11
+ '^' => :power
12
+ }
13
+ def Compiler.compile tree
14
+ if tree.is_a? Array
15
+ compile(tree.first)
16
+ elsif tree.is_a? Hash
17
+ case tree[:type]
18
+ when :number
19
+ Interpreter.const(:number, tree[:number])
20
+ when :function
21
+ params = tree[:params].map {|p| compile(p)}
22
+ case tree[:op]
23
+ when '-'
24
+ CoreCall.new :neg, params
25
+ else
26
+ FunctionCall.new tree[:op], params
27
+ end
28
+ when :ident
29
+ Interpreter::Variable.new(Interpreter.const(:string, tree[:ident]))
30
+ when :op
31
+ case tree[:op]
32
+ when ';'
33
+ s = Interpreter::Sequence.new()
34
+ if (tree[:left][:type] == :op) and (tree[:left][:op] == ';')
35
+ s += compile(tree[:left])
36
+ else
37
+ s << compile(tree[:left])
38
+ end
39
+ if (tree[:right][:type] == :op) and (tree[:right][:op] == ';')
40
+ s += compile(tree[:right])
41
+ else
42
+ s << compile(tree[:right])
43
+ end
44
+ when '='
45
+ case tree[:left][:type]
46
+ when :ident
47
+ Interpreter::Assignment.new(Interpreter.const(:string, tree[:left][:ident]),compile(tree[:right]))
48
+ when :function
49
+ body = Interpreter::Sequence.new()
50
+ i = 0
51
+ tree[:left][:params].each do |p|
52
+ raise ArgumentError, "Bad ype for a function parameter: #{p[:type]} " if p[:type] != :ident
53
+ body << Interpreter::Assignment.new(Interpreter.const(:string, p[:ident]), Interpreter::Parameter.new(Interpreter.const(:number, i)))
54
+ i += 1
55
+ end
56
+ body << compile(tree[:right])
57
+ Interpreter::FunctionDefinition.new(Interpreter.const(:string, tree[:left][:op]), AmberVM::Classes::Block.new(body))
58
+ else
59
+ raise ArgumentError, "Bad name for a variable!"
60
+ end
61
+ else
62
+ CoreCall.new(FUNCTION_MAP[tree[:op]], [compile(tree[:left]),compile(tree[:right])])
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,69 @@
1
+ require 'strscan'
2
+ module AmberVM
3
+ module Languages
4
+ class Math
5
+ class Tokenizer
6
+ def Tokenizer.tokenize str
7
+ s = StringScanner.new str
8
+ tokens = []
9
+ state = :number
10
+ paren_deepth = 0
11
+ while not s.eos?
12
+ s.skip(/\s*/)
13
+ if state == :number
14
+ if s.scan(/[+-]+/)
15
+ t = s.matched.gsub('+','').gsub('--','')
16
+ if t == '-'
17
+ tokens << [t, :function]
18
+ end
19
+ elsif s.scan(/[_a-z][_a-z0-9]*/i)
20
+ r = s.matched
21
+ if s.scan(/\(/)
22
+ tokens << [r, :function]
23
+ if s.scan(/\)/)
24
+ tokens << [s.matched, :paren_close]
25
+ else
26
+ paren_deepth += 1
27
+ end
28
+ else
29
+ tokens << [r, :ident]
30
+ state = :opperator
31
+ end
32
+ elsif s.scan(/((\d+(\.\d+)?)|(\.\d+))(e-?\d+)?/i)
33
+ tokens << [s.matched, :number]
34
+ state = :opperator
35
+ elsif s.scan(/\(/)
36
+ paren_deepth += 1
37
+ tokens << [s.matched, :paren_open]
38
+ else
39
+ raise "Unknown literal in term at positin #{s.pos}."
40
+ end
41
+ else
42
+ if s.scan(/\)/)
43
+ paren_deepth -= 1
44
+ raise "Unmatched parenthes at #{s.pos}" if paren_deepth < 0
45
+ tokens << [s.matched, :paren_close]
46
+ elsif s.scan(/,/)
47
+ tokens << [s.matched, :function_sep]
48
+ state = :number
49
+ elsif s.scan(/[*+\/^=-]/)
50
+ tokens << [s.matched, :opperator]
51
+ state = :number
52
+ elsif s.scan(/;/)
53
+ if paren_deepth == 0
54
+ tokens << [s.matched, :opperator]
55
+ state = :number
56
+ else
57
+ raise "Expression sepperator enclosed in parenthes at #{s.pos}"
58
+ end
59
+ else
60
+ raise "Unknown literal in term at positin #{s.pos}."
61
+ end
62
+ end
63
+ end
64
+ tokens
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,110 @@
1
+ module AmberVM
2
+ module Languages
3
+ class Math
4
+ class Tree
5
+ PRIORITIES = {
6
+ ';' => -100,
7
+ '=' => -50,
8
+ '(' => 0,
9
+ '+' => 10,
10
+ '-' => 10,
11
+ '*' => 20,
12
+ '/' => 20,
13
+ '^' => 30,
14
+ }
15
+ ASSOSICATIONS = {
16
+ ';' => :right,
17
+ '+' => :left,
18
+ '-' => :left,
19
+ '*' => :left,
20
+ '/' => :left,
21
+ '^' => :right,
22
+ '=' => :right
23
+ }
24
+ def Tree.generate tokens
25
+ output = []
26
+ dbgoutput = []
27
+ stack = []
28
+ dbgstack = []
29
+ while not tokens.empty?
30
+ token = tokens.shift
31
+ case token[1]
32
+ when :function
33
+ fun = token[0]
34
+ stack << {:type => :function, :op => fun}
35
+ output << {:type => :function_end}
36
+ dbgoutput << ')'
37
+ dbgstack << fun
38
+ when :function_sep
39
+ while stack.last && (stack.last[:type] != :function)
40
+ output << stack.pop
41
+ dbgoutput << dbgstack.pop
42
+ end
43
+ when :paren_open
44
+ op = token[0]
45
+ stack << {:type => :op, :op => op}
46
+ dbgstack << op
47
+ when :paren_close
48
+ while stack.last && (stack.last[:op] != '(')
49
+ output << stack.pop
50
+ dbgoutput << dbgstack.pop
51
+ end
52
+ stack.pop
53
+ dbgstack.pop
54
+ when :number
55
+ output << {:type => :number, :number => token[0]}
56
+ dbgoutput << token[0]
57
+ when :ident
58
+ output << {:type => :ident, :ident => token[0]}
59
+ dbgoutput << token[0]
60
+ when :opperator
61
+ op = token[0]
62
+ ass = ASSOSICATIONS[op]
63
+ o1p = PRIORITIES[op]
64
+ while stack.last && (stack.last[:type] != :function) &&
65
+ (((ass == :left) && (o1p <= PRIORITIES[stack.last[:op]])) ||
66
+ ((ass == :right) && (o1p < PRIORITIES[stack.last[:op]])))
67
+ output << stack.pop
68
+ dbgoutput << dbgstack.pop
69
+ end
70
+ stack << {:type => :op, :op => op}
71
+ dbgstack << op
72
+ else
73
+ raise "Unknown element in parser tree: #{token.inspect}"
74
+ end
75
+ p(dbgstack) if $DEBUG
76
+ p(dbgoutput) if $DEBUG
77
+ end
78
+ while not stack.empty?
79
+ output << stack.pop
80
+ end
81
+ gen_tree output
82
+ end
83
+
84
+ private
85
+ def Tree.gen_tree data
86
+ item = data.pop
87
+ case item[:type]
88
+ when :number, :ident
89
+ item
90
+ when :op
91
+ item[:right] = gen_tree(data)
92
+ if item[:op] == ';' and data.empty?
93
+ item = item[:right]
94
+ else
95
+ item[:left] = gen_tree(data)
96
+ end
97
+ item
98
+ when :function
99
+ item[:params] = []
100
+ while data.last && data.last[:type] != :function_end
101
+ item[:params] << gen_tree(data)
102
+ end
103
+ data.pop
104
+ item
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,26 @@
1
+ require 'amber/functions/math'
2
+ module AmberVM
3
+ module Languages
4
+ # This compiler handels mathematical expressions.
5
+ #
6
+ # It is limited to smiple terms, as in for example integration of functions is not offered.
7
+ # Yet it is hopefully enough to serve most mathematical needs.
8
+ #
9
+ # Included are:
10
+ # * Opperators: +, -, *, /, ^
11
+ # * Parenthetes
12
+ # * Functions (as in proveded by the 'amber/funcions/math' library or custom loaded)
13
+ # * Currect prioriets in execution
14
+ # * Support for variables (getting and setting)
15
+ # * Multiple concatinated statemetns sepperated by ';'
16
+ # * Custom functions (as in defining as well as calling)
17
+ class Math < AmberVM::Languages::Language
18
+ register_for :math
19
+ helper :tokenizer, :tree, :compiler
20
+
21
+ def compile text
22
+ Compiler.compile(Tree.generate(Tokenizer.tokenize(text)))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,99 @@
1
+ # = languages.rb - Class Plugin Library
2
+ #
3
+ # Copyright (C) 2008 Heinz N. Gies (heinz@licenser.net)
4
+ #
5
+ # This file is published under the MIT Licenser, see LICENSE for details.
6
+ require 'amber/plugin'
7
+ module AmberVM
8
+ # This module is the basic language container, classes are supposed to be
9
+ # used by this as in: AmberVM::Language[<class id>] this guarnatees that,
10
+ # in the case of overwriting a standard compilers the code still works.
11
+ #
12
+ # This are *COMPILERS* not *INTERPRETERS* they compile source code to a
13
+ # VM bytecode to be executed later
14
+ #
15
+ # Have a look at AmberVM::Interpreter for details
16
+ #
17
+ # == Example
18
+ #
19
+ # === COMPILING A MATHEMATICAL EQUILATION
20
+ #
21
+ # require 'lib/base/languages'
22
+ # code = AmberVM::Classes[:math].compile '(1 + 1) * 3^2'
23
+ module Languages
24
+ extend AmberVM::PluginHost
25
+ plugin_path File.dirname(__FILE__), 'languages'
26
+
27
+ # The Compiler class, it holds the compiler. As those grow big I suggest
28
+ # to split the actuall code into multiple fils. Have a look at the MUSHCode
29
+ # compile for an example.
30
+ class Language
31
+ extend AmberVM::Plugin
32
+ plugin_host Languages
33
+
34
+ def initialize *args
35
+ @compiler = self.class::Compiler.new(*args)
36
+ @core_libs = nil
37
+ core_libs
38
+ end
39
+
40
+ # Loads the core libaries for a language, they have to be in the directory
41
+ # amber/langauges/LANGUAGE_ID/ directory and have to be named core-* to be
42
+ # recongnized ase core libraries.
43
+ # For speed reasons the core libraries will be cahced, to force them to be
44
+ # recompiled use the force_reload parameter as true.
45
+ def core_libs force_reload=false, additional_core_libs=[]
46
+ if not @core_libs or force_reload
47
+ @core_libs = additional_core_libs
48
+ Dir[File.join(File.dirname(__FILE__), 'languages', self.class.plugin_id.to_s, 'core-*')].each do |f|
49
+ begin
50
+ @core_libs << compile(File.read(f),true)
51
+ rescue Exception => e
52
+ puts "Failed to compile core library: #{f}."
53
+ raise e
54
+ end
55
+ end
56
+ end
57
+
58
+ def version
59
+ @compiler.version
60
+ end
61
+
62
+ @core_libs
63
+ end
64
+
65
+ # This method returns a environment that has the needed core libraries loaded.
66
+ #
67
+ # When your langauge uses core libraries to publish AmberVM functions to the program
68
+ # this should be used.
69
+ # The first parameter force_reload can be passed to forcefully reload the core
70
+ # libraries.
71
+ # The second parameter can be passed to add the core libraries to an existing
72
+ # environment.
73
+ def env force_reload=false, additional_core_libs=[], core_env=nil
74
+ core_env ||= default_env
75
+ core_libs(force_reload, additional_core_libs).each do |lib|
76
+ lib.execute(core_env)
77
+ end
78
+ core_env
79
+ end
80
+
81
+ def optimized_env variables={}, force_reload=false, additional_core_libs=[], core_env=nil
82
+ core_env ||= default_env
83
+ core_libs(force_reload, additional_core_libs).each do |lib|
84
+ lib.optimize(variables).execute(core_env)
85
+ end
86
+ core_env
87
+ end
88
+
89
+ def default_env
90
+ AmberVM::Interpreter.env
91
+ end
92
+
93
+ # Compiles a code with the generated compiler.
94
+ def compile code, *args
95
+ @compiler.compile code, *args
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,79 @@
1
+ require 'amber'
2
+
3
+ module AmberVM
4
+
5
+ # The Library class is made to provide library loading capabilites
6
+ # using any rVM supporte langauges and build a frontend between
7
+ # the rVM code and the Ruby code
8
+ #
9
+ # A Library can hold the content of more then one, file and the loaded
10
+ # files are not required to have the same langauge
11
+ class Library
12
+ # This maps rVM classes to usual Ruby classes so you won't need to take care of it
13
+ CLASS_MAP={
14
+ String => AmberVM::Classes::String,
15
+ Fixnum => AmberVM::Classes::Number,
16
+ Bignum => AmberVM::Classes::Number,
17
+ Float => AmberVM::Classes::Number,
18
+ FalseClass => AmberVM::Classes::Boolean,
19
+ TrueClass => AmberVM::Classes::Boolean,
20
+ Array => AmberVM::Classes::List
21
+ }
22
+ # Initializes library, if anguage and file are given, they are loaded
23
+ # Optionally a saftey object can be passed to handle securing the
24
+ # interpreted code
25
+ def initialize(language, file = nil, safety = AmberVM::Safety.new)
26
+ @lang = AmberVM::Languages[language].new
27
+ @env = AmberVM::Interpreter.env #@lang.env
28
+ @safety = safety
29
+ load_library(file) if file
30
+ end
31
+
32
+ #Loads a file into the Library, attention it is executed!
33
+ def load_library(file)
34
+ @safety.execute(@lang.compile(File.read(file)),@env)
35
+ end
36
+
37
+ def call_function(name, *args)
38
+ # First we convert the args
39
+ vmargs = args.map do |arg|
40
+ if c = CLASS_MAP[arg.class]
41
+ c.new(arg)
42
+ else
43
+ arg
44
+ end
45
+ end
46
+ n = name.to_s
47
+ if fun = @env.function(n)
48
+ fun.call(vmargs, @env)
49
+ elsif v = @env[n]
50
+ v.val
51
+ elsif n =~ /=$/
52
+ @env[n.gsub(/=$/,'')] = vmargs.first
53
+ else
54
+ raise "oops!"
55
+ end
56
+ end
57
+ # This is the most important part, so to say, the ruby magic in here
58
+ # If a unknown method is called this gets executed to try to resole it form the
59
+ # loaded libraires
60
+ #
61
+ # Priorities are:
62
+ # 1) check the functions
63
+ # 2) check if it was a variable
64
+ # 3) check if the call ended with a '=' then set it's as variable
65
+ # 4) call super
66
+ def method_missing(m, *args)
67
+ begin
68
+ call_function(m, args)
69
+ rescue Exception => e
70
+ super(m, args)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+
77
+
78
+
79
+