all repos — min @ ae02e777f4e7534ac536d965b902f22893f9aef6

A small but practical concatenative programming language.

refactor(validation) Added string validations.
h3rald h3rald@h3rald.com
Sat, 04 Jun 2016 23:13:13 +0200
commit

ae02e777f4e7534ac536d965b902f22893f9aef6

parent

854dc391e4724d549431001635e1523d8e42a672

5 files changed, 147 insertions(+), 211 deletions(-)

jump to
M core/utils.nimcore/utils.nim

@@ -91,16 +91,39 @@ shallowCopy varname, value

# Validators +proc reqInt*(i: var MinInterpreter, a: var MinValue) = + a = i.pop + if not a.isInt: + raise MinInvalidError(msg: "An integer is required on the stack") + proc reqQuotation*(i: var MinInterpreter, a: var MinValue) = a = i.pop if not a.isQuotation: raise MinInvalidError(msg: "A quotation is required on the stack") +proc reqString*(i: var MinInterpreter, a: var MinValue) = + a = i.pop + if not a.isString: + raise MinInvalidError(msg: "A string is required on the stack") + proc reqStringOrQuotation*(i: var MinInterpreter, a: var MinValue) = a = i.pop - if not a.isQuotation or not a.isString: + if not a.isQuotation and not a.isString: raise MinInvalidError(msg: "A quotation or a string is required on the stack") +proc reqTwoStrings*(i: var MinInterpreter, a, b: var MinValue) = + a = i.pop + b = i.pop + if not a.isString or not b.isString: + raise MinInvalidError(msg: "Two strings are required on the stack") + +proc reqThreeStrings*(i: var MinInterpreter, a, b, c: var MinValue) = + a = i.pop + b = i.pop + c = i.pop + if not a.isString or not b.isString or not c.isString: + raise MinInvalidError(msg: "Three strings are required on the stack") + proc reqTwoQuotations*(i: var MinInterpreter, a, b: var MinValue) = a = i.pop b = i.pop

@@ -112,7 +135,7 @@ a = i.pop

b = i.pop c = i.pop if not a.isQuotation or not b.isQuotation or not c.isQuotation: - raise MinInvalidError(msg: "Four quotations are required on the stack") + raise MinInvalidError(msg: "Three quotations are required on the stack") proc reqFourQuotations*(i: var MinInterpreter, a, b, c, d: var MinValue) = a = i.pop
M lib/io.nimlib/io.nim

@@ -25,42 +25,34 @@ let a = i.peek

a.print .symbol("fread") do (i: In): - let a = i.pop - if a.isString: - if a.strVal.fileExists: - try: - i.push newVal(a.strVal.readFile) - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error errRuntime, "File '$1' not found" % [a.strVal] - else: - i.error(errIncorrect, "A string is required on the stack") - - .symbol("fwrite") do (i: In): - let a = i.pop - let b = i.pop - if a.isString and b.isString: + var a: MinValue + i.reqString a + if a.strVal.fileExists: try: - a.strVal.writeFile(b.strVal) + i.push newVal(a.strVal.readFile) except: i.error errRuntime, getCurrentExceptionMsg() else: - i.error(errIncorrect, "Two strings are required on the stack") + i.error errRuntime, "File '$1' not found" % [a.strVal] + + .symbol("fwrite") do (i: In): + var a, b: MinValue + i.reqTwoStrings a, b + try: + a.strVal.writeFile(b.strVal) + except: + i.error errRuntime, getCurrentExceptionMsg() .symbol("fappend") do (i: In): - let a = i.pop - let b = i.pop - if a.isString and b.isString: - try: - var f:File - discard f.open(a.strVal, fmAppend) - f.write(b.strVal) - f.close() - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error(errIncorrect, "Two strings are required on the stack") + var a, b: MinValue + i.reqTwoStrings a, b + try: + var f:File + discard f.open(a.strVal, fmAppend) + f.write(b.strVal) + f.close() + except: + i.error errRuntime, getCurrentExceptionMsg() .finalize()
M lib/lang.nimlib/lang.nim

@@ -112,50 +112,39 @@ .sigil("'") do (i: In):

