rVM 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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