Allow endless loops with no condition

This commit is contained in:
Daniel M 2022-02-10 20:36:26 +01:00
parent 2880ba81ab
commit 3806a61756
4 changed files with 36 additions and 26 deletions

View File

@ -101,7 +101,7 @@ pub enum Expression {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Loop {
/// The condition that determines if the loop should continue
pub condition: Expression,
pub condition: Option<Expression>,
/// This is executed after each loop to advance the condition variables
pub advancement: Option<Expression>,
/// The loop body that is executed each loop
@ -126,12 +126,19 @@ pub struct FunDecl {
pub body: Rc<BlockScope>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct VarDecl {
pub name: Sid,
pub var_stackpos: usize,
pub rhs: Expression,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Statement {
Return(Expression),
Break,
Continue,
Declaration(Sid, usize, Expression),
Declaration(VarDecl),
FunDeclare(FunDecl),
Expr(Expression),
Block(BlockScope),

View File

@ -1,4 +1,4 @@
use crate::ast::{Ast, BlockScope, Expression, If, Loop, Statement, BinOpType, UnOpType};
use crate::ast::{Ast, BlockScope, Expression, If, Loop, Statement, BinOpType, UnOpType, VarDecl};
pub trait AstOptimizer {
fn optimize(ast: Ast) -> Ast;
@ -24,7 +24,9 @@ impl SimpleAstOptimizer {
advancement,
body,
}) => {
if let Some(condition) = condition {
Self::optimize_expr(condition);
}
if let Some(advancement) = advancement {
Self::optimize_expr(advancement)
}
@ -40,7 +42,7 @@ impl SimpleAstOptimizer {
Self::optimize_block(body_false);
}
Statement::Print(expr) => Self::optimize_expr(expr),
Statement::Declaration(_, _, expr) => Self::optimize_expr(expr),
Statement::Declaration(VarDecl { name: _, var_stackpos: _, rhs}) => Self::optimize_expr(rhs),
Statement::FunDeclare(_) => (),
Statement::Return(expr) => Self::optimize_expr(expr),
Statement::Break | Statement::Continue => (),

View File

@ -155,8 +155,8 @@ impl Interpreter {
self.resolve_expr(expr)?;
}
Statement::Declaration(_sid, _idx, rhs) => {
let rhs = self.resolve_expr(rhs)?;
Statement::Declaration(decl) => {
let rhs = self.resolve_expr(&decl.rhs)?;
self.vartable.push(rhs);
}
@ -172,9 +172,11 @@ impl Interpreter {
Statement::Loop(looop) => {
// loop runs as long condition != 0
loop {
if matches!(self.resolve_expr(&looop.condition)?, Value::I64(0)) {
if let Some(condition) = &looop.condition {
if matches!(self.resolve_expr(condition)?, Value::I64(0)) {
break;
}
}
let be = self.run_block(&looop.body)?;
match be {

View File

@ -1,7 +1,7 @@
use thiserror::Error;
use crate::{
ast::{Ast, BlockScope, Expression, FunDecl, If, Loop, Statement},
ast::{Ast, BlockScope, Expression, FunDecl, If, Loop, Statement, VarDecl},
stringstore::{Sid, StringStore},
token::Token,
util::{PutBackIter, PutBackableExt},
@ -223,7 +223,11 @@ impl<T: Iterator<Item = Token>> Parser<T> {
let sp = self.var_stack.len();
self.var_stack.push(sid);
Statement::Declaration(sid, sp, rhs)
Statement::Declaration(VarDecl {
name: sid,
var_stackpos: sp,
rhs,
})
}
(first, _) => {
self.putback(first);
@ -275,26 +279,21 @@ impl<T: Iterator<Item = Token>> Parser<T> {
fn parse_loop(&mut self) -> ResPE<Loop> {
validate_next!(self, T![loop], "loop");
let condition = self.parse_expr()?;
let mut condition = None;
let mut advancement = None;
let body;
if !matches!(self.peek(), T!['{']) {
condition = Some(self.parse_expr()?);
match self.next() {
T!['{'] => {
body = self.parse_scoped_block()?;
}
T![;] => {
if matches!(self.peek(), T![;]) {
self.next();
advancement = Some(self.parse_expr()?);
}
}
validate_next!(self, T!['{'], "{");
body = self.parse_scoped_block()?;
}
tok => return Err(ParseErr::UnexpectedToken(tok, ";\" or \"{".to_string())),
}
let body = self.parse_scoped_block()?;
validate_next!(self, T!['}'], "}");