vancode/interpreter/codegen

Search:
Group by:

This module contains the code generation logic for VanCode. It takes the AST produced by your parser and generates bytecode for it, which can then be executed by the VM.

The code generator is designed to be modular and extensible, allowing you to easily hook into the code generation process to add support for new language features.

Types

CodeGen {.acyclic.} = ref object
  module*: Module ## the global scope for this code generator. this is where all
                  ## global variables and procs are declared
  case
  of gkToplevel, gkHtmlNest:
    nil
  of gkProc, gkBlockProc:
  of gkIterator:
  parserCallback*: ParserCallback ## a callback used to parse custom nodes
  allowExprResult*: bool
a code generator for a module or proc.
CodeGenCache = object
  cachedAst*: Table[string, Ast]
A cache for code generation. This is used to store the ASTs of included files, so that they don't need to be re-parsed every time they're included
ParserCallback = proc (astProgram: var Ast; path: string)
Used to parse custom nodes during code generation.

Procs

proc addIterator(script: Script; module: Module; name: string) {....raises: [],
    tags: [], forbids: [].}
Add a foreign iterator into the specified module.
proc allocCtx(allocator: ContextAllocator): Context {....raises: [], tags: [],
    forbids: [].}
Allocate a new context
proc call(gen: CodeGen; node: Node): Sym {.
    ...raises: [CodeGenError, ValueError, Exception, KeyError], tags: [RootEffect],
    forbids: [].}
proc callProc(gen: CodeGen; procSym: Sym; argTypes: seq[Sym];
              errorNode: Node = nil): Sym {.
    ...raises: [Exception, CodeGenError, ValueError, KeyError], tags: [RootEffect],
    forbids: [].}
