Add while-loop

This commit is contained in:
Sofia 2026-03-19 21:29:52 +02:00
parent 4c9b9085fd
commit 42164ef6fe
4 changed files with 63 additions and 57 deletions

View File

@ -1,59 +1,8 @@
global b = 5
function add(x)
return function (y)
x = x + 1
b = b + 1
return x + y, 1, 2, b
end
local i = 0
print("before")
while i < 10 do
i = i + 1
print(i)
end
function min(x, y)
local m = x
if y < x then
m = y
end
return m
end
function f(x, ...)
local b = {10, ..., add(10)(15)}
return x + 5, b
end
global sometable = {}
sometable["hello"] = { 100, 150, add(10)(15) }
print(#sometable["hello"])
sometable["hello"].there = "my dude"
print(sometable.hello.there)
print(max(11.12345, 9))
print(add(10)(15))
print(add(10)(15))
print(b)
print(min(11, 9))
print(10 - 15)
print("hello there!")
print(true or 0)
global value, table = f(10, 11, 12)
print("hello")
for i=1,#table do
print(table[i])
if i > 2 then
goto test
end
end
::test::
local test = table[1]
if test == 10 then
print("first")
elseif test == 11 then
print("second")
else
print("third")
end
print("after")
print("after")

View File

@ -271,6 +271,8 @@ pub enum Statement {
Node<Expression>,
Block,
),
While(Node<Expression>, Block),
Repeat(Block, Node<Expression>),
Break,
Label(Node<String>),
GoTo(Node<String>),
@ -400,6 +402,19 @@ impl Parse for Statement {
step,
block,
))
} else if let Some(Token::Keyword(Keyword::While)) = stream.peek() {
stream.next();
let expr = stream.parse()?;
stream.expect(Token::Keyword(Keyword::Do))?;
let block = stream.parse()?;
stream.expect(Token::Keyword(Keyword::End))?;
Ok(Statement::While(expr, block))
} else if let Some(Token::Keyword(Keyword::Repeat)) = stream.peek() {
stream.next();
let block = stream.parse()?;
stream.expect(Token::Keyword(Keyword::Until))?;
let expr = stream.parse()?;
Ok(Statement::Repeat(block, expr))
} else if let Ok(expr) = stream.parse() {
Ok(Self::Expression(expr))
} else if let Some(Token::Keyword(Keyword::Break)) = stream.peek() {

View File

@ -207,6 +207,18 @@ impl Statement {
constants.extend(block.find_constants(scope, Vec::new()));
constants
}
Statement::While(node, block) => {
let mut constants = HashSet::new();
constants.extend(node.kind.find_constants(scope));
constants.extend(block.find_constants(scope, Vec::new()));
constants
}
Statement::Repeat(block, node) => {
let mut constants = HashSet::new();
constants.extend(node.kind.find_constants(scope));
constants.extend(block.find_constants(scope, Vec::new()));
constants
}
Statement::Break => HashSet::new(),
Statement::Label(_) => HashSet::new(),
Statement::GoTo(_) => HashSet::new(),
@ -469,6 +481,27 @@ impl Statement {
)));
instructions.push(PreInstr::Instr(Instruction::Jmp(-(instr_len + 4))));
}
Statement::While(expr, block) => {
let (instr, expr_regs) = expr.kind.compile(state, scope, Some(1));
let expr_instr_len = instr.len() as i32;
instructions.extend(instr);
instructions.push(PreInstr::Instr(Instruction::Test(
scope.register_counter.next(),
*expr_regs.first().unwrap(),
0,
)));
let block_instructions = block.compile(state, scope);
let block_instr_len = block_instructions.len() as i32;
instructions.push(PreInstr::Instr(Instruction::Jmp(block_instr_len + 1)));
instructions.extend(block_instructions);
instructions.push(PreInstr::Instr(Instruction::Jmp(
-(block_instr_len + expr_instr_len + 2),
)));
}
Statement::Repeat(block, expr) => todo!(),
Statement::Break => instructions.push(PreInstr::Break),
Statement::Label(node) => instructions.push(PreInstr::Label(node.kind.clone())),
Statement::GoTo(node) => instructions.push(PreInstr::GoTo(node.kind.clone())),

View File

@ -23,6 +23,9 @@ pub enum Keyword {
Nil,
Not,
For,
While,
Repeat,
Until,
Do,
Break,
GoTo,
@ -48,6 +51,9 @@ impl Keyword {
"do" => Keyword::Do,
"break" => Keyword::Break,
"goto" => Keyword::GoTo,
"while" => Keyword::While,
"repeat" => Keyword::Repeat,
"until" => Keyword::Until,
_ => None?,
})
}
@ -70,6 +76,9 @@ impl ToString for Keyword {
Keyword::Nil => "nil",
Keyword::Not => "not",
Keyword::For => "for",
Keyword::While => "while",
Keyword::Repeat => "repeat",
Keyword::Until => "until",
Keyword::Do => "do",
Keyword::Break => "break",
Keyword::GoTo => "goto",