all repos — min @ cb9bfdbd60d28d4f16669e8de55394a82b2f4187

A small but practical concatenative programming language.

Moved symbols to seq module; updated tests.
h3rald h3rald@h3rald.com
Fri, 14 Apr 2017 12:43:45 +0200
commit

cb9bfdbd60d28d4f16669e8de55394a82b2f4187

parent

7fa3f654868f6b460770674dc6051a6cf9837f32

6 files changed, 240 insertions(+), 231 deletions(-)

jump to
M lib/min_lang.nimlib/min_lang.nim

@@ -3,7 +3,6 @@ critbits,

strutils, json, os, - algorithm, logging import ../core/consts,

@@ -280,28 +279,6 @@ finally:

if hasFinally: i.unquote(final) - # Operations on quotations - - .symbol("concat") do (i: In): - var q1, q2: MinValue - i.reqTwoQuotations q1, q2 - let q = q2.qVal & q1.qVal - i.push q.newVal(i.scope) - - .symbol("first") do (i: In): - var q: MinValue - i.reqQuotation q - if q.qVal.len == 0: - raiseOutOfBounds("Quotation is empty") - i.push q.qVal[0] - - .symbol("rest") do (i: In): - var q: MinValue - i.reqQuotation q - if q.qVal.len == 0: - raiseOutOfBounds("Quotation is empty") - i.push q.qVal[1..q.qVal.len-1].newVal(i.scope) - .symbol("quote") do (i: In): let a = i.pop i.push @[a].newVal(i.scope)

@@ -311,67 +288,8 @@ var q: MinValue

i.reqQuotation q i.unquote(q) - .symbol("append") do (i: In): - var q: MinValue - i.reqQuotation q - let v = i.pop - i.push newVal(q.qVal & v, i.scope) - - .symbol("prepend") do (i: In): - var q: MinValue - i.reqQuotation q - let v = i.pop - i.push newVal(v & q.qVal, i.scope) - - .symbol("at") do (i: In): - var index, q: MinValue - i.reqIntAndQuotation index, q - if q.qVal.len-1 < index.intVal: - raiseOutOfBounds("Insufficient items in quotation") - i.push q.qVal[index.intVal.int] - - .symbol("size") do (i: In): - var q: MinValue - i.reqQuotation q - i.push q.qVal.len.newVal - - .symbol("in?") do (i: In): - i.reqStackSize(2) - let v = i.pop - var q: MinValue - i.reqQuotation q - i.push q.qVal.contains(v).newVal - - .symbol("map") do (i: In): - var prog, list: MinValue - i.reqTwoQuotations prog, list - var res = newSeq[MinValue](0) - for litem in list.qVal: - i.push litem - i.unquote(prog) - res.add i.pop - i.push res.newVal(i.scope) + # Conditionals - .symbol("apply") do (i: In): - var prog: MinValue - i.reqQuotation prog - i.apply prog - - .symbol("foreach") do (i: In): - var prog, list: MinValue - i.reqTwoQuotations prog, list - for litem in list.qVal: - i.push litem - i.unquote(prog) - - .symbol("times") do (i: In): - var t, prog: MinValue - i.reqIntAndQuotation t, prog - if t.intVal < 1: - raiseInvalid("A non-zero natural number is required") - for c in 1..t.intVal: - i.unquote(prog) - .symbol("if") do (i: In): var fpath, tpath, check: MinValue i.reqThreeQuotations fpath, tpath, check

@@ -438,15 +356,24 @@ if res.boolVal == true:

var t = c.qVal[1] i.unquote(t) break - - .symbol("reverse") do (i: In): - var q: MinValue - i.reqQuotation q - var res = newSeq[MinValue](0) - for c in countdown(q.qVal.len-1, 0): - res.add q.qVal[c] - i.push res.newVal(i.scope) + # Loops + + .symbol("foreach") do (i: In): + var prog, list: MinValue + i.reqTwoQuotations prog, list + for litem in list.qVal: + i.push litem + i.unquote(prog) + + .symbol("times") do (i: In): + var t, prog: MinValue + i.reqIntAndQuotation t, prog + if t.intVal < 1: + raiseInvalid("A non-zero natural number is required") + for c in 1..t.intVal: + i.unquote(prog) + .symbol("while") do (i: In): var d, b: MinValue i.reqTwoQuotations d, b

