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* '}'
//! ```
mod new;
pub mod new;
mod test;
use std::rc::Rc;

View File

@ -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() } /
"{" __ stmt:statement(parser) __ "}" { vec![stmt].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
}
}

View File

@ -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]

View File

@ -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);

View File

@ -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,7 +190,8 @@ inner_func(x)
fn enclosing_scopes_3() {
let source = r#"
fn outer_func(x) {
fn inner_func(arg) {
fn inner_func(arg) {
arg
}

View File

@ -43,7 +43,7 @@ fn test_basic_eval() {
#[test]
fn op_eval() {
eval_assert("- 13", "-13");
eval_assert("-13", "-13");
eval_assert("10 - 2", "8");
}
@ -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)

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
#[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()
}