all repos — min @ bbf334c41ef8e933fd7229be9714b2a6771cb64c

A small but practical concatenative programming language.

Documented str module; added find operator.
h3rald h3rald@h3rald.com
Sun, 04 Jun 2017 19:10:08 +0200
commit

bbf334c41ef8e933fd7229be9714b2a6771cb64c

parent

8fdfdf818d7cd7a3999bfa63c2e0888f951b1e75

M core/interpreter.nimcore/interpreter.nim

@@ -110,18 +110,28 @@ i.push e

else: i.push(op.val) -proc apply*(i: In, q: MinValue) = - var i2 = newMinInterpreter("<apply>") - i2.scope = i.scope - i2.withScope(q, q.scope): - for v in q.qVal: - i2.push v - i.push i2.stack.newVal(i.scope) - proc unquote*(i: In, q: var MinValue) = i.withScope(q, q.scope): for v in q.qVal: i.push v + +proc apply*(i: In, q: var MinValue) = + var i2 = newMinInterpreter("<apply>") + i2.trace = i.trace + i2.scope = i.scope + try: + i2.withScope(q, q.scope): + for v in q.qVal: + if (v.kind == minQuotation): + var v2 = v + i2.unquote(v2) + else: + i2.push v + except: + i.currSym = i2.currSym + i.trace = i2.trace + raise + i.push i2.stack.newVal(i.scope) proc push*(i: In, val: MinValue) = if val.kind == minSymbol:
M lib/min_seq.nimlib/min_seq.nim

@@ -120,7 +120,7 @@ i.push res.newVal(i.scope)

def.symbol("apply") do (i: In): let vals = i.expect("quot") - let prog = vals[0] + var prog = vals[0] i.apply prog def.symbol("reverse") do (i: In):
M lib/min_str.nimlib/min_str.nim

@@ -29,11 +29,11 @@ let s = vals[0]

i.push s.getString.strip.newVal def.symbol("split") do (i: In): - let vals = i.expect("string", "string") + let vals = i.expect("'sym", "'sym") let sep = vals[0] let s = vals[1] var q = newSeq[MinValue](0) - for e in s.strVal.split(sep.strVal): + for e in s.getString().split(sep.getString()): q.add e.newVal i.push q.newVal(i.scope)

@@ -79,6 +79,13 @@ let vals = i.expect("int", "string")