i.push(@[MinValue(kind: minSymbol, symVal: i.pop.strVal)].newVal) .symbol("sigil") do (i: In): - var q1 = i.pop - var q2 = i.pop - if q1.isString: - q1 = @[q1].newVal - if q1.isQuotation and q2.isQuotation: - if q1.qVal.len == 1 and q1.qVal[0].kind == minSymbol: - var symbol = q1.qVal[0].symVal - if symbol.len == 1: - if i.scope.getSigil(symbol).isNotNil: - i.error errSystem, "Sigil '$1' already exists" % [symbol] - return - i.scope.sigils[symbol] = proc(i: In) = - i.evaluating = true - i.push q2.qVal - i.evaluating = false - else: - i.error errIncorrect, "A sigil can only have one character" + var q1, q2: MinValue + i.reqTwoQuotations q1, q2 + if q1.qVal.len == 1 and q1.qVal[0].kind == minSymbol: + var symbol = q1.qVal[0].symVal + if symbol.len == 1: + if i.scope.getSigil(symbol).isNotNil: + i.error errSystem, "Sigil '$1' already exists" % [symbol] + return + i.scope.sigils[symbol] = proc(i: In) = + i.evaluating = true + i.push q2.qVal + i.evaluating = false else: - i.error errIncorrect, "The top quotation must contain only one symbol value" + i.error errIncorrect, "A sigil can only have one character" else: - i.error errIncorrect, "Two quotations are required on the stack" + i.error errIncorrect, "The top quotation must contain only one symbol value" .symbol("eval") do (i: In): - let s = i.pop - if s.isString: - i.eval s.strVal - else: - i.error(errIncorrect, "A string is required on the stack") + var s: MinValue + i.reqString s + i.eval s.strVal .symbol("load") do (i: In): - let s = i.pop - if s.isString: - var file = s.strVal - if not file.endsWith(".min"): - file = file & ".min" - i.load i.pwd.joinPath(file) - else: - i.error(errIncorrect, "A string is required on the stack") + var s: MinValue + i.reqString s + var file = s.strVal + if not file.endsWith(".min"): + file = file & ".min" + i.load i.pwd.joinPath(file) .symbol("call") do (i: In): - let symbols = i.pop - var target = i.pop - if not symbols.isQuotation or not target.isQuotation: - i.error errIncorrect, "Two quotations are required on the stack" + var symbols, target: MinValue + i.reqTwoQuotations symbols, target let vals = symbols.qVal var q: MinValue if vals.len == 0:
M lib/str.nimlib/str.nim

@@ -9,59 +9,42 @@

define("str") .symbol("split") do (i: In): - let sep = i.pop - let s = i.pop + var sep, s: MinValue + i.reqTwoStrings sep, s var q = newSeq[MinValue](0) - if s.isString and sep.isString: - for e in s.strVal.split(sep.strVal): - q.add e.newVal - i.push q.newVal - else: - i.error errIncorrect, "Two strings are required on the stack" + for e in s.strVal.split(sep.strVal): + q.add e.newVal + i.push q.newVal .symbol("search") do (i: In): - let reg = i.pop - let str = i.pop - if str.isString and reg.isString: - var matches = str.strVal.search(reg.strVal) - var res = newSeq[MinValue](matches.len) - for i in 0..matches.len-1: - res[i] = matches[i].newVal - i.push res.newVal - else: - i.error(errIncorrect, "Two strings are required on the stack") + var reg, str: MinValue + i.reqTwoStrings reg, str + var matches = str.strVal.search(reg.strVal) + var res = newSeq[MinValue](matches.len) + for i in 0..matches.len-1: + res[i] = matches[i].newVal + i.push res.newVal .symbol("match") do (i: In): - let reg = i.pop - let str = i.pop - if str.isString and reg.isString: - if str.strVal.match(reg.strVal): - i.push true.newVal - else: - i.push false.newVal + var reg, str: MinValue + i.reqTwoStrings reg, str + if str.strVal.match(reg.strVal): + i.push true.newVal else: - i.error(errIncorrect, "Two strings are required on the stack") + i.push false.newVal .symbol("replace") do (i: In): - let s_replace = i.pop - let reg = i.pop - let s_find = i.pop - if reg.isString and s_replace.isString and s_find.isString: - i.push regex.replace(s_find.strVal, reg.strVal, s_replace.strVal).newVal - else: - i.error(errIncorrect, "Three strings are required on the stack") + var s_replace, reg, s_find: MinValue + i.reqThreeStrings s_replace, reg, s_find + i.push regex.replace(s_find.strVal, reg.strVal, s_replace.strVal).newVal .symbol("=~") do (i: In): - let reg = i.pop - let str = i.pop - if str.isString and reg.isString: - let results = str.strVal =~ reg.strVal - var res = newSeq[MinValue](0) - for r in results: - res.add(r.newVal) - i.push res.newVal - else: - i.error(errIncorrect, "Two strings are required on the stack") - + var reg, str: MinValue + i.reqTwoStrings reg, str + let results = str.strVal =~ reg.strVal + var res = newSeq[MinValue](0) + for r in results: + res.add(r.newVal) + i.push res.newVal .finalize()
M lib/sys.nimlib/sys.nim

