all repos — min @ e3d13b8ed329b168edb31ad696e58ff8b11e50e3

A small but practical concatenative programming language.

Refactoring utils.
h3rald h3rald@h3rald.com
Sun, 18 Sep 2016 15:38:16 +0200
commit

e3d13b8ed329b168edb31ad696e58ff8b11e50e3

parent

8282886a09bc0e4fea61e9e7eb73ba8fc764024c

A core/fileutils.nim

@@ -0,0 +1,101 @@

+import + os + +# Filetype and permissions + +proc filetype*(p: PathComponent): string = + case p + of pcFile: + return "file" + of pcLinkToFile: + return "filelink" + of pcDir: + return "dir" + of pcLinkToDir: + return "dirlink" + +proc unixPermissions*(s: set[FilePermission]): int = + result = 0 + for p in s: + case p: + of fpUserRead: + result += 400 + of fpUserWrite: + result += 200 + of fpUserExec: + result += 100 + of fpGroupRead: + result += 40 + of fpGroupWrite: + result += 20 + of fpGroupExec: + result += 10 + of fpOthersRead: + result += 4 + of fpOthersWrite: + result += 2 + of fpOthersExec: + result += 1 + +proc toFilePermissions*(p: BiggestInt): set[FilePermission] = + let user = ($p)[0].int + let group = ($p)[1].int + let others = ($p)[2].int + if user == 1: + result.incl fpUserExec + if user == 2: + result.incl fpUserWrite + if user == 3: + result.incl fpUserExec + result.incl fpUserWrite + if user == 4: + result.incl fpUserRead + if user == 5: + result.incl fpUserRead + result.incl fpUserExec + if user == 6: + result.incl fpUserRead + result.incl fpUserWrite + if user == 7: + result.incl fpUserRead + result.incl fpUserWrite + result.incl fpUserExec + if group == 1: + result.incl fpGroupExec + if group == 2: + result.incl fpGroupWrite + if group == 3: + result.incl fpGroupExec + result.incl fpGroupWrite + if group == 4: + result.incl fpGroupRead + if group == 5: + result.incl fpGroupRead + result.incl fpGroupExec + if group == 6: + result.incl fpGroupRead + result.incl fpGroupWrite + if group == 7: + result.incl fpGroupRead + result.incl fpGroupWrite + result.incl fpGroupExec + if others == 1: + result.incl fpOthersExec + if others == 2: + result.incl fpOthersWrite + if others == 3: + result.incl fpOthersExec + result.incl fpOthersWrite + if others == 4: + result.incl fpOthersRead + if others == 5: + result.incl fpOthersRead + result.incl fpOthersExec + if others == 6: + result.incl fpOthersRead + result.incl fpOthersWrite + if others == 7: + result.incl fpOthersRead + result.incl fpOthersWrite + result.incl fpOthersExec +
M core/interpreter.nimcore/interpreter.nim

@@ -4,6 +4,7 @@ strutils,

critbits, os import + value, parser type

@@ -167,7 +168,7 @@ i.parser.close();

proc push*(i: In, val: MinValue) {.gcsafe.} -proc execOp*(i: In, op: MinOperator) = +proc apply*(i: In, op: MinOperator) = case op.kind of minProcOp: op.prc(i)

@@ -191,13 +192,13 @@ let sym = i.scope.getSymbol(symbol)

if i.unsafe: let stack = i.copystack try: - i.execOp(sym) + i.apply(sym) except: i.stack = stack raise else: i.execute: - i.execOp(sym) + i.apply(sym) else: let found = i.scope.hasSigil(sigil) if symbol.len > 1 and found:

@@ -207,13 +208,13 @@ i.stack.add(MinValue(kind: minString, strVal: sym))

if i.unsafe: let stack = i.copystack try: - i.execOp(sig) + i.apply(sig) except: i.stack = stack raise else: i.execute: - i.execOp(sig) + i.apply(sig) else: raiseUndefined("Undefined symbol: '"&val.symVal&"'") else:

@@ -274,7 +275,3 @@ except:

stderr.writeLine getCurrentExceptionMsg() finally: i.filename = fn - -proc apply*(i: In, symbol: string) = - # TODO review - i.scope.getSymbol(symbol).prc(i)
M core/utils.nimcore/utils.nim

@@ -1,203 +1,19 @@

