From 5b46e85bc6e10868de4b0216529d4339ee2646a7 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Sun, 12 Nov 2023 22:30:16 -0500 Subject: [PATCH] added multiplication, division, and AND --- aas.rb | 6 +- cerise.m | 2 +- cerise.rb | 247 ++++++++++++++++-------------------------------------- 3 files changed, 74 insertions(+), 181 deletions(-) diff --git a/aas.rb b/aas.rb index 6664e67..672cff8 100755 --- a/aas.rb +++ b/aas.rb @@ -69,21 +69,21 @@ module Targets def muli emit "popq %rax" emit "popq %rbx" - emit "imull %rbx, %rax" + emit "imulq %rbx, %rax" emit "pushq %rax" end def divi emit "popq %rax" emit "popq %rbx" - emit "idivl %rbx, %rax" + emit "idivq %rbx, %rax" emit "pushq %rax" end def modi emit "popq %rax" emit "popq %rbx" - emit "idivl %rbx, %rax" + emit "idivq %rbx, %rax" emit "pushq %rdx" end diff --git a/cerise.m b/cerise.m index 81920d1..fc7e1bb 100644 --- a/cerise.m +++ b/cerise.m @@ -1,4 +1,4 @@ main() { - return 42 + return 43 % 2 } diff --git a/cerise.rb b/cerise.rb index 35bb776..6daa8e5 100755 --- a/cerise.rb +++ b/cerise.rb @@ -28,7 +28,7 @@ class Lexer SPACE = /([ \t\v\n\r]+|#.*\n)/ IDENT = /[_a-zA-Z][_a-zA-Z0-9]*!?/ BRACES = /[\(\)\[\]\{\}\.]/ - OPERATORS = /[:,<>*\/=+\-\$?!]+/ + OPERATORS = /[:,<>*\/=+\-\$?!%]+/ INTEGER = /[0-9]+/ FLOATING = /[0-9]+\.[0-9]+/ STRING = /"(\\"|[^"])*"/ @@ -192,8 +192,9 @@ module IR Return = Struct.new(:loc, :type, :value) Const = Struct.new(:loc, :type, :value) Var = Struct.new(:loc, :type, :name) - Def = Struct.new(:loc, :type, :name, :value) + Op = Struct.new(:loc, :type, :op, :left, :right) + # EnvRef = Struct.new(:loc, :type, :index) # Let = Struct.new(:loc, :type, :var, :expr, :body) @@ -689,6 +690,54 @@ class Parser end def expression() + simple_expr() + end + + def simple_expr() + term() + +# 269 /* first term and +/- unary ops */ +# 270 if (matches_oneof(p, (int[]){'+', '-', 0})) +# 271 { +# 272 int op = consume(p); +# 273 SsaNode* operand = term(p); +# 274 check_num(p, operand); +# 275 expr = ssa_op(p, op, operand, NULL); +# 276 } +# 277 else +# 278 { +# 279 expr = term(p); +# 280 } +# 281 +# 282 /* optional second term and binary ops */ +# 283 while (matches_oneof(p, (int[]){'+', '-', OR, 0})) +# 284 { +# 285 int op = consume(p); +# 286 SsaNode* right = term(p); +# 287 if (op == OR) +# 288 { +# 289 check_bools(p, expr, right); +# 290 } +# 291 else +# 292 { +# 293 check_nums(p, expr, right); +# 294 } +# 295 expr = ssa_op(p, op, expr, right); +# 296 } + + end + + def term() + left = factor() + while matches_any(["*", "/", "%", :and]) + op = consume() + right = factor(); + left = IR::Op.new(location, nil, op.text, left, right) + end + left + end + + def factor() constant() end @@ -708,179 +757,6 @@ class Parser error("invalid constant") end end - - - -# def declaration() -# if matches(:ident) -# expr = ident() -# expr.type = syms[expr.name][:type] if syms[expr.name] -# if accept("=") -# value = expression() -# syms.add_sym(expr.name, expr.loc, :var, expr.type) -# IR::Let.new(expr.loc, nil, expr, value, nil) -# elsif accept(":") -# expr.type = type_spec() -# syms.add_sym(expr.name, expr.loc, :var, expr.type) -# nil -# else -# expression() -# end -# else -# expression() -# end -# end -# -# def expression() -# if matches(:let) -# let_expr() -# else -# complex_expr() -# end -# end -# -# def complex_expr() -# expr = nil -# if matches(:if) -# expr = if_expr() -# elsif matches(:set) -# expr = var_set() -# elsif matches_any(["+","-", "!"]) -# expr = unop_call() -# else -# expr = atomic_expr() -# if matches("(") -# expr = func_call(expr) -# elsif operator? -# expr = binop_call(expr) -# end -# end -# expr -# end -# -# def atomic_expr() -# if matches(:func) -# func_expr() -# elsif matches(:ident) -# ident() -# else -# constant() -# end -# end -# -# -# -# -# def application() -## expr = atomic_expr() -## expr = func_call(expr) if matches("(") -# # EQ, NEQ, '<', LTEQ, '>', GTEQ -# end -# -# def simple_expr() -# # '+', '-', OR -# end -# -# def term() -# # '*', '/', '%', AND -# end -# -# def factor() -# # '(', NOT, atomic -# end -# -# -# -# -# def unop_call() -# op = consume() -# rhs = atomic_expr() -# IR::Apply.new(op.pos, nil, op.type, [rhs]) -# end -# -# def binop_call(expr) -# op = consume() -# rhs = atomic_expr() -# IR::Apply.new(expr.loc, nil, op.type, [expr, rhs]) -# end -# -# def if_expr() -# loc = expect(:if).pos -# cond = atomic_expr() -# expect(:then) -# branch1 = expression() -# expect(:else) -# branch2 = expression() -# IR::If.new(loc, nil, cond, branch1, branch2) -# end -# -# def var_set() -# loc = expect(:set).pos -# name = ident() -# expect("=") -# expr = expression() -# IR::Set.new(loc, nil, name, expr) -# end -# -# def func_call(func) -# args = [] -# expect("(") -# while !matches(")") -# args << atomic_expr() -# expect(",") if not matches(")") -# end -# expect(")") -# IR::Apply.new(func.loc, nil, func, args) -# end -# -# def func_expr() -# loc = expect(:func).pos -# args = [] -# expect("(") -# while !matches(")") -# args << ident() -# args.last.type = type_spec() if accept(":") -# expect(",") if not matches(")") -# end -# expect(")") -# type = type_spec() if accept(":") -# body = expression() -# IR::Func.new(loc, type, args, body) -# end -# -# def ident() -# name = expect(:ident) -# IR::Var.new(name.pos, nil, name.text.to_sym) -# end -# -# def typename() -# name = expect(:ident) -# sym = syms[name.text] -# if sym && sym[:kind] != :type -# error(name.pos, "#{name.text} is not a valid type") -# end -# IR::Var.new(name.pos, nil, name.text.to_sym) -# end -# -# -# def let_expr() -# expect(:let) -# name = ident() -# name.type = type_spec() if accept(":") -# expect("=") -# expr = complex_expr() -# expect(:in) -# body = expression() -# IR::Let.new(name.loc, nil, name, expr, body) -# end -# -# def type_spec() -# type = [typename().name] -# while accept("->") -# type << typename().name -# end -# (type.length == 1 ? type[0] : type) -# end end module Codegen @@ -889,8 +765,10 @@ module Codegen emit_return(v) elsif v.is_a? IR::Const then emit_const(v) -# else -# emit_const(v) + elsif v.is_a? IR::Op then + emit_op(v) + else + raise "not implemented" end end @@ -904,6 +782,21 @@ module Codegen puts " int #{v.value}" end end + + def self.emit_op(v) + emit(v.right) if v.right + emit(v.left) + case v.op + when "*" + puts " muli" + when "/" + puts " divi" + when "%" + puts " modi" + else + raise "not implemented" + end + end end $parser = Parser.new("cerise.m") -- 2.52.0