From: Michael D. Lowis Date: Mon, 27 Nov 2023 03:51:24 +0000 (-0500) Subject: moved definitions to be teh first statements in a function X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=a8e7d3b754cc98276e689c77e0a62c9608495421;p=proto%2Faas.git moved definitions to be teh first statements in a function --- diff --git a/cerise.rb b/cerise.rb index bb3cdf8..a18c280 100755 --- 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