all repos — min @ c3ee6627ab5424669b01bc28f355f9a251804b94

A small but practical concatenative programming language.

Added dict tests; other fixes and missing implementations on dicts.
h3rald h3rald@h3rald.com
Sat, 02 Jun 2018 14:27:24 +0200
commit

c3ee6627ab5424669b01bc28f355f9a251804b94

parent

4fe3fa3fcab75451c6d539ca2a8e6dee311000cb

M core/interpreter.nimcore/interpreter.nim

@@ -162,11 +162,7 @@ i2.scope = i.scope

try: i2.withScope(q): for v in q.qVal: - if (v.kind == minQuotation): - var v2 = v - i2.dequote(v2) - else: - i2.push v + i2.push v except: i.currSym = i2.currSym i.trace = i2.trace

@@ -196,10 +192,12 @@ else:

raiseUndefined("Undefined symbol '$1'" % [val.symVal]) discard i.trace.pop else: - #var v = val - #if (v.kind == minDictionary): - # i.dequote(v) - i.stack.add(val) + var v = val + if (v.kind == minDictionary): + i.dequote(v) + # Clear the initial quotation; only used when parsing a dictionary for the first time + v.qVal = @[] + i.stack.add(v) proc pop*(i: In): MinValue {.extern:"min_exported_symbol_$1".}= if i.stack.len > 0:
M core/parser.nimcore/parser.nim

@@ -711,13 +711,29 @@ if item == b.qVal[c]:

c.inc else: return false + return true + else: + return false + elif a.kind == minDictionary: + let aVal = a.dVal + let bVal = b.dVal + if aVal.len != bVal.len: + return false + else: + for t in aVal.pairs: + if not bVal.hasKey(t.key): + return false + let v1 = t.val + let v2 = bVal[t.key] + if v1.kind != v2.kind: + return false + if v1.kind == minValOp: + return v1.val == v2.val if a.objType.isNil and b.objType.isNil: return true elif not a.objType.isNil and not b.objType.isNil: return a.objType == b.objType else: return false - else: - return false else: return false
M core/scope.nimcore/scope.nim

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

proc copy*(s: ref MinScope): ref MinScope {.extern:"min_exported_symbol_$1".}= var scope = newScope(s.parent) scope.symbols = s.symbols + scope.sigils = s.sigils new(result) result[] = scope
M core/utils.nimcore/utils.nim

@@ -38,6 +38,7 @@

proc finalize*(scope: ref MinScope, name: string = "") {.extern:"min_exported_symbol_$1".}= var mdl = newDict(scope) mdl.scope = scope + mdl.objType = "module" let op = proc(i: In) {.closure.} = i.evaluating = true i.push mdl

@@ -50,14 +51,22 @@

proc dget*(i: In, q: MinValue, s: MinValue): MinValue {.extern:"min_exported_symbol_$1".}= if not q.isDictionary: raiseInvalid("Value is not a dictionary") + if q.dVal[s.getString].kind == minProcOp: + raiseInvalid("Key '$1' is set to a compiled value that cannot be retrieved." % [s.getString]) var val = q.dVal[s.getString].val - return i.call(val) + result = i.call(val) + if result.qVal.len == 1: + result = result.qVal[0] proc dget*(i: In, q: MinValue, s: string): MinValue {.extern:"min_exported_symbol_$1_2".}= if not q.isDictionary: raiseInvalid("Value is not a dictionary") + if q.dVal[s].kind == minProcOp: + raiseInvalid("Key $1 is set to a compiled value that cannot be retrieved." % [s]) var val = q.dVal[s].val - return i.call(val) + result = i.call(val) + if result.qVal.len == 1 and result.qVal[0].kind != minQuotation: + result = result.qVal[0] proc dhas*(q: MinValue, s: MinValue): bool {.extern:"min_exported_symbol_$1".}= if not q.isDictionary:

@@ -81,7 +90,7 @@ raiseInvalid("Value is not a dictionary")

excl(p.scope.symbols, s) return p -proc dset*(i: In, p: MinValue, s: MinValue, m: MinValue): MinValue {.discardable, extern:"min_exported_symbol_$1".}= +proc dset*(i: In, p: var MinValue, s: MinValue, m: MinValue): MinValue {.discardable, extern:"min_exported_symbol_$1".}= if not p.isDictionary: raiseInvalid("Value is not a dictionary") var q = m

@@ -90,7 +99,7 @@ q = @[q].newVal(i.scope)

