all repos — min @ a97c16b62b53b8703c5f1da61d3721f9e9e110c3

A small but practical concatenative programming language.

Removed named scopes.
h3rald h3rald@h3rald.com
Sat, 25 Mar 2017 12:26:28 +0100
commit

a97c16b62b53b8703c5f1da61d3721f9e9e110c3

parent

1924fba739bfd2b8fca7a307a31687b0e332e4ea

M core/interpreter.nimcore/interpreter.nim

@@ -44,7 +44,6 @@ var trace:MinStack = newSeq[MinValue](0)

var stackcopy:MinStack = newSeq[MinValue](0) var pr:MinParser var scope = new MinScope - scope.name = "ROOT" var i:MinInterpreter = MinInterpreter( filename: filename, pwd: pwd,

@@ -98,7 +97,7 @@

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

@@ -111,7 +110,7 @@ i.push e

else: i.push(op.val) -proc unquote*(i: In, name: string, q: var MinValue) = +proc unquote*(i: In, q: var MinValue) = i.withScope(q, q.scope): for v in q.qVal: i.push v

@@ -136,7 +135,7 @@ let sym = symbol[1..symbol.len-1]

i.stack.add(MinValue(kind: minString, strVal: sym)) i.apply(sig) else: - raiseUndefined("Undefined symbol '$1' in scope '$2'" % [val.symVal, i.scope.fullname]) + raiseUndefined("Undefined symbol '$1'" % [val.symVal]) discard i.trace.pop else: i.stack.add(val)
M core/parser.nimcore/parser.nim

@@ -146,25 +146,12 @@ "true",

"false" ] -var SCOPES = 0 +proc newScope*(parent: ref MinScope): MinScope = + result = MinScope(parent: parent) -proc b64(n: int): string = - let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - var residual = n - result = "" - while true: - result = alphabet[residual mod 64] & result - residual = residual div 64 - if residual == 0: - break - -proc newScope*(parent: ref MinScope, name="scope"): MinScope = - let id = atomicInc(SCOPES).b64 - result = MinScope(name: "$1-$2" % [name, id], parent: parent) - -proc newScopeRef*(parent: ref MinScope, name="scope"): ref MinScope = +proc newScopeRef*(parent: ref MinScope): ref MinScope = new(result) - result[] = newScope(parent, name) + result[] = newScope(parent) proc open*(my: var MinParser, input: Stream, filename: string) = lexbase.open(my, input)

@@ -508,7 +495,7 @@ discard getToken(p)

of tkBracketLe: var q = newSeq[MinValue](0) var oldscope = i.scope - var newscope = newScopeRef(i.scope, "q") + var newscope = newScopeRef(i.scope) i.scope = newscope discard getToken(p) while p.token != tkBracketRi:
M core/scope.nimcore/scope.nim

@@ -4,13 +4,8 @@ critbits

import parser -proc fullname*(scope: ref MinScope): string = - result = scope.name - if not scope.parent.isNil: - result = scope.parent.fullname & ":" & result - proc copy*(s: ref MinScope): ref MinScope = - var scope = newScope(s.parent, "_$1" % s.name) + var scope = newScope(s.parent) scope.symbols = s.symbols new(result) result[] = scope
M core/utils.nimcore/utils.nim

@@ -10,9 +10,8 @@ interpreter

# Library methods -proc define*(i: In, name: string): ref MinScope = +proc define*(i: In): ref MinScope = var scope = new MinScope - scope.name = name scope.parent = i.scope return scope

@@ -32,14 +31,15 @@ proc sigil*(scope: ref MinScope, sym: string, v: MinValue): ref MinScope =

scope.sigils[sym] = MinOperator(val: v, kind: minValOp, sealed: true) return scope -proc finalize*(scope: ref MinScope) = +proc finalize*(scope: ref MinScope, name: string = "") = var mdl = newSeq[MinValue](0).newVal(nil) mdl.scope = scope let op = proc(i: In) {.gcsafe, closure.} = i.evaluating = true i.push mdl i.evaluating = false - scope.previous.symbols[scope.name] = MinOperator(kind: minProcOp, prc: op) + if name != "": + scope.previous.symbols[name] = MinOperator(kind: minProcOp, prc: op) # Validators
M lib/min_crypto.nimlib/min_crypto.nim

@@ -14,7 +14,7 @@ ../packages/nimSHA2/nimSHA2,

../packages/nimAES/nimAES proc crypto_module*(i: In)= - i.define("crypto") + i.define() .symbol("md5") do (i: In): var s: MinValue