@@ -459,62 +386,8 @@ i.unquote(d)

i.unquote(b) check = i.pop discard i.pop - - .symbol("filter") do (i: In): - var filter, list: MinValue - i.reqTwoQuotations filter, list - var res = newSeq[MinValue](0) - for e in list.qVal: - i.push e - i.unquote(filter) - var check = i.pop - if check.isBool and check.boolVal == true: - res.add e - i.push res.newVal(i.scope) - .symbol("any?") do (i: In): - var filter, list: MinValue - i.reqTwoQuotations filter, list - for e in list.qVal: - i.push e - i.unquote(filter) - var check = i.pop - if check.isBool and check.boolVal == true: - i.push true.newVal - return - i.push false.newVal - - .symbol("all?") do (i: In): - var filter, list: MinValue - i.reqTwoQuotations filter, list - for e in list.qVal: - i.push e - i.unquote(filter) - var check = i.pop - if check.isBool and check.boolVal == false: - i.push false.newVal - break - i.push true.newVal - - .symbol("sort") do (i: In): - var cmp, list: MinValue - i.reqTwoQuotations cmp, list - var i2 = i - var minCmp = proc(a, b: MinValue): int {.closure.}= - i2.push a - i2.push b - i2.unquote(cmp) - let r = i2.pop - if r.isBool: - if r.boolVal == true: - return 1 - else: - return -1 - else: - raiseInvalid("Predicate quotation must return a boolean value") - var qList = list.qVal - sort[MinValue](qList, minCmp) - i.push qList.newVal(i.scope) + # Other .symbol("linrec") do (i: In): var r2, r1, t, p: MinValue

@@ -529,41 +402,6 @@ i.unquote(r1)

i.linrec(p, t, r1, r2) i.unquote(r2) i.linrec(p, t, r1, r2) - - .symbol("dhas?") do (i: In): - var d, k: MinValue - i.reqStringLike k - i.reqDictionary d - i.push d.dhas(k).newVal - - .symbol("dget") do (i: In): - var d, k: MinValue - i.reqStringLike k - i.reqDictionary d - i.push d.dget(k) - - .symbol("dset") do (i: In): - var d, k: MinValue - i.reqStringLike k - let m = i.pop - i.reqDictionary d - i.push i.dset(d, k, m) - - .symbol("ddel") do (i: In): - var d, k: MinValue - i.reqStringLike k - i.reqDictionary d - i.push i.ddel(d, k) - - .symbol("keys") do (i: In): - var d: MinValue - i.reqDictionary d - i.push i.keys(d) - - .symbol("values") do (i: In): - var d: MinValue - i.reqDictionary d - i.push i.values(d) .symbol("version") do (i: In): i.push version.newVal
M lib/min_seq.nimlib/min_seq.nim

@@ -1,6 +1,7 @@

import + critbits, tables, - random + algorithm import ../core/parser, ../core/value,

@@ -14,5 +15,174 @@ i.define()

