all repos — min @ b629141987257ea5bbd3f9bb5f8e4aeeaefb6300

A small but practical concatenative programming language.

Prepended std/ to stdlib modules; added checksums.
h3rald h3rald@h3rald.com
Sat, 30 Sep 2023 16:00:11 +0200
commit

b629141987257ea5bbd3f9bb5f8e4aeeaefb6300

parent

7c213a3d34f6e04fd7b1b8b5ad734f4f8f27751b

M min.nimblemin.nimble

@@ -14,7 +14,8 @@ installDirs = @["minpkg"]

# Dependencies -requires "nim >= 1.6.12" +requires "nim >= 2.0.0 & < 3.0.0" +requires "checksums" requires "zippy >= 0.5.6 & < 0.6.0" requires "nimquery >= 2.0.1 & < 3.0.0" requires "minline >= 0.1.1 & < 0.2.0"
M min.ymlmin.yml

@@ -1,5 +1,5 @@

author: Fabio Cevasco description: A small but practical concatenative programming language and shell. -id: 114841179 +id: 123212274 name: min -version: 0.39.2+version: 0.40.0
M minpkg/core/baseutils.nimminpkg/core/baseutils.nim

@@ -1,12 +1,12 @@

-import - strutils, - os, - json +import + std/[strutils, + os, + json] proc reverse*[T](xs: openarray[T]): seq[T] = result = newSeq[T](xs.len) for i, x in xs: - result[result.len-i-1] = x + result[result.len-i-1] = x proc simplifyPath*(filename: string, f: string): string = let file = strutils.replace(f, "\\", "/")

@@ -21,10 +21,10 @@ result = pwd&"/"&file

proc unix*(s: string): string = return s.replace("\\", "/") - + proc parentDirEx*(s: string): string = return s.parentDir - + proc escapeEx*(s: string, unquoted = false): string = if unquoted: return s.escapeJsonUnquoted
M minpkg/core/env.nimminpkg/core/env.nim

@@ -1,7 +1,7 @@

-import - os, +import + std/os, minline - + var HOME*: string if defined(windows): HOME = getenv("USERPROFILE")

@@ -9,8 +9,8 @@ if not defined(windows):

HOME = getenv("HOME") var MINRC* {.threadvar.}: string -MINRC = HOME / ".minrc" -var MINSYMBOLS* {.threadvar.}: string +MINRC = HOME / ".minrc" +var MINSYMBOLS* {.threadvar.}: string MINSYMBOLS = HOME / ".min_symbols" var MINHISTORY* {.threadvar.}: string MINHISTORY = HOME / ".min_history"
M minpkg/core/fileutils.nimminpkg/core/fileutils.nim

@@ -1,5 +1,5 @@

import - os + std/os # Filetype and permissions

@@ -97,4 +97,4 @@ result.incl fpOthersWrite

if others == 7: result.incl fpOthersRead result.incl fpOthersWrite - result.incl fpOthersExec+ result.incl fpOthersExec
M minpkg/core/interpreter.nimminpkg/core/interpreter.nim

@@ -1,15 +1,15 @@

-import - streams, - strutils, +import + std/[streams, + strutils, sequtils, os, - std/osproc, + osproc, critbits, json, algorithm, base64, - logging -import + logging] +import baseutils, value, scope,

@@ -36,10 +36,14 @@ if not a.contains it:

result.add it proc newSym*(i: In, s: string): MinValue = - return MinValue(kind: minSymbol, symVal: s, filename: i.currSym.filename, line: i.currSym.line, column: i.currSym.column, outerSym: i.currSym.symVal) + return MinValue(kind: minSymbol, symVal: s, filename: i.currSym.filename, + line: i.currSym.line, column: i.currSym.column, + outerSym: i.currSym.symVal) proc copySym*(i: In, sym: MinValue): MinValue = - return MinValue(kind: minSymbol, symVal: sym.outerSym, filename: sym.filename, line: sym.line, column: sym.column, outerSym: "", docComment: sym.docComment) + return MinValue(kind: minSymbol, symVal: sym.outerSym, filename: sym.filename, + line: sym.line, column: sym.column, outerSym: "", + docComment: sym.docComment) proc raiseRuntime*(msg: string, data: MinValue) = data.objType = "error"

@@ -57,7 +61,7 @@

proc debug*(i: In, value: string) = debug(value) -template withScope*(i: In, res:ref MinScope, body: untyped): untyped = +template withScope*(i: In, res: ref MinScope, body: untyped): untyped = let origScope = i.scope try: i.scope = newScopeRef(origScope)

@@ -86,15 +90,15 @@ proc newMinInterpreter*(filename = "input", pwd = ""): MinInterpreter =

