all repos — min @ 3e4bab89ec96894945ee25e2b8fcb5cc71194274

A small but practical concatenative programming language.

Added tests and docs on user-defined sigils.
h3rald h3rald@h3rald.com
Sun, 13 Dec 2020 09:15:38 +0100
commit

3e4bab89ec96894945ee25e2b8fcb5cc71194274

parent

5589094ee29393bffed7091295f3d906d315aade

M lib/min_lang.nimlib/min_lang.nim

@@ -66,6 +66,10 @@ def.symbol("defined?") do (i: In):

let vals = i.expect("'sym") i.push(i.scope.hasSymbol(vals[0].getString).newVal) + def.symbol("defined-sigil?") do (i: In): + let vals = i.expect("'sym") + i.push(i.scope.hasSigil(vals[0].getString).newVal) + def.symbol("sigils") do (i: In): var q = newSeq[MinValue](0) var scope = i.scope
M next-release.mdnext-release.md

@@ -1,2 +1,3 @@

-* Added support for sigils on double-quoted strings -* Added support for arbitrary strings as dictionary keys +* Added support for sigils on double-quoted strings. +* Added support for arbitrary strings as dictionary keys. +* Added **define-sigil**, **delete-sigil**, **seal-sigil**, **unseal-sigil**, **defined-sigil?**.
M site/contents/learn-data-types.mdsite/contents/learn-data-types.md

@@ -18,7 +18,7 @@ : A series of characters wrapped in double quotes: "Hello, World!".

quotation : A list of elements, which may also contain symbols. Quotations can be used to create heterogenous lists of elements of any data type, and also to create a block of code that will be evaluated later on (quoted program). Example: (1 2 3 + \*) dictionary -: A key/value table. Dictionaries are implemented as an immediately-dequoted quotation, are enclosed in curly braces, and are represented by their symbol definitions. Note that dictionary keys are symbols and therefore can only contain characters allowed in symbols. The {#link-module||dict#} provides some operators on dictionaries. +: A key/value table. Dictionaries are implemented as an immediately-dequoted quotation, are enclosed in curly braces, and are represented by their symbol definitions. Note that dictionary keys must start with `:`and be followed by a double-quoted string, or a single word (which can be written witbout double quotes). The {#link-module||dict#} provides some operators on dictionaries. > %sidebar% > Example

@@ -28,7 +28,7 @@ >

> { > "min" :name > "concatenative" :paradigm - > 2017 :first-release-year + > 2017 :"first release year" > } The {#link-module||logic#} provides predicate operators to check if an element belongs to a particular data type or pseudo-type (`boolean?`, `number?`, `integer?`, `float?`, `string?`, `quotation?`, `dictionary?`).
M site/contents/learn-operators.mdsite/contents/learn-operators.md

@@ -21,11 +21,17 @@ It is possible to define symbols using the {#link-operator||lang||define#} symbol. The following min program defines a new symbol called square that duplicates the first element on the stack and multiplies the two elements:

(dup *) "square" define -Besides symbols, min provides a set of predefined _sigils_ as abbreviations for for commonly-used symbols. For example, the previous definition could be rewritten as follows using sigils: +Besides symbols, you can also define sigila. min provides a set of predefined _sigils_ as abbreviations for for commonly-used symbols. For example, the previous definition could be rewritten as follows using sigils: (dup *) :square -A sigil like `:` can be prepended to a single-word string instead of using the corresponding symbol. Essentially, sigils are nothing more than syntactic sugar. Currently min provides the following sigils: +A sigil like `:` can be prepended to a double-quoted string or a single word (with no spaces) which will be treated as a string instead of using the corresponding symbol. + +For example, the following executes the command `ls -al` and pushes the command return code on the atack: + + !"ls -al"` + +Currently min provides the following sigils: + : Alias for {#link-operator||lang||module#}.

@@ -59,5 +65,19 @@ &

: Alias for {#link-operator||sys||run#}. $ : Alias for {#link-operator||sys||get-env#}. + +Besides system sigils, you can also create your own sigils. Unlike system sigils however, user defined sigils: + +* have the same character restricrions as symbols +* can only be prepended to double-quoted strings +* can be unsealed, deleted, redefined, and sealed. + +Sigils can be a very powerful construct and a way to reduce boulerplate code: you can define a sigil to use as you would use any symbol which requires a single string or quoted symbol on the stack. + +Consider the following example: + + 'from-json 'j define-sigil + +This will define a `j` sigil that will parse any string as JSON and convert it to its corresponding min representation. {#link-learn||quotations||Quotations#}
M site/contents/learn-scopes.mdsite/contents/learn-scopes.md

@@ -4,7 +4,7 @@ title: "Scopes"

----- {@ _defs_.md || 0 @} -As explained in [Definitions](/learn-definitions), min uses lexical scoping to resolve symbols. A *scope* is an execution context (a symbol table really) that: +As explained in [Definitions](/learn-definitions), min uses lexical scoping to resolve symbols and sigils. A *scope* is an execution context (a symbol table really) that: * is created while a new quotation is being dequoted or a dictionary is created. * is destroyed after a quotation has been dequoted. * is attached to a dictionary.
M site/contents/reference-lang.mdsite/contents/reference-lang.md

@@ -92,11 +92,20 @@

{#op||define||{{any}} {{sl}}||{{null}}|| Defines a new symbol {{sl}}, containing the specified value (auto-quoted if not already a quotation).#} +{#op||define-sigil||{{any}} {{sl}}||{{null}}|| +Defines a new sigil {{sl}}, containing the specified value (auto-quoted if not already a quotation).#} + {#op||defined?||{{sl}}||{{b}}|| -Returns {{t}} if {{sl}} is defined, {{f}} otherwise.#} +Returns {{t}} if the symbol {{sl}} is defined, {{f}} otherwise.#} + +{#op||defined-sigil?||{{sl}}||{{b}}|| +Returns {{t}} if the symbol {{sl}} is defined, {{f}} otherwise.#} {#op||delete||{{sl}}||{{null}}|| Deletes the specified symbol {{sl}}.#} + +{#op||delete-sigil||{{sl}}||{{null}}|| +Deletes the specified user-defined sigil {{sl}}.#} {#op||dequote||{{q}}||{{a0p}}|| > Pushes the contents of quotation {{q}} on the stack.

@@ -340,6 +349,9 @@

{#op||seal||{{sl}}||{{null}}|| Seals symbol {{sl}}, so that it cannot be re-assigned. #} +{#op||seal-sigil||{{sl}}||{{null}}|| +Seals the user-defined sigil {{sl}}, so that it cannot be re-defined. #} + {#op||set-type||{{d}} {{sl}}||{{d}}|| Sets the type for dictionary {{d}} to {{sl}}.#}

@@ -436,7 +448,10 @@ {#op||unless||{{q1}} {{q2}}||{{a0p}}||

If {{1}} evaluates to {{f}} then evaluates {{2}}.#} {#op||unseal||{{sl}}||{{null}}|| -Unseals symbol {{sl}}, so that it can be re-assigned. #} +Unseals the user-defined symbol {{sl}}, so that it can be re-assigned. #} + +{#op||unseal-sigil||{{sl}}||{{null}}|| +Unseals sigil {{sl}}, so that it can be re-defined (system sigils cannot be unsealed). #} {#op||version||{{null}}||{{s}}|| Returns the current min version number. #}
M tests/lang.mintests/lang.min

@@ -215,6 +215,17 @@

((2 < 3 and (4 > 2)) >< true) assert ((float 3) >> 3.0 ==) assert + + ( + ("--" suffix "--" prefix) 'del define-sigil + del"test" "--test--" == + ) assert + + ( + ("x" prefix) 'x define-sigil + 'x unseal-sigil 'x delete-sigil + 'x defined-sigil? false == + ) assert report ; Tidy up