@@ -13,61 +13,42 @@ .symbol("pwd") do (i: In):

i.push newVal(getCurrentDir()) .symbol("cd") do (i: In): - let f = i.pop - if f.isString: - try: - f.strVal.setCurrentDir - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" + var f: MinValue + i.reqString f + f.strVal.setCurrentDir .symbol("ls") do (i: In): - let a = i.pop + var a: MinValue + i.reqString a var list = newSeq[MinValue](0) - if a.isString: - if a.strVal.existsDir: - for i in walkdir(a.strVal): - list.add newVal(i.path) - i.push list.newVal - else: - i.error errRuntime, "Directory '$1' not found" % [a.strVal] - else: - i.error(errIncorrect, "A string is required on the stack") + for i in walkdir(a.strVal): + list.add newVal(i.path) + i.push list.newVal .symbol("system") do (i: In): - let a = i.pop - if a.isString: - i.push execShellCmd(a.strVal).newVal - else: - i.error(errIncorrect, "A string is required on the stack") + var a: MinValue + i.reqString a + i.push execShellCmd(a.strVal).newVal .symbol("run") do (i: In): - let a = i.pop - if a.isString: - let words = a.strVal.split(" ") - let cmd = words[0] - var args = newSeq[string](0) - if words.len > 1: - args = words[1..words.len-1] - i.push execProcess(cmd, args, nil, {poUsePath}).newVal - else: - i.error(errIncorrect, "A string is required on the stack") + var a: MinValue + i.reqString a + let words = a.strVal.split(" ") + let cmd = words[0] + var args = newSeq[string](0) + if words.len > 1: + args = words[1..words.len-1] + i.push execProcess(cmd, args, nil, {poUsePath}).newVal .symbol("getenv") do (i: In): - let a = i.pop - if a.isString: - i.push a.strVal.getEnv.newVal - else: - i.error(errIncorrect, "A string is required on the stack") + var a: MinValue + i.reqString a + i.push a.strVal.getEnv.newVal .symbol("putenv") do (i: In): - let key = i.pop - let value = i.pop - if value.isString and key.isString: - key.strVal.putEnv value.strVal - else: - i.error(errIncorrect, "Two strings are required on the stack") + var key, value: MinValue + i.reqTwoStrings key, value + key.strVal.putEnv value.strVal .symbol("os") do (i: In): i.push hostOS.newVal

@@ -76,75 +57,43 @@ .symbol("cpu") do (i: In):

i.push hostCPU.newVal .symbol("file?") do (i: In): - let f = i.pop - if f.isString: - i.push f.strVal.fileExists.newVal - else: - i.error errIncorrect, "A string is required on the stack" + var f: MinValue + i.reqString f + i.push f.strVal.fileExists.newVal .symbol("dir?") do (i: In): - let f = i.pop - if f.isString: - i.push f.strVal.dirExists.newVal - else: - i.error errIncorrect, "A string is required on the stack" + var f: MinValue + i.reqString f + i.push f.strVal.dirExists.newVal .symbol("rm") do (i: In): - let f = i.pop - if f.isString: - try: - f.strVal.removeFile - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" + var f: MinValue + i.reqString f + f.strVal.removeFile .symbol("cp") do (i: In): - let b = i.pop - let a = i.pop - if a.isString and b.isString: - try: - copyFile a.strVal, b.strVal - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error errIncorrect, "Two strings are required on the stack" + var a, b: MinValue + i.reqTwoStrings a, b + copyFile b.strVal, a.strVal .symbol("mv") do (i: In): - let b = i.pop - let a = i.pop - if a.isString and b.isString: - try: - moveFile a.strVal, b.strVal - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error errIncorrect, "Two strings are required on the stack" + var a, b: MinValue + i.reqTwoStrings a, b + moveFile b.strVal, a.strVal .symbol("rmdir") do (i: In): - let f = i.pop - if f.isString: - try: - f.strVal.removeDir - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" + var f: MinValue + i.reqString f + f.strVal.removeDir .symbol("mkdir") do (i: In): - let f = i.pop - if f.isString: - try: - f.strVal.createDir - except: - i.error errRuntime, getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" + var f: MinValue + i.reqString f + f.strVal.createDir .symbol("sleep") do (i: In): - let ms = i.pop - if not ms.isInt: - i.error errIncorrect, "An integer is required on the stack" + var ms: MinValue + i.reqInt ms sleep ms.intVal .finalize()