lower

package
v0.14.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package lower transforms Core IR into Statement IR.

This is a PROJECTION, not a translation: information is deliberately lost (type variables, effects, row polymorphism) because target languages cannot express these concepts. The loss is explicit and controlled.

No file in this package may import internal/gen/golang/.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FlattenBlock

func FlattenBlock(e core.CoreExpr, cti types.CoreTypeInfo) ([]stmt.Stmt, stmt.Expr)

FlattenBlock converts a Core expression (typically a let-chain) into a sequence of statements plus a final return expression.

Core IR uses nested Let/LetRec for sequential computation:

Let("a", e1,
  Let("b", e2,
    body))

This flattens to:

var a = e1
var b = e2
return body

This is the heart of the Statement IR lowering — it bridges the gap between functional let-chains and imperative statement sequences.

func LowerExpr

func LowerExpr(e core.CoreExpr, cti types.CoreTypeInfo) stmt.Expr

LowerExpr converts a Core expression into a Statement IR expression. For complex expressions (Let, Match, If-as-statement), it may also produce statements that must be prepended to the enclosing block. Use LowerBlock for let-chain flattening; this function handles the expression-level conversion.

func LowerMatchExpr

func LowerMatchExpr(m *core.Match, cti types.CoreTypeInfo) stmt.Expr

LowerMatchExpr converts a Core Match into a Statement IR expression.

In practice this is only reachable for non-tail-position matches (e.g. `1 + match x { ... }`). Tail-position matches are intercepted by FlattenBlock and routed to LowerMatchStmt, which produces a proper SwitchStmt or if-chain. The Phase 2C corpus does not exercise non-tail-position matches.

For the one supported shape — a 2-arm match where the first arm is a LitPattern and both bodies are simple expressions — we emit an IfExpr. Anything else PANICS rather than silently producing a lossy approximation (the previous behavior was to return `lowerExpr(arms[0].Body)`, which produced a wrong-but-running result for any match it didn't recognize).

If you hit this panic, the right fix is usually to (a) refactor the AILANG source so the match is in tail position, or (b) extend FlattenBlock to bind the match's result into a temp via a hoisted SwitchStmt and then reference that temp.

func LowerMatchStmt

func LowerMatchStmt(m *core.Match, cti types.CoreTypeInfo) stmt.Stmt

LowerMatchStmt converts a Core Match into a Statement IR SwitchStmt. This handles all 7 pattern types by dispatching to the appropriate Statement IR construct:

  • ConstructorPattern → SwitchStmt with tag-based cases
  • LitPattern → SwitchStmt or if-chain
  • VarPattern/WildcardPattern → default case
  • ListPattern, TuplePattern, RecordPattern → if-chain with destructuring

func LowerMultiModule

func LowerMultiModule(
	modules map[string]*ModuleInput,
	pkgName string,
) (*stmt.Program, error)

LowerMultiModule handles multi-module compilation by lowering each module and merging the results into a single Program.

func LowerProgram

func LowerProgram(
	coreProg *core.Program,
	cti types.CoreTypeInfo,
	astFile *ast.File,
	pkgName string,
) (*stmt.Program, error)

LowerProgram converts a Core program + AST (for type declarations) into a Statement IR Program ready for emission.

This is the main entry point for the lowering pipeline:

pipeline.Run(ModeCheck) → Core + CoreTypeInfo + AST
lower.LowerProgram(core, cti, ast) → stmt.Program
emitter.Emit(program) → Go/Rust/etc. source code

func LowerTypeDecl

func LowerTypeDecl(td *ast.TypeDecl) stmt.TypeDecl

LowerTypeDecl converts an AST type declaration into a Statement IR TypeDecl.

func ProjectASTType

func ProjectASTType(t ast.Type) stmt.ResolvedType

ProjectASTType converts an ast.Type (from surface syntax) into a stmt.ResolvedType. Used for type declarations where we have AST types rather than inferred types.Type.

func ProjectType

func ProjectType(t types.Type) stmt.ResolvedType

ProjectType converts a types.Type (from the type checker) into a stmt.ResolvedType (for the emitter). This is the semantic boundary where AILANG's rich type system is projected into target-language types.

Rules:

  • Primitive types (int, float, bool, string, ()) → PrimitiveType
  • Named types (ADTs, records) → NamedType with Pointer=true for ADTs
  • List/Array → SliceType
  • Tuple → TupleType
  • Function → FuncType
  • Type variables → InterfaceType (erased — the type was polymorphic)
  • Unknown/nil → InterfaceType (defensive)

func QualifyFuncRefs

func QualifyFuncRefs(prog *stmt.Program)

QualifyFuncRefs rewrites VarRef nodes that reference top-level functions to use the full module-prefixed name that matches the Go function definition. Core IR uses bare Var references for same-module calls; we rewrite those to include the module__name prefix (matching what funcName() produces in the emitter).

Types

type ModuleInput

type ModuleInput struct {
	Core *core.Program
	CTI  types.CoreTypeInfo
	AST  *ast.File
}

ModuleInput bundles the artifacts needed to lower one module.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL