all repos — min @ 7c889de7c640c4c7a0c8acfb1e007970237dc382

A small but practical concatenative programming language.

Dictionary keys must now be strings; improved expect validation errors.
h3rald h3rald@h3rald.com
Sun, 06 Aug 2017 11:45:16 +0200
commit

7c889de7c640c4c7a0c8acfb1e007970237dc382

parent

9b10fb86580cb0dca000c7bd5d8cf45cdf86e558

M core/utils.nimcore/utils.nim

@@ -48,21 +48,24 @@

# Dictionary Methods proc dget*(q: MinValue, s: MinValue): MinValue = - # Assumes q is a dictionary + if not q.isDictionary: + raiseInvalid("Value is not a dictionary") for v in q.qVal: if v.qVal[0].getString == s.getString: return v.qVal[1] raiseInvalid("Dictionary key '$1' not found" % s.getString) proc dhas*(q: MinValue, s: MinValue): bool = - # Assumes q is a dictionary + if not q.isDictionary: + raiseInvalid("Value is not a dictionary") for v in q.qVal: if v.qVal[0].getString == s.getString: return true return false proc ddel*(i: In, p: MinValue, s: MinValue): MinValue {.discardable.} = - # Assumes q is a dictionary + if not p.isDictionary: + raiseInvalid("Value is not a dictionary") var q = newVal(p.qVal, i.scope) var found = false var c = -1

@@ -76,7 +79,8 @@ q.qVal.delete(c)

return q proc dset*(i: In, p: MinValue, s: MinValue, m: MinValue): MinValue {.discardable.}= - # Assumes q is a dictionary + if not p.isDictionary: + raiseInvalid("Value is not a dictionary") var q = newVal(p.qVal, i.scope) var found = false var c = -1

@@ -87,9 +91,9 @@ found = true

break if found: q.qVal.delete(c) - q.qVal.insert(@[s.getString.newSym, m].newVal(i.scope), c) + q.qVal.insert(@[s.getString.newVal, m].newVal(i.scope), c) else: - q.qVal.add(@[s.getString.newSym, m].newVal(i.scope)) + q.qVal.add(@[s.getString.newVal, m].newVal(i.scope)) return q proc keys*(i: In, q: MinValue): MinValue =

@@ -147,7 +151,7 @@ result = json.getStr.newVal

of JObject: var res = newSeq[MinValue](0) for key, value in json.pairs: - res.add @[key.newSym, i.fromJson(value)].newVal(i.scope) + res.add @[key.newVal, i.fromJson(value)].newVal(i.scope) return res.newVal(i.scope) of JArray: var res = newSeq[MinValue](0)

@@ -158,13 +162,17 @@

# Validators proc expect*(i: var MinInterpreter, elements: varargs[string]): seq[MinValue] = - let stack = elements.join(" ") + let stack = elements.reverse.join(" ") + let sym = i.currSym.getString var valid = newSeq[string](0) result = newSeq[MinValue](0) let message = proc(invalid: string): string = - result = "Incorrect values found on the stack:\n" - result &= "- expected: {top} " & stack & " {bottom}\n" - result &= "- got: {top} " & valid.reverse.join(" ") & " " & invalid & " {bottom}" + result = "Symbol: $1 - Incorrect values found on the stack:\n" % sym + result &= "- expected: " & stack & " $1\n" % sym + var other = "" + if valid.len > 0: + other = valid.reverse.join(" ") & " " + result &= "- got: " & invalid & " " & other & sym for element in elements: let value = i.pop result.add value
M core/value.nimcore/value.nim

@@ -4,6 +4,21 @@ import

parser, scope +proc typeName*(v: MinValue): string = + case v.kind: + of minInt: + return "int" + of minFloat: + return "float" + of minQuotation: + return "quot" + of minString: + return "string" + of minSymbol: + return "sym" + of minBool: + return "bool" + # Predicates proc isSymbol*(s: MinValue): bool =

@@ -36,7 +51,7 @@ 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 or val.qVal[0].isString): + if not val.isQuotation or val.qVal.len != 2 or not val.qVal[0].isString: return false return true

@@ -62,21 +77,6 @@ return MinValue(kind: minBool, boolVal: s)

proc newSym*(s: string): MinValue = return MinValue(kind: minSymbol, symVal: s) - -proc typeName*(v: MinValue): string = - case v.kind: - of minInt: - return "int" - of minFloat: - return "float" - of minQuotation: - return "quot" - of minString: - return "string" - of minSymbol: - return "sym" - of minBool: - return "bool" # Get string value from string or quoted symbol
M lib/min_fs.nimlib/min_fs.nim

@@ -43,16 +43,16 @@ let vals = i.expect("'sym")

