all repos — min @ 6670090005b171cec39bd37bb1634ed2f6ccb32d

A small but practical concatenative programming language.

Made some modules optional; added "lite mode".
h3rald h3rald@h3rald.com
Sat, 25 Mar 2017 13:33:22 +0100
commit

6670090005b171cec39bd37bb1634ed2f6ccb32d

parent

a97c16b62b53b8703c5f1da61d3721f9e9e110c3

M core/utils.nimcore/utils.nim

@@ -1,8 +1,10 @@

import strutils, critbits, + json, terminal import + ../packages/nim-sgregex/sgregex, parser, value, scope,

@@ -40,6 +42,116 @@ i.push mdl

i.evaluating = false if name != "": scope.previous.symbols[name] = MinOperator(kind: minProcOp, prc: op) + +# Dictionary Methods + +proc dget*(q: MinValue, s: MinValue): MinValue = + # Assumes q is a dictionary + for v in q.qVal: + if v.qVal[0].getString == s.getString: + return v.qVal[1] + raiseInvalid("Dictionary key '$1' not found" % s.getString) + +proc dhas*(q: MinValue, s: MinValue): bool = + # Assumes q is a dictionary + for v in q.qVal: + if v.qVal[0].getString == s.getString: + return true + return false + +proc ddel*(i: In, p: MinValue, s: MinValue): MinValue {.discardable.} = + # Assumes q is a dictionary + var q = newVal(p.qVal, i.scope) + var found = false + var c = -1 + for v in q.qVal: + c.inc + if v.qVal[0].getString == s.getString: + found = true + break + if found: + q.qVal.delete(c) + return q + +proc dset*(i: In, p: MinValue, s: MinValue, m: MinValue): MinValue {.discardable.}= + # Assumes q is a dictionary + var q = newVal(p.qVal, i.scope) + var found = false + var c = -1 + for v in q.qVal: + c.inc + if v.qVal[0].getString == s.getString: + found = true + break + if found: + q.qVal.delete(c) + q.qVal.insert(@[s.getString.newSym, m].newVal(i.scope), c) + else: + q.qVal.add(@[s.getString.newSym, m].newVal(i.scope)) + return q + +proc keys*(i: In, q: MinValue): MinValue = + # Assumes q is a dictionary + result = newSeq[MinValue](0).newVal(i.scope) + for v in q.qVal: + result.qVal.add v.qVal[0] + +proc values*(i: In, q: MinValue): MinValue = + # Assumes q is a dictionary + result = newSeq[MinValue](0).newVal(i.scope) + for v in q.qVal: + result.qVal.add v.qVal[1] + +# JSON interop + +proc `%`*(a: MinValue): JsonNode = + case a.kind: + of minBool: + return %a.boolVal + of minSymbol: + return %(";sym:$1" % [a.symVal]) + of minString: + return %a.strVal + of minInt: + return %a.intVal + of minFloat: + return %a.floatVal + of minQuotation: + if a.isDictionary: + result = newJObject() + for i in a.qVal: + result[$i.qVal[0].symVal] = %i.qVal[1] + else: + result = newJArray() + for i in a.qVal: + result.add %i + +proc fromJson*(i: In, json: JsonNode): MinValue = + case json.kind: + of JNull: + result = newSeq[MinValue](0).newVal(i.scope) + of JBool: + result = json.getBVal.newVal + of JInt: + result = json.getNum.newVal + of JFloat: + result = json.getFNum.newVal + of JString: + let s = json.getStr + if s.match("^;sym:"): + result = sgregex.replace(s, "^;sym:", "").newSym + else: + result = json.getStr.newVal + of JObject: + var res = newSeq[MinValue](0) + for key, value in json.pairs: + res.add @[key.newSym, i.fromJson(value)].newVal(i.scope) + return res.newVal(i.scope) + of JArray: + var res = newSeq[MinValue](0) + for value in json.items: + res.add i.fromJson(value) + return res.newVal(i.scope) # Validators
M lib/min_lang.nimlib/min_lang.nim

@@ -1,8 +1,8 @@

import critbits, strutils, - os, json, + os, algorithm, logging import

@@ -11,121 +11,11 @@ ../core/parser,

