Skip to content

Commit

Permalink
improve parsing results for arrays with custom names
Browse files Browse the repository at this point in the history
  • Loading branch information
x87 committed Jan 7, 2024
1 parent 8676a6d commit 237a694
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 76 deletions.
8 changes: 8 additions & 0 deletions src/parser/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ pub enum Variable {
}

impl Variable {
pub fn get_var_name(&self) -> &Token {
match self {
Variable::Indexed(v) => &v.var.get_var_name(),
Variable::ArrayElement(v) => &v.array_var.get_var_name(),
Variable::Local(v) | Variable::Global(v) | Variable::Adma(v) => &v.token,
}
}

pub fn is_global(&self) -> bool {
match self {
Variable::Global(_) | Variable::Adma(_) => true,
Expand Down
55 changes: 52 additions & 3 deletions src/parser/variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ static ADMA_CHAR: char = '&';
pub fn variable(s: Span) -> R<Variable> {
alt((
map(
consumed(tuple((single_variable, array_element_scr))),
consumed(tuple((single_variable_or_const, array_element_scr))),
|(span, (var, (index, len, _type)))| {
Variable::ArrayElement(ArrayElementSCR {
array_var: Box::new(var),
Expand All @@ -32,7 +32,7 @@ pub fn variable(s: Span) -> R<Variable> {
},
),
map(
consumed(tuple((single_variable, array_index))),
consumed(tuple((single_variable_or_const, array_index))),
|(span, (var, index))| {
Variable::Indexed(IndexedVariable {
var: Box::new(var),
Expand All @@ -50,7 +50,7 @@ fn array_element_scr(s: Span) -> R<(Variable, Token, VariableType)> {
delimited(
char('('),
tuple((
terminated(single_variable, char(',')),
terminated(single_variable_or_const, char(',')),
literal::decimal,
array_type,
)),
Expand All @@ -64,6 +64,7 @@ fn array_index(s: Span) -> R<Node> {
alt((
map(single_variable, |v| Node::Variable(v)),
map(literal::decimal, |d| Node::Literal(d)),
map(literal::identifier, |d| Node::Literal(d)),
)),
char(']'),
)(s)
Expand All @@ -73,6 +74,19 @@ fn single_variable(s: Span) -> R<Variable> {
alt((local_var, global_var, adma_var))(s)
}

fn single_variable_or_const(s: Span) -> R<Variable> {
alt((
single_variable,
map(literal::identifier, |var| {
Variable::Local(SingleVariable {
name: var.clone(),
_type: VariableType::Unknown,
token: var,
})
}),
))(s)
}

fn local_var(s: Span) -> R<Variable> {
map(
consumed(tuple((
Expand Down Expand Up @@ -558,4 +572,39 @@ mod tests {
}
);
}

#[test]
fn test_parser_variables15() {
let (_, ast) = parse("a[0]").unwrap();
assert_eq!(
ast,
AST {
body: vec![Node::Variable(Variable::Indexed(IndexedVariable {
var: Box::new(Variable::Local(SingleVariable {
name: Token {
start: 1,
len: 1,
syntax_kind: SyntaxKind::Identifier
},
_type: VariableType::Unknown,
token: Token {
start: 1,
len: 1,
syntax_kind: SyntaxKind::Identifier
}
})),
index: Box::new(Node::Literal(Token {
start: 3,
len: 1,
syntax_kind: SyntaxKind::IntegerLiteral
})),
token: Token {
start: 1,
len: 4,
syntax_kind: SyntaxKind::IndexedVariable
}
}))]
}
);
}
}
54 changes: 52 additions & 2 deletions src/v4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ mod tests {
assert_eq!(t("~10@($_,1i)"), "0B1A: 10@($_,1i)");
assert_eq!(t("~$0101(1000@,12f)"), "0B1A: $0101(1000@,12f)");
assert_eq!(t("~x"), "0B1A: 3@");
assert_eq!(t("~x[0]"), "0B1A: x[0]");
assert_eq!(t("~x[1@]"), "0B1A: x[1@]");
assert_eq!(t("~1@[x]"), "0B1A: 1@[x]");
assert_eq!(t("~x(1@,1i)"), "0B1A: x(1@,1i)");

}

#[test]
Expand Down Expand Up @@ -78,6 +83,12 @@ mod tests {
assert_eq!(t("0@ >>= 1@"), "0B1C: 0@ 1@");
assert_eq!(t("0@ <<= 1@"), "0B1D: 0@ 1@");
assert_eq!(t("&101 <<= &123"), "0B1D: &101 &123");
assert_eq!(t("0@[0] &= 1@(10@,1i)"), "0B17: 0@[0] 1@(10@,1i)");
assert_eq!(t("0@[0] |= 1@(10@,1i)"), "0B18: 0@[0] 1@(10@,1i)");
assert_eq!(t("0@[0] ^= 1@(10@,1i)"), "0B19: 0@[0] 1@(10@,1i)");
assert_eq!(t("0@[0] %= 1@(10@,1i)"), "0B1B: 0@[0] 1@(10@,1i)");
assert_eq!(t("0@[0] >>= 1@(10@,1i)"), "0B1C: 0@[0] 1@(10@,1i)");
assert_eq!(t("0@[0] <<= 1@(10@,1i)"), "0B1D: 0@[0] 1@(10@,1i)");

assert_eq!(t("$var = 5"), "0004: $var 5");
assert_eq!(t("$var = -5"), "0004: $var -5");
Expand Down Expand Up @@ -153,7 +164,26 @@ mod tests {
assert_eq!(t("x = y - z"), "0A8F: 3@ 4@ 5@");
assert_eq!(t("x = y * z"), "0A90: 3@ 4@ 5@");
assert_eq!(t("x = y / z"), "0A91: 3@ 4@ 5@");

assert_eq!(t("x[0] = y[0] & y[1]"), "0B10: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] | y[1]"), "0B11: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] ^ y[1]"), "0B12: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] % y[1]"), "0B14: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] >> y[1]"), "0B15: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] << y[1]"), "0B16: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] + y[1]"), "0A8E: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] - y[1]"), "0A8F: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] * y[1]"), "0A90: x[0] y[0] y[1]");
assert_eq!(t("x[0] = y[0] / y[1]"), "0A91: x[0] y[0] y[1]");
assert_eq!(t("x(0@,1i) = y(n,2i) & y(m,2i)"), "0B10: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) | y(m,2i)"), "0B11: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) ^ y(m,2i)"), "0B12: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) % y(m,2i)"), "0B14: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) >> y(m,2i)"), "0B15: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) << y(m,2i)"), "0B16: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) + y(m,2i)"), "0A8E: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) - y(m,2i)"), "0A8F: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) * y(m,2i)"), "0A90: x(0@,1i) y(n,2i) y(m,2i)");
assert_eq!(t("x(0@,1i) = y(n,2i) / y(m,2i)"), "0A91: x(0@,1i) y(n,2i) y(m,2i)");
assert_ne!(t("0@ += 1 | 1@"), "0B11: 0@ 1 1@");
}

Expand All @@ -173,6 +203,10 @@ mod tests {
assert_eq!(t("0@ = ~1@"), "0B13: 0@ 1@");
assert_eq!(t("~0@"), "0B1A: 0@");
assert_eq!(t("~x"), "0B1A: 3@");
assert_eq!(t("~x[0]"), "0B1A: x[0]");
assert_eq!(t("~x[1@]"), "0B1A: x[1@]");
assert_eq!(t("~1@[x]"), "0B1A: 1@[x]");
assert_eq!(t("~x(1@,1i)"), "0B1A: x(1@,1i)");
}

#[test]
Expand Down Expand Up @@ -201,6 +235,10 @@ mod tests {
assert_eq!(t("0@ +=@ $var"), "007C: 0@ $var");
assert_eq!(t("$var +=@ 1@"), "007D: $var 1@");
assert_eq!(t("x +=@ y"), "007B: 3@ 4@");
assert_eq!(t("x[0] +=@ y"), "007B: x[0] 4@");
assert_eq!(t("x[1@] +=@ y"), "007B: x[1@] 4@");
assert_eq!(t("x[n] +=@ y"), "007B: x[n] 4@");
assert_eq!(t("1@[x] +=@ y"), "007B: 1@[x] 4@");

//-=@
assert_eq!(t("$var -=@ 5.0"), "007E: $var 5.0");
Expand All @@ -212,6 +250,10 @@ mod tests {
assert_eq!(t("0@ -=@ $var"), "0082: 0@ $var");
assert_eq!(t("$var -=@ 1@"), "0083: $var 1@");
assert_eq!(t("x -=@ y"), "0081: 3@ 4@");
assert_eq!(t("x[0] -=@ y"), "0081: x[0] 4@");
assert_eq!(t("x[1@] -=@ y"), "0081: x[1@] 4@");
assert_eq!(t("x[n] -=@ y"), "0081: x[n] 4@");
assert_eq!(t("1@[x] -=@ y"), "0081: 1@[x] 4@");
}

#[test]
Expand Down Expand Up @@ -244,6 +286,14 @@ mod tests {
assert_eq!(t("$f =# 0@"), "0091: $f 0@");
assert_eq!(t("0@ =# 1@"), "0092: 0@ 1@");
assert_eq!(t("1@ =# 0@"), "0093: 1@ 0@");
assert_eq!(t("x =# y"), "0092: 3@ 4@");

assert_eq!(t("$i(0@,1i) =# $f(1@,1f)"), "008C: $i(0@,1i) $f(1@,1f)");
assert_eq!(t("$i[0] =# $f[0]"), "008C: $i[0] $f[0]");
// todo:
// assert_eq!(t("$m(0@,1i) =# $n(0@,1f)"), "008C: $m(0@,1i) $n(0@,1f)"); // should not require decl
// assert_eq!(t("x =# y"), "0092: 3@ 4@"); // should resolve const name
// assert_eq!(t("x[0] =# y"), "0092: x[0] 4@");
// assert_eq!(t("x[1@] =# y"), "0092: x[1@] 4@");
// assert_eq!(t("x[n] =# y"), "0092: x[n] 4@");
}
}
132 changes: 61 additions & 71 deletions src/v4/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,84 +313,74 @@ pub fn try_tranform(
if !is_variable(&right_operand) {
return None;
}
let t1 = *var_types.map.get(&var_name)?;
let t2 = *var_types.map.get(&right_operand_name)?;
let left_var = as_variable(&var)?;
let right_var = as_variable(&right_operand)?;

let t1 = *var_types
.map
.get(token_str(expr, left_var.get_var_name()))?;
let t2 = *var_types
.map
.get(token_str(expr, right_var.get_var_name()))?;

use crate::utils::compiler_const::*;
let left_var = as_variable(&var)?;
match right_token.syntax_kind {
SyntaxKind::GlobalVariable
if left_var.is_global()
&& t1 == TOKEN_INT
&& t2 == TOKEN_FLOAT =>
{
// var =# var // int = float
return op(OP_CSET_VAR_INT_TO_VAR_FLOAT);
}
SyntaxKind::GlobalVariable
if left_var.is_global()
&& t1 == TOKEN_FLOAT
&& t2 == TOKEN_INT =>
{
op(OP_CSET_VAR_FLOAT_TO_VAR_INT)
}
SyntaxKind::LocalVariable
if left_var.is_local()
&& t1 == TOKEN_INT
&& t2 == TOKEN_FLOAT =>
{
// lvar =# lvar // int = float
return op(OP_CSET_LVAR_INT_TO_LVAR_FLOAT)
.or(op(OP_CSET_VAR_INT_TO_VAR_FLOAT)); // vcs
}
SyntaxKind::LocalVariable
if left_var.is_local()
&& t1 == TOKEN_FLOAT
&& t2 == TOKEN_INT =>
{
// lvar =# lvar // float = int
return op(OP_CSET_LVAR_FLOAT_TO_LVAR_INT)
.or(op(OP_CSET_VAR_FLOAT_TO_VAR_INT)); // vcs
}
SyntaxKind::GlobalVariable
if left_var.is_local()
&& t1 == TOKEN_INT
&& t2 == TOKEN_FLOAT =>
{
// lvar =# var // int = float
return op(OP_CSET_LVAR_INT_TO_VAR_FLOAT)
.or(op(OP_CSET_VAR_INT_TO_VAR_FLOAT)); // vcs
}
SyntaxKind::GlobalVariable
if left_var.is_local()
&& t1 == TOKEN_FLOAT
&& t2 == TOKEN_INT =>
{
// lvar =# var // float = int
return op(OP_CSET_LVAR_FLOAT_TO_VAR_INT)
.or(op(OP_CSET_VAR_FLOAT_TO_VAR_INT)); // vcs
if right_var.is_global() {
if left_var.is_global() {
if t1 == TOKEN_INT && t2 == TOKEN_FLOAT {
// var =# var // int = float
return op(OP_CSET_VAR_INT_TO_VAR_FLOAT);
};
if t1 == TOKEN_FLOAT && t2 == TOKEN_INT {
// var =# var // float = int
return op(OP_CSET_VAR_FLOAT_TO_VAR_INT);
};
}
SyntaxKind::LocalVariable
if left_var.is_global()
&& t1 == TOKEN_INT
&& t2 == TOKEN_FLOAT =>
{
// var =# lvar // int = float
return op(OP_CSET_VAR_INT_TO_LVAR_FLOAT)
.or(op(OP_CSET_VAR_INT_TO_VAR_FLOAT)); // vcs

if left_var.is_local() {
if t1 == TOKEN_INT && t2 == TOKEN_FLOAT {
// lvar =# var // int = float
return op(OP_CSET_LVAR_INT_TO_VAR_FLOAT)
.or(op(OP_CSET_VAR_INT_TO_VAR_FLOAT));
}
if t1 == TOKEN_FLOAT && t2 == TOKEN_INT {
// lvar =# var // float = int
return op(OP_CSET_LVAR_FLOAT_TO_VAR_INT)
.or(op(OP_CSET_VAR_FLOAT_TO_VAR_INT));
}
}
SyntaxKind::LocalVariable
if left_var.is_global()
&& t1 == TOKEN_FLOAT
&& t2 == TOKEN_INT =>
{
// var =# lvar // float = int
return op(OP_CSET_VAR_FLOAT_TO_LVAR_INT)
.or(op(OP_CSET_VAR_FLOAT_TO_VAR_INT)); // vcs
}

if right_var.is_local() {
if left_var.is_local() {
if t1 == TOKEN_INT && t2 == TOKEN_FLOAT {
// lvar =# lvar // int = float
return op(OP_CSET_LVAR_INT_TO_LVAR_FLOAT)
.or(op(OP_CSET_VAR_INT_TO_VAR_FLOAT));
}

if t1 == TOKEN_FLOAT && t2 == TOKEN_INT {
// lvar =# lvar // float = int
return op(OP_CSET_LVAR_FLOAT_TO_LVAR_INT)
.or(op(OP_CSET_VAR_FLOAT_TO_VAR_INT));
}
}

_ => None,
if left_var.is_global() {
if t1 == TOKEN_INT && t2 == TOKEN_FLOAT {
// var =# lvar // int = float
return op(OP_CSET_VAR_INT_TO_LVAR_FLOAT)
.or(op(OP_CSET_VAR_INT_TO_VAR_FLOAT));
}

if t1 == TOKEN_FLOAT && t2 == TOKEN_INT {
// var =# lvar // float = int
return op(OP_CSET_VAR_FLOAT_TO_LVAR_INT)
.or(op(OP_CSET_VAR_FLOAT_TO_VAR_INT));
}
}
}

return None;
}
SyntaxKind::OperatorEqual => {
let left_var = as_variable(&var)?;
Expand Down

0 comments on commit 237a694

Please sign in to comment.