Changeset - b0a907fd8513
[Not reviewed]
0 3 0
MH - 4 years ago 2021-04-02 14:35:43
contact@maxhenger.nl
Add some tests for failing imports
3 files changed with 108 insertions and 12 deletions:
0 comments (0 inline, 0 general)
src/protocol/lexer.rs
Show inline comments
 
@@ -500,6 +500,9 @@ impl Lexer<'_> {
 
            backup_pos: &mut InputPosition
 
        ) -> Result<(), ParseError2> {
 
            // Consume identifier
 
            if !ident.value.is_empty() {
 
                ident.value.extend(b"::");
 
            }
 
            let ident_start = ident.value.len();
 
            ident.value.extend(l.consume_ident()?);
 
            ident.parts.push(NamespacedIdentifierPart::Identifier{
 
@@ -510,7 +513,7 @@ impl Lexer<'_> {
 
            // Maybe consume polymorphic args.
 
            *backup_pos = l.source.pos();
 
            l.consume_whitespace(false)?;
 
            let had_poly_args = match l.consume_polymorphic_args(h, true)? {
 
            match l.consume_polymorphic_args(h, true)? {
 
                Some(args) => {
 
                    let poly_start = ident.poly_args.len();
 
                    ident.poly_args.extend(args);
 
@@ -525,7 +528,7 @@ impl Lexer<'_> {
 
                None => {}
 
            };
 

	
 
            Ok(had_poly_args)
 
            Ok(())
 
        }
 

	
 
        let mut ident = NamespacedIdentifier2{
src/protocol/parser/utils.rs
Show inline comments
 
use crate::protocol::ast::*;
 
    use crate::protocol::ast::*;
 
use crate::protocol::inputsource::*;
 
use super::symbol_table::*;
 
use super::type_table::*;
 
@@ -10,7 +10,7 @@ pub(crate) enum FindTypeResult<'t, 'i> {
 
    // Could not match symbol
 
    SymbolNotFound{ident_pos: InputPosition},
 
    // Matched part of the namespaced identifier, but not completely
 
    SymbolPartial{ident_pos: InputPosition, symbol_pos: InputPosition, ident_iter: NamespacedIdentifier2Iter<'i>},
 
    SymbolPartial{ident_pos: InputPosition, ident_iter: NamespacedIdentifier2Iter<'i>},
 
    // Symbol matched, but points to a namespace/module instead of a type
 
    SymbolNamespace{ident_pos: InputPosition, symbol_pos: InputPosition},
 
}
 
@@ -29,15 +29,12 @@ impl<'t, 'i> FindTypeResult<'t, 'i> {
 
                    "Could not resolve this identifier to a symbol"
 
                ))
 
            },
 
            FindTypeResult::SymbolPartial{ident_pos, symbol_pos, ident_iter} => {
 
            FindTypeResult::SymbolPartial{ident_pos, ident_iter} => {
 
                Err(ParseError2::new_error(
 
                    module_source, ident_pos, 
 
                    "Could not fully resolve this identifier to a symbol"
 
                ).with_postfixed_info(
 
                    module_source, symbol_pos, 
 
                    &format!(
 
                        "The partial identifier '{}' was matched to this symbol",
 
                        String::from_utf8_lossy(ident_iter.returned_section()),
 
                        "Could not fully resolve this identifier to a symbol, was only able to match '{}'",
 
                        &String::from_utf8_lossy(ident_iter.returned_section())
 
                    )
 
                ))
 
            },
 
@@ -71,8 +68,7 @@ pub(crate) fn find_type_definition<'t, 'i>(
 
    let symbol = symbol.unwrap();
 
    if ident_iter.num_remaining() != 0 { 
 
        return FindTypeResult::SymbolPartial{
 
            ident_pos: identifier.position, 
 
            symbol_pos: symbol.position, 
 
            ident_pos: identifier.position,
 
            ident_iter
 
        };
 
    }
src/protocol/tests/parser_imports.rs
Show inline comments
 
@@ -147,6 +147,103 @@ fn test_multi_symbol_import() {
 
    //     .expect_ok();
 
}
 

	
 
#[test]
 
fn test_illegal_import_use() {
 
    Tester::new("unexpected polymorphic args")
 
        .with_source("
 
        #module external
 
        struct Foo { byte f }
 
        ")
 
        .with_source("
 
        import external;
 
        byte caller() {
 
            auto foo = external::Foo<int>{ f: 0 };
 
            return foo.f;
 
        }
 
        ")
 
        .compile()
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "the type Foo is not polymorphic");
 
        });
 

	
 
    Tester::new("mismatched polymorphic args")
 
        .with_source("
 
        #module external
 
        struct Foo<T>{ T f }
 
        ")
 
        .with_source("
 
        import external;
 
        byte caller() {
 
            auto foo = external::Foo<byte, int>{ f: 0 };
 
            return foo.f;
 
        }")
 
        .compile()
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "expected 1 polymorphic")
 
            .assert_msg_has(0, "2 were specified");
 
        });
 

	
 
    Tester::new("module as type")
 
        .with_source("
 
        #module external
 
        ")
 
        .with_source("
 
        import external;
 
        byte caller() {
 
            auto foo = external{ f: 0 };
 
            return 0;
 
        }
 
        ")
 
        .compile()
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "resolved to a namespace");
 
        });
 

	
 
    Tester::new("more namespaces than needed, not polymorphic")
 
        .with_source("
 
        #module external
 
        struct Foo { byte f }
 
        ")
 
        .with_source("
 
        import external;
 
        byte caller() {
 
            auto foo = external::Foo::f{ f: 0 };
 
            return 0;
 
        }")
 
        .compile()
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "not fully resolve this identifier")
 
            .assert_msg_has(0, "able to match 'external::Foo'");
 
        });
 

	
 
    Tester::new("import from another import")
 
        .with_source("
 
        #module mod1
 
        struct Foo { byte f }
 
        ")
 
        .with_source("
 
        #module mod2
 
        import mod1::Foo;
 
        struct Bar { Foo f }
 
        ")
 
        .with_source("
 
        import mod2;
 
        byte caller() {
 
            auto bar = mod2::Bar{ f: mod2::Foo{ f: 0 } };
 
            return var.f.f;
 
        }")
 
        .compile()
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "Could not resolve this identifier")
 
            .assert_occurs_at(0, "mod2::Foo");
 
        });
 
}
 

	
 
// TODO: Test incorrect imports:
 
//  1. importing a module
 
//  2. import something a module imports
0 comments (0 inline, 0 general)