.symbol("harvest") do (i: In): discard + + .symbol("concat") do (i: In): + var q1, q2: MinValue + i.reqTwoQuotations q1, q2 + let q = q2.qVal & q1.qVal + i.push q.newVal(i.scope) + + .symbol("first") do (i: In): + var q: MinValue + i.reqQuotation q + if q.qVal.len == 0: + raiseOutOfBounds("Quotation is empty") + i.push q.qVal[0] + + .symbol("rest") do (i: In): + var q: MinValue + i.reqQuotation q + if q.qVal.len == 0: + raiseOutOfBounds("Quotation is empty") + i.push q.qVal[1..q.qVal.len-1].newVal(i.scope) + + .symbol("append") do (i: In): + var q: MinValue + i.reqQuotation q + let v = i.pop + i.push newVal(q.qVal & v, i.scope) + + .symbol("prepend") do (i: In): + var q: MinValue + i.reqQuotation q + let v = i.pop + i.push newVal(v & q.qVal, i.scope) + + .symbol("at") do (i: In): + var index, q: MinValue + i.reqIntAndQuotation index, q + if q.qVal.len-1 < index.intVal: + raiseOutOfBounds("Insufficient items in quotation") + i.push q.qVal[index.intVal.int] + + .symbol("size") do (i: In): + var q: MinValue + i.reqQuotation q + i.push q.qVal.len.newVal + + .symbol("in?") do (i: In): + i.reqStackSize(2) + let v = i.pop + var q: MinValue + i.reqQuotation q + i.push q.qVal.contains(v).newVal + + .symbol("map") do (i: In): + var prog, list: MinValue + i.reqTwoQuotations prog, list + var res = newSeq[MinValue](0) + for litem in list.qVal: + i.push litem + i.unquote(prog) + res.add i.pop + i.push res.newVal(i.scope) + + .symbol("apply") do (i: In): + var prog: MinValue + i.reqQuotation prog + i.apply prog + + .symbol("reverse") do (i: In): + var q: MinValue + i.reqQuotation q + var res = newSeq[MinValue](0) + for c in countdown(q.qVal.len-1, 0): + res.add q.qVal[c] + i.push res.newVal(i.scope) + + .symbol("filter") do (i: In): + var filter, list: MinValue + i.reqTwoQuotations filter, list + var res = newSeq[MinValue](0) + for e in list.qVal: + i.push e + i.unquote(filter) + var check = i.pop + if check.isBool and check.boolVal == true: + res.add e + i.push res.newVal(i.scope) + + .symbol("any?") do (i: In): + var filter, list: MinValue + i.reqTwoQuotations filter, list + for e in list.qVal: + i.push e + i.unquote(filter) + var check = i.pop + if check.isBool and check.boolVal == true: + i.push true.newVal + return + i.push false.newVal + + .symbol("all?") do (i: In): + var filter, list: MinValue + i.reqTwoQuotations filter, list + for e in list.qVal: + i.push e + i.unquote(filter) + var check = i.pop + if check.isBool and check.boolVal == false: + i.push false.newVal + break + i.push true.newVal + + .symbol("sort") do (i: In): + var cmp, list: MinValue + i.reqTwoQuotations cmp, list + var i2 = i + var minCmp = proc(a, b: MinValue): int {.closure.}= + i2.push a + i2.push b + i2.unquote(cmp) + let r = i2.pop + if r.isBool: + if r.boolVal == true: + return 1 + else: + return -1 + else: + raiseInvalid("Predicate quotation must return a boolean value") + var qList = list.qVal + sort[MinValue](qList, minCmp) + i.push qList.newVal(i.scope) + + # Operations on dictionaries + + .symbol("dhas?") do (i: In): + var d, k: MinValue + i.reqStringLike k + i.reqDictionary d + i.push d.dhas(k).newVal + + .symbol("dget") do (i: In): + var d, k: MinValue + i.reqStringLike k + i.reqDictionary d + i.push d.dget(k) + + .symbol("dset") do (i: In): + var d, k: MinValue + i.reqStringLike k + let m = i.pop + i.reqDictionary d + i.push i.dset(d, k, m) + + .symbol("ddel") do (i: In): + var d, k: MinValue + i.reqStringLike k + i.reqDictionary d + i.push i.ddel(d, k) + + .symbol("keys") do (i: In): + var d: MinValue + i.reqDictionary d + i.push i.keys(d) + + .symbol("values") do (i: In): + var d: MinValue + i.reqDictionary d + i.push i.values(d) + + .finalize("seq")
M tests/lang.mintests/lang.min

@@ -65,32 +65,11 @@ "tests/testload.min" rm

