Skip to content

Commit

Permalink
[BUG] Invalid operation Precedence (amber-lang#367)
Browse files Browse the repository at this point in the history
* feat(expr): overhaul of expression syntax module

* feat: adapt binary operator modules to the new structure

* merge(precedence): resolve path to command

* fix(refactor): Added macros to make writing operator precedence much easier

* fix(expr): Attach operators to work with precedence macro

* feat(precedence): remove precedence file

* fix(format): Cargo clippy and fmt

* revert(format): Cargo clippy and fmt

This reverts commit 88fc6b0.

* fix(lint): resolve clippy errors

* Update src/modules/expression/macros.rs

Co-authored-by: Hubert Jabłoński <[email protected]>

* feat(tests): add validity tests

* fix(macro): improved handle binop macro

* fix(expr): remove pub from fields

* feat(macro): change prev to next

* feat(macro): add edge case for one group

* Update src/modules/expression/binop/sub.rs

Co-authored-by: Hubert Jabłoński <[email protected]>

* Update src/modules/expression/binop/eq.rs

Co-authored-by: Hubert Jabłoński <[email protected]>

* Update src/modules/expression/binop/neq.rs

Co-authored-by: Hubert Jabłoński <[email protected]>

* Update src/modules/expression/binop/or.rs

* Update src/modules/expression/binop/and.rs

* feat(error-macro): simplify code in a macro to keep DRY principle

* feat(test): Add test for multiple cast

* fix(and): remove comment

* fix(range): Fix range and remove import from code eval (the stdlib looks diffrent now)

* Update src/modules/expression/ternop/ternary.rs

Co-authored-by: Hubert Jabłoński <[email protected]>

* Update src/modules/expression/ternop/ternary.rs

Co-authored-by: Hubert Jabłoński <[email protected]>

---------

Co-authored-by: Hubert Jabłoński <[email protected]>
  • Loading branch information
Ph0enixKM and KrosFire committed Aug 8, 2024
1 parent cde0068 commit 2851990
Show file tree
Hide file tree
Showing 41 changed files with 901 additions and 339 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ rust-version = "1.79"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
heraclitus-compiler = "1.6.2"
heraclitus-compiler = "1.7.8"
similar-string = "1.4.2"
colored = "2.0.0"
itertools = "0.13.0"
Expand Down
3 changes: 1 addition & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct Cli {
eval: Option<String>,

/// Generate docs
/// (OUTPUT is dir instead, default: `docs/`)
/// (OUTPUT is dir instead, default: `docs/`)
#[arg(long)]
docs: bool,

Expand Down Expand Up @@ -112,7 +112,6 @@ fn handle_compile(cli: Cli) -> Result<(), Box<dyn Error>> {
}

fn handle_eval(code: String, cli: Cli) -> Result<(), Box<dyn Error>> {
let code = format!("import * from \"std\"\n{code}");
match AmberCompiler::new(code, None, cli).compile() {
Ok((messages, code)) => {
messages.iter().for_each(|m| m.show());
Expand Down
3 changes: 1 addition & 2 deletions src/modules/condition/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod ifcond;
pub mod ifchain;
pub mod ternary;
pub mod failed;
pub mod failed;
36 changes: 25 additions & 11 deletions src/modules/expression/binop/add.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::{handle_binop, error_type_match};
use crate::modules::expression::expr::Expr;
use crate::translate::compute::{translate_computation, ArithOp};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::types::{Typed, Type};

use super::BinOp;

#[derive(Debug, Clone)]
pub struct Add {
left: Box<Expr>,
Expand All @@ -19,27 +22,38 @@ impl Typed for Add {
}
}

impl BinOp for Add {
fn set_left(&mut self, left: Expr) {
self.left = Box::new(left);
}

fn set_right(&mut self, right: Expr) {
self.right = Box::new(right);
}

fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, "+")?;
Ok(())
}
}

impl SyntaxModule<ParserMetadata> for Add {
syntax_name!("Add");

fn new() -> Self {
Add {
left: Box::new(Expr::new()),
right: Box::new(Expr::new()),
kind: Type::Null
kind: Type::default()
}
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
parse_left_expr(meta, &mut self.left, "+")?;
let tok = meta.get_current_token();
token(meta, "+")?;
syntax(meta, &mut *self.right)?;
let l_type = self.left.get_type();
let r_type = self.right.get_type();
let message = format!("Cannot add value of type '{l_type}' with value of type '{r_type}'");
let predicate = |kind| matches!(kind, Type::Num | Type::Text | Type::Array(_));
self.kind = expression_arms_of_type(meta, &l_type, &r_type, predicate, tok, &message)?;
self.kind = handle_binop!(meta, "add", self.left, self.right, [
Num,
Text,
Array
])?;
Ok(())
}
}
Expand Down
28 changes: 21 additions & 7 deletions src/modules/expression/binop/and.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::{handle_binop, error_type_match};
use crate::modules::expression::expr::Expr;
use crate::translate::compute::{translate_computation, ArithOp};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_same_type};
use crate::modules::types::{Typed, Type};

use super::BinOp;


#[derive(Debug, Clone)]
pub struct And {
Expand All @@ -19,6 +22,21 @@ impl Typed for And {
}
}

impl BinOp for And {
fn set_left(&mut self, left: Expr) {
self.left = Box::new(left);
}

fn set_right(&mut self, right: Expr) {
self.right = Box::new(right);
}

fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, "and")?;
Ok(())
}
}

