diff options
| -rw-r--r-- | src/interpret/mod.rs | 4 | ||||
| -rw-r--r-- | src/interpret/scope.rs | 45 | ||||
| -rw-r--r-- | src/interpret/value.rs | 181 | ||||
| -rw-r--r-- | src/interpret/walker.rs | 225 | ||||
| -rw-r--r-- | src/parse/ast/expression.rs | 38 | ||||
| -rw-r--r-- | src/parse/ast/mod.rs | 2 | ||||
| -rw-r--r-- | src/parse/ast/nodes.rs (renamed from src/parse/ast/value.rs) | 36 | ||||
| -rw-r--r-- | src/parse/ast/statement.rs | 2 | ||||
| -rw-r--r-- | src/parse/parser.rs | 33 |
9 files changed, 387 insertions, 179 deletions
diff --git a/src/interpret/mod.rs b/src/interpret/mod.rs index 2544ca3..813f45d 100644 --- a/src/interpret/mod.rs +++ b/src/interpret/mod.rs @@ -1 +1,3 @@ -pub mod walker; \ No newline at end of file +mod scope; +mod value; +pub mod walker; diff --git a/src/interpret/scope.rs b/src/interpret/scope.rs new file mode 100644 index 0000000..de32692 --- /dev/null +++ b/src/interpret/scope.rs @@ -0,0 +1,45 @@ +use super::value::Value; +use crate::parse::ast::nodes::Identifier; +use std::collections::HashMap; + +pub struct Scope { + scopes: Vec<HashMap<Identifier, Value>>, +} + +impl Scope { + pub fn new() -> Self { + Scope { scopes: Vec::new() } + } + + pub fn nest(&mut self) { + self.scopes.push(HashMap::new()); + } + + pub fn unnest(&mut self) { + self.scopes.pop(); + } + + pub fn set_var(&mut self, ident: &Identifier, value: Value) { + for scope in self.scopes.iter_mut() { + if scope.contains_key(ident) { + scope.insert(ident.clone(), value); + return; + } + } + + let inner_scope = self + .scopes + .last_mut() + .expect("Tried accessing scope after last frame is gone."); + inner_scope.insert(ident.clone(), value); + } + + pub fn get_var(&self, ident: &Identifier) -> Option<Value> { + for scope in self.scopes.iter().rev() { + if let Some(value) = scope.get(ident) { + return Some(value.clone()); + } + } + None + } +} diff --git a/src/interpret/value.rs b/src/interpret/value.rs new file mode 100644 index 0000000..0c7843c --- /dev/null +++ b/src/interpret/value.rs @@ -0,0 +1,181 @@ +use crate::parse::ast::nodes::FnNode; +use anyhow::{anyhow, Result}; +use std::{cell::RefCell, rc::Rc}; + +type Ref<T> = RefCell<Rc<T>>; + +#[derive(Clone, Debug)] +pub enum Value { + Str(String), + Float(f64), + Int(i64), + Fn(Ref<FnNode>), + Void, +} + +impl Value { + pub fn add(self, rhs: Value) -> Result<Value> { + match self { + Value::Str(l) => match rhs { + Value::Str(r) => Ok(Value::Str(l + &r)), + Value::Float(r) => Ok(Value::Str(l + &r.to_string())), + Value::Int(r) => Ok(Value::Str(l + &r.to_string())), + _ => Err(anyhow!("Right operand can't be added.")), + }, + Value::Float(l) => match rhs { + Value::Str(r) => Ok(Value::Str(l.to_string() + &r)), + Value::Float(r) => Ok(Value::Float(l + r)), + Value::Int(r) => Ok(Value::Float(l + r as f64)), + _ => Err(anyhow!("Right operand can't be added.")), + }, + Value::Int(l) => match rhs { + Value::Str(r) => Ok(Value::Str(l.to_string() + &r)), + Value::Float(r) => Ok(Value::Float(l as f64 + r)), + Value::Int(r) => Ok(Value::Int(l + r)), + _ => Err(anyhow!("Right operand can't be added.")), + }, + _ => Err(anyhow!("Left operand can't be added.")), + } + } + + pub fn sub(self, rhs: Value) -> Result<Value> { + match self { + Value::Float(l) => match rhs { + Value::Float(r) => Ok(Value::Float(l - r)), + Value::Int(r) => Ok(Value::Float(l - r as f64)), + _ => Err(anyhow!("Right operand can't be substracted.")), + }, + Value::Int(l) => match rhs { + Value::Float(r) => Ok(Value::Float(l as f64 - r)), + Value::Int(r) => Ok(Value::Int(l - r)), + _ => Err(anyhow!("Right operand can't be substracted.")), + }, + _ => Err(anyhow!("Left operand can't be substracted from.")), + } + } + + pub fn mul(self, rhs: Value) -> Result<Value> { + match self { + Value::Float(l) => match rhs { + Value::Float(r) => Ok(Value::Float(l * r)), + Value::Int(r) => Ok(Value::Float(l * r as f64)), + _ => Err(anyhow!("Right operand can't be multiplied.")), + }, + Value::Int(l) => match rhs { + Value::Float(r) => Ok(Value::Float(l as f64 * r)), + Value::Int(r) => Ok(Value::Int(l * r)), + _ => Err(anyhow!("Right operand can't be multiplied.")), + }, + _ => Err(anyhow!("Left operand can't be multiplied.")), + } + } + + pub fn div(self, rhs: Value) -> Result<Value> { + match self { + Value::Float(l) => match rhs { + Value::Float(r) => Ok(Value::Float(l / r)), + Value::Int(r) => Ok(Value::Float(l / r as f64)), + _ => Err(anyhow!("Right operand can't be multiplied.")), + }, + Value::Int(l) => match rhs { + Value::Float(r) => Ok(Value::Float(l as f64 / r)), + Value::Int(r) => Ok(Value::Float(l as f64 / r as f64)), + _ => Err(anyhow!("Right operand can't be multiplied.")), + }, + _ => Err(anyhow!("Left operand can't be multiplied.")), + } + } +} + +// pub enum Value { +// Float(f64), +// Int(i64), +// } + +// impl Add for WalkValue { +// type Output = Self; + +// fn add(self, rhs: Self) -> Self::Output { +// match self { +// Self::Float(float) => match rhs { +// Self::Float(other_float) => Self::Float(float + other_float), +// Self::Int(other_int) => Self::Float(float + other_int as f64), +// }, +// Self::Int(int) => match rhs { +// Self::Float(other_float) => Self::Float(int as f64 + other_float), +// Self::Int(other_int) => Self::Int(int + other_int), +// }, +// } +// } +// } + +// impl Sub for WalkValue { +// type Output = Self; + +// fn sub(self, rhs: Self) -> Self::Output { +// match self { +// Self::Float(float) => match rhs { +// Self::Float(other_float) => Self::Float(float - other_float), +// Self::Int(other_int) => Self::Float(float - other_int as f64), +// }, +// Self::Int(int) => match rhs { +// Self::Float(other_float) => Self::Float(int as f64 - other_float), +// Self::Int(other_int) => Self::Int(int - other_int), +// }, +// } +// } +// } + +// impl Mul for WalkValue { +// type Output = Self; + +// fn mul(self, rhs: Self) -> Self::Output { +// match self { +// Self::Float(float) => match rhs { +// Self::Float(other_float) => Self::Float(float * other_float), +// Self::Int(other_int) => Self::Float(float * other_int as f64), +// }, +// Self::Int(int) => match rhs { +// Self::Float(other_float) => Self::Float(int as f64 * other_float), +// Self::Int(other_int) => Self::Int(int * other_int), +// }, +// } +// } +// } + +// impl Div for WalkValue { +// type Output = Self; + +// fn div(self, rhs: Self) -> Self::Output { +// match self { +// Self::Float(float) => match rhs { +// Self::Float(other_float) => Self::Float(float / other_float), +// Self::Int(other_int) => Self::Float(float / other_int as f64), +// }, +// Self::Int(int) => match rhs { +// Self::Float(other_float) => Self::Float(int as f64 / other_float), +// Self::Int(other_int) => Self::Float(int as f64 / other_int as f64), +// }, +// } +// } +// } + +// impl Neg for WalkValue { +// type Output = Self; + +// fn neg(self) -> Self::Output { +// match self { +// Self::Float(float) => Self::Float(-float), +// Self::Int(int) => Self::Int(-int), +// } +// } +// } + +// impl Display for WalkValue { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// match self { +// Self::Float(float) => write!(f, "{}", float), +// Self::Int(int) => write!(f, "{}", int), +// } +// } +// } diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs index 817e94e..576cfb5 100644 --- a/src/interpret/walker.rs +++ b/src/interpret/walker.rs @@ -1,161 +1,138 @@ -use std::{ - fmt::Display, - ops::{Add, Div, Mul, Neg, Sub}, -}; +use std::{cell::RefCell, rc::Rc}; use crate::parse::ast::{ expression::Expression, - value::{BinaryOperator, Literal, UnaryOperator}, + nodes::{BinaryOperator as BinOp, Literal, UnaryOperator as UnOp}, + statement::Statement, + Program, }; -use anyhow::Result; +use anyhow::{anyhow, Result}; + +use super::{scope::Scope, value::Value}; // No state for now. -pub struct Walker {} +pub struct Walker { + scope: Scope, +} impl Walker { pub fn new() -> Self { - Walker {} + Walker { + scope: Scope::new(), + } } - pub fn walk(&self, node: &Expression) -> Result<WalkValue> { + pub fn walk(&mut self, program: &Program) { + self.scope.nest(); + for statement in program.statements.iter() { + self.walk_statement(statement).expect("Runtime error."); + } + } + + fn walk_statement(&mut self, statement: &Statement) -> Result<Option<Value>> { + let result = match statement { + Statement::Expression(node) => { + self.walk_expression(node)?; + None + } + Statement::Print(node) => { + let result = self.walk_expression(node)?; + println!("{:?}", result); + None + } + Statement::Return(node) => Some(self.walk_expression(node)?), + }; + + Ok(result) + } + + fn walk_expression(&mut self, node: &Expression) -> Result<Value> { match node { Expression::Binary { left, op, right } => { - let left_value = self.walk(left)?; - let right_value = self.walk(right)?; - let new_value = match op { - BinaryOperator::Plus => left_value + right_value, - BinaryOperator::Minus => left_value - right_value, - BinaryOperator::Star => left_value * right_value, - BinaryOperator::Slash => left_value / right_value, - BinaryOperator::Eq => todo!(), - BinaryOperator::Neq => todo!(), - BinaryOperator::Gt => todo!(), - BinaryOperator::Gte => todo!(), - BinaryOperator::Lt => todo!(), - BinaryOperator::Lte => todo!(), - BinaryOperator::Assign => todo!(), - BinaryOperator::ConstAssign => todo!(), - BinaryOperator::Dot => todo!(), - }; + BinOp::Plus => self + .walk_expression(left)? + .add(self.walk_expression(right)?), + BinOp::Minus => self + .walk_expression(left)? + .sub(self.walk_expression(right)?), + BinOp::Star => self + .walk_expression(left)? + .mul(self.walk_expression(right)?), + BinOp::Slash => self + .walk_expression(left)? + .div(self.walk_expression(right)?), + // No difference between assignments for now. + BinOp::Assign | BinOp::ConstAssign => { + let identifier = match left.as_ref() { + Expression::Identifier(i) => i, + _ => todo!("Lvalues can only be identifiers."), + }; + + let value = self.walk_expression(right)?; + self.scope.set_var(identifier, value.clone()); + Ok(value) + } + // Boolean logic comes later. + BinOp::Eq | BinOp::Neq | BinOp::Gt | BinOp::Gte | BinOp::Lt | BinOp::Lte => { + todo!() + } + // No structure access yet. + BinOp::Dot => todo!(), + }?; Ok(new_value) } Expression::Unary { op, right } => { - let value = self.walk(right)?; + let value = self.walk_expression(right)?; let new_value = match op { - UnaryOperator::Plus => value, - UnaryOperator::Minus => -value, - UnaryOperator::Not => todo!("Implement boolean arithmetic."), + UnOp::Plus => value, + UnOp::Minus => todo!(), + UnOp::Not => todo!("Implement boolean arithmetic."), }; Ok(new_value) } - Expression::Group(node) => self.walk(node), + Expression::Group(node) => self.walk_expression(node), Expression::Literal(token) => { let value = match token { - Literal::Int(int) => WalkValue::Int(*int as i64), - Literal::Float(float) => WalkValue::Float(*float as f64), - _ => todo!(), + Literal::Int(int) => Value::Int(*int as i64), + Literal::Float(float) => Value::Float(*float as f64), + Literal::Str(string) => Value::Str(string.clone()), }; Ok(value) } - _ => todo!(), - } - } -} + Expression::Block(block) => { + self.scope.nest(); -pub enum WalkValue { - Float(f64), - Int(i64), -} + for statement in block.statements.iter() { + self.walk_statement(statement)?; + } -impl Add for WalkValue { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - match self { - Self::Float(float) => match rhs { - Self::Float(other_float) => Self::Float(float + other_float), - Self::Int(other_int) => Self::Float(float + other_int as f64), - }, - Self::Int(int) => match rhs { - Self::Float(other_float) => Self::Float(int as f64 + other_float), - Self::Int(other_int) => Self::Int(int + other_int), - }, - } - } -} - -impl Sub for WalkValue { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - match self { - Self::Float(float) => match rhs { - Self::Float(other_float) => Self::Float(float - other_float), - Self::Int(other_int) => Self::Float(float - other_int as f64), - }, - Self::Int(int) => match rhs { - Self::Float(other_float) => Self::Float(int as f64 - other_float), - Self::Int(other_int) => Self::Int(int - other_int), - }, - } - } -} - -impl Mul for WalkValue { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - match self { - Self::Float(float) => match rhs { - Self::Float(other_float) => Self::Float(float * other_float), - Self::Int(other_int) => Self::Float(float * other_int as f64), - }, - Self::Int(int) => match rhs { - Self::Float(other_float) => Self::Float(int as f64 * other_float), - Self::Int(other_int) => Self::Int(int * other_int), - }, - } - } -} - -impl Div for WalkValue { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - match self { - Self::Float(float) => match rhs { - Self::Float(other_float) => Self::Float(float / other_float), - Self::Int(other_int) => Self::Float(float / other_int as f64), - }, - Self::Int(int) => match rhs { - Self::Float(other_float) => Self::Float(int as f64 / other_float), - Self::Int(other_int) => Self::Float(int as f64 / other_int as f64), - }, - } - } -} - -impl Neg for WalkValue { - type Output = Self; + let result = if let Some(tail_expression) = &block.tail_expression { + Ok(self.walk_expression(tail_expression)?) + } else { + Ok(Value::Void) + }; - fn neg(self) -> Self::Output { - match self { - Self::Float(float) => Self::Float(-float), - Self::Int(int) => Self::Int(-int), - } - } -} + self.scope.unnest(); -impl Display for WalkValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Float(float) => write!(f, "{}", float), - Self::Int(int) => write!(f, "{}", int), + result + } + Expression::Fn(fn_node) => { + let node = fn_node.as_ref().clone(); + Ok(Value::Fn(RefCell::new(Rc::new(node)))) + } + Expression::If(_) => todo!(), + Expression::Identifier(ident) => { + if let Some(value) = self.scope.get_var(ident) { + Ok(value) + } else { + Err(anyhow!("Unknown identifier: {}.", ident)) + } + } } } } diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs index 8563492..1749c40 100644 --- a/src/parse/ast/expression.rs +++ b/src/parse/ast/expression.rs @@ -1,10 +1,8 @@ use std::fmt::{self, Display, Formatter}; -use super::value::{ - BinaryOperator, Block, ConditionalBlock, FnHeader, Identifier, Literal, UnaryOperator, -}; +use super::nodes::{BinaryOperator, BlockNode, FnNode, Identifier, IfNode, Literal, UnaryOperator}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Expression { Binary { left: Box<Expression>, @@ -16,15 +14,9 @@ pub enum Expression { right: Box<Expression>, }, Group(Box<Expression>), - Block(Box<Block>), - Fn { - header: FnHeader, - body: Box<Block>, - }, - If { - conditionals: Vec<ConditionalBlock>, - else_block: Option<Box<Block>>, - }, + Block(Box<BlockNode>), + Fn(Box<FnNode>), + If(Box<IfNode>), Literal(Literal), Identifier(Identifier), } @@ -60,16 +52,16 @@ impl Expression { Expression::Block(block) => { Self::block_fmt(f, block, depth + 1)?; } - Expression::Fn { header, body } => { + Expression::Fn(node) => { write!(f, "{}Fn (", pad)?; // Write self receiver - if header.has_self_receiver { + if node.header.has_self_receiver { write!(f, "self, ")?; } // Write parameters - for p in header.parameters.iter() { + for p in node.header.parameters.iter() { write!( f, "{}: {}, ", @@ -82,9 +74,9 @@ impl Expression { writeln!( f, ") -> {}:", - header.return_type.as_ref().unwrap_or(&"_".into()) + node.header.return_type.as_ref().unwrap_or(&"_".into()) )?; - Self::block_fmt(f, body, depth + 1)?; + Self::block_fmt(f, &node.body, depth + 1)?; } Expression::Literal(literal) => { writeln!(f, "{}Literal: {:?}", pad, literal)?; @@ -92,25 +84,25 @@ impl Expression { Expression::Identifier(identifier) => { writeln!(f, "{}Identifier: {:?}", pad, identifier)?; } - Expression::If { conditionals, else_block } => { + Expression::If(node) => { writeln!(f, "{}If:", pad)?; - for (i, c) in conditionals.iter().enumerate() { + for (i, c) in node.conditionals.iter().enumerate() { writeln!(f, "{}- Condition {}:", pad, i)?; c.condition.nested_fmt(f, depth + 1)?; writeln!(f, "{}- Body {}:", pad, i)?; Self::block_fmt(f, &c.block, depth + 1)?; } - if let Some(e) = else_block { + if let Some(e) = &node.else_block { writeln!(f, "{}- Else:", pad)?; Self::block_fmt(f, e, depth + 1)?; } - }, + } } Ok(()) } - fn block_fmt(f: &mut Formatter<'_>, block: &Block, depth: usize) -> fmt::Result { + fn block_fmt(f: &mut Formatter<'_>, block: &BlockNode, depth: usize) -> fmt::Result { let pad = " ".repeat(depth); writeln!(f, "{}Block:", pad)?; for (i, statement) in block.statements.iter().enumerate() { diff --git a/src/parse/ast/mod.rs b/src/parse/ast/mod.rs index 257675f..93944b2 100644 --- a/src/parse/ast/mod.rs +++ b/src/parse/ast/mod.rs @@ -4,7 +4,7 @@ use self::statement::Statement; pub mod expression; pub mod statement; -pub mod value; +pub mod nodes; #[derive(Debug)] pub struct Program { diff --git a/src/parse/ast/value.rs b/src/parse/ast/nodes.rs index 263cb58..2347d5b 100644 --- a/src/parse/ast/value.rs +++ b/src/parse/ast/nodes.rs @@ -2,7 +2,7 @@ use crate::lex::token::{Token, TokenVariant::*}; use super::{expression::Expression, statement::Statement}; -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum BinaryOperator { Plus, Minus, @@ -35,12 +35,12 @@ impl BinaryOperator { Assign => Self::Assign, ConstAssign => Self::ConstAssign, Dot => Self::Dot, - _ => panic!("Can't create binary operator from '{:?}'.", token.variant) + _ => panic!("Can't create binary operator from '{:?}'.", token.variant), } } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum UnaryOperator { Plus, Minus, @@ -53,12 +53,12 @@ impl UnaryOperator { OpPlus => Self::Plus, OpMinus => Self::Minus, OpNot => Self::Not, - _ => panic!("Can't create unary operator from '{:?}'.", token.variant) + _ => panic!("Can't create unary operator from '{:?}'.", token.variant), } } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Literal { Int(u32), Float(f32), @@ -71,7 +71,7 @@ impl Literal { Int(int) => Self::Int(int), Float(float) => Self::Float(float), Str(string) => Self::Str(string), - _ => panic!("Can't create literal from '{:?}'.", token.variant) + _ => panic!("Can't create literal from '{:?}'.", token.variant), } } } @@ -80,27 +80,39 @@ pub type Identifier = String; // If the contraint is None the type will have to be inferred // during analysis. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct TypedIdentifier { pub identifier: Identifier, pub type_constraint: Option<Identifier>, } -#[derive(Debug)] +#[derive(Debug, Clone)] +pub struct FnNode { + pub header: FnHeader, + pub body: BlockNode, +} + +#[derive(Debug, Clone)] pub struct FnHeader { pub has_self_receiver: bool, pub parameters: Vec<TypedIdentifier>, pub return_type: Option<Identifier>, } -#[derive(Debug)] -pub struct Block { +#[derive(Debug, Clone)] +pub struct IfNode { + pub conditionals: Vec<ConditionalBlock>, + pub else_block: Option<BlockNode>, +} + +#[derive(Debug, Clone)] +pub struct BlockNode { pub statements: Vec<Statement>, pub tail_expression: Option<Expression>, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ConditionalBlock { pub condition: Expression, - pub block: Block, + pub block: BlockNode, } diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs index eec589e..b0e626d 100644 --- a/src/parse/ast/statement.rs +++ b/src/parse/ast/statement.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use super::expression::Expression; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Statement { Expression(Expression), Print(Expression), diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 0316a35..0e865da 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,6 +1,6 @@ use super::ast::expression::Expression; +use super::ast::nodes::UnaryOperator; use super::ast::statement::Statement; -use super::ast::value::UnaryOperator; use super::ast::Program; use crate::check; use crate::consume; @@ -8,12 +8,14 @@ use crate::consume_if; use crate::inner; use crate::lex::token::Token; use crate::lex::token::TokenVariant::*; -use crate::parse::ast::value::BinaryOperator; -use crate::parse::ast::value::Block; -use crate::parse::ast::value::ConditionalBlock; -use crate::parse::ast::value::FnHeader; -use crate::parse::ast::value::Literal; -use crate::parse::ast::value::TypedIdentifier; +use crate::parse::ast::nodes::BinaryOperator; +use crate::parse::ast::nodes::BlockNode; +use crate::parse::ast::nodes::ConditionalBlock; +use crate::parse::ast::nodes::FnHeader; +use crate::parse::ast::nodes::FnNode; +use crate::parse::ast::nodes::IfNode; +use crate::parse::ast::nodes::Literal; +use crate::parse::ast::nodes::TypedIdentifier; use anyhow::anyhow; use anyhow::Result; use std::iter::Peekable; @@ -203,10 +205,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { let body = self.block()?; - Ok(Expression::Fn { - header, - body: Box::new(body), - }) + Ok(Expression::Fn(Box::new(FnNode { header, body }))) } KeywordIf => { consume!(self, KeywordIf)?; @@ -232,16 +231,16 @@ impl<T: Iterator<Item = Token>> Parser<T> { }); } - let else_conditional = if consume_if!(self, KeywordElse).is_some() { + let else_block = if consume_if!(self, KeywordElse).is_some() { Some(self.block()?) } else { None }; - Ok(Expression::If { + Ok(Expression::If(Box::new(IfNode { conditionals, - else_block: else_conditional.map(Box::new), - }) + else_block, + }))) } _ => Err(anyhow!("Unexpected token: {:?}", token.variant)), } @@ -250,7 +249,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { } } - fn block(&mut self) -> Result<Block> { + fn block(&mut self) -> Result<BlockNode> { consume!(self, BlockOpen)?; let mut statements = Vec::new(); @@ -279,7 +278,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { consume!(self, BlockClose)?; - Ok(Block { + Ok(BlockNode { statements, tail_expression, }) |