var path = pwd if not pwd.isAbsolute: path = joinPath(getCurrentDir(), pwd) - var stack:MinStack = newSeq[MinValue](0) - var trace:MinStack = newSeq[MinValue](0) - var stackcopy:MinStack = newSeq[MinValue](0) - var pr:MinParser + var stack: MinStack = newSeq[MinValue](0) + var trace: MinStack = newSeq[MinValue](0) + var stackcopy: MinStack = newSeq[MinValue](0) + var pr: MinParser var scope = newScopeRef(nil) - var i:MinInterpreter = MinInterpreter( - filename: filename, + var i: MinInterpreter = MinInterpreter( + filename: filename, pwd: path, - parser: pr, + parser: pr, stack: stack, trace: trace, stackcopy: stackcopy,

@@ -109,7 +113,7 @@ if not filename.isAbsolute:

path = joinPath(getCurrentDir(), filename) result = newMinInterpreter() result.filename = filename - result.pwd = path.parentDirEx + result.pwd = path.parentDirEx result.stack = i.stack result.trace = i.trace result.stackcopy = i.stackcopy

@@ -140,21 +144,21 @@

proc error(i: In, message: string) = error(i.currSym.formatError(message)) -proc open*(i: In, stream:Stream, filename: string) = +proc open*(i: In, stream: Stream, filename: string) = i.filename = filename i.parser.open(stream, filename) -proc close*(i: In) = +proc close*(i: In) = i.parser.close(); -proc push*(i: In, val: MinValue) +proc push*(i: In, val: MinValue) proc call*(i: In, q: var MinValue): MinValue = var i2 = newMinInterpreter("<call>") i2.trace = i.trace i2.scope = i.scope try: - i2.withScope(): + i2.withScope(): for v in q.qVal: i2.push v except CatchableError:

@@ -168,7 +172,7 @@ var i2 = newMinInterpreter("<call-value>")

i2.trace = i.trace i2.scope = i.scope try: - i2.withScope(): + i2.withScope(): i2.push v except CatchableError: i.currSym = i2.currSym

@@ -177,15 +181,15 @@ raise

return i2.stack[0] proc copyDict*(i: In, val: MinValue): MinValue = - # Assuming val is a dictionary - var v = newDict(i.scope) - v.scope.symbols = val.scope.symbols - v.scope.sigils = val.scope.sigils - if val.objType != "": - v.objType = val.objType - if not val.obj.isNil: - v.obj = val.obj - return v + # Assuming val is a dictionary + var v = newDict(i.scope) + v.scope.symbols = val.scope.symbols + v.scope.sigils = val.scope.sigils + if val.objType != "": + v.objType = val.objType + if not val.obj.isNil: + v.obj = val.obj + return v proc apply*(i: In, op: MinOperator, sym = "") {.effectsOf: op.} = if op.kind == minProcOp:

@@ -203,7 +207,7 @@ i.push(op.val)

proc dequote*(i: In, q: var MinValue) = if q.kind == minQuotation: - i.withScope(): + i.withScope(): let qqval = deepCopy(q.qVal) for v in q.qVal: i.push v

@@ -216,7 +220,7 @@ var i2 = newMinInterpreter("<apply>")

i2.trace = i.trace i2.scope = i.scope try: - i2.withScope(): + i2.withScope(): for v in q.qVal: if (v.kind == minQuotation): var v2 = v

@@ -238,15 +242,15 @@

# Inherit file/line/column from current symbol proc pushSym*(i: In, s: string) = i.push MinValue( - kind: minSymbol, - symVal: s, - filename: i.currSym.filename, - line: i.currSym.line, - column: i.currSym.column, - outerSym: i.currSym.symVal, + kind: minSymbol, + symVal: s, + filename: i.currSym.filename, + line: i.currSym.line, + column: i.currSym.column, + outerSym: i.currSym.symVal, docComment: i.currSym.docComment) -proc push*(i: In, val: MinValue) = +proc push*(i: In, val: MinValue) = if val.kind == minSymbol: i.debug(val) if not i.evaluating:

@@ -260,25 +264,27 @@ if symbol == "return":

raise MinReturnException(msg: "return symbol found") if i.scope.hasSymbol(symbol): i.apply i.scope.getSymbol(symbol), symbol - else: + else: # Check if symbol ends with ! (auto-popping) if symbol.len > 1 and symbol[symbol.len-1] == '!': let apSymbol = symbol[0..symbol.len-2] if i.scope.hasSymbol(apSymbol): i.apply i.scope.getSymbol(apSymbol) - discard i.pop + discard i.pop else: var qIndex = symbol.find('"') if qIndex > 0: let sigil = symbol[0..qIndex-1] if not i.scope.hasSigil(sigil): raiseUndefined("Undefined sigil '$1'"%sigil) - i.stack.add(MinValue(kind: minString, strVal: symbol[qIndex+1..symbol.len-2])) + i.stack.add(MinValue(kind: minString, strVal: symbol[ + qIndex+1..symbol.len-2])) i.apply(i.scope.getSigil(sigil)) else: let sigil = "" & symbol[0] if symbol.len > 1 and i.scope.hasSigil(sigil): - i.stack.add(MinValue(kind: minString, strVal: symbol[1..symbol.len-1])) + i.stack.add(MinValue(kind: minString, strVal: symbol[ + 1..symbol.len-1])) i.apply(i.scope.getSigil(sigil)) else: raiseUndefined("Undefined symbol '$1'" % [val.symVal])

@@ -294,7 +300,7 @@ i.stack.add(v)

else: i.stack.add(val) -proc peek*(i: MinInterpreter): MinValue = +proc peek*(i: MinInterpreter): MinValue = if i.stack.len > 0: return i.stack[i.stack.len-1] else:

@@ -306,7 +312,8 @@ body

except MinRuntimeError: let msg = getCurrentExceptionMsg() i.stack = i.stackcopy - i.error("$1:$2,$3 $4" % [i.currSym.filename, $i.currSym.line, $i.currSym.column, msg]) + i.error("$1:$2,$3 $4" % [i.currSym.filename, $i.currSym.line, + $i.currSym.column, msg]) i.stackTrace() i.trace = @[] raise MinTrappedException(msg: msg)

@@ -320,12 +327,12 @@ i.stackTrace()

i.trace = @[] raise MinTrappedException(msg: msg) -proc interpret*(i: In, parseOnly=false): MinValue {.discardable.} = +proc interpret*(i: In, parseOnly = false): MinValue {.discardable.} = var val: MinValue var q: MinValue if parseOnly: q = newSeq[MinValue](0).newVal - while i.parser.token != tkEof: + while i.parser.token != tkEof: if i.trace.len == 0: i.stackcopy = i.stack handleErrors(i) do:

@@ -340,12 +347,12 @@ if i.stack.len > 0:

return i.stack[i.stack.len - 1] proc rawCompile*(i: In, indent = ""): seq[string] {.discardable.} = - while i.parser.token != tkEof: + while i.parser.token != tkEof: if i.trace.len == 0: i.stackcopy = i.stack handleErrors(i) do: result.add i.parser.compileMinValue(i, push = true, indent) - + proc compileFile*(i: In, main: bool): seq[string] {.discardable.} = result = newSeq[string](0) if not main:

@@ -372,17 +379,18 @@ let ef = file.readFile.encode

let asset = "COMPILEDASSETS[\"$#\"] = \"$#\".decode" % [file, ef] result.add asset -proc eval*(i: In, s: string, name="<eval>", parseOnly=false): MinValue {.discardable.}= +proc eval*(i: In, s: string, name = "<eval>", + parseOnly = false): MinValue {.discardable.} = var i2 = i.copy(name) i2.open(newStringStream(s), name) - discard i2.parser.getToken() + discard i2.parser.getToken() result = i2.interpret(parseOnly) i.trace = i2.trace i.stackcopy = i2.stackcopy i.stack = i2.stack i.scope = i2.scope -proc load*(i: In, s: string, parseOnly=false): MinValue {.discardable.}= +proc load*(i: In, s: string, parseOnly = false): MinValue {.discardable.} = var fileLines = newSeq[string](0) var contents = "" try:

@@ -395,14 +403,15 @@ else:

contents = fileLines.join("\n") var i2 = i.copy(s) i2.open(newStringStream(contents), s) - discard i2.parser.getToken() + discard i2.parser.getToken() result = i2.interpret(parseOnly) i.trace = i2.trace i.stackcopy = i2.stackcopy i.stack = i2.stack i.scope = i2.scope -proc require*(i: In, s: string, parseOnly=false): MinValue {.discardable, extern:"min_exported_symbol_$1".}= +proc require*(i: In, s: string, parseOnly = false): MinValue {.discardable, + extern: "min_exported_symbol_$1".} = if CACHEDMODULES.hasKey(s): return CACHEDMODULES[s] var fileLines = newSeq[string](0)

@@ -419,7 +428,7 @@ var i2 = i.copy(s)

let snapshot = deepCopy(i.stack) i2.withScope: i2.open(newStringStream(contents), s) - discard i2.parser.getToken() + discard i2.parser.getToken() discard i2.interpret(parseOnly) let d = snapshot.diff(i2.stack) if d.len > 0:

@@ -430,7 +439,7 @@ for key, value in i2.scope.symbols.pairs:

result.scope.symbols[key] = value CACHEDMODULES[s] = result -proc parse*(i: In, s: string, name="<parse>"): MinValue = +proc parse*(i: In, s: string, name = "<parse>"): MinValue = return i.eval(s, name, true) proc read*(i: In, s: string): MinValue =
M minpkg/core/meta.nimminpkg/core/meta.nim

@@ -1,5 +1,5 @@

-import - strutils +import + std/strutils const ymlconfig = "../../min.yml".slurp
M minpkg/core/niftylogger.nimminpkg/core/niftylogger.nim

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

-import - logging, +import + std/[logging, strutils, terminal, - std/exitprocs + exitprocs] if isatty(stdin): addExitProc(resetAttributes) -type +type NiftyLogger* = ref object of Logger proc logPrefix*(level: Level): tuple[msg: string, color: ForegroundColor] =

@@ -30,7 +30,7 @@

method log*(logger: NiftyLogger; level: Level; args: varargs[string, `$`]) = var f = stdout if level >= getLogFilter() and level >= logger.levelThreshold: - if level >= lvlWarn: + if level >= lvlWarn: f = stderr let ln = substituteLog(logger.fmtStr, level, args) let prefix = level.logPrefix()

@@ -70,4 +70,4 @@ else:

val = "warn" lvl = lvlWarn setLogFilter(lvl) - return val + return val
M minpkg/core/parser.nimminpkg/core/parser.nim

@@ -1,14 +1,16 @@

# Adapted from: https://github.com/Araq/Nimrod/blob/v0.9.6/lib/pure/json.nim -import - lexbase, - strutils, +import + std/[lexbase, + strutils, sequtils, - streams, + streams, critbits, - json, + json] + +import baseutils -import unicode except strip +import std/unicode except strip type MinTokenKind* = enum

@@ -38,32 +40,32 @@ minString,

minSymbol, minNull, minBool - MinEventKind* = enum ## enumeration of all events that may occur when parsing - eMinError, ## an error ocurred during parsing - eMinEof, ## end of file reached - eMinString, ## a string literal - eMinInt, ## an integer literal - eMinFloat, ## a float literal - eMinQuotationStart, ## start of an array: the ``(`` token - eMinQuotationEnd, ## start of an array: the ``)`` token - eMinDictionaryStart, ## start of a dictionary: the ``{`` token - eMinDictionaryEnd ## start of a dictionary: the ``}`` token - MinParserError* = enum ## enumeration that lists all errors that can occur - errNone, ## no error - errInvalidToken, ## invalid token - errStringExpected, ## string expected - errBracketRiExpected, ## ``)`` expected - errBraceRiExpected, ## ``}`` expected - errQuoteExpected, ## ``"`` or ``'`` expected - errSqBracketRiExpected,## ``]`` expected - errEOC_Expected, ## ``*/`` expected - errEofExpected, ## EOF expected + MinEventKind* = enum ## enumeration of all events that may occur when parsing + eMinError, ## an error ocurred during parsing + eMinEof, ## end of file reached + eMinString, ## a string literal + eMinInt, ## an integer literal + eMinFloat, ## a float literal + eMinQuotationStart, ## start of an array: the ``(`` token + eMinQuotationEnd, ## start of an array: the ``)`` token + eMinDictionaryStart, ## start of a dictionary: the ``{`` token + eMinDictionaryEnd ## start of a dictionary: the ``}`` token + MinParserError* = enum ## enumeration that lists all errors that can occur + errNone, ## no error + errInvalidToken, ## invalid token + errStringExpected, ## string expected + errBracketRiExpected, ## ``)`` expected + errBraceRiExpected, ## ``}`` expected + errQuoteExpected, ## ``"`` or ``'`` expected + errSqBracketRiExpected, ## ``]`` expected + errEOC_Expected, ## ``*/`` expected + errEofExpected, ## EOF expected errExprExpected - MinParserState* = enum - stateEof, - stateStart, - stateQuotation, - stateDictionary, + MinParserState* = enum + stateEof, + stateStart, + stateQuotation, + stateDictionary, stateExpectValue MinParser* = object of BaseLexer a*: string

@@ -74,7 +76,7 @@ state*: seq[MinParserState]

kind*: MinEventKind err*: MinParserError filename*: string - MinValue* = ref MinValueObject + MinValue* = ref MinValueObject MinValueObject* {.acyclic, final.} = object line*: int column*: int

@@ -87,9 +89,9 @@ of minInt: intVal*: BiggestInt

of minFloat: floatVal*: BiggestFloat of minCommand: cmdVal*: string of minDictionary: - scope*: ref MinScope - obj*: pointer - objType*: string + scope*: ref MinScope + obj*: pointer + objType*: string of minQuotation: qVal*: seq[MinValue] of minString: strVal*: string

@@ -103,7 +105,7 @@ parent*: ref MinScope

symbols*: CritBitTree[MinOperator] sigils*: CritBitTree[MinOperator] kind*: MinScopeKind - MinOperatorProc* = proc (i: In) {.closure.} + MinOperatorProc* = proc (i: In) {.closure.} MinOperatorKind* = enum minProcOp minValOp

@@ -127,13 +129,13 @@ scope*: ref MinScope

parser*: MinParser currSym*: MinValue filename*: string - evaluating*: bool - MinParsingError* = ref object of ValueError + evaluating*: bool + MinParsingError* = ref object of ValueError MinUndefinedError* = ref object of ValueError MinEmptyStackError* = ref object of ValueError MinInvalidError* = ref object of ValueError MinOutOfBoundsError* = ref object of ValueError - + var CVARCOUNT = 0 # Helpers

@@ -150,7 +152,8 @@

proc raiseEmptyStack*() = raise MinEmptyStackError(msg: "Insufficient items on the stack") -proc dVal*(v: MinValue): CritBitTree[MinOperator] {.inline, extern:"min_exported_symbol_$1".}= +proc dVal*(v: MinValue): CritBitTree[MinOperator] {.inline, + extern: "min_exported_symbol_$1".} = if v.kind != minDictionary: raiseInvalid("dVal - Dictionary expected, got " & $v.kind) if v.scope.isNil:

@@ -177,7 +180,7 @@ "string literal",

"command literal", "int literal", "float literal", - "(", + "(", ")", "[", "]",

@@ -203,54 +206,60 @@ my.state = @[stateStart]

my.kind = eMinError my.a = "" -proc close*(my: var MinParser) {.inline, extern:"min_exported_symbol_$1".}= +proc close*(my: var MinParser) {.inline, extern: "min_exported_symbol_$1".} = lexbase.close(my) -proc getInt*(my: MinParser): int {.inline, extern:"min_exported_symbol_$1".}= +proc getInt*(my: MinParser): int {.inline, extern: "min_exported_symbol_$1".} = assert(my.kind == eMinInt) return parseint(my.a) -proc getFloat*(my: MinParser): float {.inline, extern:"min_exported_symbol_$1".}= +proc getFloat*(my: MinParser): float {.inline, + extern: "min_exported_symbol_$1".} = assert(my.kind == eMinFloat) return parseFloat(my.a) -proc kind*(my: MinParser): MinEventKind {.inline, extern:"min_exported_symbol_$1".}= +proc kind*(my: MinParser): MinEventKind {.inline, + extern: "min_exported_symbol_$1".} = return my.kind -proc getColumn*(my: MinParser): int {.inline, extern:"min_exported_symbol_$1".}= +proc getColumn*(my: MinParser): int {.inline, + extern: "min_exported_symbol_$1".} = result = getColNumber(my, my.bufpos) -proc getLine*(my: MinParser): int {.inline, extern:"min_exported_symbol_$1".}= +proc getLine*(my: MinParser): int {.inline, extern: "min_exported_symbol_$1".} = result = my.lineNumber -proc getFilename*(my: MinParser): string {.inline, extern:"min_exported_symbol_$1".}= +proc getFilename*(my: MinParser): string {.inline, + extern: "min_exported_symbol_$1".} = result = my.filename - -proc errorMsg*(my: MinParser, msg: string): string = + +proc errorMsg*(my: MinParser, msg: string): string = assert(my.kind == eMinError) result = "$1 [l:$2, c:$3] ERROR - $4" % [ my.filename, $getLine(my), $getColumn(my), msg] -proc errorMsg*(my: MinParser): string = +proc errorMsg*(my: MinParser): string = assert(my.kind == eMinError) result = errorMsg(my, errorMessages[my.err]) - -proc errorMsgExpected*(my: MinParser, e: string): string = + +proc errorMsgExpected*(my: MinParser, e: string): string = result = errorMsg(my, e & " expected") -proc raiseParsing*(p: MinParser, msg: string) {.noinline, noreturn, extern:"min_exported_symbol_$1".}= +proc raiseParsing*(p: MinParser, msg: string) {.noinline, noreturn, + extern: "min_exported_symbol_$1".} = raise MinParsingError(msg: errorMsgExpected(p, msg)) -proc raiseUndefined*(p:MinParser, msg: string) {.noinline, noreturn, extern:"min_exported_symbol_$1_2".}= +proc raiseUndefined*(p: MinParser, msg: string) {.noinline, noreturn, + extern: "min_exported_symbol_$1_2".} = raise MinUndefinedError(msg: errorMsg(p, msg)) -proc parseNumber(my: var MinParser) = +proc parseNumber(my: var MinParser) = var pos = my.bufpos var buf = my.buf - if buf[pos] == '-': + if buf[pos] == '-': add(my.a, '-') inc(pos) - if buf[pos] == '.': + if buf[pos] == '.': add(my.a, "0.") inc(pos) else:

@@ -275,7 +284,7 @@ add(my.a, buf[pos])

inc(pos) my.bufpos = pos -proc handleHexChar(c: char, x: var int): bool = +proc handleHexChar(c: char, x: var int): bool = result = true # Success case c of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))

@@ -288,8 +297,8 @@ result = tkString

var pos = my.bufpos + 1 var buf = my.buf while true: - case buf[pos] - of '\0': + case buf[pos] + of '\0': my.err = errQuoteExpected result = tkError break

@@ -298,21 +307,21 @@ inc(pos)

break of '\\': case buf[pos+1] - of '\\', '"', '\'', '/': + of '\\', '"', '\'', '/': add(my.a, buf[pos+1]) inc(pos, 2) of 'b': add(my.a, '\b') - inc(pos, 2) + inc(pos, 2) of 'f': add(my.a, '\f') - inc(pos, 2) + inc(pos, 2) of 'n': add(my.a, '\L') - inc(pos, 2) + inc(pos, 2) of 'r': add(my.a, '\C') - inc(pos, 2) + inc(pos, 2) of 't': add(my.a, '\t') inc(pos, 2)

@@ -324,15 +333,15 @@ if handleHexChar(buf[pos], r): inc(pos)

if handleHexChar(buf[pos], r): inc(pos) if handleHexChar(buf[pos], r): inc(pos) add(my.a, toUTF8(Rune(r))) - else: + else: # don't bother with the error add(my.a, buf[pos]) inc(pos) - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf add(my.a, '\c') - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf add(my.a, '\L')

@@ -346,8 +355,8 @@ result = tkCommand

var pos = my.bufpos + 1 var buf = my.buf while true: - case buf[pos] - of '\0': + case buf[pos] + of '\0': my.err = errSqBracketRiExpected result = tkError break

@@ -356,21 +365,21 @@ inc(pos)

break of '\\': case buf[pos+1] - of '\\', '"', '\'', '/': + of '\\', '"', '\'', '/': add(my.a, buf[pos+1]) inc(pos, 2) of 'b': add(my.a, '\b') - inc(pos, 2) + inc(pos, 2) of 'f': add(my.a, '\f') - inc(pos, 2) + inc(pos, 2) of 'n': add(my.a, '\L') - inc(pos, 2) + inc(pos, 2) of 'r': add(my.a, '\C') - inc(pos, 2) + inc(pos, 2) of 't': add(my.a, '\t') inc(pos, 2)

@@ -382,15 +391,15 @@ if handleHexChar(buf[pos], r): inc(pos)

if handleHexChar(buf[pos], r): inc(pos) if handleHexChar(buf[pos], r): inc(pos) add(my.a, toUTF8(Rune(r))) - else: + else: # don't bother with the error add(my.a, buf[pos]) inc(pos) - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf add(my.a, '\c') - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf add(my.a, '\L')

@@ -399,55 +408,57 @@ add(my.a, buf[pos])

inc(pos) my.bufpos = pos # store back -proc parseSymbol(my: var MinParser): MinTokenKind = +proc parseSymbol(my: var MinParser): MinTokenKind = result = tkSymbol var pos = my.bufpos var buf = my.buf if not(buf[pos] in Whitespace): - while not(buf[pos] in WhiteSpace) and not(buf[pos] in ['\0', ')', '(', '}', '{', '[', ']']): - if buf[pos] == '"': - add(my.a, buf[pos]) - my.bufpos = pos - let r = parseString(my) - if r == tkError: - result = tkError - return - add(my.a, buf[pos]) + while not(buf[pos] in WhiteSpace) and not(buf[pos] in ['\0', ')', '(', '}', + '{', '[', ']']): + if buf[pos] == '"': + add(my.a, buf[pos]) + my.bufpos = pos + let r = parseString(my) + if r == tkError: + result = tkError return - else: - add(my.a, buf[pos]) - inc(pos) + add(my.a, buf[pos]) + return + else: + add(my.a, buf[pos]) + inc(pos) my.bufpos = pos proc addDoc(my: var MinParser, docComment: string, reset = true) = if my.doc and not my.currSym.isNil and my.currSym.kind == minSymbol: if reset: my.doc = false - if my.currSym.docComment.len == 0 or my.currSym.docComment.len > 0 and my.currSym.docComment[my.currSym.docComment.len-1] == '\n': + if my.currSym.docComment.len == 0 or my.currSym.docComment.len > 0 and + my.currSym.docComment[my.currSym.docComment.len-1] == '\n': my.currSym.docComment &= docComment.strip(true, false) else: my.currSym.docComment &= docComment -proc skip(my: var MinParser) = +proc skip(my: var MinParser) = var pos = my.bufpos var buf = my.buf - while true: + while true: case buf[pos] of ';': # skip line comment: - if buf[pos+1] == ';': - my.doc = true + if buf[pos+1] == ';': + my.doc = true inc(pos, 2) while true: - case buf[pos] - of '\0': + case buf[pos] + of '\0': break - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf my.addDoc "\n" break - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf my.addDoc "\n"

@@ -455,7 +466,7 @@ break

else: my.addDoc $my.buf[pos], false inc(pos) - of '#': + of '#': if buf[pos+1] == '|': # skip long comment: if buf[pos+2] == '|':

@@ -463,15 +474,15 @@ inc(pos)

my.doc = true inc(pos, 2) while true: - case buf[pos] - of '\0': + case buf[pos] + of '\0': my.err = errEOC_Expected break - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) my.addDoc "\n", false buf = my.buf - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) my.addDoc "\n", false buf = my.buf

@@ -479,21 +490,21 @@ of '|':

inc(pos) if buf[pos] == '|': inc(pos) - if buf[pos] == '#': + if buf[pos] == '#': inc(pos) break my.addDoc $buf[pos], false else: my.addDoc $my.buf[pos], false inc(pos) - else: + else: break - of ' ', '\t': + of ' ', '\t': inc(pos) - of '\c': + of '\c': pos = lexbase.handleCR(my, pos) buf = my.buf - of '\L': + of '\L': pos = lexbase.handleLF(my, pos) buf = my.buf else:

@@ -502,7 +513,7 @@ my.bufpos = pos

proc getToken*(my: var MinParser): MinTokenKind = setLen(my.a, 0) - skip(my) + skip(my) case my.buf[my.bufpos] of '-', '.': if my.bufpos+1 <= my.buf.len and my.buf[my.bufpos+1] in '0'..'9':

