Implements the proto-MIR itself and the routines for translating AST to the proto-MIR.
The proto-MIR is an intermediate representation that only covers a subset of expressions. It acts as an intermediate between AST and the MIR, offloading some attribute inheritance/synthesis from the main AST-to-MIR translation.
Types
ExprKind = enum Literal, Lvalue, Rvalue, ## non-owning rvalue that can only be copied OwnedRvalue
- Source Edit
Keep = enum kDontCare, ## lvalue-ness doesn't matter kLvalue, ## whatever the item is translated to, it must have lvalue ## semantics kMutLvalue ## whatever the item is translated to, it must have mutable ## lvalue semantics
- Source Edit
ProtoItem = object orig* {.cursor.}: PNode ## the originating-from AST node typ* {.cursor.}: PType ## the type of the sub-expression. Can be different from that of `orig` keep*: Keep ## for lvalue items, what needs to be preserved for the resulting code ## to still have the correct behaviour. Ignored for all other items case kind*: ProtoItemKind of pirLocal, pirGlobal, pirParam, pirConst, pirProc: sym* {.cursor.}: PSym of pirTupleAccess: pos*: uint32 of pirFieldAccess, pirVariantAccess: field* {.cursor.}: PSym of pirArrayAccess, pirSeqAccess, pirCheckedArrayAccess, pirCheckedSeqAccess: index*: int ## the item index of the index operand expression of pirCheckedVariantAccess: nodeIndex*: int ## the check's index in the originating-from ``nkCheckedFieldAccess`` of pirCheckedObjConv: check* {.cursor.}: PType ## the type to emit a run-time check with of pirArrayConstr, pirClosureConstr, pirTupleConstr, pirObjConstr: owning*: bool ## whether the construction produces an owning aggregate value else: nil
-
A chain of ProtoItems forms a proto-MIR expression. Multiple sub- expressions can be part of a single buffer, with each one delimited by a terminal item.
The items are ordered as the AST expression would be displayed. Take, for example:
a.b[1].c
The item representing a comes first, then the dot (i.e., the field access), then b, etc.
Note: All fields of ref types are cursors, in order to eliminate costly copies and destructions. This is safe, because the AST is guaranteed to outlive the proto-MIR items.Source Edit ProtoItemKind = enum pirLiteral, ## some literal value or type pirProc, pirParam, pirLocal, pirGlobal, pirConst, pirDeref, pirViewDeref, pirTupleAccess, pirFieldAccess, pirArrayAccess, pirSeqAccess, pirVariantAccess, pirLvalueConv, pirCheckedArrayAccess, pirCheckedSeqAccess, pirCheckedVariantAccess, pirCheckedObjConv, pirAddr, pirView, pirConv, pirStdConv, pirCast, pirToSlice, pirToSubSlice, pirCall, pirChckRange, pirStringToCString, pirCStringToString, pirComplex, ## a complex expression, such as an if-expression pirStmtList, pirCopy, pirMove, pirDestructiveMove, pirSink, pirClosureConstr, pirSetConstr, pirObjConstr, pirRefConstr, pirTupleConstr, pirArrayConstr, pirSeqConstr, pirConstExpr, ## an expression that needs to be turned into an anonymous ## constant pirMat, ## materialize the value into an owning temporary pirMatCursor, ## materialize the value into non-owning temporary pirMatLvalue ## materialize the lvalue into a temporary reference
- Source Edit
TranslateCtx = object config: ConfigRef options: TOptions pickVm: bool ## pick the ``nimvm`` branch when faced with a when statement
- Source Edit
Procs
func classify(e: seq[ProtoItem]): ExprKind {....raises: [], tags: [].}
- Returns the kind of the given proto-MIR expression. Source Edit
func classify(e: seq[ProtoItem]; i: int): ExprKind {....raises: [], tags: [].}
- Returns the kind of the given proto-MIR expression. Source Edit
proc exprToPmir(options: TOptions; config: ConfigRef; pickVm: bool; n: PNode; sink, mutable: bool): seq[ProtoItem] {.inline, ...raises: [Exception, ERecoverableError], tags: [RootEffect].}
- Translates the expression n and all its relevant sub-expression into the corresponding proto-MIR representation, already performing some necessary lowering. Source Edit
func selectWhenBranch(n: PNode; isNimvm: bool): PNode {....raises: [], tags: [].}
- Source Edit
func symbolToPmir(s: PSym): range[pirProc .. pirConst] {....raises: [], tags: [].}
- Source Edit
func wantConsumeable(e: var seq[ProtoItem]) {....raises: [], tags: [].}
- Makes sure e is an expression that can be used in a context requiring a certainly-consumeable value (either a materialized temporary or a literal value). Source Edit
func wantOwning(e: var seq[ProtoItem]; forceTemp: bool) {....raises: [], tags: [].}
- Makes sure e produces an owning value. If forceTemp is true, a temporary is materialized even if the expression would already produce an owning value. Source Edit
proc wantPure(e: var seq[ProtoItem]) {....raises: [], tags: [].}
- Makes sure e is a pure expression. An impure expression is turned into a pure expression by materializing it into a temporary and then using the temporary in its place. Source Edit
proc wantShallow(e: var seq[ProtoItem]) {....raises: [], tags: [].}
- Makes sure e is something that can be assigned to a non-owning destination. Source Edit
proc wantStable(e: var seq[ProtoItem]) {....raises: [], tags: [].}
- Makes sure e is a stable lvalue expression. Rvalues and literal values are committed to temporaries. Source Edit