Prepare support for non-source code function.
This commit is contained in:
parent
774ab2f92e
commit
c04997ad17
|
@ -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
|
||||||
|
|
13
src/chalk/function_finder.cr
Normal file
13
src/chalk/function_finder.cr
Normal 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
|
Loading…
Reference in New Issue
Block a user