@@ -513,7 +524,7 @@ else:

result = tkInt else: result = parseSymbol(my) - of '0'..'9': + of '0'..'9': parseNumber(my) if {'.', 'e', 'E'} in my.a: result = tkFloat

@@ -539,16 +550,16 @@ of '\0':

result = tkEof else: result = parseSymbol(my) - case my.a + case my.a of "null": result = tkNull of "true": result = tkTrue of "false": result = tkFalse - else: + else: discard my.token = result -proc next*(my: var MinParser) = +proc next*(my: var MinParser) = var tk = getToken(my) var i = my.state.len-1 case my.state[i]

@@ -558,15 +569,15 @@ my.kind = eMinEof

else: my.kind = eMinError my.err = errEofExpected - of stateStart: + of stateStart: case tk of tkString, tkInt, tkFloat, tkTrue, tkFalse: my.state[i] = stateEof # expect EOF next! my.kind = MinEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state.add(stateQuotation) # we expect any my.kind = eMinQuotationStart - of tkBraceLe: + of tkBraceLe: my.state.add(stateDictionary) # we expect any my.kind = eMinDictionaryStart of tkEof:

@@ -578,10 +589,10 @@ of stateQuotation:

case tk of tkString, tkInt, tkFloat, tkTrue, tkFalse: my.kind = MinEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state.add(stateQuotation) my.kind = eMinQuotationStart - of tkBraceLe: + of tkBraceLe: my.state.add(stateDictionary) my.kind = eMinDictionaryStart of tkBracketRi:

@@ -597,10 +608,10 @@ of stateDictionary:

case tk of tkString, tkInt, tkFloat, tkTrue, tkFalse: my.kind = MinEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state.add(stateQuotation) my.kind = eMinQuotationStart - of tkBraceLe: + of tkBraceLe: my.state.add(stateDictionary) my.kind = eMinDictionaryStart of tkBracketRi:

@@ -616,21 +627,21 @@ of stateExpectValue:

case tk of tkString, tkInt, tkFloat, tkTrue, tkFalse: my.kind = MinEventKind(ord(tk)) - of tkBracketLe: + of tkBracketLe: my.state.add(stateQuotation) my.kind = eMinQuotationStart - of tkBraceLe: + of tkBraceLe: my.state.add(stateDictionary) my.kind = eMinDictionaryStart else: my.kind = eMinError my.err = errExprExpected -proc eat(p: var MinParser, token: MinTokenKind) = +proc eat(p: var MinParser, token: MinTokenKind) = if p.token == token: discard getToken(p) else: raiseParsing(p, tokToStr[token]) -proc `$`*(a: MinValue): string {.inline, extern:"min_exported_symbol_$1".}= +proc `$`*(a: MinValue): string {.inline, extern: "min_exported_symbol_$1".} = case a.kind: of minNull: return "null"

@@ -662,14 +673,14 @@ var k = $i.key

if k.contains(" "): k = "\"$1\"" % k d = d & v & " :" & k & " " - if a.objType != "": + if a.objType != "": d = d & ";" & a.objType d = d.strip & "}" return d of minCommand: return "[" & a.cmdVal & "]" -proc `$$`*(a: MinValue): string {.inline, extern:"min_exported_symbol_$1".}= +proc `$$`*(a: MinValue): string {.inline, extern: "min_exported_symbol_$1".} = case a.kind: of minNull: return "null"

@@ -703,7 +714,7 @@ var k = $i.key

if k.contains(" "): k = "\"$1\"" % k d = d & v & " :" & k & " " - if a.objType != "": + if a.objType != "": d = d & ";" & a.objType d = d.strip & "}" return d

@@ -736,7 +747,7 @@ discard getToken(p)

of tkBracketLe: var q = newSeq[MinValue](0) discard getToken(p) - while p.token != tkBracketRi: + while p.token != tkBracketRi: q.add p.parseMinValue(i) eat(p, tkBracketRi) result = MinValue(kind: minQuotation, qVal: q)

@@ -745,7 +756,7 @@ var scope = newScopeRef(nil)

var val: MinValue discard getToken(p) var c = 0 - while p.token != tkBraceRi: + while p.token != tkBraceRi: c = c+1 let v = p.parseMinValue(i) if val.isNil:

@@ -756,7 +767,8 @@ if key[0] == ':':

var offset = 0 if key[1] == '"': offset = 1 - scope.symbols[key[1+offset .. key.len-1-offset]] = MinOperator(kind: minValOp, val: val, sealed: false) + scope.symbols[key[1+offset .. key.len-1-offset]] = MinOperator( + kind: minValOp, val: val, sealed: false) val = nil else: raiseInvalid("Invalid dictionary key: " & key)

@@ -767,15 +779,16 @@ if c mod 2 != 0:

raiseInvalid("Invalid dictionary") result = MinValue(kind: minDictionary, scope: scope) of tkSymbol: - result = MinValue(kind: minSymbol, symVal: p.a, column: p.getColumn, line: p.lineNumber, filename: p.filename) + result = MinValue(kind: minSymbol, symVal: p.a, column: p.getColumn, + line: p.lineNumber, filename: p.filename) p.a = "" p.currSym = result discard getToken(p) else: - let err = "Undefined or invalid value: "&p.a - raiseUndefined(p, err) + let err = "Undefined or invalid value: "&p.a + raiseUndefined(p, err) result.filename = p.filename - + proc compileMinValue*(p: var MinParser, i: In, push = true, indent = ""): seq[string] = var op = indent if push:

@@ -806,13 +819,13 @@ CVARCOUNT.inc

var qvar = "q" & $CVARCOUNT result.add indent&"var "&qvar&" = newSeq[MinValue](0)" discard getToken(p) - while p.token != tkBracketRi: + while p.token != tkBracketRi: var instructions = p.compileMinValue(i, false, indent) let v = instructions.pop result = result.concat(instructions) result.add indent&qvar&".add "&v eat(p, tkBracketRi) - result.add op&"MinValue(kind: minQuotation, qVal: "&qvar&")" + result.add op&"MinValue(kind: minQuotation, qVal: "&qvar&")" of tkSqBracketLe, tkSqBracketRi: discard getToken(p) of tkCommand:

@@ -828,7 +841,7 @@ CVARCOUNT.inc

var scopevar = "scope" & $CVARCOUNT CVARCOUNT.inc var valvar = "val" & $CVARCOUNT - while p.token != tkBraceRi: + while p.token != tkBraceRi: c = c+1 var instructions = p.compileMinValue(i, false, indent) let v = p.parseMinValue(i)

@@ -842,7 +855,8 @@ result.add indent&valvar&" = "&vs

elif v.kind == minSymbol: let key = v.symVal if key[0] == ':': - result.add indent&scopevar&".symbols["&key[1 .. key.len-1]&"] = MinOperator(kind: minValOp, val: "&valvar&", sealed: false)" + result.add indent&scopevar&".symbols["&key[1 .. + key.len-1]&"] = MinOperator(kind: minValOp, val: "&valvar&", sealed: false)" val = nil else: raiseInvalid("Invalid dictionary key: " & key)

@@ -872,13 +886,13 @@

proc isSymbol*(s: MinValue): bool = return s.kind == minSymbol -proc isQuotation*(s: MinValue): bool = +proc isQuotation*(s: MinValue): bool = return s.kind == minQuotation -proc isCommand*(s: MinValue): bool = +proc isCommand*(s: MinValue): bool = return s.kind == minCommand -proc isString*(s: MinValue): bool = +proc isString*(s: MinValue): bool = return s.kind == minString proc isFloat*(s: MinValue): bool =

@@ -894,7 +908,8 @@ proc isBool*(s: MinValue): bool =

return s.kind == minBool proc isStringLike*(s: MinValue): bool = - return s.isSymbol or s.isString or (s.isQuotation and s.qVal.len == 1 and s.qVal[0].isSymbol) + return s.isSymbol or s.isString or (s.isQuotation and s.qVal.len == 1 and + s.qVal[0].isSymbol) proc isDictionary*(q: MinValue): bool = return q.kind == minDictionary

@@ -909,7 +924,8 @@ if q.isTypedDictionary:

return q.objType == t return false -proc `==`*(a: MinValue, b: MinValue): bool {.inline, extern:"min_exported_symbol_eqeq".}= +proc `==`*(a: MinValue, b: MinValue): bool {.inline, + extern: "min_exported_symbol_eqeq".} = if not (a.kind == b.kind or (a.isNumber and b.isNumber)): return false if a.kind == minSymbol and b.kind == minSymbol:
M minpkg/core/scope.nimminpkg/core/scope.nim

@@ -1,6 +1,6 @@

import - strutils, - critbits + std/[strutils, + critbits] import parser

@@ -10,8 +10,8 @@ scope.symbols = s.symbols

scope.sigils = s.sigils new(result) result[] = scope - -proc getSymbol*(scope: ref MinScope, key: string, acc=0): MinOperator = + +proc getSymbol*(scope: ref MinScope, key: string, acc = 0): MinOperator = if scope.symbols.hasKey(key): return scope.symbols[key] else:

@@ -29,20 +29,21 @@ return scope.parent.hasSymbol(key)

else: return false -proc delSymbol*(scope: ref MinScope, key: string): bool {.discardable.}= +proc delSymbol*(scope: ref MinScope, key: string): bool {.discardable.} = if scope.symbols.hasKey(key): if scope.symbols[key].sealed: - raiseInvalid("Symbol '$1' is sealed." % key) + raiseInvalid("Symbol '$1' is sealed." % key) scope.symbols.excl(key) return true return false -proc setSymbol*(scope: ref MinScope, key: string, value: MinOperator, override = false): bool {.discardable.}= +proc setSymbol*(scope: ref MinScope, key: string, value: MinOperator, + override = false): bool {.discardable.} = result = false # check if a symbol already exists in current scope if not scope.isNil and scope.symbols.hasKey(key): if not override and scope.symbols[key].sealed: - raiseInvalid("Symbol '$1' is sealed ." % key) + raiseInvalid("Symbol '$1' is sealed ." % key) scope.symbols[key] = value result = true else:

@@ -68,20 +69,21 @@ return scope.parent.hasSigil(key)

else: return false -proc delSigil*(scope: ref MinScope, key: string): bool {.discardable.}= +proc delSigil*(scope: ref MinScope, key: string): bool {.discardable.} = if scope.sigils.hasKey(key): if scope.sigils[key].sealed: - raiseInvalid("Sigil '$1' is sealed." % key) + raiseInvalid("Sigil '$1' is sealed." % key) scope.sigils.excl(key) return true return false -proc setSigil*(scope: ref MinScope, key: string, value: MinOperator, override = false): bool {.discardable.}= +proc setSigil*(scope: ref MinScope, key: string, value: MinOperator, + override = false): bool {.discardable.} = result = false # check if a sigil already exists in current scope if not scope.isNil and scope.sigils.hasKey(key): if not override and scope.sigils[key].sealed: - raiseInvalid("Sigil '$1' is sealed." % key) + raiseInvalid("Sigil '$1' is sealed." % key) scope.sigils[key] = value result = true else:

@@ -91,6 +93,6 @@ result = scope.parent.setSymbol(key, value)

proc previous*(scope: ref MinScope): ref MinScope = if scope.parent.isNil: - return scope + return scope else: return scope.parent
M minpkg/core/utils.nimminpkg/core/utils.nim

@@ -1,15 +1,15 @@

-import - strutils, - critbits -import +import + std/[strutils, + critbits] +import baseutils, - parser, + parser, value, json, scope, env, interpreter - + # Library methods proc define*(i: In): ref MinScope =

@@ -17,13 +17,15 @@ var scope = newScopeRef(i.scope, minNativeScope)

scope.parent = i.scope return scope -proc symbol*(scope: ref MinScope, sym: string, p: MinOperatorProc) {.effectsOf: p.} = +proc symbol*(scope: ref MinScope, sym: string, + p: MinOperatorProc) {.effectsOf: p.} = scope.symbols[sym] = MinOperator(prc: p, kind: minProcOp, sealed: true) proc symbol*(scope: ref MinScope, sym: string, v: MinValue) = scope.symbols[sym] = MinOperator(val: v, kind: minValOp, sealed: true) -proc sigil*(scope: ref MinScope, sym: string, p: MinOperatorProc) {.effectsOf: p.} = +proc sigil*(scope: ref MinScope, sym: string, + p: MinOperatorProc) {.effectsOf: p.} = scope.sigils[sym] = MinOperator(prc: p, kind: minProcOp, sealed: true) proc sigil*(scope: ref MinScope, sym: string, v: MinValue) =

@@ -39,14 +41,15 @@ i.push mdl

i.evaluating = false if name != "": scope.previous.symbols[name] = MinOperator(kind: minProcOp, prc: op) - + # Dictionary Methods proc dget*(i: In, q: MinValue, s: MinValue): MinValue = if not q.isDictionary: raiseInvalid("Value is not a dictionary") if q.dVal[s.getString].kind == minProcOp: - raiseInvalid("Key '$1' is set to an operator and it cannot be retrieved." % [s.getString]) + raiseInvalid("Key '$1' is set to an operator and it cannot be retrieved." % + [s.getString]) result = q.dVal[s.getString].val proc dget*(i: In, q: MinValue, s: string): MinValue =

@@ -66,26 +69,30 @@ if not q.isDictionary:

raiseInvalid("Value is not a dictionary") return q.dVal.contains(s) -proc ddel*(i: In, p: var MinValue, s: MinValue): MinValue {.discardable, extern:"min_exported_symbol_$1".} = +proc ddel*(i: In, p: var MinValue, s: MinValue): MinValue {.discardable, + extern: "min_exported_symbol_$1".} = if not p.isDictionary: raiseInvalid("Value is not a dictionary") excl(p.scope.symbols, s.getString) return p - -proc ddel*(i: In, p: var MinValue, s: string): MinValue {.discardable, extern:"min_exported_symbol_$1_2".} = + +proc ddel*(i: In, p: var MinValue, s: string): MinValue {.discardable, + extern: "min_exported_symbol_$1_2".} = if not p.isDictionary: raiseInvalid("Value is not a dictionary") excl(p.scope.symbols, s) return p - -proc dset*(i: In, p: var MinValue, s: MinValue, m: MinValue): MinValue {.discardable, extern:"min_exported_symbol_$1".}= + +proc dset*(i: In, p: var MinValue, s: MinValue, + m: MinValue): MinValue {.discardable, extern: "min_exported_symbol_$1".} = if not p.isDictionary: raiseInvalid("Value is not a dictionary") var q = m p.scope.symbols[s.getString] = MinOperator(kind: minValOp, val: q, sealed: false) return p -proc dset*(i: In, p: var MinValue, s: string, m: MinValue): MinValue {.discardable, extern:"min_exported_symbol_$1_2".}= +proc dset*(i: In, p: var MinValue, s: string, + m: MinValue): MinValue {.discardable, extern: "min_exported_symbol_$1_2".} = if not p.isDictionary: raiseInvalid("Value is not a dictionary") var q = m

