"_string"
elsif type.is_a? Symbol
type
+ elsif type.is_a? IR::Var
+ "#{type.module || @parser.module}_#{type.name}"
elsif type.form == :array
"_array"
elsif type.form == :hash
end
end
+ def declare_sym(sym)
+ if sym.kind == :type
+ type = sym.value
+ if type.form == :alias
+ puts "typedef #{type_to_s(type.base)} #{symname(sym)};"
+ elsif type.form == :record
+ puts "typedef struct #{symname(sym)} #{symname(sym)};"
+ else
+ raise "unimplemented"
+ end
+ elsif sym.kind == :func
+ args = sym.type[0..-2].map{|e| type_to_s(e) }.join(", ")
+ puts "#{type_to_s(sym.type.last)} #{symname(sym)}(#{args});"
+ else
+ puts "// #{sym.name}"
+ end
+ end
+
+ def define_sym(sym)
+ if sym.kind == :type
+ define_type(sym)
+ elsif sym.kind == :func
+ define_func(sym)
+ else
+ puts "// #{sym.name}"
+ end
+ end
+
+ def define_type(sym)
+ type = sym.value
+ if type.form == :record
+ puts "struct #{symname(sym)} {"
+ if (type.base)
+ puts " #{type_to_s(type.base)} _base;"
+ end
+ type.fields.each do |k,v|
+ puts " #{type_to_s(v)} #{k};"
+ end
+ puts "};"
+ end
+ end
+
+ def define_func(sym)
+ args = sym.value.args.map{|e| "#{type_to_s(e.type)} #{e.name}" }.join(", ")
+ puts "#{type_to_s(sym.type.last)} #{symname(sym)}(#{args}) {"
+ @syms.open_scope
+ @locals = sym.value.locals
+ sym.value.args.each_with_index do |name, idx|
+ @syms.add_sym(name.name, name.loc, :param, name.type, idx)
+ end
+ sym.value.body.each do |stmnt|
+ emit(stmnt)
+ end
+ puts "}\n\n"
+ @syms.close_scope
+ end
+
+
def output(outpath)
@output = File.open(outpath, "wb")
puts "#include <runtime.h>\n\n"
- (@parser.imported_modules || {}).values.each do |mod|
+
+ # output imported symbol declarations
+ imported_mods = (@parser.imported_modules || {}).values
+ imported_mods.each do |mod|
@syms[mod[:name]].type.exports.each do |name, val|
- args = val.type[0..-2].map{|e| type_to_s(e) }.join(", ")
- puts "#{type_to_s(val.type.last)} #{symname(val)}(#{args});"
+ declare_sym(val)
end
puts ""
end
- @syms.each do |name, val|
- args = val.value.args.map{|e| "#{type_to_s(e.type)} #{e.name}" }.join(", ")
- puts "#{type_to_s(val.type.last)} #{symname(val)}(#{args});"
- end
- puts ""
+# # output imported record declarations
+# imported_mods.each do |mod|
+# @syms[mod[:name]].type.exports.each do |name, val|
+# define_sym(val) if val.kind == :type
+# end
+# puts ""
+# end
- @syms.each do |name, val|
- args = val.value.args.map{|e| "#{type_to_s(e.type)} #{e.name}" }.join(", ")
- puts "#{type_to_s(val.type.last)} #{symname(val)}(#{args}) {"
- @syms.open_scope
- @locals = val.value.locals
- val.value.args.each_with_index do |name, idx|
- @syms.add_sym(name.name, name.loc, :param, name.type, idx)
- end
- val.value.body.each do |stmnt|
- emit(stmnt)
- end
- puts "}\n\n"
- @syms.close_scope
- end
+ # output this modules symbol declarations
+ @syms.each { |name, val| declare_sym(val) }
+ puts ""
+ @syms.each {|name, val| define_sym(val) }
@output.close
end
syms = SymTable.new
syms.module_name = @module
@syms.globals.each do |k,v|
- syms.add_sym(k, v.loc, v.kind, v.type, nil)
+ syms.add_sym(k, v.loc, v.kind, v.type, (v.kind == :func ? nil : v.value))
end
syms
end
kind = :var
elsif mod_def.value.is_a? IR::Func
kind = :func
-# elsif mod_def.value.is_a? IR::Type
-# kind = :type
+ elsif mod_def.value.is_a? Value::Type
+ kind = :type
else
raise "invalid toplevel definition #{mod_def.value.class}"
end
ident = identifier()
if matches("(") then
val = function_definition(ident)
+ elsif accept(:is)
+ val = type_definition(ident)
elsif matches("=") then
val = constant_definition(ident)
else
defs = []
if accept(":")
func.type = type_specifier()
+ else
+ func.type = :void
end
expect("{")
while matches(:def)
func
end
+ def type_definition(name)
+ if accept(:record)
+ base_type = nil
+ if accept("(")
+ base_type = identifier()
+ expect(")")
+ end
+ type = Value::Type.new(:record, {}, base_type, 0)
+ expect("{")
+ while not matches("}")
+ name = expect(:ident).text.to_sym
+ if type.fields[name]
+ error("field #{name} already defined in record")
+ end
+ expect("=")
+ type.fields[name] = type_specifier()
+ end
+ # parse fields here
+ expect("}")
+ else
+ type = type_specifier()
+ type = Value::Type.new(:alias, nil, type, 0)
+ end
+ type
+ end
+
def constant_definition(name)
error("constant definitions not yet supported")
end
expect("(")
while !matches(")")
id = identifier()
- if accept(":")
- id.type = type_specifier()
- end
+ expect(":")
+ id.type = type_specifier()
args << id
expect(",") if !matches(")")
end
end
def type_specifier()
- expect(:ident).text.to_sym
+ if accept("[")
+ base_type = type_specifier()
+ type = Value::Type.new(:array, nil, base_type, 0)
+ expect("]")
+ else
+ type = expect(:ident).text.to_sym
+ end
+ type
end
-
##
# Statements
##