본문으로 건너뛰기

구조

Compiler pipeline and T0 IR

이 페이지는 영어입니다. 하나의 언어로 유지된 사양은 하나의 내용만 말합니다.

1. Pipeline#

stage crate / module input → output may report
1. lexing t0-syntax::lexer text → tokens with spans E-SYN-*
2. parsing t0-syntax::parser tokens → AST E-SYN-*
3. headers and versions t0-compiler::headers headers + compiler and manifest versions E-VER-*, E-CAP-NO-HOST, E-CAP-UNKNOWN, E-CAP-VERSION
4. item collection t0-compiler::items declarations → symbol tables (types, functions, consts, strategies, contract namespaces) E-RES-*
5. type checking t0-compiler::check bodies → typed bodies E-TYPE-*, E-FIN-*, E-RES-*
6. capability analysis t0-compiler::check (host calls) used operations ⊆ declared contracts E-CAP-*, W-CAP-UNUSED, W-DEPRECATED
7. strategy lowering t0-compiler::strategy strategy bodies → signal graphs E-STRAT-*
8. IR generation t0-compiler::check (emits IR directly from typed bodies) → IR artifact —
9. IR validation t0-ir::validate artifact → validated artifact E-IR-*
10. execution planning t0-runtime + host artifact + manifest + grants → run or refuse E-VER-*, E-CAP-*, E-PERM-DENIED

Rules: financial semantics live in the dimension table (t0-ir::ops), not in the parser; permission enforcement is not part of type checking (the compiler computes the needed permissions; the session decides). Diagnostics accumulate: an error in one function does not stop checking of the others.

2. IR (format t0-ir, version 0.1.0)#

2.1 Artifact#

{
  "format": "t0-ir",
  "ir_version": "0.1.0",
  "language_version": "0.1.0",
  "compiler": { "name": "t0-compiler", "version": "0.1.0" },
  "source_sha256": "…",
  "requirements": {
    "language": ">=0.1.0, <0.2.0",
    "host": { "name": "ttt", "range": ">=0.1.0, <0.2.0" },
    "contracts": [ { "id": "backtest", "range": ">=0.1.0, <0.2.0", "checked_against": "0.1.0" } ],
    "permissions": ["backtest.run", "market.read"]
  },
  "body": { "types": [], "consts": [], "functions": [], "strategies": [], "entry": 0 },
  "body_sha256": "…"
}

body_sha256 is the SHA-256 of the JSON serialisation of body (field order as declared). A mismatch is E-IR-HASH.

2.2 Body#

  • types: user structs/enums and contract types used, each with a stable index; a type reference is an IrType (Int, List(IrType), Struct(index), Enum(index), …).
  • functions[i] = { name, params: [IrType], ret: IrType, locals: [IrType], body: [Stmt] }; parameters are the first locals.
  • Stmt = Let{local, value} | Assign{local, path: [field index], value} | Expr | If{cond, then, else} | While{cond, body} | For{local, list, body} | Match{scrutinee, arms} | Return(Option<Expr>) | Break | Continue.
  • Expr = { ty: IrType, span, kind } where kind is one of Const, Local(i), Global(const index), Call{func, args}, Builtin{op, args}, Host{contract, version, op, args}, Binary{op: BinOp, l, r}, Unary{op, e}, And, Or, Field{e, index}, Index{list, index}, Struct{type, fields}, Variant{type, variant, payload}, List[...], If{c, a, b}, Match{scrutinee, arms}, Try{e}, Strategy{index, args}.
  • BinOp names a fully resolved operation (AddInt, AddDecimal, MulPriceQuantity, SubTimestamp, …). The validator looks it up in t0-ir::ops and checks operand and result types.
  • Strategies: { name, version, params: [(name, IrType)], nodes, rules, flatten_on_stop } — ADR-0004 and the spec §9.

2.3 Validator checks (trusts nothing)#

  1. Format name; IR version within the runtime's accepted range.
  2. Body hash.
  3. Every type, function, local and const index in range.
  4. Every expression's declared type equals the type its kind produces (operators via the table, calls via signatures, fields via type definitions, builtins via their signatures).
  5. Break/Continue only inside loops; Try only in functions whose return type can carry the error; match arms well formed.
  6. Every Host node names a contract listed in requirements.contracts at the version it was checked against, and the operation's needed permission is listed in requirements.permissions. The host verifies the operation against its own manifest again at call time.
  7. Strategy graphs: node references point to earlier nodes (acyclic), rule conditions are boolean, feature nodes reference declared contracts.

3. Native backend (Phase 7, not implemented)#

The backend interface takes a validated artifact and a subset predicate; supported functions are lowered tree → SSA → machine code. Candidates (Cranelift, LLVM) are chosen by measured compile latency and generated-code speed on representative kernels (rolling statistics over 10⁶–10⁸ elements, parameter sweeps). Differential tests run every supported program on both backends and compare results, errors and the order of host calls. Native code runs in a worker process (ADR-0002).