diff --git a/schala-lang/language/src/ast/mod.rs b/schala-lang/language/src/ast/mod.rs index 6078bd2..c8e53de 100644 --- a/schala-lang/language/src/ast/mod.rs +++ b/schala-lang/language/src/ast/mod.rs @@ -135,7 +135,10 @@ pub struct Signature { //TODO I can probably get rid of TypeBody #[derive(Debug, PartialEq, Clone)] -pub struct TypeBody(pub Vec); +pub enum TypeBody { + Variants(Vec), + ImmediateRecord(ItemId, Vec<(Rc, TypeIdentifier)>), +} #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] diff --git a/schala-lang/language/src/parsing/mod.rs b/schala-lang/language/src/parsing/mod.rs index afe156c..329c70c 100644 --- a/schala-lang/language/src/parsing/mod.rs +++ b/schala-lang/language/src/parsing/mod.rs @@ -26,7 +26,8 @@ //! type_declaration := "type" type_declaration_body //! type_declaration_body := "alias" type_alias | "mut"? type_singleton_name "=" type_body //! type_alias := IDENTIFIER "=" type_name -//! type_body := variant_specifier ("|" variant_specifier)* +//! type_body := immediate_record | (variant_specifier ("|" variant_specifier)*) +//! immediate_record := "{" typed_identifier_list "}" //! variant_specifier := IDENTIFIER | IDENTIFIER "{" typed_identifier_list "}" | IDENTIFIER "(" type_name* ")" //! typed_identifier_list := typed_identifier* //! typed_identifier := IDENTIFIER type_anno @@ -454,12 +455,17 @@ impl Parser { #[recursive_descent_method] fn type_body(&mut self) -> ParseResult { - let mut variants = vec![self.variant_specifier()?]; - while let Pipe = self.token_handler.peek_kind() { - self.token_handler.next(); - variants.push(self.variant_specifier()?); - } - Ok(TypeBody(variants)) + Ok(if let LCurlyBrace = self.token_handler.peek_kind() { + let typed_identifier_list = delimited!(self, LCurlyBrace, typed_identifier, Comma, RCurlyBrace); + TypeBody::ImmediateRecord(self.id_store.fresh(), typed_identifier_list) + } else { + let mut variants = vec![self.variant_specifier()?]; + while let Pipe = self.token_handler.peek_kind() { + self.token_handler.next(); + variants.push(self.variant_specifier()?); + } + TypeBody::Variants(variants) + }) } #[recursive_descent_method] @@ -471,7 +477,6 @@ impl Parser { VariantKind::TupleStruct(tuple_members) } LCurlyBrace => { - println!("ARAH"); let typed_identifier_list = delimited!(self, LCurlyBrace, typed_identifier, Comma, RCurlyBrace); VariantKind::Record(typed_identifier_list) @@ -690,7 +695,9 @@ impl Parser { fn prefix_expr(&mut self) -> ParseResult { loop { match self.token_handler.peek_kind() { - Semicolon | Newline => { self.token_handler.next(); }, + Semicolon | Newline => { + self.token_handler.next(); + } _ => break, } } diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index 1ea2899..fc94514 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -572,7 +572,7 @@ fn type_declarations() { decl(TypeDecl { name: TypeSingletonName { name: rc("Alpha"), params: vec![] }, mutable: false, - body: TypeBody(vec![ + body: TypeBody::Variants(vec![ Variant { id: Default::default(), name: rc("Alpha"), @@ -588,7 +588,7 @@ fn type_declarations() { decl(TypeDecl { name: TypeSingletonName { name: rc("Kuah"), params: vec![] }, mutable: true, - body: TypeBody(vec![Variant { + body: TypeBody::Variants(vec![Variant { id: Default::default(), name: rc("Kuah"), kind: VariantKind::UnitStruct @@ -596,26 +596,36 @@ fn type_declarations() { }) ); - //TODO support this - let specs = ["type Alpha = Alpha { a: Int, b: Int }" /* "type Alpha = { a: Int, b: Int }"*/]; - for spec in specs { - assert_ast! { - spec, vec![decl(TypeDecl { - name: TypeSingletonName { name: rc("Alpha"), params: vec![] }, - mutable: false, - body: TypeBody(vec![ - Variant { - id: Default::default(), - name: rc("Alpha"), - kind: VariantKind::Record(vec![ - (rc("a"), ty_simple("Int")), - (rc("b"), ty_simple("Int")) - ]) - } - ]) - })] - }; - } + assert_ast! { + "type Alpha = Alpha { a: Int, b: Int }", + vec![decl(TypeDecl { + name: TypeSingletonName { name: rc("Alpha"), params: vec![] }, + mutable: false, + body: TypeBody::Variants(vec![ + Variant { + id: Default::default(), + name: rc("Alpha"), + kind: VariantKind::Record(vec![ + (rc("a"), ty_simple("Int")), + (rc("b"), ty_simple("Int")) + ]) + } + ]) + })] + }; + + assert_ast! { + "type Alpha = { a: Int, b: Int }", + vec![decl(TypeDecl { + name: TypeSingletonName { name: rc("Alpha"), params: vec![] }, + mutable: false, + body: TypeBody::ImmediateRecord(Default::default(), vec![ + (rc("a"), ty_simple("Int")), + (rc("b"), ty_simple("Int")) + ]) + + })] + }; assert_ast!( "type Option = None | Some(T)", @@ -625,7 +635,7 @@ fn type_declarations() { params: vec![TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] })] }, mutable: false, - body: TypeBody(vec![ + body: TypeBody::Variants(vec![ Variant { id: Default::default(), name: rc("None"), kind: VariantKind::UnitStruct }, Variant { id: Default::default(), @@ -651,7 +661,7 @@ fn type_declarations() { TypeIdentifier::Singleton(TypeSingletonName { name: rc("U"), params: vec![] }), ] }, mutable: false, - body: TypeBody(vec![ + body: TypeBody::Variants(vec![ Variant { id: Default::default(), name: rc("Unit"), kind: VariantKind::UnitStruct }, Variant { id: Default::default(), name: rc("Record"), kind: VariantKind::Record( vec![ diff --git a/schala-lang/language/src/symbol_table/mod.rs b/schala-lang/language/src/symbol_table/mod.rs index 071ba2a..4ed9a7a 100644 --- a/schala-lang/language/src/symbol_table/mod.rs +++ b/schala-lang/language/src/symbol_table/mod.rs @@ -404,7 +404,14 @@ impl<'a> SymbolTableRunner<'a> { location: Location, scope_stack: &mut Vec, ) -> Vec { - let TypeBody(variants) = type_body; + let variants = match type_body { + TypeBody::Variants(variants) => variants.clone(), + TypeBody::ImmediateRecord(id, fields) => vec![Variant { + id: *id, + name: type_name.name.clone(), + kind: VariantKind::Record(fields.clone()), + }], + }; let type_fqsn = Fqsn::from_scope_stack(scope_stack, type_name.name.clone()); let new_scope = Scope::Name(type_name.name.clone()); @@ -414,7 +421,7 @@ impl<'a> SymbolTableRunner<'a> { let mut seen_variants = HashSet::new(); let mut errors = vec![]; - for variant in variants { + for variant in variants.iter() { if seen_variants.contains(&variant.name) { errors.push(SymbolError::DuplicateVariant { type_fqsn: type_fqsn.clone(), diff --git a/schala-lang/language/src/tree_walk_eval/test.rs b/schala-lang/language/src/tree_walk_eval/test.rs index 7b86229..a1a0539 100644 --- a/schala-lang/language/src/tree_walk_eval/test.rs +++ b/schala-lang/language/src/tree_walk_eval/test.rs @@ -371,7 +371,7 @@ let x = Some(9); if x is Some(q) then { q } else { 0 }"#; #[test] fn accessors() { let source = r#" -type Klewos = Klewos { a: Int, b: String } +type Klewos = { a: Int, b: String } let value = Klewos::Klewos { a: 50, b: "nah" } (value.a, value.b) "#;