]> git.mdlowis.com Git - proto/sclpl-rb.git/commitdiff
almost have closure generation working
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 15 Oct 2020 00:50:36 +0000 (20:50 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 15 Oct 2020 00:50:36 +0000 (20:50 -0400)
lib/dyn.rb

index 2c4bc799a4fcfed3c6478d406dad020e3e23e683..b7f9699fe586c7bb58623f02d440b61de193a641 100755 (executable)
@@ -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 <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)