all repos — min @ c3b66db7c5690867421e406932fef4faf94a5bdc

A small but practical concatenative programming language.

Added additional combinators borrowed from Factor.
h3rald h3rald@h3rald.com
Fri, 14 Apr 2017 12:16:56 +0200
commit

c3b66db7c5690867421e406932fef4faf94a5bdc

parent

03d1979ce43ee7c9dbeab17585c4cd487853ce18

M core/utils.nimcore/utils.nim

@@ -191,6 +191,22 @@ a = i.pop

if not a.isQuotation: raiseInvalid("A quotation is required on the stack") +proc reqQuotationOfQuotations*(i: var MinInterpreter, a: var MinValue) = + a = i.pop + if not a.isQuotation: + raiseInvalid("A quotation is required on the stack") + for s in a.qVal: + if not s.isQuotation: + raiseInvalid("A quotation of quotations is required on the stack") + +proc reqQuotationOfNumbers*(i: var MinInterpreter, a: var MinValue) = + a = i.pop + if not a.isQuotation: + raiseInvalid("A quotation is required on the stack") + for s in a.qVal: + if not s.isNumber: + raiseInvalid("A quotation of numbers is required on the stack") + proc reqIntAndQuotation*(i: var MinInterpreter, a, b: var MinValue) = a = i.pop b = i.pop
M lib/min_lang.nimlib/min_lang.nim

@@ -372,7 +372,7 @@ raiseInvalid("A non-zero natural number is required")

for c in 1..t.intVal: i.unquote(prog) - .symbol("ifte") do (i: In): + .symbol("if") do (i: In): var fpath, tpath, check: MinValue i.reqThreeQuotations fpath, tpath, check var stack = i.stack

@@ -386,7 +386,7 @@ i.unquote(tpath)

else: i.unquote(fpath) - .symbol("ift") do (i: In): + .symbol("when") do (i: In): var tpath, check: MinValue i.reqTwoQuotations tpath, check var stack = i.stack

@@ -396,6 +396,18 @@ i.stack = stack

if not res.isBool: raiseInvalid("Result of check is not a boolean value") if res.boolVal == true: + i.unquote(tpath) + + .symbol("unless") do (i: In): + var tpath, check: MinValue + i.reqTwoQuotations tpath, check + var stack = i.stack + 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 == false: i.unquote(tpath) # 4 (
M lib/min_num.nimlib/min_num.nim

@@ -104,4 +104,20 @@ var n: MinValue

i.reqInt n i.push newVal(n.intVal mod 2 != 0) + .symbol("sum") do (i: In): + var s: MinValue + i.reqQuotationOfNumbers s + var c = 0.float + var isInt = true + for n in s.qVal: + if n.isFloat: + isInt = false + c = + n.floatVal + else: + c = c + n.intVal.float + if isInt: + i.push c.int.newVal + else: + i.push c.newVal + .finalize("num")
M lib/min_stack.nimlib/min_stack.nim

@@ -70,17 +70,69 @@ let v = i.pop

i.unquote(q) i.push v + .symbol("cleave") do (i: In): + var q: MinValue + i.reqQuotationOfQuotations q + let v = i.pop + for s in q.qVal: + var s1 = s + i.push v + i.unquote(s1) + + .symbol("spread") do (i: In): + var q: MinValue + i.reqQuotationOfQuotations q + var els = newSeq[MinValue](0) + for el in 0..q.qVal.len-1: + els.add i.pop + var count = els.len-1 + for s in q.qVal: + var s1 = s + i.push els[count] + i.unquote(s1) + count.dec + + .symbol("keep") do (i: In): + var q: MinValue + i.reqQuotation q + let v = i.pop + i.push v + i.unquote(q) + i.push v + .symbol("swap") do (i: In): - if i.stack.len < 2: - raiseEmptyStack() + i.reqStackSize 2 + let a = i.pop + let b = i.pop + i.push a + i.push b + + .symbol("nip") do (i: In): + i.reqStackSize 2 + let a = i.pop + discard i.pop + i.push a + + .symbol("over") do (i: In): + i.reqStackSize 2 let a = i.pop let b = i.pop + i.push b i.push a i.push b + .symbol("pick") do (i: In): + i.reqStackSize 3 + let a = i.pop + let b = i.pop + let c = i.pop + i.push c + i.push b + i.push a + i.push c + .symbol("rollup") do (i: In): - if i.stack.len < 3: - raiseEmptyStack() + i.reqStackSize 3 let first = i.pop let second = i.pop let third = i.pop

@@ -89,8 +141,7 @@ i.push second