../core/value, ../core/interpreter, ../core/utils, - ../packages/niftylogger, ../packages/nim-sgregex/sgregex, + ../packages/niftylogger, ../packages/nimline/nimline, ../core/scope -# Dictionary Methods - -proc dget*(q: MinValue, s: MinValue): MinValue = - # Assumes q is a dictionary - for v in q.qVal: - if v.qVal[0].getString == s.getString: - return v.qVal[1] - raiseInvalid("Dictionary key '$1' not found" % s.getString) - -proc dhas*(q: MinValue, s: MinValue): bool = - # Assumes q is a dictionary - for v in q.qVal: - if v.qVal[0].getString == s.getString: - return true - return false - -proc ddel*(i: In, p: MinValue, s: MinValue): MinValue {.discardable.} = - # Assumes q is a dictionary - var q = newVal(p.qVal, i.scope) - var found = false - var c = -1 - for v in q.qVal: - c.inc - if v.qVal[0].getString == s.getString: - found = true - break - if found: - q.qVal.delete(c) - return q - -proc dset*(i: In, p: MinValue, s: MinValue, m: MinValue): MinValue {.discardable.}= - # Assumes q is a dictionary - var q = newVal(p.qVal, i.scope) - var found = false - var c = -1 - for v in q.qVal: - c.inc - if v.qVal[0].getString == s.getString: - found = true - break - if found: - q.qVal.delete(c) - q.qVal.insert(@[s.getString.newSym, m].newVal(i.scope), c) - else: - q.qVal.add(@[s.getString.newSym, m].newVal(i.scope)) - return q - -proc keys*(i: In, q: MinValue): MinValue = - # Assumes q is a dictionary - result = newSeq[MinValue](0).newVal(i.scope) - for v in q.qVal: - result.qVal.add v.qVal[0] - -proc values*(i: In, q: MinValue): MinValue = - # Assumes q is a dictionary - result = newSeq[MinValue](0).newVal(i.scope) - for v in q.qVal: - result.qVal.add v.qVal[1] - -# JSON interop - -proc `%`*(a: MinValue): JsonNode = - case a.kind: - of minBool: - return %a.boolVal - of minSymbol: - return %(";sym:$1" % [a.symVal]) - of minString: - return %a.strVal - of minInt: - return %a.intVal - of minFloat: - return %a.floatVal - of minQuotation: - if a.isDictionary: - result = newJObject() - for i in a.qVal: - result[$i.qVal[0].symVal] = %i.qVal[1] - else: - result = newJArray() - for i in a.qVal: - result.add %i - -proc fromJson*(i: In, json: JsonNode): MinValue = - case json.kind: - of JNull: - result = newSeq[MinValue](0).newVal(i.scope) - of JBool: - result = json.getBVal.newVal - of JInt: - result = json.getNum.newVal - of JFloat: - result = json.getFNum.newVal - of JString: - let s = json.getStr - if s.match("^;sym:"): - result = sgregex.replace(s, "^;sym:", "").newSym - else: - result = json.getStr.newVal - of JObject: - var res = newSeq[MinValue](0) - for key, value in json.pairs: - res.add @[key.newSym, i.fromJson(value)].newVal(i.scope) - return res.newVal(i.scope) - of JArray: - var res = newSeq[MinValue](0) - for value in json.items: - res.add i.fromJson(value) - return res.newVal(i.scope) - proc lang_module*(i: In) = i.scope .symbol("exit") do (i: In):

@@ -139,6 +29,31 @@ while not scope.isNil:

for s in scope.symbols.keys: q.add s.newVal scope = scope.parent + i.push q.newVal(i.scope) + + .symbol("sigils") do (i: In): + var q = newSeq[MinValue](0) + var scope = i.scope + while not scope.isNil: + for s in scope.sigils.keys: + q.add s.newVal + scope = scope.parent + i.push q.newVal(i.scope) + + .symbol("module-symbols") do (i: In): + var m: MinValue + i.reqQuotation m + var q = newSeq[MinValue](0) + for s in m.scope.symbols.keys: + q.add s.newVal + i.push q.newVal(i.scope) + + .symbol("module-sigils") do (i: In): + var m: MinValue + i.reqQuotation m + var q = newSeq[MinValue](0) + for s in m.scope.sigils.keys: + q.add s.newVal i.push q.newVal(i.scope) .symbol("sigils") do (i: In):