impl SyntaxModule<ParserMetadata> for And {
syntax_name!("And");

Expand All @@ -30,15 +48,11 @@ impl SyntaxModule<ParserMetadata> for And {
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
parse_left_expr(meta, &mut self.left, "and")?;
let tok = meta.get_current_token();
token(meta, "and")?;
syntax(meta, &mut *self.right)?;
let error = "Logical and operation can only be used on arguments of the same type";
expression_arms_of_same_type(meta, &self.left, &self.right, tok, error)?;
handle_binop!(meta, "conjoin", self.left, self.right)?;
Ok(())
}
}

impl TranslateModule for And {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let left = self.left.translate(meta);
Expand Down
37 changes: 25 additions & 12 deletions src/modules/expression/binop/div.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use heraclitus_compiler::prelude::*;
use crate::{docs::module::DocumentationModule, translate::compute::{translate_computation, ArithOp}, utils::{metadata::ParserMetadata, TranslateMetadata}};
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::{docs::module::DocumentationModule, utils::TranslateMetadata};
use crate::{handle_binop, error_type_match};
use crate::modules::expression::expr::Expr;
use crate::translate::compute::ArithOp;
use crate::utils::metadata::ParserMetadata;
use crate::translate::compute::translate_computation;
use crate::modules::types::{Typed, Type};
use crate::translate::module::TranslateModule;

use super::BinOp;

#[derive(Debug, Clone)]
pub struct Div {
left: Box<Expr>,
Expand All @@ -16,9 +22,24 @@ impl Typed for Div {
}
}

impl BinOp for Div {
fn set_left(&mut self, left: Expr) {
self.left = Box::new(left);
}

fn set_right(&mut self, right: Expr) {
self.right = Box::new(right);
}

fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, "/")?;
Ok(())
}
}

impl SyntaxModule<ParserMetadata> for Div {
syntax_name!("Div");

fn new() -> Self {
Div {
left: Box::new(Expr::new()),
Expand All @@ -27,15 +48,7 @@ impl SyntaxModule<ParserMetadata> for Div {
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
parse_left_expr(meta, &mut self.left, "/")?;
let tok = meta.get_current_token();
token(meta, "/")?;
syntax(meta, &mut *self.right)?;
let error = "Divide operation can only divide numbers";
let l_type = self.left.get_type();
let r_type = self.right.get_type();
let predicate = |kind| matches!(kind, Type::Num);
expression_arms_of_type(meta, &l_type, &r_type, predicate, tok, error)?;
handle_binop!(meta, "divide", self.left, self.right, [Num])?;
Ok(())
}
}
Expand Down
29 changes: 19 additions & 10 deletions src/modules/expression/binop/eq.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::{handle_binop, error_type_match};
use crate::modules::expression::expr::Expr;
use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::strip_text_quotes;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_same_type};
use super::{strip_text_quotes, BinOp};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
Expand All @@ -19,6 +20,21 @@ impl Typed for Eq {
}
}

