compiler/sem/transf

  Source   Edit

This module implements the transformator. It transforms the syntax tree to ease the work of the code generators. Does some transformations:

  • inlines iterators
  • converts "continue" to "break"; disambiguates "break"
  • introduces method dispatchers
  • performs lambda lifting for closure support
  • transforms 'defer' into a 'try finally' statement

Procs

proc commonOptimizations(g: ModuleGraph; idgen: IdGenerator; c: PSym; n: PNode): PNode {.
    ...raises: [KeyError, Exception, ERecoverableError],
    tags: [ReadDirEffect, RootEffect, ReadEnvEffect, TimeEffect].}
  Source   Edit
proc extractGlobals(body: PNode; output: var seq[PNode]; isNimVm: bool) {.
    ...raises: [], tags: [].}
Searches for all nkIdentDefs defining a global that's not owned by a module, appends them to output in the order they appear in the input AST, and removes the nodes from body. isNimVm signals which branch to select for when nimvm statements/expressions.
XXX: this can't happen as part of transformBody, as transformBody
is reentrant because of lambdalifting and it's thus not easily possible to collect something from the body of a single procedure only. There's also the problem that extracting the globals is not wanted when transformation happens for a procedure that's invoked during CTFE and used in normal code. Eventually, transformBody will no longer use the current caching mechanism and only produce the transformed version of the input AST, but until then, collectGlobals works good enough
  Source   Edit
proc transformBody(g: ModuleGraph; idgen: IdGenerator; prc: PSym; body: PNode): PNode {.
    ...raises: [Exception, ERecoverableError, KeyError, ValueError],
    tags: [RootEffect, ReadDirEffect].}

Applies the various transformations to body and returns the result. This step is not indempotent, and since no caching is performed, it must not be performed more than once for a routine and its body.

The transformations are:

  1. the lambdalifting transformation
  2. general lowerings -- these are the ones implemented here in transf
  3. the closureiters transformation

Application always happens in that exact order.

  Source   Edit
proc transformBody(g: ModuleGraph; idgen: IdGenerator; prc: PSym; cache: bool): PNode {.
    ...raises: [KeyError, Exception, ERecoverableError, ValueError],
    tags: [ReadDirEffect, RootEffect].}
  Source   Edit
proc transformBodyWithCache(g: ModuleGraph; idgen: IdGenerator; prc: PSym): PNode {.
    ...raises: [KeyError, Exception, ERecoverableError, ValueError],
    tags: [ReadDirEffect, RootEffect].}
Fetches the cached transformed body of prc, transforming it if not available, new transforms are not cached   Source   Edit
proc transformExpr(g: ModuleGraph; idgen: IdGenerator; module: PSym; n: PNode): PNode {.
    ...raises: [Exception, ERecoverableError, KeyError],
    tags: [RootEffect, ReadDirEffect].}
  Source   Edit
proc transformStmt(g: ModuleGraph; idgen: IdGenerator; module: PSym; n: PNode): PNode {.
    ...raises: [Exception, ERecoverableError, KeyError],
    tags: [RootEffect, ReadDirEffect].}
  Source   Edit