let s = vals[0] let fi = s.getString.getFileInfo var info = newSeq[MinValue](0).newVal(i.scope) - info.qVal.add @["name".newSym, s].newVal(i.scope) - info.qVal.add @["device".newSym, fi.id.device.BiggestInt.newVal].newVal(i.scope) - info.qVal.add @["file".newSym, fi.id.file.BiggestInt.newVal].newVal(i.scope) - info.qVal.add @["type".newSym, fi.kind.filetype.newVal].newVal(i.scope) - info.qVal.add @["size".newSym, fi.size.newVal].newVal(i.scope) - info.qVal.add @["permissions".newSym, fi.permissions.unixPermissions.newVal].newVal(i.scope) - info.qVal.add @["nlinks".newSym, fi.linkCount.newVal].newVal(i.scope) - info.qVal.add @["ctime".newSym, fi.creationTime.toSeconds.newVal].newVal(i.scope) - info.qVal.add @["atime".newSym, fi.lastAccessTime.toSeconds.newVal].newVal(i.scope) - info.qVal.add @["mtime".newSym, fi.lastWriteTime.toSeconds.newVal].newVal(i.scope) + info.qVal.add @["name".newVal, s].newVal(i.scope) + info.qVal.add @["device".newVal, fi.id.device.BiggestInt.newVal].newVal(i.scope) + info.qVal.add @["file".newVal, fi.id.file.BiggestInt.newVal].newVal(i.scope) + info.qVal.add @["type".newVal, fi.kind.filetype.newVal].newVal(i.scope) + info.qVal.add @["size".newVal, fi.size.newVal].newVal(i.scope) + info.qVal.add @["permissions".newVal, fi.permissions.unixPermissions.newVal].newVal(i.scope) + info.qVal.add @["nlinks".newVal, fi.linkCount.newVal].newVal(i.scope) + info.qVal.add @["ctime".newVal, fi.creationTime.toSeconds.newVal].newVal(i.scope) + info.qVal.add @["atime".newVal, fi.lastAccessTime.toSeconds.newVal].newVal(i.scope) + info.qVal.add @["mtime".newVal, fi.lastWriteTime.toSeconds.newVal].newVal(i.scope) i.push info def.symbol("ftype") do (i: In):
M lib/min_lang.nimlib/min_lang.nim

@@ -223,7 +223,7 @@

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

@@ -231,7 +231,7 @@

def.symbol("format-error") do (i: In): let vals = i.expect("dict") let err = vals[0] - if err.dhas("error".newSym) and err.dhas("message".newSym): + if err.dhas("error".newVal) and err.dhas("message".newVal): var msg: string var list = newSeq[MinValue]() list.add err.dget("message".newVal)

@@ -282,12 +282,12 @@ return

let e = getCurrentException() var res = newSeq[MinValue](0) let err = sgregex.replace($e.name, ":.+$", "") - res.add @["error".newSym, err.newVal].newVal(i.scope) - res.add @["message".newSym, e.msg.newVal].newVal(i.scope) - res.add @["symbol".newSym, i.currSym].newVal(i.scope) - res.add @["filename".newSym, i.currSym.filename.newVal].newVal(i.scope) - res.add @["line".newSym, i.currSym.line.newVal].newVal(i.scope) - res.add @["column".newSym, i.currSym.column.newVal].newVal(i.scope) + res.add @["error".newVal, err.newVal].newVal(i.scope) + res.add @["message".newVal, e.msg.newVal].newVal(i.scope) + res.add @["symbol".newVal, i.currSym].newVal(i.scope) + res.add @["filename".newVal, i.currSym.filename.newVal].newVal(i.scope) + res.add @["line".newVal, i.currSym.line.newVal].newVal(i.scope) + res.add @["column".newVal, i.currSym.column.newVal].newVal(i.scope) i.push res.newVal(i.scope) i.dequote(catch) finally:
M lib/min_sys.nimlib/min_sys.nim

@@ -56,7 +56,7 @@ def.symbol("run") do (i: In):

let vals = i.expect("'sym") let cmd = vals[0] let res = execCmdEx(cmd.getString) - i.push @[@["output".newSym, res.output.newVal].newVal(i.scope), @["code".newSym, res.exitCode.newVal].newVal(i.scope)].newVal(i.scope) + i.push @[@["output".newVal, res.output.newVal].newVal(i.scope), @["code".newVal, res.exitCode.newVal].newVal(i.scope)].newVal(i.scope) def.symbol("get-env") do (i: In): let vals = i.expect("'sym")
M lib/min_time.nimlib/min_time.nim

@@ -29,16 +29,16 @@ else:

