Changeset - d7baa792c2c2
[Not reviewed]
src/protocol/input_source.rs
Show inline comments
 
@@ -161,7 +161,7 @@ impl InputSource {
 
            }
 
        }
 

	
 
        lookup.push(self.input.len() as u32); // for lookup_line_end
 
        lookup.push(self.input.len() as u32 + 1); // for lookup_line_end, intentionally adding one character
 
        debug_assert_eq!(self.line as usize + 2, lookup.len(), "remove me: i am a testing assert and sometimes invalid");
 

	
 
        // Return created lookup
 
@@ -183,13 +183,11 @@ impl InputSource {
 
        let offset = lookup[(line_number + 1) as usize] - 1;
 
        let offset_usize = offset as usize;
 

	
 
        // Compensate for newlines and a potential carriage feed
 
        if self.input[offset_usize] == b'\n' {
 
            if offset_usize > 0 && self.input[offset_usize] == b'\r' {
 
                offset - 2
 
            } else {
 
                offset - 1
 
            }
 
        // Compensate for newlines and a potential carriage feed. Note that the
 
        // end position is exclusive. So we only need to compensate for a
 
        // "\r\n"
 
        if offset_usize > 0 && offset_usize < self.input.len() && self.input[offset_usize] == b'\n' && self.input[offset_usize - 1] == b'\r' {
 
            offset - 1
 
        } else {
 
            offset
 
        }
 
@@ -319,17 +317,28 @@ impl fmt::Display for ParseErrorStatement {
 

	
 
        fn extend_annotation(first_col: u32, last_col: u32, source: &str, target: &mut String, extend_char: char) {
 
            debug_assert!(first_col > 0 && last_col > first_col);
 

	
 
            // If the first index exceeds the size of the context then we should
 
            // have a message placed at the newline character
 
            let first_idx = first_col as usize - 1;
 
            let last_idx = last_col as usize - 1;
 
            for (char_idx, char) in source.chars().enumerate().skip(first_idx) {
 
                if char_idx == last_idx as usize {
 
                    break;
 
                }
 

	
 
                if char == '\t' {
 
                    for _ in 0..4 { target.push(extend_char); }
 
                } else {
 
                    target.push(extend_char);
 
            if first_idx >= source.len() {
 
                // If any of these fail then the logic behind reporting errors
 
                // is incorrect.
 
                debug_assert_eq!(first_idx, source.len());
 
                debug_assert_eq!(first_idx + 1, last_idx);
 
                target.push(extend_char);
 
            } else {
 
                for (char_idx, char) in source.chars().enumerate().skip(first_idx) {
 
                    if char_idx == last_idx as usize {
 
                        break;
 
                    }
 

	
 
                    if char == '\t' {
 
                        for _ in 0..4 { target.push(extend_char); }
 
                    } else {
 
                        target.push(extend_char);
 
                    }
 
                }
 
            }
 
        }
src/protocol/parser/pass_definitions.rs
Show inline comments
 
@@ -52,12 +52,16 @@ impl PassDefinitions {
 

	
 
            match cur_range.range_kind {
 
                TokenRangeKind::Module => unreachable!(), // should not be reachable
 
                TokenRangeKind::Pragma | TokenRangeKind::Import => continue, // already fully parsed
 
                TokenRangeKind::Definition | TokenRangeKind::Code => {}
 
                TokenRangeKind::Pragma | TokenRangeKind::Import => {
 
                    // Already fully parsed, fall through and go to next range
 
                },
 
                TokenRangeKind::Definition | TokenRangeKind::Code => {
 
                    // Visit range even if it is a "code" range to provide
 
                    // proper error messages.
 
                    self.visit_range(modules, module_idx, ctx, range_idx_usize)?;
 
                },
 
            }
 

	
 
            self.visit_range(modules, module_idx, ctx, range_idx_usize)?;
 

	
 
            if cur_range.next_sibling_idx == NO_SIBLING {
 
                break;
 
            } else {
 
@@ -1290,7 +1294,7 @@ impl PassDefinitions {
 
                                        let value = self.consume_expression(module, iter, ctx)?;
 
                                        Ok(LiteralStructField{ identifier, value, field_idx: 0 })
 
                                    },
 
                                    &mut struct_fields, "a struct field", "a list of struct field", Some(&mut last_token)
 
                                    &mut struct_fields, "a struct field", "a list of struct fields", Some(&mut last_token)
 
                                )?;
 

	
 
                                ctx.heap.alloc_literal_expression(|this| LiteralExpression{
 
@@ -1329,8 +1333,12 @@ impl PassDefinitions {
 
                                let variant = consume_ident_interned(&module.source, iter, ctx)?;
 

	
 
                                // Consume any possible embedded values
 
                                let mut end_pos = iter.last_valid_pos();
 
                                let values = self.consume_expression_list(module, iter, ctx, Some(&mut end_pos))?;
 
                                let mut end_pos = variant.span.end;
 
                                let values = if Some(TokenKind::OpenParen) == iter.next() {
 
                                    self.consume_expression_list(module, iter, ctx, Some(&mut end_pos))?
 
                                } else {
 
                                    Vec::new()
 
                                };
 

	
 
                                ctx.heap.alloc_literal_expression(|this| LiteralExpression{
 
                                    this,
 
@@ -1402,6 +1410,8 @@ impl PassDefinitions {
 
            } else {
 
                // Check for builtin keywords or builtin functions
 
                if ident_text == KW_LIT_NULL || ident_text == KW_LIT_TRUE || ident_text == KW_LIT_FALSE {
 
                    iter.consume();
 

	
 
                    // Parse builtin literal
 
                    let value = match ident_text {
 
                        KW_LIT_NULL => Literal::Null,
 
@@ -1418,13 +1428,27 @@ impl PassDefinitions {
 
                        concrete_type: ConcreteType::default(),
 
                    }).upcast()
 
                } else {
 
                    // I'm a bit unsure about this. One may as well have wrongfully
 
                    // typed `TypeWithTypo<Subtype>::`, then we assume that
 
                    // `TypeWithTypo` is a variable. So might want to come back to
 
                    // this later to do some silly heuristics.
 
                    // Not a builtin literal, but also not a known type. So we
 
                    // assume it is a variable expression. Although if we do,
 
                    // then if a programmer mistyped a struct/function name the
 
                    // error messages will be rather cryptic. For polymorphic
 
                    // arguments we can't really do anything at all (because it
 
                    // uses the '<' token). In the other cases we try to provide
 
                    // a better error message.
 
                    iter.consume();
 
                    if Some(TokenKind::ColonColon) == iter.next() {
 
                    let next = iter.next();
 
                    if Some(TokenKind::ColonColon) == next {
 
                        return Err(ParseError::new_error_str_at_span(&module.source, ident_span, "unknown identifier"));
 
                    } else if Some(TokenKind::OpenParen) == next {
 
                        return Err(ParseError::new_error_str_at_span(
 
                            &module.source, ident_span,
 
                            "unknown identifier, did you mistype a union variant's or a function's name?"
 
                        ));
 
                    } else if Some(TokenKind::OpenCurly) == next {
 
                        return Err(ParseError::new_error_str_at_span(
 
                            &module.source, ident_span,
 
                            "unknown identifier, did you mistype a struct type's name?"
 
                        ))
 
                    }
 

	
 
                    let ident_text = ctx.pool.intern(ident_text);
 
@@ -1498,7 +1522,7 @@ impl PassDefinitions {
 
/// these.
 
///
 
/// Note that the first depth index is used as a hack.
 
// TODO: @Optimize, @Span fix
 
// TODO: @Optimize, @Span fix, @Cleanup
 
fn consume_parser_type(
 
    source: &InputSource, iter: &mut TokenIter, symbols: &SymbolTable, heap: &Heap, poly_vars: &[Identifier],
 
    cur_scope: SymbolScope, wrapping_definition: DefinitionId, allow_inference: bool, first_angle_depth: i32,
 
@@ -1508,6 +1532,8 @@ fn consume_parser_type(
 
        depth: i32,
 
    }
 

	
 
    // After parsing the array modified "[]", we need to insert an array type
 
    // before the most recently parsed type.
 
    fn insert_array_before(elements: &mut Vec<Entry>, depth: i32, span: InputSpan) {
 
        let index = elements.iter().rposition(|e| e.depth == depth).unwrap();
 
        elements.insert(index, Entry{
 
@@ -1517,9 +1543,11 @@ fn consume_parser_type(
 
    }
 

	
 
    // Most common case we just have one type, perhaps with some array
 
    // annotations.
 
    // annotations. This is both the hot-path, and simplifies the state machine
 
    // that follows and is responsible for parsing more complicated types.
 
    let element = consume_parser_type_ident(source, iter, symbols, heap, poly_vars, cur_scope, wrapping_definition, allow_inference)?;
 
    if iter.next() != Some(TokenKind::OpenAngle) {
 
        let num_embedded = element.variant.num_embedded();
 
        let mut num_array = 0;
 
        while iter.next() == Some(TokenKind::OpenSquare) {
 
            iter.consume();
 
@@ -1528,12 +1556,22 @@ fn consume_parser_type(
 
        }
 

	
 
        let array_span = element.full_span;
 
        let mut elements = Vec::with_capacity(num_array + 1);
 
        let mut elements = Vec::with_capacity(num_array + num_embedded + 1);
 
        for _ in 0..num_array {
 
            elements.push(ParserTypeElement{ full_span: array_span, variant: ParserTypeVariant::Array });
 
        }
 
        elements.push(element);
 

	
 
        if num_embedded != 0 {
 
            if !allow_inference {
 
                return Err(ParseError::new_error_str_at_span(source, array_span, "type inference is not allowed here"));
 
            }
 

	
 
            for _ in 0..num_embedded {
 
                elements.push(ParserTypeElement { full_span: array_span, variant: ParserTypeVariant::Inferred });
 
            }
 
        }
 

	
 
        return Ok(ParserType{ elements });
 
    };
 

	
 
@@ -1696,12 +1734,26 @@ fn consume_parser_type(
 
                    });
 
                }
 
            } else {
 
                // Mismatch in number of embedded types
 
                let expected_args_text = if expected_subtypes == 1 {
 
                    "polymorphic argument"
 
                } else {
 
                    "polymorphic arguments"
 
                };
 
                // Mismatch in number of embedded types, produce a neat error
 
                // message.
 
                let type_name = String::from_utf8_lossy(source.section_at_span(cur_element.element.full_span));
 
                fn polymorphic_name_text(num: usize) -> &'static str {
 
                    if num == 1 { "polymorphic argument" } else { "polymorphic arguments" }
 
                }
 
                fn were_or_was(num: usize) -> &'static str {
 
                    if num == 1 { "was" } else { "were" }
 
                }
 

	
 
                if expected_subtypes == 0 {
 
                    return Err(ParseError::new_error_at_span(
 
                        source, cur_element.element.full_span,
 
                        format!(
 
                            "the type '{}' is not polymorphic, yet {} {} {} provided",
 
                            type_name, encountered_subtypes, polymorphic_name_text(encountered_subtypes),
 
                            were_or_was(encountered_subtypes)
 
                        )
 
                    ));
 
                }
 

	
 
                let maybe_infer_text = if allow_inference {
 
                    " (or none, to perform implicit type inference)"
 
@@ -1712,8 +1764,10 @@ fn consume_parser_type(
 
                return Err(ParseError::new_error_at_span(
 
                    source, cur_element.element.full_span,
 
                    format!(
 
                        "expected {} {}{}, but {} were provided",
 
                        expected_subtypes, expected_args_text, maybe_infer_text, encountered_subtypes
 
                        "expected {} {}{} for the type '{}', but {} {} provided",
 
                        expected_subtypes, polymorphic_name_text(expected_subtypes),
 
                        maybe_infer_text, type_name, encountered_subtypes,
 
                        were_or_was(encountered_subtypes)
 
                    )
 
                ));
 
            }
 
@@ -1785,7 +1839,7 @@ fn consume_parser_type_ident(
 
                        SymbolVariant::Module(symbol_module) => {
 
                            // Expecting more identifiers
 
                            if Some(TokenKind::ColonColon) != iter.next() {
 
                                return Err(ParseError::new_error_str_at_span(source, type_span, "expected type but got module"));
 
                                return Err(ParseError::new_error_str_at_span(source, type_span, "expected a type but got a module"));
 
                            }
 

	
 
                            consume_token(source, iter, TokenKind::ColonColon)?;
 
@@ -1800,13 +1854,22 @@ fn consume_parser_type_ident(
 

	
 
                            let new_symbol = symbols.get_symbol_by_name_defined_in_scope(scope, type_text);
 
                            if new_symbol.is_none() {
 
                                return Err(ParseError::new_error_at_span(
 
                                    source, next_span,
 
                                // If the type is imported in the module then notify the programmer
 
                                // that imports do not leak outside of a module
 
                                let type_name = String::from_utf8_lossy(type_text);
 
                                let module_name = String::from_utf8_lossy(old_text);
 
                                let suffix = if symbols.get_symbol_by_name(scope, type_text).is_some() {
 
                                    format!(
 
                                        "unknown type '{}' in module '{}'",
 
                                        String::from_utf8_lossy(type_text),
 
                                        String::from_utf8_lossy(old_text)
 
                                        ". The module '{}' does import '{}', but these imports are not visible to other modules",
 
                                        &module_name, &type_name
 
                                    )
 
                                } else {
 
                                    String::new()
 
                                };
 

	
 
                                return Err(ParseError::new_error_at_span(
 
                                    source, next_span,
 
                                    format!("unknown type '{}' in module '{}'{}", type_name, module_name, suffix)
 
                                ));
 
                            }
 

	
src/protocol/parser/pass_imports.rs
Show inline comments
 
@@ -161,7 +161,6 @@ impl PassImport {
 

	
 
            if Some(TokenKind::Ident) == next {
 
                // Importing a single symbol
 
                iter.consume();
 
                let (imported_symbol, symbol_definition) = consume_symbol_and_maybe_alias(
 
                    &module.source, &mut iter, ctx, &module_identifier.value, target_root_id
 
                )?;
src/protocol/parser/pass_tokenizer.rs
Show inline comments
 
@@ -154,7 +154,7 @@ impl PassTokenizer {
 
        let last_registered_idx = target.ranges[0].end;
 
        let last_token_idx = target.tokens.len() as u32;
 
        if last_registered_idx != last_token_idx {
 
            self.add_code_range(target, 0, last_registered_idx, last_token_idx);
 
            self.add_code_range(target, 0, last_registered_idx, last_token_idx, NO_RELATION);
 
        }
 

	
 
        // TODO: @remove once I'm sure the algorithm works. For now it is better
 
@@ -644,11 +644,11 @@ impl PassTokenizer {
 

	
 
    fn add_code_range(
 
        &mut self, target: &mut TokenBuffer, parent_idx: i32,
 
        code_start_idx: u32, code_end_idx: u32
 
        code_start_idx: u32, code_end_idx: u32, next_sibling_idx: i32
 
    ) {
 
        let new_range_idx = target.ranges.len() as i32;
 
        let parent_range = &mut target.ranges[parent_idx as usize];
 
        debug_assert_ne!(parent_range.end, code_start_idx, "called push_code_range without a need to do so");
 
        debug_assert_ne!(parent_range.end, code_end_idx, "called push_code_range without a need to do so");
 

	
 
        let sibling_idx = parent_range.last_child_idx;
 

	
 
@@ -666,7 +666,7 @@ impl PassTokenizer {
 
            num_child_ranges: 0,
 
            first_child_idx: NO_RELATION,
 
            last_child_idx: NO_RELATION,
 
            next_sibling_idx: new_range_idx + 1, // we're going to push this range below
 
            next_sibling_idx,
 
        });
 

	
 
        // Fix up the sibling indices
 
@@ -687,7 +687,7 @@ impl PassTokenizer {
 

	
 
        let last_registered_idx = parent_range.end;
 
        if last_registered_idx != first_token_idx {
 
            self.add_code_range(target, parent_idx, last_registered_idx, first_token_idx);
 
            self.add_code_range(target, parent_idx, last_registered_idx, first_token_idx, new_range_idx + 1);
 
        }
 

	
 
        // Push the new range
 
@@ -798,9 +798,10 @@ fn is_integer_literal_start(c: u8) -> bool {
 
}
 

	
 
fn maybe_number_remaining(c: u8) -> bool {
 
    // Note: hex range includes the possible binary indicator 'b' and 'B';
 
    return
 
        (c == b'b' || c == b'B' || c == b'o' || c == b'O' || c == b'x' || c == b'X') ||
 
            (c >= b'0' && c <= b'9') ||
 
        (c == b'o' || c == b'O' || c == b'x' || c == b'X') ||
 
            (c >= b'0' && c <= b'9') || (c >= b'A' && c <= b'F') || (c >= b'a' && c <= b'f') ||
 
            c == b'_';
 
}
 

	
src/protocol/parser/pass_validation_linking.rs
Show inline comments
 
@@ -594,7 +594,7 @@ impl Visitor2 for PassValidationLinking {
 
                    let ast_definition = ctx.heap[literal.definition].as_union();
 
                    return Err(ParseError::new_error_at_span(
 
                        &ctx.module.source, literal.parser_type.elements[0].full_span, format!(
 
                            "the variant does '{}' does not exist on the union '{}'",
 
                            "the variant '{}' does not exist on the union '{}'",
 
                            literal.variant.value.as_str(), ast_definition.identifier.value.as_str()
 
                        )
 
                    ));
src/protocol/parser/symbol_table.rs
Show inline comments
 
@@ -191,8 +191,6 @@ impl SymbolTable {
 
        );
 
        debug_assert!(!self.scope_lookup.contains_key(&new_scope), "inserting scope {:?}, but it already exists", new_scope);
 

	
 
        println!("DEBUG: Inserting scope {:?} with parent {:?}", new_scope, parent_scope);
 

	
 
        if let Some(parent_scope) = parent_scope {
 
            let parent = self.scope_lookup.get_mut(&parent_scope).unwrap();
 
            parent.child_scopes.push(new_scope);
 
@@ -214,7 +212,6 @@ impl SymbolTable {
 
    // Note: we do not return a reference because Rust doesn't like it.
 
    pub(crate) fn insert_symbol(&mut self, in_scope: SymbolScope, symbol: Symbol) -> Result<(), (Symbol, Symbol)> {
 
        debug_assert!(self.scope_lookup.contains_key(&in_scope), "inserting symbol {}, but scope {:?} does not exist", symbol.name.as_str(), in_scope);
 
        println!("DEBUG: Inserting symbol {:?} in scope {:?}", symbol, in_scope);
 
        let mut seek_scope = in_scope;
 
        loop {
 
            let scoped_symbols = self.scope_lookup.get(&seek_scope).unwrap();
src/protocol/parser/token_parsing.rs
Show inline comments
 
@@ -283,6 +283,7 @@ pub(crate) fn consume_comma_separated<T, F, E>(
 

	
 
/// Consumes an integer literal, may be binary, octal, hexadecimal or decimal,
 
/// and may have separating '_'-characters.
 
/// TODO: @Cleanup, @Performance
 
pub(crate) fn consume_integer_literal(source: &InputSource, iter: &mut TokenIter, buffer: &mut String) -> Result<(u64, InputSpan), ParseError> {
 
    if Some(TokenKind::Integer) != iter.next() {
 
        return Err(ParseError::new_error_str_at_pos(source, iter.last_valid_pos(), "expected an integer literal"));
 
@@ -314,7 +315,8 @@ pub(crate) fn consume_integer_literal(source: &InputSource, iter: &mut TokenIter
 
        if char == b'_' {
 
            continue;
 
        }
 
        if !char.is_ascii_digit() {
 

	
 
        if !((char >= b'0' && char <= b'9') || (char >= b'A' && char <= b'F') || (char >= b'a' || char <= b'f')) {
 
            return Err(ParseError::new_error_at_span(
 
                source, integer_span,
 
                format!("incorrectly formatted {} number", radix_name)
src/protocol/tests/parser_imports.rs
Show inline comments
 
@@ -13,7 +13,7 @@ fn test_module_import() {
 
        ")
 
        .with_source("
 
        import external;
 
        s32 caller() {
 
        func caller() -> s32 {
 
            auto a = external::Foo{ field: 0 };
 
            return a.field;
 
        }
 
@@ -28,7 +28,7 @@ fn test_module_import() {
 
        ")
 
        .with_source("
 
        import external.domain;
 
        s32 caller() {
 
        func caller() -> s32 {
 
            auto a = domain::Foo{ field: 0 };
 
            return a.field;
 
        }
 
@@ -43,7 +43,7 @@ fn test_module_import() {
 
        ")
 
        .with_source("
 
        import external as aliased;
 
        s32 caller() {
 
        func caller() -> s32 {
 
            auto a = aliased::Foo{ field: 0 };
 
            return a.field;
 
        }
 
@@ -61,7 +61,7 @@ fn test_single_symbol_import() {
 
        ")
 
        .with_source("
 
        import external::Foo;
 
        s32 caller() {
 
        func caller() -> s32 {
 
            auto a = Foo{ field: 1 };
 
            auto b = Foo{ field: 2 };
 
            return a.field + b.field;
 
@@ -76,7 +76,7 @@ fn test_single_symbol_import() {
 
        ")
 
        .with_source("
 
        import external::Foo as Bar;
 
        s32 caller() {
 
        func caller() -> s32 {
 
            return Bar{ field: 0 }.field;
 
        }
 
        ")
 
@@ -107,7 +107,7 @@ fn test_multi_symbol_import() {
 
        ")
 
        .with_source("
 
        import external::{Foo, Bar};
 
        s8 caller() {
 
        func caller() -> s8 {
 
            return Foo{f:0}.f + Bar{b:1}.b;
 
        }
 
        ")
 
@@ -122,29 +122,28 @@ fn test_multi_symbol_import() {
 
        ")
 
        .with_source("
 
        import external::{Foo as Bar, Bar as Foo};
 
        s8 caller() {
 
        func caller() -> s8 {
 
            return Foo{in_bar:0}.in_bar + Bar{in_foo:0}.in_foo;    
 
        }")
 
        .compile()
 
        .expect_ok();
 

	
 
    // TODO: Re-enable once std lib is properly implemented
 
    // Tester::new("import all")
 
    //     .with_source("
 
    //     #module external
 
    //     struct Foo { s8 f };
 
    //     struct Bar { s8 b };
 
    //     ")
 
    //     .with_source("
 
    //     import external::*;
 
    //     s8 caller() {
 
    //         auto f = Foo{f:0};
 
    //         auto b = Bar{b:0};
 
    //         return f.f + b.b;
 
    //     }
 
    //     ")
 
    //     .compile()
 
    //     .expect_ok();
 
    Tester::new("import all")
 
        .with_source("
 
        #module external
 
        struct Foo { s8 f }
 
        struct Bar { s8 b }
 
        ")
 
        .with_source("
 
        import external::*;
 
        func caller() -> s8 {
 
            auto f = Foo{f:0};
 
            auto b = Bar{b:0};
 
            return f.f + b.b;
 
        }
 
        ")
 
        .compile()
 
        .expect_ok();
 
}
 

	
 
#[test]
 
@@ -156,7 +155,7 @@ fn test_illegal_import_use() {
 
        ")
 
        .with_source("
 
        import external;
 
        s8 caller() {
 
        func caller() -> s8 {
 
            auto foo = external::Foo<s32>{ f: 0 };
 
            return foo.f;
 
        }
 
@@ -164,7 +163,7 @@ fn test_illegal_import_use() {
 
        .compile()
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "the type Foo is not polymorphic");
 
            .assert_msg_has(0, "the type 'external::Foo' is not polymorphic");
 
        });
 

	
 
    Tester::new("mismatched polymorphic args")
 
@@ -174,7 +173,7 @@ fn test_illegal_import_use() {
 
        ")
 
        .with_source("
 
        import external;
 
        s8 caller() {
 
        func caller() -> s8 {
 
            auto foo = external::Foo<s8, s32>{ f: 0 };
 
            return foo.f;
 
        }")
 
@@ -182,7 +181,7 @@ fn test_illegal_import_use() {
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "expected 1 polymorphic")
 
            .assert_msg_has(0, "2 were specified");
 
            .assert_msg_has(0, "2 were provided");
 
        });
 

	
 
    Tester::new("module as type")
 
@@ -191,7 +190,7 @@ fn test_illegal_import_use() {
 
        ")
 
        .with_source("
 
        import external;
 
        s8 caller() {
 
        func caller() -> s8 {
 
            auto foo = external{ f: 0 };
 
            return 0;
 
        }
 
@@ -199,25 +198,22 @@ fn test_illegal_import_use() {
 
        .compile()
 
        .expect_err()
 
        .error(|e| { e
 
            .assert_msg_has(0, "resolved to a namespace");
 
            .assert_msg_has(0, "expected a type but got a module");
 
        });
 

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

	
 
    Tester::new("import from another import")
 
@@ -232,14 +228,15 @@ fn test_illegal_import_use() {
 
        ")
 
        .with_source("
 
        import mod2;
 
        s8 caller() {
 
        func caller() -> s8 {
 
            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");
 
            .assert_msg_has(0, "unknown type 'Foo' in module 'mod2'")
 
            .assert_msg_has(0, "module 'mod2' does import 'Foo'")
 
            .assert_occurs_at(0, "Foo");
 
        });
 
}
 
\ No newline at end of file
src/protocol/tests/parser_inference.rs
Show inline comments
 
@@ -159,61 +159,61 @@ fn test_struct_inference() {
 
        });
 
    });
 

	
 
    // Tester::new_single_source_expect_ok(
 
    //     "by field access",
 
    //     "
 
    //     struct Pair<T1, T2>{ T1 first, T2 second }
 
    //     func construct<T1, T2>(T1 first, T2 second) -> Pair<T1, T2> {
 
    //         return Pair{ first: first, second: second };
 
    //     }
 
    //     test() -> s32 {
 
    //         auto first = 0;
 
    //         auto second = 1;
 
    //         auto pair = construct(first, second);
 
    //         s8 assign_first = 0;
 
    //         s64 assign_second = 1;
 
    //         pair.first = assign_first;
 
    //         pair.second = assign_second;
 
    //         return 0;
 
    //     }
 
    //     "
 
    // ).for_function("test", |f| { f
 
    //     .for_variable("first", |v| { v
 
    //         .assert_parser_type("auto")
 
    //         .assert_concrete_type("s8");
 
    //     })
 
    //     .for_variable("second", |v| { v
 
    //         .assert_parser_type("auto")
 
    //         .assert_concrete_type("s64");
 
    //     })
 
    //     .for_variable("pair", |v| { v
 
    //         .assert_parser_type("auto")
 
    //         .assert_concrete_type("Pair<s8,s64>");
 
    //     });
 
    // });
 
    //
 
    // Tester::new_single_source_expect_ok(
 
    //     "by nested field access",
 
    //     "
 
    //     struct Node<T1, T2>{ T1 l, T2 r }
 
    //     func construct<T1, T2>(T1 l, T2 r) -> Node<T1, T2> {
 
    //         return Node{ l: l, r: r };
 
    //     }
 
    //     func fix_poly<T>(Node<T, T> a) -> s32 { return 0; }
 
    //     func test() -> s32 {
 
    //         s8 assigned = 0;
 
    //         auto thing = construct(assigned, construct(0, 1));
 
    //         fix_poly(thing.r);
 
    //         thing.r.r = assigned;
 
    //         return 0;
 
    //     }
 
    //     ",
 
    // ).for_function("test", |f| { f
 
    //     .for_variable("thing", |v| { v
 
    //         .assert_parser_type("auto")
 
    //         .assert_concrete_type("Node<s8,Node<s8,s8>>");
 
    //     });
 
    // });
 
    Tester::new_single_source_expect_ok(
 
        "by field access",
 
        "
 
        struct Pair<T1, T2>{ T1 first, T2 second }
 
        func construct<T1, T2>(T1 first, T2 second) -> Pair<T1, T2> {
 
            return Pair{ first: first, second: second };
 
        }
 
        func test() -> s32 {
 
            auto first = 0;
 
            auto second = 1;
 
            auto pair = construct(first, second);
 
            s8 assign_first = 0;
 
            s64 assign_second = 1;
 
            pair.first = assign_first;
 
            pair.second = assign_second;
 
            return 0;
 
        }
 
        "
 
    ).for_function("test", |f| { f
 
        .for_variable("first", |v| { v
 
            .assert_parser_type("auto")
 
            .assert_concrete_type("s8");
 
        })
 
        .for_variable("second", |v| { v
 
            .assert_parser_type("auto")
 
            .assert_concrete_type("s64");
 
        })
 
        .for_variable("pair", |v| { v
 
            .assert_parser_type("auto")
 
            .assert_concrete_type("Pair<s8,s64>");
 
        });
 
    });
 

	
 
    Tester::new_single_source_expect_ok(
 
        "by nested field access",
 
        "
 
        struct Node<T1, T2>{ T1 l, T2 r }
 
        func construct<T1, T2>(T1 l, T2 r) -> Node<T1, T2> {
 
            return Node{ l: l, r: r };
 
        }
 
        func fix_poly<T>(Node<T, T> a) -> s32 { return 0; }
 
        func test() -> s32 {
 
            s8 assigned = 0;
 
            auto thing = construct(assigned, construct(0, 1));
 
            fix_poly(thing.r);
 
            thing.r.r = assigned;
 
            return 0;
 
        }
 
        ",
 
    ).for_function("test", |f| { f
 
        .for_variable("thing", |v| { v
 
            .assert_parser_type("auto")
 
            .assert_concrete_type("Node<s8,Node<s8,s8>>");
 
        });
 
    });
 
}
 

	
 
#[test]
 
@@ -222,7 +222,7 @@ fn test_enum_inference() {
 
        "no polymorphic vars",
 
        "
 
        enum Choice { A, B }
 
        test_instances() -> s32 {
 
        func test_instances() -> s32 {
 
            auto foo = Choice::A;
 
            auto bar = Choice::B;
 
            return 0;
 
@@ -247,14 +247,14 @@ fn test_enum_inference() {
 
            B,
 
        }
 
        func fix_as_s8(Choice<s8> arg) -> s32 { return 0; }
 
        fix_as_s32(Choice<s32> arg) -> s32 { return 0; }
 
        test_instances() -> s32 {
 
        func fix_as_s32(Choice<s32> arg) -> s32 { return 0; }
 
        func test_instances() -> s32 {
 
            auto choice_s8 = Choice::A;
 
            auto choice_s32_1 = Choice::B;
 
            Choice<auto> choice_s32_2 = Choice::B;
 
            fix_as_s8(choice_s8);
 
            fix_as_s32(choice_s32_1);
 
            return fix_as_int(choice_s32_2);
 
            return fix_as_s32(choice_s32_2);
 
        }
 
        "
 
    ).for_function("test_instances", |f| { f
 
@@ -262,13 +262,13 @@ fn test_enum_inference() {
 
            .assert_parser_type("auto")
 
            .assert_concrete_type("Choice<s8>");
 
        })
 
        .for_variable("choice_int1", |v| { v
 
        .for_variable("choice_s32_1", |v| { v
 
            .assert_parser_type("auto")
 
            .assert_concrete_type("Choice<int>");
 
            .assert_concrete_type("Choice<s32>");
 
        })
 
        .for_variable("choice_int2", |v| { v
 
        .for_variable("choice_s32_2", |v| { v
 
            .assert_parser_type("Choice<auto>")
 
            .assert_concrete_type("Choice<int>");
 
            .assert_concrete_type("Choice<s32>");
 
        });
 
    });
 

	
 
@@ -276,11 +276,11 @@ fn test_enum_inference() {
 
        "two polymorphic vars",
 
        "
 
        enum Choice<T1, T2>{ A, B, }
 
        fix_t1<T>(Choice<s8, T> arg) -> s32 { return 0; }
 
        fix_t2<T>(Choice<T, int> arg) -> s32 { return 0; }
 
        test_instances() -> int {
 
        func fix_t1<T>(Choice<s8, T> arg) -> s32 { return 0; }
 
        func fix_t2<T>(Choice<T, s32> arg) -> s32 { return 0; }
 
        func test_instances() -> s32 {
 
            Choice<s8, auto> choice1 = Choice::A;
 
            Choice<auto, int> choice2 = Choice::A;
 
            Choice<auto, s32> choice2 = Choice::A;
 
            Choice<auto, auto> choice3 = Choice::B;
 
            auto choice4 = Choice::B;
 
            fix_t1(choice1); fix_t1(choice2); fix_t1(choice3); fix_t1(choice4);
 
@@ -291,19 +291,19 @@ fn test_enum_inference() {
 
    ).for_function("test_instances", |f| { f
 
        .for_variable("choice1", |v| { v
 
            .assert_parser_type("Choice<s8,auto>")
 
            .assert_concrete_type("Choice<s8,int>");
 
            .assert_concrete_type("Choice<s8,s32>");
 
        })
 
        .for_variable("choice2", |v| { v
 
            .assert_parser_type("Choice<auto,int>")
 
            .assert_concrete_type("Choice<s8,int>");
 
            .assert_parser_type("Choice<auto,s32>")
 
            .assert_concrete_type("Choice<s8,s32>");
 
        })
 
        .for_variable("choice3", |v| { v
 
            .assert_parser_type("Choice<auto,auto>")
 
            .assert_concrete_type("Choice<s8,int>");
 
            .assert_concrete_type("Choice<s8,s32>");
 
        })
 
        .for_variable("choice4", |v| { v
 
            .assert_parser_type("auto")
 
            .assert_concrete_type("Choice<s8,int>");
 
            .assert_concrete_type("Choice<s8,s32>");
 
        });
 
    });
 
}
 
@@ -335,7 +335,7 @@ fn test_failed_polymorph_inference() {
 
        "struct literal inference mismatch",
 
        "
 
        struct Pair<T>{ T first, T second }
 
        call() -> s32 {
 
        func call() -> s32 {
 
            s8 first_arg = 5;
 
            s64 second_arg = 2;
 
            auto pair = Pair{ first: first_arg, second: second_arg };
 
@@ -362,14 +362,14 @@ fn test_failed_polymorph_inference() {
 
        func call() -> s32 {
 
            auto a = Uninteresting::Variant;
 
            fix_t<s8>(a);
 
            fix_t<int>(a);
 
            fix_t<s32>(a);
 
            return 4;
 
        }
 
        "
 
    ).error(|e| { e
 
        .assert_num(2)
 
        .assert_any_msg_has("type 'Uninteresting<s8>'")
 
        .assert_any_msg_has("type 'Uninteresting<int>'");
 
        .assert_any_msg_has("type 'Uninteresting<s32>'");
 
    });
 

	
 
    Tester::new_single_source_expect_err(
 
@@ -388,7 +388,7 @@ fn test_failed_polymorph_inference() {
 
        .assert_occurs_at(0, ".")
 
        .assert_msg_has(0, "Conflicting type for polymorphic variable 'Shazam'")
 
        .assert_msg_has(1, "inferred it to 's8'")
 
        .assert_msg_has(2, "inferred it to 'int'");
 
        .assert_msg_has(2, "inferred it to 's32'");
 
    });
 

	
 
    // TODO: Needs better error messages anyway, but this failed before
src/protocol/tests/parser_monomorphs.rs
Show inline comments
 
@@ -18,7 +18,7 @@ fn test_struct_monomorphs() {
 
        "single polymorph",
 
        "
 
        struct Number<T>{ T number }
 
        s32 instantiator() {
 
        func instantiator() -> s32 {
 
            auto a = Number<s8>{ number: 0 };
 
            auto b = Number<s8>{ number: 1 };
 
            auto c = Number<s32>{ number: 2 };
 
@@ -46,7 +46,7 @@ fn test_enum_monomorphs() {
 
        "no polymorph",
 
        "
 
        enum Answer{ Yes, No }
 
        s32 do_it() { auto a = Answer::Yes; return 0; }
 
        func do_it() -> s32 { auto a = Answer::Yes; return 0; }
 
        "
 
    ).for_enum("Answer", |e| { e
 
        .assert_num_monomorphs(0);
 
@@ -56,7 +56,7 @@ fn test_enum_monomorphs() {
 
        "single polymorph",
 
        "
 
        enum Answer<T> { Yes, No }
 
        s32 instantiator() {
 
        func instantiator() -> s32 {
 
            auto a = Answer<s8>::Yes;
 
            auto b = Answer<s8>::No;
 
            auto c = Answer<s32>::Yes;
 
@@ -77,8 +77,8 @@ fn test_union_monomorphs() {
 
    Tester::new_single_source_expect_ok(
 
        "no polymorph",
 
        "
 
        union Trinary { Undefined, Value(boolean) }
 
        s32 do_it() { auto a = Trinary::Value(true); return 0; }
 
        union Trinary { Undefined, Value(bool) }
 
        func do_it() -> s32 { auto a = Trinary::Value(true); return 0; }
 
        "
 
    ).for_union("Trinary", |e| { e
 
        .assert_num_monomorphs(0);
 
@@ -90,10 +90,10 @@ fn test_union_monomorphs() {
 
        "polymorphs",
 
        "
 
        union Result<T, E>{ Ok(T), Err(E) }
 
        s32 instantiator() {
 
        func instantiator() -> s32 {
 
            s16 a_s16 = 5;
 
            auto a = Result<s8, boolean>::Ok(0);
 
            auto b = Result<boolean, s8>::Ok(true);
 
            auto a = Result<s8, bool>::Ok(0);
 
            auto b = Result<bool, s8>::Ok(true);
 
            auto c = Result<Result<s8, s32>, Result<s16, s64>>::Err(Result::Ok(5));
 
            auto d = Result<Result<s8, s32>, auto>::Err(Result<auto, s64>::Ok(a_s16));
 
            return 0;
src/protocol/tests/parser_validation.rs
Show inline comments
 
@@ -11,7 +11,7 @@ fn test_correct_struct_instance() {
 
        "single field",
 
        "
 
        struct Foo { s32 a }
 
        Foo bar(s32 arg) { return Foo{ a: arg }; }
 
        func bar(s32 arg) -> Foo { return Foo{ a: arg }; }
 
        "
 
    );
 

	
 
@@ -19,7 +19,7 @@ fn test_correct_struct_instance() {
 
        "multiple fields",
 
        "
 
        struct Foo { s32 a, s32 b }
 
        Foo bar(s32 arg) { return Foo{ a: arg, b: arg }; }
 
        func bar(s32 arg) -> Foo { return Foo{ a: arg, b: arg }; }
 
        "
 
    );
 

	
 
@@ -27,7 +27,7 @@ fn test_correct_struct_instance() {
 
        "single field, explicit polymorph",
 
        "
 
        struct Foo<T>{ T field }
 
        Foo<s32> bar(s32 arg) { return Foo<s32>{ field: arg }; }
 
        func bar(s32 arg) -> Foo<s32> { return Foo<s32>{ field: arg }; }
 
        "
 
    );
 

	
 
@@ -35,7 +35,7 @@ fn test_correct_struct_instance() {
 
        "single field, implicit polymorph",
 
        "
 
        struct Foo<T>{ T field }
 
        s32 bar(s32 arg) {
 
        func bar(s32 arg) -> s32 {
 
            auto thingo = Foo{ field: arg };
 
            return arg;
 
        }
 
@@ -46,7 +46,7 @@ fn test_correct_struct_instance() {
 
        "multiple fields, same explicit polymorph",
 
        "
 
        struct Pair<T1, T2>{ T1 first, T2 second }
 
        s32 bar(s32 arg) {
 
        func bar(s32 arg) -> s32 {
 
            auto qux = Pair<s32, s32>{ first: arg, second: arg };
 
            return arg;
 
        }
 
@@ -57,7 +57,7 @@ fn test_correct_struct_instance() {
 
        "multiple fields, same implicit polymorph", 
 
        "
 
        struct Pair<T1, T2>{ T1 first, T2 second }
 
        s32 bar(s32 arg) {
 
        func bar(s32 arg) -> s32 {
 
            auto wup = Pair{ first: arg, second: arg };
 
            return arg;
 
        }
 
@@ -68,7 +68,7 @@ fn test_correct_struct_instance() {
 
        "multiple fields, different explicit polymorph",
 
        "
 
        struct Pair<T1, T2>{ T1 first, T2 second }
 
        s32 bar(s32 arg1, s8 arg2) {
 
        func bar(s32 arg1, s8 arg2) -> s32 {
 
            auto shoo = Pair<s32, s8>{ first: arg1, second: arg2 };
 
            return arg1;
 
        }
 
@@ -79,7 +79,7 @@ fn test_correct_struct_instance() {
 
        "multiple fields, different implicit polymorph",
 
        "
 
        struct Pair<T1, T2>{ T1 first, T2 second }
 
        s32 bar(s32 arg1, s8 arg2) {
 
        func bar(s32 arg1, s8 arg2) -> s32 {
 
            auto shrubbery = Pair{ first: arg1, second: arg2 };
 
            return arg1;
 
        }
 
@@ -103,8 +103,8 @@ fn test_incorrect_struct_instance() {
 
    Tester::new_single_source_expect_err(
 
        "reused field in instance",
 
        "
 
        struct Foo{ int a, int b }
 
        int bar() {
 
        struct Foo{ s32 a, s32 b }
 
        func bar() -> s32 {
 
            auto foo = Foo{ a: 5, a: 3 };
 
            return 0;
 
        }
 
@@ -117,8 +117,8 @@ fn test_incorrect_struct_instance() {
 
    Tester::new_single_source_expect_err(
 
        "missing field",
 
        "
 
        struct Foo { int a, int b }
 
        int bar() {
 
        struct Foo { s32 a, s32 b }
 
        func bar() -> s32 {
 
            auto foo = Foo{ a: 2 };
 
            return 0;
 
        }
 
@@ -131,8 +131,8 @@ fn test_incorrect_struct_instance() {
 
    Tester::new_single_source_expect_err(
 
        "missing fields",
 
        "
 
        struct Foo { int a, int b, int c }
 
        int bar() {
 
        struct Foo { s32 a, s32 b, s32 c }
 
        func bar() -> s32 {
 
            auto foo = Foo{ a: 2 };
 
            return 0;
 
        }
 
@@ -149,7 +149,7 @@ fn test_correct_enum_instance() {
 
        "single variant",
 
        "
 
        enum Foo { A }
 
        Foo bar() { return Foo::A; }
 
        func bar() -> Foo { return Foo::A; }
 
        "
 
    );
 

	
 
@@ -157,7 +157,7 @@ fn test_correct_enum_instance() {
 
        "multiple variants",
 
        "
 
        enum Foo { A=15, B = 0xF }
 
        Foo bar() { auto a = Foo::A; return Foo::B; }
 
        func bar() -> Foo { auto a = Foo::A; return Foo::B; }
 
        "
 
    );
 

	
 
@@ -165,7 +165,7 @@ fn test_correct_enum_instance() {
 
        "explicit single polymorph",
 
        "
 
        enum Foo<T>{ A }
 
        Foo<int> bar() { return Foo::A; }
 
        func bar() -> Foo<s32> { return Foo::A; }
 
        "
 
    );
 

	
 
@@ -173,7 +173,7 @@ fn test_correct_enum_instance() {
 
        "explicit multi-polymorph",
 
        "
 
        enum Foo<A, B>{ A, B }
 
        Foo<s8, int> bar() { return Foo::B; }
 
        func bar() -> Foo<s8, s32> { return Foo::B; }
 
        "
 
    );
 
}
 
@@ -184,7 +184,7 @@ fn test_incorrect_enum_instance() {
 
        "variant name reuse",
 
        "
 
        enum Foo { A, A }
 
        Foo bar() { return Foo::A; }
 
        func bar() -> Foo { return Foo::A; }
 
        "
 
    ).error(|e| { e
 
        .assert_num(2)
 
@@ -198,7 +198,7 @@ fn test_incorrect_enum_instance() {
 
        "undefined variant",
 
        "
 
        enum Foo { A }
 
        Foo bar() { return Foo::B; }
 
        func bar() -> Foo { return Foo::B; }
 
        "
 
    ).error(|e| { e
 
        .assert_num(1)
 
@@ -212,7 +212,7 @@ fn test_correct_union_instance() {
 
        "single tag",
 
        "
 
        union Foo { A }
 
        Foo bar() { return Foo::A; }
 
        func bar() -> Foo { return Foo::A; }
 
        "
 
    );
 

	
 
@@ -220,39 +220,39 @@ fn test_correct_union_instance() {
 
        "multiple tags",
 
        "
 
        union Foo { A, B }
 
        Foo bar() { return Foo::B; }
 
        func bar() -> Foo { return Foo::B; }
 
        "
 
    );
 

	
 
    Tester::new_single_source_expect_ok(
 
        "single embedded",
 
        "
 
        union Foo { A(int) }
 
        Foo bar() { return Foo::A(5); }
 
        union Foo { A(s32) }
 
        func bar() -> Foo { return Foo::A(5); }
 
        "
 
    );
 

	
 
    Tester::new_single_source_expect_ok(
 
        "multiple embedded",
 
        "
 
        union Foo { A(int), B(s8) }
 
        Foo bar() { return Foo::B(2); }
 
        union Foo { A(s32), B(s8) }
 
        func bar() -> Foo { return Foo::B(2); }
 
        "
 
    );
 

	
 
    Tester::new_single_source_expect_ok(
 
        "multiple values in embedded",
 
        "
 
        union Foo { A(int, s8) }
 
        Foo bar() { return Foo::A(0, 2); }
 
        union Foo { A(s32, s8) }
 
        func bar() -> Foo { return Foo::A(0, 2); }
 
        "
 
    );
 

	
 
    Tester::new_single_source_expect_ok(
 
        "mixed tag/embedded",
 
        "
 
        union OptionInt { None, Some(int) }
 
        OptionInt bar() { return OptionInt::Some(3); } 
 
        union OptionInt { None, Some(s32) }
 
        func bar() -> OptionInt { return OptionInt::Some(3); }
 
        "
 
    );
 

	
 
@@ -260,14 +260,14 @@ fn test_correct_union_instance() {
 
        "single polymorphic var",
 
        "
 
        union Option<T> { None, Some(T) }
 
        Option<int> bar() { return Option::Some(3); }"
 
        func bar() -> Option<s32> { return Option::Some(3); }"
 
    );
 

	
 
    Tester::new_single_source_expect_ok(
 
        "multiple polymorphic vars",
 
        "
 
        union Result<T, E> { Ok(T), Err(E), }
 
        Result<int, s8> bar() { return Result::Ok(3); }
 
        func bar() -> Result<s32, s8> { return Result::Ok(3); }
 
        "
 
    );
 

	
 
@@ -275,7 +275,7 @@ fn test_correct_union_instance() {
 
        "multiple polymorphic in one variant",
 
        "
 
        union MaybePair<T1, T2>{ None, Some(T1, T2) }
 
        MaybePair<s8, int> bar() { return MaybePair::Some(1, 2); }
 
        func bar() -> MaybePair<s8, s32> { return MaybePair::Some(1, 2); }
 
        "
 
    );
 
}
 
@@ -298,13 +298,13 @@ fn test_incorrect_union_instance() {
 
    Tester::new_single_source_expect_err(
 
        "embedded-variant name reuse",
 
        "
 
        union Foo{ A(int), A(s8) }
 
        union Foo{ A(s32), A(s8) }
 
        "
 
    ).error(|e| { e 
 
        .assert_num(2)
 
        .assert_occurs_at(0, "A(s8)")
 
        .assert_msg_has(0, "union variant is defined more than once")
 
        .assert_occurs_at(1, "A(int)")
 
        .assert_occurs_at(1, "A(s32)")
 
        .assert_msg_has(1, "other union variant");
 
    });
 

	
 
@@ -312,7 +312,7 @@ fn test_incorrect_union_instance() {
 
        "undefined variant",
 
        "
 
        union Silly{ Thing(s8) }
 
        Silly bar() { return Silly::Undefined(5); }
 
        func bar() -> Silly { return Silly::Undefined(5); }
 
        "
 
    ).error(|e| { e
 
        .assert_msg_has(0, "variant 'Undefined' does not exist on the union 'Silly'");
 
@@ -321,8 +321,8 @@ fn test_incorrect_union_instance() {
 
    Tester::new_single_source_expect_err(
 
        "using tag instead of embedded",
 
        "
 
        union Foo{ A(int) }
 
        Foo bar() { return Foo::A; }
 
        union Foo{ A(s32) }
 
        func bar() -> Foo { return Foo::A; }
 
        "
 
    ).error(|e| { e
 
        .assert_msg_has(0, "variant 'A' of union 'Foo' expects 1 embedded values, but 0 were");
 
@@ -332,7 +332,7 @@ fn test_incorrect_union_instance() {
 
        "using embedded instead of tag",
 
        "
 
        union Foo{ A }
 
        Foo bar() { return Foo::A(3); }
 
        func bar() -> Foo { return Foo::A(3); }
 
        "
 
    ).error(|e| { e 
 
        .assert_msg_has(0, "The variant 'A' of union 'Foo' expects 0");
 
@@ -341,14 +341,14 @@ fn test_incorrect_union_instance() {
 
    Tester::new_single_source_expect_err(
 
        "wrong embedded value",
 
        "
 
        union Foo{ A(int) }
 
        Foo bar() { return Foo::A(false); }
 
        union Foo{ A(s32) }
 
        func bar() -> Foo { return Foo::A(false); }
 
        "
 
    ).error(|e| { e
 
        .assert_occurs_at(0, "Foo::A")
 
        .assert_msg_has(0, "Failed to fully resolve")
 
        .assert_msg_has(0, "failed to fully resolve")
 
        .assert_occurs_at(1, "false")
 
        .assert_msg_has(1, "has been resolved to 'int'")
 
        .assert_msg_has(1, "has been resolved to 's32'")
 
        .assert_msg_has(1, "has been resolved to 'bool'");
 
    });
 
}
 
\ No newline at end of file
src/protocol/tests/utils.rs
Show inline comments
 
@@ -124,7 +124,7 @@ pub(crate) struct AstOkTester {
 
    heap: Heap,
 
    symbols: SymbolTable,
 
    types: TypeTable,
 
    pool: StringPool,
 
    pool: StringPool, // This is stored because if we drop it on the floor, we lose all our `StringRef<'static>`s
 
}
 

	
 
impl AstOkTester {
 
@@ -212,7 +212,6 @@ impl AstOkTester {
 
        let mut found = false;
 
        for definition in self.heap.definitions.iter() {
 
            if let Definition::Function(definition) = definition {
 
                println!("DEBUG: Have {}", definition.identifier.value.as_str());
 
                if definition.identifier.value.as_str() != name {
 
                    continue;
 
                }
 
@@ -222,8 +221,6 @@ impl AstOkTester {
 
                f(tester);
 
                found = true;
 
                break;
 
            } else {
 
                println!("DEBUG: Have (not a function, but) {}", definition.identifier().value.as_str());
 
            }
 
        }
 

	
0 comments (0 inline, 0 general)