import - tables, strutils, - macros, - critbits, - json, - os, - regex + critbits import parser, + value, interpreter -# Predicates - -proc isSymbol*(s: MinValue): bool = - return s.kind == minSymbol - -proc isQuotation*(s: MinValue): bool = - return s.kind == minQuotation +# Library methods -proc isString*(s: MinValue): bool = - return s.kind == minString - -proc isFloat*(s: MinValue): bool = - return s.kind == minFloat - -proc isInt*(s: MinValue): bool = - return s.kind == minInt - -proc isNumber*(s: MinValue): bool = - return s.kind == minInt or s.kind == minFloat - -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) - -proc isDictionary*(q: MinValue): bool = - if not q.isQuotation: - return false - if q.qVal.len == 0: - return true - for val in q.qVal: - if not val.isQuotation or val.qVal.len != 2 or not val.qVal[0].isSymbol: - return false - return true - -# Constructors - -proc newVal*(s: string): MinValue = - return MinValue(kind: minString, strVal: s) - -proc newVal*(s: cstring): MinValue = - return MinValue(kind: minString, strVal: $s) - -proc newVal*(q: seq[MinValue]): MinValue = - return MinValue(kind: minQuotation, qVal: q) - -proc newVal*(s: BiggestInt): MinValue = - return MinValue(kind: minInt, intVal: s) - -proc newVal*(s: BiggestFloat): MinValue = - return MinValue(kind: minFloat, floatVal: s) - -proc newVal*(s: bool): MinValue = - return MinValue(kind: minBool, boolVal: s) - -proc newSym*(s: string): MinValue = - return MinValue(kind: minSymbol, symVal: s) - -proc newQuotation*(): MinValue = - return MinValue(kind: minQuotation, qVal: newSeq[MinValue](0)) - -# Filetype and permissions - -proc filetype*(p: PathComponent): string = - case p - of pcFile: - return "file" - of pcLinkToFile: - return "filelink" - of pcDir: - return "dir" - of pcLinkToDir: - return "dirlink" - -proc unixPermissions*(s: set[FilePermission]): int = - result = 0 - for p in s: - case p: - of fpUserRead: - result += 400 - of fpUserWrite: - result += 200 - of fpUserExec: - result += 100 - of fpGroupRead: - result += 40 - of fpGroupWrite: - result += 20 - of fpGroupExec: - result += 10 - of fpOthersRead: - result += 4 - of fpOthersWrite: - result += 2 - of fpOthersExec: - result += 1 - -proc toFilePermissions*(p: BiggestInt): set[FilePermission] = - let user = ($p)[0].int - let group = ($p)[1].int - let others = ($p)[2].int - if user == 1: - result.incl fpUserExec - if user == 2: - result.incl fpUserWrite - if user == 3: - result.incl fpUserExec - result.incl fpUserWrite - if user == 4: - result.incl fpUserRead - if user == 5: - result.incl fpUserRead - result.incl fpUserExec - if user == 6: - result.incl fpUserRead - result.incl fpUserWrite - if user == 7: - result.incl fpUserRead - result.incl fpUserWrite - result.incl fpUserExec - if group == 1: - result.incl fpGroupExec - if group == 2: - result.incl fpGroupWrite - if group == 3: - result.incl fpGroupExec - result.incl fpGroupWrite - if group == 4: - result.incl fpGroupRead - if group == 5: - result.incl fpGroupRead - result.incl fpGroupExec - if group == 6: - result.incl fpGroupRead - result.incl fpGroupWrite - if group == 7: - result.incl fpGroupRead - result.incl fpGroupWrite - result.incl fpGroupExec - if others == 1: - result.incl fpOthersExec - if others == 2: - result.incl fpOthersWrite - if others == 3: - result.incl fpOthersExec - result.incl fpOthersWrite - if others == 4: - result.incl fpOthersRead - if others == 5: - result.incl fpOthersRead - result.incl fpOthersExec - if others == 6: - result.incl fpOthersRead - result.incl fpOthersWrite - if others == 7: - result.incl fpOthersRead - result.incl fpOthersWrite - result.incl fpOthersExec - -proc getString*(v: MinValue): string = - if v.isSymbol: - return v.symVal - elif v.isString: - return v.strVal - elif v.isQuotation: - if v.qVal.len != 1: - raiseInvalid("Quotation is not a quoted symbol") - let sym = v.qVal[0] - if sym.isSymbol: - return sym.symVal - else: - raiseInvalid("Quotation is not a quoted symbol") - -proc warn*(s: string) = - stderr.writeLine s - -proc previous*(scope: ref MinScope): ref MinScope = +proc previous(scope: ref MinScope): ref MinScope = if scope.parent.isNil: return scope #### was: ROOT else: return scope.parent -proc replace*[T](c: var CritBitTree, s: string, v: T): T {.discardable.}= - if c.hasKey(s): - c.excl(s) - c[s] = v - proc define*(i: In, name: string): ref MinScope = var scope = new MinScope scope.name = name