@@ -70,4 +70,4 @@ var key = k.getString.compute.toHex # SHA1 of key, to make sure it's long enough

var nonce = key[0..15] i.push ctx.cryptOFB(nonce, text).newVal - .finalize() + .finalize("crypto")
M lib/min_fs.nimlib/min_fs.nim

@@ -10,7 +10,7 @@ ../core/utils,

../core/fileutils proc fs_module*(i: In) = - i.define("fs") + i.define() .symbol("mtime") do (i: In): var s: MinValue i.reqStringLike s

@@ -63,4 +63,4 @@ var s: MinValue

i.reqStringLike s i.push s.getString.getFilePermissions.unixPermissions.newVal - .finalize() + .finalize("fs")
M lib/min_io.nimlib/min_io.nim

@@ -14,7 +14,7 @@ # I/O

proc io_module*(i: In) = - i.define("io") + i.define() .symbol("newline") do (i: In): echo ""

@@ -118,7 +118,7 @@ return choose()

else: return choice let choice = choose() - i.unquote("<choose>", q.qVal[choice-1].qVal[1]) + i.unquote(q.qVal[choice-1].qVal[1]) .symbol("print") do (i: In): let a = i.peek

@@ -145,4 +145,4 @@ discard f.open(a.strVal, fmAppend)

f.write(b.strVal) f.close() - .finalize() + .finalize("io")
M lib/min_lang.nimlib/min_lang.nim

@@ -182,9 +182,8 @@ symbol = sym.getString

if not symbol.match "^[a-zA-Z0-9_][a-zA-Z0-9/!?+*._-]*$": raiseInvalid("Symbol identifier '$1' contains invalid characters." % symbol) info "[define] $1 = $2" % [symbol, $q1] - debug("[define] Scope: $1" % i.scope.fullname) if i.scope.symbols.hasKey(symbol) and i.scope.symbols[symbol].sealed: - raiseUndefined("Attempting to redefine sealed symbol '$1' on scope '$2'" % [symbol, i.scope.name]) + raiseUndefined("Attempting to redefine sealed symbol '$1'" % [symbol]) i.scope.symbols[symbol] = MinOperator(kind: minValOp, val: q1, sealed: false) .symbol("bind") do (i: In):

@@ -196,7 +195,6 @@ if not q1.isQuotation:

q1 = @[q1].newVal(i.scope) symbol = sym.getString info "[bind] $1 = $2" % [symbol, $q1] - debug("[bind] Scope: $1" % i.scope.fullname) let res = i.scope.setSymbol(symbol, MinOperator(kind: minValOp, val: q1)) if not res: raiseUndefined("Attempting to bind undefined symbol: " & symbol)

@@ -213,7 +211,7 @@ var code, name: MinValue

i.reqStringLike name i.reqQuotation code code.filename = i.filename - i.unquote("<module>", code) + i.unquote(code) info("[module] $1 ($2 symbols)" % [name.getString, $code.scope.symbols.len]) i.scope.symbols[name.getString] = MinOperator(kind: minValOp, val: @[code].newVal(i.scope))

@@ -226,16 +224,15 @@ var op = i.scope.getSymbol(name)

i.apply(op) i.reqQuotation mdl info("[import] Importing: $1 ($2 symbols, $3 sigils)" % [name, $mdl.scope.symbols.len, $mdl.scope.sigils.len]) - debug("[import] Scope: $1" % i.scope.fullname) 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' on scope '$2'" % [sym, i.scope.name]) - i.debug "[import] $1:$2" % [i.scope.fullname, sym] + raiseUndefined("Attempting to redefine sealed symbol '$1'" % [sym]) + i.debug "[import] $1" % [sym] i.scope.symbols[sym] = val for sig, val in mdl.scope.sigils.pairs: if i.scope.sigils.hasKey(sig) and i.scope.sigils[sig].sealed: - raiseUndefined("Attempting to redefine sealed sigil '$1' on scope '$2'" % [sig, i.scope.name]) - i.debug "[import] $1:$2" % [i.scope.fullname, sig] + raiseUndefined("Attempting to redefine sealed sigil '$1'" % [sig]) + i.debug "[import] $1" % [sig] i.scope.sigils[sig] = val .symbol("eval") do (i: In):

@@ -260,7 +257,7 @@ var qscope, qprog: MinValue

