Add basic for loops

This commit is contained in:
Sofia 2026-03-18 20:39:00 +02:00
parent 954b8417b3
commit 3405f45169
5 changed files with 88 additions and 4 deletions

View File

@ -36,4 +36,10 @@ print(min(11, 9))
print(10 - 15) print(10 - 15)
print("hello there!") print("hello there!")
print(true or 0) print(true or 0)
print(123, f(10, 11, 12))
global value, table = f(10, 11, 12)
print("hello")
for i=1,10 do
print(table[i])
end

View File

@ -256,6 +256,13 @@ pub enum Statement {
Return(ExpressionList), Return(ExpressionList),
If(Node<Expression>, Block), If(Node<Expression>, Block),
Expression(Node<Expression>), Expression(Node<Expression>),
NumericalFor(
Node<String>,
Node<Expression>,
Node<Expression>,
Node<Expression>,
Block,
),
} }
impl Parse for Statement { impl Parse for Statement {
@ -316,6 +323,35 @@ impl Parse for Statement {
vec![(access.0, access.1.0)], vec![(access.0, access.1.0)],
ExpressionList(vec![expression]), ExpressionList(vec![expression]),
)) ))
} else if stream.peek() == Some(Token::Keyword(Keyword::For)) {
stream.next();
let counter_name = stream.parse()?;
stream.expect_symbol('=')?;
let init = stream.parse()?;
stream.expect_symbol(',')?;
let end = stream.parse()?;
let step = if let Some(Token::Symbol(',')) = stream.peek() {
stream.next();
stream.parse()?
} else {
Node {
kind: Expression::Literal(Literal::Integer(LuaInteger(1))),
meta: Metadata::empty(),
}
};
stream.expect(Token::Keyword(Keyword::Do))?;
let block = stream.parse()?;
stream.expect(Token::Keyword(Keyword::End))?;
Ok(Statement::NumericalFor(
counter_name,
init,
end,
step,
block,
))
} else if let Ok(expr) = stream.parse() { } else if let Ok(expr) = stream.parse() {
Ok(Self::Expression(expr)) Ok(Self::Expression(expr))
} else { } else {

View File

@ -154,6 +154,14 @@ impl Statement {
constants constants
} }
Statement::Expression(expr) => expr.kind.find_constants(scope), Statement::Expression(expr) => expr.kind.find_constants(scope),
Statement::NumericalFor(_, init, end, step, block) => {
let mut constants = HashSet::new();
constants.extend(init.kind.find_constants(scope));
constants.extend(end.kind.find_constants(scope));
constants.extend(step.kind.find_constants(scope));
constants.extend(block.find_constants(scope, Vec::new()));
constants
}
} }
} }
@ -332,8 +340,6 @@ impl Statement {
)); ));
} }
dbg!(&first_ret_register);
instructions.push(Instruction::Return( instructions.push(Instruction::Return(
first_ret_register, first_ret_register,
if vararg { if vararg {
@ -358,6 +364,36 @@ impl Statement {
let (instr, _) = expr.kind.compile(state, scope, None); let (instr, _) = expr.kind.compile(state, scope, None);
instructions.extend(instr); instructions.extend(instr);
} }
Statement::NumericalFor(counter, init, end, step, block) => {
let (instr, init_reg) = init.kind.compile(state, scope, Some(1));
instructions.extend(instr);
let (instr, end_reg) = end.kind.compile(state, scope, Some(1));
instructions.extend(instr);
let (instr, step_reg) = step.kind.compile(state, scope, Some(1));
instructions.extend(instr);
let init_reg = init_reg.first().unwrap();
let end_reg = end_reg.first().unwrap();
let step_reg = step_reg.first().unwrap();
scope.locals.insert(counter.kind.clone(), *init_reg);
scope.locals.insert("_END".to_owned(), *end_reg);
scope.locals.insert("_STEP".to_owned(), *step_reg);
let is_eql = scope.register_counter.next();
instructions.push(Instruction::LessThan(is_eql, *end_reg, *init_reg));
instructions.push(Instruction::Test(scope.register_counter.next(), is_eql, 1));
let mut inner_scope = scope.clone();
let instr = block.compile(state, &mut inner_scope);
let instr_len = instr.len() as i32;
instructions.push(Instruction::Jmp(instr_len + 2));
instructions.extend(instr);
instructions.push(Instruction::Add(*init_reg, *init_reg, *step_reg));
instructions.push(Instruction::Jmp(-(instr_len + 5)));
}
} }
for reg in 0..scope.register_counter.0 { for reg in 0..scope.register_counter.0 {

View File

@ -20,6 +20,8 @@ pub enum Keyword {
False, False,
Nil, Nil,
Not, Not,
For,
Do,
} }
impl Keyword { impl Keyword {
@ -36,6 +38,8 @@ impl Keyword {
"false" => Keyword::False, "false" => Keyword::False,
"nil" => Keyword::Nil, "nil" => Keyword::Nil,
"not" => Keyword::Not, "not" => Keyword::Not,
"for" => Keyword::For,
"do" => Keyword::Do,
_ => None?, _ => None?,
}) })
} }
@ -55,6 +59,8 @@ impl ToString for Keyword {
Keyword::False => "false", Keyword::False => "false",
Keyword::Nil => "nil", Keyword::Nil => "nil",
Keyword::Not => "not", Keyword::Not => "not",
Keyword::For => "for",
Keyword::Do => "do",
} }
.to_string() .to_string()
} }

View File

@ -888,7 +888,7 @@ impl ClosureRunner {
.map(|v| v.borrow().clone()) .map(|v| v.borrow().clone())
.unwrap_or(Value::Nil) .unwrap_or(Value::Nil)
{ {
Value::Float(val) => (val.lua_number().0 as u16) == *c, Value::Boolean(val) => (val.0 as u16) == *c,
_ => false, _ => false,
}; };
if is_true { if is_true {