@@ -498,7 +413,7 @@ else:

i.unquote(fpath) .symbol("ift") do (i: In): - var fpath, tpath, check: MinValue + var tpath, check: MinValue i.reqTwoQuotations tpath, check var stack = i.stack i.unquote(check)
M lib/min_str.nimlib/min_str.nim

@@ -9,6 +9,7 @@ ../core/interpreter,

../core/utils, ../packages/nim-sgregex/sgregex + proc str_module*(i: In) = i.define()

@@ -29,37 +30,6 @@ .symbol("join") do (i: In):

var q, s: MinValue i.reqStringLikeAndQuotation s, q i.push q.qVal.mapIt($$it).join(s.getString).newVal - - .symbol("search") do (i: In): - var reg, str: MinValue - i.reqTwoStrings reg, str - var matches = str.strVal.search(reg.strVal) - var res = newSeq[MinValue](matches.len) - for i in 0..matches.len-1: - res[i] = matches[i].newVal - i.push res.newVal(i.scope) - - .symbol("match") do (i: In): - var reg, str: MinValue - i.reqTwoStrings reg, str - if str.strVal.match(reg.strVal): - i.push true.newVal - else: - i.push false.newVal - - .symbol("replace") do (i: In): - var s_replace, reg, s_find: MinValue - i.reqThreeStrings s_replace, reg, s_find - i.push sgregex.replace(s_find.strVal, reg.strVal, s_replace.strVal).newVal - - .symbol("regex") do (i: In): - var reg, str: MinValue - i.reqTwoStrings reg, str - let results = str.strVal =~ reg.strVal - var res = newSeq[MinValue](0) - for r in results: - res.add(r.newVal) - i.push res.newVal(i.scope) .symbol("lowercase") do (i: In): var s: MinValue

@@ -138,6 +108,37 @@ else:

i.push 0.float.newVal else: raiseInvalid("Cannot convert a quotation to float.") + + .symbol("search") do (i: In): + var reg, str: MinValue + i.reqTwoStrings reg, str + var matches = str.strVal.search(reg.strVal) + var res = newSeq[MinValue](matches.len) + for i in 0..matches.len-1: + res[i] = matches[i].newVal + i.push res.newVal(i.scope) + + .symbol("match") do (i: In): + var reg, str: MinValue + i.reqTwoStrings reg, str + if str.strVal.match(reg.strVal): + i.push true.newVal + else: + i.push false.newVal + + .symbol("replace") do (i: In): + var s_replace, reg, s_find: MinValue + i.reqThreeStrings s_replace, reg, s_find + i.push sgregex.replace(s_find.strVal, reg.strVal, s_replace.strVal).newVal + + .symbol("regex") do (i: In): + var reg, str: MinValue + i.reqTwoStrings reg, str + let results = str.strVal =~ reg.strVal + var res = newSeq[MinValue](0) + for r in results: + res.add(r.newVal) + i.push res.newVal(i.scope) .symbol("=~") do (i: In): i.push("regex".newSym)
M lib/min_sys.nimlib/min_sys.nim

@@ -9,170 +9,191 @@ ../core/parser,