@@ -107,7 +114,7 @@ if item.kind == minProcOp:

raiseInvalid("Dictionary contains operators that cannot be accessed.") r.add item.val return r.newVal - + proc pairs*(i: In, q: MinValue): MinValue = # Assumes q is a dictionary var r = newSeq[MinValue](0)

@@ -142,14 +149,14 @@ for it in a.qVal:

result.add(i%it) of minDictionary: result = newJObject() - for it in a.dVal.pairs: + for it in a.dVal.pairs: result[it.key] = i%i.dget(a, it.key) -proc fromJson*(i: In, json: JsonNode): MinValue = +proc fromJson*(i: In, json: JsonNode): MinValue = case json.kind: of JNull: result = newNull() - of JBool: + of JBool: result = json.getBool.newVal of JInt: result = json.getBiggestInt.newVal

@@ -176,9 +183,10 @@ return res.newVal

# Validators -proc validate*(i: In, value: MinValue, t: string, generics: var CritBitTree[string]): bool +proc validate*(i: In, value: MinValue, t: string, generics: var CritBitTree[string]): bool -proc validateValueType*(i: var MinInterpreter, element: string, value: MinValue, generics: var CritBitTree[string], vTypes: var seq[string], c: int): bool = +proc validateValueType*(i: var MinInterpreter, element: string, value: MinValue, + generics: var CritBitTree[string], vTypes: var seq[string], c: int): bool = vTypes.add value.typeName let ors = element.split("|") for to in ors:

@@ -200,10 +208,11 @@ else:

vTypes[c] = value.typeName break if andr: - result = true + result = true break -proc validateValueType*(i: var MinInterpreter, element: string, value: MinValue): bool = +proc validateValueType*(i: var MinInterpreter, element: string, + value: MinValue): bool = var g: CritBitTree[string] var s = newSeq[string](0) var c = 0

@@ -240,7 +249,7 @@ let tc = "typeclass:$#" % t

let ta = "typealias:$#" % t if t.contains(":"): var split = t.split(":") - # Typed dictionaries + # Typed dictionaries if split[0] == "dict": if value.isTypedDictionary(split[1]): return true

@@ -257,12 +266,14 @@ i2.push value

i2.pushSym("typeclass:$#" % t) let res = i2.pop if not res.isBool: - raiseInvalid("Type class '$#' does not evaluate to a boolean value ($# was returned instead)" % [t, $res]) + raiseInvalid("Type class '$#' does not evaluate to a boolean value ($# was returned instead)" % + [t, $res]) return res.boolVal else: raiseInvalid("Unknown type '$#'" % t) -proc validate*(i: In, value: MinValue, t: string, generics: var CritBitTree[string]): bool = +proc validate*(i: In, value: MinValue, t: string, generics: var CritBitTree[ + string]): bool = if generics.hasKey(t): let ts = generics[t].split("|") for tp in ts:

@@ -271,12 +282,13 @@ generics[t] = tp # lock type for future uses within same signature

return true return false return i.basicValidate(value, t) - + proc validate*(i: In, value: MinValue, t: string): bool = return i.basicValidate(value, t) - + proc validType*(i: In, s: string): bool = - const ts = ["bool", "null", "int", "num", "flt", "quot", "dict", "'sym", "sym", "str", "a"] + const ts = ["bool", "null", "int", "num", "flt", "quot", "dict", "'sym", + "sym", "str", "a"] if ts.contains(s): return true if i.scope.hasSymbol("typeclass:$#" % s):

@@ -288,16 +300,18 @@ if to.len < 2:

return false if to[0] == '!': tt = to[1..to.len-1] - if not ts.contains(tt) and not tt.startsWith("dict:") and not i.scope.hasSymbol("typeclass:$#" % tt): + if not ts.contains(tt) and not tt.startsWith("dict:") and + not i.scope.hasSymbol("typeclass:$#" % tt): let ta = "typealias:$#" % tt if i.scope.hasSymbol(ta): return i.validType(i.scope.getSymbol(ta).val.getString) return false return true - + # The following is used in operator signatures -proc expect*(i: var MinInterpreter, elements: varargs[string], generics: var CritBitTree[string]): seq[MinValue] = +proc expect*(i: var MinInterpreter, elements: varargs[string], + generics: var CritBitTree[string]): seq[MinValue] = if not DEV: # Ignore validation, just return elements result = newSeq[MinValue](0)

@@ -307,7 +321,8 @@ return result

let sym = i.currSym.getString var valid = newSeq[string](0) result = newSeq[MinValue](0) - let message = proc(invalid: string, elements: varargs[string], generics: CritBitTree[string]): string = + let message = proc(invalid: string, elements: varargs[string], + generics: CritBitTree[string]): string = var pelements = newSeq[string](0) for e in elements.reverse: if generics.hasKey(e):

@@ -340,7 +355,7 @@ # The following is used in expect symbol and native symbol expectations.

proc expect*(i: var MinInterpreter, elements: varargs[string]): seq[MinValue] = var c: CritBitTree[string] return i.expect(elements, c) - + proc reqQuotationOfQuotations*(i: var MinInterpreter, a: var MinValue) = a = i.pop if not a.isQuotation:

@@ -356,7 +371,7 @@ raiseInvalid("A quotation is required on the stack")

for s in a.qVal: if not s.isNumber: raiseInvalid("A quotation of numbers is required on the stack") - + proc reqQuotationOfIntegers*(i: var MinInterpreter, a: var MinValue) = a = i.pop if not a.isQuotation:
M minpkg/core/value.nimminpkg/core/value.nim

@@ -1,6 +1,6 @@

import parser, - hashes + std/hashes proc typeName*(v: MinValue): string = case v.kind:

@@ -8,12 +8,12 @@ of minInt:

return "int" of minFloat: return "flt" - of minCommand: + of minCommand: return "cmd" - of minDictionary: + of minDictionary: if v.isTypedDictionary: return "dict:" & v.objType - else: + else: return "dict" of minQuotation: return "quot"
M minpkg/lib/min_crypto.nimminpkg/lib/min_crypto.nim

@@ -1,19 +1,20 @@

import - base64, + std/[base64, strutils, - std/macros, - times, + macros, + times] +import ../vendor/aes/aes import - ../core/parser, - ../core/value, - ../core/interpreter, + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils {.compile: "../vendor/aes/libaes.c".} when defined(ssl): - import + import openssl proc MD4(d: cstring, n: culong, md: cstring = nil): cstring {.cdecl, importc.}

@@ -21,18 +22,18 @@ proc EVP_MD_CTX_new*(): EVP_MD_CTX {.cdecl, importc: "EVP_MD_CTX_new".}

proc EVP_MD_CTX_free*(ctx: EVP_MD_CTX) {.cdecl, importc: "EVP_MD_CTX_free".} else: import - std/sha1, - md5 + checksums/sha1, + checksums/md5 -proc crypto_module*(i: In)= +proc crypto_module*(i: In) = let def = i.define() - + def.symbol("encode") do (i: In): let vals = i.expect("'sym") let s = vals[0] i.push s.getString.encode.newVal - + def.symbol("decode") do (i: In): let vals = i.expect("'sym") let s = vals[0]

@@ -40,7 +41,7 @@ i.push s.getString.decode.newVal

when defined(ssl): - when defined(windows) and defined(amd64): + when defined(windows) and defined(amd64): {.passL: "-static -L"&getProjectPath()&"/minpkg/vendor/openssl/windows -lssl -lcrypto -lbcrypt".} elif defined(linux) and defined(amd64): {.passL: "-static -L"&getProjectPath()&"/minpkg/vendor/openssl/linux -lssl -lcrypto".}

@@ -106,7 +107,8 @@ var text = s.getString

var key = hash(k.getString, EVP_sha1(), 40) var iv = hash((key & $getTime().toUnix), EVP_sha1(), 40) var ctx = cast[ptr AES_ctx](alloc0(sizeof(AES_ctx))) - AES_init_ctx_iv(ctx, cast[ptr uint8](key[0].addr), cast[ptr uint8](iv[0].addr)); + AES_init_ctx_iv(ctx, cast[ptr uint8](key[0].addr), cast[ptr uint8](iv[ + 0].addr)); var input = cast[ptr uint8](text[0].addr) AES_CTR_xcrypt_buffer(ctx, input, text.len.uint32); i.push text.newVal

@@ -131,9 +133,10 @@ var text = s.getString

var key = ($secureHash(k.getString)).toLowerAscii var iv = ($secureHash((key & $getTime().toUnix))).toLowerAscii var ctx = cast[ptr AES_ctx](alloc0(sizeof(AES_ctx))) - AES_init_ctx_iv(ctx, cast[ptr uint8](key[0].addr), cast[ptr uint8](iv[0].addr)); + AES_init_ctx_iv(ctx, cast[ptr uint8](key[0].addr), cast[ptr uint8](iv[ + 0].addr)); var input = cast[ptr uint8](text[0].addr) AES_CTR_xcrypt_buffer(ctx, input, text.len.uint32); i.push text.newVal - + def.finalize("crypto")
M minpkg/lib/min_dict.nimminpkg/lib/min_dict.nim

@@ -1,12 +1,12 @@

-import - critbits -import - ../core/parser, - ../core/value, - ../core/interpreter, +import + std/critbits +import + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils - -proc dict_module*(i: In)= + +proc dict_module*(i: In) = let def = i.define()

@@ -33,20 +33,20 @@ i.dset(rv, "type", v.typeName.newVal)

i.dset(rv, "val", v) i.dset(rv, "str", newVal($v)) i.push rv - + def.symbol("dset") do (i: In): let vals = i.expect("'sym", "a", "dict") let k = vals[0] let m = vals[1] var d = vals[2] - i.push i.dset(d, k, m) + i.push i.dset(d, k, m) def.symbol("dset-sym") do (i: In): let vals = i.expect("'sym", "'sym", "dict") let k = vals[0] let m = newSym(vals[1].getString) var d = vals[2] - i.push i.dset(d, k, m) + i.push i.dset(d, k, m) def.symbol("ddel") do (i: In): let vals = i.expect("'sym", "dict")

@@ -63,7 +63,7 @@ def.symbol("dvalues") do (i: In):

let vals = i.expect("dict") let d = vals[0] i.push i.values(d) - + def.symbol("dpairs") do (i: In): let vals = i.expect("dict") let d = vals[0]
M minpkg/lib/min_dstore.nimminpkg/lib/min_dstore.nim

@@ -1,14 +1,14 @@

import - json, + std/[json, strutils, - oids + oids] import ../core/parser, ../core/value, ../core/interpreter, ../core/utils -proc dstore_module*(i: In)= +proc dstore_module*(i: In) = let def = i.define() def.symbol("dsinit") do (i: In):

@@ -19,18 +19,18 @@ var d = newDict(i.scope)

i.dset(d, "data", newDict(i.scope)) i.dset(d, "path", p.newVal) d.objType = "datastore" - i.push d + i.push d def.symbol("dsread") do (i: In): let vals = i.expect("'sym") let p = vals[0].getString - var j = p.readFile.parseJson + var j = p.readFile.parseJson var d = newDict(i.scope) i.dset(d, "data", i.fromJson(j)) i.dset(d, "path", p.newVal) d.objType = "datastore" - i.push d - + i.push d + def.symbol("dswrite") do (i: In): let vals = i.expect("dict:datastore") let ds = vals[0]

@@ -38,7 +38,7 @@ let p = i.dget(ds, "path".newVal).getString

let data = i%(i.dget(ds, "data".newVal)) p.writeFile(data.pretty) i.push ds - + def.symbol("dshas?") do (i: In): let vals = i.expect("'sym", "dict:datastore") let s = vals[0].getString

@@ -55,7 +55,7 @@ if dhas(cll, id.newVal):

i.push true.newVal else: i.push false.newVal - + def.symbol("dsget") do (i: In): let vals = i.expect("'sym", "dict:datastore") let s = vals[0].getString

@@ -68,9 +68,9 @@ if not dhas(data, collection):

raiseInvalid("Collection '$#' does not exist" % collection) let cll = i.dget(data, collection) i.push i.dget(cll, id.newVal) - + def.symbol("dsquery") do (i: In): - let vals = i.expect("quot", "'sym", "dict:datastore") + let vals = i.expect("quot", "'sym", "dict:datastore") var filter = vals[0] let collection = vals[1] let ds = vals[2]

@@ -90,7 +90,7 @@ res.add e

except CatchableError: discard i.push res.newVal - + def.symbol("dspost") do (i: In): let vals = i.expect("dict", "'sym", "dict:datastore") var d = vals[0]

@@ -104,7 +104,7 @@ i.dset(data, collection, newDict(i.scope))

var cll = i.dget(data, collection) i.dset(cll, id, d) i.push ds - + def.symbol("dsput") do (i: In): let vals = i.expect("dict", "'sym", "dict:datastore") var d = vals[0]

@@ -121,7 +121,7 @@ i.dset(data, collection, newDict(i.scope))

var cll = i.dget(data, collection) i.dset(cll, id, d) i.push ds - + def.symbol("dsdelete") do (i: In): let vals = i.expect("'sym", "dict:datastore") let s = vals[0].getString

@@ -135,7 +135,7 @@ var data = i.dget(ds, "data".newVal)

if not dhas(data, collection): raiseInvalid("Collection '$#' does not exist" % collection) var cll = i.dget(data, collection) - i.ddel(cll, id) + i.ddel(cll, id) i.push ds - - def.finalize("dstore")+ + def.finalize("dstore")
M minpkg/lib/min_fs.nimminpkg/lib/min_fs.nim

@@ -1,14 +1,14 @@

-import - os, +import + std/[os, times, strutils, - critbits -import + critbits] +import ../core/env, - ../core/parser, - ../core/baseutils, - ../core/value, - ../core/interpreter, + ../core/parser, + ../core/baseutils, + ../core/value, + ../core/interpreter, ../core/utils, ../core/fileutils

@@ -74,26 +74,26 @@ let f = vals[0].getString

var found = false if MINCOMPILED: let cf = strutils.replace(strutils.replace(f, "\\", "/"), "./", "") - + found = COMPILEDASSETS.hasKey(cf) if found: i.push true.newVal else: i.push newVal(f.fileExists or f.dirExists) - + def.symbol("file?") do (i: In): let vals = i.expect("'sym") let f = vals[0].getString var found = false if MINCOMPILED: let cf = strutils.replace(strutils.replace(f, "\\", "/"), "./", "") - + found = COMPILEDASSETS.hasKey(cf) if found: i.push true.newVal else: i.push f.fileExists.newVal - + def.symbol("dir?") do (i: In): let vals = i.expect("'sym") let f = vals[0]

