summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/vmgen.nim6
-rw-r--r--compiler/vmhooks.nim7
-rw-r--r--compiler/vmops.nim10
-rw-r--r--lib/pure/os.nim90
4 files changed, 69 insertions, 44 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 97c6a5580..2a16406e7 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1604,7 +1604,8 @@ proc matches(s: PSym; x: string): bool =
   var s = s
   var L = y.len-1
   while L >= 0:
-    if s == nil or y[L].cmpIgnoreStyle(s.name.s) != 0: return false
+    if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
+      return false
     s = s.owner
     dec L
   result = true
@@ -1613,7 +1614,8 @@ proc matches(s: PSym; y: varargs[string]): bool =
   var s = s
   var L = y.len-1
   while L >= 0:
-    if s == nil or y[L].cmpIgnoreStyle(s.name.s) != 0: return false
+    if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
+      return false
     s = if sfFromGeneric in s.flags: s.owner.owner else: s.owner
     dec L
   result = true
diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim
index 576b0565f..3456e893b 100644
--- a/compiler/vmhooks.nim
+++ b/compiler/vmhooks.nim
@@ -55,9 +55,16 @@ template getX(k, field) {.immediate, dirty.} =
   result = s[i+a.rb+1].field
 
 proc getInt*(a: VmArgs; i: Natural): BiggestInt = getX(rkInt, intVal)
+proc getBool*(a: VmArgs; i: Natural): bool = getInt(a, i) != 0
 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
+
+proc getNode*(a: VmArgs; i: Natural): PNode =
+  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
diff --git a/compiler/vmops.nim b/compiler/vmops.nim
index e1a0dfef8..e40e05eff 100644
--- a/compiler/vmops.nim
+++ b/compiler/vmops.nim
@@ -13,7 +13,7 @@ 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
+from os import getEnv, existsEnv, dirExists, fileExists, walkDir
 
 template mathop(op) {.immediate, dirty.} =
   registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`)
@@ -48,6 +48,12 @@ proc getCurrentExceptionMsgWrapper(a: VmArgs) {.nimcall.} =
   setResult(a, if a.currentException.isNil: ""
                else: a.currentException.sons[3].skipColon.strVal)
 
+proc staticWalkDirImpl(path: string, relative: bool): PNode =
+  result = newNode(nkBracket)
+  for k, f in walkDir(path, relative):
+    result.add newTree(nkPar, newIntNode(nkIntLit, k.ord),
+                              newStrNode(nkStrLit, f))
+
 proc registerAdditionalOps*(c: PCtx) =
   wrap1f(sqrt)
   wrap1f(ln)
@@ -78,3 +84,5 @@ proc registerAdditionalOps*(c: PCtx) =
   wrap1s(fileExists)
   wrap2svoid(writeFile)
   systemop getCurrentExceptionMsg
+  registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
+    setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index c01228563..7c14c46cf 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -810,6 +810,10 @@ type
 
 {.deprecated: [TPathComponent: PathComponent].}
 
+proc staticWalkDir(dir: string; relative: bool): seq[
+                  tuple[kind: PathComponent, path: string]] =
+  discard
+
 iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] {.
   tags: [ReadDirEffect].} =
   ## walks over the directory `dir` and yields for each directory or file in
@@ -833,49 +837,53 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
   ##   dirA/dirC
   ##   dirA/fileA1.txt
   ##   dirA/fileA2.txt
-  when defined(windows):
-    var f: WIN32_FIND_DATA
-    var h = findFirstFile(dir / "*", f)
-    if h != -1:
-      while true:
-        var k = pcFile
-        if not skipFindData(f):
-          if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
-            k = pcDir
-          if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
-            k = succ(k)
-          let xx = if relative: extractFilename(getFilename(f))
-                   else: dir / extractFilename(getFilename(f))
-          yield (k, xx)
-        if findNextFile(h, f) == 0'i32: break
-      findClose(h)
+  when nimvm:
+    for k, v in items(staticWalkDir(dir, relative)):
+      yield (k, v)
   else:
-    var d = opendir(dir)
-    if d != nil:
-      while true:
-        var x = readdir(d)
-        if x == nil: break
-        var y = $x.d_name
-        if y != "." and y != "..":
-          var s: Stat
-          if not relative:
-            y = dir / y
+    when defined(windows):
+      var f: WIN32_FIND_DATA
+      var h = findFirstFile(dir / "*", f)
+      if h != -1:
+        while true:
           var k = pcFile
-
-          when defined(linux) or defined(macosx) or defined(bsd):
-            if x.d_type != DT_UNKNOWN:
-              if x.d_type == DT_DIR: k = pcDir
-              if x.d_type == DT_LNK:
-                if dirExists(y): k = pcLinkToDir
-                else: k = succ(k)
-              yield (k, y)
-              continue
-
-          if lstat(y, s) < 0'i32: break
-          if S_ISDIR(s.st_mode): k = pcDir
-          if S_ISLNK(s.st_mode): k = succ(k)
-          yield (k, y)
-      discard closedir(d)
+          if not skipFindData(f):
+            if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
+              k = pcDir
+            if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
+              k = succ(k)
+            let xx = if relative: extractFilename(getFilename(f))
+                     else: dir / extractFilename(getFilename(f))
+            yield (k, xx)
+          if findNextFile(h, f) == 0'i32: break
+        findClose(h)
+    else:
+      var d = opendir(dir)
+      if d != nil:
+        while true:
+          var x = readdir(d)
+          if x == nil: break
+          var y = $x.d_name
+          if y != "." and y != "..":
+            var s: Stat
+            if not relative:
+              y = dir / y
+            var k = pcFile
+
+            when defined(linux) or defined(macosx) or defined(bsd):
+              if x.d_type != DT_UNKNOWN:
+                if x.d_type == DT_DIR: k = pcDir
+                if x.d_type == DT_LNK:
+                  if dirExists(y): k = pcLinkToDir
+                  else: k = succ(k)
+                yield (k, y)
+                continue
+
+            if lstat(y, s) < 0'i32: break
+            if S_ISDIR(s.st_mode): k = pcDir
+            if S_ISLNK(s.st_mode): k = succ(k)
+            yield (k, y)
+        discard closedir(d)
 
 iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
   tags: [ReadDirEffect].} =