move the code insertion functionality up to function. makes more sense. block still carries code though
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
Reference in New Issue
Block a user