Add basic for loops
This commit is contained in:
parent
954b8417b3
commit
3405f45169
@ -36,4 +36,10 @@ print(min(11, 9))
|
||||
print(10 - 15)
|
||||
print("hello there!")
|
||||
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
|
||||
36
src/ast.rs
36
src/ast.rs
@ -256,6 +256,13 @@ pub enum Statement {
|
||||
Return(ExpressionList),
|
||||
If(Node<Expression>, Block),
|
||||
Expression(Node<Expression>),
|
||||
NumericalFor(
|
||||
Node<String>,
|
||||
Node<Expression>,
|
||||
Node<Expression>,
|
||||
Node<Expression>,
|
||||
Block,
|
||||
),
|
||||
}
|
||||
|
||||
impl Parse for Statement {
|
||||
@ -316,6 +323,35 @@ impl Parse for Statement {
|
||||
vec![(access.0, access.1.0)],
|
||||
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() {
|
||||
Ok(Self::Expression(expr))
|
||||
} else {
|
||||
|
||||
@ -154,6 +154,14 @@ impl Statement {
|
||||
constants
|
||||
}
|
||||
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(
|
||||
first_ret_register,
|
||||
if vararg {
|
||||
@ -358,6 +364,36 @@ impl Statement {
|
||||
let (instr, _) = expr.kind.compile(state, scope, None);
|
||||
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 {
|
||||
|
||||
@ -20,6 +20,8 @@ pub enum Keyword {
|
||||
False,
|
||||
Nil,
|
||||
Not,
|
||||
For,
|
||||
Do,
|
||||
}
|
||||
|
||||
impl Keyword {
|
||||
@ -36,6 +38,8 @@ impl Keyword {
|
||||
"false" => Keyword::False,
|
||||
"nil" => Keyword::Nil,
|
||||
"not" => Keyword::Not,
|
||||
"for" => Keyword::For,
|
||||
"do" => Keyword::Do,
|
||||
_ => None?,
|
||||
})
|
||||
}
|
||||
@ -55,6 +59,8 @@ impl ToString for Keyword {
|
||||
Keyword::False => "false",
|
||||
Keyword::Nil => "nil",
|
||||
Keyword::Not => "not",
|
||||
Keyword::For => "for",
|
||||
Keyword::Do => "do",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user