type declarations
This commit is contained in:
parent
02fc76c8fc
commit
d46f40bc0f
@ -2,6 +2,10 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
|
||||||
|
fn rc_string(s: &str) -> Rc<String> {
|
||||||
|
Rc::new(s.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
peg::parser! {
|
peg::parser! {
|
||||||
pub grammar schala_parser() for str {
|
pub grammar schala_parser() for str {
|
||||||
|
|
||||||
@ -14,11 +18,6 @@ peg::parser! {
|
|||||||
|
|
||||||
rule delimiter() = (";" / "\n")+
|
rule delimiter() = (";" / "\n")+
|
||||||
|
|
||||||
rule statement() -> Statement =
|
|
||||||
_ expr:expression() { Statement {
|
|
||||||
id: Default::default(), location: Default::default(), kind: StatementKind::Expression(expr) }
|
|
||||||
}
|
|
||||||
|
|
||||||
//Note - this is a hack, ideally the rule `rule block() -> Block = "{" _ items:(statement() **
|
//Note - this is a hack, ideally the rule `rule block() -> Block = "{" _ items:(statement() **
|
||||||
//delimiter()) _ "}" { items.into() }` would've worked, but it doesn't.
|
//delimiter()) _ "}" { items.into() }` would've worked, but it doesn't.
|
||||||
pub rule block() -> Block = "{" _ items:block_item()* _ "}" { items.into() } /
|
pub rule block() -> Block = "{" _ items:block_item()* _ "}" { items.into() } /
|
||||||
@ -27,10 +26,61 @@ peg::parser! {
|
|||||||
rule block_item() -> Statement =
|
rule block_item() -> Statement =
|
||||||
stmt:statement() delimiter()+ { stmt }
|
stmt:statement() delimiter()+ { stmt }
|
||||||
|
|
||||||
|
rule statement() -> Statement =
|
||||||
|
_ decl:declaration() { Statement { id: Default::default(), location: Default::default(), kind: StatementKind::Declaration(decl) } } /
|
||||||
|
_ expr:expression() { Statement { id: Default::default(), location: Default::default(), kind: StatementKind::Expression(expr) } }
|
||||||
|
|
||||||
|
rule declaration() -> Declaration =
|
||||||
|
binding() / type_decl()
|
||||||
|
|
||||||
|
rule binding() -> Declaration =
|
||||||
|
"let" _ mutable:"mut"? _ ident:identifier() _ type_anno:type_anno()? _ "=" _ expr:expression() {
|
||||||
|
Declaration::Binding { name: Rc::new(ident.to_string()), constant: mutable.is_none(),
|
||||||
|
type_anno, expr }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rule type_decl() -> Declaration =
|
||||||
|
"type" _ "alias" _ alias:type_alias() { alias } /
|
||||||
|
"type" _ mutable:"mut"? _ name:type_singleton_name() _ "=" _ body:type_body() {
|
||||||
|
Declaration::TypeDecl { name, body, mutable: mutable.is_some() }
|
||||||
|
}
|
||||||
|
|
||||||
|
rule type_singleton_name() -> TypeSingletonName =
|
||||||
|
name:identifier() params:type_params()? { TypeSingletonName { name: rc_string(name), params: if let Some(params) = params { params } else { vec![] } } }
|
||||||
|
|
||||||
|
rule type_params() -> Vec<TypeIdentifier> =
|
||||||
|
"<" _ idents:(type_identifier() ** (_ "," _)) _ ">" { idents }
|
||||||
|
|
||||||
|
rule type_identifier() -> TypeIdentifier =
|
||||||
|
"(" _ items:(type_identifier() ** (_ "," _)) _ ")" { TypeIdentifier::Tuple(items) } /
|
||||||
|
singleton:type_singleton_name() { TypeIdentifier::Singleton(singleton) }
|
||||||
|
|
||||||
|
rule type_body() -> TypeBody =
|
||||||
|
"{" _ items:(record_variant_item() ++ (_ "," _)) _ "}" { TypeBody::ImmediateRecord(Default::default(), items) } /
|
||||||
|
variants:(variant_spec() ** (_ "|" _)) { TypeBody::Variants(variants) }
|
||||||
|
|
||||||
|
rule variant_spec() -> Variant =
|
||||||
|
name:identifier() _ "{" _ typed_identifier_list:(record_variant_item() ++ (_ "," _)) _ "}" { Variant {
|
||||||
|
id: Default::default(), name: rc_string(name), kind: VariantKind::Record(typed_identifier_list)
|
||||||
|
} } /
|
||||||
|
name:identifier() "(" tuple_members:(type_identifier() ++ (_ "," _)) ")" { Variant {
|
||||||
|
id: Default::default(), name: rc_string(name), kind: VariantKind::TupleStruct(tuple_members) } } /
|
||||||
|
name:identifier() { Variant { id: Default::default(), name: rc_string(name), kind: VariantKind::UnitStruct } }
|
||||||
|
|
||||||
|
rule record_variant_item() -> (Rc<String>, TypeIdentifier) =
|
||||||
|
name:identifier() _ ":" _ ty:type_identifier() { (rc_string(name), ty) }
|
||||||
|
|
||||||
|
rule type_alias() -> Declaration =
|
||||||
|
alias:identifier() _ "=" _ name:identifier() { Declaration::TypeAlias { alias: rc_string(alias), original: rc_string(name), } }
|
||||||
|
|
||||||
|
rule type_anno() -> TypeIdentifier =
|
||||||
|
":" _ ident:identifier() { TypeIdentifier::Singleton(TypeSingletonName { name: Rc::new(ident.to_string()), params: vec![] }) }
|
||||||
|
|
||||||
pub rule expression() -> Expression =
|
pub rule expression() -> Expression =
|
||||||
_ kind:expression_kind() { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
_ kind:expression_kind() { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
||||||
|
|
||||||
pub rule expression_no_struct() -> Expression =
|
rule expression_no_struct() -> Expression =
|
||||||
_ kind:expression_kind_no_struct() { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
_ kind:expression_kind_no_struct() { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
||||||
|
|
||||||
rule expression_kind() -> ExpressionKind =
|
rule expression_kind() -> ExpressionKind =
|
||||||
|
@ -597,7 +597,7 @@ fn type_annotations() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn type_declarations() {
|
fn type_declarations() {
|
||||||
use Declaration::TypeDecl;
|
use Declaration::TypeDecl;
|
||||||
assert_ast! {
|
assert_ast2! {
|
||||||
"type Alpha = Alpha", vec![
|
"type Alpha = Alpha", vec![
|
||||||
decl(TypeDecl {
|
decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
||||||
@ -613,7 +613,7 @@ fn type_declarations() {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast2!(
|
||||||
"type mut Kuah = Kuah",
|
"type mut Kuah = Kuah",
|
||||||
decl(TypeDecl {
|
decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Kuah"), params: vec![] },
|
name: TypeSingletonName { name: rc("Kuah"), params: vec![] },
|
||||||
@ -626,7 +626,7 @@ fn type_declarations() {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ast! {
|
assert_ast2! {
|
||||||
"type Alpha = Alpha { a: Int, b: Int }",
|
"type Alpha = Alpha { a: Int, b: Int }",
|
||||||
vec![decl(TypeDecl {
|
vec![decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
||||||
@ -644,7 +644,7 @@ fn type_declarations() {
|
|||||||
})]
|
})]
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ast! {
|
assert_ast2! {
|
||||||
"type Alpha = { a: Int, b: Int }",
|
"type Alpha = { a: Int, b: Int }",
|
||||||
vec![decl(TypeDecl {
|
vec![decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
||||||
@ -657,7 +657,7 @@ fn type_declarations() {
|
|||||||
})]
|
})]
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast2!(
|
||||||
"type Option<T> = None | Some(T)",
|
"type Option<T> = None | Some(T)",
|
||||||
vec![decl(TypeDecl {
|
vec![decl(TypeDecl {
|
||||||
name: TypeSingletonName {
|
name: TypeSingletonName {
|
||||||
@ -679,12 +679,12 @@ fn type_declarations() {
|
|||||||
})]
|
})]
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast2!(
|
||||||
"type alias Alpha = Beta",
|
"type alias Alpha = Beta",
|
||||||
decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") })
|
decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") })
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ast!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))",
|
assert_ast2!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))",
|
||||||
decl(TypeDecl {
|
decl(TypeDecl {
|
||||||
name: TypeSingletonName { name: rc("Complex"), params: vec![
|
name: TypeSingletonName { name: rc("Complex"), params: vec![
|
||||||
TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }),
|
TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }),
|
||||||
@ -721,7 +721,7 @@ fn type_declarations() {
|
|||||||
fn declarations() {
|
fn declarations() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast2!(
|
||||||
"let q_q = Yolo::Swaggins",
|
"let q_q = Yolo::Swaggins",
|
||||||
vec![decl(Declaration::Binding {
|
vec![decl(Declaration::Binding {
|
||||||
name: rc("q_q"),
|
name: rc("q_q"),
|
||||||
@ -736,7 +736,7 @@ fn declarations() {
|
|||||||
fn bindings() {
|
fn bindings() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast2!(
|
||||||
"let mut a = 10",
|
"let mut a = 10",
|
||||||
vec![decl(Declaration::Binding {
|
vec![decl(Declaration::Binding {
|
||||||
name: rc("a"),
|
name: rc("a"),
|
||||||
@ -746,7 +746,7 @@ fn bindings() {
|
|||||||
})]
|
})]
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast2!(
|
||||||
"let a = 2 + a",
|
"let a = 2 + a",
|
||||||
vec![stmt(StatementKind::Declaration(Declaration::Binding {
|
vec![stmt(StatementKind::Declaration(Declaration::Binding {
|
||||||
name: rc("a"),
|
name: rc("a"),
|
||||||
@ -756,7 +756,7 @@ fn bindings() {
|
|||||||
}))]
|
}))]
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast2!(
|
||||||
"let a: Nat = 2",
|
"let a: Nat = 2",
|
||||||
vec![stmt(StatementKind::Declaration(Declaration::Binding {
|
vec![stmt(StatementKind::Declaration(Declaration::Binding {
|
||||||
name: rc("a"),
|
name: rc("a"),
|
||||||
|
Loading…
Reference in New Issue
Block a user