envPairs works in vm, nims (#18615)

* envPairs works in vm, nims

* fixup
This commit is contained in:
Timothee Cour 2021-09-29 00:32:39 -07:00 • committed by GitHub
commit f061971a9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 213 additions and 210 deletions

View file

@ -13,7 +13,7 @@ from std/math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc, arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
floor, ceil, `mod`, cbrt, arcsinh, arccosh, arctanh, erf, erfc, gamma, floor, ceil, `mod`, cbrt, arcsinh, arccosh, arctanh, erf, erfc, gamma,
lgamma lgamma
from std/sequtils import toSeq
when declared(math.copySign): when declared(math.copySign):
# pending bug #18762, avoid renaming math # pending bug #18762, avoid renaming math
from std/math as math2 import copySign from std/math as math2 import copySign
@ -22,8 +22,8 @@ when declared(math.signbit):
# ditto # ditto
from std/math as math3 import signbit from std/math as math3 import signbit
from std/os import getEnv, existsEnv, delEnv, putEnv, dirExists, fileExists, walkDir, from std/os import getEnv, existsEnv, delEnv, putEnv, envPairs,
getAppFilename, raiseOSError, osLastError dirExists, fileExists, walkDir, getAppFilename, raiseOSError, osLastError
from std/md5 import getMD5 from std/md5 import getMD5
from std/times import cpuTime from std/times import cpuTime
@ -156,6 +156,12 @@ proc stackTrace2(c: PCtx, msg: string, n: PNode) =
stackTrace(c, PStackFrame(prc: c.prc.sym, comesFrom: 0, next: nil), c.exceptionInstr, msg, n.info) stackTrace(c, PStackFrame(prc: c.prc.sym, comesFrom: 0, next: nil), c.exceptionInstr, msg, n.info)
proc registerAdditionalOps*(c: PCtx) = proc registerAdditionalOps*(c: PCtx) =
template wrapIterator(fqname: string, iter: untyped) =
registerCallback c, fqname, proc(a: VmArgs) =
setResult(a, toLit(toSeq(iter)))
proc gorgeExWrapper(a: VmArgs) = proc gorgeExWrapper(a: VmArgs) =
let ret = opGorge(getString(a, 0), getString(a, 1), getString(a, 2), let ret = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
a.currentLineInfo, c.config) a.currentLineInfo, c.config)
@ -341,3 +347,5 @@ proc registerAdditionalOps*(c: PCtx) =
let p = a.getVar(0) let p = a.getVar(0)
let x = a.getFloat(1) let x = a.getFloat(1)
addFloatSprintf(p.strVal, x) addFloatSprintf(p.strVal, x)
wrapIterator("stdlib.os.envPairsImplSeq"): envPairs()

View file

