Changeset - 622cf123a4e6
[Not reviewed]
0 9 0
MH - 4 years ago 2021-05-27 18:56:55
contact@maxhenger.nl
Add concatenation assignment
9 files changed with 69 insertions and 12 deletions:
0 comments (0 inline, 0 general)
src/protocol/ast.rs
Show inline comments
 
@@ -1279,6 +1279,7 @@ impl Expression {
 
#[derive(Debug, Clone, Copy)]
 
pub enum AssignmentOperator {
 
    Set,
 
    Concatenated,
 
    Multiplied,
 
    Divided,
 
    Remained,
src/protocol/eval/executor.rs
Show inline comments
 
@@ -729,7 +729,7 @@ impl Prompt {
 
            debug_log!("Heap:");
 
            for (_heap_idx, _heap_region) in self.store.heap_regions.iter().enumerate() {
 
                let _is_free = self.store.free_regions.iter().any(|idx| *idx as usize == _heap_idx);
 
                debug_log!("  [{:03}] in_use: {}, len: {}, vals: {:?}", _heap_idx, !_is_free, heap_region.values.len(), &_heap_region.values);
 
                debug_log!("  [{:03}] in_use: {}, len: {}, vals: {:?}", _heap_idx, !_is_free, _heap_region.values.len(), &_heap_region.values);
 
            }
 
        }
 
        // No (more) expressions to evaluate. So evaluate statement (that may
src/protocol/eval/value.rs
Show inline comments
 
@@ -261,6 +261,8 @@ impl Default for ValueGroup {
 
    }
 
}
 

	
 
enum ValueKind { Message, String, Array }
 

	
 
pub(crate) fn apply_assignment_operator(store: &mut Store, lhs: ValueId, op: AssignmentOperator, rhs: Value) {
 
    use AssignmentOperator as AO;
 

	
 
@@ -280,7 +282,6 @@ pub(crate) fn apply_assignment_operator(store: &mut Store, lhs: ValueId, op: Ass
 
        }
 
    }
 

	
 
    // let rhs = store.maybe_read_ref(&rhs).clone(); // we don't own this thing, so don't drop it
 
    let lhs = store.read_mut_ref(lhs);
 

	
 
    let mut to_dealloc = None;
 
@@ -314,6 +315,28 @@ pub(crate) fn apply_assignment_operator(store: &mut Store, lhs: ValueId, op: Ass
 
                _ => unreachable!("apply_assignment_operator {:?} on lhs {:?} and rhs {:?}", op, lhs, rhs),
 
            }
 
        },
 
        AO::Concatenated => {
 
            let lhs_heap_pos = lhs.get_heap_pos().unwrap() as usize;
 
            let rhs_heap_pos = rhs.get_heap_pos().unwrap() as usize;
 

	
 
            // To prevent borrowing crap, swap out heap region with a temp empty array
 
            let mut total = Vec::new();
 
            std::mem::swap(&mut total, &mut store.heap_regions[lhs_heap_pos].values);
 

	
 
            // Push everything onto the swapped vector
 
            let rhs_len = store.heap_regions[rhs_heap_pos].values.len();
 
            total.reserve(rhs_len);
 
            for value_idx in 0..rhs_len {
 
                total.push(store.clone_value(store.heap_regions[rhs_heap_pos].values[value_idx].clone()));
 
            }
 

	
 
            // Swap back in place
 
            std::mem::swap(&mut total, &mut store.heap_regions[lhs_heap_pos].values);
 

	
 
            // We took ownership of the RHS, but we copied it into the LHS, so
 
            // different form assignment we need to drop the RHS heap pos.
 
            to_dealloc = Some(rhs_heap_pos as u32);
 
        },
 
        AO::Multiplied =>   { apply_int_op!(lhs, *=,  op, rhs) },
 
        AO::Divided =>      { apply_int_op!(lhs, /=,  op, rhs) },
 
        AO::Remained =>     { apply_int_op!(lhs, %=,  op, rhs) },
 