let n = vals[0] let s = vals[1] i.push s.getString.indent(n.intVal).newVal + + def.symbol("indexof") do (i: In): + let vals = i.expect("string", "string") + let reg = vals[0] + let str = vals[1] + let index = str.strVal.find(reg.strVal) + i.push index.newVal def.symbol("search") do (i: In): let vals = i.expect("string", "string")
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 args ask atime bind bool boolean? call call! capitalize case cd chmod choose clear-stack cleave column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode define delete dget dictionary? dip dir? dirname div dprint dprint! dset dup encode env? error eval even? exists? exit expect fappend fatal find file? filename filter first flatten float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite get gets get-env get-stack hardlink harvest hidden? id if import in? indent info insert int integer? interpolate interval io join keep keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map map-reduce match md5 mkdir mod module module-symbols module-sigils mtime mv newline nip not notice now num number? odd? opts os over partition password pick pop popd pred prepend print print! prompt publish puts puts! put-env q quotation? quote quote-bind quote-define random raise reduce regex reject remove remove-symbol repeat replace rest reverse rm rmdir run save-symbol scope scope? seal search seq set set-stack sha1 sha224 sha256 sha384 sha512 shorten sigils sip size sleep slice sort source split spread stack startup stored-symbols str string string? strip succ sum swap swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote uppercase unzip values version warn when which while with xor zip +syntax keyword minDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / : < <= == => =~ > >= @ ROOT aes all? and any? append args ask atime bind bool boolean? call call! capitalize case cd chmod choose clear-stack cleave column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode define delete dget dictionary? dip dir? dirname div dprint dprint! dset dup encode env? error eval even? exists? exit expect fappend fatal find file? filename filter first flatten float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite get gets get-env get-stack hardlink harvest hidden? id if import in? indent indexof info insert int integer? interpolate interval io join keep keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map map-reduce match md5 mkdir mod module module-symbols module-sigils mtime mv newline nip not notice now num number? odd? opts os over partition password pick pop popd pred prepend print print! prompt publish puts puts! put-env q quotation? quote quote-bind quote-define random raise reduce regex reject remove remove-symbol repeat replace rest reverse rm rmdir run save-symbol scope scope? seal search seq set set-stack sha1 sha224 sha256 sha384 sha512 shorten sigils sip size sleep slice sort source split spread stack startup stored-symbols str string string? strip succ sum swap swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote uppercase unzip values version warn when which while with xor zip syntax match minDefaultSigil ;\<[:@'~!$%&$=<>#^*#+/]; contained
M site/contents/_includes/_defs_.mdsite/contents/_includes/_defs_.md

@@ -25,6 +25,8 @@ {{s0p => [string<sub>\*</sub>](class:kwd)}}

{{s => [string](class:kwd)}} {{s1 => [string<sub>1</sub>](class:kwd)}} {{s2 => [string<sub>2</sub>](class:kwd)}} +{{s3 => [string<sub>3</sub>](class:kwd)}} +{{s4 => [string<sub>4</sub>](class:kwd)}} {{b => [bool](class:kwd)}} {{b1 => [bool<sub>1</sub>](class:kwd)}} {{b2 => [bool<sub>2</sub>](class:kwd)}}

@@ -33,10 +35,14 @@ {{01 => [<sub>?</sub>](class:kwd)}}

{{0p => [<sub>\*</sub>](class:kwd)}} {{1p => [<sub>\+</sub>](class:kwd)}} {{sl => [&apos;sym](class:kwd)}} +{{sl1 => [&apos;sym<sub>1</sub>](class:kwd)}} +{{sl2 => [&apos;sym<sub>2</sub>](class:kwd)}} {{f => [false](class:kwd)}} {{t => [true](class:kwd)}} {{null => &#x2205;}} {{m => _min_}} + +{{sgregex => [sgregex](https://github.com/snake5/sgregex).}} {#op => <a id="op-$1"></>

@@ -68,3 +74,5 @@ #}

{# link-module => [`$1` Module](/reference-$1/) #} +{# link-operator => [`$2`](/reference-$1/$2) #} +
M site/contents/_includes/_reference-str.mdsite/contents/_includes/_reference-str.md

@@ -1,1 +1,140 @@

-... +{@ _defs_.md || 0 @} + +{#alias||%||interpolate#} + +{#alias||=~||regex#} + +{#op||capitalize||{{sl}}||{{s}}|| +Returns a copy of {{sl}} with the first character capitalized.#} + +{#op||indent||{{sl}} {{i}}||{{s}}|| +Returns {{s}} containing {{sl}} indented with {{i}} spaces.#} + +{#op||indexof||{{s1}} {{s2}}||{{i}}|| +If {{s2}} is contained in {{s1}}, returns the index of the first match or -1 if no match is found. #} + +{#op||interpolate||{{s}} {{q}}||{{s}}|| +> Substitutes the placeholders included in {{s}} with the values in {{q}}. +> > %note% +> > Note +> > +> > If {{q}} contains symbols or quotations, they are not interpreted. To do so, call `apply` before interpolating. +> +> > %sidebar% +> > Example +> > +> > The following code (executed in a directory called '/Users/h3rald/Development/min' containing 19 files): +> > +> > `"Directory '$1' includes $2 files." (. (. ls 'file? filter size)) apply interpolate` +> > +> > produces: +> > +> > `"Directory '/Users/h3rald/Development/min' includes 19 files."`#} + +{#op||join||{{q}} {{sl}}||{{s}}|| +Joins the elements of {{q}} using separator {{sl}}, producing {{s}}.#} + +{#op||length||{{sl}}||{{i}}|| +Returns the length of {{sl}}.#} + +{#op||lowercase||{{sl}}||{{s}}|| +Returns a copy of {{sl}} converted to lowercase.#} + +{#op||match||{{s1}} {{s2}}||{{b}}|| +> Returns {{t}} if {{s2}} matches {{s1}}, {{f}} otherwise. +> > %tip% +> > Tip +> > +> > {{s2}} can be a {{sgregex}}-compatible regular expression.#} + +{#op||repeat||{{sl}} {{i}}||{{s}}|| +Returns {{s}} containing {{sl}} repeated {{i}} times.#} + +{#op||replace||{{s1}} {{s2}} {{s3}}||{{s4}}|| +> Returns a copy of {{s1}} containing all occurrences of {{s2}} replaced by {{s3}} +> > %tip% +> > Tip +> > +> > {{s2}} can be a {{sgregex}}-compatible regular expression. +> +> > %sidebar% +> > Example +> > +> > The following: +> > +> > `"This is a stupid test. Is it really a stupid test?" " s[a-z]+" " simple" replace` +> > +> > produces: `"This is a simple test. Is it really a simple test?"`#} + +{#op||regex||{{s1}} {{s2}}||{{q}}|| +> Performs a search and/or a search-and-replace operation using pattern {{s2}}. +> +> {{s2}} can be one of the following patterns: +> +> * **/**_search-regex_**/**_modifiers_ +> * **s/**_search-regex_**/**_replacemenet_**/**_modifiers_ +> +> {{q}} is always a quotation containing: +> +> * One or more strings containing the first match and captures (if any), like for the `search` operator. +> * A string containing the resuling string after the search-and-replace operation. +> +> > %tip% +> > Tip +> > +> > * _search-regex_ can be a {{sgregex}}-compatible regular expression. +> > * _modifiers_ are optionals can contain one or more of the following characters, in any order: +> > * **i**: case-insensitive match. +> > * **m**: multi-line match. +> > * **s**: dot character includes newlines. +> +> > %sidebar% +> > Example: Search +> > +> > The following: +> > +> > `"This is a GOOD idea." "/(good) idea/i" regex` +> > +> > produces: `("GOOD idea", "GOOD")` +> +> > %sidebar% +> > Example: Search and Replace +> > +> > The following: +> > +> > `"This is a GOOD idea." "s/good/bad/i" regex` +> > +> > produces: `("This is a bad idea")`#} + +{#op||search||{{s1}} {{s2}}||{{q}}|| +> Returns a quotation containing the first occurrence of {{s2}} within {{s2}}. Note that: +> +> * The first element of {{q}} is the matching substring. +> * Other elements (if any) contain captured substrings. +> +> > %tip% +> > Tip +> > +> > {{s2}} can be a {{sgregex}}-compatible regular expression. +> +> > %sidebar% +> > Example +> > +> > The following: +> > +> > `"192.168.1.1, 127.0.0.1" "[0-9]+\.[0-9]+\.([0-9]+)\.([0-9]+)" search` +> > +> > produces: `("192.168.1.1", "1", "1")`#} + +{#op||split||{{sl1}} {{sl2}}||{{q}}|| +Splits {{sl1}} using separator {{sl2}} and returns the resulting strings within the quotation {{q}}. #} + +{#op||strip||{{sl}}||{{s}}|| +Returns {{s}}, which is set to {{sl}} with leading and trailing spaces removed.#} + +{#op||titleize||{{sl}}||{{s}}|| +Returns a copy of {{sl}} in which the first character of each word is capitalized.#} + +{#op||uppercase||{{sl1}}||{{sl2}}|| +Returns a copy of {{sl}} converted to uppercase.#} +
M tests/str.mintests/str.min

@@ -5,12 +5,16 @@ "str" describe

("$1 - $2 - $3" (1 true "test") interpolate "1 - true - test" ==) assert + ("$1 + $2 = $3" (2 2 (2 2 +)) apply interpolate "2 + 2 = 4" ==) assert + (" test " strip "test" ==) assert ("test" length 4 ==) assert ("a,b,c" "," split ("a" "b" "c") ==) assert + ("This is a test" "is" indexof 2 ==) assert + ("test #1" "[0-9]" search ("1") ==) assert ("This is test #1" "test #([0-9])" search ("test #1" "1") ==) assert

@@ -19,7 +23,7 @@ ("This is a random string" "random" match true ==) assert

("something is not something else" "some" "any" replace "anything is not anything else" ==) assert - ("MiNiM is a concatenative programming language" "/^minim/i" =~ ("MiNiM") ==) assert + ("MiN is a concatenative programming language" "/^min/i" =~ ("MiN") ==) assert ("This is a difficult test" "s/difficult/simple/" =~ ("This is a simple test") ==) assert