@@ -122,7 +122,7 @@ if not p.isStringLike:

raiseInvalid("A quotation of strings is required") fragments.add(p.getString) i.push fragments.joinPath.unix.newVal - + def.symbol("expand-filename") do (i: In): let vals = i.expect("'sym") i.push vals[0].getString.expandFilename.unix.newVal

@@ -150,7 +150,7 @@

def.symbol("windows-path") do (i: In): let vals = i.expect("'sym") i.push vals[0].getString.replace("/", "\\").newVal - + def.symbol("unix-path") do (i: In): let vals = i.expect("'sym") i.push vals[0].getString.replace("\\", "/").newVal
M minpkg/lib/min_http.nimminpkg/lib/min_http.nim

@@ -1,43 +1,43 @@

-import - std/macros, - httpclient, - asynchttpserver, - asyncdispatch, - strutils, - uri, - critbits -import - ../core/parser, +import + std/[macros, + httpclient, + asynchttpserver, + asyncdispatch, + strutils, + uri, + critbits] +import + ../core/parser, ../core/meta, - ../core/value, - ../core/interpreter, + ../core/value, + ../core/interpreter, ../core/utils when defined(ssl) and defined(amd64): - when defined(windows): + when defined(windows): {.passL: "-static -L"&getProjectPath()&"/minpkg/vendor/openssl/windows -lssl -lcrypto -lws2_32".} elif defined(linux): {.passL: "-static -L"&getProjectPath()&"/minpkg/vendor/openssl/linux -lssl -lcrypto".} elif defined(macosx): {.passL: "-Bstatic -L"&getProjectPath()&"/minpkg/vendor/openssl/macosx -lssl -lcrypto -Bdynamic".} -var minUserAgent {.threadvar.} : string +var minUserAgent {.threadvar.}: string minUserAgent = "$1 http-module/$2" % [pkgName, pkgVersion] proc newCli(): HttpClient = return newHttpClient(userAgent = minUseragent) -proc newVal(i: In, headers: HttpHeaders): MinValue = +proc newVal(i: In, headers: HttpHeaders): MinValue = result = newDict(i.scope) for k, v in headers: result = i.dset(result, k, v.newVal) -type MinServerExit = ref object of CatchableError +type MinServerExit = ref object of CatchableError -proc http_module*(i: In)= +proc http_module*(i: In) = let def = i.define() - def.symbol("request") do (i: In) : + def.symbol("request") do (i: In): let vals = i.expect "dict" let req = vals[0] let cli = newCli()

@@ -58,7 +58,8 @@ if req.dhas("body"):

body = i.dget(req, "body") meth = i.dget(req, "method") url = i.dget(req, "url") - let resp = cli.request(url = url.getString, httpMethod = parseEnum[HttpMethod](meth.getString), body = body.getString, headers = headers) + let resp = cli.request(url = url.getString, httpMethod = parseEnum[ + HttpMethod](meth.getString), body = body.getString, headers = headers) var res = newDict(i.scope) res.objType = "http-response" res = i.dset(res, "version", resp.version.newVal)

@@ -69,7 +70,7 @@ if resp.status != $Http204:

b = resp.body res = i.dset(res, "body", b.newVal) i.push res - + def.symbol("get-content") do (i: In): let vals = i.expect "str" let url = vals[0]

@@ -83,7 +84,7 @@ let url = vals[1]

let cli = newCli() cli.downloadFile(url.getString, file.getString) - def.symbol("start-server") do (ii: In) : + def.symbol("start-server") do (ii: In): let vals = ii.expect "dict" let cfg = vals[0] if not cfg.dhas("port"):

@@ -109,7 +110,8 @@ qreq = i.dset(qreq, "url", newVal($req.url))

qreq = i.dset(qreq, "headers", i.newVal(req.headers)) qreq = i.dset(qreq, "method", newVal($req.reqMethod)) qreq = i.dset(qreq, "hostname", newVal($req.hostname)) - qreq = i.dset(qreq, "version", newVal("$1.$2" % [$req.protocol.major, $req.protocol.minor])) + qreq = i.dset(qreq, "version", newVal("$1.$2" % [$req.protocol.major, + $req.protocol.minor])) qreq = i.dset(qreq, "body", newVal($req.body)) i.handleErrors do: i.push qreq

@@ -143,7 +145,8 @@ while i.stack.len > 0:

discard i.pop await req.respond(status.intVal.HttpCode, body.getString, headers) try: - waitFor server.serve(port = port.intVal.Port, callback = handler, address = address.getString) + waitFor server.serve(port = port.intVal.Port, callback = handler, + address = address.getString) except MinServerExit: server.close()
M minpkg/lib/min_io.nimminpkg/lib/min_io.nim

@@ -1,18 +1,19 @@

-import - strutils, +import + std/[strutils, logging, nre, critbits, - minline, - terminal -import - ../core/parser, - ../core/value, + terminal] +import + minline +import + ../core/parser, + ../core/value, ../core/env, - ../core/interpreter, + ../core/interpreter, ../core/utils -var ORIGKEYMAP {.threadvar.}: CritBitTree[KeyCallback] +var ORIGKEYMAP {.threadvar.}: CritBitTree[KeyCallback] for key, value in KEYMAP.pairs: ORIGKEYMAP[key] = value

@@ -44,10 +45,10 @@ var ic = i.copy(i.filename)

let action = proc (ed: var LineEditor) {.closure.} = ic.apply(q) KEYMAP[key] = action - + def.symbol("newline") do (i: In): echo "" - + def.symbol("notice") do (i: In): let a = i.peek notice $$a

@@ -72,7 +73,7 @@ def.symbol("fatal") do (i: In):

let a = i.peek fatal $$a quit(100) - + def.symbol("column-print") do (i: In): let vals = i.expect("int", "quot") let n = vals[0]

@@ -94,17 +95,17 @@ if ch[0].getString.len != 1:

raiseInvalid("Symbol putch requires a string containing a single character.") putchr(ch[0].getString[0].cint) - def.symbol("password") do (i: In) : + def.symbol("password") do (i: In): var ed = initEditor() i.push ed.password("Enter Password: ").newVal - def.symbol("ask") do (i: In) : + def.symbol("ask") do (i: In): var ed = initEditor() let vals = i.expect("str") let s = vals[0] i.push ed.readLine(s.getString & ": ").newVal - def.symbol("confirm") do (i: In) : + def.symbol("confirm") do (i: In): var ed = initEditor() let vals = i.expect("str") let s = vals[0]

@@ -120,7 +121,7 @@ stdout.flushFile()

return confirm() i.push confirm().newVal - def.symbol("choose") do (i: In) : + def.symbol("choose") do (i: In): var ed = initEditor() let vals = i.expect("'sym", "quot") let s = vals[0]

@@ -132,7 +133,8 @@ stdout.flushFile()

proc choose(): int = var c = 0 for item in q.qVal: - if not item.isQuotation or not item.qVal.len == 2 or not item.qVal[0].isString or not item.qVal[1].isQuotation: + if not item.isQuotation or not item.qVal.len == 2 or not item.qVal[ + 0].isString or not item.qVal[1].isQuotation: raiseInvalid("Each item of the quotation must be a quotation containing a string and a quotation") c.inc echo "$1 - $2" % [$c, item.qVal[0].getString]

@@ -153,30 +155,31 @@

def.symbol("print") do (i: In): let a = i.peek a.print - + def.symbol("fread") do (i: In): let vals = i.expect("str") let file = vals[0].strVal var contents = "" if MINCOMPILED: - var compiledFile = strutils.replace(strutils.replace(file, "\\", "/"), "./", "") + var compiledFile = strutils.replace(strutils.replace(file, "\\", "/"), + "./", "") if COMPILEDASSETS.hasKey(compiledFile): contents = COMPILEDASSETS[compiledFile] if contents == "": contents = file.readFile i.push newVal(contents) - + def.symbol("fwrite") do (i: In): let vals = i.expect("str", "str") let a = vals[0] let b = vals[1] a.strVal.writeFile(b.strVal) - + def.symbol("fappend") do (i: In): let vals = i.expect("str", "str") let a = vals[0] let b = vals[1] - var f:File + var f: File discard f.open(a.strVal, fmAppend) f.write(b.strVal) f.close()
M minpkg/lib/min_lang.nimminpkg/lib/min_lang.nim

@@ -1,36 +1,37 @@

-import - critbits, - strutils, +import + std/[critbits, + strutils, sequtils, json, parseopt, algorithm, nre, - minline, os, - logging, + logging] +import + minline +import ../core/baseutils, - ../core/niftylogger -import + ../core/niftylogger, ../core/env, ../core/meta, - ../core/parser, - ../core/value, - ../core/interpreter, + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils, ../core/scope proc lang_module*(i: In) = let def = i.scope - + const HELPFILE = "../../help.json".slurp let HELP = HELPFILE.parseJson - def.symbol("from-json") do (i: In) : + def.symbol("from-json") do (i: In): let vals = i.expect("str") let s = vals[0] i.push i.fromJson(s.getString.parseJson) - + def.symbol("to-json") do (i: In): let vals = i.expect "a" let q = vals[0]

@@ -38,7 +39,7 @@ i.push(($((i%q).pretty)).newVal)

# Save/load symbols - def.symbol("save-symbol") do (i: In) : + def.symbol("save-symbol") do (i: In): let vals = i.expect("'sym") let s = vals[0] let sym = s.getString

@@ -57,12 +58,13 @@ let json = MINSYMBOLS.readFile.parseJson

if not json.hasKey(sym): raiseUndefined("Symbol '$1' not found." % sym) let val = i.fromJson(json[sym]) - i.scope.symbols[sym] = MinOperator(kind: minValOp, val: val, quotation: true) + i.scope.symbols[sym] = MinOperator(kind: minValOp, val: val, + quotation: true) def.symbol("saved-symbols") do (i: In): var q = newSeq[MinValue](0) let json = MINSYMBOLS.readFile.parseJson - for k,v in json.pairs: + for k, v in json.pairs: q.add k.newVal i.push q.newVal

@@ -85,11 +87,11 @@ file = file & ".min"

info("[load] File: ", file) let f = simplifyPath(i.filename, file) if MINCOMPILED and COMPILEDMINFILES.hasKey(f): - var i2 = i.copy(f) - i2.withScope(): - COMPILEDMINFILES[f](i2) - i = i2.copy(i.filename) - return + var i2 = i.copy(f) + i2.withScope(): + COMPILEDMINFILES[f](i2) + i = i2.copy(i.filename) + return else: if not f.fileExists: raiseInvalid("File '$1' does not exist." % file)

@@ -104,17 +106,17 @@ file = file & ".min"

info("[require] File: ", file) let f = simplifyPath(i.filename, file) if MINCOMPILED and COMPILEDMINFILES.hasKey(f): - var i2 = i.copy(f) - i2.withScope(): - var mdl: MinValue - if not CACHEDMODULES.hasKey(f): - COMPILEDMINFILES[f](i2) - CACHEDMODULES[f] = newDict(i2.scope) - CACHEDMODULES[f].objType = "module" - mdl = CACHEDMODULES[f] - for key, value in i2.scope.symbols.pairs: - mdl.scope.symbols[key] = value - i.push(mdl) + var i2 = i.copy(f) + i2.withScope(): + var mdl: MinValue + if not CACHEDMODULES.hasKey(f): + COMPILEDMINFILES[f](i2) + CACHEDMODULES[f] = newDict(i2.scope) + CACHEDMODULES[f].objType = "module" + mdl = CACHEDMODULES[f] + for key, value in i2.scope.symbols.pairs: + mdl.scope.symbols[key] = value + i.push(mdl) else: if not f.fileExists: raiseInvalid("File '$1' does not exist." % file)

@@ -123,7 +125,7 @@

def.symbol("raw-args") do (i: In): var args = newSeq[MinValue](0) for par in commandLineParams(): - args.add par.newVal + args.add par.newVal i.push args.newVal def.symbol("with") do (i: In):

@@ -144,7 +146,7 @@ raiseUndefined("Attempting to redefine sealed symbol '$1'" % [sym])

let scope = i.scope info("[publish] Symbol: $2" % [sym]) let op = proc(i: In) {.closure.} = - let origscope = i.scope + let origscope = i.scope i.scope = scope i.evaluating = true i.pushSym sym

@@ -160,7 +162,8 @@ raiseInvalid("Invalid operator definition")

let tv = q.qVal[0] let t = tv.symVal let nv = q.qVal[1] - if not tv.isSymbol or (not ["symbol", "sigil", "typeclass", "constructor"].contains(t)): + if not tv.isSymbol or (not ["symbol", "sigil", "typeclass", + "constructor"].contains(t)): raiseInvalid("Incorrect operator type specified (it must be 'symbol', 'sigil', 'constructor', or 'typeclass' - found '$#')" % tv.symVal) if not nv.isSymbol: raiseInvalid("Operator name must be a symbol")

@@ -182,9 +185,9 @@ raiseInvalid("Invalid signature")

var c = 0 # Process signature let docSig = $sv - var inExpects= newSeq[string](0) + var inExpects = newSeq[string](0) var inVars = newSeq[string](0) - var outExpects= newSeq[string](0) + var outExpects = newSeq[string](0) var outVars = newSeq[string](0) var rawOutVars = newSeq[string](0) var generics: CritBitTree[string]

@@ -203,9 +206,11 @@ raiseInvalid("Generic quotation must contain exactly two symbols")

let t = vv.qVal[0].getString let g = vv.qVal[1].getString if not i.validType(t): - raiseInvalid("Invalid type '$#' in generic in signature at position $#" % [$t, $(c+1)]) + raiseInvalid("Invalid type '$#' in generic in signature at position $#" % + [$t, $(c+1)]) if g[0] != ':' and g[0] != '^': - raiseInvalid("No mapping symbol specified in generic in signature at position $#" % $(c+1)) + raiseInvalid("No mapping symbol specified in generic in signature at position $#" % + $(c+1)) v = g[1..g.len-1] generics[v] = t else:

@@ -214,7 +219,8 @@ if check:

if v == "==>": o = true elif not i.validType(v) and not generics.hasKey(v): - raiseInvalid("Invalid type '$#' specified in signature at position $#" % [v, $(c+1)]) + raiseInvalid("Invalid type '$#' specified in signature at position $#" % + [v, $(c+1)]) else: if o: if tv.symVal == "typeclass" and (outExpects.len > 0 or v != "bool"):

@@ -228,16 +234,19 @@ raiseInvalid("typeclasses can only have one input value")