impl BinOp for Eq {
fn set_left(&mut self, left: Expr) {
self.left = Box::new(left);
}

fn set_right(&mut self, right: Expr) {
self.right = Box::new(right);
}

fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, "==")?;
Ok(())
}
}

impl SyntaxModule<ParserMetadata> for Eq {
syntax_name!("Eq");

Expand All @@ -30,14 +46,7 @@ impl SyntaxModule<ParserMetadata> for Eq {
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
parse_left_expr(meta, &mut self.left, "==")?;
let tok = meta.get_current_token();
token(meta, "==")?;
syntax(meta, &mut *self.right)?;
let l_type = self.left.get_type();
let r_type = self.right.get_type();
let message = format!("Cannot compare two values of different types '{l_type}' == '{r_type}'");
expression_arms_of_same_type(meta, &self.left, &self.right, tok, &message)?;
handle_binop!(meta, "equate", self.left, self.right)?;
Ok(())
}
}
Expand Down
29 changes: 19 additions & 10 deletions src/modules/expression/binop/ge.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::{handle_binop, error_type_match};
use crate::modules::expression::expr::Expr;
use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::types::{Typed, Type};
use super::BinOp;

#[derive(Debug, Clone)]
pub struct Ge {
Expand All @@ -18,6 +20,21 @@ impl Typed for Ge {
}
}

impl BinOp for Ge {
fn set_left(&mut self, left: Expr) {
self.left = Box::new(left);
}

fn set_right(&mut self, right: Expr) {
self.right = Box::new(right);
}

fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, ">=")?;
Ok(())
}
}

impl SyntaxModule<ParserMetadata> for Ge {
syntax_name!("Ge");

Expand All @@ -29,15 +46,7 @@ impl SyntaxModule<ParserMetadata> for Ge {
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
parse_left_expr(meta, &mut self.left, ">=")?;
let tok = meta.get_current_token();
token(meta, ">=")?;
syntax(meta, &mut *self.right)?;
let l_type = self.left.get_type();
let r_type = self.right.get_type();
let message = format!("Cannot compare two values of different types '{l_type}' >= '{r_type}'");
let predicate = |kind| matches!(kind, Type::Num);
expression_arms_of_type(meta, &l_type, &r_type, predicate, tok, &message)?;
handle_binop!(meta, "compare", self.left, self.right, [Num])?;
Ok(())
}
}
Expand Down
29 changes: 19 additions & 10 deletions src/modules/expression/binop/gt.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::{handle_binop, error_type_match};
use crate::modules::expression::expr::Expr;
use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::types::{Typed, Type};
use super::BinOp;

#[derive(Debug, Clone)]
pub struct Gt {
Expand All @@ -18,6 +20,21 @@ impl Typed for Gt {
}
}

impl BinOp for Gt {
fn set_left(&mut self, left: Expr) {
self.left = Box::new(left);
}

fn set_right(&mut self, right: Expr) {
self.right = Box::new(right);
}

fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, ">")?;
Ok(())
}
}

impl SyntaxModule<ParserMetadata> for Gt {
syntax_name!("Gt");

Expand All @@ -29,15 +46,7 @@ impl SyntaxModule<ParserMetadata> for Gt {
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
parse_left_expr(meta, &mut self.left, ">")?;
let tok = meta.get_current_token();
token(meta, ">")?;
syntax(meta, &mut *self.right)?;
let l_type = self.left.get_type();
let r_type = self.right.get_type();
let message = format!("Cannot compare two values of different types '{l_type}' > '{r_type}'");
let predicate = |kind| matches!(kind, Type::Num);
expression_arms_of_type(meta, &l_type, &r_type, predicate, tok, &message)?;
handle_binop!(meta, "compare", self.left, self.right, [Num])?;
Ok(())
}
}
Expand Down
Loading

0 comments on commit 2851990

Please sign in to comment.