all repos — min @ 70cd9f441a13a6d9bf518cda78050ab99a37b94e

A small but practical concatenative programming language.

Updating docs.
h3rald h3rald@h3rald.com
Sat, 12 Oct 2024 14:40:07 +0200
commit

70cd9f441a13a6d9bf518cda78050ab99a37b94e

parent

7925f337299d95ffd63cf04275a6822410401b51

M site/contents/get-started.mdsite/contents/get-started.md

@@ -110,7 +110,7 @@

The result of each operation will be placed on top of the stack, and it will be available to subsequent operation > %min-terminal% -> [[/Users/h3rald/test]$](class:prompt) dup * +> [[/Users/h3rald/test]$](class:prompt) stack.dup * > 16 > [[/Users/h3rald/test]$](class:prompt)

@@ -125,7 +125,7 @@ ## Executing a min program

To execute a min script, you can: -* Run `min eval "... program..."` to execute a program inline. +* Run `min eval "...program..."` to execute a program inline. * Run `min myfile.min` to execute a program contained in a file. * Run `min run <mmm>` to execute the `main` symbol of the specified {#link-page||learn-mmm||min managed module#}. If the managed module is not installed globally, it will be downloaded and installed automatically.
M site/contents/home.mdsite/contents/home.md

@@ -45,7 +45,7 @@ <p>The following example shows how to find recursively all files in the current folder that were modified in the last hour:</p>

<pre> <code>. sys.ls-r (fs.mtime time.now 3600 - >) -filter</code> +seq.filter</code> </pre> <p>The following example shows how to calculate the factorial of 5 using the <code>linrec</code> combinator:</p> <pre>
M site/contents/learn-control-flow.mdsite/contents/learn-control-flow.md

@@ -73,10 +73,10 @@ . ls

( ( (fs.size) - (pop 0) + (stack.pop 0) ) try - ) map - 1 (+) reduce + ) seq.map + 1 (+) seq.reduce This program calculates the size in bytes of all files included in the current directory. Because the {#link-operator||fs||size#} symbol throws an error if the argument provided is not a file (for example, if it is a directory), the `try` symbol is used to remove the error from the stack and push `0` on the stack instead.
M site/contents/learn-data-types.mdsite/contents/learn-data-types.md

@@ -56,9 +56,4 @@ The {#link-module||global#} provides predicate operators to check if an element belongs to a particular data type or pseudo-type (`boolean?`, `number?`, `integer?`, `float?`, ...).

Additionally, the {#link-module||global#} provides operators to convert values from a data type to another (e.g. {#link-global-operator||integer#}, {#link-global-operator||string#}, and so on). -> %note% -> Note -> -> Most of the operators defined in the {#link-module||num#} are able to operate on both integers and floats. - {#link-learn||operators||Operators#}
M site/contents/learn-definitions.mdsite/contents/learn-definitions.md

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

Being a concatenative language, min does not really need named parameters or variables: symbols just pop elements off the main stack in order, and that's normally enough. There is however one small problem with the traditional concatenative paradigm; consider the following program for example: - dup dup + stack.dup stack.dup "\.zip$" match? - swap fs.size 1000000 > and - swap fs.mtime now 3600 - > + stack.swap fs.size 1000000 > and + stack.swap fs.mtime now 3600 - > This program takes a single string corresponding to a file path and returns true if it's a .zip file bigger than 1MB that was modified in the last hour. Sure, it is remarkable that no variables are needed for such a program, but it is not very readable: because no variables are used, it is often necessary to make copies of elements and push them to the end of the stack -- that's what the {#link-operator||stack||dup#} and {#link-operator||stack||swap#} are used for.

@@ -21,7 +21,7 @@

:filepath filepath "\.zip$" match? filepath fs.size 1000000 > - filepath fs.mtime now 3600 - > + filepath fs.mtime time.now 3600 - > and and In this case, the `filepath` symbol is defined and then used on the following three lines, each of which defines a condition to be evaluated. The last line contains just two {#link-global-operator||and#} symbols necessary to compare the three conditions.

@@ -39,13 +39,13 @@ (

a 3 + :a ( a 1 + :a - (a dup * :a) dequote + (a stack.dup * :a) dequote ) dequote ) dequote ...What is the value of the symbol `a` after executing it? -Simple: `4`. Every quotation defines its own scope, and in each scope, a new variable called `a` is defined. In the innermost scope containing the quotation `(a dup * :a)` the value of `a` is set to `64`, but this value is not propagated to the outer scopes. Note also that the value of `a` in the innermost scope is first retrieved from the outer scope (8). +Simple: `4`. Every quotation defines its own scope, and in each scope, a new variable called `a` is defined. In the innermost scope containing the quotation `(a stack.dup * :a)` the value of `a` is set to `64`, but this value is not propagated to the outer scopes. Note also that the value of `a` in the innermost scope is first retrieved from the outer scope (8). If we want to change the value of the original `a` symbol defined in the outermost scope, we have to use the {#link-global-operator||bind#} or its shorthand sigil `@`, so that the program becomes the following:

@@ -54,7 +54,7 @@ (

a 3 + @a ;The value of a is updated to 7. ( a 1 + @a ;The value of a is updated to 8 - (a dup * @a) dequote ;The value of a is now 64 + (a stack.dup * @a) dequote ;The value of a is now 64 ) dequote ) dequote

@@ -66,7 +66,7 @@ 5 :quote

...because the symbol quote is already defined in the root scope. However, note that the following code will _not_ return an error: - (5 :quote quote dup *) -> ;returns 25 + (5 :quote quote stack.dup *) -> ;returns 25 ...because the `quote` symbol is only defined in the root scope and can therefore be redefined in child scopes.
M site/contents/learn-extending.mdsite/contents/learn-extending.md

@@ -4,11 +4,11 @@ title: "Learn: Extending min"

----- {@ _defs_.md || 0 @} -min provides a fairly complete standard library with many useful modules. However, you may feel the need to extend min in order to perform more specialized tasks. +{{m}} provides a fairly complete standard library with many useful modules. However, you may feel the need to extend min in order to perform more specialized tasks. In such situations, you basically have the following options: -* Implementing new min modules using min itself +* Implementing new {{m}} modules using {{m}} itself * Specifying your custom prelude program * Embedding min in your [Nim](https://nim-lang.org) program

@@ -19,9 +19,9 @@

To create a new module, simply create a file containing your operator definitions implemented using either the {#link-global-operator||operator#} operator or the {#link-global-operator||lambda#} operator ``` -(dup *) ^pow2 -(dup dup * *) ^pow3 -(dup * dup *) ^pow4 +(stack.dup *) ^pow2 +(stack.dup stack.dup * *) ^pow3 +(stack.dup * stack.dup *) ^pow4 ```

@@ -33,27 +33,9 @@

2 qp.pow3 qp.pow2 puts ;prints 64 ``` -## Specifying your custom prelude program - -By default, when min is started it loads the following *prelude.min* program: - -``` -; Imports -'io import -'sys import -'stack import -'dict import -'time import -'fs import -'crypto import -'math import -'net import -'http import -; Unseal prompt symbol -'prompt unseal-symbol -``` +## Specifying a _prelude_ program -Essentially, this causes min to import *all* the modules and unseals the {#link-global-operator||prompt#} symbol so that it can be customized. If you want, you can provide your own prelude file to specify your custom behaviors, selectively import modules, and define your own symbols, like this: +If you want, you can execute the {{m}} executable with the `-p` option to specify a _prelude_ program that will be executed when {{m}} is started. This can be useful to specify your custom behaviors, selectively import modules, and define your own symbols, like this: > %min-terminal% > [$](class:prompt) min -i -p:myfile.min
M site/contents/learn-operators.mdsite/contents/learn-operators.md

@@ -14,7 +14,7 @@ There are two types of operators: _symbols_ and _sigils_.

## Symbols -_Symbols_ are the most common type of operator. A min symbol is a single word that is either provided by one of the predefined min {#link-page||reference||modules#} like `dup` or `pwd` or defined by the user. User-defined symbols must: +_Symbols_ are the most common type of operator. A min symbol is a single word that is either provided by one of the predefined min {#link-page||reference||modules#} like `stack.dup` or `sys.pwd` or defined by the user. User-defined symbols must: * Start with a letter or an underscore (\_). * Contain zero or more letters, numbers and/or any of the following characters: `/ ! ? + * _ -`

@@ -42,7 +42,7 @@ ### Using the lambda operator

Sometimes you just want to bind a piece of code to a symbol to reuse it later, typically something simple and easy-to-read. In these cases, you can use the {#link-global-operator||lambda#} operator (or the `^` sigil). For example, the previous `square` operator definition could be rewritten simply as the following. - (dup *) ^square + (stack.dup *) ^square Note that this feels like using {#link-global-operator||define#}, but the main difference between {#link-global-operator||lambda#} and {#link-global-operator||define#} is that `lambda` only works on quotations doesn't auto-quote them, so that they are immediately evaluated when the corresponding symbol is pushed on the stack.

@@ -63,38 +63,22 @@ Besides symbols, you can also define sigils. min provides a set of predefined _sigils_ as abbreviations for commonly used symbols.

A sigil 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 stack: - - !"ls -al" - Currently min provides the following sigils: ' : Alias for {#link-global-operator||quote#}. \: : Alias for {#link-global-operator||define#}. +? +: Alias for {#link-global-operator||help#}. +~ +: Alias for {#link-global-operator||lambda-bind#}. +$ +: Alias for {#link-global-operator|||get-env#}. @ : Alias for {#link-global-operator||bind#}. ^ : Alias for {#link-global-operator||lambda#}. -~ -: Alias for {#link-global-operator||lambda-bind#}. -> -: Alias for {#link-global-operator||save-symbol#}. -< -: Alias for {#link-global-operator||load-symbol#}. -/ -: Alias for {#link-operator||dict||dget#}. -% -: Alias for {#link-operator||dict||dset#}. -? -: Alias for {#link-global-operator||help#}. -! -: Alias for {#link-operator||sys||system#}. -& -: 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:

@@ -136,7 +120,7 @@

( symbol square (num :n ==> num :result) - (n dup * @result) + (n stack.dup * @result) ) operator In this case for example the `square` symbol expects a number on the stack, which will be captured to the symbol `n` and it will place a number on the stack which needs to be bound in the operator body to the symbol `result`.

@@ -190,7 +174,7 @@ (

symbol square (==> quot ^o) ( - (dup *) ~o + (stack.dup *) ~o ) ) ::
M site/contents/learn-quotations.mdsite/contents/learn-quotations.md

@@ -8,7 +8,7 @@ Quotations are the most important thing to understand in min. Besides being the data type used for lists, they are also used to delimit blocks of min code that is not going to be immediately executed.

Consider for example the following min code which returns all the files present in the current folder sorted by name: - . ls (fs.type "file" ==) filter '> sort + sys.pwd sys.ls (fs.type "file" ==) seq.filter '> seq.sort The symbol {#link-operator||seq||filter#} takes two quotations as arguments -- the first quotation on the stack is applied to all the elements of the second quotation on the stack, to determine which elements of the second quotation will be part of the resulting quotation. This is an example of how quotations can be used both as lists and programs.

@@ -17,12 +17,12 @@

{{fdlist => ("dir1" "dir2" file1.txt "file2.txt" "file3.md" "file4.md")}} {{flist => ("file1.txt" "file2.txt" "file3.md" "file4.md")}} -1. The `.` symbol is pushed on the stack, and it is immediately evaluated to the full path to the current directory. -2. The `ls` symbol is pushed on the stack, it consumes the string already on the stack and returns a quotation containing all files and directories within the current directory. +1. The `sys.pwd` symbol is pushed on the stack, and it is immediately evaluated to the full path to the current directory. +2. The `sys.ls` symbol is pushed on the stack, it consumes the string already on the stack and returns a quotation containing all files and directories within the current directory. 3. The quotation `(fs.type 'file ==)` is pushed on the stack. It is treated exactly like a list of data and it is not evaluated. -4. The `filter` symbol is pushed on the stack. This symbol takes two quotations as input, and applies the result of the first quotation on the stack (`(fs.type "file" ==)`) to all elements of the second quotation of the stack (the list of files and directories), returning a new quotation containing only those elements of the second quotation on the stack that satisfy the result of the first quotation. In this case, it returns a new quotation containing only files. +4. The `seq.filter` symbol is pushed on the stack. This symbol takes two quotations as input, and applies the result of the first quotation on the stack (`(fs.type "file" ==)`) to all elements of the second quotation of the stack (the list of files and directories), returning a new quotation containing only those elements of the second quotation on the stack that satisfy the result of the first quotation. In this case, it returns a new quotation containing only files. 5. `'>` is pushed on the stack. The `'` sigil can be used instead of the `quote` symbol to quote a single symbol, `>` in this case. In other words, it is instantly evaluated to the quotation `(>)`. -6. The symbol `sort` is pushed on the stack. This symbol, like `filter`, takes two quotations as input, and applies the first quotation to each element of the second quotation, effectively sorting each element of the second quotation using the predicate expressed by the first quotation. In this case, all files are sorted by name in ascending order. +6. The symbol `seq.sort` is pushed on the stack. This symbol, like `seq.filter`, takes two quotations as input, and applies the first quotation to each element of the second quotation, effectively sorting each element of the second quotation using the predicate expressed by the first quotation. In this case, all files are sorted by name in ascending order. > %tip% > Tip

@@ -36,11 +36,11 @@ When a quotation is created, it is treated as data, no matter what it contains: it is placed on the stack, like an integer or a string would. However, unlike other data types, a quotation can be evaluated in certain situations and when it happens its contents are pushed on the stack.

Consider the following program: - (1 2 3 4 5 6 7) (odd?) filter + (1 2 3 4 5 6 7) (odd?) seq.filter This program returns a new quotation containing all odd numbers contained in quotation `(1 2 3 4 5 6 7)`. -In this case, the second quotation is used to _quote_ the symbol `odd?` so that instead of being executed immediately, it will be executed by the symbol `filter` on each element of the first quotation. In this way, we may say that `(odd?)` is _dequoted_ by the symbol `filter`. +In this case, the second quotation is used to _quote_ the symbol `odd?` so that instead of being executed immediately, it will be executed by the symbol `seq.filter` on each element of the first quotation. In this way, we may say that `(odd?)` is _dequoted_ by the symbol `seq.filter`. The symbol {#link-global-operator||dequote#} or its alias `->` can be used to dequote a quotation by pushing all its elements on the main stack. Essentially, this *executes* the quotation in the current context.
M site/contents/learn-shell.mdsite/contents/learn-shell.md

@@ -29,8 +29,8 @@ Context | Result

---------------------------------------------------------------|-------------- ...a string | Auto-completes the current word using file and directory names. ...a word starting with `$` | Auto-completes the current word using environment variable names. -...a word starting with `'`, `@`, `#`, `>`, `<`, `(`, `?` | Auto-completes the current word using symbol names. -...a word starting with `*` and optionally containing `/`s | Auto-completes the current word using dictionaries and their symbol (nested invocation) +...a word starting with `'`, `@`, `(`, `?` | Auto-completes the current word using symbol names. +...a word ending with `.` | If the current word is a valid dictionary or module, auto-completes any symbol defined in the dictionary or module. Additionally, the following common shortcuts are also available:
M site/contents/learn.mdsite/contents/learn.md

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

If not, well, here's how a short min program looks like: ; This is a comment - (1 2 3 4 5) (dup *) map + (1 2 3 4 5) (stack.dup *) seq.map #| This is a... ...multiline comment |#

@@ -22,8 +22,8 @@

Let's see how it works: 1. First, a list containing the first five integers is pushed on the stack. -2. Then, another list containing two symbols (`dup` and `*`) is pushed on the stack. This constitutes a quoted program which, when executed duplicates the first element on the stack &mdash; this is done by `dup`&mdash; and then multiplies &mdash; with `*`&mdash; the two elements together. -3. Finally, the symbol `map` is pushed on the stack. Map takes a list of elements and a quoted program and applies the program to each element. +2. Then, another list containing two symbols (`stack.dup` and `*`) is pushed on the stack. This constitutes a quoted program which, when executed duplicates the first element on the stack &mdash; this is done by `stack.dup`&mdash; and then multiplies &mdash; with `*`&mdash; the two elements together. +3. Finally, the symbol `seq.map` is pushed on the stack. Map takes a list of elements and a quoted program and applies the program to each element. Note that: