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
Imports
-
../ast/ast, ../ast/astalgo, ../ast/trees, ../ast/idents, ../ast/renderer, ../ast/types, ../ast/lineinfos, ../modules/magicsys, ../modules/modulegraphs, ../front/options, ../front/msgs, ast_analysis, closureiters, semfold, lambdalifting, lowerings, unreachable_elim, ../backend/cgmeth, ../utils/idioms, semdata
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
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:
- the lambdalifting transformation
- general lowerings -- these are the ones implemented here in transf
- 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