all repos — min @ b6be71e4892cb35d73d42f933402456c080ac6fd

A small but practical concatenative programming language.

refactor(modules) Rewrote all libs as modules.
h3rald h3rald@h3rald.com
Sat, 21 May 2016 23:06:43 +0200
commit

b6be71e4892cb35d73d42f933402456c080ac6fd

parent

77d6d7fdbe07ff6f7c0b10961599e476d98560b8

M core/utils.nimcore/utils.nim

@@ -64,7 +64,8 @@ return scope

proc symbol*(scope: ref MinScope, sym: string, p: MinOperator): ref MinScope = scope.symbols[sym] = p - scope.previous.symbols[scope.name & ":" & sym] = p + if not scope.parent.isNil: + scope.parent.symbols[scope.name & ":" & sym] = p return scope proc sigil*(scope: ref MinScope, sym: string, p: MinOperator): ref MinScope =

@@ -78,12 +79,3 @@ mdl.scope.previous.symbols[scope.name] = proc(i: var MinInterpreter) =

i.evaluating = true i.push mdl i.evaluating = false - -template minsym*(name: string, i: expr, body: stmt): stmt {.immediate.} = - ROOT.symbols[name] = proc (i: var MinInterpreter) {.closure.} = - body - -template minsigil*(name: char, i: expr, body: stmt): stmt {.immediate.} = - ROOT.sigils[name] = proc (i: var MinInterpreter) = - body -
M lib/io.nimlib/io.nim

@@ -7,37 +7,42 @@ ../core/utils

# I/O -minsym "puts", i: - let a = i.peek - echo a + +define("io") + + .symbol("puts") do (i: In): + let a = i.peek + echo a + + .symbol("puts") do (i: In): + i.push newVal(stdin.readLine()) -minsym "gets", i: - i.push newVal(stdin.readLine()) + .symbol("print") do (i: In): + let a = i.peek + a.print -minsym "print", i: - let a = i.peek - a.print + .symbol("read") do (i: In): + let a = i.pop + if a.isString: + if a.strVal.fileExists: + try: + i.push newVal(a.strVal.readFile) + except: + warn getCurrentExceptionMsg() + else: + warn "File '$1' not found" % [a.strVal] + else: + i.error(errIncorrect, "A string is required on the stack") -minsym "read", i: - let a = i.pop - if a.isString: - if a.strVal.fileExists: + .symbol("write") do (i: In): + let a = i.pop + let b = i.pop + if a.isString and b.isString: try: - i.push newVal(a.strVal.readFile) + a.strVal.writeFile(b.strVal) except: warn getCurrentExceptionMsg() else: - warn "File '$1' not found" % [a.strVal] - else: - i.error(errIncorrect, "A string is required on the stack") + i.error(errIncorrect, "Two strings are required on the stack") -minsym "write", i: - let a = i.pop - let b = i.pop - if a.isString and b.isString: - try: - a.strVal.writeFile(b.strVal) - except: - warn getCurrentExceptionMsg() - else: - i.error(errIncorrect, "Two strings are required on the stack") + .finalize()
M lib/lang.nimlib/lang.nim

@@ -180,4 +180,113 @@ i.push newVal(q.strVal[1..q.strVal.len-1])