@@ -228,119 +44,6 @@ i.evaluating = true

i.push mdl i.evaluating = false mdl.scope.previous.symbols[scope.name] = MinOperator(kind: minProcOp, prc: op) - -template alias*[T](varname: untyped, value: var T) = - var varname {.inject.}: type(value) - shallowCopy varname, value - -proc to*(q: MinValue, T: typedesc): T = - return cast[T](q.obj) - -proc `%`*(c: CritBitTree[string]): JsonNode = - result = newJObject() - for key, value in c.pairs: - result[key] = %value - -proc critbit*(o: JsonNode): CritBitTree[string] = - for key, value in o.pairs: - result[key] = value.getStr - -proc `%`*(a: MinValue): JsonNode = - case a.kind: - of minBool: - return %a.boolVal - of minSymbol: - return %(";sym:$1" % [a.symVal]) - of minString: - return %a.strVal - of minInt: - return %a.intVal - of minFloat: - return %a.floatVal - of minQuotation: - if a.isDictionary: - result = newJObject() - for i in a.qVal: - result[$i.qVal[0].symVal] = %i.qVal[1] - else: - result = newJArray() - for i in a.qVal: - result.add %i - -proc fromJson*(json: JsonNode): MinValue = - case json.kind: - of JNull: - result = newSeq[MinValue](0).newVal - of JBool: - result = json.getBVal.newVal - of JInt: - result = json.getNum.newVal - of JFloat: - result = json.getFNum.newVal - of JString: - let s = json.getStr - if s.match("^;sym:"): - result = regex.replace(s, "^;sym:", "").newSym - else: - result = json.getStr.newVal - of JObject: - var res = newSeq[MinValue](0) - for key, value in json.pairs: - res.add @[key.newSym, value.fromJson].newVal - return res.newVal - of JArray: - var res = newSeq[MinValue](0) - for value in json.items: - res.add value.fromJson - return res.newVal - -# Dictionary Methods - -proc dget*(q: MinValue, s: MinValue): MinValue = - # Assumes q is a dictionary - for v in q.qVal: - if v.qVal[0].getString == s.getString: - return v.qVal[1] - raiseInvalid("Key '$1' not found" % [s.getString]) - -proc ddel*(q: var MinValue, s: MinValue): MinValue = - # Assumes q is a dictionary - var found = false - var c = -1 - for v in q.qVal: - c.inc - if v.qVal[0].getString == s.getString: - found = true - break - if found: - q.qVal.delete(c) - return q - -proc dset*(q: var MinValue, s: MinValue, m: MinValue): MinValue {.discardable.}= - # Assumes q is a dictionary - var found = false - var c = -1 - for v in q.qVal: - c.inc - if v.qVal[0].getString == s.getString: - found = true - break - if found: - q.qVal.delete(c) - q.qVal.insert(@[s.getString.newSym, m].newVal, c) - return q - -proc keys*(q: MinValue): MinValue = - # Assumes q is a dictionary - result = newSeq[MinValue](0).newVal - for v in q.qVal: - result.qVal.add v.qVal[0] - -proc values*(q: MinValue): MinValue = - # Assumes q is a dictionary - result = newSeq[MinValue](0).newVal - for v in q.qVal: - result.qVal.add v.qVal[1] # Validators
A core/value.nim

@@ -0,0 +1,83 @@

