Previously, each time a literal was evaluated, a new object was created.
This meant that if you had code like:
foreach x : list
if x == 'hello'
do_something
endif
endforeach
In each loop, when the condition was evaluated, a new string containing
'hello' was allocated. With many loops or lots of literals inside
loops, this can become a source of wasteful memory use.
The implemented solution is to create these objects once during the
parse step, and then reuse them inside the interpreter. Currently only
strings, bools, and numbers get this treatment, but it should be
possible to handle arrays/dicts composed purely of literals as well,
although that would start to get into constant folding.