else: i.error(errIncorrect, "A quotation or a string is required on the stack") + .symbol("quote") do (i: In): + let a = i.pop + i.push MinValue(kind: minQuotation, qVal: @[a]) + + .symbol("unquote") do (i: In): + let q = i.pop + if not q.isQuotation: + i.error errNoQuotation + let scope = i.scope + i.scope = new MinScope + i.scope.parent = scope + for item in q.qVal: + i.push item + i.scope = scope + + .symbol("cons") do (i: In): + var q = i.pop + let v = i.pop + if not q.isQuotation: + i.error errNoQuotation + q.qVal.add v + i.push q + + .symbol("at") do (i: In): + var index = i.pop + var q = i.pop + if index.isInt and q.isQuotation: + i.push q.qVal[index.intVal] + else: + i.error errIncorrect, "An integer and a quotation are required on the stack" + + .symbol("map") do (i: In): + let prog = i.pop + let list = i.pop + if prog.isQuotation and list.isQuotation: + i.push newVal(newSeq[MinValue](0)) + for litem in list.qVal: + i.push litem + for pitem in prog.qVal: + i.push pitem + i.apply("swap") + i.apply("cons") + else: + i.error(errIncorrect, "Two quotations are required on the stack") + + .symbol("times") do (i: In): + let t = i.pop + let prog = i.pop + if t.isInt and prog.isQuotation: + for c in 1..t.intVal: + for pitem in prog.qVal: + i.push pitem + else: + i.error errIncorrect, "An integer and a quotation are required on the stack" + + .symbol("ifte") do (i: In): + let fpath = i.pop + let tpath = i.pop + let check = i.pop + var stack = i.copystack + if check.isQuotation and tpath.isQuotation and fpath.isQuotation: + i.push check.qVal + let res = i.pop + i.stack = stack + if res.isBool and res.boolVal == true: + i.push tpath.qVal + else: + i.push fpath.qVal + else: + i.error(errIncorrect, "Three quotations are required on the stack") + + .symbol("while") do (i: In): + let d = i.pop + let b = i.pop + if b.isQuotation and d.isQuotation: + i.push b.qVal + var check = i.pop + while check.isBool and check.boolVal == true: + i.push d.qVal + i.push b.qVal + check = i.pop + else: + i.error(errIncorrect, "Two quotations are required on the stack") + + .symbol("filter") do (i: In): + let filter = i.pop + let list = i.pop + var res = newSeq[MinValue](0) + if filter.isQuotation and list.isQuotation: + for e in list.qVal: + i.push e + i.push filter.qVal + var check = i.pop + if check.isBool and check.boolVal == true: + res.add e + i.push res.newVal + else: + i.error(errIncorrect, "Two quotations are required on the stack") + + .symbol("linrec") do (i: In): + var r2 = i.pop + var r1 = i.pop + var t = i.pop + var p = i.pop + if p.isQuotation and t.isQuotation and r1.isQuotation and r2.isQuotation: + i.linrec(p, t, r1, r2) + else: + i.error(errIncorrect, "Four quotations are required on the stack") + .finalize()
M lib/logic.nimlib/logic.nim

@@ -7,155 +7,159 @@ ../core/utils

