From d67ccf5c7af0bc3e727a59ce7037f80f3dbb18ba Mon Sep 17 00:00:00 2001 From: greg Date: Wed, 10 Jul 2019 18:52:25 -0700 Subject: [PATCH] Refactor Expression struct to have explicit kind and type_anno fields, to make it clearer that this represents source-code level annotation and not any kind of type inference intermediate product --- schala-lang/language/src/ast.rs | 14 +++++- schala-lang/language/src/parsing.rs | 63 ++++++++++++------------ schala-lang/language/src/parsing/test.rs | 14 +++--- schala-lang/language/src/reduced_ast.rs | 2 +- schala-lang/language/src/typechecking.rs | 6 +-- 5 files changed, 55 insertions(+), 44 deletions(-) diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index 0934c49..0b9e07b 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -100,8 +100,20 @@ pub enum Variant { } #[derive(Debug, PartialEq, Clone)] -pub struct Expression(pub ExpressionKind, pub Option); +pub struct Expression { + pub kind: ExpressionKind, + pub type_anno: Option +} +impl Expression { + pub fn new(kind: ExpressionKind) -> Expression { + Expression { kind, type_anno: None } + } + + pub fn with_anno(kind: ExpressionKind, type_anno: TypeIdentifier) -> Expression { + Expression { kind, type_anno: Some(type_anno) } + } +} #[derive(Debug, PartialEq, Clone)] pub enum TypeIdentifier { diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index 457f50b..60bd508 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -549,10 +549,10 @@ impl Parser { Colon => Some(self.type_anno()?), _ => None }; - if let Some(_) = expr_body.1 { + if let Some(_) = expr_body.type_anno { return ParseError::new_with_token("Bad parse state encountered", self.token_handler.peek()); } - expr_body.1 = type_anno; + expr_body.type_anno = type_anno; Ok(expr_body) } @@ -608,7 +608,7 @@ impl Parser { None => unreachable!() }; let rhs = self.precedence_expr(new_precedence)?; - lhs = Expression(ExpressionKind::BinExp(operation, bx!(lhs.into()), bx!(rhs.into())), None); + lhs = Expression::new(ExpressionKind::BinExp(operation, bx!(lhs.into()), bx!(rhs.into()))); } self.parse_level -= 1; Ok(lhs) @@ -623,9 +623,8 @@ impl Parser { _ => unreachable!(), }; let expr = self.primary()?; - Ok(Expression( - ExpressionKind::PrefixExp(PrefixOp::from_sigil(sigil.as_str()), bx!(expr.into())), - None + Ok(Expression::new( + ExpressionKind::PrefixExp(PrefixOp::from_sigil(sigil.as_str()), bx!(expr.into())) )) }, _ => self.call_expr() @@ -638,7 +637,7 @@ impl Parser { while let LParen = self.token_handler.peek_kind() { let arguments = delimited!(self, LParen, invocation_argument, Comma, RParen); let arguments = arguments.into_iter().map(|s| Meta::new(s)).collect(); - expr = Expression(ExpressionKind::Call { f: bx!(expr.into()), arguments }, None); //TODO none is incorrect + expr = Expression::new(ExpressionKind::Call { f: bx!(expr.into()), arguments }); //TODO no type anno is incorrect } Ok(expr) @@ -675,10 +674,10 @@ impl Parser { Ok(if let LSquareBracket = self.token_handler.peek_kind() { let indexers = delimited!(self, LSquareBracket, expression, Comma, RSquareBracket) .into_iter().map(|ex| ex.into()).collect(); - Expression(ExpressionKind::Index { - indexee: bx!(Expression(primary.0, None).into()), + Expression::new(ExpressionKind::Index { + indexee: bx!(Expression::new(primary.kind).into()), indexers, - }, None) + }) } else { primary }) @@ -703,7 +702,7 @@ impl Parser { fn list_expr(&mut self) -> ParseResult { let exprs = delimited!(self, LSquareBracket, expression, Comma, RSquareBracket) .into_iter().map(|ex| ex.into()).collect(); - Ok(Expression(ExpressionKind::ListLiteral(exprs), None)) + Ok(Expression::new(ExpressionKind::ListLiteral(exprs))) } #[recursive_descent_method] @@ -720,7 +719,7 @@ impl Parser { _ => None, }; let body = self.nonempty_func_body()?; - Ok(Expression(ExpressionKind::Lambda { params, type_anno, body }, None)) //TODO need to handle types somehow + Ok(Expression::new(ExpressionKind::Lambda { params, type_anno, body })) //TODO need to handle types somehow } #[recursive_descent_method] @@ -741,11 +740,11 @@ impl Parser { let output = { let mut inner = delimited!(self, LParen, expression, Comma, RParen); match inner.len() { - 0 => Ok(Expression(TupleLiteral(vec![]), None)), + 0 => Ok(Expression::new(TupleLiteral(vec![]))), 1 => Ok(inner.pop().unwrap()), _ => { let inner: Vec> = inner.into_iter().map(|ex| ex.into()).collect(); - Ok(Expression(TupleLiteral(inner), None)) + Ok(Expression::new(TupleLiteral(inner))) } } }; @@ -760,9 +759,9 @@ impl Parser { Ok(match self.token_handler.peek_kind() { LCurlyBrace if !self.restrictions.no_struct_literal => { let fields = self.record_block()?; - Expression(NamedStruct { name: identifier, fields }, None) + Expression::new(NamedStruct { name: identifier, fields }) }, - _ => Expression(Value(identifier), None) + _ => Expression::new(Value(identifier)) }) } @@ -798,7 +797,7 @@ impl Parser { _ => self.guard_block()? }); - Ok(Expression(ExpressionKind::IfExpression { discriminator, body }, None)) + Ok(Expression::new(ExpressionKind::IfExpression { discriminator, body })) } #[recursive_descent_method] @@ -890,13 +889,13 @@ impl Parser { ref tok if BinOp::from_sigil_token(tok).is_some() => { let op = BinOp::from_sigil_token(&self.token_handler.next().kind).unwrap(); let precedence = op.get_precedence(); - let Expression(expr, _) = self.precedence_expr(precedence)?; - Guard::HalfExpr(HalfExpr { op: Some(op), expr }) + let Expression { kind, .. } = self.precedence_expr(precedence)?; + Guard::HalfExpr(HalfExpr { op: Some(op), expr: kind }) }, _ => { //TODO - I think there's a better way to do this involving the precedence of -> - let Expression(expr, _) = self.prefix_expr()?; - Guard::HalfExpr(HalfExpr { op: None, expr }) + let Expression { kind, .. } = self.prefix_expr()?; + Guard::HalfExpr(HalfExpr { op: None, expr: kind }) } }) } @@ -962,8 +961,8 @@ impl Parser { }, _ => false }; - let Expression(expr_type, _) = self.number_literal()?; - Ok(Pattern::Literal(PatternLiteral::NumPattern { neg, num: expr_type })) + let Expression { kind, .. } = self.number_literal()?; + Ok(Pattern::Literal(PatternLiteral::NumPattern { neg, num: kind })) } #[recursive_descent_method] @@ -1007,7 +1006,7 @@ impl Parser { x?.map(|expr| bx!(expr.into())) }; let body = self.block()?; - Ok(Expression(WhileExpression {condition, body}, None)) + Ok(Expression::new(WhileExpression {condition, body})) } #[recursive_descent_method] @@ -1033,7 +1032,7 @@ impl Parser { vec![single_enum] }; let body = Box::new(self.for_expr_body()?); - Ok(Expression(ExpressionKind::ForExpression { enumerators, body }, None)) + Ok(Expression::new(ExpressionKind::ForExpression { enumerators, body })) } #[recursive_descent_method] @@ -1079,15 +1078,15 @@ impl Parser { DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => self.number_literal(), Keyword(Kw::True) => { self.token_handler.next(); - Ok(Expression(BoolLiteral(true), None)) + Ok(Expression::new(BoolLiteral(true))) }, Keyword(Kw::False) => { self.token_handler.next(); - Ok(Expression(BoolLiteral(false), None)) + Ok(Expression::new(BoolLiteral(false))) }, StrLiteral(s) => { self.token_handler.next(); - Ok(Expression(StringLiteral(s.clone()), None)) + Ok(Expression::new(StringLiteral(s.clone()))) } e => ParseError::new_with_token(format!("Expected a literal expression, got {:?}", e), tok), } @@ -1109,12 +1108,12 @@ impl Parser { BinNumberSigil => { let digits = self.digits()?; let n = parse_binary(digits, tok)?; - Ok(Expression(NatLiteral(n), None)) + Ok(Expression::new(NatLiteral(n))) }, HexLiteral(text) => { let digits: String = text.chars().filter(|c| c.is_digit(16)).collect(); let n = parse_hex(digits, tok)?; - Ok(Expression(NatLiteral(n), None)) + Ok(Expression::new(NatLiteral(n))) }, _ => return ParseError::new_with_token("Expected '0x' or '0b'", tok), } @@ -1130,13 +1129,13 @@ impl Parser { digits.push_str("."); digits.push_str(&self.digits()?); match digits.parse::() { - Ok(f) => Ok(Expression(FloatLiteral(f), None)), + Ok(f) => Ok(Expression::new(FloatLiteral(f))), Err(e) => ParseError::new_with_token(format!("Float failed to parse with error: {}", e), tok), } } else { match digits.parse::() { - Ok(d) => Ok(Expression(NatLiteral(d), None)), + Ok(d) => Ok(Expression::new(NatLiteral(d))), Err(e) => ParseError::new_with_token(format!("Integer failed to parse with error: {}", e), tok), } } diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index 243d758..be6ad41 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -39,9 +39,9 @@ macro_rules! tys { } macro_rules! ex { - ($expr_type:expr) => { Expression($expr_type, None) }; - (m $expr_type:expr) => { Meta::new(Expression($expr_type, None)) }; - (m $expr_type:expr, $type_anno:expr) => { Meta::new(Expression($expr_type, Some($type_anno))) }; + ($expr_type:expr) => { Expression::new($expr_type) }; + (m $expr_type:expr) => { Meta::new(Expression::new($expr_type)) }; + (m $expr_type:expr, $type_anno:expr) => { Meta::new(Expression::with_anno($expr_type, $type_anno)) }; (s $expr_text:expr) => { { let tokens: Vec = tokenize($expr_text); @@ -56,14 +56,14 @@ macro_rules! inv { } macro_rules! binexp { - ($op:expr, $lhs:expr, $rhs:expr) => { BinExp(BinOp::from_sigil($op), bx!(Expression($lhs, None).into()), bx!(Expression($rhs, None).into())) } + ($op:expr, $lhs:expr, $rhs:expr) => { BinExp(BinOp::from_sigil($op), bx!(Expression::new($lhs).into()), bx!(Expression::new($rhs).into())) } } macro_rules! prefexp { - ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_sigil($op), bx!(Expression($lhs, None).into())) } + ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_sigil($op), bx!(Expression::new($lhs).into())) } } macro_rules! exst { - ($expr_type:expr) => { Meta::new(Statement::ExpressionStatement(Expression($expr_type, None).into())) }; - ($expr_type:expr, $type_anno:expr) => { Meta::new(Statement::ExpressionStatement(Expression($expr_type, Some($type_anno)).into())) }; + ($expr_type:expr) => { Meta::new(Statement::ExpressionStatement(Expression::new($expr_type).into())) }; + ($expr_type:expr, $type_anno:expr) => { Meta::new(Statement::ExpressionStatement(Expression::with_anno($expr_type, $type_anno).into())) }; ($op:expr, $lhs:expr, $rhs:expr) => { Meta::new(Statement::ExpressionStatement(ex!(binexp!($op, $lhs, $rhs)))) }; (s $statement_text:expr) => { { diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index 03e8300..695d771 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -132,7 +132,7 @@ impl InvocationArgument { impl Expression { fn reduce(&self, symbol_table: &SymbolTable) -> Expr { use crate::ast::ExpressionKind::*; - let ref input = self.0; + let ref input = self.kind; match input { NatLiteral(n) => Expr::Lit(Lit::Nat(*n)), FloatLiteral(f) => Expr::Lit(Lit::Float(*f)), diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index 43e81ec..eea0c87 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -299,12 +299,12 @@ impl<'a> TypeContext<'a> { fn expr(&mut self, expr: &Expression) -> InferResult { match expr { - Expression(expr_type, Some(anno)) => { - let t1 = self.expr_type(expr_type)?; + Expression { kind, type_anno: Some(anno) } => { + let t1 = self.expr_type(kind)?; let t2 = self.get_type_from_name(anno)?; self.unify(t2, t1) }, - Expression(expr_type, None) => self.expr_type(expr_type) + Expression { kind, type_anno: None } => self.expr_type(kind) } }