Update of HashMap stored in immutable struct doesn't persist

Hi, I'm working on a parser for a simple assembly language and struggled to update the symbol_table stored in a state that's passed throughout the parser. I tried implementing the symbol_table as HashMap<String, usize> and Box<HashMap<String, usize>> but updates in both are lost.

Here's the immutable State sturct:

#[derive(Clone)]
pub struct State {
  symbol_table: HashMap<String, usize>,
  instruction_index: usize,
  variable_index: usize,
}

Update logic:

update_state(move |label, state|
          if !state.symbol_table.contains_key::<str>(&label) {
            let mut new_symbol_table = state.symbol_table.clone();
            new_symbol_table.insert(label.clone(), state.instruction_index + 1);
            State {
              symbol_table: new_symbol_table,
              ..state
            }
          } else {
            state
          }
        )

Here's the link to the full assembler on github: https://github.com/AlienKevin/hack-assembler

I had a look around in your code, and the only thing I could think of is that output is the value before it is sent through the closure (see here).

The im crate might be useful to you here.

2 Likes

Thank you for looking through the code. I think output is only an argument to the closure and the returned state of the closure is set to be the new state in update_state.

Thanks for the suggestion. I replaced the std::collections::HashMap with the im version but the problem persisted. I believe it's a problem of returning new struct from a function. For some reason, the new struct is not remembered but the old version is kept. Do you have any idea on how to correct this?

It is likely a logic bug somewhere in your code.

1 Like

Thank you so much for pointing me in the right direction. I finaly found and fixed the bug. It is a logic error indeed and a lot of them... It turns out the HashMap is updated very time but I didn't use the new state in most of the parser combinators so they are discarded😭. An even more absurd loophole is in the map_with_state function where I didn't even expose the new state. I went through an afternoon of refactoring and simply lost my mind.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.