# Comparison operators -minsym ">", i: - let n2 = i.pop - let n1 = i.pop - if n1.isNumber and n2.isNumber: - if n1.isInt and n2.isInt: - i.push newVal(n1.intVal > n2.intVal) - elif n1.isInt and n2.isFloat: - i.push newVal(n1.intVal.float > n2.floatVal) - elif n1.isFloat and n2.isFloat: - i.push newVal(n1.floatVal > n2.floatVal) - elif n1.isFloat and n2.isInt: - i.push newVal(n1.floatVal > n2.intVal.float) - elif n1.isString and n2.isString: - i.push newVal(n1.strVal > n2.strVal) - else: - i.error(errIncorrect, "Two numbers or two strings are required on the stack") - -minsym ">=", i: - let n2 = i.pop - let n1 = i.pop - if n1.isNumber and n2.isNumber: - if n1.isInt and n2.isInt: - i.push newVal(n1.intVal >= n2.intVal) - elif n1.isInt and n2.isFloat: - i.push newVal(n1.intVal.float >= n2.floatVal) - elif n1.isFloat and n2.isFloat: - i.push newVal(n1.floatVal >= n2.floatVal) - elif n1.isFloat and n2.isInt: - i.push newVal(n1.floatVal >= n2.intVal.float) - elif n1.isString and n2.isString: - i.push newVal(n1.strVal >= n2.strVal) - else: - i.error(errIncorrect, "Two numbers or two strings are required on the stack") - -minsym "<", i: - let n1 = i.pop - let n2 = i.pop - if n1.isNumber and n2.isNumber: - if n1.isInt and n2.isInt: - i.push newVal(n1.intVal > n2.intVal) - elif n1.isInt and n2.isFloat: - i.push newVal(n1.intVal.float > n2.floatVal) - elif n1.isFloat and n2.isFloat: - i.push newVal(n1.floatVal > n2.floatVal) - elif n1.isFloat and n2.isInt: - i.push newVal(n1.floatVal > n2.intVal.float) - elif n1.isString and n2.isString: - i.push newVal(n1.strVal > n2.strVal) - else: - i.error(errIncorrect, "Two numbers or two strings are required on the stack") +define("logic") -minsym "<=", i: - let n1 = i.pop - let n2 = i.pop - if n1.isNumber and n2.isNumber: - if n1.isInt and n2.isInt: - i.push newVal(n1.intVal >= n2.intVal) - elif n1.isInt and n2.isFloat: - i.push newVal(n1.intVal.float >= n2.floatVal) - elif n1.isFloat and n2.isFloat: - i.push newVal(n1.floatVal >= n2.floatVal) - elif n1.isFloat and n2.isInt: - i.push newVal(n1.floatVal >= n2.intVal.float) - elif n1.isString and n2.isString: - i.push newVal(n1.strVal >= n2.strVal) - else: - i.error(errIncorrect, "Two numbers or two strings are required on the stack") - -minsym "==", i: - let n2 = i.pop - let n1 = i.pop - if (n1.kind == n2.kind or (n1.isNumber and n2.isNumber)) and not n1.isSymbol: - i.push newVal(n1 == n2) - else: - i.error(errIncorrect, "Two non-symbol values of similar type are required") - -minsym "!=", i: - let n2 = i.pop - let n1 = i.pop - if (n1.kind == n2.kind or (n1.isNumber and n2.isNumber)) and not n1.isSymbol: - i.push newVal(not (n1 == n2)) - else: - i.error(errIncorrect, "Two non-symbol values of similar type are required") - -# Boolean Logic - -minsym "not", i: - let b = i.pop - if b.isBool: - i.push newVal(not b.boolVal) - else: - i.error(errIncorrect, "A bool value is required on the stack") - -minsym "and", i: - let a = i.pop - let b = i.pop - if a.isBool and b.isBool: - i.push newVal(a.boolVal and b.boolVal) - else: - i.error(errIncorrect, "Two bool values are required on the stack") - -minsym "or", i: - let a = i.pop - let b = i.pop - if a.isBool and b.isBool: - i.push newVal(a.boolVal or b.boolVal) - else: - i.error(errIncorrect, "Two bool values are required on the stack") - -minsym "xor", i: - let a = i.pop - let b = i.pop - if a.isBool and b.isBool: - i.push newVal(a.boolVal xor b.boolVal) - else: - i.error(errIncorrect, "Two bool values are required on the stack") - -minsym "string?", i: - if i.peek.kind == minString: - i.push true.newVal - else: - i.push false.newVal - -minsym "int?", i: - if i.peek.kind == minInt: - i.push true.newVal - else: - i.push false.newVal - -minsym "float?", i: - if i.peek.kind == minFloat: - i.push true.newVal - else: - i.push false.newVal - -minsym "number?", i: - if i.peek.kind == minFloat or i.peek.kind == minInt: - i.push true.newVal - else: - i.push false.newVal + .symbol(">") do (i: In): + let n2 = i.pop + let n1 = i.pop + if n1.isNumber and n2.isNumber: + if n1.isInt and n2.isInt: + i.push newVal(n1.intVal > n2.intVal) + elif n1.isInt and n2.isFloat: + i.push newVal(n1.intVal.float > n2.floatVal) + elif n1.isFloat and n2.isFloat: + i.push newVal(n1.floatVal > n2.floatVal) + elif n1.isFloat and n2.isInt: + i.push newVal(n1.floatVal > n2.intVal.float) + elif n1.isString and n2.isString: + i.push newVal(n1.strVal > n2.strVal) + else: + i.error(errIncorrect, "Two numbers or two strings are required on the stack") -minsym "bool?", i: - if i.peek.kind == minBool: - i.push true.newVal - else: - i.push false.newVal + .symbol(">=") do (i: In): + let n2 = i.pop + let n1 = i.pop + if n1.isNumber and n2.isNumber: + if n1.isInt and n2.isInt: + i.push newVal(n1.intVal >= n2.intVal) + elif n1.isInt and n2.isFloat: + i.push newVal(n1.intVal.float >= n2.floatVal) + elif n1.isFloat and n2.isFloat: + i.push newVal(n1.floatVal >= n2.floatVal) + elif n1.isFloat and n2.isInt: + i.push newVal(n1.floatVal >= n2.intVal.float) + elif n1.isString and n2.isString: + i.push newVal(n1.strVal >= n2.strVal) + else: + i.error(errIncorrect, "Two numbers or two strings are required on the stack") + + .symbol("<") do (i: In): + let n1 = i.pop + let n2 = i.pop + if n1.isNumber and n2.isNumber: + if n1.isInt and n2.isInt: + i.push newVal(n1.intVal > n2.intVal) + elif n1.isInt and n2.isFloat: + i.push newVal(n1.intVal.float > n2.floatVal) + elif n1.isFloat and n2.isFloat: + i.push newVal(n1.floatVal > n2.floatVal) + elif n1.isFloat and n2.isInt: + i.push newVal(n1.floatVal > n2.intVal.float) + elif n1.isString and n2.isString: + i.push newVal(n1.strVal > n2.strVal) + else: + i.error(errIncorrect, "Two numbers or two strings are required on the stack") + + .symbol("<=") do (i: In): + let n1 = i.pop + let n2 = i.pop + if n1.isNumber and n2.isNumber: + if n1.isInt and n2.isInt: + i.push newVal(n1.intVal >= n2.intVal) + elif n1.isInt and n2.isFloat: + i.push newVal(n1.intVal.float >= n2.floatVal) + elif n1.isFloat and n2.isFloat: + i.push newVal(n1.floatVal >= n2.floatVal) + elif n1.isFloat and n2.isInt: + i.push newVal(n1.floatVal >= n2.intVal.float) + elif n1.isString and n2.isString: + i.push newVal(n1.strVal >= n2.strVal) + else: + i.error(errIncorrect, "Two numbers or two strings are required on the stack") + + .symbol("==") do (i: In): + let n2 = i.pop + let n1 = i.pop + if (n1.kind == n2.kind or (n1.isNumber and n2.isNumber)) and not n1.isSymbol: + i.push newVal(n1 == n2) + else: + i.error(errIncorrect, "Two non-symbol values of similar type are required") + + .symbol("!=") do (i: In): + let n2 = i.pop + let n1 = i.pop + if (n1.kind == n2.kind or (n1.isNumber and n2.isNumber)) and not n1.isSymbol: + i.push newVal(not (n1 == n2)) + else: + i.error(errIncorrect, "Two non-symbol values of similar type are required") + + # Boolean Logic + + .symbol("not") do (i: In): + let b = i.pop + if b.isBool: + i.push newVal(not b.boolVal) + else: + i.error(errIncorrect, "A bool value is required on the stack") + + .symbol("and") do (i: In): + let a = i.pop + let b = i.pop + if a.isBool and b.isBool: + i.push newVal(a.boolVal and b.boolVal) + else: + i.error(errIncorrect, "Two bool values are required on the stack") + + .symbol("or") do (i: In): + let a = i.pop + let b = i.pop + if a.isBool and b.isBool: + i.push newVal(a.boolVal or b.boolVal) + else: + i.error(errIncorrect, "Two bool values are required on the stack") + + .symbol("xor") do (i: In): + let a = i.pop + let b = i.pop + if a.isBool and b.isBool: + i.push newVal(a.boolVal xor b.boolVal) + else: + i.error(errIncorrect, "Two bool values are required on the stack") + + .symbol("string?") do (i: In): + if i.peek.kind == minString: + i.push true.newVal + else: + i.push false.newVal + + .symbol("int?") do (i: In): + if i.peek.kind == minInt: + i.push true.newVal + else: + i.push false.newVal + + .symbol("float?") do (i: In): + if i.peek.kind == minFloat: + i.push true.newVal + else: + i.push false.newVal + + .symbol("number?") do (i: In): + if i.peek.kind == minFloat or i.peek.kind == minInt: + i.push true.newVal + else: + i.push false.newVal + + .symbol("bool?") do (i: In): + if i.peek.kind == minBool: + i.push true.newVal + else: + i.push false.newVal + + .symbol("quotation?") do (i: In): + if i.peek.kind == minQuotation: + i.push true.newVal + else: + i.push false.newVal -minsym "quotation?", i: - if i.peek.kind == minQuotation: - i.push true.newVal - else: - i.push false.newVal + .finalize()
M lib/num.nimlib/num.nim