@ -3,6 +3,7 @@
when not declared(os) and not declared(ospaths): when not declared(os) and not declared(ospaths):
{.error: "This is an include file for os.nim!".} {.error: "This is an include file for os.nim!".}
when not defined(nimscript):
when defined(nodejs): when defined(nodejs):
proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} = proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} =
var ret = default.cstring var ret = default.cstring
@ -26,7 +27,7 @@ when defined(nodejs):
var key2 = key.cstring var key2 = key.cstring
{.emit: "delete process.env[`key2`];".} {.emit: "delete process.env[`key2`];".}
iterator envPairs*(): tuple[key, value: string] {.tags: [ReadEnvEffect].} = iterator envPairsImpl(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
var num: int var num: int
var keys: RootObj var keys: RootObj
{.emit: "`keys` = Object.keys(process.env); `num` = `keys`.length;".} {.emit: "`keys` = Object.keys(process.env); `num` = `keys`.length;".}
@ -151,17 +152,7 @@ else:
else: else:
var gEnv {.importc: "environ".}: cstringArray var gEnv {.importc: "environ".}: cstringArray
iterator envPairs*(): tuple[key, value: string] {.tags: [ReadEnvEffect].} = iterator envPairsImpl(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
## Iterate over all `environments variables`:idx:.
##
## In the first component of the tuple is the name of the current variable stored,
## in the second its value.
##
## See also:
## * `getEnv proc <#getEnv,string,string>`_
## * `existsEnv proc <#existsEnv,string>`_
## * `putEnv proc <#putEnv,string,string>`_
## * `delEnv proc <#delEnv,string>`_
when defined(windows): when defined(windows):
block: block:
template impl(get_fun, typ, size, zero, free_fun) = template impl(get_fun, typ, size, zero, free_fun) =
@ -189,3 +180,23 @@ else:
inc(i) inc(i)
let p = find(kv, '=') let p = find(kv, '=')
yield (substr(kv, 0, p-1), substr(kv, p+1)) yield (substr(kv, 0, p-1), substr(kv, p+1))
proc envPairsImplSeq(): seq[tuple[key, value: string]] = discard # vmops
iterator envPairs*(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
## Iterate over all `environments variables`:idx:.
##
## In the first component of the tuple is the name of the current variable stored,
## in the second its value.
##
## Works in native backends, nodejs and vm, like the following APIs:
## * `getEnv proc <#getEnv,string,string>`_
## * `existsEnv proc <#existsEnv,string>`_
## * `putEnv proc <#putEnv,string,string>`_
## * `delEnv proc <#delEnv,string>`_
when nimvm:
for ai in envPairsImplSeq(): yield ai
else:
when defined(nimscript): discard
else:
for ai in envPairsImpl(): yield ai

View file

@ -871,7 +871,6 @@ proc unixToNativePath*(path: string, drive=""): string {.
inc(i) inc(i)
include "includes/oserr" include "includes/oserr"
when not defined(nimscript):
include "includes/osenv" include "includes/osenv"
proc getHomeDir*(): string {.rtl, extern: "nos$1", proc getHomeDir*(): string {.rtl, extern: "nos$1",

View file

@ -1,4 +1,7 @@
import std/private/miscdollars import std/private/miscdollars
when defined(nimscript):
import std/os # xxx investigate why needed
else:
from std/os import getEnv from std/os import getEnv
import std/[macros, genasts] import std/[macros, genasts]
@ -26,7 +29,7 @@ template flakyAssert*(cond: untyped, msg = "", notifySuccess = true) =
msg2.add $expr & " " & msg msg2.add $expr & " " & msg
echo msg2 echo msg2
when not defined(js): when not defined(js) and not defined(nimscript):
import std/strutils import std/strutils
proc greedyOrderedSubsetLines*(lhs, rhs: string, allowPrefixMatch = false): bool = proc greedyOrderedSubsetLines*(lhs, rhs: string, allowPrefixMatch = false): bool =

View file

@ -1,3 +1,5 @@
# xxx consider merging this in tests/stdlib/tos.nim for increased coverage (with selecting disabling)
static: doAssert defined(nodejs) static: doAssert defined(nodejs)
import os import os
@ -19,29 +21,3 @@ block:
if not isWindows: if not isWindows:
doAssert cwd.isAbsolute doAssert cwd.isAbsolute
doAssert relativePath(getCurrentDir() / "foo", "bar") == "../foo" doAssert relativePath(getCurrentDir() / "foo", "bar") == "../foo"
import std/sequtils
template main =
putEnv("foo", "bar")
doAssert getEnv("foo") == "bar"
doAssert existsEnv("foo")
putEnv("foo", "")
doAssert existsEnv("foo")
putEnv("foo", "bar2")
doAssert getEnv("foo") == "bar2"
when nimvm:
discard
else:
# need support in vmops: envPairs, delEnv
let s = toSeq(envPairs())
doAssert ("foo", "bar2") in s
doAssert ("foo", "bar") notin s
delEnv("foo")
doAssert not existsEnv("foo")
static: main()
main()

View file

@ -13,15 +13,17 @@ template main =
for val in ["val", ""]: # ensures empty val works too for val in ["val", ""]: # ensures empty val works too
const key = "NIM_TESTS_TOSENV_KEY" const key = "NIM_TESTS_TOSENV_KEY"
doAssert not existsEnv(key) doAssert not existsEnv(key)
putEnv(key, val)
putEnv(key, "tempval")
doAssert existsEnv(key)
doAssert getEnv(key) == "tempval"
putEnv(key, val) # change a key that already exists
doAssert existsEnv(key) doAssert existsEnv(key)
doAssert getEnv(key) == val doAssert getEnv(key) == val
when nimvm: discard
else:
doAssert (key, val) in toSeq(envPairs()) doAssert (key, val) in toSeq(envPairs())
delEnv(key) delEnv(key)
when nimvm: discard
else:
doAssert (key, val) notin toSeq(envPairs()) doAssert (key, val) notin toSeq(envPairs())
doAssert not existsEnv(key) doAssert not existsEnv(key)
delEnv(key) # deleting an already deleted env var delEnv(key) # deleting an already deleted env var
@ -43,7 +45,7 @@ template main =
static: main() static: main()
main() main()
when not defined(js): when not defined(js) and not defined(nimscript):
block: # bug #18533 block: # bug #18533
proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".} proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
var thr: Thread[void] var thr: Thread[void]

View file

@ -71,7 +71,11 @@ import std/[
decls, compilesettings, with, wrapnils decls, compilesettings, with, wrapnils
] ]
# non-std imports
import stdtest/testutils
# tests (increase coverage via code reuse)
import stdlib/trandom import stdlib/trandom
import stdlib/tosenv
echo "Nimscript imports are successful." echo "Nimscript imports are successful."