f9824079d6
The decision on which is moving up to the ruby compiler, so it can at the same time emit the correct assignment form. Just another example of moving away from a language and to an intermediate form (that has no language equivalent)
144 lines
3.5 KiB
Ruby
144 lines
3.5 KiB
Ruby
module Vm
|
|
|
|
def self.ast_to_code statement
|
|
compiler = ToCode.new
|
|
compiler.process statement
|
|
end
|
|
|
|
class ToCode < AST::Processor
|
|
|
|
def handler_missing node
|
|
raise "No handler on_#{node.type}(node)"
|
|
end
|
|
|
|
def on_parameters statement
|
|
params = {}
|
|
statement.children.each do |param , type , name|
|
|
type , name = *param
|
|
params[name] = type
|
|
end
|
|
params
|
|
end
|
|
|
|
def on_while_statement statement
|
|
branch_type , condition , statements = *statement
|
|
w = Tree::WhileStatement.new()
|
|
w.branch_type = branch_type
|
|
w.condition = process(condition)
|
|
w.statements = process(statements)
|
|
w
|
|
end
|
|
|
|
def on_if_statement statement
|
|
branch_type , condition , if_true , if_false = *statement
|
|
w = Tree::IfStatement.new()
|
|
w.branch_type = branch_type
|
|
w.condition = process(condition)
|
|
w.if_true = process(if_true)
|
|
w.if_false = process(if_false)
|
|
w
|
|
end
|
|
|
|
def process_first code
|
|
raise "Too many children #{code.inspect}" if code.children.length != 1
|
|
process code.children.first
|
|
end
|
|
alias :on_conditional :process_first
|
|
alias :on_condition :process_first
|
|
alias :on_field :process_first
|
|
|
|
def on_statements statement
|
|
w = Statements.new()
|
|
return w unless statement.children
|
|
return w unless statement.children.first
|
|
w.statements = process_all(statement.children)
|
|
w
|
|
end
|
|
alias :on_true_statements :on_statements
|
|
alias :on_false_statements :on_statements
|
|
|
|
def on_return statement
|
|
w = Tree::ReturnStatement.new()
|
|
w.return_value = process(statement.children.first)
|
|
w
|
|
end
|
|
|
|
def on_operator_value statement
|
|
operator , left_e , right_e = *statement
|
|
w = Tree::OperatorExpression.new()
|
|
w.operator = operator
|
|
w.left_expression = process(left_e)
|
|
w.right_expression = process(right_e)
|
|
w
|
|
end
|
|
|
|
def on_field_access statement
|
|
receiver_ast , field_ast = *statement
|
|
w = Tree::FieldAccess.new()
|
|
w.receiver = process(receiver_ast)
|
|
w.field = process(field_ast)
|
|
w
|
|
end
|
|
|
|
def on_receiver expression
|
|
process expression.children.first
|
|
end
|
|
|
|
def on_call statement
|
|
name_s , arguments , receiver = *statement
|
|
w = Tree::CallSite.new()
|
|
w.name = name_s.children.first
|
|
w.arguments = process_all(arguments)
|
|
w.receiver = process(receiver)
|
|
w
|
|
end
|
|
|
|
def on_int expression
|
|
Tree::IntegerExpression.new(expression.children.first)
|
|
end
|
|
|
|
def on_true _expression
|
|
Tree::TrueExpression.new
|
|
end
|
|
|
|
def on_false _expression
|
|
Tree::FalseExpression.new
|
|
end
|
|
|
|
def on_nil _expression
|
|
Tree::NilExpression.new
|
|
end
|
|
|
|
def on_name statement
|
|
Tree::NameExpression.new(statement.children.first)
|
|
end
|
|
def on_string expression
|
|
Tree::StringExpression.new(expression.children.first)
|
|
end
|
|
|
|
def on_class_name expression
|
|
Tree::ClassExpression.new(expression.children.first)
|
|
end
|
|
|
|
def on_i_assignment statement
|
|
assignment_for( statement, Vm::Tree::IvarAssignment)
|
|
end
|
|
|
|
def on_a_assignment statement
|
|
assignment_for( statement, Vm::Tree::ArgAssignment)
|
|
end
|
|
|
|
def on_l_assignment( statement )
|
|
assignment_for( statement, Vm::Tree::LocalAssignment)
|
|
end
|
|
|
|
def assignment_for( statement , clazz)
|
|
name , value = *statement
|
|
p_name = process name
|
|
p_value = process(value)
|
|
clazz.new(p_name , p_value)
|
|
end
|
|
|
|
end
|
|
end
|