find_sym(@scopes[3..-1], name)
end
- def add_builtin(name, kind, type, value)
- @scopes[0][name] =
- Symbol.new(name, 0, kind, type, value)
- end
-
def find_sym(scopes, name)
scopes.reverse_each.detect do |scope|
- scope[name]
+ return scope[name]
end
end
find_sym(@scopes, name)
end
+ def add_builtin(name, kind, type, value)
+ @scopes[0][name] =
+ Symbol.new(name, 0, kind, type, value)
+ end
+ def add_sym(name, loc, kind, type, value)
+ @scopes.last[name] =
+ Symbol.new(name, loc, kind, type, value)
+ end
-# def add_sym(name, loc, kind, scope = :local, type = nil, value = nil)
-# self[name] = {
-# loc: loc,
-# kind: kind,
-# scope: scope,
-# type: type,
-# value: nil
-# }
-# end
-#
-# def set_type(name, type)
-# (self[name] || {})[:type] = type
-# end
+ def each(&block)
+ @scopes.last.each(&block)
+ end
end
def initialize(path = nil)
@syms = SymTable.new
- syms.add_sym(:void, 0, :type, :builtin, :void)
- syms.add_sym(:bool, 0, :type, :builtin, :bool)
- syms.add_sym(:int, 0, :type, :builtin, :int)
- syms.add_sym(:string, 0, :type, :builtin, :string)
- syms.add_sym(:float, 0, :type, :builtin, :float)
+ syms.add_builtin(:void, 0, :type, :void)
+ syms.add_builtin(:bool, 0, :type, :bool)
+ syms.add_builtin(:int, 0, :type, :int)
+ syms.add_builtin(:string, 0, :type, :string)
+ syms.add_builtin(:float, 0, :type, :float)
parse_file(path)
end
def toplevel
imports
exports
- @defs = {}
-# @syms = SymTable.new
-
while !matches(:eof)
mod_def = toplevel_defintion()
+ if mod_def.value.is_a? IR::Const
+ kind = :const
+ elsif mod_def.value.is_a? IR::Var
+ kind = :var
+ elsif mod_def.value.is_a? IR::Func
+ kind = :func
+# elsif mod_def.value.is_a? IR::Type
+# kind = :type
+ else
+ raise "invalid toplevel definition #{mod_def.value.class}"
+ end
-# kind = (case mod_def.value.class
-# when IR::Const.class
-# :const
-# when IR::Var.class
-# :var
-# when IR::Func.class
-# :func
-# else
-# raise "invalid toplevel definition #{mod_def.value.class}"
-# end)
-# @syms.add_sym(
-# mod_def.name.name,
-# 0,
-# kind,
-# :global,
-# nil,
-# mod_def.value)
-
- @defs[mod_def.name.name] = mod_def
+ syms.add_sym(
+ mod_def.name.name,
+ mod_def.name.loc,
+ kind,
+ mod_def.type,
+ mod_def.value
+ )
end
end
end
module Codegen
- def self.emit(v)
+ def self.emit(syms, v)
if v.is_a? IR::Return then
- emit_return(v)
+ emit_return(syms, v)
elsif v.is_a? IR::Const then
- emit_const(v)
+ emit_const(syms, v)
elsif v.is_a? IR::Op then
- emit_binop(v)
+ emit_binop(syms, v)
elsif v.is_a? IR::Var then
- emit_var(v)
+ emit_var(syms, v)
elsif v.is_a? IR::Call then
- emit_call(v)
+ emit_call(syms, v)
else
raise "code emitting of #{v.class} not implemented"
end
end
- def self.emit_return(v)
- emit(v.value)
+ def self.emit_return(syms, v)
+ emit(syms, v.value)
puts " retwv"
end
- def self.emit_const(v)
+ def self.emit_const(syms, v)
if v.value.is_a? Integer
puts " int #{v.value}"
end
end
- def self.emit_binop(v)
- emit(v.left)
- emit(v.right)
+ def self.emit_binop(syms, v)
+ emit(syms, v.left)
+ emit(syms, v.right)
case v.op
when "+"
puts " addi"
end
end
- def self.emit_var(v)
- puts " #{v.name}"
+ def self.emit_var(syms, v)
+ sym = syms[v.name]
+ if sym.kind == :param
+ puts " get_param #{sym.value}"
+ end
end
- def self.emit_call(v)
+ def self.emit_call(syms, v)
v.args.reverse.each do |arg|
- emit(arg)
+ emit(syms, arg)
end
# TODO: handle args/locals/globals
if v.func.is_a? IR::Var
- puts " call #{v.func.name}"
+ puts " fcall #{v.func.name.inspect}"
else
- emit(v.func)
- emit " callv"
+ emit(syms, v.func)
+ puts " fcallv"
end
end
end
-#$parser = Parser.new("cerise.m")
-#$parser.defs.each do |name, val|
-# puts "func #{name.to_sym.inspect}, #{val.value.args.length} do"
-# val.value.body.each do |stmnt|
-# Codegen.emit(stmnt)
-# end
-# puts "end\n\n"
-#end
-
-syms = SymTable.new
-syms.add_builtin(:foo, :var, nil, nil)
-syms.add_sym(:foo, :var, nil, nil)
-#syms.add_param(:foo, :var, nil, nil)
-#syms.add_param(:foo, :var, nil, nil)
-# def add_builtin(name, kind, type, value)
-
-pp syms
+$parser = Parser.new("cerise.m")
+$parser.syms.each do |name, val|
+ $parser.syms.open_scope
+ puts "func #{name.to_sym.inspect}, #{val.value.args.length} do"
+ val.value.args.each_with_index do |name, idx|
+ $parser.syms.add_sym(
+ name.name, name.loc, :param, name.type, idx)
+ end
+ val.value.body.each do |stmnt|
+ Codegen.emit($parser.syms, stmnt)
+ end
+ puts "end\n\n"
+ $parser.syms.close_scope
+end