move the code insertion functionality up to function. makes more sense. block still carries code though

This commit is contained in:
Torsten Ruger
2014-06-10 23:57:56 +03:00
parent e9fc8ac6aa
commit e9519d4f05
15 changed files with 130 additions and 115 deletions

View File

@ -4,7 +4,7 @@ module Ast
class IntegerExpression < Expression
# attr_reader :value
def compile context , into
def compile context
Vm::IntegerConstant.new value
end
end
@ -13,7 +13,7 @@ module Ast
# attr_reader :name
# compiling a variable resolves it. if it wasn't defined, raise an exception
def compile context , into
def compile context
raise "Undefined variable #{name}, defined locals #{context.locals.keys.join('-')}" unless context.locals.has_key?(name)
context.locals[name]
end
@ -21,7 +21,7 @@ module Ast
class ModuleName < NameExpression
def compile context , into
def compile context
clazz = context.object_space.get_or_create_class name
raise "uups #{clazz}.#{name}" unless clazz
#class qualifier, means call from metaclass
@ -34,7 +34,7 @@ module Ast
class StringExpression < Expression
# attr_reader :string
def compile context , into
def compile context
value = Vm::StringConstant.new(string)
context.object_space.add_object value
value

View File

@ -4,14 +4,15 @@ module Ast
class CallSiteExpression < Expression
# attr_reader :name, :args , :receiver
@@counter = 0
def compile context , into
params = args.collect{ |a| a.compile(context, into) }
def compile context
into = context.function
params = args.collect{ |a| a.compile(context) }
if receiver.is_a?(NameExpression) and (receiver.name == :self)
function = context.current_class.get_or_create_function(name)
value_receiver = Vm::Integer.new(Vm::RegisterMachine.instance.receiver_register)
else
value_receiver = receiver.compile(context , into)
value_receiver = receiver.compile(context)
function = context.current_class.get_or_create_function(name)
end
# this lot below should go, since the compile should handle all
@ -25,9 +26,10 @@ module Ast
into.push([]) unless current_function.nil?
call.load_args into
call.do_call into
after = into.new_block("#{into.name}_call#{@@counter+=1}")
after = into.new_block("call#{@@counter+=1}")
into.insert_at after
after.pop([]) unless current_function.nil?
into.pop([]) unless current_function.nil?
puts "compile call #{function.return_type}"
function.return_type
end

View File

@ -1,8 +1,7 @@
module Ast
class FunctionExpression < Expression
# attr_reader :name, :params, :body , :receiver
def compile context , into
raise "function does not compile into anything #{self}" if into
def compile context
args = []
locals = {}
params.each_with_index do |param , index|
@ -33,7 +32,7 @@ module Ast
last_compiled = nil
body.each do |b|
puts "compiling in function #{b}"
last_compiled = b.compile(context , into)
last_compiled = b.compile(context)
raise "alarm #{last_compiled} \n #{b}" unless last_compiled.is_a? Vm::Word
end

View File

@ -1,32 +1,36 @@
module Ast
class IfExpression < Expression
# attr_reader :cond, :if_true, :if_false
def compile context , into
def compile context
f = context.function
# to execute the logic as the if states it, the blocks are the other way around
# so we can the jump over the else if true ,and the else joins unconditionally after the true_block
false_block = into.new_block "#{into.name}_if_false"
true_block = false_block.new_block "#{into.name}_if_true"
merge_block = true_block.new_block "#{into.name}_if_merge"
false_block = f.new_block "if_false"
true_block = f.new_block "if_true"
merge_block = f.new_block "if_merge"
puts "compiling if condition #{cond}"
cond_val = cond.compile(context , into)
into.b true_block , condition_code: cond_val.operator
into.branch = true_block
cond_val = cond.compile(context)
f.b true_block , condition_code: cond_val.operator
f.insertion_point.branch = true_block
f.insert_at false_block
if_false.each do |part|
puts "compiling in if false #{part}"
last = part.compile(context , false_block )
last = part.compile(context )
end
false_block.b merge_block
f.b merge_block
f.insertion_point.branch = false_block
f.insert_at true_block
last = nil
if_true.each do |part|
puts "compiling in if true #{part}"
last = part.compile(context , true_block )
last = part.compile(context )
end
puts "compiled if: end"
into.insert_at merge_block
f.insert_at merge_block
return last
end

View File

@ -1,7 +1,7 @@
module Ast
class ModuleExpression < Expression
# attr_reader :name ,:expressions
def compile context , into
def compile context
clazz = context.object_space.get_or_create_class name
puts "Created class #{clazz.name.inspect}"
context.current_class = clazz
@ -10,7 +10,7 @@ module Ast
# if not, execute it, but that does means we should be in crystal (executable), not ruby. ie throw an error for now
raise "only functions for now #{expression.inspect}" unless expression.is_a? Ast::FunctionExpression
puts "compiling expression #{expression}"
expression_value = expression.compile(context , nil )
expression_value = expression.compile(context )
#puts "compiled expression #{expression_value.inspect}"
end

View File

@ -1,9 +1,10 @@
module Ast
class OperatorExpression < Expression
# attr_reader :operator, :left, :right
def compile context , into
def compile context
into = context.function
puts "compiling operator #{to_s}"
r_val = right.compile(context , into)
r_val = right.compile(context)
#puts "compiled right #{r_val.inspect}"
if operator == "=" # assignment, value based
raise "Can only assign variables, not #{left}" unless left.is_a?(NameExpression)
@ -18,7 +19,7 @@ module Ast
return l_val
end
l_val = left.compile(context , into)
l_val = left.compile(context)
case operator
when ">"
code = l_val.greater_than into , r_val

View File

@ -1,9 +1,9 @@
module Ast
class ReturnExpression < Expression
# attr_reader :expression
def compile context , into
def compile context
puts "compiling return expression #{expression}, now return in return_regsiter"
expression_value = expression.compile(context , into)
expression_value = expression.compile(context)
# copied from function expression: TODO make function
return_reg = Vm::Integer.new(Vm::RegisterMachine.instance.return_register)

View File

@ -1,18 +1,21 @@
module Ast
class WhileExpression < Expression
# attr_reader :condition, :body
def compile context , into
while_block = into.new_block "#{into.name}_while"
ret = while_block.new_block "#{into.name}_return"
def compile context
into = context.function
while_block = into.new_block "while"
ret = while_block.new_block "return"
into.insert_at while_block
puts "compiling while condition #{condition}"
cond_val = condition.compile(context , while_block)
cond_val = condition.compile(context)
while_block.b ret , condition_code: cond_val.not_operator
while_block.branch = ret
last = nil
body.each do |part|
puts "compiling in while #{part}"
last = part.compile(context , while_block )
last = part.compile(context)
end
while_block.b while_block
puts "compile while end"