(2 2 mymath ^myplus 4 ==) assert - (1 2 3 4 stack (1 2 3 4) ==) assert - - ((1 2 3) unstack stack (1 2 3) ==) assert - - ((1 2) (3 4) concat (1 2 3 4) ==) assert - - ((1 2 3) first 1 ==) assert - - ((1 2 3) rest (2 3) ==) assert (2 quote (2) ==) assert ((2 3) unquote stack (2 3) ==) assert - (4 (1 2 3) append (1 2 3 4) ==) assert - - (0 (1 2 3) prepend (0 1 2 3) ==) assert - - ((1 2 3 4) 2 at 3 ==) assert - ((1 2 3) size 3 ==) assert - - ((1 2 3 4) 5 in? false ==) assert - ((1 2 3 4) 2 in?) assert - - ((1 2 3 4) (2 +) map (3 4 5 6) ==) assert - (3 (succ) 3 times 6 ==) assert ((2 3 >) ("YES") ("NO") if "NO" ==) assert

@@ -102,20 +81,8 @@ ((2 3 <) ("YES") when "YES" ==) assert

((2 3 >) ("YES") unless "YES" ==) assert - (0 :c - (c 10 <) (c succ @c) while - c 10 ==) assert - - ((1 2 3 4 5) (even?) filter (2 4) ==) assert - - ((1 2 3 4 5) (even?) any?) assert - - ((2 4 6 8) (even?) all?) assert - - ((5 4 3 2 1) reverse (1 2 3 4 5) ==) assert (5 (dup 0 ==) (1 +) (dup 1 -) ( * ) linrec 120 ==) assert ;factorial of 5 - ( (

@@ -158,18 +125,6 @@ ((1 2 3 "aaa" 'q q true) to-json "\n" "" replace " " "" replace "[1,2,3,\"aaa\",\";sym:'q\",\";sym:q\",true]" ==) assert

((1 2 3 "aaa" 'q q true) to-json from-json (1 2 3 "aaa" 'q q true) ==) 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)) ' :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)) keys (a b c) ==) assert - - (((a 1)(b 2)(c 3)) values (1 2 3) ==) assert - (((1 2 3)) :sym1 >sym1 stored-symbols "sym1" in?) assert (<sym1 symbols "sym1" in?) assert

@@ -187,10 +142,6 @@ ((3 <) (false))

((3 >) (true)) ) case ) assert - - ((3 4 7 2 4 6 5 6) '> sort (2 3 4 4 5 6 6 7) ==) assert - - ((3 4 7 2 4 6 5 6) '< sort (7 6 6 5 4 4 3 2) ==) assert (time module-symbols ("datetime" "now" "tformat" "timeinfo" "timestamp") ==) assert
M tests/num.mintests/num.min

@@ -32,5 +32,15 @@ (1000 random 1000 <) assert

((1 2 3 4 5) sum 15 ==) assert + (0 :c + (c 10 <) (c succ @c) while + c 10 ==) assert + + ((1 2 3 4 5) (even?) filter (2 4) ==) assert + + ((1 2 3 4 5) (even?) any?) assert + + ((2 4 6 8) (even?) all?) assert + report newstack
M tests/seq.mintests/seq.min

@@ -3,5 +3,41 @@ 'test import

"seq" describe + ((1 2) (3 4) concat (1 2 3 4) ==) assert + + ((1 2 3) first 1 ==) assert + + ((1 2 3) rest (2 3) ==) assert + + (4 (1 2 3) append (1 2 3 4) ==) assert + + (0 (1 2 3) prepend (0 1 2 3) ==) assert + + ((1 2 3 4) 2 at 3 ==) assert + ((1 2 3) size 3 ==) assert + + ((1 2 3 4) 5 in? false ==) assert + ((1 2 3 4) 2 in?) assert + + ((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)) '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 '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)) values (1 2 3) ==) assert + + ((3 4 7 2 4 6 5 6) '> sort (2 3 4 4 5 6 6 7) ==) assert + + ((3 4 7 2 4 6 5 6) '< sort (7 6 6 5 4 4 3 2) ==) assert + report newstack
M tests/stack.mintests/stack.min

@@ -3,6 +3,10 @@ 'test import

"stack" describe + (1 2 3 4 stack (1 2 3 4) ==) assert + + ((1 2 3) unstack stack (1 2 3) ==) assert + (1 id 1 ==) assert (2 id 2 ==) assert