From 327f8960e54afc0385852c821f332eac0839f221 Mon Sep 17 00:00:00 2001 From: oczekrb <49495932+oczekrb@users.noreply.github.com> Date: Sat, 4 Dec 2021 11:23:07 +0100 Subject: [PATCH] =?UTF-8?q?Implement=20visit=5Funary=20operator=20logic=20?= =?UTF-8?q?in=20copiler=20for=20minus=20unary=20opera=E2=80=A6=20(#46)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement visit_unary operator logic in copiler for minus unary operator. * Add test for missing unary operator case. Co-authored-by: Jarosław Konik --- examples/mandelbrot.rc | 2 +- src/compiler/mod.rs | 17 ++++++++++++++-- src/llvm/mod.rs | 4 ++++ tests/compiler_tests.rs | 43 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/examples/mandelbrot.rc b/examples/mandelbrot.rc index ce05cd04..3bfa449f 100644 --- a/examples/mandelbrot.rc +++ b/examples/mandelbrot.rc @@ -58,7 +58,7 @@ while y < HEIGHT { if sqrt(vecget(acc, 0) * vecget(acc, 0) + vecget(acc, 1) * vecget(acc, 1)) > 2 { isstable = 0 } - if sqrt(vecget(acc, 0) * vecget(acc, 0) + vecget(acc, 1) * vecget(acc, 1)) < 0-2 { + if sqrt(vecget(acc, 0) * vecget(acc, 0) + vecget(acc, 1) * vecget(acc, 1)) < -2 { isstable = 0 } i = i + 1 diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index bfb63fd5..dd787e44 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -219,8 +219,21 @@ impl Visitor for Compiler { val } - fn visit_unary(&mut self, _: &expression::Unary) -> Value { - todo!() + fn visit_unary(&mut self, expr: &expression::Unary) -> Value { + match expr.operator { + expression::Operator::Minus => { + let r = match self.walk(&expr.right) { + Value::Numeric(p) => p, + _ => panic!("panic"), + }; + + Value::Numeric(self.builder.build_fneg(r, "")) + } + _ => panic!( + "operator {:?} is not valid for unary operations", + expr.operator + ), + } } fn visit_grouping(&mut self, expr: &expression::Expression) -> Value { diff --git a/src/llvm/mod.rs b/src/llvm/mod.rs index 0dc76e92..a05e2eae 100644 --- a/src/llvm/mod.rs +++ b/src/llvm/mod.rs @@ -139,6 +139,10 @@ impl Builder { Value(unsafe { LLVMBuildFMul(self.0, lhs.0, rhs.0, c_str(name).as_ptr()) }) } + pub fn build_fneg(&self, rhs: Value, name: &str) -> Value { + Value(unsafe { LLVMBuildFNeg(self.0, rhs.0, c_str(name).as_ptr()) }) + } + pub fn build_fcmp(&self, lhs: Value, rhs: Value, operator: Cmp, name: &str) -> Value { Value(unsafe { LLVMBuildFCmp( diff --git a/tests/compiler_tests.rs b/tests/compiler_tests.rs index 0d618dcc..fc2aa7be 100644 --- a/tests/compiler_tests.rs +++ b/tests/compiler_tests.rs @@ -1,6 +1,6 @@ use rocklang::compiler::{Compile, Compiler}; use rocklang::expression::{ - Assignment, Binary, Conditional, Expression, FuncCall, FuncDecl, Operator, While, + Assignment, Binary, Conditional, Expression, FuncCall, FuncDecl, Operator, Unary, While, }; use rocklang::parser::{Param, Program, Type}; @@ -693,3 +693,44 @@ fn it_panics_when_not_equal_string_to_numeric() { Box::new(Expression::Numeric(10.0)) ); } + +#[test] +fn it_compiles_unary_operator() { + let program = Program { + body: vec![Expression::Unary(Unary { + operator: Operator::Minus, + right: Box::new(Expression::Numeric(2.0)), + })], + }; + + let mut compiler = Compiler::new(program); + compiler.compile().unwrap(); +} + +#[test] +#[should_panic] +fn it_panics_when_pass_string_to_unary() { + let program = Program { + body: vec![Expression::Unary(Unary { + operator: Operator::Minus, + right: Box::new(Expression::String("foo".to_string())), + })], + }; + + let mut compiler = Compiler::new(program); + compiler.compile().unwrap(); +} + +#[test] +#[should_panic] +fn it_panics_when_wrong_unary_operator() { + let program = Program { + body: vec![Expression::Unary(Unary { + operator: Operator::Plus, + right: Box::new(Expression::Numeric(2.0)), + })], + }; + + let mut compiler = Compiler::new(program); + compiler.compile().unwrap(); +}