inExpects.add v else: if v[0] != ':' and v[0] != '^': - raiseInvalid("No capturing symbol specified in signature at position $#" % $(c+1)) + raiseInvalid("No capturing symbol specified in signature at position $#" % + $(c+1)) else: if o: if v[0] == '^' and outExpects[outExpects.len-1] != "quot": - raiseInvalid("Only quotations can be captured to a lambda, found $# instead at position $#" % [outExpects[outExpects.len-1], $(c+1)]) + raiseInvalid("Only quotations can be captured to a lambda, found $# instead at position $#" % + [outExpects[outExpects.len-1], $(c+1)]) rawOutVars.add v outVars.add v[1..v.len-1] else: if v[0] == '^': - raiseInvalid("A lambda capturing symbol was specified in signature at position $#. Lambda capturing symbols are only allowed for output values" % $(c+1)) + raiseInvalid("A lambda capturing symbol was specified in signature at position $#. Lambda capturing symbols are only allowed for output values" % + $(c+1)) inVars.add v[1..v.len-1] c.inc() if not o:

@@ -251,7 +260,7 @@ inExpects.reverse

inVars.reverse var p: MinOperatorProc = proc (i: In) = var inVals: seq[MinValue] - try: + try: inVals = i.expect(inExpects, generics) except CatchableError: generics = origGenerics

@@ -262,10 +271,12 @@ for k in 0..inVars.len-1:

var iv = inVals[k] if iv.isQuotation: iv = @[iv].newVal - i.scope.symbols[inVars[k]] = MinOperator(kind: minValOp, sealed: false, val: iv, quotation: inVals[k].isQuotation) + i.scope.symbols[inVars[k]] = MinOperator(kind: minValOp, + sealed: false, val: iv, quotation: inVals[k].isQuotation) # Inject variables for mapped outputs for k in 0..outVars.len-1: - i.scope.symbols[outVars[k]] = MinOperator(kind: minValOp, sealed: false, val: @[newNull()].newVal, quotation: true) + i.scope.symbols[outVars[k]] = MinOperator(kind: minValOp, + sealed: false, val: @[newNull()].newVal, quotation: true) # Actually execute the body of the operator if DEV: var endSnapshot: seq[MinValue]

@@ -274,8 +285,8 @@ try:

snapshot = deepCopy(i.stack) i.dequote bv endSnapshot = i.stack - let d= snapshot.diff(endSnapshot) - if d.len > 0 : + let d = snapshot.diff(endSnapshot) + if d.len > 0: raiseInvalid("Operator '$#' is polluting the stack -- $#" % [n, $d.newVal]) except MinReturnException: discard

@@ -307,7 +318,8 @@ var tp = o

if generics.hasKey(o): tp = generics[o] generics = origGenerics - raiseInvalid("Invalid value for output symbol '$#'. Expected $#, found $#" % [outVars[k], tp, $x]) + raiseInvalid("Invalid value for output symbol '$#'. Expected $#, found $#" % + [outVars[k], tp, $x]) # Push output on stack i.pushSym outVars[k] generics = origGenerics

@@ -316,7 +328,7 @@ var doc = newJObject()

doc["name"] = %n doc["kind"] = %t doc["signature"] = %docSig - doc["description"] = %i.currSym.docComment.strip + doc["description"] = %i.currSym.docComment.strip if ["symbol", "typeclass", "constructor"].contains(t): if i.scope.symbols.hasKey(n) and i.scope.symbols[n].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [n])

@@ -338,11 +350,11 @@

def.symbol("puts") do (i: In): let a = i.peek echo $$a - - def.symbol("gets") do (i: In) : + + def.symbol("gets") do (i: In): var ed = initEditor() i.push ed.readLine().newVal - + def.symbol("apply") do (i: In): let vals = i.expect("quot") var prog = vals[0]

@@ -364,15 +376,15 @@

def.symbol("defined-sigil?") do (i: In): let vals = i.expect("'sym") i.push(i.scope.hasSigil(vals[0].getString).newVal) - + def.symbol("sealed-symbol?") do (i: In): let vals = i.expect("'sym") i.push i.scope.getSymbol(vals[0].getString).sealed.newVal - + def.symbol("sealed-sigil?") do (i: In): let vals = i.expect("'sym") i.push i.scope.getSigil(vals[0].getString).sealed.newVal - + def.symbol("sigils") do (i: In): var q = newSeq[MinValue](0) var scope = i.scope

@@ -454,8 +466,9 @@ raiseInvalid("Symbol identifier '$1' contains invalid characters." % symbol)

info "[define] $1 = $2" % [symbol, $q1] if i.scope.symbols.hasKey(symbol) and i.scope.symbols[symbol].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [symbol]) - i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, sealed: false, quotation: isQuot) - + i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, + sealed: false, quotation: isQuot) + def.symbol("typealias") do (i: In): let vals = i.expect("'sym", "'sym") let sym = vals[0].getString

@@ -468,8 +481,9 @@ raiseInvalid("Symbol identifier '$1' contains invalid characters." % sym)

info "[typealias] $1 = $2" % [sym, s] if i.scope.symbols.hasKey(symbol) and i.scope.symbols[symbol].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [symbol]) - i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: s.newVal, sealed: false, quotation: false) - + i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: s.newVal, + sealed: false, quotation: false) + def.symbol("lambda") do (i: In): let vals = i.expect("'sym", "quot") let sym = vals[0]

@@ -481,8 +495,9 @@ raiseInvalid("Symbol identifier '$1' contains invalid characters." % symbol)

info "[lambda] $1 = $2" % [symbol, $q1] if i.scope.symbols.hasKey(symbol) and i.scope.symbols[symbol].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [symbol]) - i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, sealed: false, quotation: true) - + i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, + sealed: false, quotation: true) + def.symbol("bind") do (i: In): let vals = i.expect("'sym", "a") let sym = vals[0]

@@ -492,32 +507,34 @@ var isQuot = q1.isQuotation

q1 = @[q1].newVal symbol = sym.getString info "[bind] $1 = $2" % [symbol, $q1] - let res = i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1, quotation: isQuot)) + let res = i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1, + quotation: isQuot)) if not res: raiseUndefined("Attempting to bind undefined symbol: " & symbol) - + def.symbol("lambda-bind") do (i: In): let vals = i.expect("'sym", "quot") let sym = vals[0] - var q1 = vals[1] + var q1 = vals[1] var symbol: string symbol = sym.getString info "[lambda-bind] $1 = $2" % [symbol, $q1] - let res = i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1, quotation: true)) + let res = i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1, + quotation: true)) if not res: raiseUndefined("Attempting to lambda-bind undefined symbol: " & symbol) def.symbol("delete-symbol") do (i: In): let vals = i.expect("'sym") let sym = vals[0] - let res = i.scope.delSymbol(sym.getString) + let res = i.scope.delSymbol(sym.getString) if not res: raiseUndefined("Attempting to delete undefined symbol: " & sym.getString) - + def.symbol("delete-sigil") do (i: In): let vals = i.expect("'sym") let sym = vals[0] - let res = i.scope.delSigil(sym.getString) + let res = i.scope.delSigil(sym.getString) if not res: raiseUndefined("Attempting to delete undefined sigil: " & sym.getString)

@@ -572,7 +589,7 @@ doc.objType = "help"

i.push doc return elif HELP["operators"].hasKey(s): - var doc =i.fromJson(HELP["operators"][s]) + var doc = i.fromJson(HELP["operators"][s]) doc.objType = "help" i.push doc return

@@ -629,7 +646,8 @@ var op = i.scope.getSymbol(name)

i.apply(op) vals = i.expect("dict:module") let mdl = vals[0] - info("[import] Importing: $1 ($2 symbols, $3 sigils)" % [name, $mdl.scope.symbols.len, $mdl.scope.sigils.len]) + info("[import] Importing: $1 ($2 symbols, $3 sigils)" % [name, + $mdl.scope.symbols.len, $mdl.scope.sigils.len]) for sym, val in mdl.scope.symbols.pairs: if i.scope.symbols.hasKey(sym) and i.scope.symbols[sym].sealed: raiseUndefined("Attempting to redefine sealed symbol '$1'" % [sym])

@@ -640,12 +658,12 @@ if i.scope.sigils.hasKey(sig) and i.scope.sigils[sig].sealed:

raiseUndefined("Attempting to redefine sealed sigil '$1'" % [sig]) i.debug "[import] $1" % [sig] i.scope.sigils[sig] = val - + def.symbol("eval") do (i: In): let vals = i.expect("str") let s = vals[0] i.eval s.strVal - + def.symbol("quit") do (i: In): i.push 0.newVal i.pushSym "exit"

@@ -675,7 +693,7 @@ i.pushSym parts[0]

for p in 0..parts.len-2: let vals = i.expect("dict") let mdl = vals[0] - let symId = parts[p+1] + let symId = parts[p+1] let origScope = i.scope i.scope = mdl.scope if not i.scope.parent.isNil:

@@ -688,7 +706,8 @@ def.symbol("raise") do (i: In):

let vals = i.expect("dict") let err = vals[0] if err.dhas("error".newVal) and err.dhas("message".newVal): - raiseRuntime("($1) $2" % [i.dget(err, "error".newVal).getString, i.dget(err, "message").getString], err) + raiseRuntime("($1) $2" % [i.dget(err, "error".newVal).getString, i.dget( + err, "message").getString], err) else: raiseInvalid("Invalid error dictionary")

@@ -710,7 +729,8 @@ list.add i.dget(err, "column")

if list.len <= 3: msg = "$1" % $$list[0] else: - msg = "$3($4,$5) `$2`: $1" % [$$list[0], $$list[1], $$list[2], $$list[3], $$list[4]] + msg = "$3($4,$5) `$2`: $1" % [$$list[0], $$list[1], $$list[2], $$list[ + 3], $$list[4]] i.push msg.newVal else: raiseInvalid("Invalid error dictionary")

@@ -730,7 +750,8 @@ hasCatch = true

if prog.qVal.len > 2: final = prog.qVal[2] hasFinally = true - if (not code.isQuotation) or (hasCatch and not catch.isQuotation) or (hasFinally and not final.isQuotation): + if (not code.isQuotation) or (hasCatch and not catch.isQuotation) or ( + hasFinally and not final.isQuotation): raiseInvalid("Quotation must contain at least one quotation") try: i.dequote(code)

@@ -767,7 +788,7 @@ def.symbol("quote") do (i: In):

let vals = i.expect("a") let a = vals[0] i.push @[a].newVal - + def.symbol("dequote") do (i: In): let vals = i.expect("quot") var q = vals[0]

@@ -866,7 +887,7 @@ var list = vals[1]

for litem in list.qVal: i.push litem i.dequote(prog) - + def.symbol("times") do (i: In): let vals = i.expect("int", "quot") var t = vals[0].intVal

@@ -874,7 +895,7 @@ var prog = vals[1]

if t > 0: for c in 1..t: i.dequote(prog) - + def.symbol("while") do (i: In): let vals = i.expect("quot", "quot") var d = vals[0]

@@ -887,7 +908,7 @@ i.dequote(b)

check = i.pop # Other - + def.symbol("linrec") do (i: In): let vals = i.expect("quot", "quot", "quot", "quot") var r2 = vals[0]

@@ -911,28 +932,28 @@

def.symbol("seal-symbol") do (i: In): let vals = i.expect("'sym") let sym = vals[0].getString - var s = i.scope.getSymbol(sym) + var s = i.scope.getSymbol(sym) s.sealed = true i.scope.setSymbol(sym, s, true) - + def.symbol("seal-sigil") do (i: In): let vals = i.expect("'sym") let sym = vals[0].getString - var s = i.scope.getSigil(sym) + var s = i.scope.getSigil(sym) s.sealed = true i.scope.setSigil(sym, s, true) def.symbol("unseal-symbol") do (i: In): let vals = i.expect("'sym") let sym = vals[0].getString - var s = i.scope.getSymbol(sym) + var s = i.scope.getSymbol(sym) s.sealed = false i.scope.setSymbol(sym, s, true) - + def.symbol("unseal-sigil") do (i: In): let vals = i.expect("'sym") let sym = vals[0].getString - var s = i.scope.getSigil(sym) + var s = i.scope.getSigil(sym) if not sym.contains re(USER_SYMBOL_REGEX): # Prevent accidentally unsealing system sigils # Not that they can redefined, but still

@@ -951,7 +972,7 @@ discard

i.push args.newVal def.symbol("opts") do (i: In): - var opts = newDict(i.scope) + var opts = newDict(i.scope) for kind, key, val in getopt(): case kind: of cmdLongOption, cmdShortOption:

@@ -962,12 +983,12 @@ opts = i.dset(opts, key.newVal, val.newVal)

else: discard i.push opts - + def.symbol("expect") do (i: In): var q: MinValue i.reqQuotationOfSymbols q i.push(i.expect(q.qVal.mapIt(it.getString())).reversed.newVal) - + def.symbol("infix-dequote") do (i: In): let vals = i.expect("quot") let q = vals[0]

@@ -988,7 +1009,7 @@ i.dequote(res)

res = newSeq[MinValue](0).newVal return i.pop i.push i.infix(q) - + def.symbol("prefix-dequote") do (i: In): let vals = i.expect("quot") var q = vals[0]

@@ -1100,7 +1121,7 @@ i.pushSym("load-symbol")

def.sigil("^") do (i: In): i.pushSym("lambda") - + def.sigil("~") do (i: In): i.pushSym("lambda-bind")

@@ -1111,16 +1132,16 @@ i.pushSym("expect-empty-stack")

def.symbol(":") do (i: In): i.pushSym("define") - + def.symbol("?") do (i: In): i.pushSym("help") def.symbol("@") do (i: In): i.pushSym("bind") - + def.symbol("^") do (i: In): i.pushSym("lambda") - + def.symbol("~") do (i: In): i.pushSym("lambda-bind")

@@ -1129,22 +1150,22 @@ i.pushSym("quotesym")

def.symbol("->") do (i: In): i.pushSym("dequote") - + def.symbol("::") do (i: In): i.pushSym("operator") - + def.symbol("=>") do (i: In): i.pushSym("apply") - + def.symbol("==>") do (i: In): discard # used within operator defs - + def.symbol("return") do (i: In): discard # used within operator defs - + def.symbol(">>") do (i: In): i.pushSym("prefix-dequote") - + def.symbol("><") do (i: In): i.pushSym("infix-dequote")
M minpkg/lib/min_logic.nimminpkg/lib/min_logic.nim

@@ -1,15 +1,15 @@

-import - math -import - ../core/parser, - ../core/value, - ../core/interpreter, +import + std/math +import + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils proc floatCompare(n1, n2: MinValue): bool = let - a:float = if n1.kind != minFloat: n1.intVal.float else: n1.floatVal - b:float = if n2.kind != minFloat: n2.intVal.float else: n2.floatVal + a: float = if n1.kind != minFloat: n1.intVal.float else: n1.floatVal + b: float = if n2.kind != minFloat: n2.intVal.float else: n2.floatVal if a.classify == fcNan and b.classify == fcNan: return true else:

