summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/vm.nim5
-rw-r--r--compiler/vmdeps.nim40
-rw-r--r--compiler/vmgen.nim14
-rw-r--r--lib/system.nim15
4 files changed, 59 insertions, 15 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 6d496d6e1..40d273ceb 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1168,9 +1168,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
                                      c.module)
     of opcGorge:
       decodeBC(rkNode)
+      inc pc
+      let rd = c.code[pc].regA
+
       createStr regs[ra]
       regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
-                                     regs[rc].node.strVal)
+                                     regs[rc].node.strVal, regs[rd].node.strVal)
     of opcNError:
       stackTrace(c, tos, pc, errUser, regs[ra].node.strVal)
     of opcNWarning:
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 88bb7ae24..73016108d 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-import ast, types, msgs, osproc, streams, options, idents
+import ast, types, msgs, osproc, streams, options, idents, securehash
 
 proc readOutput(p: Process): string =
   result = ""
@@ -19,15 +19,35 @@ proc readOutput(p: Process): string =
     result.setLen(result.len - "\n".len)
   discard p.waitForExit
 
-proc opGorge*(cmd, input: string): string =
-  try:
-    var p = startProcess(cmd, options={poEvalCommand})
-    if input.len != 0:
-      p.inputStream.write(input)
-      p.inputStream.close()
-    result = p.readOutput
-  except IOError, OSError:
-    result = ""
+proc opGorge*(cmd, input, cache: string): string =
+  if cache.len > 0:# and optForceFullMake notin gGlobalOptions:
+    let h = secureHash(cmd & "\t" & input & "\t" & cache)
+    let filename = options.toGeneratedFile("gorge_" & $h, "txt")
+    var f: File
+    if open(f, filename):
+      result = f.readAll
+      f.close
+      return
+    var readSuccessful = false
+    try:
+      var p = startProcess(cmd, options={poEvalCommand})
+      if input.len != 0:
+        p.inputStream.write(input)
+        p.inputStream.close()
+      result = p.readOutput
+      readSuccessful = true
+      writeFile(filename, result)
+    except IOError, OSError:
+      if not readSuccessful: result = ""
+  else:
+    try:
+      var p = startProcess(cmd, options={poEvalCommand})
+      if input.len != 0:
+        p.inputStream.write(input)
+        p.inputStream.close()
+      result = p.readOutput
+    except IOError, OSError:
+      result = ""
 
 proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
   try:
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 004adedb9..7abcbdb92 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -599,6 +599,18 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
   c.freeTemp(tmp)
   c.freeTemp(tmp2)
 
+proc genBinaryABCD(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
+  let
+    tmp = c.genx(n.sons[1])
+    tmp2 = c.genx(n.sons[2])
+    tmp3 = c.genx(n.sons[3])
+  if dest < 0: dest = c.getTemp(n.typ)
+  c.gABC(n, opc, dest, tmp, tmp2)
+  c.gABC(n, opc, tmp3)
+  c.freeTemp(tmp)
+  c.freeTemp(tmp2)
+  c.freeTemp(tmp3)
+
 proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
   let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
   # uint is uint64 in the VM, we we only need to mask the result for
@@ -932,7 +944,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     c.gABC(n, opcTypeTrait, dest, tmp)
     c.freeTemp(tmp)
   of mSlurp: genUnaryABC(c, n, dest, opcSlurp)
-  of mStaticExec: genBinaryABC(c, n, dest, opcGorge)
+  of mStaticExec: genBinaryABCD(c, n, dest, opcGorge)
   of mNLen: genUnaryABI(c, n, dest, opcLenSeq)
   of mNChild: genBinaryABC(c, n, dest, opcNChild)
   of mNSetChild, mNDel:
diff --git a/lib/system.nim b/lib/system.nim
index 27338b3b4..f8a4f7fcf 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -3091,11 +3091,11 @@ proc staticRead*(filename: string): string {.magic: "Slurp".}
   ##
   ## `slurp <#slurp>`_ is an alias for ``staticRead``.
 
-proc gorge*(command: string, input = ""): string {.
+proc gorge*(command: string, input = "", cache = ""): string {.
   magic: "StaticExec".} = discard
   ## This is an alias for `staticExec <#staticExec>`_.
 
-proc staticExec*(command: string, input = ""): string {.
+proc staticExec*(command: string, input = "", cache = ""): string {.
   magic: "StaticExec".} = discard
   ## Executes an external process at compile-time.
   ## if `input` is not an empty string, it will be passed as a standard input
@@ -3108,6 +3108,15 @@ proc staticExec*(command: string, input = ""): string {.
   ## `gorge <#gorge>`_ is an alias for ``staticExec``. Note that you can use
   ## this proc inside a pragma like `passC <nimc.html#passc-pragma>`_ or `passL
   ## <nimc.html#passl-pragma>`_.
+  ##
+  ## If ``cache`` is not empty, the results of ``staticExec`` are cached within
+  ## the ``nimcache`` directory. Use ``--forceBuild`` to get rid of this caching
+  ## behaviour then. ``command & input & cache`` (the concatenated string) is
+  ## used to determine wether the entry in the cache is still valid. You can
+  ## use versioning information for ``cache``:
+  ##
+  ## .. code-block:: nim
+  ##     const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0")
 
 proc `+=`*[T: SomeOrdinal|uint|uint64](x: var T, y: T) {.magic: "Inc", noSideEffect.}
   ## Increments an ordinal
@@ -3329,7 +3338,7 @@ when declared(initDebugger):
 when hasAlloc:
   # XXX: make these the default (or implement the NilObject optimization)
   proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} =
-    ## Adds ``y`` to ``x`` unless ``x`` is not yet initialized; in that case, 
+    ## Adds ``y`` to ``x`` unless ``x`` is not yet initialized; in that case,
     ## ``x`` becomes ``@[y]``
     if x == nil: x = @[y]
     else: x.add(y)