this function is used by both the file-based parser and the LSP parser (which needs the source map)
the LSP parser can also optionally pass in a pre-parsed tree to avoid parsing twice (which is how caching is implemented)
if the tree is not passed in, we will parse it from scratch (this is what the file-based parser does)
which will cause it to re-parse the source code and update the cache (Model = ast, SorceMap = map)
letting a be [ [ 1,2,3 ; int(1,2,4) ], [ 1,3,2 ; int(1,2,4) ], [ 3,2,1 ; int(1,2,4) ] ; int(-2..0) ]