@@ -5,95 +5,98 @@ ../core/parser,

../core/interpreter, ../core/utils -# Arithmetic + # Arithmetic + +define("num") -minsym "+", i: - let a = i.pop - let b = i.pop - if a.isInt: - if b.isInt: - i.push newVal(a.intVal + b.intVal) - elif b.isFloat: - i.push newVal(a.intVal.float + b.floatVal) + .symbol("+") do (i: In): + let a = i.pop + let b = i.pop + if a.isInt: + if b.isInt: + i.push newVal(a.intVal + b.intVal) + elif b.isFloat: + i.push newVal(a.intVal.float + b.floatVal) + else: + i.error(errTwoNumbersRequired) + elif a.isFloat: + if b.isFloat: + i.push newVal(a.floatVal + b.floatVal) + elif b.isInt: + i.push newVal(a.floatVal + b.intVal.float) + else: + i.error(errTwoNumbersRequired) + + .symbol("-") do (i: In): + let a = i.pop + let b = i.pop + if a.isInt: + if b.isInt: + i.push newVal(b.intVal - a.intVal) + elif b.isFloat: + i.push newVal(b.floatVal - a.intVal.float) + else: + i.error(errTwoNumbersRequired) + elif a.isFloat: + if b.isFloat: + i.push newVal(b.floatVal - a.floatVal) + elif b.isInt: + i.push newVal(b.intVal.float - a.floatVal) + else: + i.error(errTwoNumbersRequired) + + .symbol("*") do (i: In): + let a = i.pop + let b = i.pop + if a.isInt: + if b.isInt: + i.push newVal(a.intVal * b.intVal) + elif b.isFloat: + i.push newVal(a.intVal.float * b.floatVal) + else: + i.error(errTwoNumbersRequired) + elif a.isFloat: + if b.isFloat: + i.push newVal(a.floatVal * b.floatVal) + elif b.isInt: + i.push newVal(a.floatVal * b.intVal.float) + else: + i.error(errTwoNumbersRequired) + + .symbol("/") do (i: In): + let a = i.pop + let b = i.pop + if b.isInt and b.intVal == 0: + i.error errDivisionByZero + if a.isInt: + if b.isInt: + i.push newVal(b.intVal / a.intVal) + elif b.isFloat: + i.push newVal(b.floatVal / a.intVal.float) + else: + i.error(errTwoNumbersRequired) + elif a.isFloat: + if b.isFloat: + i.push newVal(b.floatVal / a.floatVal) + elif b.isInt: + i.push newVal(b.intVal.float / a.floatVal) + else: + i.error(errTwoNumbersRequired) + + .symbol("div") do (i: In): + let b = i.pop + let a = i.pop + if a.isInt and b.isInt: + i.push(newVal(a.intVal div b.intVal)) else: - i.error(errTwoNumbersRequired) - elif a.isFloat: - if b.isFloat: - i.push newVal(a.floatVal + b.floatVal) - elif b.isInt: - i.push newVal(a.floatVal + b.intVal.float) - else: - i.error(errTwoNumbersRequired) - -minsym "-", i: - let a = i.pop - let b = i.pop - if a.isInt: - if b.isInt: - i.push newVal(b.intVal - a.intVal) - elif b.isFloat: - i.push newVal(b.floatVal - a.intVal.float) - else: - i.error(errTwoNumbersRequired) - elif a.isFloat: - if b.isFloat: - i.push newVal(b.floatVal - a.floatVal) - elif b.isInt: - i.push newVal(b.intVal.float - a.floatVal) - else: - i.error(errTwoNumbersRequired) - -minsym "*", i: - let a = i.pop - let b = i.pop - if a.isInt: - if b.isInt: - i.push newVal(a.intVal * b.intVal) - elif b.isFloat: - i.push newVal(a.intVal.float * b.floatVal) - else: - i.error(errTwoNumbersRequired) - elif a.isFloat: - if b.isFloat: - i.push newVal(a.floatVal * b.floatVal) - elif b.isInt: - i.push newVal(a.floatVal * b.intVal.float) - else: - i.error(errTwoNumbersRequired) - -minsym "/", i: - let a = i.pop - let b = i.pop - if b.isInt and b.intVal == 0: - i.error errDivisionByZero - if a.isInt: - if b.isInt: - i.push newVal(b.intVal / a.intVal) - elif b.isFloat: - i.push newVal(b.floatVal / a.intVal.float) + i.error errIncorrect, "Two integers are required on the stack" + + .symbol("mod") do (i: In): + let b = i.pop + let a = i.pop + if a.isInt and b.isInt: + i.push(newVal(a.intVal mod b.intVal)) else: - i.error(errTwoNumbersRequired) - elif a.isFloat: - if b.isFloat: - i.push newVal(b.floatVal / a.floatVal) - elif b.isInt: - i.push newVal(b.intVal.float / a.floatVal) - else: - i.error(errTwoNumbersRequired) - -minsym "div", i: - let b = i.pop - let a = i.pop - if a.isInt and b.isInt: - i.push(newVal(a.intVal div b.intVal)) - else: - i.error errIncorrect, "Two integers are required on the stack" - -minsym "mod", i: - let b = i.pop - let a = i.pop - if a.isInt and b.isInt: - i.push(newVal(a.intVal mod b.intVal)) - else: - i.error errIncorrect, "Two integers are required on the stack" - + i.error errIncorrect, "Two integers are required on the stack" + + .finalize()
M lib/prelude.minlib/prelude.min

