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(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
|
||||||
36
src/ast.rs
36
src/ast.rs
@ -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 {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user