../core/value, ../core/interpreter, ../core/utils, - ../core/fileutils, - ../packages/nim-miniz/miniz + ../core/fileutils + +when not defined(lite): + import ../packages/nim-miniz/miniz proc unix(s: string): string = return s.replace("\\", "/") proc sys_module*(i: In)= - i.define() + var sys = i.define() - .symbol(".") do (i: In): - i.push newVal(getCurrentDir().unix) - - .symbol("..") do (i: In): - i.push newVal(getCurrentDir().parentDir.unix) - - .symbol("cd") do (i: In): - var f: MinValue - i.reqStringLike f - f.getString.setCurrentDir - - .symbol("ls") do (i: In): - var a: MinValue - i.reqStringLike a - var list = newSeq[MinValue](0) - for i in walkDir(a.getString): - list.add newVal(i.path.unix) - i.push list.newVal(i.scope) + sys = sys.symbol(".") do (i: In): + i.push newVal(getCurrentDir().unix) - .symbol("ls-r") do (i: In): - var a: MinValue - i.reqStringLike a - var list = newSeq[MinValue](0) - for i in walkDirRec(a.getString): - list.add newVal(i.unix) - i.push list.newVal(i.scope) + .symbol("..") do (i: In): + i.push newVal(getCurrentDir().parentDir.unix) - .symbol("system") do (i: In): - var a: MinValue - i.reqStringLike a - i.push execShellCmd(a.getString).newVal + .symbol("cd") do (i: In): + var f: MinValue + i.reqStringLike f + f.getString.setCurrentDir + + .symbol("ls") do (i: In): + var a: MinValue + i.reqStringLike a + var list = newSeq[MinValue](0) + for i in walkDir(a.getString): + list.add newVal(i.path.unix) + i.push list.newVal(i.scope) + + .symbol("ls-r") do (i: In): + var a: MinValue + i.reqStringLike a + var list = newSeq[MinValue](0) + for i in walkDirRec(a.getString): + list.add newVal(i.unix) + i.push list.newVal(i.scope) + + .symbol("system") do (i: In): + var a: MinValue + i.reqStringLike a + i.push execShellCmd(a.getString).newVal + + .symbol("run") do (i: In): + var cmd: MinValue + i.reqStringLike cmd + let res = execCmdEx(cmd.getString) + i.push @[@["output".newSym, res.output.newVal].newVal(i.scope), @["code".newSym, res.exitCode.newVal].newVal(i.scope)].newVal(i.scope) + + .symbol("getenv") do (i: In): + var a: MinValue + i.reqStringLike a + i.push a.getString.getEnv.newVal + + .symbol("putenv") do (i: In): + var key, value: MinValue + i.reqTwoStringLike key, value + key.getString.putEnv value.getString - .symbol("run") do (i: In): - var cmd: MinValue - i.reqStringLike cmd - let res = execCmdEx(cmd.getString) - i.push @[@["output".newSym, res.output.newVal].newVal(i.scope), @["code".newSym, res.exitCode.newVal].newVal(i.scope)].newVal(i.scope) - - .symbol("getenv") do (i: In): - var a: MinValue - i.reqStringLike a - i.push a.getString.getEnv.newVal - - .symbol("putenv") do (i: In): - var key, value: MinValue - i.reqTwoStringLike key, value - key.getString.putEnv value.getString - - .symbol("env?") do (i: In): - var s: MinValue - i.reqStringLike s - i.push s.getString.existsEnv.newVal + .symbol("env?") do (i: In): + var s: MinValue + i.reqStringLike s + i.push s.getString.existsEnv.newVal - .symbol("which") do (i: In): - var s: MinValue - i.reqStringLike s - i.push s.getString.findExe.newVal + .symbol("which") do (i: In): + var s: MinValue + i.reqStringLike s + i.push s.getString.findExe.newVal - .symbol("os") do (i: In): - i.push hostOS.newVal + .symbol("os") do (i: In): + i.push hostOS.newVal + + .symbol("cpu") do (i: In): + i.push hostCPU.newVal + + .symbol("file?") do (i: In): + var f: MinValue + i.reqStringLike f + i.push f.getString.fileExists.newVal - .symbol("cpu") do (i: In): - i.push hostCPU.newVal + .symbol("dir?") do (i: In): + var f: MinValue + i.reqStringLike f + i.push f.getString.dirExists.newVal - .symbol("file?") do (i: In): - var f: MinValue - i.reqStringLike f - i.push f.getString.fileExists.newVal - - .symbol("dir?") do (i: In): - var f: MinValue - i.reqStringLike f - i.push f.getString.dirExists.newVal - - .symbol("rm") do (i: In): - var v: MinValue - i.reqStringLike v - let f = v.getString - if f.existsFile: - f.removeFile - elif f.existsDir: - f.removeDir - else: - raiseInvalid("File '$1' does not exist." % f) + .symbol("rm") do (i: In): + var v: MinValue + i.reqStringLike v + let f = v.getString + if f.existsFile: + f.removeFile + elif f.existsDir: + f.removeDir + else: + raiseInvalid("File '$1' does not exist." % f) - .symbol("cp") do (i: In): - var a, b: MinValue - i.reqTwoStringLike a, b - let src = b.getString - var dest = a.getString + .symbol("cp") do (i: In): + var a, b: MinValue + i.reqTwoStringLike a, b + let src = b.getString + var dest = a.getString + if src.dirExists: + copyDirWithPermissions src, dest + elif dest.dirExists: if src.dirExists: copyDirWithPermissions src, dest - elif dest.dirExists: - if src.dirExists: - copyDirWithPermissions src, dest - else: - copyFileWithPermissions src, dest / src.extractFilename else: - copyFileWithPermissions src, dest - - .symbol("mv") do (i: In): - var a, b: MinValue - i.reqTwoStringLike a, b - let src = b.getString - var dest = a.getString - if dest.dirExists: - dest = dest / src.extractFilename - moveFile src, dest - - .symbol("rmdir") do (i: In): - var f: MinValue - i.reqStringLike f - f.getString.removeDir + copyFileWithPermissions src, dest / src.extractFilename + else: + copyFileWithPermissions src, dest - .symbol("mkdir") do (i: In): - var f: MinValue - i.reqStringLike f - f.getString.createDir + .symbol("mv") do (i: In): + var a, b: MinValue + i.reqTwoStringLike a, b + let src = b.getString + var dest = a.getString + if dest.dirExists: + dest = dest / src.extractFilename + moveFile src, dest - .symbol("sleep") do (i: In): - var ms: MinValue - i.reqInt ms - sleep ms.intVal.int + .symbol("rmdir") do (i: In): + var f: MinValue + i.reqStringLike f + f.getString.removeDir - .symbol("chmod") do (i: In): - var s, perms: MinValue - i.reqIntAndString perms, s - s.getString.setFilePermissions(perms.intVal.toFilePermissions) + .symbol("mkdir") do (i: In): + var f: MinValue + i.reqStringLike f + f.getString.createDir + + .symbol("sleep") do (i: In): + var ms: MinValue + i.reqInt ms + sleep ms.intVal.int + + .symbol("chmod") do (i: In): + var s, perms: MinValue + i.reqIntAndString perms, s + s.getString.setFilePermissions(perms.intVal.toFilePermissions) + + .symbol("symlink?") do (i: In): + var s: MinValue + i.reqStringLike s + i.push s.getString.symlinkExists.newVal + + .symbol("symlink") do (i: In): + var src, dest: MinValue + i.reqTwoStringLike dest, src + src.getString.createSymlink dest.getString - .symbol("symlink?") do (i: In): - var s: MinValue - i.reqStringLike s - i.push s.getString.symlinkExists.newVal + .symbol("hardlink") do (i: In): + var src, dest: MinValue + i.reqTwoStringLike dest, src + src.getString.createHardlink dest.getString - .symbol("symlink") do (i: In): - var src, dest: MinValue - i.reqTwoStringLike dest, src - src.getString.createSymlink dest.getString + .symbol("filename") do (i: In): + var f: MinValue + i.reqStringLike f + i.push f.getString.extractFilename.unix.newVal - .symbol("hardlink") do (i: In): - var src, dest: MinValue - i.reqTwoStringLike dest, src - src.getString.createHardlink dest.getString + .symbol("dirname") do (i: In): + var f: MinValue + i.reqStringLike f + i.push f.getString.parentDir.unix.newVal + + .symbol("$") do (i: In): + i.push("getenv".newSym) + + .symbol("!") do (i: In): + i.push("system".newSym) + + .symbol("&") do (i: In): + i.push("run".newSym) + + .sigil("$") do (i: In): + i.push("getenv".newSym) - .symbol("filename") do (i: In): - var f: MinValue - i.reqStringLike f - i.push f.getString.extractFilename.unix.newVal + .sigil("!") do (i: In): + i.push("system".newSym) - .symbol("dirname") do (i: In): - var f: MinValue - i.reqStringLike f - i.push f.getString.parentDir.unix.newVal + .sigil("&") do (i: In): + i.push("run".newSym) - .symbol("unzip") do (i: In): + when not defined(lite): + sys = sys.symbol("unzip") do (i: In): var f, dir: MinValue i.reqTwoStringLike dir, f miniz.unzip(f.getString, dir.getString)

