Dynamic Constant Normalization
To avoid issues in type-checking (and make it so that types and dynamic constants can just be compared by their ID) we should normalize all dynamic constants at creation so that all dynamic constants are normalized. In particular, we want to constant fold as much as possible and introduce n-ary add/mul/min/max with their arguments sorted in some defined manner, with at-most one constant, and no nesting of the same operator type, so add { a, add {x, y}, b}
is normalized as add { a, x, y, b }
or something similar.
Then, when type-checking function arguments, we will perform substitution of the dynamic constants and construct the normalized type and then we can just compare the dynamic constant IDs of the actual argument and the substituted (and normalized) parameter type.