Semantic Analysis v6

hard · compilers, semantics, types

Semantic Analysis v6

Validate v6 programs with modules and static types.

Function signature

func Analyze(prog *Program) []string

Return a slice of error strings (in the order discovered). If there are no errors, return nil or an empty slice.

New type rules

Variable declarations

  • If a type annotation is present, the initializer (if any) must be assignable.
  • If no annotation is present, the initializer must exist and be inferable.
  • Empty arrays/maps require an expected collection type supplied by an annotated declaration, typed call argument, or explicit return context. Plain assignment RHS inference does not receive the target type in this implementation.

Function declarations

  • Parameter types are required.
  • Return type is required.
  • return expressions must be assignable to the declared return type.

Expressions

  • + works on numbers or strings only.
  • - * / work on numbers only.
  • && || ! work on bools only.
  • < <= > >= work on numbers only.
  • == != require compatible types.
  • Arrays and maps must be homogeneous.
  • Map keys must be number/bool/string.

Assignability

  • Types must match structurally.
  • nil is assignable to any type.

Module rules (from v5)

  • Unique module names.
  • main exists and is last.
  • Imports refer to earlier modules.
  • Member access requires exported names.

Notes

  • Keep error messages simple and consistent.

Function and loop boundaries

A loop body is a block nested inside the for initializer scope. Body locals may shadow initializer bindings and are not visible in the post clause. Entering a nested function resets loop context for that function; restore the outer context afterward. Break/continue cannot target a loop in a different function, even when the function declaration appears inside that loop.

Typed module interfaces and limits

Exported variables require explicit annotations. Exported functions require complete signatures. Local variables can infer their type from initializers. The checker validates explicit returns but does not prove all-path return coverage, bounds safety, nil safety, or flow-sensitive narrowing. Nil remains assignable to every type; accepted programs can still fail dynamic VM checks.

Before implementation

Use the module’s worked reconstruction and independent debugging lab to predict an intermediate artifact first. Preserve one failing counterexample while implementing the stated API. The lesson’s transfer task uses a fresh case after the guided trace.

Run tests to see results
No issues detected
    Join Discord