@@ -2,6 +2,12 @@ (import) (#) sigil

// Imports #str +#io +#logic +#num +#stack +#sys +#time // Common sigils (set) (:) sigil
D lib/q.nim

@@ -1,118 +0,0 @@

-import tables -import - ../core/types, - ../core/parser, - ../core/interpreter, - ../core/utils - -# Operations on quotations - -minsym "quote", i: - let a = i.pop - i.push MinValue(kind: minQuotation, qVal: @[a]) - -minsym "unquote", i: - let q = i.pop - if not q.isQuotation: - i.error errNoQuotation - let scope = i.scope - i.scope = new MinScope - i.scope.parent = scope - for item in q.qVal: - i.push item - i.scope = scope - -minsym "cons", i: - var q = i.pop - let v = i.pop - if not q.isQuotation: - i.error errNoQuotation - q.qVal.add v - i.push q - -minsym "at", i: - var index = i.pop - var q = i.pop - if index.isInt and q.isQuotation: - i.push q.qVal[index.intVal] - else: - i.error errIncorrect, "An integer and a quotation are required on the stack" - -minsym "map", i: - let prog = i.pop - let list = i.pop - if prog.isQuotation and list.isQuotation: - i.push newVal(newSeq[MinValue](0)) - for litem in list.qVal: - i.push litem - for pitem in prog.qVal: - i.push pitem - i.apply("swap") - i.apply("cons") - else: - i.error(errIncorrect, "Two quotations are required on the stack") - -minsym "times", i: - let t = i.pop - let prog = i.pop - if t.isInt and prog.isQuotation: - for c in 1..t.intVal: - for pitem in prog.qVal: - i.push pitem - else: - i.error errIncorrect, "An integer and a quotation are required on the stack" - -minsym "ifte", i: - let fpath = i.pop - let tpath = i.pop - let check = i.pop - var stack = i.copystack - if check.isQuotation and tpath.isQuotation and fpath.isQuotation: - i.push check.qVal - let res = i.pop - i.stack = stack - if res.isBool and res.boolVal == true: - i.push tpath.qVal - else: - i.push fpath.qVal - else: - i.error(errIncorrect, "Three quotations are required on the stack") - -minsym "while", i: - let d = i.pop - let b = i.pop - if b.isQuotation and d.isQuotation: - i.push b.qVal - var check = i.pop - while check.isBool and check.boolVal == true: - i.push d.qVal - i.push b.qVal - check = i.pop - else: - i.error(errIncorrect, "Two quotations are required on the stack") - -minsym "filter", i: - let filter = i.pop - let list = i.pop - var res = newSeq[MinValue](0) - if filter.isQuotation and list.isQuotation: - for e in list.qVal: - i.push e - i.push filter.qVal - var check = i.pop - if check.isBool and check.boolVal == true: - res.add e - i.push res.newVal - else: - i.error(errIncorrect, "Two quotations are required on the stack") - -minsym "linrec", i: - var r2 = i.pop - var r1 = i.pop - var t = i.pop - var p = i.pop - if p.isQuotation and t.isQuotation and r1.isQuotation and r2.isQuotation: - i.linrec(p, t, r1, r2) - else: - i.error(errIncorrect, "Four quotations are required on the stack") -
M lib/stack.nimlib/stack.nim

@@ -5,39 +5,43 @@ ../core/parser,

../core/interpreter, ../core/utils -# Common stack operations - -minsym "id", i: - discard - -minsym "pop", i: - discard i.pop - -minsym "dup", i: - i.push i.peek + # Common stack operations + +define("stack") -minsym "dip", i: - let q = i.pop - if not q.isQuotation: - i.error errNoQuotation - let v = i.pop - for item in q.qVal: - i.push item - i.push v - -minsym "swap", i: - let a = i.pop - let b = i.pop - i.push a - i.push b - -minsym "sip", i: - let a = i.pop - let b = i.pop - if a.isQuotation and b.isQuotation: - i.push b - i.push a.qVal + .symbol("id") do (i: In): + discard + + .symbol("pop") do (i: In): + discard i.pop + + .symbol("dup") do (i: In): + i.push i.peek + + .symbol("dip") do (i: In): + let q = i.pop + if not q.isQuotation: + i.error errNoQuotation + let v = i.pop + for item in q.qVal: + i.push item + i.push v + + .symbol("swap") do (i: In): + let a = i.pop + let b = i.pop + i.push a i.push b - else: - i.error(errIncorrect, "Two quotations are required on the stack") + + .symbol("sip") do (i: In): + let a = i.pop + let b = i.pop + if a.isQuotation and b.isQuotation: + i.push b + i.push a.qVal + i.push b + else: + i.error(errIncorrect, "Two quotations are required on the stack") + .finalize() +
M lib/sys.nimlib/sys.nim

@@ -5,136 +5,140 @@ ../core/parser,

../core/interpreter, ../core/utils -# OS + # OS + +define("sys") -minsym "pwd", i: - i.push newVal(getCurrentDir()) - -minsym "cd", i: - let f = i.pop - if f.isString: - try: - f.strVal.setCurrentDir - except: - warn getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" - -minsym "ls", i: - let a = i.pop - 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 + .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: + warn getCurrentExceptionMsg() else: - warn "Directory '$1' not found" % [a.strVal] - else: - i.error(errIncorrect, "A string is required on the stack") - -minsym "system", i: - let a = i.pop - if a.isString: - i.push execShellCmd(a.strVal).newVal - else: - i.error(errIncorrect, "A string is required on the stack") - -minsym "run", i: - 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") - -minsym "getenv", i: - let a = i.pop - if a.isString: - i.push a.strVal.getEnv.newVal - else: - i.error(errIncorrect, "A string is required on the stack") - -minsym "putenv", i: - let value = i.pop - let key = i.pop - if value.isString and key.isString: - key.strVal.putEnv value.strVal - else: - i.error(errIncorrect, "Two strings are required on the stack") - -minsym "os", i: - i.push hostOS.newVal - -minsym "cpu", i: - i.push hostCPU.newVal - -minsym "file?", i: - let f = i.pop - if f.isString: - i.push f.strVal.fileExists.newVal - else: - i.error errIncorrect, "A string is required on the stack" - -minsym "dir?", i: - let f = i.pop - if f.isString: - i.push f.strVal.dirExists.newVal - else: - i.error errIncorrect, "A string is required on the stack" - -minsym "rm", i: - let f = i.pop - if f.isString: - try: - f.strVal.removeFile - except: - warn getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" - -minsym "cp", i: - let b = i.pop - let a = i.pop - if a.isString and b.isString: - try: - copyFile a.strVal, b.strVal - except: - warn getCurrentExceptionMsg() - else: - i.error errIncorrect, "Two strings are required on the stack" - -minsym "mv", i: - let b = i.pop - let a = i.pop - if a.isString and b.isString: - try: - moveFile a.strVal, b.strVal - except: - warn getCurrentExceptionMsg() - else: - i.error errIncorrect, "Two strings are required on the stack" - -minsym "rmdir", i: - let f = i.pop - if f.isString: - try: - f.strVal.removeDir - except: - warn getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" + i.error errIncorrect, "A string is required on the stack" + + .symbol("ls") do (i: In): + let a = i.pop + 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: + warn "Directory '$1' not found" % [a.strVal] + else: + i.error(errIncorrect, "A string is required on the stack") + + .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") + + .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") + + .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") + + .symbol("putenv") do (i: In): + let value = i.pop + let key = i.pop + if value.isString and key.isString: + key.strVal.putEnv value.strVal + else: + i.error(errIncorrect, "Two strings are required on the stack") + + .symbol("os") do (i: In): + i.push hostOS.newVal + + .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" + + .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" + + .symbol("rm") do (i: In): + let f = i.pop + if f.isString: + try: + f.strVal.removeFile + except: + warn getCurrentExceptionMsg() + else: + i.error errIncorrect, "A string is required on the stack" + + .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: + warn getCurrentExceptionMsg() + else: + i.error errIncorrect, "Two strings are required on the stack" + + .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: + warn getCurrentExceptionMsg() + else: + i.error errIncorrect, "Two strings are required on the stack" + + .symbol("rmdir") do (i: In): + let f = i.pop + if f.isString: + try: + f.strVal.removeDir + except: + warn getCurrentExceptionMsg() + else: + i.error errIncorrect, "A string is required on the stack" + + .symbol("mkdir") do (i: In): + let f = i.pop + if f.isString: + try: + f.strVal.createDir + except: + warn getCurrentExceptionMsg() + else: + i.error errIncorrect, "A string is required on the stack" -minsym "mkdir", i: - let f = i.pop - if f.isString: - try: - f.strVal.createDir - except: - warn getCurrentExceptionMsg() - else: - i.error errIncorrect, "A string is required on the stack" + .finalize()
M lib/time.nimlib/time.nim

@@ -7,9 +7,13 @@ ../core/utils

# Time -minsym "timestamp", i: - i.push getTime().int.newVal +define("time") -minsym "now", i: - i.push epochTime().newVal + .symbol("timestamp") do (i: In): + i.push getTime().int.newVal + + .symbol("now") do (i: In): + i.push epochTime().newVal + + .finalize()
M minim.nimminim.nim

@@ -6,7 +6,6 @@ core/utils

import lib/lang, lib/stack, - lib/q, lib/num, lib/str, lib/logic,