From 1f85b3b5d3f8a9cf84fc5c03604ac3a7ea901d8c Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 30 Aug 2014 16:37:27 +0200 Subject: [PATCH] VM supports math and a few os procs --- compiler/nimblecmd.nim | 2 +- compiler/pretty.nim | 2 +- compiler/vm.nim | 14 ++++-- compiler/vmdef.nim | 13 +++++- compiler/vmgen.nim | 23 +++++++++- compiler/vmhooks.nim | 45 ++++++++++++++++++++ compiler/vmops.nim | 66 +++++++++++++++++++++++++++++ lib/{stdlib.babel => stdlib.nimble} | 2 +- 8 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 compiler/vmhooks.nim create mode 100644 compiler/vmops.nim rename lib/{stdlib.babel => stdlib.nimble} (71%) diff --git a/compiler/nimblecmd.nim b/compiler/nimblecmd.nim index 0f73c17bdc..049b94aa96 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 5f990a658b..356399c1c8 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 af0b30faa0..fe2b9c6178 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) .. = 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 0000000000..cce87d4330 --- /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 0000000000..8e75cc23ac --- /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 similarity index 71% rename from lib/stdlib.babel rename to lib/stdlib.nimble index f22598aba6..0805ead548 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"