Prepare support for non-source code function.

This commit is contained in:
Danila Fedorin 2018-07-27 23:24:37 -07:00
parent 774ab2f92e
commit c04997ad17
2 changed files with 54 additions and 13 deletions

View File

@ -46,14 +46,16 @@ module Chalk
return table return table
end end
private def create_code(trees, table) private def create_code(tree : TreeFunction, table)
code = {} of String => Array(Instruction)
trees.each do |tree|
tree = tree.as(TreeFunction)
generator = CodeGenerator.new table, tree generator = CodeGenerator.new table, tree
@logger.debug("Generating code for #{tree.name}") @logger.debug("Generating code for #{tree.name}")
instructions = generator.generate! return generator.generate!
code[tree.name] = instructions end
private def create_code(trees : Array(TreeFunction), table)
code = {} of String => Array(Instruction)
trees.each do |tree|
code[tree.name] = create_code(tree, table)
end end
return code return code
end end
@ -87,20 +89,46 @@ module Chalk
end end
end end
private def collect_calls(table)
open = Set(String).new
done = Set(String).new
open << "main"
while !open.empty?
first = open.first
open.delete first
done << first
entry = table[first]?
raise "Unknown function" unless entry && entry.is_a?(FunctionEntry)
next unless entry.function.is_a?(TreeFunction)
visitor = CallVisitor.new
entry.function.accept(visitor)
open.concat(visitor.calls - done)
end
return done
end
private def run_binary private def run_binary
all_instructions = [] of Instruction all_instructions = [] of Instruction
trees = create_trees(@config.file) trees = create_trees(@config.file)
table = create_table(trees) table = create_table(trees)
code = create_code(trees, table) names = collect_calls(table)
all_instructions.concat code["main"] names.delete "main"
table["main"]?.as(FunctionEntry).addr = 0
main_entry = table["main"]?.as(FunctionEntry)
all_instructions.concat create_code(main_entry.function, table)
main_entry.addr = 0
all_instructions << JumpRelativeInstruction.new 0 all_instructions << JumpRelativeInstruction.new 0
code.delete "main"
code.each do |key, value| names.each do |name|
table[key]?.as(FunctionEntry).addr = all_instructions.size entry = table[name]?.as(FunctionEntry)
all_instructions.concat(value) entry.addr = all_instructions.size
all_instructions.concat create_code(entry.function, table)
all_instructions << ReturnInstruction.new all_instructions << ReturnInstruction.new
end end
file = File.open("out.ch8", "w") file = File.open("out.ch8", "w")
generate_binary(table, all_instructions, file) generate_binary(table, all_instructions, file)
file.close file.close

View File

@ -0,0 +1,13 @@
module Chalk
class CallVisitor < Visitor
property calls : Set(String)
def initialize
@calls = Set(String).new
end
def visit(t : TreeCall)
@calls << t.name
end
end
end