def type_to_s(type, name)
if type.is_a? Array
- raise "unsupported"
+ raise "unsupported array"
else
"#{type.to_s} #{name}"
end
lastexpr = nil
out.puts "{"
block.exprs.each do |e|
- lastexpr = emit(out, e)
+ lastexpr = emit(out, e) unless e.is_a? Parser::Ann
end
out.puts "}"
out.string
elsif type.is_a? Array
out.puts "#{type.last} (*#{name})(#{type[0..-2].join(",")}) = #{val};"
else
- raise "unsupported"
+ raise "unsupported var"
end
name
end
-
-# Ident = Struct.new(:loc, :type, :name)
-# Val = Struct.new(:loc, :type, :value)
-# Def = Struct.new(:loc, :type, :name, :value)
-# Func = Struct.new(:loc, :type, :args, :body, :freevars)
-# Call = Struct.new(:loc, :type, :func, :args)
-# IfExpr = Struct.new(:loc, :type, :cond, :br1, :br2)
-# Ann = Struct.new(:loc, :type, :expr)
-# Block = Struct.new(:loc, :type, :exprs)
-
-
def emit(out, e, var = nil)
val = nil
type = e.type
-# puts
if e.is_a? Parser::Val
val = emit_val(out, e)
elsif e.is_a? Parser::Def
val = emit_def(out, e)
type = e.value.type
-# elsif e.is_a? Parser::Call and e.func == :set!
-# var = e.args[0].name
-# type = e.args[1].type
-# val = emit(out, e.args[1])
elsif e.is_a? Parser::Call
val = emit_call(out, e)
-# elsif e.is_a? Parser::IfExpr
-# val = emit_ifexpr(out, e)
-# elsif e.is_a? Parser::Block
-# val = emit_block(out, e)
-# elsif e.is_a? Parser::Func
-# val = emit_func(out, e)
+ elsif e.is_a? Parser::IfExpr
+ val = emit_ifexpr(out, e)
+ elsif e.is_a? Parser::Block
+ val = emit_block(out, e)
+ elsif e.is_a? Parser::Func
+ val = emit_func(out, e)
+ elsif e.is_a? Parser::Ident
+ val = e.name
else
- raise "unsupported"
+ raise "unsupported expression"
end
var ||= tempvar()
emit_var(out, var, type, val)
when :float
e.value.to_s
when :string
- e.value.to_s
+ "STRINGLIT(#{e.value.to_s})"
else
raise "unknown value type: #{e.value.to_s}"
end
if e.func.is_a? String
emit_opcall(out, e)
else
- raise "unsupported"
+ args = e.args.map {|a| emit(out, a) }
+ "#{e.func.name}(#{args[0]})"
end
end
end
end
-# def emit_ifexpr(out, e)
-# cond = emit(out, e.cond)
-# var = tempvar()
-# emit_var(out, var, e.type)
-# out.puts "if (#{cond}) {"
-# out.puts "#{var} = #{emit(out, e.br1)};"
-# out.puts "} else {"
-# out.puts "#{var} = #{emit(out, e.br2)};"
-# out.puts "}"
-# var
-# end
-#
-# def emit_block(out, e)
-# var = tempvar()
-# emit_var(out, var, e.type)
-# out.puts "{"
-# exprs = e.exprs.map do |e|
-# emit(out, e)
-# end
-# out.puts "#{var} = #{exprs.last};"
-# out.puts "}"
-# var
-# end
-#
-# def emit_func(out, e)
-# newout = StringIO.new
-# var = mkfunc()
-# args = []
-# e.type[0..-2].each_with_index do |t,i|
-# args << type_to_s(t, e.args[i].name)
-# end
-# @protos.puts "#{e.type.last} #{var}(#{args.join(", ")});"
-# newout.puts "#{e.type.last} #{var}(#{args.join(", ")}) {"
-# exprs = e.body.exprs.map do |e|
-# emit(newout, e)
-# end
-# newout.puts "return #{exprs.last};" if (e.type.last != :void)
-# newout.puts "}\n\n"
-# @funcs.puts newout.string
-# var
-# end
+ def emit_ifexpr(out, e)
+ cond = emit(out, e.cond)
+ var = tempvar()
+ emit_var(out, var, e.type)
+ out.puts "if (#{cond}) {"
+ out.puts "#{var} = #{emit(out, e.br1)};"
+ out.puts "} else {"
+ out.puts "#{var} = #{emit(out, e.br2)};"
+ out.puts "}"
+ var
+ end
+
+ def emit_block(out, e)
+ var = tempvar()
+ emit_var(out, var, e.type)
+ out.puts "{"
+ exprs = e.exprs.map do |e|
+ emit(out, e) unless e.is_a? Parser::Ann
+ end.compact
+ out.puts "#{var} = #{exprs.last};"
+ out.puts "}"
+ var
+ end
+
+ def emit_func(out, e)
+ newout = StringIO.new
+ var = mkfunc()
+ args = []
+ e.type[0..-2].each_with_index do |t,i|
+ args << type_to_s(t, e.args[i].name)
+ end
+ @protos.puts "#{e.type.last} #{var}(#{args.join(", ")});"
+ newout.puts "#{e.type.last} #{var}(#{args.join(", ")}) {"
+ exprs = e.body.exprs.map do |e|
+ emit(newout, e) unless e.is_a? Parser::Ann
+ end
+ newout.puts "return #{exprs.last};" if (e.type.last != :void)
+ newout.puts "}\n\n"
+ @funcs.puts newout.string
+ if e.freevars.length > 0 then
+ "MKCLOSURE(#{var},#{e.freevars.length},#{e.freevars.join(", ")})"
+ else
+ var
+ end
+ end
end
STRING = <<-eos
123
-123.0 # Fix emit
+123.0
""
true
false
+
a = 123
b = (123 < 321)
-#a = 123
-#
-#foo : int -> int
-#foo = func(b){
-# d = 123
-# bar : int -> int
-# bar = func(c){
-# a + b + c
-# }
-# bar(1)
-# d
-# e = 1
-# e
-# d
-#}
+c = (if (123 < 1) 1 else 2)
+
+if (123 < 1) {
+ 123
+} else {
+ 321
+}
+
+somefunc : int -> int
+somefunc = func(a) {
+ 42
+}
+d = somefunc(42)
+
+foo : int -> int
+foo = func(b) {
+ d = 123
+ bar : int -> int
+ bar = func(c) {
+ a + b + c
+ }
+ bar(1)
+ d
+ e = 1
+ e
+ d
+}
eos
tree = Parser.new.parse_string(STRING)
TypeChecker.infer_block(SymTable.new, tree, false)
+
+puts <<-eos
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+typedef struct string {
+ size_t offset; \
+ size_t nelems;
+ char* elems;
+}* string;
+
+static inline void* MKCLOSURE(void* fn, int nfree, ...)
+{
+ return NULL;
+}
+
+#define STRINGLIT(str) \
+ &(struct string){ .offset = 0, .nelems = sizeof(str)-1, .elems = str }
+
+eos
puts Codegen.new(tree)