Added non-newline print.

This commit is contained in:
Erin 2022-05-03 23:13:17 +02:00 committed by ondra05
parent ba4ba1f4fd
commit 8f98c24f68
3 changed files with 134 additions and 99 deletions

View file

@ -136,7 +136,10 @@ pub enum Stmt {
expr: Spanned<Expr>, expr: Spanned<Expr>,
args: Vec<Spanned<Expr>>, args: Vec<Spanned<Expr>>,
}, },
Print(Spanned<Expr>), Print {
expr: Spanned<Expr>,
newline: bool,
},
Read(Assignable), Read(Assignable),
Melo(Spanned<String>), Melo(Spanned<String>),
Rlyeh, Rlyeh,

View file

@ -214,8 +214,14 @@ impl ExecEnv {
/// Perform the action indicated by a statement. /// Perform the action indicated by a statement.
fn eval_stmt(&mut self, stmt: &Spanned<Stmt>) -> Result<HaltStatus, Error> { fn eval_stmt(&mut self, stmt: &Spanned<Stmt>) -> Result<HaltStatus, Error> {
match &stmt.item { match &stmt.item {
Stmt::Print(expr) => { Stmt::Print { expr, newline } => {
println!("{}", self.eval_expr(expr)?); let value = self.eval_expr(expr)?;
if *newline {
println!("{value}");
} else {
print!("{value}");
stdout().lock().flush()?;
}
} }
Stmt::Dim { ident, init } => { Stmt::Dim { ident, init } => {
let init = match init { let init = match init {

View file

@ -363,10 +363,24 @@ impl<'source> Parser<'source> {
match self.checked_next()? { match self.checked_next()? {
// Print to stdout // Print to stdout
Token::Print => { Token::Print => {
let stmt = Stmt::Print(buf.take().ok_or_else(|| { break Stmt::Print {
Error::new(ErrorKind::UnexpectedToken(Token::Print), self.lexer.span()) expr: buf.take().ok_or_else(|| {
})?); Error::new(ErrorKind::UnexpectedToken(Token::Print), self.lexer.span())
break self.semicolon_terminated(stmt)?; })?,
newline: match self.checked_next()? {
Token::Semicolon => true,
Token::Minus => {
self.require(Token::Semicolon)?;
false
}
token => {
return Err(Error::new(
ErrorKind::UnexpectedToken(token),
self.lexer.span(),
));
}
},
};
} }
// Functio call // Functio call
@ -642,40 +656,43 @@ mod tests {
fn simple_math() { fn simple_math() {
let code = "1 * (num + 3) / 666 print;"; let code = "1 * (num + 3) / 666 print;";
let expected = &[Spanned { let expected = &[Spanned {
item: Stmt::Print(Spanned { item: Stmt::Print {
item: Expr::BinOp { expr: Spanned {
lhs: Box::new(Spanned { item: Expr::BinOp {
item: Expr::BinOp { lhs: Box::new(Spanned {
lhs: Box::new(Spanned { item: Expr::BinOp {
item: Expr::Literal(Literal::Int(1)), lhs: Box::new(Spanned {
span: 0..1, item: Expr::Literal(Literal::Int(1)),
}), span: 0..1,
rhs: Box::new(Spanned { }),
item: Expr::BinOp { rhs: Box::new(Spanned {
lhs: Box::new(Spanned { item: Expr::BinOp {
item: Expr::Variable("num".to_owned()), lhs: Box::new(Spanned {
span: 5..6, item: Expr::Variable("num".to_owned()),
}), span: 5..6,
rhs: Box::new(Spanned { }),
item: Expr::Literal(Literal::Int(3)), rhs: Box::new(Spanned {
span: 9..10, item: Expr::Literal(Literal::Int(3)),
}), span: 9..10,
kind: BinOpKind::Add, }),
}, kind: BinOpKind::Add,
span: 5..10, },
}), span: 5..10,
kind: BinOpKind::Multiply, }),
}, kind: BinOpKind::Multiply,
span: 0..11, },
}), span: 0..11,
rhs: Box::new(Spanned { }),
item: Expr::Literal(Literal::Int(666)), rhs: Box::new(Spanned {
span: 14..17, item: Expr::Literal(Literal::Int(666)),
}), span: 14..17,
kind: BinOpKind::Divide, }),
kind: BinOpKind::Divide,
},
span: 0..17,
}, },
span: 0..17, newline: true,
}), },
span: 0..24, span: 0..24,
}]; }];
@ -724,10 +741,13 @@ mod tests {
span: 8..21, span: 8..21,
}, },
body: vec![Spanned { body: vec![Spanned {
item: Stmt::Print(Spanned { item: Stmt::Print {
item: Expr::Literal(Literal::Str("Buy Able products!".to_owned())), expr: Spanned {
span: 25..47, item: Expr::Literal(Literal::Str("Buy Able products!".to_owned())),
}), span: 25..47,
},
newline: true,
},
span: 25..54, span: 25..54,
}], }],
}, },
@ -773,41 +793,44 @@ mod tests {
fn cart_construction() { fn cart_construction() {
let code = "[/*able*/ <= 1, /*script*/ <= 3 - 1] print;"; let code = "[/*able*/ <= 1, /*script*/ <= 3 - 1] print;";
let expected = &[Spanned { let expected = &[Spanned {
item: Stmt::Print(Spanned { item: Stmt::Print {
item: Expr::Cart(vec![ expr: Spanned {
( item: Expr::Cart(vec![
Spanned { (
item: Expr::Literal(Literal::Str("able".to_owned())), Spanned {
span: 1..7, item: Expr::Literal(Literal::Str("able".to_owned())),
}, span: 1..7,
Spanned {
item: Expr::Literal(Literal::Int(1)),
span: 11..12,
},
),
(
Spanned {
item: Expr::Literal(Literal::Str("script".to_owned())),
span: 14..22,
},
Spanned {
item: Expr::BinOp {
kind: BinOpKind::Subtract,
lhs: Box::new(Spanned {
item: Expr::Literal(Literal::Int(3)),
span: 26..27,
}),
rhs: Box::new(Spanned {
item: Expr::Literal(Literal::Int(1)),
span: 30..31,
}),
}, },
span: 26..31, Spanned {
}, item: Expr::Literal(Literal::Int(1)),
), span: 11..12,
]), },
span: 0..32, ),
}), (
Spanned {
item: Expr::Literal(Literal::Str("script".to_owned())),
span: 14..22,
},
Spanned {
item: Expr::BinOp {
kind: BinOpKind::Subtract,
lhs: Box::new(Spanned {
item: Expr::Literal(Literal::Int(3)),
span: 26..27,
}),
rhs: Box::new(Spanned {
item: Expr::Literal(Literal::Int(1)),
span: 30..31,
}),
},
span: 26..31,
},
),
]),
span: 0..32,
},
newline: true,
},
span: 0..39, span: 0..39,
}]; }];
@ -819,28 +842,31 @@ mod tests {
fn cart_index() { fn cart_index() {
let code = "[/*able*/ <= /*ablecorp*/][/*ablecorp*/] print;"; let code = "[/*able*/ <= /*ablecorp*/][/*ablecorp*/] print;";
let expected = &[Spanned { let expected = &[Spanned {
item: Stmt::Print(Spanned { item: Stmt::Print {
item: Expr::Index { expr: Spanned {
expr: Box::new(Spanned { item: Expr::Index {
item: Expr::Cart(vec![( expr: Box::new(Spanned {
Spanned { item: Expr::Cart(vec![(
item: Expr::Literal(Literal::Str("able".to_owned())), Spanned {
span: 1..7, item: Expr::Literal(Literal::Str("able".to_owned())),
}, span: 1..7,
Spanned { },
item: Expr::Literal(Literal::Str("ablecorp".to_owned())), Spanned {
span: 11..21, item: Expr::Literal(Literal::Str("ablecorp".to_owned())),
}, span: 11..21,
)]), },
span: 0..22, )]),
}), span: 0..22,
index: Box::new(Spanned { }),
item: Expr::Literal(Literal::Str("ablecorp".to_owned())), index: Box::new(Spanned {
span: 23..33, item: Expr::Literal(Literal::Str("ablecorp".to_owned())),
}), span: 23..33,
}),
},
span: 0..34,
}, },
span: 0..34, newline: true,
}), },
span: 0..41, span: 0..41,
}]; }];