diff --git a/schala-lang/language/src/ast.rs b/schala-lang/language/src/ast.rs index 01cab96..0ce6743 100644 --- a/schala-lang/language/src/ast.rs +++ b/schala-lang/language/src/ast.rs @@ -29,6 +29,7 @@ impl ItemIdStore { ItemIdStore { last_idx: 0 } } /// Always returns an ItemId with internal value zero + #[cfg(test)] pub fn new_id() -> ItemId { ItemId { idx: 0 } } @@ -158,8 +159,10 @@ pub enum Variant { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Derivative, Clone)] +#[derivative(PartialEq)] pub struct Expression { + #[derivative(PartialEq="ignore")] pub id: ItemId, pub kind: ExpressionKind, pub type_anno: Option diff --git a/schala-lang/language/src/parsing.rs b/schala-lang/language/src/parsing.rs index b1b7ec8..4e5aa84 100644 --- a/schala-lang/language/src/parsing.rs +++ b/schala-lang/language/src/parsing.rs @@ -614,7 +614,7 @@ impl Parser { None => unreachable!() }; let rhs = self.precedence_expr(new_precedence)?; - lhs = Expression::new(ExpressionKind::BinExp(operation, bx!(lhs.into()), bx!(rhs.into()))); + lhs = Expression::new(self.id_store.fresh(), ExpressionKind::BinExp(operation, bx!(lhs.into()), bx!(rhs.into()))); } self.parse_level -= 1; Ok(lhs) @@ -631,6 +631,7 @@ impl Parser { let expr = self.primary()?; let prefix_op = PrefixOp::from_str(sigil.as_str()).unwrap(); Ok(Expression::new( + self.id_store.fresh(), ExpressionKind::PrefixExp(prefix_op, bx!(expr.into())) )) }, @@ -644,7 +645,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().collect(); - expr = Expression::new(ExpressionKind::Call { f: bx!(expr.into()), arguments }); //TODO no type anno is incorrect + expr = Expression::new(self.id_store.fresh(), ExpressionKind::Call { f: bx!(expr.into()), arguments }); //TODO no type anno is incorrect } Ok(expr) @@ -681,8 +682,8 @@ 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::new(ExpressionKind::Index { - indexee: bx!(Expression::new(primary.kind).into()), + Expression::new(self.id_store.fresh(), ExpressionKind::Index { + indexee: bx!(Expression::new(self.id_store.fresh(), primary.kind).into()), indexers, }) } else { @@ -709,7 +710,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::new(ExpressionKind::ListLiteral(exprs))) + Ok(Expression::new(self.id_store.fresh(), ExpressionKind::ListLiteral(exprs))) } #[recursive_descent_method] @@ -726,7 +727,7 @@ impl Parser { _ => None, }; let body = self.nonempty_func_body()?; - Ok(Expression::new(ExpressionKind::Lambda { params, type_anno, body })) //TODO need to handle types somehow + Ok(Expression::new(self.id_store.fresh(), ExpressionKind::Lambda { params, type_anno, body })) //TODO need to handle types somehow } #[recursive_descent_method] @@ -747,11 +748,11 @@ impl Parser { let output = { let mut inner = delimited!(self, LParen, expression, Comma, RParen); match inner.len() { - 0 => Ok(Expression::new(TupleLiteral(vec![]))), + 0 => Ok(Expression::new(self.id_store.fresh(), TupleLiteral(vec![]))), 1 => Ok(inner.pop().unwrap()), _ => { let inner: Vec> = inner.into_iter().map(|ex| ex.into()).collect(); - Ok(Expression::new(TupleLiteral(inner))) + Ok(Expression::new(self.id_store.fresh(), TupleLiteral(inner))) } } }; @@ -766,9 +767,9 @@ impl Parser { Ok(match self.token_handler.peek_kind() { LCurlyBrace if !self.restrictions.no_struct_literal => { let fields = self.record_block()?; - Expression::new(NamedStruct { name: Meta::new(qualified_identifier), fields }) + Expression::new(self.id_store.fresh(), NamedStruct { name: Meta::new(qualified_identifier), fields }) }, - _ => Expression::new(Value(Meta::new(qualified_identifier))) + _ => Expression::new(self.id_store.fresh(), Value(Meta::new(qualified_identifier))) }) } @@ -819,7 +820,7 @@ impl Parser { _ => self.guard_block()? }); - Ok(Expression::new(ExpressionKind::IfExpression { discriminator, body })) + Ok(Expression::new(self.id_store.fresh(), ExpressionKind::IfExpression { discriminator, body })) } #[recursive_descent_method] @@ -1080,7 +1081,7 @@ impl Parser { x?.map(|expr| bx!(expr.into())) }; let body = self.block()?; - Ok(Expression::new(WhileExpression {condition, body})) + Ok(Expression::new(self.id_store.fresh(), WhileExpression {condition, body})) } #[recursive_descent_method] @@ -1106,7 +1107,7 @@ impl Parser { vec![single_enum] }; let body = Box::new(self.for_expr_body()?); - Ok(Expression::new(ExpressionKind::ForExpression { enumerators, body })) + Ok(Expression::new(self.id_store.fresh(), ExpressionKind::ForExpression { enumerators, body })) } #[recursive_descent_method] @@ -1152,15 +1153,18 @@ impl Parser { DigitGroup(_) | HexLiteral(_) | BinNumberSigil | Period => self.number_literal(), Keyword(Kw::True) => { self.token_handler.next(); - Ok(Expression::new(BoolLiteral(true))) + let id = self.id_store.fresh(); + Ok(Expression::new(id, BoolLiteral(true))) }, Keyword(Kw::False) => { self.token_handler.next(); - Ok(Expression::new(BoolLiteral(false))) + let id = self.id_store.fresh(); + Ok(Expression::new(id, BoolLiteral(false))) }, StrLiteral(s) => { self.token_handler.next(); - Ok(Expression::new(StringLiteral(s.clone()))) + let id = self.id_store.fresh(); + Ok(Expression::new(id, StringLiteral(s.clone()))) } e => ParseError::new_with_token(format!("Expected a literal expression, got {:?}", e), tok), } @@ -1182,12 +1186,12 @@ impl Parser { BinNumberSigil => { let digits = self.digits()?; let n = parse_binary(digits, tok)?; - Ok(Expression::new(NatLiteral(n))) + Ok(Expression::new(self.id_store.fresh(), NatLiteral(n))) }, HexLiteral(text) => { let digits: String = text.chars().filter(|c| c.is_digit(16)).collect(); let n = parse_hex(digits, tok)?; - Ok(Expression::new(NatLiteral(n))) + Ok(Expression::new(self.id_store.fresh(), NatLiteral(n))) }, _ => return ParseError::new_with_token("Expected '0x' or '0b'", tok), } @@ -1203,13 +1207,13 @@ impl Parser { digits.push_str("."); digits.push_str(&self.digits()?); match digits.parse::() { - Ok(f) => Ok(Expression::new(FloatLiteral(f))), + Ok(f) => Ok(Expression::new(self.id_store.fresh(), 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::new(NatLiteral(d))), + Ok(d) => Ok(Expression::new(self.id_store.fresh(), 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 b0bf34e..e961b11 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -47,9 +47,9 @@ macro_rules! decl { } macro_rules! ex { - ($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)) }; + ($expr_type:expr) => { Expression::new(ItemIdStore::new_id(), $expr_type) }; + (m $expr_type:expr) => { Meta::new(Expression::new(ItemIdStore::new_id(), $expr_type)) }; + (m $expr_type:expr, $type_anno:expr) => { Meta::new(Expression::with_anno(ItemIdStore::new_id(), $expr_type, $type_anno)) }; (s $expr_text:expr) => { { let tokens: Vec = tokenize($expr_text); @@ -64,14 +64,14 @@ macro_rules! inv { } macro_rules! binexp { - ($op:expr, $lhs:expr, $rhs:expr) => { BinExp(BinOp::from_sigil($op), bx!(Expression::new($lhs).into()), bx!(Expression::new($rhs).into())) } + ($op:expr, $lhs:expr, $rhs:expr) => { BinExp(BinOp::from_sigil($op), bx!(Expression::new(ItemIdStore::new_id(), $lhs).into()), bx!(Expression::new(ItemIdStore::new_id(), $rhs).into())) } } macro_rules! prefexp { - ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_str($op).unwrap(), bx!(Expression::new($lhs).into())) } + ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_str($op).unwrap(), bx!(Expression::new(ItemIdStore::new_id(), $lhs).into())) } } macro_rules! exst { - ($expr_type:expr) => { Meta::new(Statement { id: ItemIdStore::new_id(), kind: StatementKind::Expression(Expression::new($expr_type).into())}) }; - ($expr_type:expr, $type_anno:expr) => { Meta::new(Statement { id: ItemIdStore::new_id(), kind: StatementKind::Expression(Expression::with_anno($expr_type, $type_anno).into())}) }; + ($expr_type:expr) => { Meta::new(Statement { id: ItemIdStore::new_id(), kind: StatementKind::Expression(Expression::new(ItemIdStore::new_id(), $expr_type).into())}) }; + ($expr_type:expr, $type_anno:expr) => { Meta::new(Statement { id: ItemIdStore::new_id(), kind: StatementKind::Expression(Expression::with_anno(ItemIdStore::new_id(), $expr_type, $type_anno).into())}) }; ($op:expr, $lhs:expr, $rhs:expr) => { Meta::new( Statement { id: ItemIdStore::new_id(), ,kind: StatementKind::Expression(ex!(binexp!($op, $lhs, $rhs)))} )}; @@ -179,7 +179,7 @@ fn qualified_identifiers() { parse_test_wrap_ast! { "let q_q = Yolo::Swaggins", Meta::new(decl!(Binding { name: rc!(q_q), constant: true, type_anno: None, - expr: Meta::new(Expression::new(Value(Meta::new(QualifiedName(vec![rc!(Yolo), rc!(Swaggins)]))))), + expr: Meta::new(Expression::new(ItemIdStore::new_id(), Value(Meta::new(QualifiedName(vec![rc!(Yolo), rc!(Swaggins)]))))), })) } diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index 220adbd..52464dc 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 { kind, type_anno: Some(anno) } => { + 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 { kind, type_anno: None } => self.expr_type(kind) + Expression { kind, type_anno: None, .. } => self.expr_type(kind) } }