p.scope.symbols[s.getString] = MinOperator(kind: minValOp, val: q, sealed: false) return p -proc dset*(i: In, p: MinValue, s: string, m: MinValue): MinValue {.discardable, extern:"min_exported_symbol_$1_2".}= +proc dset*(i: In, p: var MinValue, s: string, m: MinValue): MinValue {.discardable, extern:"min_exported_symbol_$1_2".}= if not p.isDictionary: raiseInvalid("Value is not a dictionary") var q = m

@@ -109,8 +118,14 @@

proc values*(i: In, q: MinValue): MinValue {.extern:"min_exported_symbol_$1".}= # Assumes q is a dictionary var r = newSeq[MinValue](0) - for i in q.dVal.values: - r.add i.val + for item in q.dVal.values: + if item.kind == minProcOp: + raiseInvalid("Dictionary contains compiled values that cannot be accessed.") + var v = item.val + var val = i.call(v) + if val.qVal.len == 1 and val.qVal[0].kind != minQuotation: + val = val.qVal[0] + r.add val return r.newVal(i.scope) # JSON interop
M lib/min_dict.nimlib/min_dict.nim

@@ -27,7 +27,7 @@ def.symbol("dset") do (i: In):

let vals = i.expect("'sym", "a", "dict") let k = vals[0] let m = vals[1] - let d = vals[2] + var d = vals[2] i.push i.dset(d, k, m) def.symbol("ddel") do (i: In):

@@ -45,6 +45,14 @@ def.symbol("dvalues") do (i: In):

let vals = i.expect("dict") let d = vals[0] i.push i.values(d) + + def.symbol("ddup") do (i: In): + let vals = i.expect("dict") + let d = vals[0] + var r = newDict(i.scope) + for item in d.dVal.pairs: + r.scope.symbols[item.key] = item.val + i.push r def.symbol("dpick") do (i: In): let vals = i.expect("quot", "dict")
M lib/min_lang.nimlib/min_lang.nim

@@ -232,7 +232,7 @@ else:

raiseInvalid("No source available for native symbol '$1'." % str) def.symbol("call") do (i: In): - let vals = i.expect("'sym", "quot") + let vals = i.expect("'sym", "dict") let symbol = vals[0] let q = vals[1] let s = symbol.getString

@@ -668,7 +668,6 @@ def.sigil("=") do (i: In):

i.push("quote-define".newSym) # Shorthand symbol aliases - def.symbol("#") do (i: In): i.push("quote-bind".newSym)
M min.nimmin.nim

@@ -237,7 +237,7 @@ else:

echo " ".repeat(n.len) & " ;" & res.objType echo " ".repeat(n.len) & " }" else: - echo "{$1} -> $2" % [$i.stack.len, $i.stack[i.stack.len - 1]] + echo "[$1] -> $2" % [$i.stack.len, $i.stack[i.stack.len - 1]] proc minRepl*(i: var MinInterpreter) = i.stdLib()
M min.vimmin.vim

@@ -11,7 +11,7 @@

