Skip to content

Commit

Permalink
Builtin lines function part I - Refactoring (#565)
Browse files Browse the repository at this point in the history
  • Loading branch information
hdwalters authored Nov 7, 2024
1 parent d87e0c0 commit 188abb4
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 86 deletions.
7 changes: 4 additions & 3 deletions src/modules/expression/binop/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ impl TranslateModule for Add {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let left = self.left.translate_eval(meta, false);
let right = self.right.translate_eval(meta, false);
let quote = meta.gen_quote();
match self.kind {
Type::Array(_) => {
let quote = meta.gen_quote();
let id = meta.gen_array_id();
meta.stmt_queue.push_back(format!("__AMBER_ARRAY_ADD_{id}=({left} {right})"));
format!("{quote}${{__AMBER_ARRAY_ADD_{id}[@]}}{quote}")
let name = format!("__AMBER_ARRAY_ADD_{id}");
meta.stmt_queue.push_back(format!("{name}=({left} {right})"));
format!("{quote}${{{name}[@]}}{quote}")
},
Type::Text => format!("{}{}", left, right),
_ => translate_computation(meta, ArithOp::Add, Some(left), Some(right))
Expand Down
56 changes: 36 additions & 20 deletions src/modules/shorthand/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,47 @@ impl SyntaxModule<ParserMetadata> for ShorthandAdd {
}

impl TranslateModule for ShorthandAdd {
//noinspection DuplicatedCode
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let expr = self.is_ref
.then(|| self.expr.translate_eval(meta, true))
.unwrap_or_else(|| self.expr.translate(meta));
let name: String = match self.global_id {
Some(id) => format!("__{id}_{}", self.var),
None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() }
let name = if let Some(id) = self.global_id {
format!("__{id}_{}", self.var)
} else if self.is_ref {
format!("${{{}}}", self.var)
} else {
self.var.clone()
};
let stmt = match self.kind {
Type::Text => format!("{}+={}", name, expr),
Type::Array(_) => format!("{}+=({})", name, expr),
match self.kind {
Type::Text => {
if self.is_ref {
let expr = self.expr.translate_eval(meta, true);
format!("eval \"{name}+={expr}\"")
} else {
let expr = self.expr.translate(meta);
format!("{name}+={expr}")
}
}
Type::Array(_) => {
if self.is_ref {
let expr = self.expr.translate_eval(meta, true);
format!("eval \"{name}+=({expr})\"")
} else {
let expr = self.expr.translate(meta);
format!("{name}+=({expr})")
}
}
_ => {
let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") };
let translated_computation = if self.is_ref {
translate_computation_eval(meta, ArithOp::Add, Some(var), Some(expr))
if self.is_ref {
let var = format!("\\${{{name}}}");
let expr = self.expr.translate_eval(meta, true);
let expr = translate_computation_eval(meta, ArithOp::Add, Some(var), Some(expr));
format!("eval \"{name}={expr}\"")
} else {
translate_computation(meta, ArithOp::Add, Some(var), Some(expr))
};
format!("{}={}", name, translated_computation)
let var = format!("${{{name}}}");
let expr = self.expr.translate(meta);
let expr = translate_computation(meta, ArithOp::Add, Some(var), Some(expr));
format!("{name}={expr}")
}
}
};
if self.is_ref {
format!("eval \"{}\"", stmt)
} else {
stmt
}
}
}
Expand Down
26 changes: 15 additions & 11 deletions src/modules/shorthand/div.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,25 @@ impl SyntaxModule<ParserMetadata> for ShorthandDiv {
}

impl TranslateModule for ShorthandDiv {
//noinspection DuplicatedCode
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let expr = self.is_ref
.then(|| self.expr.translate_eval(meta, true))
.unwrap_or_else(|| self.expr.translate(meta));
let name = match self.global_id {
Some(id) => format!("__{id}_{}", self.var),
None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() }
let name = if let Some(id) = self.global_id {
format!("__{id}_{}", self.var)
} else if self.is_ref {
format!("${{{}}}", self.var)
} else {
self.var.clone()
};
let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") };
if self.is_ref {
let eval = translate_computation_eval(meta, ArithOp::Div, Some(var), Some(expr));
format!("eval \"{}={}\"", name, eval)
let var = format!("\\${{{name}}}");
let expr = self.expr.translate_eval(meta, true);
let expr = translate_computation_eval(meta, ArithOp::Div, Some(var), Some(expr));
format!("eval \"{name}={expr}\"")
} else {
let eval = translate_computation(meta, ArithOp::Div, Some(var), Some(expr));
format!("{}={}", name, eval)
let var = format!("${{{name}}}");
let expr = self.expr.translate(meta);
let expr = translate_computation(meta, ArithOp::Div, Some(var), Some(expr));
format!("{name}={expr}")
}
}
}
Expand Down
22 changes: 13 additions & 9 deletions src/modules/shorthand/modulo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,25 @@ impl SyntaxModule<ParserMetadata> for ShorthandModulo {
}

impl TranslateModule for ShorthandModulo {
//noinspection DuplicatedCode
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let expr = self.is_ref
.then(|| self.expr.translate_eval(meta, true))
.unwrap_or_else(|| self.expr.translate(meta));
let name = match self.global_id {
Some(id) => format!("__{id}_{}", self.var),
None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() }
let name = if let Some(id) = self.global_id {
format!("__{id}_{}", self.var)
} else if self.is_ref {
format!("${{{}}}", self.var)
} else {
self.var.clone()
};
let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") };
if self.is_ref {
let var = format!("\\${{{name}}}");
let expr = self.expr.translate_eval(meta, true);
let expr = translate_computation_eval(meta, ArithOp::Modulo, Some(var), Some(expr));
format!("eval \"{}={}\"", name, expr)
format!("eval \"{name}={expr}\"")
} else {
let var = format!("${{{name}}}");
let expr = self.expr.translate(meta);
let expr = translate_computation(meta, ArithOp::Modulo, Some(var), Some(expr));
format!("{}={}", name, expr)
format!("{name}={expr}")
}
}
}
Expand Down
22 changes: 13 additions & 9 deletions src/modules/shorthand/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,25 @@ impl SyntaxModule<ParserMetadata> for ShorthandMul {
}

impl TranslateModule for ShorthandMul {
//noinspection DuplicatedCode
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let expr = self.is_ref
.then(|| self.expr.translate_eval(meta, true))
.unwrap_or_else(|| self.expr.translate(meta));
let name = match self.global_id {
Some(id) => format!("__{id}_{}", self.var),
None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() }
let name = if let Some(id) = self.global_id {
format!("__{id}_{}", self.var)
} else if self.is_ref {
format!("${{{}}}", self.var)
} else {
self.var.clone()
};
let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") };
if self.is_ref {
let var = format!("\\${{{name}}}");
let expr = self.expr.translate_eval(meta, true);
let expr = translate_computation_eval(meta, ArithOp::Mul, Some(var), Some(expr));
format!("eval \"{}={}\"", name, expr)
format!("eval \"{name}={expr}\"")
} else {
let var = format!("${{{name}}}");
let expr = self.expr.translate(meta);
let expr = translate_computation(meta, ArithOp::Mul, Some(var), Some(expr));
format!("{}={}", name, expr)
format!("{name}={expr}")
}
}
}
Expand Down
22 changes: 13 additions & 9 deletions src/modules/shorthand/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,25 @@ impl SyntaxModule<ParserMetadata> for ShorthandSub {
}

