Split symbol table into have a separate hash for each entry type.

This commit is contained in:
Danila Fedorin 2018-08-05 20:32:10 -07:00
parent 61fb44bbce
commit 89709fef97
5 changed files with 36 additions and 43 deletions

View File

@ -19,7 +19,7 @@ module Chalk
@table = Table.new table @table = Table.new table
@function.params.each do |param| @function.params.each do |param|
@table[param] = VarEntry.new @registers @table.set_var param, VarEntry.new @registers
@registers += 1 @registers += 1
end end
end end
@ -74,9 +74,8 @@ module Chalk
def generate!(tree, table, target, free) def generate!(tree, table, target, free)
case tree case tree
when Trees::TreeId when Trees::TreeId
entry = table[tree.id]? entry = table.get_var? tree.id
raise "Unknown variable" unless entry && raise "Unknown variable" unless entry
entry.is_a?(VarEntry)
loadr target, entry.register loadr target, entry.register
when Trees::TreeLit when Trees::TreeLit
load target, tree.lit load target, tree.lit
@ -85,7 +84,7 @@ module Chalk
generate! tree.right, table, free, free + 1 generate! tree.right, table, free, free + 1
opr tree.op, target, free opr tree.op, target, free
when Trees::TreeCall when Trees::TreeCall
entry = table[tree.name]?.not_nil! entry = table.get_function?(tree.name).not_nil!
raise "Unknown function" unless entry.is_a?(FunctionEntry) raise "Unknown function" unless entry.is_a?(FunctionEntry)
generate! tree, entry.function, table, target, free generate! tree, entry.function, table, target, free
when Trees::TreeBlock when Trees::TreeBlock
@ -94,19 +93,17 @@ module Chalk
free += generate! child, table, THROWAWAY_REG, free free += generate! child, table, THROWAWAY_REG, free
end end
when Trees::TreeVar when Trees::TreeVar
entry = table[tree.name]? entry = table.get_var? tree.name
if entry == nil if entry == nil
entry = VarEntry.new free entry = VarEntry.new free
free += 1 free += 1
table[tree.name] = entry table.set_var tree.name, entry
end end
raise "Unknown variable" unless entry.is_a?(VarEntry) generate! tree.expr, table, entry.as(VarEntry).register, free
generate! tree.expr, table, entry.register, free
return 1 return 1
when Trees::TreeAssign when Trees::TreeAssign
entry = table[tree.name]? entry = table.get_var? tree.name
raise "Unknown variable" unless entry && raise "Unknown variable" unless entry
entry.is_a?(VarEntry)
generate! tree.expr, table, entry.register, free generate! tree.expr, table, entry.register, free
when Trees::TreeIf when Trees::TreeIf
generate! tree.condition, table, free, free + 1 generate! tree.condition, table, free, free + 1

View File