@@ -376,7 +399,6 @@ pub(crate) fn apply_binary_operator(store: &mut Store, lhs: &Value, op: BinaryOp
 
        let lhs = store.maybe_read_ref(lhs);
 
        let rhs = store.maybe_read_ref(rhs);
 

	
 
        enum ValueKind { Message, String, Array }
 
        let value_kind;
 

	
 
        match lhs {
src/protocol/parser/mod.rs
Show inline comments
 
@@ -187,9 +187,6 @@ impl Parser {
 
        // Continue compilation with the remaining phases now that the types
 
        // are all in the type table
 
        for module_idx in 0..self.modules.len() {
 
            // TODO: Remove the entire Visitor abstraction. It really doesn't
 
            //  make sense considering the amount of special handling we do
 
            //  in each pass.
 
            let mut ctx = visitor::Ctx{
 
                heap: &mut self.heap,
 
                module: &mut self.modules[module_idx],
src/protocol/parser/pass_definitions.rs
Show inline comments
 
@@ -916,6 +916,7 @@ impl PassDefinitions {
 

	
 
            match token.unwrap() {
 
                TK::Equal               => Some(AO::Set),
 
                TK::AtEquals            => Some(AO::Concatenated),
 
                TK::StarEquals          => Some(AO::Multiplied),
 
                TK::SlashEquals         => Some(AO::Divided),
 
                TK::PercentEquals       => Some(AO::Remained),
src/protocol/parser/pass_tokenizer.rs
Show inline comments
 
@@ -355,7 +355,12 @@ impl PassTokenizer {
 
            token_kind = TokenKind::Question;
 
        } else if first_char == b'@' {
 
            source.consume();
 
            token_kind = TokenKind::At;
 
            if let Some(b'=') = source.next() {
 
                source.consume();
 
                token_kind = TokenKind::AtEquals;
 
            } else {
 
                token_kind = TokenKind::At;
 
            }
 
        } else if first_char == b'[' {
 
            source.consume();
 
            token_kind = TokenKind::OpenSquare;
src/protocol/parser/pass_typing.rs
Show inline comments
 
@@ -1631,6 +1631,8 @@ impl PassTyping {
 
        let progress_forced = match expr.operation {
 
            AO::Set =>
 
                false,
 
            AO::Concatenated =>
 
                self.apply_template_constraint(ctx, arg1_expr_id, &ARRAYLIKE_TEMPLATE)?,
 
            AO::Multiplied | AO::Divided | AO::Added | AO::Subtracted =>
 
                self.apply_template_constraint(ctx, arg1_expr_id, &NUMBERLIKE_TEMPLATE)?,
 
            AO::Remained | AO::ShiftedLeft | AO::ShiftedRight |
 
@@ -1641,7 +1643,6 @@ impl PassTyping {
 
        let (progress_arg1, progress_arg2) = self.apply_equal2_constraint(
 
            ctx, upcast_id, arg1_expr_id, 0, arg2_expr_id, 0
 
        )?;
 
        debug_assert!(if progress_forced { progress_arg2 } else { true });
 

	
 
        debug_log!(" * After:");
 
        debug_log!("   - Arg1 type [{}]: {}", progress_forced || progress_arg1, self.debug_get_display_name(ctx, arg1_expr_id));
src/protocol/parser/tokens.rs
Show inline comments
 
@@ -49,6 +49,7 @@ pub enum TokenKind {
 
    DotDot,         // ..
 
    ArrowRight,     // ->
 
    // Operator-like (two characters)
 
    AtEquals,       // @=
 
    PlusPlus,       // ++
 
    PlusEquals,     // +=
 
    MinusMinus,     // --
 
@@ -87,7 +88,7 @@ impl TokenKind {
 
        debug_assert!(!self.has_span_end() && *self != TokenKind::SpanEnd);
 
        if *self <= TokenKind::Equal {
 
            1
 
        } else if *self <= TokenKind::ShiftRight {
 
        } else if *self <= TokenKind::GreaterEquals {
 
            2
 
        } else {
 
            3
 
@@ -129,6 +130,7 @@ impl TokenKind {
 
            TK::ColonColon => "::",
 
            TK::DotDot => "..",
 
            TK::ArrowRight => "->",
 
            TK::AtEquals => "@=",
 
            TK::PlusPlus => "++",
 
            TK::PlusEquals => "+=",
 
            TK::MinusMinus => "--",
src/protocol/tests/eval_binding.rs
Show inline comments
 
@@ -134,7 +134,7 @@ fn test_binding_fizz_buzz() {
 
    Tester::new_single_source_expect_ok("am I employable?", "
 
        union Fizzable { Number(u32), FizzBuzz, Fizz, Buzz }
 

	
 
        func construct_fizz_buzz(u32 num) -> Fizzable[] {
 
        func construct_fizz_buzz_very_slow(u32 num) -> Fizzable[] {
 
            u32 counter = 1;
 
            auto result = {};
 
            while (counter <= num) {
 
@@ -156,6 +156,28 @@ fn test_binding_fizz_buzz() {
 
            return result;
 
        }
 

	
 
        func construct_fizz_buzz_slightly_less_slow(u32 num) -> Fizzable[] {
 
            u32 counter = 1;
 
            auto result = {};
 
            while (counter <= num) {
 
                auto value = Fizzable::Number(counter);
 
                if (counter % 5 == 0) {
 
                    if (counter % 3 == 0) {
 
                        value = Fizzable::FizzBuzz;
 
                    } else {
 
                        value = Fizzable::Buzz;
 
                    }
 
                } else if (counter % 3 == 0) {
 
                    value = Fizzable::Fizz;
 
                }
 

	
 
                result @= { value }; // woohoo, no array builtins!
 
                counter += 1;
 
            }
 

	
 
            return result;
 
        }
 

	
 
        func test_fizz_buzz(Fizzable[] fizzoid) -> bool {
 
            u32 idx = 0;
 
            bool valid = true;
 
@@ -184,8 +206,14 @@ fn test_binding_fizz_buzz() {
 
        }
 

	
 
        func fizz_buzz() -> bool {
 
            auto fizz = construct_fizz_buzz(100);
 
            return test_fizz_buzz(fizz);
 
            // auto fizz_more_slow = construct_fizz_buzz_very_slow(100);
 
            // return test_fizz_buzz(fizz_more_slow);
 
            // auto fizz_less_slow = construct_fizz_buzz_slightly_less_slow(100);
 
            // return test_fizz_buzz(fizz_less_slow);
 

	
 
            auto fizz_more_slow2 = construct_fizz_buzz_very_slow(100);
 
            auto fizz_less_slow2 = construct_fizz_buzz_slightly_less_slow(100);
 
            return test_fizz_buzz(fizz_more_slow2) && test_fizz_buzz(fizz_less_slow2);
 
        }
 
    ").for_function("fizz_buzz", |f| { f
 
        .call_ok(Some(Value::Bool(true)));
0 comments (0 inline, 0 general)