Implement immediate records
This commit is contained in:
parent
663e99df23
commit
803a836887
@ -135,7 +135,10 @@ pub struct Signature {
|
|||||||
|
|
||||||
//TODO I can probably get rid of TypeBody
|
//TODO I can probably get rid of TypeBody
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct TypeBody(pub Vec<Variant>);
|
pub enum TypeBody {
|
||||||
|
Variants(Vec<Variant>),
|
||||||
|
ImmediateRecord(ItemId, Vec<(Rc<String>, TypeIdentifier)>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Derivative, Clone)]
|
#[derive(Debug, Derivative, Clone)]
|
||||||
#[derivative(PartialEq)]
|
#[derivative(PartialEq)]
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
//! type_declaration := "type" type_declaration_body
|
//! type_declaration := "type" type_declaration_body
|
||||||
//! type_declaration_body := "alias" type_alias | "mut"? type_singleton_name "=" type_body
|
//! type_declaration_body := "alias" type_alias | "mut"? type_singleton_name "=" type_body
|
||||||
//! type_alias := IDENTIFIER "=" type_name
|
//! 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* ")"
|
//! variant_specifier := IDENTIFIER | IDENTIFIER "{" typed_identifier_list "}" | IDENTIFIER "(" type_name* ")"
|
||||||
//! typed_identifier_list := typed_identifier*
|
//! typed_identifier_list := typed_identifier*
|
||||||
//! typed_identifier := IDENTIFIER type_anno
|
//! typed_identifier := IDENTIFIER type_anno
|
||||||
@ -454,12 +455,17 @@ impl Parser {
|
|||||||
|
|
||||||
#[recursive_descent_method]
|
#[recursive_descent_method]
|
||||||
fn type_body(&mut self) -> ParseResult<TypeBody> {
|
fn type_body(&mut self) -> ParseResult<TypeBody> {
|
||||||
|
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()?];
|
let mut variants = vec![self.variant_specifier()?];
|
||||||
while let Pipe = self.token_handler.peek_kind() {
|
while let Pipe = self.token_handler.peek_kind() {
|
||||||
self.token_handler.next();
|
self.token_handler.next();
|
||||||
variants.push(self.variant_specifier()?);
|
variants.push(self.variant_specifier()?);
|
||||||
}
|
}
|
||||||
Ok(TypeBody(variants))
|
TypeBody::Variants(variants)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[recursive_descent_method]
|
#[recursive_descent_method]
|
||||||
@ -471,7 +477,6 @@ impl Parser {
|
|||||||
VariantKind::TupleStruct(tuple_members)
|
VariantKind::TupleStruct(tuple_members)
|
||||||
}
|
}
|
||||||
LCurlyBrace => {
|
LCurlyBrace => {
|
||||||
println!("ARAH");
|
|
||||||
let typed_identifier_list =
|
let typed_identifier_list =
|
||||||
delimited!(self, LCurlyBrace, typed_identifier, Comma, RCurlyBrace);
|
delimited!(self, LCurlyBrace, typed_identifier, Comma, RCurlyBrace);
|
||||||
VariantKind::Record(typed_identifier_list)
|
VariantKind::Record(typed_identifier_list)
|
||||||
@ -690,7 +695,9 @@ impl Parser {
|
|||||||
fn prefix_expr(&mut self) -> ParseResult<Expression> {
|
fn prefix_expr(&mut self) -> ParseResult<Expression> {
|
||||||
loop {
|
loop {
|
||||||
match self.token_handler.peek_kind() {
|
match self.token_handler.peek_kind() {
|
||||||
Semicolon | Newline => { self.token_handler.next(); },
|
Semicolon | Newline => {
|
||||||
|
self.token_handler.next();
|
||||||
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,7 +572,7 @@ fn type_declarations() {
|
|||||||
decl(TypeDecl {
|
decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
||||||
mutable: false,
|
mutable: false,
|
||||||
body: TypeBody(vec![
|
body: TypeBody::Variants(vec![
|
||||||
Variant {
|
Variant {
|
||||||
id: Default::default(),
|
id: Default::default(),
|
||||||
name: rc("Alpha"),
|
name: rc("Alpha"),
|
||||||
@ -588,7 +588,7 @@ fn type_declarations() {
|
|||||||
decl(TypeDecl {
|
decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Kuah"), params: vec![] },
|
name: TypeSingletonName { name: rc("Kuah"), params: vec![] },
|
||||||
mutable: true,
|
mutable: true,
|
||||||
body: TypeBody(vec![Variant {
|
body: TypeBody::Variants(vec![Variant {
|
||||||
id: Default::default(),
|
id: Default::default(),
|
||||||
name: rc("Kuah"),
|
name: rc("Kuah"),
|
||||||
kind: VariantKind::UnitStruct
|
kind: VariantKind::UnitStruct
|
||||||
@ -596,14 +596,12 @@ 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! {
|
assert_ast! {
|
||||||
spec, vec![decl(TypeDecl {
|
"type Alpha = Alpha { a: Int, b: Int }",
|
||||||
|
vec![decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
||||||
mutable: false,
|
mutable: false,
|
||||||
body: TypeBody(vec![
|
body: TypeBody::Variants(vec![
|
||||||
Variant {
|
Variant {
|
||||||
id: Default::default(),
|
id: Default::default(),
|
||||||
name: rc("Alpha"),
|
name: rc("Alpha"),
|
||||||
@ -615,7 +613,19 @@ fn type_declarations() {
|
|||||||
])
|
])
|
||||||
})]
|
})]
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
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!(
|
assert_ast!(
|
||||||
"type Option<T> = None | Some(T)",
|
"type Option<T> = None | Some(T)",
|
||||||
@ -625,7 +635,7 @@ fn type_declarations() {
|
|||||||
params: vec![TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] })]
|
params: vec![TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] })]
|
||||||
},
|
},
|
||||||
mutable: false,
|
mutable: false,
|
||||||
body: TypeBody(vec![
|
body: TypeBody::Variants(vec![
|
||||||
Variant { id: Default::default(), name: rc("None"), kind: VariantKind::UnitStruct },
|
Variant { id: Default::default(), name: rc("None"), kind: VariantKind::UnitStruct },
|
||||||
Variant {
|
Variant {
|
||||||
id: Default::default(),
|
id: Default::default(),
|
||||||
@ -651,7 +661,7 @@ fn type_declarations() {
|
|||||||
TypeIdentifier::Singleton(TypeSingletonName { name: rc("U"), params: vec![] }),
|
TypeIdentifier::Singleton(TypeSingletonName { name: rc("U"), params: vec![] }),
|
||||||
] },
|
] },
|
||||||
mutable: false,
|
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("Unit"), kind: VariantKind::UnitStruct },
|
||||||
Variant { id: Default::default(), name: rc("Record"), kind: VariantKind::Record(
|
Variant { id: Default::default(), name: rc("Record"), kind: VariantKind::Record(
|
||||||
vec![
|
vec![
|
||||||
|
@ -404,7 +404,14 @@ impl<'a> SymbolTableRunner<'a> {
|
|||||||
location: Location,
|
location: Location,
|
||||||
scope_stack: &mut Vec<Scope>,
|
scope_stack: &mut Vec<Scope>,
|
||||||
) -> Vec<SymbolError> {
|
) -> Vec<SymbolError> {
|
||||||
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 type_fqsn = Fqsn::from_scope_stack(scope_stack, type_name.name.clone());
|
||||||
|
|
||||||
let new_scope = Scope::Name(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 seen_variants = HashSet::new();
|
||||||
let mut errors = vec![];
|
let mut errors = vec![];
|
||||||
|
|
||||||
for variant in variants {
|
for variant in variants.iter() {
|
||||||
if seen_variants.contains(&variant.name) {
|
if seen_variants.contains(&variant.name) {
|
||||||
errors.push(SymbolError::DuplicateVariant {
|
errors.push(SymbolError::DuplicateVariant {
|
||||||
type_fqsn: type_fqsn.clone(),
|
type_fqsn: type_fqsn.clone(),
|
||||||
|
@ -371,7 +371,7 @@ let x = Some(9); if x is Some(q) then { q } else { 0 }"#;
|
|||||||
#[test]
|
#[test]
|
||||||
fn accessors() {
|
fn accessors() {
|
||||||
let source = r#"
|
let source = r#"
|
||||||
type Klewos = Klewos { a: Int, b: String }
|
type Klewos = { a: Int, b: String }
|
||||||
let value = Klewos::Klewos { a: 50, b: "nah" }
|
let value = Klewos::Klewos { a: 50, b: "nah" }
|
||||||
(value.a, value.b)
|
(value.a, value.b)
|
||||||
"#;
|
"#;
|
||||||
|
Loading…
Reference in New Issue
Block a user