A small but practical
concatenative programming language and shell
► For more info, go to https://min-lang.org.
A small but practical concatenative programming language and shell
Home Page: https://min-lang.org
License: MIT License
A small but practical
concatenative programming language and shell
► For more info, go to https://min-lang.org.
In the documentation, 6.15 http Module, the server example doesn't work.
Error: Symbol: tap - Incorrect values found on the stack
I removed tap.
Error: Handler is not a quotation.
Remark: It is confusing that the word "Handler" is uppercase.
I inserted the handler quotation directly into directory. Now it starts. Yeah!
When accessing http://127.0.0.1:5555/nope
Error: Response body is not a string.
I tried adding
body string @Body
before
{body :body}
But it did't help.
I changed the line
{body :body}
to {"hm" :body}
Making the server functionality void.
Error: Response headers are not in a dictionary.
I changed that line to
{"hm" :body {} :headers}
Error: 'qVal' is not accessible using discriminant 'kind' of type 'MinValueObject'
Now I'm stuck :-)
Hi Fabio,
I pulled min, and tried to
nim c -d:release min.nim
again. Got the following error:
Hint: min_math [Processing]
lib/min_math.nim(34, 5) Error: undeclared identifier: 'formatValue'
(As I don't know Nim yet, I don' know where to look.)
(Linux Debian)
Kind greetings.
z.
Current version of the docs:
system
'sym ⇒ ∅
Executes the external command 'sym in the current directory.
This differs from actual behavior where system
pushes return code on stack.
"ls" system
something.min
{1} -> 0
"ls /wrong" system
ls: cannot access '/wrong': No such file or directory
{2} -> 2
In https://min-lang.org/download/ the download links don't work.
Right:
https://github.com/h3rald/min/releases/download/0.19.6/min_v0.19.6_linux_x64.zip
Wrong, and current:
https://github.com/h3rald/min/releases/download/v0.19.6/min_v0.19.6_linux_x64.zip
(the v in the first version number is not correct)
at https://min-lang.org/learn-operators/
z@z ~/min> ./min -i
[/home/z/min]$ 1
{1} -> 1
[/home/z/min]$ 2
{2} -> 2
[/home/z/min]$ (dup *) square define
(!) <repl>(1,14) [square]: Undefined symbol 'square'
<repl>(1,14) in symbol: square
[/home/z/min]$
To reproduce:
root/file1.min
"File 1 loaded!" puts!
root/dir1/file2.min
("file2.min" file?) (args first dirname cd) unless
"../file1" load
Error scenario:
min root/dir1/file2.min
(!) root/dir1/file2.min(3,15) [load]: File 'root/dir1/../file1.min' does not exists.
root/dir1/file2.min(3,15) in symbol: load
No problems when run without cd, from the exact dir like the code above suggests, or, without the "unless" line, from anywhere. It's the cd that messes it up. fread
, fappend
, fwrite
, and even read
(!!) don't conflict with cd under this scenario.
Error message typo: "does not exists" should be "does not exist".
Like always, big fan of this project. 🥇
Currently there is no way to parse a string into a quoted expression without interpreting it. eval
parses and interprets a string, and load
parses and interprets a file.
Scheme-like read
would parse a file into a quoted expression without interpreting it. A parse
function would parse a string into a quoted expression without interpreting it. int
and float
already do that for ints and floats, so this would behave similarly but for quotes.
Hello,
today I took the pleasure to play with min. Thank you for this, it's cool!
As that's the only moment to really read documentation, I did note about spelling issues, strangenesses and whatever. I hope this will help.
Kind regards, and thank you!
zenon
Notes about https://h3rald.com/min/Min_DeveloperGuide.htm
Quotes in bold.
2.2
To exit min shell, press CTRL+C or type exit and press ENTER.
z: For exit to work, there needs to be an int on the stack. Suggested formulations:
3.
..
Then, another list containing two symbols (dup and ) is pushed on the stack. This constitutes a quoted program which, when executed duplicates (dup) the first element on the stack and then multiplies () the two elements together.
z: It can be confusing whether the parens are mentioned or used. I mean, you talk about (dup *) [here i mention the parentheses :-)], and then you use several parentheses. Suggestion:
Then, another list containing two symbols, i.e. dup and *, is pushed on the stack. This constitutes a quoted program which, when executed duplicates the first element on the stack -this is done by dup- and then multiplies -with *- the two elements together.
Parentheses are grouped together one or more elements, so that they are treated as a single element and they are not evaluated immediately.
z: are grouped together -> are used to group together
Symbols can be used to perform operations on the whole stack.
3.1 Data Types
z: the type boolean seems to exist, but is missing.
z: The link to the dict module is broken
3.2.1
..
The synbol**
z: (spelling) synbol -> symbol
.. while the symbol apply can be used to dequote a quotation by pushing its elements on a separate stack.
z: this needs some explanation. until now we only heard of one stack.
3.3 Operators
..
Besides symbols, min provides a set of predefined sigils for commonly-used symbols.
z: I suggest an addition, like:
Besides symbols, min provides a set of predefined sigils as abbreviation for commonly-used symbols.
z: In the sigil list, the links to dget, dset, dhas? are broken
*3.4 Definitions
Being a concatenative language, min does not really need named parameters or variables: simbols just pop..
z: (spell) simbols -> symbols
3.4.1 Lexical scoping and binding
z: broken link to wikipedia
4.2
z: my windows computer doesn't have a HOMEPROFILE environment variable. It has USERPROFILE instead.
I didn'tread the reference yet. Except http; it'll get an extra issue.
What is the preferred method of concatenating two strings? Should we format them using interpolate? Is it reasonable to ask for concat-str
? Maybe something I overlooked? Thank you :)
I'm trying to compile min with NIM 020
Nim Compiler Version 0.20.0 [Linux: i386]
Compiled at 2019-06-06
Copyright (c) 2006-2019 by Andreas Rumpf
git hash: e7471cebae2a404f3e4239f199f5a0c422484aac
active boot switches: -d:release
and I'm getting this error
min/packages/nim-miniz/src/nim_miniz.nim(244, 21) Error: 'typedesc' metatype is not valid here; typed '=' instead of ':'?
I'm new to NIM and "min" and can't find what is wrong here. As the "min" code has not been changed for some time, it might be a regression with the new NIM compiler version.
{1 :uno 2 :due 3}
gives
{1} -> {
2 :due
1 :uno
}
without any error message, i.e. the leftover 3 is just ignored. I think this is not a good idea. It is not exactly a bug, but I suggest to add the feature of giving an error message here.
Trying to use find
like this:
(1 'hello 3) ('hello ==) find
Fails with [==]: Two non-symbol values of similar type are required on the stack
. (Which is probably a usecase in it's own - to have a scheme-like hierarchy of eq?
eqv?
equal?
with more-permissive and less-permissive variants).
Trying to safeguard this with quotation?
, I cannot figure out a way to apply multiple predicates, because quotation?
just executes and puts it's result on the stack, and we have nothing left to check against. Trying to quote-define the argument for reuse like this:
(1 'hello 3) (#item item quotation?) find
Results in [bind]: Attempting to bind undefined symbol: item
. In general I couldn't get quote-define to work even in the form it's seen in tutorial:
(1 2 3 4 5) #my-list
Using the github version of Min.
Thank you for your time <3
I know that args
and opts
exist, but I need a way to get the raw input passed to the program.
My use case is that I want to eval what comes after my program, which isn't possible since args gets rid of the quotation marks around strings.
Is it possible to include this in io or lang?
While playing in REPL, I typed something like this
[path]$ ("a string" puts!") ->
(!) <repl>(1,14) [puts!"]: Undefined symbol 'puts!"'
<repl>(1,14) in symbol: puts!"
<native> in symbol: dequote
<repl>(1,18) in symbol: ->
and after that Tab-completion stopped working. So I got my nose into the source and found out that the template withScope in core/interpreter.nim does not handle exceptions in body
passed to it.
I suggest wrapping body and scope restoring lines in try...finally
.
I can set the loglevel at runtime. Can I read it too?
on https://min-lang.org/download/
Clone the min ->repository.<-
points to https://github.com/h3rald/hastyscribe
Min tries to parse all args as filenames.
For a file like:
#!/usr/bin/env min
args puts
We get following results:
$ min demo.min
("demo.min")
$ min demo.min hello
(x) Cannot read from file: hello
We can pass stuff to our scripts using opts
, and currently there's no overlap with min's options - either it terminates before running the script, like --help
, or ignores the option and passes it to the script, like min -i demo.min
. I imagine when there are more switches in the future the overlap will be awkward. Script options and interpreter options should be separate, based on positioning. Scripts should be able to have their own --help.
min should provide a native dictionary data type. This will likely improve performance and also make the language richer and easier to use.
What are your thoughts on letting bind (@) and quote-bind (#) put their values on top of the stack?
For example, I have this code:
{} :scores ;empty dict for scores to populate
0 :counter
"abcdefghijklmnopqrstuvwxyz" "" split ;add alphabet to stack
(scores swap counter succ @counter counter swap dset) map ;set each letter to their score
and I thought it might look and feel better as:
(scores swap counter succ @counter swap dset) map
Another simpler example is:
1 :x
2 :y
y x + @y x swap
print ;should be 3
I'm using min 0.15.1, at Linux Mint 18.3.
If you try to push an empty quotation (i.e. ()
), it doesn't get on the stack. Instead, nothing happens:
$ ()
{1} -> ()
Is this the expected behaviour? It seems wrong to me since quotations can also represent lists, and an empty list is still a valid one.
In the docs, % is the symbol for both interpolate and dset. In the source:
lib/min_str.nim
def.symbol("%") do (i: In):
i.push("interpolate".newSym)
lib/min_seq.nim
def.sigil("%") do (i: In):
i.push("dset".newSym)
In practice interpolate is the one that gets called.
Simple example:
(1 2 3 4) sum ;10
(1 2 3 4.0) sum ;4.0
This lacks an opening quote:
([$1]$$ " (.) => %)
should be
("[$1]$$ " (.) => %)
Unlike other predefined symbols, this symbol is unsealed
Does not apply to .minrc
, which is where we're likely to redefine prompt from
Thanks to Rafael Carrasco, there's now a min sublime syntax file:
https://github.com/rscarrasco/min-sublime-syntax
This should be mentioned in the docs, along with the min.vim file.
Hi Fabio,
as I always fool around with code while attempting to understand it, the example changed a bit, to match my own taste. I paste it here so you can decide whether to use it for the docu.
; Define the request handler
(
; Assume there is a request on the stack, take it off and give it the name req
:req
; Let's see what we got (print req to standard out)
"THE REQUEST:" puts! req puts!
; The request is a map, we retrieve the value for the key url, and give it the name url
req /url :url
"THE URL is '$1'." url quote % puts!
; Constuct response body
(
(("/datetime" url ==) (timestamp datetime))
(("/timestamp" url ==) (timestamp string))
(("/shutdown" url ==) ("Stopping server..." puts! stop-server))
(("/" url ==) (
; this is a bit short, but works with Chrome, IE, Edge, Safari
"<a href='/datetime'>datetime</a>, <a href='/timestamp'>timestamp</a>, <a href='/shutdown'>stop</a>"
))
((true) ("Invalid Request: $1" url quote %))
) case
:body
; Prepare the response
{} body %body
dup puts!
)
; The request handler is ready, give it the name handler
=handler
; Create the parameter dictionary for the server
{}
handler %handler
5555 %port
; Start server
"Server started on port 5555." puts!
"Press Ctrl+C to stop." puts!
start-server
The main changes are a case structure instead of when, and
"Invalid Request: $1" (url) => %
into
"Invalid Request: $1" url quote %
as I deem this to be easyer to understand.
Then a version without variable naming
; Define the request handler
(
; Assume there is a request on the stack.
; Let's see what we got (print req to standard out)
"THE REQUEST:" puts! dup puts!
; The request is a map, we retrieve the value for the key url
/url
"THE URL is '$1'." dup quote % puts!
; Constuct response body
(
((dup "/datetime" ==) (timestamp datetime))
((dup "/timestamp" ==) (timestamp string))
((dup "/shutdown" ==) ("Stopping server..." puts! stop-server))
((dup "/" ==) (
; this is a bit short, but works with Chrome, IE, Edge, Safari
"<a href='/datetime'>datetime</a>, <a href='/timestamp'>timestamp</a>, <a href='/shutdown'>stop</a>"
))
((true) ("Invalid Request: $1" swap quote %))
) case
; Prepare the response
{} swap %body
dup puts!
)
; The request handler is ready, on top of stack
; Create the parameter dictionary for the server
{}
swap %handler
5555 %port
; Start server
"Server started on port 5555." puts!
"Press Ctrl+C to stop." puts!
start-server
Kind greetings,
z
Creating an example dyntest library, importing it and calling the dynplus function works.
Now, trying to create my own thing, that looks like this:
import mindyn
proc dyntools*(i: In) {.dynlib, exportc.} =
let def = i.define()
def.symbol("get-pos") do (i: In):
var res = newSeq[MinValue](0)
res.add @["line".newVal, i.currSym.line.newVal].newVal(i.scope)
res.add @["column".newVal, i.currSym.column.newVal].newVal(i.scope)
i.push res.newVal(i.scope)
def.finalize("dyntools")
Fails upon calling get-pos
with SIGSEGV: Illegal storage access. (Attempt to read from nil?)
This exact function works when defined in lib/min_lang.nim
. Probably using something that's not implemented in mindyn? Or it can be my nonexistent Nim skills. Please point me in the right direction! :) Thank you
The REPL writes the TOS (when length of stack > 0), prefixed with "[n] ->" or "{n} ->", with n the length (i.e. the number of TOS). The choice of [] or {} is confusing.
Looks like {} is for quotes, [] for anything else including dictionaries (that have the {} in their syntax).
Modules seem to use {} too.
Is there anything else behind?
If not, suggestion:
(n) for quotes
{n} for dictionaries
[], or even no parens otherwise.
Plus: I'd like to be able to switch this off. Having ROOT on the stack is not the only situation where I don't want the TOS to be printed :-)
https://min-lang.org/download/
still points to min 0.19.4 which I recognised because the windows build seems to be broken.
Is it possible for you to implement a mini sockets library? Thanks.
Hello,
after I compiled min some days ago, I just tested the web example and left it.
Now, I find that the REPL stopped echoing the keys I type. So after pressing ENTER, I see the results, but I can't see what I type.
Debian Linux (Windows 10 Linux Subsystem), Nim 1.1.1
I can't tell if this is anything related to min. But I don't know anywhere else to ask.
Any ideas?
Kind greetings, z.
Hey,
First off, I have been having a lot of fun with this language. It makes me think about what I write, and I haven't had that feeling in years.
One shortcoming I have noticed is the lack of web related tools. You do have a sockets library, however I didn't see an easy way to get the HTML of a website. I feel like it would be nice to have GET and POST built in to the library similar to the way Nim handles them. I honestly feel like the example provided was too much and should be abstracted away by a sigil built into min.
I am personally planning on hooking up nimquery by using a dynamic library. Basically, I want an easy way to get the full text of an HTML page.
I see a prelude.min in the project, but no place where it is loaded. Is it?
If yes, can I load a changed prelude instead? (e.g. using a runtime option, like, -p:prolog2.min)
How would I go about doing that? I tried concating in a loop, but I can't concat things that are ints.
Sorry if this is in the docs, I may not have seen that bit.
Is it possible to support the project? Some kind of donates via Bountysource or something like this...
The documentation has:
ROOT
Returns an empty quotation holding a reference to the ROOT scope.
z: What? How can something empty hold a reference? I see a dictionary.
Question: In the examples I've seen until now there is always only one scope, and it is called ROOT. If there are more, it would be nice to explain their logic, and ways to access them.
related?:
with
Applies quotation quot1 within the scope of quot2.
z: I may completely out of grasp here. I assumed that the second argument has to be a dictionary. (First because I don't understand how a quote can have a scope, second because ROOT looks like a dictionary.)
So I tried
(5 5 plus) {'- :plus} with
get-stack
{4} -> (
5
5
(-)
)
I'm surprised that it isn't executed. Maybe I have a wrong interpretation of the word "apply"?
The example for with uses ROOT, and changes ROOT. This makes it a bit confusing, as in general the environment is only used, not changed; as seen in the following example (Again, assuming that I at least remotely understand what I'm doing here ..)
{'- :plus} :arithmetics--
(5 5 plus) arithmetics-- with
[3] -> (-)
get-stack
{4} -> (
5
5
(-)
)
arithmetics--
[5] -> {'- :plus}
debug
∅ ⇒ ∅
Toggles debug mode.
This conflicts with:
debug
a ⇒ a
Prints a and a new line to STDOUT, if logging level is set to debug or lower.
Couldn't find the first one in sources. Debug mode is in practice toggled with 'debug loglevel
.
Currently shorten
throws Quotation too short
error when the quotation is shorter than the given argument. If all we want is to make sure the quotation is no longer than X, a forgiving version of shorten could be useful.
Minlang version:
; quot int -> quot
( :i =q
(q size i >)
(q i shorten)
(q)
if
) :take
Haskell's take
behaves like this. Racket's take raises an exception. In both cases there's also drop
counterpart.
All in all, just an idea, as using min version works perfectly fine.
If you run min shell and type a character like è or §, you get a fatal error:
$ ./min -i
[C:/Data/Dev/_other/min]$ #fatal.nim(39) sysFatal
Error: unhandled exception: index 194 not in 0 .. 31 [IndexError]
Debug stack trace:
[C:/Data/Dev/_other/min]$ C:\Data\Dev\_other\min\min.nim(363) min
C:\Data\Dev\_other\min\min.nim(266) minRepl
C:\Data\Dev\_other\min\min.nim(261) minRepl
C:\Data\Dev\_other\min\packages\nimline\nimline.nim(652) readLine
C:\nim\lib\system\fatal.nim(39) sysFatal
Error: unhandled exception: index 167 not in 0 .. 31 [IndexError]
I can't find any way how to slice string. There isn't any function in the str module for this purpose.
My idea was at first to split a string a char by char into strings in a quote and then get or slice it by functions from seq module however when I try to do so system gets stuck as if it gets into endless loop. The problem is propably that I wanted to split string by empty string:
"abcdefgh" "" split
How can I slice string by another way? (by which I don't have to insert delimiters between every char)
Thanks
Can and
be made infix? Postfix and
is highly noisy for complex code.
What would be really nice is if we could write modules for min in Nim and compile them as dynlibs (.so/.dll) and have min load them on runtime. If you would like I can have a look at implementing this.
I'm curious as to the performance of min. Would be nice to see a few benchmarks, maybe for some of these.
I believe the all?
function isn't working correctly. No matter what I provide the function, it always returns true. For example..
(true) (false ==) all?
-> true
The REPL currently assumes that a complete expression has been entered when you press ENTER, or input a line feed; and it gives an error otherwise. This prohibits me from pasting multi line expressions (as I have them in my files) into the REPL, e.g.
{
1 :uno
2 :due
3 :tres
4 :quattro
}
In the REPL of Julia, e.g., I can enter an expression line by line, it recognizes when the expression is done. Navigation in the REPL (cursor key UP) brings me back to the complete expression, so I can change it as a whole.
For min this would need the REPL to recognise quotations and dictionaries, and nested of the same.
This would be cool.
To replicate, run min -i
:
5 random
{1} -> 2
5 random
{2} -> 4
5 random
{3} -> 3
5 random
{4} -> 1
Close interpreter, restart, repeat, observe same sequence.
How to re-seed the random? I'm trying to shuffle a list of tests so that they run independently of each other, just in case some tests might affect others.
Thank you 🥇
#!/usr/bin/env min
"hello" puts
Min feels like it's made for being an awesome scripting language. Would be awesome to have a special case for a shebang so that we can make script files executable.
Some more comments on the documentation, to get it even better.
Kind greetings from Hamburg!
Types:
z: You may mention that ints (and floats too, I presume) are 64 bit long.
3.4.3
z: spell: pervent -> prevent
in reference-stack
get-stack
Returns a quotation containing the contents of the stack.
z: The stack behavior explains what "returns" means. However, for a person coming from Forth, and looking for the equivalent of .s , it may be helpful to explicitly state:
Puts a quotation containing the contents of the stack on the stack.
clear-stack
z: The stack comment EmptyStack => EmptyStack is wrong, it should be something like:
Anything => EmptyStack
reference-lang
apply
If a dictionary dict is passed, it returns a new dictionary obtained by evaluating each symbol of dict in a separate stack.
z: "each symbol" may mean keys as well as values, but here it seems to refer to values only.
Suggestion:
If a dictionary dict (with values and keys) is passed, it returns a new dictionary obtained by evaluating each value in the dict that is a symbol in a separate stack. (Values that aren't symbols stay as they are.)
1 :uno
2 :due
3 :tres
4 :quattro
{uno :due tres :quattro}
{1} -> {
uno :due
tres :quattro
}
apply
{1} -> {
1 :due
3 :quattro
}
side note that adding an apply solves our issues with the dict literal in the http example.
like this:
{handler :handler 5555 :port} apply
=server-parameters
bool
If a is a non-zero numeric value, it is converted to true, otherwise it is converted to false.
z: natural languages lack parentheses. This can be read as
If a (is a non-zero numeric value, it is converted to true,) otherwise it is converted to false.
The left hand side would apply to anything that is not a number.
Suggestion:
If a is a numeric value, zero is converted to false, otherwise it is converted to true.
If a is a quotation, the empty quotation is converted to false, otherwise it is converted to true.
If a is a string, the empty string and "false" are converted to false, otherwise it is converted to true.
Note: Any dictionary seems to get converted into true.
Note2: This might be nitpicking. Probably every of your readers understands what you intend :-)
dequote
Pushes the contents of quotation quot on the stack.
z: This seems to be something like a transaction.
Suggestion (if I understand it correctly):
Pushes the contents of quotation quot on the stack, as if the elements are put on the stack one by one; except that if any of them fails, the whole operation fails (and the quot stays on the stack).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.