rubyx/lib/vm/nodes.rb

83 lines
1.9 KiB
Ruby
Raw Normal View History

2014-04-24 14:53:48 +02:00
module Vm
2014-04-24 16:38:06 +02:00
class Expression
# evey Expression has a eval function that returns a value
def eval
raise "abstract"
end
end
class NumberExpression < Expression
attr_reader :value
def initialize val
@value = val
end
2014-04-24 14:43:20 +02:00
def eval(context, builder)
builder.mov "r0" , value
2014-04-24 14:43:20 +02:00
end
end
2014-04-24 16:38:06 +02:00
class NameExpression < Expression
attr_reader :name
def initialize name
@name = name
end
2014-04-24 14:43:20 +02:00
def eval(context, builder)
param_names = context[:params] || []
position = param_names.index(name)
raise "Unknown parameter #{name}" unless position
builder.iload position
end
end
2014-04-24 16:38:06 +02:00
class FuncallExpression < Expression
attr_reader :name, :args
def initialize name, args
@name , @args = name , args
end
2014-04-24 14:43:20 +02:00
def eval(context, builder)
args.each { |a| a.eval(context, builder) }
types = [builder.int] * (args.length + 1)
builder.invokestatic builder.class_builder, name, types
end
end
2014-04-24 16:38:06 +02:00
class ConditionalExpression < Expression
attr_reader :cond, :if_true, :if_false
def initialize cond, if_true, if_false
@cond, @if_true, @if_false = cond, if_true, if_false
end
2014-04-24 14:43:20 +02:00
def eval(context, builder)
cond.eval context, builder
builder.ifeq :else
if_true.eval context, builder
builder.goto :endif
builder.label :else
if_false.eval context, builder
builder.label :endif
end
end
2014-04-24 16:38:06 +02:00
class FunctionExpression < Expression
attr_reader :name, :params, :body
def initialize name, params, body
@name, @params, @body = name, params, body
end
2014-04-24 14:43:20 +02:00
def eval(context, builder)
param_names = [params].flatten.map(&:name)
context[:params] = param_names
types = [builder.int] * (param_names.count + 1)
builder.public_static_method(self.name, [], *types) do |method|
self.body.eval(context, method)
method.ireturn
end
end
end
end