i.reqTwoQuotations qscope, qprog if qscope.qVal.len > 0: # System modules are empty quotes and don't need to be unquoted - i.unquote("<with-scope>", qscope) + i.unquote(qscope) i.withScope(qscope, qscope.scope): for v in qprog.qVal: i.push v

@@ -270,10 +267,9 @@ var qscope, str: MinValue

i.reqQuotationAndStringLike qscope, str let sym = str.getString if qscope.scope.symbols.hasKey(sym) and qscope.scope.symbols[sym].sealed: - raiseUndefined("Attempting to redefine sealed symbol '$1' on scope '$2'" % [sym, qscope.scope.name]) + raiseUndefined("Attempting to redefine sealed symbol '$1'" % [sym]) let scope = i.scope info("[publish] Symbol: $2" % [sym]) - debug("[publish] $1 -> $2" % [i.scope.fullname, qscope.scope.fullname]) let op = proc(i: In) {.gcsafe, closure.} = let origscope = i.scope i.scope = scope

@@ -364,13 +360,13 @@ hasFinally = true

if (not code.isQuotation) or (hasCatch and not catch.isQuotation) or (hasFinally and not final.isQuotation): raiseInvalid("Quotation must contain at one quotation") try: - i.unquote("<try-code>", code) + i.unquote(code) except MinRuntimeError: if not hasCatch: return let e = (MinRuntimeError)getCurrentException() i.push e.qVal.newVal(i.scope) - i.unquote("<try-catch>", catch) + i.unquote(catch) except: if not hasCatch: return

@@ -384,10 +380,10 @@ 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) i.push res.newVal(i.scope) - i.unquote("<try-catch>", catch) + i.unquote(catch) finally: if hasFinally: - i.unquote("<try-finally>", final) + i.unquote(final) # Operations on quotations or strings

@@ -432,7 +428,7 @@

.symbol("unquote") do (i: In): var q: MinValue i.reqQuotation q - i.unquote("<unquote>", q) + i.unquote(q) .symbol("append") do (i: In): var q: MinValue

@@ -468,7 +464,7 @@ i.reqTwoQuotations prog, list

var res = newSeq[MinValue](0) for litem in list.qVal: i.push litem - i.unquote("<map-quotation>", prog) + i.unquote(prog) res.add i.pop i.push res.newVal(i.scope)

@@ -477,7 +473,7 @@ var prog, list: MinValue

i.reqTwoQuotations prog, list for litem in list.qVal: i.push litem - i.unquote("<foreach-quotation>", prog) + i.unquote(prog) .symbol("times") do (i: In): var t, prog: MinValue

@@ -485,33 +481,33 @@ i.reqIntAndQuotation t, prog

if t.intVal < 1: raiseInvalid("A non-zero natural number is required") for c in 1..t.intVal: - i.unquote("<times-quotation>", prog) + i.unquote(prog) .symbol("ifte") do (i: In): var fpath, tpath, check: MinValue i.reqThreeQuotations fpath, tpath, check var stack = i.stack - i.unquote("<ifte-check>", check) + i.unquote(check) let res = i.pop i.stack = stack if not res.isBool: raiseInvalid("Result of check is not a boolean value") if res.boolVal == true: - i.unquote("<ifte-true>", tpath) + i.unquote(tpath) else: - i.unquote("<ifte-false>", fpath) + i.unquote(fpath) .symbol("ift") do (i: In): var fpath, tpath, check: MinValue i.reqTwoQuotations tpath, check var stack = i.stack - i.unquote("<ift-check>", check) + i.unquote(check) let res = i.pop i.stack = stack if not res.isBool: raiseInvalid("Result of check is not a boolean value") if res.boolVal == true: - i.unquote("<ift-true>", tpath) + i.unquote(tpath) # 4 ( # ((> 3) ("Greater than 3" put!))

@@ -533,13 +529,13 @@ k.inc

if c.qVal.len != 2 or not c.qVal[0].isQuotation or not c.qVal[1].isQuotation: raiseInvalid("Inner quotations in case operator must contain two quotations") var q = c.qVal[0] - i.unquote("<case-$1-check>" % $k, q) + i.unquote(q) let res = i.pop if not res.isBool(): raiseInvalid("Result of case #$1 is not a boolean value" % $k) if res.boolVal == true: var t = c.qVal[1] - i.unquote("<case-$1-true>" % $k, t) + i.unquote(t) break

@@ -548,11 +544,11 @@ var d, b: MinValue

