Semantic analysis: scope building and validation.
Signature files (.sig): When .sig files are provided (e.g. stdlib), they are parsed
with the signature grammar, then type expressions in each function/global declaration
are turned into Type via parse_type_expr and seeded into the root scope. The type checker
uses these for inference (e.g. call return types, global variable types). Use
analyze_with_signatures(program_root, signature_roots) so that built-in names resolve and
types are inferred from the .sig definitions.