]> git.mdlowis.com Git - proto/aas.git/commitdiff
moved definitions to be teh first statements in a function
authorMichael D. Lowis <mike@mdlowis.com>
Mon, 27 Nov 2023 03:51:24 +0000 (22:51 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Mon, 27 Nov 2023 03:51:24 +0000 (22:51 -0500)
cerise.rb

index bb3cdf8017e745f7873998b42a6a7b7b81dbe91d..a18c280763513b9e272b805f9910b5ad5df411b5 100755 (executable)
--- a/cerise.rb
+++ b/cerise.rb
@@ -146,7 +146,7 @@ end
 
 
 module IR
-  Func   = Struct.new(:loc, :type, :args, :body)
+  Func   = Struct.new(:loc, :type, :args, :locals, :body)
   Return = Struct.new(:loc, :type, :value)
   Const  = Struct.new(:loc, :type, :value)
   Var    = Struct.new(:loc, :type, :name)
@@ -634,8 +634,12 @@ class Parser
 
   def function_definition(name)
     args = function_arglist()
-    func = IR::Func.new(name.loc, nil, args, [])
+    func = IR::Func.new(name.loc, nil, args, [], [])
     expect("{")
+    while matches(:def)
+      local = variable_definition()
+      func.locals << local.name.name
+    end
     stmts = statement_list(["}", :return])
     stmts << return_statement
     func.body = stmts
@@ -689,9 +693,7 @@ class Parser
     # if statement
     # expression
 
-    if matches(:def)
-      variable_definition()
-    elsif matches(:set)
+    if matches(:set)
       variable_assignment()
     elsif matches(:if)
       if_statement()
@@ -849,49 +851,53 @@ class Parser
 end
 
 module Codegen
-  @@label_count = 0
+  State = Struct.new(:label, :locals, :syms)
+
+  def self.init(syms)
+    State.new(0, [], syms)
+  end
 
-  def self.genlabel()
-   label = @@label_count
-   @@label_count = @@label_count + 1
+  def self.genlabel(state)
+   label = state.label
+   state.label = state.label + 1
   end
 
-  def self.emit(syms, v)
+  def self.emit(state, v)
     if v.is_a? IR::Return then
-      emit_return(syms, v)
+      emit_return(state, v)
     elsif v.is_a? IR::Const then
-      emit_const(syms, v)
+      emit_const(state, v)
     elsif v.is_a? IR::Op then
-      emit_binop(syms, v)
+      emit_binop(state, v)
     elsif v.is_a? IR::Var then
-      emit_var(syms, v)
+      emit_var(state, v)
     elsif v.is_a? IR::Call then
-      emit_call(syms, v)
+      emit_call(state, v)
     elsif v.is_a? IR::Def then
-      emit_def(syms, v)
+      emit_def(state, v)
     elsif v.is_a? IR::Set then
-      emit_set(syms, v)
+      emit_set(state, v)
     elsif v.is_a? IR::If then
-      emit_if(syms, v)
+      emit_if(state, v)
     else
       raise "code emitting of #{v.class} not implemented"
     end
   end
 
-  def self.emit_return(syms, v)
-    emit(syms, v.value)
+  def self.emit_return(state, v)
+    emit(state, v.value)
     puts "    retwv"
   end
 
-  def self.emit_const(syms, v)
+  def self.emit_const(state, v)
     if v.value.is_a? Integer
       puts "    int #{v.value}"
     end
   end
 
-  def self.emit_binop(syms, v)
-    emit(syms, v.left)
-    emit(syms, v.right)
+  def self.emit_binop(state, v)
+    emit(state, v.left)
+    emit(state, v.right)
     case v.op
     when "+"
       puts "    addi"
@@ -920,8 +926,8 @@ module Codegen
     end
   end
 
-  def self.emit_var(syms, v)
-    sym = syms[v.name]
+  def self.emit_var(state, v)
+    sym = state.syms[v.name]
     if sym
       if sym.kind == :param
         puts "    get_param #{sym.value}"
@@ -933,60 +939,62 @@ module Codegen
     end
   end
 
-  def self.emit_call(syms, v)
+  def self.emit_call(state, v)
     v.args.reverse.each do |arg|
-      emit(syms, arg)
+      emit(state, arg)
     end
     # TODO: handle args/locals/globals
     if v.func.is_a? IR::Var
       puts "    fcall #{v.func.name.inspect}"
     else
-      emit(syms, v.func)
+      emit(state, v.func)
       puts "    fcallv"
     end
   end
 
-  def self.emit_def(syms, v)
-    syms.add_sym(
+  def self.emit_def(state, v)
+    state.add_sym(
         v.name.name, v.loc, :local, v.type, v.value)
-    emit(syms, v.value)
+    emit(state, v.value)
     puts "    set_local :#{v.name.name}"
   end
 
-  def self.emit_set(syms, v)
+  def self.emit_set(state, v)
     puts "    set_local :#{v.name.name}"
   end
 
-  def self.emit_if(syms, v)
-    lbl1 = genlabel()
-    lbl2 = genlabel()
-    emit(syms, v.cond)
+  def self.emit_if(state, v)
+    lbl1 = genlabel(state)
+    lbl2 = genlabel(state)
+    emit(state, v.cond)
     puts "    jmp_if0 :L#{lbl1}"
-    emit_block(syms, v.then)
+    emit_block(state, v.then)
     puts "    jmp :L#{lbl2}"
     puts "label :L#{lbl1}"
-    emit_block(syms, v.else)
+    emit_block(state, v.else)
     puts "label :L#{lbl2}"
   end
 
-  def self.emit_block(syms, v)
+  def self.emit_block(state, v)
     return if v.nil?
     v.each do |v|
-      emit(syms, v);
+      emit(state, v);
     end
   end
 end
 
 $parser = Parser.new("cerise.m")
+state = Codegen.init($parser.syms)
 $parser.syms.each do |name, val|
   $parser.syms.open_scope
   puts "func #{name.to_sym.inspect}, #{val.value.args.length} do"
+  puts "    locals #{val.value.locals.length}" if val.value.locals.length > 0
   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)
+    Codegen.emit(state, stmnt)
   end
   puts "end\n\n"
   $parser.syms.close_scope