setl iskeyword=@,36-39,+,-,*,.,/,:,~,!,48-57,60-65,94-95,192-255 setl iskeyword+=^ -syntax keyword minDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / § : = # < <= == => =~ > >= @ -inf ROOT accept acos aes all? and any? append apply args asin ask atan atime bind bool boolean? call call! capitalize case cd ceil chmod choose clear-stack cleave close column-print concat confirm connect cons cos cosh cp cpu crypto ctime d2r datetime ddel debug decode define defined? delete dequote dequote-and dequote-or dget dhas? dkeys dict dictionary? dip dir? dirname div download dpick dprint dprint! drop dset dsort dup dvalues e encode env? error eval even? exists? exit expect fappend fatal find file? filename filter first flatten float float? floor foreach fperms fread from-json format-error fs fsize fstats ftype fwrite get get-content gets get-env get-stack hardlink harvest hidden? http id if import in? indent indexof inf info insert int integer? interpolate interval io join keep last length linrec listen ln load load-symbol log2 log10 logic loglevel loglevel? lowercase ls ls-r map map-reduce match math md5 mkdir mod module module-symbols module-sigils mtime mv nan newline net nip not notice now num number? odd? opts os over parse partition password pi pick pop popd pow pred prepend print print! prompt publish puts puts! put-env q quotation? quote quote-bind quote-define quote-map r2d random randomize raise read recv recv-line reduce regex reject remove remove-symbol repeat replace request rest reverse rm rmdir round run save-symbol scope scope? seal search send seq set set-stack sha1 sha224 sha256 sha384 sha512 shorten sigils sin sinh sip size sleep slice socket sort source split spread sqrt stack start-server startup stop-server stored-symbols str string string? strip succ sum swap swons symbols symlink symlink? sys system take tan tanh tap tap! tau tformat time timeinfo times timestamp titleize to-json to-timestamp try trunc unless substr unseal unzip uppercase version warn when which while with xor zip +syntax keyword minDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / § : = # < <= == => =~ > >= @ -inf ROOT accept acos aes all? and any? append apply args asin ask atan atime bind bool boolean? call call! capitalize case cd ceil chmod choose clear-stack cleave close column-print concat confirm connect cons cos cosh cp cpu crypto ctime d2r datetime ddel ddup debug decode define defined? delete dequote dequote-and dequote-or dget dhas? dkeys dict dictionary? dip dir? dirname div download dpick dprint dprint! drop dset dup dvalues e encode env? error eval even? exists? exit expect fappend fatal find file? filename filter first flatten float float? floor foreach fperms fread from-json format-error fs fsize fstats ftype fwrite get get-content gets get-env get-stack hardlink harvest hidden? http id if import in? indent indexof inf info insert int integer? interpolate interval io join keep last length linrec listen ln load load-symbol log2 log10 logic loglevel loglevel? lowercase ls ls-r map map-reduce match math md5 mkdir mod module module-symbols module-sigils mtime mv nan newline net nip not notice now num number? odd? opts os over parse partition password pi pick pop popd pow pred prepend print print! prompt publish puts puts! put-env q quotation? quote quote-bind quote-define quote-map r2d random randomize raise read recv recv-line reduce regex reject remove remove-symbol repeat replace request rest reverse rm rmdir round run save-symbol scope scope? seal search send seq set set-stack sha1 sha224 sha256 sha384 sha512 shorten sigils sin sinh sip size sleep slice socket sort source split spread sqrt stack start-server startup stop-server stored-symbols str string string? strip succ sum swap swons symbols symlink symlink? sys system take tan tanh tap tap! tau tformat time timeinfo times timestamp titleize to-json to-timestamp try trunc unless substr unseal unzip uppercase version warn when which while with xor zip syntax match minDefaultSigil ;\<[/:@'~!?$%&$=<>#^*#+]; contained syntax match minQuote ;\<['];

@@ -31,7 +31,7 @@ syntax region minBoundSymbol start=;@; end=;\>; contains=minBinding

syntax region minQuotedBoundSymbol start=;#; end=;\>; contains=minQuotedBinding syntax match minSymbol ;[a-zA-Z._][a-zA-Z0-9/!?+*._-]*; -syntax match minParen ;(\|); +syntax match minParen ;(\|)\|{\|}; syntax match minSharpBang /\%^#!.*/
A tests/dict.min

@@ -0,0 +1,29 @@

+'test load +'test import + +"dict" describe + + ((("a" 1)("b" 2)("c" 3)) dictionary? not) assert + + ({1 :a 2 :b 3 :c} dictionary?) assert + + ({1 :a 2 :b 3 :c} 'b dget 2 ==) assert + + ({1 :a 2 :b 3 :c} :dict1 dict1 5 'b dset 7 %d :newdict newdict {1 :a 5 :b 3 :c 7 :d} == dict1 newdict == and) assert + + ({1 :a 2 :b 3 :c} :dict1 dict1 ddup 5 'b dset 7 %d :newdict newdict {1 :a 5 :b 3 :c 7 :d} == dict1 {1 :a 2 :b 3 :c} == and) assert + + ({1 :a 2 :b 3 :c} :dict1 dict1 'b ddel {1 :a 3 :c} ==) assert + + ({1 :a 2 :b 3 :c} dkeys ("a" "b" "c") ==) assert + + ({1 :a 2 :b 3 :c} dvalues (1 2 3) ==) assert + + ({1 :a 2 :b 3 :c 4 :d} ("b" "c") dpick {2 :b 3 :c} ==) assert + + (2 2 {'+ :plus} ^plus 4 ==) assert + + (2 {(2 3 +) :sum} /sum + 7 ==) assert + + report + clear-stack
M tests/test.mintests/test.min

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

;; test module -( +{ 'OK =ok + (" " print!) :padding ;; describe

@@ -60,4 +61,4 @@ map

pop ;Remove results accomulator from get-stack ) :report -) +test+} +test