Fix all tests

This commit is contained in:
Greg Shuflin 2021-11-14 00:34:21 -08:00
parent 869de8c033
commit abab667c43
7 changed files with 88 additions and 60 deletions

View File

@ -168,7 +168,7 @@
//! //!
//! module := 'module' IDENTIFIER '{' statement* '}' //! module := 'module' IDENTIFIER '{' statement* '}'
//! ``` //! ```
mod new; pub mod new;
mod test; mod test;
use std::rc::Rc; use std::rc::Rc;

View File

@ -66,17 +66,18 @@ peg::parser! {
pub rule program(parser: &mut Parser) -> AST = 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")+ rule delimiter() = (";" / "\n")+
//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(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() } "{" __ stmt:statement(parser) __ "}" { vec![stmt].into() }
rule block_item(parser: &mut Parser) -> Statement = rule block_item(parser: &mut Parser) -> Statement =
stmt:statement(parser) delimiter()+ { stmt } _ stmt:statement(parser) _ delimiter()+ { stmt }
rule statement(parser: &mut Parser) -> Statement = rule statement(parser: &mut Parser) -> Statement =
_ pos:position!() kind:statement_kind(parser) _ { Statement { id: parser.fresh(), location: pos.into(), kind } } _ 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 = 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) implementation(parser) / module(parser)
rule module(parser: &mut Parser) -> Declaration = 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" _ "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() } Declaration::TypeDecl { name, body, mutable: mutable.is_some() }
} }
rule type_singleton_name() -> TypeSingletonName = 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> = rule type_params() -> Vec<TypeIdentifier> =
"<" _ idents:(type_identifier() ** (_ "," _)) _ ">" { idents } "<" _ idents:(type_identifier() ** (_ "," _)) _ ">" { idents }
@ -196,17 +199,17 @@ peg::parser! {
"(" _ items:(type_identifier() ** (_ "," _)) _ ")" { TypeIdentifier::Tuple(items) } / "(" _ items:(type_identifier() ** (_ "," _)) _ ")" { TypeIdentifier::Tuple(items) } /
singleton:type_singleton_name() { TypeIdentifier::Singleton(singleton) } singleton:type_singleton_name() { TypeIdentifier::Singleton(singleton) }
rule type_body() -> TypeBody = rule type_body(parser: &mut Parser) -> TypeBody =
"{" _ items:(record_variant_item() ++ (_ "," _)) _ "}" { TypeBody::ImmediateRecord(Default::default(), items) } / "{" _ items:(record_variant_item() ** (__ "," __)) __ "}" { TypeBody::ImmediateRecord(parser.fresh(), items) } /
variants:(variant_spec() ** (_ "|" _)) { TypeBody::Variants(variants) } variants:(variant_spec(parser) ** (__ "|" __)) { TypeBody::Variants(variants) }
rule variant_spec() -> Variant = rule variant_spec(parser: &mut Parser) -> Variant =
name:identifier() _ "{" _ typed_identifier_list:(record_variant_item() ++ (_ "," _)) _ "}" { Variant { name:identifier() __ "{" __ typed_identifier_list:(record_variant_item() ** (__ "," __)) __ ","? __ "}" { Variant {
id: Default::default(), name: rc_string(name), kind: VariantKind::Record(typed_identifier_list) id: parser.fresh(), name: rc_string(name), kind: VariantKind::Record(typed_identifier_list)
} } / } } /
name:identifier() "(" tuple_members:(type_identifier() ++ (_ "," _)) ")" { Variant { name:identifier() "(" tuple_members:(type_identifier() ++ (__ "," __)) ")" { Variant {
id: Default::default(), name: rc_string(name), kind: VariantKind::TupleStruct(tuple_members) } } / id: parser.fresh(), name: rc_string(name), kind: VariantKind::TupleStruct(tuple_members) } } /
name:identifier() { Variant { id: Default::default(), name: rc_string(name), kind: VariantKind::UnitStruct } } name:identifier() { Variant { id: parser.fresh(), name: rc_string(name), kind: VariantKind::UnitStruct } }
rule record_variant_item() -> (Rc<String>, TypeIdentifier) = rule record_variant_item() -> (Rc<String>, TypeIdentifier) =
name:identifier() _ ":" _ ty:type_identifier() { (rc_string(name), ty) } 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 } } __ kind:expression_kind(true, parser) _ type_anno:type_anno()? { Expression { id: parser.fresh(), type_anno, kind } }
rule expression_no_struct(parser: &mut Parser) -> Expression = 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 = rule expression_kind(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
precedence_expr(struct_ok, parser) precedence_expr(struct_ok, parser)
@ -229,7 +232,7 @@ peg::parser! {
rule precedence_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind = rule precedence_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
first:prefix_expr(struct_ok, parser) _ next:(precedence_continuation(struct_ok, parser))* { 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(); 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) = 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 = rule extended_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
primary:primary(struct_ok, parser) parts:(extended_expr_part(parser)*) { 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() { for part in parts.into_iter() {
let kind = match part { let kind = match part {
ExtendedPart::Index(indexers) => { ExtendedPart::Index(indexers) => {
@ -340,7 +343,7 @@ peg::parser! {
rule while_expr(parser: &mut Parser) -> ExpressionKind = rule while_expr(parser: &mut Parser) -> ExpressionKind =
"while" _ cond:expression_kind(false, parser)? _ body:block(parser) { "while" _ cond:expression_kind(false, parser)? _ body:block(parser) {
ExpressionKind::WhileExpression { 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, body,
} }
} }
@ -370,7 +373,10 @@ peg::parser! {
//TODO improve the definition of identifiers //TODO improve the definition of identifiers
rule identifier() -> &'input str = 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" / rule reserved() = "if" / "then" / "else" / "is" / "fn" / "for" / "while" / "let" / "in" / "mut" / "return" /
"break" / "alias" / "type" / "self" / "Self" / "interface" / "impl" / "true" / "false" / "module" / "import" "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() _ ":" _ pat:pattern(parser) _ { (name, pat) } /
_ name:identifier() _ { _ name:identifier() _ {
let qn = QualifiedName { let qn = QualifiedName {
id: Default::default(), id: parser.fresh(),
components: vec![Rc::new(name.to_string())], components: vec![Rc::new(name.to_string())],
}; };
(name, Pattern::VarOrName(qn)) (name, Pattern::VarOrName(qn))
@ -561,13 +567,14 @@ struct BinopSequence {
} }
impl BinopSequence { impl BinopSequence {
fn do_precedence(self) -> ExpressionKind { fn do_precedence(self, parser: &mut Parser) -> ExpressionKind {
fn helper( fn helper(
precedence: i32, precedence: i32,
lhs: ExpressionKind, lhs: ExpressionKind,
rest: &mut Vec<(BinOp, ExpressionKind)>, rest: &mut Vec<(BinOp, ExpressionKind)>,
parser: &mut Parser,
) -> Expression { ) -> Expression {
let mut lhs = Expression::new(Default::default(), lhs); let mut lhs = Expression::new(parser.fresh(), lhs);
loop { loop {
let (next_op, next_rhs) = match rest.pop() { let (next_op, next_rhs) = match rest.pop() {
Some((a, b)) => (a, b), Some((a, b)) => (a, b),
@ -578,15 +585,15 @@ impl BinopSequence {
rest.push((next_op, next_rhs)); rest.push((next_op, next_rhs));
break; break;
} }
let rhs = helper(new_precedence, next_rhs, rest); let rhs = helper(new_precedence, next_rhs, rest, parser);
lhs = Expression::new( lhs = Expression::new(
Default::default(), parser.fresh(),
ExpressionKind::BinExp(next_op, Box::new(lhs), Box::new(rhs)), ExpressionKind::BinExp(next_op, Box::new(lhs), Box::new(rhs)),
); );
} }
lhs lhs
} }
let mut as_stack = self.next.into_iter().rev().collect(); 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
} }
} }

View File

@ -1305,6 +1305,25 @@ fn blocks() {
let block = schala_parser::block(case, &mut parser); let block = schala_parser::block(case, &mut parser);
assert_eq!(block.unwrap(), vec![exst(Value(qn!(a)))].into()); 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] #[test]

View File

@ -128,11 +128,11 @@ pub(crate) struct SourceReference {
} }
impl SourceReference { impl SourceReference {
fn new() -> SourceReference { pub(crate) fn new() -> SourceReference {
SourceReference { last_source: None, newline_offsets: vec![] } 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() { for (offset, ch) in source.as_bytes().iter().enumerate() {
if *ch == ('\n' as u8) { if *ch == ('\n' as u8) {
self.newline_offsets.push(offset); self.newline_offsets.push(offset);

View File

@ -137,7 +137,7 @@ fn dont_falsely_detect_duplicates() {
let a = 40; let a = 40;
77 77
} }
let q = 39; let q = 39
"#; "#;
let (symbols, _) = add_symbols(source); let (symbols, _) = add_symbols(source);
@ -173,7 +173,8 @@ fn second_inner_func() {
} }
inner_func(x) inner_func(x)
}"#; }
"#;
let (symbols, _) = add_symbols(source); 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"])).is_some());
assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func", "inner_func"])).is_some()); assert!(symbols.fq_names.table.get(&make_fqsn(&["outer_func", "inner_func"])).is_some());
@ -189,7 +190,8 @@ inner_func(x)
fn enclosing_scopes_3() { fn enclosing_scopes_3() {
let source = r#" let source = r#"
fn outer_func(x) { fn outer_func(x) {
fn inner_func(arg) {
fn inner_func(arg) {
arg arg
} }

View File

@ -43,7 +43,7 @@ fn test_basic_eval() {
#[test] #[test]
fn op_eval() { fn op_eval() {
eval_assert("- 13", "-13"); eval_assert("-13", "-13");
eval_assert("10 - 2", "8"); eval_assert("10 - 2", "8");
} }
@ -96,7 +96,7 @@ trad()"#,
); );
let err = 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( eval_assert_failure(
r#" r#"
@ -271,26 +271,26 @@ fn full_if_matching() {
let source = r#" let source = r#"
type Option<T> = Some(T) | None type Option<T> = Some(T) | None
let a = Option::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"); eval_assert(source, "4");
let source = r#" let source = r#"
type Option<T> = Some(T) | None type Option<T> = Some(T) | None
let sara = Option::Some(99) 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"); eval_assert(source, "99");
let source = r#" let source = r#"
let a = 10 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\""); eval_assert(source, "\"x\"");
let source = r#" let source = r#"
let a = 10 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\""); eval_assert(source, "\"y\"");
} }
@ -300,7 +300,7 @@ if a { is 15 then "x", is 10 then "y" }
fn string_pattern() { fn string_pattern() {
let source = r#" let source = r#"
let a = "foo" 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\""); eval_assert(source, "\"x\"");
} }
@ -310,7 +310,7 @@ fn boolean_pattern() {
let source = r#" let source = r#"
let a = true let a = true
if a { if a {
is true then "x", is true then "x"
is false then "y" is false then "y"
} }
"#; "#;
@ -321,7 +321,7 @@ if a {
fn boolean_pattern_2() { fn boolean_pattern_2() {
let source = r#" let source = r#"
let a = false 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\""); eval_assert(source, "\"y\"");
} }
@ -341,7 +341,7 @@ if Option::Some(10) {
fn tuple_pattern() { fn tuple_pattern() {
let source = r#" let source = r#"
if (1, 2) { if (1, 2) {
is (1, x) then x, is (1, x) then x;
is _ then 99 is _ then 99
} }
"#; "#;
@ -352,7 +352,7 @@ if (1, 2) {
fn tuple_pattern_2() { fn tuple_pattern_2() {
let source = r#" let source = r#"
if (1, 2) { if (1, 2) {
is (10, x) then x, is (10, x) then x
is (y, x) then x + y is (y, x) then x + y
} }
"#; "#;
@ -363,7 +363,7 @@ if (1, 2) {
fn tuple_pattern_3() { fn tuple_pattern_3() {
let source = r#" let source = r#"
if (1, 5) { if (1, 5) {
is (10, x) then x, is (10, x) then x
is (1, x) then x is (1, x) then x
} }
"#; "#;
@ -374,8 +374,8 @@ if (1, 5) {
fn tuple_pattern_4() { fn tuple_pattern_4() {
let source = r#" let source = r#"
if (1, 5) { if (1, 5) {
is (10, x) then x, is (10, x) then x
is (1, x) then x, is (1, x) then x
} }
"#; "#;
eval_assert(source, "5"); eval_assert(source, "5");
@ -390,21 +390,21 @@ let b = Stuff::Jugs(1, "haha")
let c = Stuff::Mardok let c = Stuff::Mardok
let x = if a { let x = if a {
is Stuff::Mulch(20) then "x", is Stuff::Mulch(20) then "x"
is _ then "ERR" is _ then "ERR"
} }
let y = if b { let y = if b {
is Stuff::Mulch(n) then "ERR", is Stuff::Mulch(n) then "ERR"
is Stuff::Jugs(2, _) then "ERR", is Stuff::Jugs(2, _) then "ERR"
is Stuff::Jugs(1, s) then s, is Stuff::Jugs(1, s) then s
is _ then "ERR", is _ then "ERR"
} }
let z = if c { let z = if c {
is Stuff::Jugs(_, _) then "ERR", is Stuff::Jugs(_, _) then "ERR"
is Stuff::Mardok then "NIGH", is Stuff::Mardok then "NIGH"
is _ then "ERR", is _ then "ERR"
} }
(x, y, z) (x, y, z)

View File

@ -52,10 +52,10 @@ where T: Hash + Eq
/// Quickly create an AST from a string, with no error checking. For test use only /// Quickly create an AST from a string, with no error checking. For test use only
#[cfg(test)] #[cfg(test)]
pub fn quick_ast(input: &str) -> crate::ast::AST { pub fn quick_ast(input: &str) -> crate::ast::AST {
let tokens = crate::tokenizing::tokenize(input); let mut source_reference = crate::schala::SourceReference::new();
let mut parser = crate::parsing::Parser::new(); let mut parser = crate::parsing::new::Parser::new();
parser.add_new_tokens(tokens); source_reference.load_new_source(input);
let output = parser.parse(); let output = parser.parse(input, &source_reference);
output.unwrap() output.unwrap()
} }