Changeset - 392c59600687
[Not reviewed]
0 3 0
mh - 4 years ago 2021-05-31 11:37:55
contact@maxhenger.nl
Test non-ascii string literals and recursion
3 files changed with 57 insertions and 1 deletions:
0 comments (0 inline, 0 general)
src/protocol/input_source.rs
Show inline comments
 
@@ -147,49 +147,48 @@ impl InputSource {
 

	
 
        // Lookup was not constructed yet
 
        let mut lookup = self.offset_lookup.write().unwrap();
 
        if !lookup.is_empty() {
 
            // Somebody created it before we had the chance
 
            drop(lookup);
 
            let lookup = self.offset_lookup.read().unwrap();
 
            return lookup;
 
        }
 

	
 
        // Build the line number (!) to offset lookup, so offset by 1. We 
 
        // assume the entire source file is scanned (most common case) for
 
        // preallocation.
 
        lookup.reserve(self.line as usize + 2);
 
        lookup.push(0); // line 0: never used
 
        lookup.push(0); // first line: first character
 

	
 
        for char_idx in 0..self.input.len() {
 
            if self.input[char_idx] == b'\n' {
 
                lookup.push(char_idx as u32 + 1);
 
            }
 
        }
 

	
 
        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
 
        drop(lookup);
 
        let lookup = self.offset_lookup.read().unwrap();
 
        return lookup;
 
    }
 

	
 
    /// Retrieves offset at which line starts (right after newline)
 
    fn lookup_line_start_offset(&self, line_number: u32) -> u32 {
 
        let lookup = self.get_lookup();
 
        lookup[line_number as usize]
 
    }
 

	
 
    /// Retrieves offset at which line ends (at the newline character or the
 
    /// preceding carriage feed for \r\n-encoded newlines)
 
    fn lookup_line_end_offset(&self, line_number: u32) -> u32 {
 
        let lookup = self.get_lookup();
 
        let offset = lookup[(line_number + 1) as usize] - 1;
 
        let offset_usize = offset as usize;
 

	
 
        // 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' {
src/protocol/tests/eval_calls.rs
Show inline comments
 
@@ -6,36 +6,88 @@ fn test_function_call() {
 
    func add_two(u32 value) -> u32 {
 
        return value + 2;
 
    }
 
    func foo() -> u32 {
 
        return add_two(5);
 
    }
 
    ").for_function("foo", |f| {
 
        f.call_ok(Some(Value::UInt32(7)));
 
    });
 

	
 
    Tester::new_single_source_expect_ok("with variable arg", "
 
    func add_two(u32 value) -> u32 {
 
        value += 1;
 
        return value + 1;
 
    }
 
    func foo() -> bool {
 
        auto initial = 5;
 
        auto result = add_two(initial);
 
        return initial == 5 && result == 7;
 
    }").for_function("foo", |f| {
 
        f.call_ok(Some(Value::Bool(true)));
 
    });
 
}
 

	
 
#[test]
 
fn test_recursion() {
 
    // Single-chain
 
    Tester::new_single_source_expect_ok("factorial", "
 
    func horribly_slow_factorial(u32 term) -> u32 {
 
        if (term <= 0) { return 1; }
 

	
 
        return term * horribly_slow_factorial(term - 1);
 
    }
 
    func foo() -> u32 {
 
        return horribly_slow_factorial(10);
 
    }
 
    ").for_function("foo", |f| {
 
        f.call_ok(Some(Value::UInt32(3628800)));
 
    });
 

	
 
    // Multi-chain horribleness
 
    Tester::new_single_source_expect_ok("fibonacci", "
 
    func horribly_slow_fibo(u32 term) -> u32 {
 
        if (term <= 1) {
 
            return 1;
 
        }
 
        return horribly_slow_fibo(term - 2) + horribly_slow_fibo(term - 1);
 
    }
 
    func foo() -> u32 {
 
        return horribly_slow_fibo(10);
 
    }").for_function("foo", |f| {
 
        f.call_ok(Some(Value::UInt32(89)));
 
    });
 

	
 
    // Mutual recursion (in a contrived fashion, ofcourse)
 
    Tester::new_single_source_expect_ok("mutual recursion", "
 
    func collatz_even(u32 iter, u32 value) -> u32 {
 
        value = value / 2;
 
        if (value % 2 == 0) return collatz_even(iter + 1, value);
 
        else                return collatz_odd(iter + 1, value);
 
    }
 
    func collatz_odd(u32 iter, u32 value) -> u32 {
 
        if (value <= 1) return iter;
 

	
 
        value = 3 * value + 1;
 
        if (value % 2 == 0) return collatz_even(iter + 1, value);
 
        else                return collatz_odd(iter + 1, value);
 
    }
 
    func foo() -> u32 {
 
        return collatz_odd(1, 19);
 
    }
 
    ").for_function("foo", |f| {
 
        f.call_ok(Some(Value::UInt32(21)));
 
    });
 
}
 

	
 
#[test]
 
fn test_empty_blocks() {
 
    // Yes this is silly, but I managed to make this a bug before
 
    Tester::new_single_source_expect_ok("traversing empty statements", "
 
    func foo() -> u32 {
 
        auto val = 128;
 
        if (true) {}
 
        while (false) {}
 
        return val;
 
    }
 
    ").for_function("foo", |f| { f.call_ok(Some(Value::UInt32(128))); });
 
}
 
\ No newline at end of file
src/protocol/tests/parser_literals.rs
Show inline comments
 
@@ -41,25 +41,30 @@ fn test_string_literals() {
 
        .for_variable("v1", |v| { v.assert_concrete_type("string"); })
 
        .for_variable("v2", |v| { v.assert_concrete_type("string"); })
 
        .for_variable("v3", |v| { v.assert_concrete_type("string"); });
 
    });
 

	
 
    Tester::new_single_source_expect_err("unterminated simple", "
 
        func test() -> string { return \"'; }
 
    ").error(|e| { e
 
        .assert_num(1)
 
        .assert_occurs_at(0, "\"")
 
        .assert_msg_has(0, "unterminated");
 
    });
 

	
 
    Tester::new_single_source_expect_err("unterminated with preceding escaped", "
 
        func test() -> string { return \"\\\"; }
 
    ").error(|e| { e
 
        .assert_num(1)
 
        .assert_occurs_at(0, "\"\\")
 
        .assert_msg_has(0, "unterminated");
 
    });
 

	
 
    Tester::new_single_source_expect_err("invalid escaped character", "
 
        func test() -> string { return \"\\y\"; }
 
    ").error(|e| { e.assert_msg_has(0, "unsupported escape character 'y'"); });
 

	
 
    // Note sure if this should always be in here...
 
    Tester::new_single_source_expect_err("non-ASCII string", "
 
        func test() -> string { return \"💧\"; }
 
    ").error(|e| { e.assert_msg_has(0, "non-ASCII character in string literal"); });
 
}
 
\ No newline at end of file
0 comments (0 inline, 0 general)