diff options
-rw-r--r-- | compiler/nimblecmd.nim | 2 | ||||
-rw-r--r-- | compiler/pretty.nim | 2 | ||||
-rw-r--r-- | compiler/vm.nim | 14 | ||||
-rw-r--r-- | compiler/vmdef.nim | 13 | ||||
-rw-r--r-- | compiler/vmgen.nim | 23 | ||||
-rw-r--r-- | compiler/vmhooks.nim | 45 | ||||
-rw-r--r-- | compiler/vmops.nim | 66 | ||||
-rw-r--r-- | lib/stdlib.nimble (renamed from lib/stdlib.babel) | 2 |
8 files changed, 157 insertions, 10 deletions
diff --git a/compiler/nimblecmd.nim b/compiler/nimblecmd.nim index 0f73c17bd..049b94aa9 100644 --- a/compiler/nimblecmd.nim +++ b/compiler/nimblecmd.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## Implements some helper procs for Babel (Nim's package manager) support. +## Implements some helper procs for Nimble (Nim's package manager) support. import parseutils, strutils, strtabs, os, options, msgs, lists diff --git a/compiler/pretty.nim b/compiler/pretty.nim index 5f990a658..356399c1c 100644 --- a/compiler/pretty.nim +++ b/compiler/pretty.nim @@ -160,7 +160,7 @@ proc check(c: PGen, n: PNode) = check(c, a.sons[L-2]) check(c, a.sons[L-1]) of nkTypeSection, nkConstSection: - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): let a = n.sons[i] if a.kind == nkCommentStmt: continue checkSonsLen(a, 3) diff --git a/compiler/vm.nim b/compiler/vm.nim index af0b30faa..fe2b9c617 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -133,6 +133,8 @@ proc createStrKeepNode(x: var TFullReg) = # cause of bugs like these is that the VM does not properly distinguish # between variable defintions (var foo = e) and variable updates (foo = e). +include vmhooks + template createStr(x) = x.node = newNode(nkStrLit) @@ -801,7 +803,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let bb = regs[rb].node let isClosure = bb.kind == nkPar let prc = if not isClosure: bb.sym else: bb.sons[0].sym - if sfImportc in prc.flags: + if prc.offset < -1: + # it's a callback: + c.callbacks[-prc.offset-2].value( + VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs))) + elif sfImportc in prc.flags: if allowFFI notin c.features: globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI") # we pass 'tos.slots' instead of 'regs' so that the compiler can keep @@ -832,9 +838,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = if isClosure: newFrame.slots[rc].kind = rkNode newFrame.slots[rc].node = regs[rb].node.sons[1] - # allocate the temporaries: - #for i in rc+ord(isClosure) .. <prc.offset: - # newFrame.slots[i] = newNode(nkEmpty) tos = newFrame move(regs, newFrame.slots) # -1 for the following 'inc pc' @@ -1316,6 +1319,8 @@ proc evalExpr*(c: PCtx, n: PNode): PNode = assert c.code[start].opcode != opcEof result = execute(c, start) +include vmops + # for now we share the 'globals' environment. XXX Coming soon: An API for # storing&loading the 'globals' environment to get what a component system # requires. @@ -1325,6 +1330,7 @@ var proc setupGlobalCtx(module: PSym) = if globalCtx.isNil: globalCtx = newCtx(module) else: refresh(globalCtx, module) + registerAdditionalOps(globalCtx) proc myOpen(module: PSym): PPassContext = #var c = newEvalContext(module, emRepl) diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index e25fd6392..d7cdafb69 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -170,7 +170,12 @@ type sym*: PSym slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]] maxSlots*: int - + + VmArgs* = object + ra*, rb*, rc*: Natural + slots*: pointer + VmCallback* = proc (args: VmArgs) {.closure.} + PCtx* = ref TCtx TCtx* = object of passes.TPassContext # code gen context code*: seq[TInstr] @@ -189,6 +194,7 @@ type traceActive*: bool loopIterations*: int comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces + callbacks*: seq[tuple[key: string, value: VmCallback]] TPosition* = distinct int @@ -198,12 +204,15 @@ proc newCtx*(module: PSym): PCtx = PCtx(code: @[], debug: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations, - comesFromHeuristic: unknownLineInfo()) + comesFromHeuristic: unknownLineInfo(), callbacks: @[]) proc refresh*(c: PCtx, module: PSym) = c.module = module c.prc = PProc(blocks: @[]) +proc registerCallback*(c: PCtx; name: string; callback: VmCallback) = + c.callbacks.add((name, callback)) + const firstABxInstr* = opcTJmp largeInstrs* = { # instructions which use 2 int32s instead of 1: diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 6a6f85d76..05c894ee3 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1489,6 +1489,26 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) = proc genProc*(c: PCtx; s: PSym): int +proc matches(s: PSym; x: string): bool = + let y = x.split('.') + var s = s + var L = y.len-1 + while L >= 0: + if s == nil or y[L].cmpIgnoreStyle(s.name.s) != 0: return false + s = s.owner + dec L + result = true + +proc procIsCallback(c: PCtx; s: PSym): bool = + if s.offset < -1: return true + var i = -2 + for key, value in items(c.callbacks): + if s.matches(key): + doAssert s.offset == -1 + s.offset = i + return true + dec i + proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = case n.kind of nkSym: @@ -1499,7 +1519,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = genRdVar(c, n, dest, flags) of skProc, skConverter, skMacro, skTemplate, skMethod, skIterators: # 'skTemplate' is only allowed for 'getAst' support: - if sfImportc in s.flags: c.importcSym(n.info, s) + if procIsCallback(c, s): discard + elif sfImportc in s.flags: c.importcSym(n.info, s) genLit(c, n, dest) of skConst: gen(c, s.ast, dest) diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim new file mode 100644 index 000000000..cce87d433 --- /dev/null +++ b/compiler/vmhooks.nim @@ -0,0 +1,45 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +template setX(k, field) {.immediate, dirty.} = + var s: seq[TFullReg] + move(s, cast[seq[TFullReg]](a.slots)) + if s[a.ra].kind != k: + myreset(s[a.ra]) + s[a.ra].kind = k + s[a.ra].field = v + +proc setResult*(a: VmArgs; v: BiggestInt) = setX(rkInt, intVal) +proc setResult*(a: VmArgs; v: BiggestFloat) = setX(rkFloat, floatVal) +proc setResult*(a: VmArgs; v: bool) = + let v = v.ord + setX(rkInt, intVal) + +proc setResult*(a: VmArgs; v: string) = + var s: seq[TFullReg] + move(s, cast[seq[TFullReg]](a.slots)) + if s[a.ra].kind != rkNode: + myreset(s[a.ra]) + s[a.ra].kind = rkNode + s[a.ra].node = newNode(nkStrLit) + s[a.ra].node.strVal = v + +template getX(k, field) {.immediate, dirty.} = + doAssert i < a.rc-1 + let s = cast[seq[TFullReg]](a.slots) + doAssert s[i+a.rb+1].kind == k + result = s[i+a.rb+1].field + +proc getInt*(a: VmArgs; i: Natural): BiggestInt = getX(rkInt, intVal) +proc getFloat*(a: VmArgs; i: Natural): BiggestFloat = getX(rkFloat, floatVal) +proc getString*(a: VmArgs; i: Natural): string = + doAssert i < a.rc-1 + let s = cast[seq[TFullReg]](a.slots) + doAssert s[i+a.rb+1].kind == rkNode + result = s[i+a.rb+1].node.strVal diff --git a/compiler/vmops.nim b/compiler/vmops.nim new file mode 100644 index 000000000..8e75cc23a --- /dev/null +++ b/compiler/vmops.nim @@ -0,0 +1,66 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# Unforunately this cannot be a module yet: +#import vmdeps, vm +from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin, + arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc, + floor, ceil, fmod + +from os import getEnv, existsEnv, dirExists, fileExists + +template mathop(op) {.immediate, dirty.} = + registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`) + +template osop(op) {.immediate, dirty.} = + registerCallback(c, "stdlib.os." & astToStr(op), `op Wrapper`) + +template wrap1f(op) {.immediate, dirty.} = + proc `op Wrapper`(a: VmArgs) {.nimcall.} = + setResult(a, op(getFloat(a, 0))) + mathop op + +template wrap2f(op) {.immediate, dirty.} = + proc `op Wrapper`(a: VmArgs) {.nimcall.} = + setResult(a, op(getFloat(a, 0), getFloat(a, 1))) + mathop op + +template wrap1s(op) {.immediate, dirty.} = + proc `op Wrapper`(a: VmArgs) {.nimcall.} = + setResult(a, op(getString(a, 0))) + osop op + +proc registerAdditionalOps*(c: PCtx) = + wrap1f(sqrt) + wrap1f(ln) + wrap1f(log10) + wrap1f(log2) + wrap1f(exp) + wrap1f(round) + wrap1f(arccos) + wrap1f(arcsin) + wrap1f(arctan) + wrap2f(arctan2) + wrap1f(cos) + wrap1f(cosh) + wrap2f(hypot) + wrap1f(sinh) + wrap1f(sin) + wrap1f(tan) + wrap1f(tanh) + wrap2f(pow) + wrap1f(trunc) + wrap1f(floor) + wrap1f(ceil) + wrap2f(fmod) + + wrap1s(getEnv) + wrap1s(existsEnv) + wrap1s(dirExists) + wrap1s(fileExists) diff --git a/lib/stdlib.babel b/lib/stdlib.nimble index f22598aba..0805ead54 100644 --- a/lib/stdlib.babel +++ b/lib/stdlib.nimble @@ -2,5 +2,5 @@ name = "stdlib" version = "0.9.0" author = "Dominik Picheta" -description = "Nimrod's standard library." +description = "Nim's standard library." license = "MIT" |