Fix all tests
This commit is contained in:
parent
869de8c033
commit
abab667c43
@ -168,7 +168,7 @@
|
||||
//!
|
||||
//! module := 'module' IDENTIFIER '{' statement* '}'
|
||||
//! ```
|
||||
mod new;
|
||||
pub mod new;
|
||||
mod test;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
@ -66,17 +66,18 @@ peg::parser! {
|
||||
|
||||
|
||||
pub rule program(parser: &mut Parser) -> AST =
|
||||
__ statements:(statement(parser) ** delimiter() ) __ { AST { id: Default::default(), statements: statements.into() } }
|
||||
__ statements:(statement(parser) ** (delimiter()+) ) __ { AST { id: parser.fresh(), statements: statements.into() } }
|
||||
|
||||
rule delimiter() = (";" / "\n")+
|
||||
|
||||
//Note - this is a hack, ideally the rule `rule block() -> Block = "{" _ items:(statement() **
|
||||
//delimiter()) _ "}" { items.into() }` would've worked, but it doesn't.
|
||||
pub rule block(parser: &mut Parser) -> Block = "{" __ items:block_item(parser)* __ "}" { items.into() } /
|
||||
pub rule block(parser: &mut Parser) -> Block =
|
||||
"{" __ items:block_item(parser)* __ "}" { items.into() } /
|
||||
"{" __ stmt:statement(parser) __ "}" { vec![stmt].into() }
|
||||
|
||||
rule block_item(parser: &mut Parser) -> Statement =
|
||||
stmt:statement(parser) delimiter()+ { stmt }
|
||||
_ stmt:statement(parser) _ delimiter()+ { stmt }
|
||||
|
||||
rule statement(parser: &mut Parser) -> Statement =
|
||||
_ pos:position!() kind:statement_kind(parser) _ { Statement { id: parser.fresh(), location: pos.into(), kind } }
|
||||
@ -116,7 +117,7 @@ peg::parser! {
|
||||
|
||||
|
||||
rule declaration(parser: &mut Parser) -> Declaration =
|
||||
binding(parser) / type_decl() / annotation(parser) / func(parser) / interface(parser) /
|
||||
binding(parser) / type_decl(parser) / annotation(parser) / func(parser) / interface(parser) /
|
||||
implementation(parser) / module(parser)
|
||||
|
||||
rule module(parser: &mut Parser) -> Declaration =
|
||||
@ -180,14 +181,16 @@ peg::parser! {
|
||||
}
|
||||
|
||||
|
||||
rule type_decl() -> Declaration =
|
||||
rule type_decl(parser: &mut Parser) -> Declaration =
|
||||
"type" _ "alias" _ alias:type_alias() { alias } /
|
||||
"type" _ mutable:"mut"? _ name:type_singleton_name() _ "=" _ body:type_body() {
|
||||
"type" _ mutable:"mut"? _ name:type_singleton_name() _ "=" _ body:type_body(parser) {
|
||||
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![] } } }
|
||||
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 }
|
||||
@ -196,17 +199,17 @@ peg::parser! {
|
||||
"(" _ 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 type_body(parser: &mut Parser) -> TypeBody =
|
||||
"{" _ items:(record_variant_item() ** (__ "," __)) __ "}" { TypeBody::ImmediateRecord(parser.fresh(), items) } /
|
||||
variants:(variant_spec(parser) ** (__ "|" __)) { 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)
|
||||
rule variant_spec(parser: &mut Parser) -> Variant =
|
||||
name:identifier() __ "{" __ typed_identifier_list:(record_variant_item() ** (__ "," __)) __ ","? __ "}" { Variant {
|
||||
id: parser.fresh(), 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 } }
|
||||
name:identifier() "(" tuple_members:(type_identifier() ++ (__ "," __)) ")" { Variant {
|
||||
id: parser.fresh(), name: rc_string(name), kind: VariantKind::TupleStruct(tuple_members) } } /
|
||||
name:identifier() { Variant { id: parser.fresh(), name: rc_string(name), kind: VariantKind::UnitStruct } }
|
||||
|
||||
rule record_variant_item() -> (Rc<String>, TypeIdentifier) =
|
||||
name:identifier() _ ":" _ ty:type_identifier() { (rc_string(name), ty) }
|
||||
@ -221,7 +224,7 @@ peg::parser! {
|
||||
__ kind:expression_kind(true, parser) _ type_anno:type_anno()? { Expression { id: parser.fresh(), type_anno, kind } }
|
||||
|
||||
rule expression_no_struct(parser: &mut Parser) -> Expression =
|
||||
__ kind:expression_kind(false, parser) { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
||||
__ kind:expression_kind(false, parser) { Expression { id: parser.fresh(), type_anno: None, kind: kind } }
|
||||
|
||||
rule expression_kind(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
precedence_expr(struct_ok, parser)
|
||||
@ -229,7 +232,7 @@ peg::parser! {
|
||||
rule precedence_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
first:prefix_expr(struct_ok, parser) _ next:(precedence_continuation(struct_ok, parser))* {
|
||||
let next = next.into_iter().map(|(sigil, expr)| (BinOp::from_sigil(sigil), expr)).collect();
|
||||
BinopSequence { first, next }.do_precedence()
|
||||
BinopSequence { first, next }.do_precedence(parser)
|
||||
}
|
||||
|
||||
rule precedence_continuation(struct_ok: bool, parser: &mut Parser) -> (&'input str, ExpressionKind) =
|
||||
@ -257,7 +260,7 @@ peg::parser! {
|
||||
|
||||
rule extended_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
primary:primary(struct_ok, parser) parts:(extended_expr_part(parser)*) {
|
||||
let mut expression = Expression::new(Default::default(), primary);
|
||||
let mut expression = Expression::new(parser.fresh(), primary);
|
||||
for part in parts.into_iter() {
|
||||
let kind = match part {
|
||||
ExtendedPart::Index(indexers) => {
|
||||
@ -340,7 +343,7 @@ peg::parser! {
|
||||
rule while_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
"while" _ cond:expression_kind(false, parser)? _ body:block(parser) {
|
||||
ExpressionKind::WhileExpression {
|
||||
condition: cond.map(|kind| Box::new(Expression::new(Default::default(), kind))),
|
||||
condition: cond.map(|kind| Box::new(Expression::new(parser.fresh(), kind))),
|
||||
body,
|
||||
}
|
||||
}
|
||||
@ -370,7 +373,10 @@ peg::parser! {
|
||||
|
||||
//TODO improve the definition of identifiers
|
||||
rule identifier() -> &'input str =
|
||||
!reserved() text:$(['a'..='z' | 'A'..='Z' | '_'] ['a'..='z' | 'A'..='Z' | '0'..='9' | '_']*) { text }
|
||||
!(reserved() !(ident_continuation())) text:$(['a'..='z' | 'A'..='Z' | '_'] ident_continuation()*) { text }
|
||||
|
||||
rule ident_continuation() -> &'input str =
|
||||
text:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_'])
|
||||
|
||||
rule reserved() = "if" / "then" / "else" / "is" / "fn" / "for" / "while" / "let" / "in" / "mut" / "return" /
|
||||
"break" / "alias" / "type" / "self" / "Self" / "interface" / "impl" / "true" / "false" / "module" / "import"
|
||||
@ -441,7 +447,7 @@ peg::parser! {
|
||||
_ name:identifier() _ ":" _ pat:pattern(parser) _ { (name, pat) } /
|
||||
_ name:identifier() _ {
|
||||
let qn = QualifiedName {
|
||||
id: Default::default(),
|
||||
id: parser.fresh(),
|
||||
components: vec![Rc::new(name.to_string())],
|
||||
};
|
||||
(name, Pattern::VarOrName(qn))
|
||||
@ -561,13 +567,14 @@ struct BinopSequence {
|
||||
}
|
||||
|
||||
impl BinopSequence {
|
||||
fn do_precedence(self) -> ExpressionKind {
|
||||
fn do_precedence(self, parser: &mut Parser) -> ExpressionKind {
|
||||
fn helper(
|
||||
precedence: i32,
|
||||
lhs: ExpressionKind,
|
||||
rest: &mut Vec<(BinOp, ExpressionKind)>,
|
||||
parser: &mut Parser,
|
||||
) -> Expression {
|
||||
let mut lhs = Expression::new(Default::default(), lhs);
|
||||
let mut lhs = Expression::new(parser.fresh(), lhs);
|
||||
loop {
|
||||
let (next_op, next_rhs) = match rest.pop() {
|
||||
Some((a, b)) => (a, b),
|
||||
@ -578,15 +585,15 @@ impl BinopSequence {
|
||||
rest.push((next_op, next_rhs));
|
||||
break;
|
||||
}
|
||||
let rhs = helper(new_precedence, next_rhs, rest);
|
||||
let rhs = helper(new_precedence, next_rhs, rest, parser);
|
||||
lhs = Expression::new(
|
||||
Default::default(),
|
||||
parser.fresh(),
|
||||
ExpressionKind::BinExp(next_op, Box::new(lhs), Box::new(rhs)),
|
||||
);
|
||||
}
|
||||
lhs
|
||||
}
|
||||
let mut as_stack = self.next.into_iter().rev().collect();
|
||||
helper(BinOp::min_precedence(), self.first, &mut as_stack).kind
|
||||
helper(BinOp::min_precedence(), self.first, &mut as_stack, parser).kind
|
||||
}
|
||||
}
|
||||
|
@ -1305,6 +1305,25 @@ fn blocks() {
|
||||
let block = schala_parser::block(case, &mut parser);
|
||||
assert_eq!(block.unwrap(), vec![exst(Value(qn!(a)))].into());
|
||||
}
|
||||
|
||||
let source = r#"{
|
||||
fn quah() {
|
||||
fn foo() { }
|
||||
}
|
||||
}"#;
|
||||
let block = schala_parser::block(source, &mut parser);
|
||||
assert_eq!(
|
||||
block.unwrap(),
|
||||
vec![decl(Declaration::FuncDecl(
|
||||
Signature { name: rc("quah"), operator: false, params: vec![], type_anno: None },
|
||||
vec![decl(Declaration::FuncDecl(
|
||||
Signature { name: rc("foo"), operator: false, params: vec![], type_anno: None },
|
||||
vec![].into(),
|
||||
))]
|
||||
.into()
|
||||
))]
|
||||
.into()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -128,11 +128,11 @@ pub(crate) struct SourceReference {
|
||||
}
|
||||
|
||||
impl SourceReference {
|
||||
fn new() -> SourceReference {
|
||||
pub(crate) fn new() -> SourceReference {
|
||||
SourceReference { last_source: None, newline_offsets: vec![] }
|
||||
}
|
||||
|
||||
fn load_new_source(&mut self, source: &str) {
|
||||
pub(crate) fn load_new_source(&mut self, source: &str) {
|
||||
for (offset, ch) in source.as_bytes().iter().enumerate() {
|
||||
if *ch == ('\n' as u8) {
|
||||
self.newline_offsets.push(offset);
|
||||
|
@ -137,7 +137,7 @@ fn dont_falsely_detect_duplicates() {
|
||||
let a = 40;
|
||||
77
|
||||
}
|
||||
let q = 39;
|
||||
let q = 39
|
||||
"#;
|
||||
let (symbols, _) = add_symbols(source);
|
||||
|
||||
@ -173,7 +173,8 @@ fn second_inner_func() {
|
||||
}
|
||||
|
||||
inner_func(x)
|
||||
}"#;
|
||||
}
|
||||
"#;
|
||||
let (symbols, _) = add_symbols(source);
|
||||
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func"])).is_some());
|
||||
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func", "inner_func"])).is_some());
|
||||
@ -189,6 +190,7 @@ inner_func(x)
|
||||
fn enclosing_scopes_3() {
|
||||
let source = r#"
|
||||
fn outer_func(x) {
|
||||
|
||||
fn inner_func(arg) {
|
||||
arg
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ trad()"#,
|
||||
);
|
||||
|
||||
let err =
|
||||
"No symbol found for name: QualifiedName { id: Id { idx: 4, t: PhantomData }, components: [\"a\"] }";
|
||||
"No symbol found for name: QualifiedName { id: Id { idx: 9, t: PhantomData }, components: [\"a\"] }";
|
||||
|
||||
eval_assert_failure(
|
||||
r#"
|
||||
@ -271,26 +271,26 @@ fn full_if_matching() {
|
||||
let source = r#"
|
||||
type Option<T> = Some(T) | None
|
||||
let a = Option::None
|
||||
if a { is Option::None then 4, is Option::Some(x) then x }
|
||||
if a { is Option::None then 4; is Option::Some(x) then x }
|
||||
"#;
|
||||
eval_assert(source, "4");
|
||||
|
||||
let source = r#"
|
||||
type Option<T> = Some(T) | None
|
||||
let sara = Option::Some(99)
|
||||
if sara { is Option::None then 1 + 3, is Option::Some(x) then x }
|
||||
if sara { is Option::None then 1 + 3; is Option::Some(x) then x }
|
||||
"#;
|
||||
eval_assert(source, "99");
|
||||
|
||||
let source = r#"
|
||||
let a = 10
|
||||
if a { is 10 then "x", is 4 then "y" }
|
||||
if a { is 10 then "x"; is 4 then "y" }
|
||||
"#;
|
||||
eval_assert(source, "\"x\"");
|
||||
|
||||
let source = r#"
|
||||
let a = 10
|
||||
if a { is 15 then "x", is 10 then "y" }
|
||||
if a { is 15 then "x"; is 10 then "y" }
|
||||
"#;
|
||||
eval_assert(source, "\"y\"");
|
||||
}
|
||||
@ -300,7 +300,7 @@ if a { is 15 then "x", is 10 then "y" }
|
||||
fn string_pattern() {
|
||||
let source = r#"
|
||||
let a = "foo"
|
||||
if a { is "foo" then "x", is _ then "y" }
|
||||
if a { is "foo" then "x"; is _ then "y" }
|
||||
"#;
|
||||
eval_assert(source, "\"x\"");
|
||||
}
|
||||
@ -310,7 +310,7 @@ fn boolean_pattern() {
|
||||
let source = r#"
|
||||
let a = true
|
||||
if a {
|
||||
is true then "x",
|
||||
is true then "x"
|
||||
is false then "y"
|
||||
}
|
||||
"#;
|
||||
@ -321,7 +321,7 @@ if a {
|
||||
fn boolean_pattern_2() {
|
||||
let source = r#"
|
||||
let a = false
|
||||
if a { is true then "x", is false then "y" }
|
||||
if a { is true then "x"; is false then "y" }
|
||||
"#;
|
||||
eval_assert(source, "\"y\"");
|
||||
}
|
||||
@ -341,7 +341,7 @@ if Option::Some(10) {
|
||||
fn tuple_pattern() {
|
||||
let source = r#"
|
||||
if (1, 2) {
|
||||
is (1, x) then x,
|
||||
is (1, x) then x;
|
||||
is _ then 99
|
||||
}
|
||||
"#;
|
||||
@ -352,7 +352,7 @@ if (1, 2) {
|
||||
fn tuple_pattern_2() {
|
||||
let source = r#"
|
||||
if (1, 2) {
|
||||
is (10, x) then x,
|
||||
is (10, x) then x
|
||||
is (y, x) then x + y
|
||||
}
|
||||
"#;
|
||||
@ -363,7 +363,7 @@ if (1, 2) {
|
||||
fn tuple_pattern_3() {
|
||||
let source = r#"
|
||||
if (1, 5) {
|
||||
is (10, x) then x,
|
||||
is (10, x) then x
|
||||
is (1, x) then x
|
||||
}
|
||||
"#;
|
||||
@ -374,8 +374,8 @@ if (1, 5) {
|
||||
fn tuple_pattern_4() {
|
||||
let source = r#"
|
||||
if (1, 5) {
|
||||
is (10, x) then x,
|
||||
is (1, x) then x,
|
||||
is (10, x) then x
|
||||
is (1, x) then x
|
||||
}
|
||||
"#;
|
||||
eval_assert(source, "5");
|
||||
@ -390,21 +390,21 @@ let b = Stuff::Jugs(1, "haha")
|
||||
let c = Stuff::Mardok
|
||||
|
||||
let x = if a {
|
||||
is Stuff::Mulch(20) then "x",
|
||||
is Stuff::Mulch(20) then "x"
|
||||
is _ then "ERR"
|
||||
}
|
||||
|
||||
let y = if b {
|
||||
is Stuff::Mulch(n) then "ERR",
|
||||
is Stuff::Jugs(2, _) then "ERR",
|
||||
is Stuff::Jugs(1, s) then s,
|
||||
is _ then "ERR",
|
||||
is Stuff::Mulch(n) then "ERR"
|
||||
is Stuff::Jugs(2, _) then "ERR"
|
||||
is Stuff::Jugs(1, s) then s
|
||||
is _ then "ERR"
|
||||
}
|
||||
|
||||
let z = if c {
|
||||
is Stuff::Jugs(_, _) then "ERR",
|
||||
is Stuff::Mardok then "NIGH",
|
||||
is _ then "ERR",
|
||||
is Stuff::Jugs(_, _) then "ERR"
|
||||
is Stuff::Mardok then "NIGH"
|
||||
is _ then "ERR"
|
||||
}
|
||||
|
||||
(x, y, z)
|
||||
|
@ -52,10 +52,10 @@ where T: Hash + Eq
|
||||
/// Quickly create an AST from a string, with no error checking. For test use only
|
||||
#[cfg(test)]
|
||||
pub fn quick_ast(input: &str) -> crate::ast::AST {
|
||||
let tokens = crate::tokenizing::tokenize(input);
|
||||
let mut parser = crate::parsing::Parser::new();
|
||||
parser.add_new_tokens(tokens);
|
||||
let output = parser.parse();
|
||||
let mut source_reference = crate::schala::SourceReference::new();
|
||||
let mut parser = crate::parsing::new::Parser::new();
|
||||
source_reference.load_new_source(input);
|
||||
let output = parser.parse(input, &source_reference);
|
||||
output.unwrap()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user