+import + critbits +import + parser + +# Predicates + +proc isSymbol*(s: MinValue): bool = + return s.kind == minSymbol + +proc isQuotation*(s: MinValue): bool = + return s.kind == minQuotation + +proc isString*(s: MinValue): bool = + return s.kind == minString + +proc isFloat*(s: MinValue): bool = + return s.kind == minFloat + +proc isInt*(s: MinValue): bool = + return s.kind == minInt + +proc isNumber*(s: MinValue): bool = + return s.kind == minInt or s.kind == minFloat + +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) + +proc isDictionary*(q: MinValue): bool = + if not q.isQuotation: + return false + if q.qVal.len == 0: + return true + for val in q.qVal: + if not val.isQuotation or val.qVal.len != 2 or not val.qVal[0].isSymbol: + return false + return true + +# Constructors + +proc newVal*(s: string): MinValue = + return MinValue(kind: minString, strVal: s) + +proc newVal*(s: cstring): MinValue = + return MinValue(kind: minString, strVal: $s) + +proc newVal*(q: seq[MinValue]): MinValue = + return MinValue(kind: minQuotation, qVal: q) + +proc newVal*(s: BiggestInt): MinValue = + return MinValue(kind: minInt, intVal: s) + +proc newVal*(s: BiggestFloat): MinValue = + return MinValue(kind: minFloat, floatVal: s) + +proc newVal*(s: bool): MinValue = + return MinValue(kind: minBool, boolVal: s) + +proc newSym*(s: string): MinValue = + return MinValue(kind: minSymbol, symVal: s) + +proc newQuotation*(): MinValue = + return MinValue(kind: minQuotation, qVal: newSeq[MinValue](0)) + +# Get string value from string or quoted symbol + +proc getString*(v: MinValue): string = + if v.isSymbol: + return v.symVal + elif v.isString: + return v.strVal + elif v.isQuotation: + if v.qVal.len != 1: + raiseInvalid("Quotation is not a quoted symbol") + let sym = v.qVal[0] + if sym.isSymbol: + return sym.symVal + else: + raiseInvalid("Quotation is not a quoted symbol") +
M lib/min_crypto.nimlib/min_crypto.nim

@@ -5,6 +5,7 @@ strutils,

times import ../core/parser, + ../core/value, ../core/interpreter, ../core/utils, ../vendor/sha1,
M lib/min_fs.nimlib/min_fs.nim

@@ -4,8 +4,10 @@ os,

times import ../core/parser, + ../core/value, ../core/interpreter, - ../core/utils + ../core/utils, + ../core/fileutils proc fs_module*(i: In) = i.define("fs")
M lib/min_io.nimlib/min_io.nim

@@ -4,6 +4,7 @@ strutils

import ../core/linedit, ../core/parser, + ../core/value, ../core/interpreter, ../core/utils
M lib/min_lang.nimlib/min_lang.nim

@@ -6,11 +6,111 @@ json

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

@@ -121,7 +221,7 @@ var mdl, rawName: MinValue

var name: string i.reqStringLike rawName name = rawName.getString - i.execOp(i.scope.getSymbol(name)) + i.apply(i.scope.getSymbol(name)) i.reqQuotation mdl if not mdl.scope.isNil: for sym, val in mdl.scope.symbols.pairs:

@@ -175,7 +275,7 @@ let s = symbol.getString

let origScope = i.scope i.scope = q.scope let sym = i.scope.getSymbol(s) - i.execOp(sym) + i.apply(sym) i.scope = origScope .symbol("inspect") do (i: In):
M lib/min_logic.nimlib/min_logic.nim

@@ -2,6 +2,7 @@ import

tables import ../core/parser, + ../core/value, ../core/interpreter, ../core/utils
M lib/min_num.nimlib/min_num.nim

@@ -3,6 +3,7 @@ tables,

random import ../core/parser, + ../core/value, ../core/interpreter, ../core/utils
M lib/min_str.nimlib/min_str.nim

@@ -4,6 +4,7 @@ strutils,

sequtils import ../core/parser, + ../core/value, ../core/interpreter, ../core/utils, ../core/regex
M lib/min_sys.nimlib/min_sys.nim

@@ -5,8 +5,10 @@ osproc,

strutils import ../core/parser, + ../core/value, ../core/interpreter, - ../core/utils + ../core/utils, + ../core/fileutils proc sys_module*(i: In)= i.define("sys")
M lib/min_time.nimlib/min_time.nim

@@ -3,6 +3,7 @@ times,

tables import ../core/parser, + ../core/value, ../core/interpreter, ../core/utils
M minim.nimminim.nim

@@ -3,6 +3,7 @@ import

core/linedit, core/consts, core/parser, + core/value, core/interpreter, core/utils import

@@ -164,7 +165,7 @@ discard i.parser.getToken()

try: i.interpret() except: - warn getCurrentExceptionMsg() + stderr.writeLine getCurrentExceptionMsg() finally: if i.stack.len > 0: let last = i.stack[i.stack.len - 1]