proc collectGenericParams(gen: CodeGen; genericParams: Node): Option[seq[Sym]] {.
    ...raises: [KeyError, CodeGenError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
proc collectParams(gen: CodeGen; formalParams: Node;
                   genericParams: Option[seq[Sym]] = none(seq[Sym])): seq[
    ProcParam] {....raises: [CodeGenError, ValueError, Exception, KeyError],
                 tags: [RootEffect], forbids: [].}
proc count(gen: CodeGen): uint {....raises: [], tags: [], forbids: [].}
Get the current value of the codegen's counter, and increment it.
proc declareVar(gen: CodeGen; name: Node; kind: SymKind; ty: Sym;
                isMagic = false; varExport = false): Sym {.discardable,
    ...raises: [CodeGenError, ValueError, KeyError], tags: [], forbids: [].}
proc error(node: Node; msg: string) {....raises: [CodeGenError, ValueError],
                                      tags: [], forbids: [].}
Raise a compile error on the given node.
proc findOverload(gen: CodeGen; sym: Sym; args: seq[Sym]; errorNode: Node = nil;
                  quiet = false): Sym {....raises: [Exception, CodeGenError,
    ValueError], tags: [RootEffect], forbids: [].}
proc freeCtx(allocator: ContextAllocator; ctx: Context) {....raises: [], tags: [],
    forbids: [].}
Free a context
proc genArray(gen: CodeGen; node: Node; isInstantiation = false): Sym {.
    ...raises: [KeyError, CodeGenError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
proc genArrayAccess(gen: CodeGen; node: Node): Sym {.
    ...raises: [Exception, CodeGenError, ValueError, KeyError], tags: [RootEffect],
    forbids: [].}
proc genBlock(gen: CodeGen; node: Node; isStmt: bool): Sym {.
    ...raises: [CodeGenError, ValueError, KeyError, Exception, OSError, IOError],
    tags: [RootEffect, ReadDirEffect, WriteIOEffect], forbids: [].}
proc genBreak(gen: CodeGen; node: Node) {....raises: [CodeGenError, ValueError],
    tags: [], forbids: [].}
proc genComment(gen: CodeGen; node: Node) {....raises: [], tags: [], forbids: [].}
proc genContinue(gen: CodeGen; node: Node) {....raises: [CodeGenError, ValueError],
    tags: [], forbids: [].}
proc genExpr(gen: CodeGen; node: Node; varUnwrap = true): Sym {.
    ...raises: [KeyError, CodeGenError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
proc genFor(gen: CodeGen; node: Node) {....raises: [CodeGenError, ValueError,
    Exception, KeyError], tags: [RootEffect], forbids: [].}
proc genGetField(gen: CodeGen; node: Node): Sym {.
    ...raises: [Exception, KeyError, CodeGenError, ValueError], tags: [RootEffect],
    forbids: [].}
proc genIf(gen: CodeGen; node: Node; isStmt: bool): Sym {.
    ...raises: [Exception, CodeGenError, ValueError, KeyError], tags: [RootEffect],
    forbids: [].}
proc genImport(gen: CodeGen; node: Node) {....raises: [ValueError, CodeGenError,
    KeyError, Exception, OSError, KeyError, CodeGenError, ValueError, IOError,
    KeyError, CodeGenError, ValueError],
    tags: [ReadDirEffect, RootEffect, WriteIOEffect], forbids: [].}
proc genIterator(gen: CodeGen; node: Node; isInstantiation = false): Sym {.
    ...raises: [KeyError, CodeGenError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
proc genObject(gen: CodeGen; node: Node; isInstantiation = false): Sym {.
    ...raises: [CodeGenError, ValueError, Exception, KeyError], tags: [RootEffect],
    forbids: [].}
proc genObjectStorage(gen: CodeGen; node: Node; isInstantiation = false): Sym {.
    ...raises: [CodeGenError, ValueError, KeyError, Exception], tags: [RootEffect],
    forbids: [].}
proc genProc(gen: CodeGen; node: Node; isInstantiation = false): Sym {.
    ...raises: [KeyError, CodeGenError, ValueError, Exception], tags: [RootEffect],
    forbids: [].}
proc genReturn(gen: CodeGen; node: Node) {.
    ...raises: [CodeGenError, ValueError, Exception, KeyError], tags: [RootEffect],
    forbids: [].}
proc genScript(gen: CodeGen; program: Ast; includePath: Option[string];
               emitHalt: static bool = true)
proc genStmt(gen: CodeGen; node: Node) {.
    ...raises: [CodeGenError, ValueError, KeyError, Exception, OSError, IOError],
    tags: [RootEffect, ReadDirEffect, WriteIOEffect], forbids: [].}
proc genTypeDef(gen: CodeGen; node: Node): Sym {....raises: [Exception],
    tags: [RootEffect], forbids: [].}
proc genVar(gen: CodeGen; node: Node) {....raises: [CodeGenError, ValueError,
    KeyError, Exception], tags: [RootEffect], forbids: [].}
proc genWhile(gen: CodeGen; node: Node) {.
    ...raises: [CodeGenError, ValueError, Exception, KeyError], tags: [RootEffect],
    forbids: [].}
proc genYield(gen: CodeGen; node: Node) {.
    ...raises: [CodeGenError, ValueError, KeyError, Exception], tags: [RootEffect],
    forbids: [].}
proc getDefaultSym(gen: CodeGen; kind: NodeKind): Sym {....raises: [KeyError],
    tags: [], forbids: [].}
Returns the default type for the given node kind.
proc infix(gen: CodeGen; node: Node): Sym {.
    ...raises: [Exception, KeyError, CodeGenError, ValueError], tags: [RootEffect],
    forbids: [].}
proc initCodeGen(script: Script; module: Module; chunk: Chunk;
                 kind = gkToplevel; ctxAllocator: ContextAllocator = nil;
                 pkgr: Packager = nil; parserCallback: ParserCallback = nil): CodeGen {.
    ...raises: [], tags: [], forbids: [].}
proc initCompiler(script: Script; module: Module; chunk: Chunk; pkgr: Packager;
                  stdlibs: StandardLibrary;
                  parserCallback: ParserCallback = nil;
                  triggerFromPath: Option[string] = none(string)): CodeGen {.
    ...raises: [], tags: [], forbids: [].}

Initialize a new code generator with a new script and module

This is the main entry point for code generation, and can be called by your main module or by other modules to initialize code generation for a new script

proc newProc(script: Script; name, impl: Node; params: seq[ProcParam];
             returnTy: Sym; kind: ProcKind; exported = false;
             genKind: GenKind = gkToplevel): (Sym, Proc) {.
    ...raises: [CodeGenError, ValueError], tags: [], forbids: [].}
Creates a procedure for the given script. Returns its symbol and Proc object. This does not add the procedure to the script!
proc objConstr(gen: CodeGen; node: Node; ty: Sym; constructFromIdent = false): Sym {.
    ...raises: [CodeGenError, ValueError, Exception, KeyError], tags: [RootEffect],
    forbids: [].}
proc prefix(gen: CodeGen; node: Node): Sym {.
    ...raises: [Exception, KeyError, CodeGenError, ValueError], tags: [RootEffect],
    forbids: [].}
proc procCall(gen: CodeGen; node: Node; procSym: Sym): Sym {.
    ...raises: [Exception, CodeGenError, ValueError, KeyError], tags: [RootEffect],
    forbids: [].}
proc pushConst(gen: CodeGen; node: Node): Sym {....raises: [KeyError], tags: [],
    forbids: [].}
proc resolveGenerics(gen: CodeGen; callable: var Sym; callArgTypes: seq[Sym];
                     errorNode: Node) {....raises: [KeyError, Exception,
    CodeGenError, ValueError], tags: [RootEffect], forbids: [].}
Helper used to resolve generic parameters via inference.
proc splitCall(gen: CodeGen; ast: Node): tuple[callee: Sym, args: seq[Node]] {.
    ...raises: [CodeGenError, ValueError, Exception, KeyError], tags: [RootEffect],
    forbids: [].}
proc tryElideWhile(gen: CodeGen; node: Node): bool {.
    ...raises: [CodeGenError, ValueError, Exception, KeyError], tags: [RootEffect],
    forbids: [].}