impl TranslateModule for ShorthandSub {
//noinspection DuplicatedCode
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let expr = self.is_ref
.then(|| self.expr.translate_eval(meta, true))
.unwrap_or_else(|| self.expr.translate(meta));
let name = match self.global_id {
Some(id) => format!("__{id}_{}", self.var),
None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() }
let name = if let Some(id) = self.global_id {
format!("__{id}_{}", self.var)
} else if self.is_ref {
format!("${{{}}}", self.var)
} else {
self.var.clone()
};
let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") };
if self.is_ref {
let var = format!("\\${{{name}}}");
let expr = self.expr.translate_eval(meta, true);
let expr = translate_computation_eval(meta, ArithOp::Sub, Some(var), Some(expr));
format!("eval \"{}={}\"", name, expr)
format!("eval \"{name}={expr}\"")
} else {
let var = format!("${{{name}}}");
let expr = self.expr.translate(meta);
let expr = translate_computation(meta, ArithOp::Sub, Some(var), Some(expr));
format!("{}={}", name, expr)
format!("{name}={expr}")
}
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/modules/variable/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ impl SyntaxModule<ParserMetadata> for VariableInit {
impl TranslateModule for VariableInit {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let name = self.name.clone();
let mut expr = self.expr.translate(meta);
let mut expr = self.expr.translate(meta);
if let Type::Array(_) = self.expr.get_type() {
expr = format!("({expr})");
}
let local = if self.is_fun_ctx { "local " } else { "" };
match self.global_id {
Some(id) => format!("__{id}_{name}={expr}"),
None => format!("{local}{name}={expr}")
if let Some(id) = self.global_id {
format!("__{id}_{name}={expr}")
} else if self.is_fun_ctx {
format!("local {name}={expr}")
} else {
format!("{name}={expr}")
}
}
}
Expand Down
46 changes: 26 additions & 20 deletions src/modules/variable/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,29 @@ use crate::modules::types::{Typed, Type};
#[derive(Debug, Clone)]
pub struct VariableSet {
name: String,
value: Box<Expr>,
expr: Box<Expr>,
global_id: Option<usize>,
index: Option<Expr>,
is_ref: bool
}

impl VariableSet {
fn translate_eval_if_ref(&self, expr: &Expr, meta: &mut TranslateMetadata) -> String {
if self.is_ref {
expr.translate_eval(meta, true)
} else {
expr.translate(meta)
}
}
}

impl SyntaxModule<ParserMetadata> for VariableSet {
syntax_name!("Variable Set");

fn new() -> Self {
VariableSet {
name: String::new(),
value: Box::new(Expr::new()),
expr: Box::new(Expr::new()),
global_id: None,
index: None,
is_ref: false
Expand All @@ -32,13 +42,13 @@ impl SyntaxModule<ParserMetadata> for VariableSet {
self.name = variable(meta, variable_name_extensions())?;
self.index = handle_index_accessor(meta)?;
token(meta, "=")?;
syntax(meta, &mut *self.value)?;
syntax(meta, &mut *self.expr)?;
let variable = handle_variable_reference(meta, tok.clone(), &self.name)?;
self.global_id = variable.global_id;
self.is_ref = variable.is_ref;
// Typecheck the variable
let left_type = variable.kind.clone();
let right_type = self.value.get_type();
let right_type = self.expr.get_type();
// Check if the variable can be indexed
if self.index.is_some() && !matches!(variable.kind, Type::Array(_)) {
return error!(meta, tok, format!("Cannot assign a value to an index of a non-array variable of type '{left_type}'"));
Expand All @@ -47,14 +57,14 @@ impl SyntaxModule<ParserMetadata> for VariableSet {
if self.index.is_some() {
// Check if the assigned value is compatible with the array
if let Type::Array(kind) = variable.kind.clone() {
if *kind != self.value.get_type() {
let right_type = self.value.get_type();
if *kind != self.expr.get_type() {
let right_type = self.expr.get_type();
return error!(meta, tok, format!("Cannot assign value of type '{right_type}' to an array of '{kind}'"));
}
}
}
// Check if the variable is compatible with the assigned value
else if variable.kind != self.value.get_type() {
else if variable.kind != self.expr.get_type() {
return error!(meta, tok, format!("Cannot assign value of type '{right_type}' to a variable of type '{left_type}'"));
}
Ok(())
Expand All @@ -65,23 +75,19 @@ impl TranslateModule for VariableSet {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let name = self.name.clone();
let index = self.index.as_ref()
.map(|index| format!("[{}]", self.is_ref
.then(|| index.translate_eval(meta, true))
.unwrap_or_else(|| index.translate(meta))))
.map(|index| self.translate_eval_if_ref(index, meta))
.map(|index| format!("[{index}]"))
.unwrap_or_default();
let mut expr = self.is_ref
.then(|| self.value.translate_eval(meta, true))
.unwrap_or_else(|| self.value.translate(meta));
if let Type::Array(_) = self.value.get_type() {
expr = format!("({})", expr);
let mut expr = self.translate_eval_if_ref(self.expr.as_ref(), meta);
if let Type::Array(_) = self.expr.get_type() {
expr = format!("({expr})");
}
if self.is_ref {
if let Some(id) = self.global_id {
format!("__{id}_{name}{index}={expr}")
} else if self.is_ref {
format!("eval \"${{{name}}}{index}={expr}\"")
} else {
match self.global_id {
Some(id) => format!("__{id}_{name}{index}={expr}"),
None => format!("{name}{index}={expr}")
}
format!("{name}{index}={expr}")
}
}
}
Expand Down

0 comments on commit 188abb4

Please sign in to comment.