@@ -29,9 +29,9 @@ return diff < (epsilon * FLOAT_MIN_NORMAL)

else: return diff / min((absA + absB), FLOAT_MAX_VALUE) < epsilon -proc logic_module*(i: In)= +proc logic_module*(i: In) = let def = i.define() - + def.symbol(">") do (i: In): var n1, n2: MinValue i.reqTwoNumbersOrStrings n2, n1

@@ -45,8 +45,8 @@ i.push newVal(n1.floatVal > n2.floatVal)

elif n1.isFloat and n2.isInt: i.push newVal(n1.floatVal > n2.intVal.float) else: - i.push newVal(n1.strVal > n2.strVal) - + i.push newVal(n1.strVal > n2.strVal) + def.symbol(">=") do (i: In): var n1, n2: MinValue i.reqTwoNumbersOrStrings n2, n1

@@ -61,7 +61,7 @@ elif n1.isFloat and n2.isInt:

i.push newVal(n1.floatVal > n2.intVal.float or floatCompare(n1, n2)) else: i.push newVal(n1.strVal >= n2.strVal) - + def.symbol("<") do (i: In): var n1, n2: MinValue i.reqTwoNumbersOrStrings n1, n2

@@ -75,8 +75,8 @@ i.push newVal(n1.floatVal > n2.floatVal)

elif n1.isFloat and n2.isInt: i.push newVal(n1.floatVal > n2.intVal.float) else: - i.push newVal(n1.strVal > n2.strVal) - + i.push newVal(n1.strVal > n2.strVal) + def.symbol("<=") do (i: In): var n1, n2: MinValue i.reqTwoNumbersOrStrings n1, n2

@@ -90,8 +90,8 @@ i.push newVal(n1.floatVal > n2.floatVal or floatCompare(n1, n2))

elif n1.isFloat and n2.isInt: i.push newVal(n1.floatVal > n2.intVal.float or floatCompare(n1, n2)) else: - i.push newVal(n1.strVal >= n2.strVal) - + i.push newVal(n1.strVal >= n2.strVal) + def.symbol("==") do (i: In): var n1, n2: MinValue let vals = i.expect("a", "a")

@@ -101,7 +101,7 @@ if (n1.kind == minFloat or n2.kind == minFloat) and n1.isNumber and n2.isNumber:

i.push newVal(floatCompare(n1, n2)) else: i.push newVal(n1 == n2) - + def.symbol("!=") do (i: In): var n1, n2: MinValue let vals = i.expect("a", "a")

@@ -110,18 +110,18 @@ n2 = vals[1]

if (n1.kind == minFloat or n2.kind == minFloat) and n1.isNumber and n2.isNumber: i.push newVal(not floatCompare(n1, n2)) i.push newVal(not (n1 == n2)) - + def.symbol("not") do (i: In): let vals = i.expect("bool") let b = vals[0] i.push newVal(not b.boolVal) - + def.symbol("and") do (i: In): let vals = i.expect("bool", "bool") let a = vals[0] let b = vals[1] i.push newVal(a.boolVal and b.boolVal) - + def.symbol("expect-all") do (i: In): let vals = i.expect("quot") let q = vals[0]

@@ -139,13 +139,13 @@ if not r.boolVal:

i.push r return i.push true.newVal - + def.symbol("or") do (i: In): let vals = i.expect("bool", "bool") let a = vals[0] let b = vals[1] i.push newVal(a.boolVal or b.boolVal) - + def.symbol("expect-any") do (i: In): let vals = i.expect("quot") let q = vals[0]

@@ -169,50 +169,50 @@ let vals = i.expect("bool", "bool")

let a = vals[0] let b = vals[1] i.push newVal(a.boolVal xor b.boolVal) - + def.symbol("string?") do (i: In): if i.pop.kind == minString: i.push true.newVal else: i.push false.newVal - + def.symbol("integer?") do (i: In): if i.pop.kind == minInt: i.push true.newVal else: i.push false.newVal - + def.symbol("float?") do (i: In): if i.pop.kind == minFloat: i.push true.newVal else: i.push false.newVal - + def.symbol("null?") do (i: In): if i.pop.kind == minNull: i.push true.newVal else: i.push false.newVal - + def.symbol("number?") do (i: In): let a = i.pop if a.kind == minFloat or a.kind == minInt: i.push true.newVal else: i.push false.newVal - + def.symbol("boolean?") do (i: In): if i.pop.kind == minBool: i.push true.newVal else: i.push false.newVal - + def.symbol("quotation?") do (i: In): if i.pop.kind == minQuotation: i.push true.newVal else: i.push false.newVal - + def.symbol("quoted-symbol?") do (i: In): let item = i.pop if item.kind == minQuotation and item.qVal.len == 1 and item.qVal[0].kind == minSymbol:

@@ -225,7 +225,7 @@ if i.pop.isStringLike:

i.push true.newVal else: i.push false.newVal - + def.symbol("dictionary?") do (i: In): if i.pop.isDictionary: i.push true.newVal

@@ -238,10 +238,10 @@ let t = vals[0].getString

let v = vals[1] let res = i.validateValueType(t, v) i.push res.newVal - + def.symbol("&&") do (i: In): i.pushSym("expect-all") - + def.symbol("||") do (i: In): i.pushSym("expect-any")
M minpkg/lib/min_math.nimminpkg/lib/min_math.nim

@@ -1,29 +1,29 @@

-import - math, +import + std/[math, strformat, - strutils -import - ../core/parser, - ../core/value, - ../core/interpreter, + strutils] +import + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils -proc math_module*(i: In)= +proc math_module*(i: In) = let def = i.define() def.symbol("floor") do (i: In): let vals = i.expect("num") i.push BiggestInt(vals[0].getFloat.floor).newVal - + def.symbol("ceil") do (i: In): let vals = i.expect("num") i.push BiggestInt(vals[0].getFloat.ceil).newVal - + def.symbol("trunc") do (i: In): let vals = i.expect("num") i.push vals[0].getFloat.trunc.newVal - + def.symbol("abs") do (i: In): let vals = i.expect("num") let n = vals[0]

@@ -31,7 +31,7 @@ if n.kind == minFloat:

i.push n.floatVal.abs.newVal else: i.push n.intVal.abs.newVal - + def.symbol("round") do (i: In): let vals = i.expect("int", "num") let places = vals[0].intVal.int

@@ -39,42 +39,42 @@ let n = vals[1].getFloat

var res = "" formatValue(res, n, "." & $places & "f") i.push parseFloat(res).newVal - + def.symbol("e") do (i: In): i.push E.newVal - + def.symbol("pi") do (i: In): i.push PI.newVal - + def.symbol("tau") do (i: In): i.push TAU.newVal - + def.symbol("ln") do (i: In): let vals = i.expect("num") i.push vals[0].getFloat.ln.newVal - + def.symbol("log2") do (i: In): let vals = i.expect("num") i.push vals[0].getFloat.log2.newVal - + def.symbol("log10") do (i: In): let vals = i.expect("num") i.push vals[0].getFloat.log10.newVal - + def.symbol("pow") do (i: In): let vals = i.expect("num", "num") let y = vals[0].getFloat let x = vals[1].getFloat i.push x.pow(y).newVal - + def.symbol("sqrt") do (i: In): let vals = i.expect("num") i.push vals[0].getFloat.sqrt.newVal - + def.symbol("sin") do (i: In): let vals = i.expect("num") i.push vals[0].getFloat.sin.newVal - + def.symbol("cos") do (i: In): let vals = i.expect("num") i.push vals[0].getFloat.cos.newVal
M minpkg/lib/min_net.nimminpkg/lib/min_net.nim

@@ -1,20 +1,22 @@

-import net, nativesockets -import - ../core/parser, - ../core/value, - ../core/interpreter, +import + std/[net, + nativesockets] +import + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils proc toSocket(q: MinValue): Socket = return cast[Socket](q.obj) -proc net_module*(i: In)= +proc net_module*(i: In) = let def = i.define() - + def.symbol("socket") do (i: In): let vals = i.expect "dict" var q = vals[0] - var + var domain = AF_INET sockettype = SOCK_STREAM protocol = IPPROTO_TCP

@@ -59,7 +61,7 @@

def.symbol("close") do (i: In): let vals = i.expect("dict:socket") vals[0].toSocket.close() - + def.symbol("listen") do (i: In): let vals = i.expect("dict", "dict:socket") let params = vals[0]
M minpkg/lib/min_num.nimminpkg/lib/min_num.nim

@@ -1,24 +1,24 @@

-import - random -import - ../core/parser, - ../core/value, - ../core/interpreter, +import + std/random +import + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils -proc num_module*(i: In)= +proc num_module*(i: In) = let def = i.define() def.symbol("nan") do (i: In): i.push newVal(NaN) - + def.symbol("inf") do (i: In): i.push newVal(Inf) - + def.symbol("-inf") do (i: In): i.push newVal(NegInf) - + def.symbol("+") do (i: In): let vals = i.expect("num", "num") let a = vals[0]

@@ -33,7 +33,7 @@ if b.isFloat:

i.push newVal(a.floatVal + b.floatVal) else: i.push newVal(a.floatVal + b.intVal.float) - + def.symbol("-") do (i: In): let vals = i.expect("num", "num") let a = vals[0]

@@ -47,8 +47,8 @@ else:

if b.isFloat: i.push newVal(b.floatVal - a.floatVal) else: - i.push newVal(b.intVal.float - a.floatVal) - + i.push newVal(b.intVal.float - a.floatVal) + def.symbol("*") do (i: In): let vals = i.expect("num", "num") let a = vals[0]

@@ -63,7 +63,7 @@ if b.isFloat:

i.push newVal(a.floatVal * b.floatVal) else: i.push newVal(a.floatVal * b.intVal.float) - + def.symbol("/") do (i: In): let vals = i.expect("num", "num") let a = vals[0]

@@ -77,8 +77,8 @@ else:

if b.isFloat: i.push newVal(b.floatVal / a.floatVal) else: - i.push newVal(b.intVal.float / a.floatVal) - + i.push newVal(b.intVal.float / a.floatVal) + def.symbol("randomize") do (i: In): randomize()

@@ -92,7 +92,7 @@ let vals = i.expect("int", "int")

let b = vals[0] let a = vals[1] i.push(newVal(a.intVal div b.intVal)) - + def.symbol("mod") do (i: In): let vals = i.expect("int", "int") let b = vals[0]

@@ -108,7 +108,7 @@ def.symbol("pred") do (i: In):

let vals = i.expect("int") let n = vals[0] i.push newVal(n.intVal - 1) - + def.symbol("even?") do (i: In): let vals = i.expect("int") let n = vals[0]

@@ -118,9 +118,9 @@ def.symbol("odd?") do (i: In):

let vals = i.expect("int") let n = vals[0] i.push newVal(n.intVal mod 2 != 0) - + def.symbol("bitand") do (i: In): - let vals = i.expect("int","int") + let vals = i.expect("int", "int") let b = vals[0] let a = vals[1] i.push newVal(a.intVal and b.intVal)

@@ -131,25 +131,25 @@ let a = vals[0]

i.push newVal(not a.intVal) def.symbol("bitor") do (i: In): - let vals = i.expect("int","int") + let vals = i.expect("int", "int") let b = vals[0] let a = vals[1] i.push newVal(a.intVal or b.intVal) def.symbol("bitxor") do (i: In): - let vals = i.expect("int","int") + let vals = i.expect("int", "int") let b = vals[0] let a = vals[1] i.push newVal(a.intVal xor b.intVal) def.symbol("shl") do (i: In): - let vals = i.expect("int","int") + let vals = i.expect("int", "int") let b = vals[0] let a = vals[1] i.push newVal(a.intVal shl b.intVal) def.symbol("shr") do (i: In): - let vals = i.expect("int","int") + let vals = i.expect("int", "int") let b = vals[0] let a = vals[1] i.push newVal(a.intVal shr b.intVal)

@@ -197,7 +197,7 @@ else:

c = c + n.intVal.float c = c / len(s.qVal).float i.push c.newVal - + def.symbol("med") do (i: In): var s: MinValue i.reqQuotationOfNumbers s

@@ -216,7 +216,7 @@ if second.isFloat:

i.push ((first.intVal.float+second.floatVal)/2).newVal else: i.push ((first.intVal+second.intVal).float/2).newVal - + def.symbol("range") do (i: In): var s: MinValue i.reqQuotationOfIntegers s

@@ -224,7 +224,7 @@ var a = s.qVal[0]

var b = s.qVal[1] var step = 1.newVal var res = newSeq[MinValue](0) - if len(s.qVal)==3: + if len(s.qVal) == 3: a = s.qVal[0] b = s.qVal[1] step = s.qVal[2]
M minpkg/lib/min_seq.nimminpkg/lib/min_seq.nim

@@ -1,15 +1,15 @@

-import - tables, +import + std/[tables, algorithm, sets, - sequtils -import - ../core/parser, - ../core/value, - ../core/interpreter, + sequtils] +import + ../core/parser, + ../core/value, + ../core/interpreter, ../core/utils - -proc seq_module*(i: In)= + +proc seq_module*(i: In) = let def = i.define()

@@ -17,25 +17,25 @@ def.symbol("intersection") do (i: In):

let vals = i.expect("quot", "quot") let q1 = toHashSet(vals[0].qVal) let q2 = toHashSet(vals[1].qVal) - i.push toSeq(items(q2.intersection(q1))).newVal + i.push toSeq(items(q2.intersection(q1))).newVal def.symbol("union") do (i: In): let vals = i.expect("quot", "quot") let q1 = toHashSet(vals[0].qVal) let q2 = toHashSet(vals[1].qVal) - i.push toSeq(items(q2.union(q1))).newVal + i.push toSeq(items(q2.union(q1))).newVal def.symbol("difference") do (i: In): let vals = i.expect("quot", "quot") let q1 = toHashSet(vals[0].qVal) let q2 = toHashSet(vals[1].qVal) - i.push toSeq(items(q2.difference(q1))).newVal + i.push toSeq(items(q2.difference(q1))).newVal def.symbol("symmetric-difference") do (i: In): let vals = i.expect("quot", "quot") let q1 = toHashSet(vals[0].qVal) let q2 = toHashSet(vals[1].qVal) - i.push toSeq(items(q2.symmetricDifference(q1))).newVal + i.push toSeq(items(q2.symmetricDifference(q1))).newVal def.symbol("concat") do (i: In): let vals = i.expect("quot", "quot")

@@ -43,40 +43,40 @@ let q1 = vals[0]

