CLIPPY IS GOD.
This commit is contained in:
parent
2f0798bfe1
commit
a317e54426
3 changed files with 28 additions and 45 deletions
|
@ -18,7 +18,7 @@ pub enum StmtNode {
|
||||||
/// The print statement
|
/// The print statement
|
||||||
Print(ExprNode),
|
Print(ExprNode),
|
||||||
/// A block containing multiple statements.
|
/// A block containing multiple statements.
|
||||||
Block(Vec<Box<StmtNode>>),
|
Block(Vec<StmtNode>),
|
||||||
/// A conditional statement.
|
/// A conditional statement.
|
||||||
IfStmt {
|
IfStmt {
|
||||||
condition: ExprNode,
|
condition: ExprNode,
|
||||||
|
@ -100,7 +100,7 @@ impl AstDumper for StmtNode {
|
||||||
match self {
|
match self {
|
||||||
Self::VarDecl(name, Some(expr)) => format!("( var {} {} )", name.lexeme, expr.dump()),
|
Self::VarDecl(name, Some(expr)) => format!("( var {} {} )", name.lexeme, expr.dump()),
|
||||||
Self::VarDecl(name, None) => format!("( var {} nil )", name.lexeme),
|
Self::VarDecl(name, None) => format!("( var {} nil )", name.lexeme),
|
||||||
Self::Expression(expr) => format!("{}", expr.dump()),
|
Self::Expression(expr) => expr.dump(),
|
||||||
Self::Print(expr) => format!("(print {})", expr.dump()),
|
Self::Print(expr) => format!("(print {})", expr.dump()),
|
||||||
|
|
||||||
Self::Block(stmts) => format!(
|
Self::Block(stmts) => format!(
|
||||||
|
|
|
@ -39,9 +39,9 @@ impl Default for InterpreterFlowControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<InterpreterFlowControl> for Value {
|
impl From<Value> for InterpreterFlowControl {
|
||||||
fn into(self: Self) -> InterpreterFlowControl {
|
fn from(value: Value) -> Self {
|
||||||
InterpreterFlowControl::Result(self)
|
Self::Result(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ impl Interpretable for ast::StmtNode {
|
||||||
label,
|
label,
|
||||||
condition,
|
condition,
|
||||||
body,
|
body,
|
||||||
after_body
|
after_body,
|
||||||
} => self.on_loop_statement(environment, label, condition, body, after_body),
|
} => self.on_loop_statement(environment, label, condition, body, after_body),
|
||||||
ast::StmtNode::LoopControlStmt {
|
ast::StmtNode::LoopControlStmt {
|
||||||
is_break,
|
is_break,
|
||||||
|
@ -139,11 +139,7 @@ impl ast::StmtNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute the contents of a block.
|
/// Execute the contents of a block.
|
||||||
fn on_block(
|
fn on_block(&self, environment: &EnvironmentRef, stmts: &[ast::StmtNode]) -> InterpreterResult {
|
||||||
&self,
|
|
||||||
environment: &EnvironmentRef,
|
|
||||||
stmts: &Vec<Box<ast::StmtNode>>,
|
|
||||||
) -> InterpreterResult {
|
|
||||||
let child = Environment::create_child(environment);
|
let child = Environment::create_child(environment);
|
||||||
for stmt in stmts.iter() {
|
for stmt in stmts.iter() {
|
||||||
let result = stmt.interprete(&child)?;
|
let result = stmt.interprete(&child)?;
|
||||||
|
@ -180,10 +176,7 @@ impl ast::StmtNode {
|
||||||
body: &ast::StmtNode,
|
body: &ast::StmtNode,
|
||||||
after_body: &Option<Box<ast::StmtNode>>,
|
after_body: &Option<Box<ast::StmtNode>>,
|
||||||
) -> InterpreterResult {
|
) -> InterpreterResult {
|
||||||
let ln = match label {
|
let ln = label.as_ref().map(|token| token.lexeme.clone());
|
||||||
None => None,
|
|
||||||
Some(token) => Some(token.lexeme.clone()),
|
|
||||||
};
|
|
||||||
while condition.interprete(environment)?.result().is_truthy() {
|
while condition.interprete(environment)?.result().is_truthy() {
|
||||||
let result = body.interprete(environment)?;
|
let result = body.interprete(environment)?;
|
||||||
match &result {
|
match &result {
|
||||||
|
@ -211,10 +204,7 @@ impl ast::StmtNode {
|
||||||
is_break: bool,
|
is_break: bool,
|
||||||
label: &Option<Token>,
|
label: &Option<Token>,
|
||||||
) -> InterpreterResult {
|
) -> InterpreterResult {
|
||||||
let name = match label {
|
let name = label.as_ref().map(|token| token.lexeme.clone());
|
||||||
None => None,
|
|
||||||
Some(token) => Some(token.lexeme.clone()),
|
|
||||||
};
|
|
||||||
if is_break {
|
if is_break {
|
||||||
Ok(InterpreterFlowControl::Break(name))
|
Ok(InterpreterFlowControl::Break(name))
|
||||||
} else {
|
} else {
|
||||||
|
@ -263,9 +253,9 @@ impl ast::ExprNode {
|
||||||
right: &ast::ExprNode,
|
right: &ast::ExprNode,
|
||||||
) -> InterpreterResult {
|
) -> InterpreterResult {
|
||||||
let left_value = left.interprete(environment)?.result();
|
let left_value = left.interprete(environment)?.result();
|
||||||
if operator.token_type == TokenType::Or && left_value.is_truthy() {
|
if operator.token_type == TokenType::Or && left_value.is_truthy()
|
||||||
Ok(left_value.into())
|
|| operator.token_type == TokenType::And && !left_value.is_truthy()
|
||||||
} else if operator.token_type == TokenType::And && !left_value.is_truthy() {
|
{
|
||||||
Ok(left_value.into())
|
Ok(left_value.into())
|
||||||
} else {
|
} else {
|
||||||
right.interprete(environment)
|
right.interprete(environment)
|
||||||
|
|
|
@ -15,17 +15,17 @@ pub struct Parser {
|
||||||
/// The state of the parser regarding loops. We may be parsing an unnamed or
|
/// The state of the parser regarding loops. We may be parsing an unnamed or
|
||||||
/// named loop, or we might not be parsing a loop at all.
|
/// named loop, or we might not be parsing a loop at all.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum LoopParsingState {
|
enum LoopParsingState {
|
||||||
NoLoop,
|
None,
|
||||||
UnnamedLoop,
|
Unnamed,
|
||||||
NamedLoop(String),
|
Named(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Option<Token>> for LoopParsingState {
|
impl From<&Option<Token>> for LoopParsingState {
|
||||||
fn from(value: &Option<Token>) -> Self {
|
fn from(value: &Option<Token>) -> Self {
|
||||||
match &value {
|
match &value {
|
||||||
None => LoopParsingState::UnnamedLoop,
|
None => LoopParsingState::Unnamed,
|
||||||
Some(name) => LoopParsingState::NamedLoop(name.lexeme.clone()),
|
Some(name) => LoopParsingState::Named(name.lexeme.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ impl Parser {
|
||||||
/// Parse the tokens into an AST and return it, or return nothing if a
|
/// Parse the tokens into an AST and return it, or return nothing if a
|
||||||
/// parser error occurs.
|
/// parser error occurs.
|
||||||
pub fn parse(mut self, err_hdl: &mut ErrorHandler) -> Option<ast::ProgramNode> {
|
pub fn parse(mut self, err_hdl: &mut ErrorHandler) -> Option<ast::ProgramNode> {
|
||||||
self.loop_state.push(LoopParsingState::NoLoop);
|
self.loop_state.push(LoopParsingState::None);
|
||||||
let result = self.parse_program(err_hdl);
|
let result = self.parse_program(err_hdl);
|
||||||
self.loop_state.pop();
|
self.loop_state.pop();
|
||||||
result
|
result
|
||||||
|
@ -172,10 +172,9 @@ impl Parser {
|
||||||
/// block := "{" statement* "}"
|
/// block := "{" statement* "}"
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_block(&mut self) -> ParserResult<ast::StmtNode> {
|
fn parse_block(&mut self) -> ParserResult<ast::StmtNode> {
|
||||||
let mut stmts: Vec<Box<ast::StmtNode>> = Vec::new();
|
let mut stmts: Vec<ast::StmtNode> = Vec::new();
|
||||||
while !(self.check(&TokenType::RightBrace) || self.is_at_end()) {
|
while !(self.check(&TokenType::RightBrace) || self.is_at_end()) {
|
||||||
let stmt = self.parse_statement()?;
|
stmts.push(self.parse_statement()?);
|
||||||
stmts.push(Box::new(stmt));
|
|
||||||
}
|
}
|
||||||
self.consume(&TokenType::RightBrace, "expected '}' after block.")?;
|
self.consume(&TokenType::RightBrace, "expected '}' after block.")?;
|
||||||
Ok(ast::StmtNode::Block(stmts))
|
Ok(ast::StmtNode::Block(stmts))
|
||||||
|
@ -314,16 +313,10 @@ impl Parser {
|
||||||
label,
|
label,
|
||||||
condition,
|
condition,
|
||||||
body: Box::new(body_stmt),
|
body: Box::new(body_stmt),
|
||||||
after_body: match increment {
|
after_body: increment.map(|incr| Box::new(ast::StmtNode::Expression(incr))),
|
||||||
Some(incr) => Some(Box::new(ast::StmtNode::Expression(incr))),
|
|
||||||
None => None,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
if let Some(init_stmt) = initializer {
|
if let Some(init_stmt) = initializer {
|
||||||
Ok(ast::StmtNode::Block(vec![
|
Ok(ast::StmtNode::Block(vec![init_stmt, while_stmt]))
|
||||||
Box::new(init_stmt),
|
|
||||||
Box::new(while_stmt),
|
|
||||||
]))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(while_stmt)
|
Ok(while_stmt)
|
||||||
}
|
}
|
||||||
|
@ -335,7 +328,7 @@ impl Parser {
|
||||||
/// loop_control_statement := "continue" ( IDENTIFIER )? ";"
|
/// loop_control_statement := "continue" ( IDENTIFIER )? ";"
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_loop_control_statement(&mut self, stmt_token: &Token) -> ParserResult<ast::StmtNode> {
|
fn parse_loop_control_statement(&mut self, stmt_token: &Token) -> ParserResult<ast::StmtNode> {
|
||||||
if self.loop_state() == &LoopParsingState::NoLoop {
|
if self.loop_state() == &LoopParsingState::None {
|
||||||
return Err(ParserError::new(
|
return Err(ParserError::new(
|
||||||
stmt_token,
|
stmt_token,
|
||||||
&format!(
|
&format!(
|
||||||
|
@ -629,10 +622,10 @@ impl Parser {
|
||||||
let mut pos = self.loop_state.len() - 1;
|
let mut pos = self.loop_state.len() - 1;
|
||||||
loop {
|
loop {
|
||||||
match &self.loop_state[pos] {
|
match &self.loop_state[pos] {
|
||||||
LoopParsingState::NoLoop => break,
|
LoopParsingState::None => break,
|
||||||
LoopParsingState::UnnamedLoop => (),
|
LoopParsingState::Unnamed => (),
|
||||||
LoopParsingState::NamedLoop(n) if n == name => return true,
|
LoopParsingState::Named(n) if n == name => return true,
|
||||||
LoopParsingState::NamedLoop(_) => (),
|
LoopParsingState::Named(_) => (),
|
||||||
}
|
}
|
||||||
pos -= 1;
|
pos -= 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue