rVM 0.0.4 → 0.0.5

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.
@@ -40,8 +40,6 @@ module RVM
40
40
  @data = {
41
41
  :locals => {},
42
42
  :functions => {},
43
- :caller => nil,
44
- :self => nil,
45
43
  :evaldeepth => 0,
46
44
  :params => []
47
45
  }.merge(data)
@@ -50,27 +48,6 @@ module RVM
50
48
 
51
49
  end
52
50
 
53
- # returns the object that issued the VM call - so to say it's owner.
54
- #
55
- # If the current enviroment has no caller it tries it's 'oldenv' attrib
56
- # to see if that had a owner.
57
- def caller
58
- r = @data[:caller] || (@prev.is_a?(Enviroment) ? @prev.caller : nil)
59
- RVM::debug "Getting caller: #{r}"
60
- r
61
- end
62
-
63
- # returns the object that the code is run as, so it has the rights of
64
- # this object.
65
- #
66
- # If the current enviroment has no object it tries it's 'oldenv' attrib
67
- # to see if that had a object.
68
- def object
69
- r = @data[:self] || (@prev.is_a?(Enviroment) ? @prev.object : nil)
70
- RVM::debug "Getting object: #{r}"
71
- r
72
- end
73
-
74
51
  # returns a parameter that was passed to the call. For function calls
75
52
  # this is especially important, it beginns with 0.
76
53
  #
@@ -51,10 +51,10 @@ module RVM
51
51
  tree[:left][:params].each do |p|
52
52
  raise ArgumentError, "Bad ype for a function parameter: #{p[:type]} " if p[:type] != :ident
53
53
  body << Interpreter::Assignment.new(Interpreter.const(:string, p[:ident]), Interpreter::Parameter.new(Interpreter.const(:number, i)))
54
+ i += 1
54
55
  end
55
56
  body << compile(tree[:right])
56
57
  Interpreter::FunctionDefinition.new(Interpreter.const(:string, tree[:left][:op]), Interpreter.const(:block,body))
57
-
58
58
  else
59
59
  raise ArgumentError, "Bad name for a variable!"
60
60
  end
@@ -16,16 +16,20 @@ module RVM
16
16
  if t == '-'
17
17
  tokens << [t, :function]
18
18
  end
19
- elsif s.scan(/[a-z][a-z0-9]*/i)
19
+ elsif s.scan(/[_a-z][_a-z0-9]*/i)
20
20
  r = s.matched
21
21
  if s.scan(/\(/)
22
22
  tokens << [r, :function]
23
- paren_deepth += 1
23
+ if s.scan(/\)/)
24
+ tokens << [s.matched, :paren_close]
25
+ else
26
+ paren_deepth += 1
27
+ end
24
28
  else
25
29
  tokens << [r, :ident]
26
30
  state = :opperator
27
31
  end
28
- elsif s.scan(/[\d]+(\.\d+)?/i)
32
+ elsif s.scan(/((\d+(\.\d+)?)|(\.\d+))(e-?\d+)?/i)
29
33
  tokens << [s.matched, :number]
30
34
  state = :opperator
