From: Mike Lowis Date: Tue, 21 Nov 2023 19:18:43 +0000 (-0500) Subject: added parsing rules for if statements and local variables X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=4e21a088f3680603c49905c78266e9164ff6b245;p=proto%2Faas.git added parsing rules for if statements and local variables --- diff --git a/.gitignore b/.gitignore index d7756c2..3a9dea0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ a.out *.o +*.aas +*.s diff --git a/cerise.m b/cerise.m index 48e0867..a0e98a5 100644 --- a/cerise.m +++ b/cerise.m @@ -1,9 +1,18 @@ sum(a,b) { - return a==b + def c = 5 + if (a < b) + { + set c = 1 + } + else + { + set c = 0 + } + return c } main() { - return sum(3,2) + return sum(1+1,2) } diff --git a/cerise.rb b/cerise.rb index 282b05a..8fad22d 100755 --- a/cerise.rb +++ b/cerise.rb @@ -47,13 +47,11 @@ class Lexer "true" => :bool, "false" => :bool, "if" => :if, - "then" => :then, "else" => :else, - "end" => :end, - "let" => :let, - "func" => :func, - "in" => :in, - "set!" => :set, + "def" => :def, + "set" => :set, +# "func" => :func, +# "in" => :in, "is" => :is, "return" => :return, } @@ -153,8 +151,10 @@ module IR Const = Struct.new(:loc, :type, :value) Var = Struct.new(:loc, :type, :name) Def = Struct.new(:loc, :type, :name, :value) + Set = Struct.new(:loc, :type, :name, :value) Op = Struct.new(:loc, :type, :op, :left, :right) Call = Struct.new(:loc, :type, :func, :args) + If = Struct.new(:loc, :type, :cond, :then, :else) # EnvRef = Struct.new(:loc, :type, :index) # Let = Struct.new(:loc, :type, :var, :expr, :body) @@ -636,10 +636,9 @@ class Parser args = function_arglist() func = IR::Func.new(name.loc, nil, args, []) expect("{") - expect(:return); - if !matches("}") - func.body << IR::Return.new(location, nil, expression()) - end + stmts = statement_list(["}", :return]) + stmts << return_statement + func.body = stmts expect("}"); func end @@ -672,6 +671,94 @@ class Parser IR::Var.new(name.pos, nil, name.text.to_sym) end + + ## + # Statements + ## + def statement_list(terminators) + stmts = [] + while !matches_any(terminators) + stmts << statement + end + stmts + end + + def statement() + # variable definition + # variable assignment + # if statement + # expression + + if matches(:def) + variable_definition() + elsif matches(:set) + variable_assignment() + elsif matches(:if) + if_statement() + else + expression() + end + end + + def return_statement() + loc = location + expect(:return); + if !matches("}") + IR::Return.new(loc, nil, expression()) + else + IR::Return.new(loc, nil, nil) + end + end + + def variable_definition() + loc = location + expect(:def) + name = identifier() + expect ("=") + value = expression() + IR::Def.new(loc, nil, name, value) + end + + def variable_assignment() + loc = location + expect(:set) + name = identifier() + expect ("=") + value = expression() + IR::Set.new(loc, nil, name, value) + end + + def if_statement() + loc = location + expect(:if) + cond = expression() + then_branch = statement_block() + if accept(:else) + if matches(:if) + else_branch = [ if_statement() ] + else + else_branch = statement_block() + end + end + IR::If.new(loc, nil, cond, then_branch, else_branch) + end + + def statement_block() + loc = location + stmts = [] + expect("{") + while !matches("}") + stmts << statement() + end + expect("}") + return stmts + end + + + ## + # Expressions + ## + def expression() left = simple_expr() if matches_any(["==", "!=", "<", "<=", ">", ">="]) @@ -773,6 +860,12 @@ module Codegen emit_var(syms, v) elsif v.is_a? IR::Call then emit_call(syms, v) + elsif v.is_a? IR::Def then + emit_def(syms, v) + elsif v.is_a? IR::Set then + emit_set(syms, v) + elsif v.is_a? IR::If then + emit_if(syms, v) else raise "code emitting of #{v.class} not implemented" end @@ -822,8 +915,14 @@ module Codegen def self.emit_var(syms, v) sym = syms[v.name] - if sym.kind == :param - puts " get_param #{sym.value}" + if sym + if sym.kind == :param + puts " get_param #{sym.value}" + elsif sym.kind == :local + puts " get_local :#{sym.name}" + end + else + puts "# invalid var #{v.name}" end end @@ -839,6 +938,22 @@ module Codegen puts " fcallv" end end + + def self.emit_def(syms, v) + puts "# def #{v.name} = #{v}" + syms.add_sym( + v.name.name, v.loc, :local, v.type, v.value) + emit(syms, v.value) + puts " set_local :#{v.name.name}" + end + + def self.emit_set(syms, v) + puts " set_local :#{v.name.name}" + end + + def self.emit_if(syms, v) + puts "# if " + end end $parser = Parser.new("cerise.m")