@@ -182,22 +203,5 @@ var files, file: MinValue

i.reqStringLikeAndQuotation file, files miniz.zip(files.qVal.mapIt(it.getString), file.getString) - .symbol("$") do (i: In): - i.push("getenv".newSym) - - .symbol("!") do (i: In): - i.push("system".newSym) - - .symbol("&") do (i: In): - i.push("run".newSym) - - .sigil("$") do (i: In): - i.push("getenv".newSym) - - .sigil("!") do (i: In): - i.push("system".newSym) - - .sigil("&") do (i: In): - i.push("run".newSym) - - .finalize("sys") + sys.finalize("sys") +
M min.nimmin.nim

@@ -26,8 +26,10 @@ lib/min_logic,

lib/min_time, lib/min_io, lib/min_sys, - lib/min_crypto, lib/min_fs + +when not defined(lite): + import lib/min_crypto export parser,

@@ -128,7 +130,8 @@ i.str_module

i.sys_module i.time_module i.fs_module - i.crypto_module + when not defined(lite): + i.crypto_module i.eval PRELUDE, "<prelude>" i.eval MINRC.readFile()
M min.vimmin.vim

@@ -11,7 +11,7 @@

setl iskeyword=@,36-39,+,-,/,*,.,:,~,!,48-57,60-65,94-95,192-255 setl iskeyword+=^ -syntax keyword minDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / : < <= == => =~ > >= @ ROOT aes and append ask at atime b bind bool bool? bury1 bury2 bury3 c call call! capitalize case cd chmod choose clear-stack column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode decrypt define delete dget dictionary? dig1 dig2 dig3 dip dir? dirname div dprint dprint! dset dump-stack dup dupd encode encrypt env? error eval even? exit fappend fatal file? filename filter first float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite gets get-stack getenv hardlink hidden? i id ift ifte import indent info inspect int int? interpolate interval io join k keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map match md5 mkdir mod module mtime mv newline not notice now num number? odd? os password pop popd pred print print! prompt publish puts puts! putenv q quotation? quote quote-bind quote-define raise regex remove-symbol repeat replace rest rm rmdir run save-symbol scope scope? seal search set-stack sha1 sha224 sha256 sha384 sha512 sigils sip sleep sort source split startup stored-symbols str string string? strip succ swap swapd swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote uppercase unzip values version warn which while with xor zip contains +syntax keyword minDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / : < <= == => =~ > >= @ ROOT aes and append ask at atime b bind bool bool? bury1 bury2 bury3 c call call! capitalize case cd chmod choose clear-stack column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode decrypt define delete dget dictionary? dig1 dig2 dig3 dip dir? dirname div dprint dprint! dset dump-stack dup dupd encode encrypt env? error eval even? exit fappend fatal file? filename filter first float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite gets get-stack getenv hardlink hidden? i id ift ifte import indent info inspect int int? interpolate interval io join k keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map match md5 mkdir mod module module-symbols module-sigils mtime mv newline not notice now num number? odd? os password pop popd pred print print! prompt publish puts puts! putenv q quotation? quote quote-bind quote-define raise regex remove-symbol repeat replace rest rm rmdir run save-symbol scope scope? seal search set-stack sha1 sha224 sha256 sha384 sha512 sigils sip sleep sort source split startup stored-symbols str string string? strip succ swap swapd swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote uppercase unzip values version warn which while with xor zip contains syntax match minDefaultSigil ;\<[:@'~!$%&$=<>#^*#+/]; contained
M prelude.minprelude.min

@@ -1,13 +1,13 @@

; Imports -'stack import 'str import 'io import 'logic import 'num import 'sys import -'time import -'fs import -'crypto import +;'stack import +;'time import +;'fs import +;'crypto import ; Unsealed symbols () :startup
M tests/all.mintests/all.min

@@ -1,3 +1,10 @@

+; Import optional module +'stack import +'time import +'fs import +'crypto import + +; Load test files 'lang load 'stack load 'io load
M tests/lang.mintests/lang.min

@@ -186,6 +186,10 @@ ((3 4 7 2 4 6 5 6) '> sort (2 3 4 4 5 6 6 7) ==) assert

((3 4 7 2 4 6 5 6) '< sort (7 6 6 5 4 4 3 2) ==) assert + (time module-symbols ("datetime" "now" "tformat" "timeinfo" "timestamp") ==) assert + + (sys module-sigils ("!" "$" "&") ==) assert + report ; Tidy up clear-stack