From: Michael D. Lowis Date: Thu, 15 Oct 2020 00:50:36 +0000 (-0400) Subject: almost have closure generation working X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=1febb210fdb3f0bf04d1e78fb84c79ac558832b4;p=proto%2Fsclpl-rb.git almost have closure generation working --- diff --git a/lib/dyn.rb b/lib/dyn.rb index 2c4bc79..b7f9699 100755 --- a/lib/dyn.rb +++ b/lib/dyn.rb @@ -707,7 +707,7 @@ class Codegen def type_to_s(type, name) if type.is_a? Array - raise "unsupported" + raise "unsupported array" else "#{type.to_s} #{name}" end @@ -719,7 +719,7 @@ class Codegen 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 @@ -732,45 +732,31 @@ class Codegen 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) @@ -786,7 +772,7 @@ class Codegen 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 @@ -801,7 +787,8 @@ class Codegen 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 @@ -814,72 +801,89 @@ class Codegen 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 @@ -889,5 +893,26 @@ eos tree = Parser.new.parse_string(STRING) TypeChecker.infer_block(SymTable.new, tree, false) + +puts <<-eos +#include +#include +#include + +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)