let q2 = vals[1] let q = q2.qVal & q1.qVal i.push q.newVal - + def.symbol("first") do (i: In): let vals = i.expect("quot") let q = vals[0] if q.qVal.len == 0: raiseOutOfBounds("Quotation is empty") i.push q.qVal[0] - + def.symbol("last") do (i: In): let vals = i.expect("quot") let q = vals[0] if q.qVal.len == 0: raiseOutOfBounds("Quotation is empty") i.push q.qVal[q.qVal.len - 1] - + def.symbol("rest") do (i: In): let vals = i.expect("quot") let q = vals[0] if q.qVal.len == 0: raiseOutOfBounds("Quotation is empty") i.push q.qVal[1..q.qVal.len-1].newVal - + def.symbol("append") do (i: In): let vals = i.expect("quot", "a") let q = vals[0] let v = vals[1] i.push newVal(q.qVal & v) - + def.symbol("prepend") do (i: In): let vals = i.expect("quot", "a") let q = vals[0] let v = vals[1] i.push newVal(v & q.qVal) - + def.symbol("get") do (i: In): let vals = i.expect("int", "quot") let index = vals[0]

@@ -100,7 +100,7 @@ i.dset(rv, "type", v.typeName.newVal)

i.dset(rv, "val", v) i.dset(rv, "str", newVal($v)) i.push rv - + def.symbol("set") do (i: In): let vals = i.expect("int", "a", "quot") let index = vals[0]

@@ -122,7 +122,7 @@ if q.qVal.len < ix or ix < 0:

raiseOutOfBounds("Index out of bounds") q.qVal[ix.int] = val i.push q - + def.symbol("remove") do (i: In): let vals = i.expect("int", "quot") let index = vals[0]

@@ -136,7 +136,7 @@ if x == ix:

continue res.add q.qVal[x] i.push res.newVal - + def.symbol("insert") do (i: In): let vals = i.expect("int", "a", "quot") let index = vals[0]

@@ -156,13 +156,13 @@ def.symbol("size") do (i: In):

let vals = i.expect("quot") let q = vals[0] i.push q.qVal.len.newVal - + def.symbol("in?") do (i: In): let vals = i.expect("a", "quot") let v = vals[0] let q = vals[1] - i.push q.qVal.contains(v).newVal - + i.push q.qVal.contains(v).newVal + def.symbol("map") do (i: In): let vals = i.expect("quot", "quot") var prog = vals[0]

@@ -227,7 +227,7 @@ i.dequote(filter)

var check = i.pop if check.isBool and check.boolVal == true: res = true.newVal - break + break i.push res def.symbol("one?") do (i: In):

@@ -265,7 +265,7 @@ let vals = i.expect("quot", "quot")

var cmp = vals[0] let list = vals[1] var i2 = i - var minCmp = proc(a, b: MinValue): int {.closure.}= + var minCmp = proc(a, b: MinValue): int {.closure.} = i2.push a i2.push b i2.dequote(cmp)

@@ -280,7 +280,7 @@ raiseInvalid("Predicate quotation must return a boolean value")

var qList = list.qVal sort[MinValue](qList, minCmp) i.push qList.newVal - + def.symbol("shorten") do (i: In): let vals = i.expect("int", "quot") let n = vals[0]
M minpkg/lib/min_str.nimminpkg/lib/min_str.nim

@@ -1,21 +1,21 @@

-import - strutils, +import + std/[strutils, sequtils, nre, - std/macros, - uri -import - ../core/parser, - ../core/value, - ../core/interpreter, + macros, + uri] +import + ../core/parser, + ../core/value, + ../core/interpreter, ../core/baseutils, ../core/utils -proc str_module*(i: In) = +proc str_module*(i: In) = let def = i.define() when not defined(nopcre): - when defined(windows) and defined(amd64): + when defined(windows) and defined(amd64): {.passL: "-static -L"&getProjectPath()&"/minpkg/vendor/pcre/windows -lpcre".} elif defined(linux) and defined(amd64): {.passL: "-static -L"&getProjectPath()&"/minpkg/vendor/pcre/linux -lpcre".}

@@ -72,7 +72,7 @@ ss.add match.match.newVal

for s in match.captures: if s.isNone: ss.add "".newVal - else: + else: ss.add s.get.newVal i2.push ss.newVal i2.push q

@@ -105,13 +105,13 @@ def.symbol("strip") do (i: In):

let vals = i.expect("'sym") let s = vals[0] i.push s.getString.strip.newVal - + def.symbol("substr") do (i: In): let vals = i.expect("int", "int", "'sym") let length = vals[0].intVal let start = vals[1].intVal let s = vals[2].getString - let index = min(start+length-1, s.len-1) + let index = min(start+length-1, s.len-1) i.push s[start..index].newVal def.symbol("split") do (i: In):

@@ -127,13 +127,13 @@ def.symbol("join") do (i: In):

let vals = i.expect("'sym", "quot") let s = vals[0] let q = vals[1] - i.push q.qVal.mapIt($$it).join(s.getString).newVal + i.push q.qVal.mapIt($$it).join(s.getString).newVal def.symbol("length") do (i: In): let vals = i.expect("'sym") let s = vals[0] i.push s.getString.len.newVal - + def.symbol("lowercase") do (i: In): let vals = i.expect("'sym") let s = vals[0]

@@ -155,7 +155,7 @@ let s = vals[0]

if s.getString.len != 1: raiseInvalid("Symbol ord requires a string containing a single character.") i.push s.getString[0].ord.newVal - + def.symbol("chr") do (i: In): let vals = i.expect("int") let n = vals[0]

@@ -190,12 +190,12 @@ def.symbol("encode-url") do (i: In):

let vals = i.expect("str") let s = vals[0].strVal i.push s.encodeUrl.newVal - + def.symbol("decode-url") do (i: In): let vals = i.expect("str") let s = vals[0].strVal i.push s.decodeUrl.newVal - + def.symbol("parse-url") do (i: In): let vals = i.expect("str") let s = vals[0].strVal

@@ -217,11 +217,11 @@ let vals = i.expect("str")

let v = vals[0].strVal let m = v.match(re"^\d+\.\d+\.\d+$") i.push m.isSome.newVal - + def.symbol("from-semver") do (i: In): let vals = i.expect("str") let v = vals[0].strVal - let reg = re"^(\d+)\.(\d+)\.(\d+)$" + let reg = re"^(\d+)\.(\d+)\.(\d+)$" let rawMatch = v.match(reg) if rawMatch.isNone: raiseInvalid("String '$1' is not a basic semver" % v)

@@ -231,7 +231,7 @@ i.dset(d, "major", parts[0].parseInt.newVal)

i.dset(d, "minor", parts[1].parseInt.newVal) i.dset(d, "patch", parts[2].parseInt.newVal) i.push d - + def.symbol("to-semver") do (i: In): let vals = i.expect("dict") let v = vals[0]

@@ -239,7 +239,7 @@ if not v.dhas("major") or not v.dhas("minor") or not v.dhas("patch"):

raiseInvalid("Dictionary does not contain major, minor and patch keys") let major = i.dget(v, "major") let minor = i.dget(v, "minor") - let patch = i.dget(v, "patch") + let patch = i.dget(v, "patch") if major.kind != minInt or minor.kind != minInt or patch.kind != minInt: raiseInvalid("major, minor, and patch values are not integers") i.push(newVal("$#.$#.$#" % [$major, $minor, $patch]))

@@ -278,14 +278,14 @@ def.symbol("escape") do (i: In):

let vals = i.expect("'sym") let a = vals[0].getString i.push a.escapeEx(true).newVal - + def.symbol("prefix") do (i: In): let vals = i.expect("'sym", "'sym") let a = vals[1].getString let b = vals[0].getString var s = b & a i.push s.newVal - + def.symbol("suffix") do (i: In): let vals = i.expect("'sym", "'sym") let a = vals[1].getString
M minpkg/lib/min_sys.nimminpkg/lib/min_sys.nim

@@ -1,35 +1,35 @@

-import - os, - osproc, +import + std/[os, + osproc, strutils, logging, - tables -import - ../core/parser, + tables] +import + ../core/parser, ../core/baseutils, - ../core/value, - ../core/interpreter, + ../core/value, + ../core/interpreter, ../core/utils, ../core/fileutils import zippy/ziparchives -proc sys_module*(i: In)= +proc sys_module*(i: In) = let def = i.define() - + def.symbol(".") do (i: In): i.push newVal(getCurrentDir().unix) - + def.symbol("..") do (i: In): i.push newVal(getCurrentDir().parentDir.unix) - + def.symbol("cd") do (i: In): let vals = i.expect("'sym") let f = vals[0].getString i.pwd = joinPath(getCurrentDir(), f) info("Current directory changed to: ", i.pwd) f.setCurrentDir - + def.symbol("ls") do (i: In): let vals = i.expect("'sym") let a = vals[0]

@@ -37,7 +37,7 @@ var list = newSeq[MinValue](0)

for i in walkDir(a.getString): list.add newVal(i.path.unix) i.push list.newVal - + def.symbol("ls-r") do (i: In): let vals = i.expect("'sym") let a = vals[0]

@@ -59,18 +59,18 @@ var d = newDict(i.scope)

i.dset(d, "output", res.output.strip.newVal) i.dset(d, "code", res.exitCode.newVal) i.push(d) - + def.symbol("get-env") do (i: In): let vals = i.expect("'sym") let a = vals[0] i.push a.getString.getEnv.newVal - + def.symbol("put-env") do (i: In): let vals = i.expect("'sym", "'sym") let key = vals[0] let value = vals[1] key.getString.putEnv value.getString - + def.symbol("env?") do (i: In): let vals = i.expect("'sym") let s = vals[0]

@@ -83,10 +83,10 @@ i.push s.getString.findExe.newVal

def.symbol("os") do (i: In): i.push hostOS.newVal - + def.symbol("cpu") do (i: In): i.push hostCPU.newVal - + def.symbol("rm") do (i: In): let vals = i.expect("'sym") let v = vals[0]

@@ -95,7 +95,7 @@ if f.fileExists:

f.removeFile else: raiseInvalid("File '$1' does not exist." % f) - + def.symbol("cp") do (i: In): let vals = i.expect("'sym", "'sym") let a = vals[0]

@@ -108,10 +108,10 @@ elif dest.dirExists:

if src.dirExists: copyDirWithPermissions src, dest else: - copyFileWithPermissions src, dest / src.extractFilename + copyFileWithPermissions src, dest / src.extractFilename else: - copyFileWithPermissions src, dest - + copyFileWithPermissions src, dest + def.symbol("mv") do (i: In): let vals = i.expect("'sym", "'sym") let a = vals[0]

@@ -119,14 +119,14 @@ let b = vals[1]

let src = b.getString var dest = a.getString if dest.dirExists: - dest = dest / src.extractFilename + dest = dest / src.extractFilename moveFile src, dest - + def.symbol("rmdir") do (i: In): let vals = i.expect("'sym") let f = vals[0] f.getString.removeDir - + def.symbol("mkdir") do (i: In): let vals = i.expect("'sym") let f = vals[0]

@@ -199,4 +199,4 @@ def.symbol("admin?") do (i: In):

i.push isAdmin().newVal def.finalize("sys") - +
M minpkg/lib/min_time.nimminpkg/lib/min_time.nim

@@ -1,12 +1,12 @@

import - times + std/times import ../core/parser, ../core/value, ../core/interpreter, ../core/utils -proc time_module*(i: In)= +proc time_module*(i: In) = let def = i.define() def.symbol("timestamp") do (i: In):
M minpkg/lib/min_xml.nimminpkg/lib/min_xml.nim

@@ -1,10 +1,11 @@

-import - std/xmlparser, - std/xmltree, - std/parsexml, - std/strtabs, - std/critbits, +import + std/[xmlparser, + xmltree, + parsexml, + strtabs, + critbits] +import nimquery import ../core/parser,

@@ -47,7 +48,7 @@ result.objType = "xml-comment"

i.dset(result, "text", xml.text.newVal) proc newXml(i: In, xdict: MinValue): XmlNode = - case xdict.objType: + case xdict.objType: of "xml-text": result = newText(i.dget(xdict, "text").getString) of "xml-element":

@@ -77,13 +78,15 @@ proc xml_module*(i: In) =

let def = i.define() - i.scope.symbols["typealias:xml-node"] = MinOperator(kind: minValOp, val: xmltypes.newVal, sealed: false, quotation: false) + i.scope.symbols["typealias:xml-node"] = MinOperator(kind: minValOp, + val: xmltypes.newVal, sealed: false, quotation: false) def.symbol("from-xml") do (i: In): let vals = i.expect("str") - let s = vals[0].getString() + let s = vals[0].getString() try: - let xml = parseXml(s, {reportComments, allowUnquotedAttribs, allowEmptyAttribs}) + let xml = parseXml(s, {reportComments, allowUnquotedAttribs, + allowEmptyAttribs}) i.push(i.newXDict(xml)) except CatchableError: let msg = getCurrentExceptionMsg()

@@ -91,19 +94,19 @@ raiseInvalid(msg)

def.symbol("xcomment") do (i: In): let vals = i.expect("'sym") - i.push i.newXDict(newComment(vals[0].getString)) - + i.push i.newXDict(newComment(vals[0].getString)) + def.symbol("xcdata") do (i: In): let vals = i.expect("'sym") - i.push i.newXDict(newCData(vals[0].getString)) + i.push i.newXDict(newCData(vals[0].getString)) def.symbol("xtext") do (i: In): let vals = i.expect("'sym") - i.push i.newXDict(newText(vals[0].getString)) + i.push i.newXDict(newText(vals[0].getString)) def.symbol("xentity") do (i: In): let vals = i.expect("'sym") - i.push i.newXDict(newEntity(vals[0].getString)) + i.push i.newXDict(newEntity(vals[0].getString)) def.symbol("xelement") do (i: In): let vals = i.expect("'sym")

@@ -130,7 +133,7 @@ let root = i.newXml(xdict)

let xresults = root.querySelectorAll(query) var results = newSeq[MinValue](0) for e in xresults: - results.add i.newXDict(e) + results.add i.newXDict(e) i.push results.newVal def.finalize("xml")
M next-release.mdnext-release.md

@@ -1,4 +1,7 @@

+### New Features + + ### Fixes and Improvements -* Removed depentency unnecessary dependency on nifty. -* Now compiling using `--mm:refc` to decrease memory usage. +* Now requiring `checksums` unless OpenSSL is used. +* Prepended `std/` to standard library modules.
M site/settings.jsonsite/settings.json

@@ -6,5 +6,5 @@ "rules": "rules.min",

"temp": "temp", "templates": "templates", "title": "min language", - "version": "0.39.2" + "version": "0.40.0" }