compiler/mir/proto_mir

  Source   Edit

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 typ(n: seq[ProtoItem]): PType {.inline, ...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
proc wantValue(e: var seq[ProtoItem]) {....raises: [], tags: [].}
Makes sure e is a literal value or lvalue expression.   Source   Edit