i.reqTwoQuotations d, b for e in b.qVal: i.push e - i.unquote("<while-check>", b) + i.unquote(b) var check = i.pop while check.isBool and check.boolVal == true: - i.unquote("<while-quotation>", d) - i.unquote("<while-check>", b) + i.unquote(d) + i.unquote(b) check = i.pop .symbol("filter") do (i: In):

@@ -561,7 +557,7 @@ i.reqTwoQuotations filter, list

var res = newSeq[MinValue](0) for e in list.qVal: i.push e - i.unquote("<filter-check>", filter) + i.unquote(filter) var check = i.pop if check.isBool and check.boolVal == true: res.add e

@@ -574,7 +570,7 @@ var i2 = i

var minCmp = proc(a, b: MinValue): int {.closure.}= i2.push a i2.push b - i2.unquote("<sort-cmp>", cmp) + i2.unquote(cmp) let r = i2.pop if r.isBool: if r.boolVal == true:

@@ -591,14 +587,14 @@ .symbol("linrec") do (i: In):

var r2, r1, t, p: MinValue i.reqFourQuotations r2, r1, t, p proc linrec(i: In, p, t, r1, r2: var MinValue) = - i.unquote("<linrec-predicate>", p) + i.unquote(p) var check = i.pop if check.isBool and check.boolVal == true: - i.unquote("<linrec-true>", t) + i.unquote(t) else: - i.unquote("<linrec-r1>", r1) + i.unquote(r1) i.linrec(p, t, r1, r2) - i.unquote("<linrec-r2>", r2) + i.unquote(r2) i.linrec(p, t, r1, r2) .symbol("dhas?") do (i: In):

@@ -797,4 +793,4 @@

.symbol("->") do (i: In): i.push("unquote".newSym) - .finalize() + .finalize("ROOT")
M lib/min_logic.nimlib/min_logic.nim

@@ -10,7 +10,7 @@ # Comparison operators

proc logic_module*(i: In)= - i.define("logic") + i.define() .symbol(">") do (i: In): var n2, n1: MinValue

@@ -146,4 +146,4 @@ i.push true.newVal

else: i.push false.newVal - .finalize() + .finalize("logic")
M lib/min_num.nimlib/min_num.nim

@@ -11,7 +11,7 @@ # Arithmetic

proc num_module*(i: In)= - i.define("num") + i.define() .symbol("+") do (i: In): var a, b: MinValue

@@ -99,4 +99,4 @@ var n: MinValue

i.reqInt n i.push newVal(n.intVal mod 2 != 0) - .finalize() + .finalize("num")
M lib/min_stack.nimlib/min_stack.nim

@@ -10,7 +10,7 @@

# Operations on the whole stack proc stack_module*(i: In)= - i.define("stack") + i.define() .symbol("i") do (i: In): i.push "unquote".newSym

@@ -52,7 +52,7 @@ .symbol("dip") do (i: In):

var q: MinValue i.reqQuotation q let v = i.pop - i.unquote("<dip>", q) + i.unquote(q) i.push v # ((dip) cons cons)

@@ -137,7 +137,7 @@ .symbol("sip") do (i: In):

var a, b: MinValue i.reqTwoQuotations a, b i.push b - i.unquote("<sip>", a) + i.unquote(a) i.push b - .finalize() + .finalize("stack")
M lib/min_str.nimlib/min_str.nim

@@ -10,7 +10,7 @@ ../core/utils,

../packages/nim-sgregex/sgregex proc str_module*(i: In) = - i.define("str") + i.define() .symbol("strip") do (i: In): var s: MinValue

@@ -142,4 +142,4 @@

.symbol("=~") do (i: In): i.push("regex".newSym) - .finalize() + .finalize("str")
M lib/min_sys.nimlib/min_sys.nim

@@ -16,7 +16,7 @@ proc unix(s: string): string =

return s.replace("\\", "/") proc sys_module*(i: In)= - i.define("sys") + i.define() .symbol(".") do (i: In): i.push newVal(getCurrentDir().unix)

@@ -200,4 +200,4 @@

.sigil("&") do (i: In): i.push("run".newSym) - .finalize() + .finalize("sys")
M lib/min_time.nimlib/min_time.nim

@@ -11,7 +11,7 @@ # Time

proc time_module*(i: In)= - i.define("time") + i.define() .symbol("timestamp") do (i: In): i.push getTime().int.newVal

@@ -60,5 +60,4 @@ else:

time = t.floatVal.fromSeconds i.push time.getLocalTime.format(s.getString).newVal - .finalize() - + .finalize("time")