Added tests and docs on user-defined sigils.
h3rald h3rald@h3rald.com
Sun, 13 Dec 2020 09:15:38 +0100
7 files changed,
60 insertions(+),
9 deletions(-)
M
lib/min_lang.nim
→
lib/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.md
→
next-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.md
→
site/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.md
→
site/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.md
→
site/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.md
→
site/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.min
→
tests/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