i.push third .symbol("rolldown") do (i: In): - if i.stack.len < 3: - raiseEmptyStack() + i.reqStackSize 3 let first = i.pop let second = i.pop let third = i.pop
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 ! != $ & ' * + # - % ^ -> . .. / : < <= == => =~ > >= @ ROOT aes all? and any? append ask at atime b bind bool bool? bury1 bury2 bury3 c call call! capitalize case cd chmod choose column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode define delete dget dictionary? dig1 dig2 dig3 dip dir? dirname div dprint dprint! dset dup dupd encode env? error eval even? exists? exit fappend fatal file? filename filter first float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite gets getenv hardlink hidden? id ift ifte import in? indent info int int? interpolate interval io join k keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map match md5 mkdir mod module module-symbols module-sigils mtime mv newline newstack not notice now num number? odd? os password pop popd pred prepend print print! prompt publish puts puts! putenv q quotation? quote quote-bind quote-define random raise regex remove-symbol repeat replace rest reverse rm rmdir run save-symbol scope scope? seal search sha1 sha224 sha256 sha384 sha512 sigils sip size sleep sort source split stack startup stored-symbols str string string? strip succ swap swapd swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote unstack uppercase unzip values version warn which while with xor zip +syntax keyword minDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / : < <= == => =~ > >= @ ROOT aes all? and any? append ask at atime b bind bool bool? bury1 bury2 bury3 c call call! capitalize case cd chmod choose cleave column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode define delete dget dictionary? dig1 dig2 dig3 dip dir? dirname div dprint dprint! dset dup dupd encode env? error eval even? exists? exit fappend fatal file? filename filter first float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite gets getenv hardlink hidden? id if import in? indent info int int? interpolate interval io join k keep keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map match md5 mkdir mod module module-symbols module-sigils mtime mv newline newstack nip not notice now num number? odd? os over password pick pop popd pred prepend print print! prompt publish puts puts! putenv q quotation? quote quote-bind quote-define random raise regex remove-symbol repeat replace rest reverse rm rmdir run save-symbol scope scope? seal search sha1 sha224 sha256 sha384 sha512 sigils sip size sleep sort source split spread stack startup stored-symbols str string string? strip succ sum swap swapd swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote unstack uppercase unzip values version warn when which while with xor zip syntax match minDefaultSigil ;\<[:@'~!$%&$=<>#^*#+/]; contained
M site/contents/_includes/_reference-lang_.mdsite/contents/_includes/_reference-lang_.md

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

{#op||from-json||S||\*|| Converts a JSON string into {{M -> min}} data.#} -{#op||ifte||(2) (1)||\*?|| -If {{2}} evaluates to {{t}} then evaluates {{1}}.#} - -{#op||ifte||(3) (2) (1)||\*?|| +{#op||if||(3) (2) (1)||\*?|| If {{3}} evaluates to {{t}} then evaluates {{2}}, otherwise evaluates {{1}}.#} {#op||import||ยง||{{null}}||

@@ -303,6 +300,9 @@ > > (format-error puts)

> > (0) > > ) try #} +{#op||unless||(2) (1)||\*?|| +If {{2}} evaluates to {{f}} then evaluates {{1}}.#} + {#op||unquote||(\*)||\*|| Pushes the contents of quotation {{q}} on the stack. #}

@@ -314,6 +314,9 @@ Returns a quotation containing all the values of dictionary {{d}}. #}

{#op||version||{{null}}||S|| Returns the current min version number. #} + +{#op||when||(2) (1)||\*?|| +If {{2}} evaluates to {{t}} then evaluates {{1}}.#} {#op||while||(2) (1)||\*?|| > Executes {{1}} while {{2}} evaluates to {{t}}.
M tests/lang.mintests/lang.min

@@ -93,11 +93,14 @@ ((1 2 3 4) (2 +) map (3 4 5 6) ==) assert

(3 (succ) 3 times 6 ==) assert - ((2 3 >) ("YES") ("NO") ifte "NO" ==) assert - ((2 3 <) ("YES") ("NO") ifte "YES" ==) assert + ((2 3 >) ("YES") ("NO") if "NO" ==) assert + ((2 3 <) ("YES") ("NO") if "YES" ==) assert + + ("NO" (2 3 >) ("YES") when "NO" ==) assert + + ((2 3 <) ("YES") when "YES" ==) assert - ("NO" (2 3 >) ("YES") ift "NO" ==) assert - ((2 3 <) ("YES") ift "YES" ==) assert + ((2 3 >) ("YES") unless "YES" ==) assert (0 :c (c 10 <) (c succ @c) while
M tests/num.mintests/num.min

@@ -30,5 +30,7 @@ (-3 2 mod -1 ==) assert

(1000 random 1000 <) assert + ((1 2 3 4 5) sum 15 ==) assert + report newstack
M tests/stack.mintests/stack.min

@@ -13,9 +13,23 @@ (1 dup stack (1 1) ==) assert

(3 2 (1 +) dip + 6 ==) assert + (1 2 4 '+ dip stack (3 4) ==) assert + + (1 2 4 '+ keep stack (1 6 4) ==) assert + ((1) (2 swap append) sip concat (1 2 1) ==) assert (1 (2 3) cons (1 2 3) ==) assert + + (1 2 nip 2 ==) assert + + (1 2 over stack (1 2 1) ==) assert + + (1 2 3 pick stack (1 2 3 1) ==) assert + + ((1 2 3) ('sum 'size) => cleave / 2 ==) assert + + ((1 2) (3 4) ((0 at) (1 at)) spread stack (1 4) ==) assert report newstack
M tests/test.mintests/test.min

@@ -30,7 +30,7 @@ (

check results append quote @results "x" print! ) - ifte + if results ) :assert

@@ -42,7 +42,7 @@ 0 :total

0 :failed results ( total succ @total - (ok !=) (failed succ @failed) () ifte + (ok !=) (failed succ @failed) () if ) map padding total print! " tests executed - " print! failed print! " failed." puts! (

@@ -51,10 +51,10 @@ result

(ok !=) (padding "FAILED: " print! result puts!) () - ifte + if ) map pop ;Remove results accomulator from stack ) :report -) +test +) +test