@ -49,15 +49,15 @@ module Chalk
@logger.debug("Creating symbol table") @logger.debug("Creating symbol table")
trees.each do |tree| trees.each do |tree|
@logger.debug("Storing #{tree.name} in symbol table") @logger.debug("Storing #{tree.name} in symbol table")
table[tree.name] = FunctionEntry.new tree table.set_function tree.name, FunctionEntry.new tree
end end
@logger.debug("Done creating symbol table") @logger.debug("Done creating symbol table")
table["get_key"] = FunctionEntry.new Builtin::InlineAwaitKeyFunction.new table.set_function "get_key", FunctionEntry.new Builtin::InlineAwaitKeyFunction.new
table["set_delay"] = FunctionEntry.new Builtin::InlineSetDelayFunction.new table.set_function "set_delay", FunctionEntry.new Builtin::InlineSetDelayFunction.new
table["get_delay"] = FunctionEntry.new Builtin::InlineGetDelayFunction.new table.set_function "get_delay", FunctionEntry.new Builtin::InlineGetDelayFunction.new
table["set_sound"] = FunctionEntry.new Builtin::InlineSetSoundFunction.new table.set_function "set_sound", FunctionEntry.new Builtin::InlineSetSoundFunction.new
table["draw_number"] = FunctionEntry.new Builtin::InlineDrawNumberFunction.new table.set_function "draw_number", FunctionEntry.new Builtin::InlineDrawNumberFunction.new
return table return table
end end
@ -143,8 +143,8 @@ module Chalk
first = open.first first = open.first
open.delete first open.delete first
entry = table[first]? entry = table.get_function? first
raise "Unknown function" unless entry && entry.is_a?(FunctionEntry) raise "Unknown function" unless entry
function = entry.function function = entry.function
next if function.is_a?(Builtin::InlineFunction) next if function.is_a?(Builtin::InlineFunction)
done << first done << first
@ -166,13 +166,13 @@ module Chalk
names = collect_calls(table) names = collect_calls(table)
names.delete "main" names.delete "main"
main_entry = table["main"]?.as(FunctionEntry) main_entry = table.get_function?("main").not_nil!
all_instructions.concat create_code(main_entry.function.as(Trees::TreeFunction), all_instructions.concat create_code(main_entry.function.as(Trees::TreeFunction),
table, Ir::JumpRelativeInstruction.new 0) table, Ir::JumpRelativeInstruction.new 0)
main_entry.addr = 0 main_entry.addr = 0
names.each do |name| names.each do |name|
entry = table[name]?.as(FunctionEntry) entry = table.get_function?(name).not_nil!
entry.addr = all_instructions.size entry.addr = all_instructions.size
function = entry.function function = entry.function
raise "Trying to compile inlined function" if function.is_a?(Builtin::InlineFunction) raise "Trying to compile inlined function" if function.is_a?(Builtin::InlineFunction)

View File

@ -282,7 +282,7 @@ module Chalk
end end
def to_bin(table, stack, index) def to_bin(table, stack, index)
return 0x2000 | (table[name]?.as(Compiler::FunctionEntry).addr * 2 + 0x200) return 0x2000 | (table.get_function?(name).as(Compiler::FunctionEntry).addr * 2 + 0x200)
end end
end end

View File

@ -1,11 +1,7 @@
module Chalk module Chalk
module Compiler module Compiler
# An entry in the symbol table.
class Entry
end
# An entry that represents a function in the symbol table. # An entry that represents a function in the symbol table.
class FunctionEntry < Entry class FunctionEntry
# Gets the function stored in this entry. # Gets the function stored in this entry.
getter function getter function
# Gets the address in code of this function. # Gets the address in code of this function.
@ -23,7 +19,7 @@ module Chalk
end end
# An entry that represents a variable in the symbol table. # An entry that represents a variable in the symbol table.
class VarEntry < Entry class VarEntry
# Gets the register occupied by the variable # Gets the register occupied by the variable
# in this entry. # in this entry.
getter register getter register
@ -42,22 +38,22 @@ module Chalk
getter parent getter parent
def initialize(@parent : Table? = nil) def initialize(@parent : Table? = nil)
@data = {} of String => Entry @functions = {} of String => FunctionEntry
@vars = {} of String => VarEntry
end end
# Looks up the given *key* first in this table, macro table_functions(name)
# then in its parent, continuing recursively. def get_{{name}}?(key)
def []?(key) @{{name}}s[key]? || @parent.try &.get_{{name}}?(key)
if entry = @data[key]?
return entry
end
return @parent.try &.[key]?
end end
# Stores an *entry* under the given *key* into this table. def set_{{name}}(key, value)
def []=(key, entry) @{{name}}s[key] = value
@data[key] = entry
end end
end
table_functions function
table_functions var
def to_s(io) def to_s(io)
@parent.try &.to_s(io) @parent.try &.to_s(io)

View File

@ -12,8 +12,8 @@ module Chalk
end end
def reduce(t : TreeCall, children) def reduce(t : TreeCall, children)
entry = @table[t.name]? entry = @table.get_function? t.name
raise "Unknwon function" unless entry && entry.is_a?(Compiler::FunctionEntry) raise "Unknwon function" unless entry
type = entry.function.type type = entry.function.type
raise "Invalid parameters" if type.param_types.size != children.size raise "Invalid parameters" if type.param_types.size != children.size
children.each_with_index do |child, i| children.each_with_index do |child, i|