Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions crates/dreamchecker/tests/branch_eval_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,27 +119,10 @@ fn for_kv_check() {
check_errors_match(code, NO_ERRORS);
}

pub const FOR_KV_VAR_ERROR: &[(u32, u16, &str)] =
&[(3, 19, "for (var/key, value) requires a 'var' keyword")];

#[test]
fn for_kv_var_check() {
let code = r##"
/proc/test()
var/alist/A = alist()
for (k, v in A)
world.log << k
world.log << v

"##
.trim();
check_errors_match(code, FOR_KV_VAR_ERROR);
}

pub const FOR_KV_VALUE_ERROR: &[(u32, u16, &str)] = &[(
3,
23,
"value must be a variable in a for (var/key, value) statement",
"value must be a variable in a for (key, value) statement",
)];

#[test]
Expand All @@ -157,7 +140,7 @@ fn for_kv_value_check() {
pub const FOR_KV_KEY_ERROR: &[(u32, u16, &str)] = &[(
3,
27,
"cannot assigned a value to var/key in a for(var/key, value) statement",
"cannot assigned a value to key in a for(key, value) statement",
)];

#[test]
Expand Down
20 changes: 11 additions & 9 deletions crates/dreammaker/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1603,36 +1603,38 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> {
// for (..., ... in ...)
match test {
// This should necessarily be caught because the expression is going be
//for(var/k, [v in x]) and [v in x] will be passed as BinaryOp::In
//for(k, [v in x]) and [v in x] will be passed as BinaryOp::In
// This is a bit ugly but it workss
Some(Expression::BinaryOp {
op: BinaryOp::In,
lhs,
rhs,
}) => {
// First thing first: for (var/k, v in x) REQUIRES the var/k.
// This unboxes it and rejects other type for(x, [...]), for(0, [...])
// Just... throws an error and pulls some type info if it's there
let (var_type, key) = match init {
// this is a really terrible way to do this
Some(Statement::Var(var_statement)) => match var_statement.value {
None => (Some(var_statement.var_type), var_statement.name),
_ => return Err(self.error("cannot assigned a value to var/key in a for(var/key, value) statement")),
_ => return Err(self.error("cannot assigned a value to key in a for(key, value) statement")),
},
_ => return Err(self.error("for (var/key, value) requires a 'var' keyword")),
Some(Statement::Expr(expr)) => match expr.into_term() {
Some(Term::Ident(name)) => (None, name),
_ => return Err(self.error("for-list must start with variable")),
},
_ => return Err(self.error("for-list must start with variable")),
};
// Value is the lhs of for(var/k, [v in x])
// Value is the lhs of for(k, [v in x])
// It should also pass only if it's an ident
let value = match lhs.into_term() {
Some(Term::Ident(value)) => value,
_ => return Err(self.error(
"value must be a variable in a for (var/key, value) statement",
"value must be a variable in a for (key, value) statement",
)),
};
// TODO : check if `x` is an ident/a "list()" or "alist()" statement ?
require!(self.exact(Token::Punct(Punctuation::RParen)));
// Returns a for(k,v)
spanned(Statement::ForKeyValue(Box::new(ForKeyValueStatement {
var_type: Some(var_type.expect("/")),
var_type: var_type,
key,
key_input_type,
value,
Expand Down