time = t.floatVal.fromSeconds let tinfo = time.getLocalTime var info = newSeq[MinValue](0).newVal(i.scope) - info.qVal.add @["year".newSym, tinfo.year.newVal].newVal(i.scope) - info.qVal.add @["month".newSym, (tinfo.month.int+1).newVal].newVal(i.scope) - info.qVal.add @["day".newSym, tinfo.monthday.newVal].newVal(i.scope) - info.qVal.add @["weekday".newSym, (tinfo.weekday.int+1).newVal].newVal(i.scope) - info.qVal.add @["yearday".newSym, tinfo.yearday.newVal].newVal(i.scope) - info.qVal.add @["hour".newSym, tinfo.hour.newVal].newVal(i.scope) - info.qVal.add @["minute".newSym, tinfo.minute.newVal].newVal(i.scope) - info.qVal.add @["second".newSym, tinfo.second.newVal].newVal(i.scope) - info.qVal.add @["dst".newSym, tinfo.isDST.newVal].newVal(i.scope) - info.qVal.add @["timezone".newSym, tinfo.timezone.newVal].newVal(i.scope) + info.qVal.add @["year".newVal, tinfo.year.newVal].newVal(i.scope) + info.qVal.add @["month".newVal, (tinfo.month.int+1).newVal].newVal(i.scope) + info.qVal.add @["day".newVal, tinfo.monthday.newVal].newVal(i.scope) + info.qVal.add @["weekday".newVal, (tinfo.weekday.int+1).newVal].newVal(i.scope) + info.qVal.add @["yearday".newVal, tinfo.yearday.newVal].newVal(i.scope) + info.qVal.add @["hour".newVal, tinfo.hour.newVal].newVal(i.scope) + info.qVal.add @["minute".newVal, tinfo.minute.newVal].newVal(i.scope) + info.qVal.add @["second".newVal, tinfo.second.newVal].newVal(i.scope) + info.qVal.add @["dst".newVal, tinfo.isDST.newVal].newVal(i.scope) + info.qVal.add @["timezone".newVal, tinfo.timezone.newVal].newVal(i.scope) i.push info def.symbol("to-timestamp") do (i: In):
M tests/lang.mintests/lang.min

@@ -99,7 +99,7 @@ 2 a1 ==) assert

( ( - (((error "TestError")(message "Test Message")) raise) + ((("error" "TestError")("message" "Test Message")) raise) ('error dget) ) try "TestError" ==) assert

@@ -114,7 +114,7 @@ ) try 1 ==) assert

((a b +) (4 :a 5 :b) with 9 ==) assert - ("{\"a\": 1, \"b\": 2.3}" from-json ((a 1) (b 2.3)) ==) assert + ("{\"a\": 1, \"b\": 2.3}" from-json (("a" 1) ("b" 2.3)) ==) assert ((1 2 3 "aaa" 'q q true) to-json "\r\n" "" replace "\n" "" replace " " "" replace "[1,2,3,\"aaa\",\";sym:'q\",\";sym:q\",true]" ==) assert

@@ -175,11 +175,11 @@

("3.678" float 3.678 ==) assert ( - ((a 1) (b 2) (c 3)) ( + (("a" 1) ("b" 2) ("c" 3)) ( (dup /a succ succ %a) (dup /b succ %b) ) tap - ((a 3) (b 3) (c 3)) == + (("a" 3) ("b" 3) ("c" 3)) == ) assert (
M tests/seq.mintests/seq.min

@@ -31,17 +31,17 @@ ((1 2 3 4) (2 +) map (3 4 5 6) ==) assert

((5 4 3 2 1) reverse (1 2 3 4 5) ==) assert - (((a 1)(b 2)(c 3)) dictionary?) assert + ((("a" 1)("b" 2)("c" 3)) dictionary?) assert - (((a 1)(b 2)(c 3)) 'b dget 2 ==) assert + ((("a" 1)("b" 2)("c" 3)) 'b dget 2 ==) assert - (((a 1)(b 2)(c 3)) ' :dict dict 5 'b dset 7 %d =newdict newdict ((a 1)(b 5)(c 3)(d 7)) == dict ((a 1)(b 2)(c 3)) == and) assert + ((("a" 1)("b" 2)("c" 3)) ' :dict dict 5 'b dset 7 %d =newdict newdict (("a" 1)("b" 5)("c" 3)("d" 7)) == dict (("a" 1)("b" 2)("c" 3)) == and) assert - (((a 1)(b 2)(c 3)) ' :dict dict 'b ddel =newdict newdict ((a 1)(c 3)) == dict ((a 1)(b 2)(c 3)) == and) assert + ((("a" 1)("b" 2)("c" 3)) ' :dict dict 'b ddel =newdict newdict (("a" 1)("c" 3)) == dict (("a" 1)("b" 2)("c" 3)) == and) assert - (((a 1)(b 2)(c 3)) keys ("a" "b" "c") ==) assert + ((("a" 1)("b" 2)("c" 3)) keys ("a" "b" "c") ==) assert - (((a 1)(b 2)(c 3)) values (1 2 3) ==) assert + ((("a" 1)("b" 2)("c" 3)) values (1 2 3) ==) assert ((3 4 7 2 4 6 5 6) '> sort (2 3 4 4 5 6 6 7) ==) assert