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)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct Loop { pub struct Loop {
/// The condition that determines if the loop should continue /// 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 /// This is executed after each loop to advance the condition variables
pub advancement: Option<Expression>, pub advancement: Option<Expression>,
/// The loop body that is executed each loop /// The loop body that is executed each loop
@ -126,12 +126,19 @@ pub struct FunDecl {
pub body: Rc<BlockScope>, 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)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum Statement { pub enum Statement {
Return(Expression), Return(Expression),
Break, Break,
Continue, Continue,
Declaration(Sid, usize, Expression), Declaration(VarDecl),
FunDeclare(FunDecl), FunDeclare(FunDecl),
Expr(Expression), Expr(Expression),
Block(BlockScope), 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 { pub trait AstOptimizer {
fn optimize(ast: Ast) -> Ast; fn optimize(ast: Ast) -> Ast;
@ -24,7 +24,9 @@ impl SimpleAstOptimizer {
advancement, advancement,
body, body,
}) => { }) => {
Self::optimize_expr(condition); if let Some(condition) = condition {
Self::optimize_expr(condition);
}
if let Some(advancement) = advancement { if let Some(advancement) = advancement {
Self::optimize_expr(advancement) Self::optimize_expr(advancement)
} }
@ -40,7 +42,7 @@ impl SimpleAstOptimizer {
Self::optimize_block(body_false); Self::optimize_block(body_false);
} }
Statement::Print(expr) => Self::optimize_expr(expr), 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::FunDeclare(_) => (),
Statement::Return(expr) => Self::optimize_expr(expr), Statement::Return(expr) => Self::optimize_expr(expr),
Statement::Break | Statement::Continue => (), Statement::Break | Statement::Continue => (),

View File

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

View File

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