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(); +}