31
35
  elsif s.scan(/\(/)
@@ -3,17 +3,17 @@ module RVM
3
3
  module Math
4
4
  class Tree
5
5
  PRIORITIES = {
6
- ';' => -1,
7
- '=' => 0,
6
+ ';' => -100,
7
+ '=' => -50,
8
8
  '(' => 0,
9
- '+' => 1,
10
- '-' => 1,
11
- '*' => 2,
12
- '/' => 2,
13
- '^' => 3,
9
+ '+' => 10,
10
+ '-' => 10,
11
+ '*' => 20,
12
+ '/' => 20,
13
+ '^' => 30,
14
14
  }
15
15
  ASSOSICATIONS = {
16
- ';' => :right,
16
+ ';' => :right,
17
17
  '+' => :left,
18
18
  '-' => :left,
19
19
  '*' => :left,
@@ -36,7 +36,7 @@ module RVM
36
36
  dbgoutput << ')'
37
37
  dbgstack << fun
38
38
  when :function_sep
39
- while stack.last && (stack.last[:op] != '(')
39
+ while stack.last && (stack.last[:type] != :function)
40
40
  output << stack.pop
41
41
  dbgoutput << dbgstack.pop
42
42
  end
@@ -51,10 +51,6 @@ module RVM
51
51
  end
52
52
  stack.pop
53
53
  dbgstack.pop
54
- if stack.last && (stack.last[:type] == :function)
55
- output << stack.pop
56
- dbgoutput << dbgstack.pop
57
- end
58
54
  when :number
59
55
  output << {:type => :number, :number => token[0]}
60
56
  dbgoutput << token[0]
@@ -65,7 +61,7 @@ module RVM
65
61
  op = token[0]
66
62
  ass = ASSOSICATIONS[op]
67
63
  o1p = PRIORITIES[op]
68
- while stack.last &&
64
+ while stack.last && (stack.last[:type] != :function) &&
69
65
  (((ass == :left) && (o1p <= PRIORITIES[stack.last[:op]])) ||
70
66
  ((ass == :right) && (o1p < PRIORITIES[stack.last[:op]])))
71
67
  output << stack.pop
@@ -74,25 +70,30 @@ module RVM
74
70
  stack << {:type => :op, :op => op}
75
71
  dbgstack << op
76
72
  else
73
+ raise "Unknown element in parser tree: #{token.inspect}"
77
74
  end
75
+ p(dbgstack) if $DEBUG
76
+ p(dbgoutput) if $DEBUG
78
77
  end
79
78
  while not stack.empty?
80
79
  output << stack.pop
81
80
  end
82
- p output
83
81
  gen_tree output
84
82
  end
85
83
 
86
84
  private
87
85
  def Tree.gen_tree data
88
- p data
89
86
  item = data.pop
90
87
  case item[:type]
91
88
  when :number, :ident
92
89
  item
93
- when :op
90
+ when :op
94
91
  item[:right] = gen_tree(data)
95
- item[:left] = gen_tree(data)
92
+ if item[:op] == ';' and data.empty?
93
+ item = item[:right]
94
+ else
95
+ item[:left] = gen_tree(data)
96
+ end
96
97
  item
97
98
  when :function
98
99
  item[:params] = []
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/simple/tokenizer'
2
+ require File.dirname(__FILE__) + '/simple/tree'
3
+ require File.dirname(__FILE__) + '/simple/compiler'
4
+ require 'rvm/functions/math'
5
+ module RVM
6
+ module Languages
7
+ class SimpleLanguage < Language
8
+ include Simple
9
+ def compile text
10
+ Compiler.compile(Tree.generate(Tokenizer.tokenize(text)))
11
+ end
12
+ register_for :simple
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,73 @@
1
+ module RVM
2
+ module Languages
3
+ module Simple
4
+ class Compiler
5
+ include RVM::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 :paren
19
+ compile tree[:content]
20
+ when :number
21
+ Interpreter.const(:number, tree[:number])
22
+ when :function
23
+ params = tree[:params].map {|p| compile(p)}
24
+ case tree[:op]
25
+ when '-'
26
+ FunctionCall.new :neg, params
27
+ else
28
+ FunctionCall.new tree[:op], params
29
+ end
30
+ when :ident
31
+ Interpreter::Variable.new(Interpreter.const(:string, tree[:ident]))
32
+ when :op
33
+ case tree[:op]
34
+ when ';'
35
+ s = Interpreter::Sequence.new()
36
+ if (tree[:left][:type] == :op) and (tree[:left][:op] == ';')
37
+ s += compile(tree[:left])
38
+ else
39
+ s << compile(tree[:left])
40
+ end
41
+ if (tree[:right][:type] == :op) and (tree[:right][:op] == ';')
42
+ s += compile(tree[:right])
43
+ else
44
+ s << compile(tree[:right])
45
+ end
46
+ when '='
47
+ case tree[:left][:type]
48
+ when :ident
49
+ Interpreter::Assignment.new(Interpreter.const(:string, tree[:left][:ident]),compile(tree[:right]))
50
+ when :function
51
+ body = Interpreter::Sequence.new()
52
+ i = 0
53
+ tree[:left][:params].each do |p|
54
+ raise ArgumentError, "Bad ype for a function parameter: #{p[:type]} " if p[:type] != :ident
55
+ body << Interpreter::Assignment.new(Interpreter.const(:string, p[:ident]), Interpreter::Parameter.new(Interpreter.const(:number, i)))
56
+ i += 1
57
+ end
58
+ body << compile(tree[:right])
59
+ Interpreter::FunctionDefinition.new(Interpreter.const(:string, tree[:left][:op]), Interpreter.const(:block,body))
60
+
61
+ else
62
+ raise ArgumentError, "Bad name for a variable!"
63
+ end
64
+ else
65
+ FunctionCall.new(FUNCTION_MAP[tree[:op]], [compile(tree[:left]),compile(tree[:right])])
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,75 @@
1
+ require 'strscan'
2
+ module RVM
3
+ module Languages
4
+ module Simple
5
+ class Tokenizer
6
+
7
+ def Tokenizer.tokenize str
8
+ s = StringScanner.new str
9
+ tokens = []
10
+ state = :number
11
+ paren_deepth = 0
12
+ block_deepth = 0
13
+ while not s.eos?
14
+ s.skip(/\s*/)
15
+ if state == :number
16
+ if s.scan(/[+-]+/)
17
+ t = s.matched.gsub('+','').gsub('--','')
18
+ if t == '-'
19
+ tokens << [t, :function]
20
+ end
21
+ elsif s.scan(/[a-z][a-z0-9]*/i)
22
+ r = s.matched
23
+ if s.scan(/[(]/)
24
+ tokens << [r, :function]
25
+ paren_deepth += 1
26
+ else
27
+ tokens << [r, :ident]
28
+ state = :opperator
29
+ end
30
+ elsif s.scan(/[\d]+(\.\d+)?/i)
31
+ tokens << [s.matched, :number]
32
+ state = :opperator
33
+ elsif s.scan(/[(]/)
34
+ paren_deepth += 1
35
+ tokens << [s.matched, :paren_open]
36
+ elsif s.scan(/[{]/)
37
+ block_deepth += 1
38
+ tokens << [s.matched, :block_close]
39
+ else
40
+ raise "Unknown literal in term at positin #{s.pos}."
41
+ end
42
+ else
43
+ if s.scan(/[)]/)
44
+ paren_deepth -= 1
45
+ raise "Unmatched ')' parenthes at #{s.pos}" if paren_deepth < 0
46
+ tokens << [s.matched, :paren_close]
47
+ elsif s.scan(/[}]/)
48
+ block_deepth -= 1
49
+ raise "Unmatched '}' parenthes at #{s.pos}" if paren_deepth < 0
50
+ tokens << [s.matched, :block_close]
51
+ elsif s.scan(/,/)
52
+ tokens << [s.matched, :function_sep]
53
+ state = :number
54
+ elsif s.scan(/[*+\/^=-]/)
55
+ tokens << [s.matched, :opperator]
56
+ state = :number
57
+ elsif s.scan(/;/)
58
+ if paren_deepth == 0
59
+ tokens << [s.matched, :opperator]
60
+ state = :number
61
+ else
62
+ raise "Expression sepperator enclosed in parenthes at #{s.pos}"
63
+ end
64
+ else
65
+ raise "Unknown literal in term at positin #{s.pos}."
66
+ end
67
+ end
68
+ end
69
+ tokens
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,144 @@
1
+ module RVM
2
+ module Languages
3
+ module Simple
4
+ class Tree
5
+ PRIORITIES = {
6
+
7
+ ';' => -100,
8
+ '{' => -50,
9
+ '=' => -50,
10
+ '(' => 0,
11
+ '+' => 10,
12
+ '-' => 10,
13
+ '*' => 20,
14
+ '/' => 20,
15
+ '^' => 30,
16
+ }
17
+ ASSOSICATIONS = {
18
+ '{' => :left,
19
+ '+' => :left,
20
+ '-' => :left,
21
+ '*' => :left,
22
+ '/' => :left,
23
+ ';' => :right,
24
+ '^' => :right,
25
+ '=' => :right
26
+ }
27
+ PARENS = {
28
+ '(' => ')',
29
+ '{' => '}'
30
+ }
31
+ def Tree.generate tokens
32
+ output = []
33
+ dbgoutput = []
34
+ pstack = []
35
+ stack = []
36
+ dbgstack = []
37
+
38
+ while not tokens.empty?
39
+ token = tokens.shift
40
+ case token[1]
41
+ when :function
42
+ fun = token[0]
43
+ stack << {:type => :function, :op => fun}
44
+ output << {:type => :function_end}
45
+ dbgoutput << ')'
46
+ dbgstack << fun
47
+ when :function_sep
48
+ while stack.last && (stack.last[:type] != :function)
49
+ output << stack.pop
50
+ dbgoutput << dbgstack.pop
51
+ end
52
+ #Parenthetes
53
+ when :paren_open
54
+ op = token[0]
55
+ pstack << op
56
+ stack << {:type => :paren, :op => op}
57
+ dbgstack << op
58
+ when :paren_close
59
+ while stack.last && (stack.last[:op] != ')')
60
+ output << stack.pop
61
+ dbgoutput << dbgstack.pop
62
+ end
63
+ stack.pop
64
+ dbgstack.pop
65
+ if stack.last && (stack.last[:type] == :function)
66
+ output << stack.pop
67
+ dbgoutput << dbgstack.pop
68
+ end
69
+ #Blocks
70
+ when :block_open
71
+ op = token[0]
72
+ pstack << op
73
+ stack << {:type => :block, :op => op}
74
+ dbgstack << op
75
+ when :block_close
76
+ while stack.last && (stack.last[:op] != '}')
77
+ output << stack.pop
78
+ dbgoutput << dbgstack.pop
79
+ end
80
+ stack.pop
81
+ dbgstack.pop
82
+ #numbers
83
+ when :number
84
+ output << {:type => :number, :number => token[0]}
85
+ dbgoutput << token[0]
86
+ #idents
87
+ when :ident
88
+ output << {:type => :ident, :ident => token[0]}
89
+ dbgoutput << token[0]
90
+ # opperators
91
+ when :opperator
92
+ op = token[0]
93
+ ass = ASSOSICATIONS[op]
94
+ o1p = PRIORITIES[op]
95
+ while stack.last &&
96
+ (((ass == :left) && (o1p <= PRIORITIES[stack.last[:op]])) ||
97
+ ((ass == :right) && (o1p < PRIORITIES[stack.last[:op]])))
98
+ output << stack.pop
99
+ dbgoutput << dbgstack.pop
100
+ end
101
+ stack << {:type => :op, :op => op}
102
+ dbgstack << op
103
+ else
104
+ end
105
+ if $DEBUG
106
+ p dbgstack
107
+ p dbgoutput
108
+ end
109
+ end
110
+ while not stack.empty?
111
+ output << stack.pop
112
+ end
113
+ p output if $DEBUG
114
+ gen_tree output
115
+ end
116
+
117
+ private
118
+ def Tree.gen_tree data
119
+ p data if $DEBUG
120
+ item = data.pop
121
+ p item
122
+ case item[:type]
123
+ when :number, :ident
124
+ item
125
+ when :op
126
+ item[:right] = gen_tree(data)
127
+ item[:left] = gen_tree(data)
128
+ item
129
+ when :paren, :block
130
+ item[:content] = gen_tree(data)
131
+ item
132
+ when :function
133
+ item[:params] = []
134
+ while data.last && data.last[:type] != :function_end
135
+ item[:params] << gen_tree(data)
136
+ end
137
+ data.pop
138
+ item
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rVM
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Heinz N. Gies
8
- autorequire: ""
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-03-05 00:00:00 +01:00
12
+ date: 2008-03-06 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -73,6 +73,11 @@ files:
73
73
  - lib/rvm/languages/math/tokenizer.rb
74
74
  - lib/rvm/languages/math/tree.rb
75
75
  - lib/rvm/languages/math.rb
76
+ - lib/rvm/languages/simple
77
+ - lib/rvm/languages/simple/compiler.rb
78
+ - lib/rvm/languages/simple/tokenizer.rb
79
+ - lib/rvm/languages/simple/tree.rb
80
+ - lib/rvm/languages/simple.rb
76
81
  - lib/rvm/languages.rb
77
82
  - lib/rvm/plugin.rb
78
83
  - lib/rvm.rb