Update SPECIFICATION.MD

This commit is contained in:
zongor 2024-07-20 15:42:18 -04:00
parent 5d81bc1bf3
commit 92803e7852
1 changed files with 109 additions and 225 deletions

View File

@ -147,24 +147,33 @@ In general the paradigms are designed to be: var'aq-like, Interpreted, Distribut
# *zwl* Grammar and Specification # *zwl* Grammar and Specification
How do I read these operations?
With most of the operations below they will be in the follwing format
anything between « » should be read as a type of thing and not a literal
for any operations they will look like
« input arguments » `operator` « output arguments »
unless stated you should assume that any arguments are pushed or poped from the nodes stack, if it does not return a value I will use `-`
## Form ## Form
- describe storage objects "the ideal state of the object" - describe storage objects "the ideal state of the object"
- atoms (invoked forms) are stored in the internal database which is why they need version numbers - atoms (invoked forms) are stored in the internal database which is why they need version numbers
- Forms can be implementations of interfaces, collsions are not important as the names of interfaces only carry what needs to be implemented a not any implemtntation itself. for people coming from OOP you can think of this similar to an abstract class. - Forms can be implementations of interfaces, collsions are not important as the names of interfaces only carry what needs to be implemented a not any implemtntation itself. for people coming from OOP you can think of this similar to an abstract class.
- there are also a list of "substantial forms" which come with the language which are the building blocks for more complex forms. If you are coming from object oriented languages you can think of this as "primitive types" - there are also a list of "substantial forms" which come with the language which are the building blocks for more complex forms. If you are coming from object oriented languages you can think of this as "primitive types"
- all forms derive from the root form or the "parent of all forms"
``` "form name" string for the command
~ «form_token» { «dimensions» this returns how many dimensions it can exist in, 0th means non drawable, 2 means 2D GUI usually, 3 means 3D object, and >3 is somthing you will have to implement yourself, e.g. miegakure
«version» ! version number for auto saving to a database or whatnot «unit» this is for the unit/measures system
«migrate» ! this is to migrate from the previous version to new, in case of interface changes, or None «display» some kind of procedure to draw the element in space or None
«dimensions» ! this returns how many dimensions it can exist in, 0th means non drawable, 2 means 2D GUI usually, 3 means 3D object, and >3 is somthing you will have to implement yourself, e.g. miegakure «position» a position in space or None
«unit» ! this is for the unit/measures system «data» a list containing the data of that form
«display» ! some kind of UI form or None `frmdef`
«position» ! a position in space or None -
} frmdef
```
# Substantial Forms # Substantial Forms
@ -172,155 +181,66 @@ In general the paradigms are designed to be: var'aq-like, Interpreted, Distribut
### bit (or unsigned units) ### bit (or unsigned units)
`u8, u16, u32, u64` `u8`, `u16`, `u32`, u64`
### integer (signed) ### integer (signed)
`i8, i16, i32, i64` `i8`, `i16`, `i32`, `i64`
### real ### real
`f32, f64` `f32`, `f64`
## string ## string
`str`
matching `''` for char
matching `""` for string matching `""` for string
strings are always utf8, other formats will need to be done manually strings are always utf8, other formats will need to be done manually
## logical ## logical
`bool`
`true` / `false` `true` / `false`
Also follows the style boolean 'c' rules of nonzero / zero, but the interpreter will make fun of you
## null values
*zwl* does not have null, because each value can have an error on it.
error is a form which describes an error that occurred, it is similar to the Go programming language and is returned as a monad like the maybe monad above and is unwrapped in a similar way, take a look at the tunnel section for an example
```
1| i32 a = 3; ! this would be similar to the follwing in Rust: `let a: Result<i32, &'static str> = Ok(3);`
2| i32 b; ! or like in Rust: `let b: Result<i32, &'static str>;`
3|
4| i32 x = a; ! this will set x to 3
5| i32 y = b; ! this will set the error part of y to an undefined error because we tried setting a undefined variable to another variable, imagine in Rust: `let y: Result<i32, &'static str> = Err("undefined");`
6| i32 z = b ? 1; ! this will check if b has an error and since it does it will set y = 1;
7|
8| print("$x $y $z\n") ! prints 3, "error: failed to unwrap a 'none' on line 5", 1
```
additionally, if a value has an error it will evaluate as "false" and Just as "true" in a boolean check, unless you are explicitly checking for an error
### panic ### panic
calling panic on a variable that has an error will halt execution of the node that is running. calling panic on a variable that has an error will halt execution of the node that is running. it will broadcast the reason to the main kernel and to all other nodes listening
``` "reason" `panic` -
i32 n;
i32 e = n; ! this will set e's error that we tried setting n to undefined.
err (e) { ! we can check if there is an error by using the `err` keyword in the same way as an `if`
panic(e); ! panic will halt exectution of the task and pass a message what the error was to all the other tasks listening.
}
```
## datastructures ## datastructures
### list ### list
A list will act similar to a list in LISP, it is esentially a block of memory that has an internal "length" and other operations.
syntax syntax
``` (item1 item2 …)
«form»[] «atom_token» = [item1 item2 …];
```
### set
same as list except does not allow duplicates, allows set operations
n is the starting size of the set
```
«form»{} «atom_token»();
```
sets also have the following transforms associated with them
### map
a simple form to form storage
```
«form» ~> «form» «atom_token»();
```
### tunnel
described in "tunnel" section
### uri
matching `` (backtics)
### Basic operators ### Basic operators
The following is a list of global operators and their effect: The following is a list of global operators and their effect:
``` !
! line comment
comment !!
!! block comment (looks for another !! to close)
block comment (looks for another !! to close) { … }
= anonymous subtroutine
set operator set
? sets a value in the node's map
unwrap del
?= delete from node's map
unwrap and set add
\ addition
lambda function sub
+ subtraction
addition mul
- multiplication
subtraction div
negation divisor
* pow
multiplication power
/
divisor
**
power
.
accessor
..
expander
(1..10) is the same as writing (1,2,3,4,5,6,7,8,9,10)
++
inline add 1
--
inline subtract 1
+=
inline add n
-=
inline subtract n
*=
inline multiply n
\=
inline divide n
**=
inline power n
```
### basic transforms
```
eq eq
equal to equal to
ne ne
@ -347,7 +267,6 @@ expander
bitwise nor bitwise nor
bxor bxor
bitwise xor bitwise xor
```
## Atom ## Atom
@ -355,17 +274,12 @@ An atom is an invoked form.
For those of you coming from an object oriented language For those of you coming from an object oriented language
this is similar to creating an object on the heap using "new" keyword or the like this is similar to creating an object on the heap using "new" keyword or the like
Atoms persist in the universe until they are not needed. Atoms are pushed onto the stack of the node they are running in.
Each atom has its own "process" with "socket like" i/o.
an atom can be created (in the universe) using the following syntax: Here is an example of creating an atom and storing it as a variable in nram (the nodes map)
``` "atom name" («fields», …) `«form»` set
«form» «atom_token»(«fields», …);
```
note: if the atom name is omitted, it will make the atom unaccessible! but it is allowed, this is usually useful in the "universe" namespace
## Tunnel ## Tunnel
Represents a path to a file, url endpoint, other process endpoint (like a socket, etc.) Represents a path to a file, url endpoint, other process endpoint (like a socket, etc.)
@ -376,61 +290,81 @@ tunnels are invoked like atoms, but have scope like control flow end scope close
note the form must always be of a form which is "tunnel-able" i.e. Files, sockets, etc note the form must always be of a form which is "tunnel-able" i.e. Files, sockets, etc
### transforms for tunnels ### subroutines for tunnels
`tunnel attach(tunnel_atom)` -> open communication #### create a new tunnel
`bool success = tunnel_atom.clunk()` -> close communication «field», … `«tunnel-able form»` tunnel
`bool success = tunnel_atom.flush()` -> cancels long operation and dumps whatever is in buffer open communication
`bool success = tunnel_atom.open(resource, mode)` -> opens a tunnel for doing operations on tunnel args, … `attach` bool tunnel
`bool success = tunnel_atom.create(resource)` -> creates the object from the database graph/file from file structure close communication
`«form» data = tunnel_atom.read(resource)` -> reads from a tunnel tunnel `clunk` bool tunnel
`bool success = tunnel_atom.write(resource, data)` -> writes to a tunnel cancels long operation and dumps whatever is in buffer
`bool success = tunnel_atom.remove(resource)` -> removes the object from the database graph/file from file structure tunnel `flush` bool tunnel
`«form» stat_data = tunnel_atom.stat(resource)` -> returns the status of the file/resource opens a tunnel for doing operations on
`«form» version = tunnel_atom.version()` -> returns the version code for the connected tunnel tunnel resource mode `open` bool tunnel
`bool success = tunnel_atom.walk(path_or_endpoint)` -> moves around the filesystem or through the graph creates the object from the database graph/file from file structure
tunnel resource `create` bool tunnel
reads from a tunnel
tunnel resource `read` «form» tunnel
writes to a tunnel, gets response from endpoint
tunnel resource data `write` bool tunnel
removes the object from the database graph/file from file structure
tunnel resource `remove` bool tunnel
returns the status of the file/resource
tunnel resource `stat` tunnel «status data»
returns the version code for the connected tunnel, returns of version info
tunnel `version` (list) tunnel
moves around the filesystem or through the graph
tunnel "path_or_endpoint" `walk` bool tunnel
#### example
``` ```
«some form» data(); "echo_tunnel" "user" "auth" "http://example.com" url attach set ! create a new tunnel called "echo tunnel" and attach it to the resource
«tunnel-able form» endpoint(endpoint_str); "hello world" "/some/rest/echo" echo_tunnel open pop write ! open the endpoint and read write the "hello world" to it
«tunnel» tunnel = endpoint.attach(user, auth); echo_tunnel read std write ! syncronously read in the data echoed back from the endpoint and print it to stdout
data = tunnel.open(`\some\resource`).read() flush
std.write(data) ! will either write the data or if the data has an error will write the error message instead clunk pop
tunnel.flush() "echo_tunnel" del
endpoint.clunk()
``` ```
in "terminal mode" the default tunnel is std in "terminal mode" the default tunnel is std
in "web mode" the default tunnels are log, info, trace, warn, error, but note these are all special tunnels which only accept write commands in "web mode" the default tunnels are log, info, trace, warn, error, but note these are all special tunnels which only accept write commands
## Transforms ## subroutines
``` ```
tf «transform_token» («form» «parameter», ...) «return_form», ... { {
«instructions» «instructions»
} }
``` ```
You can also create a lambda/closure form by using the syntax - Built in subroutines
```
\«form» «parameter», ... {
«instructions»
}
```
- Built in transforms
- sort - sort
- filter - filter
- trig functions - trig functions
@ -441,49 +375,15 @@ You can also create a lambda/closure form by using the syntax
### loops ### loops
``` runs the subroutine infinitely until it breaks or panics
for «token» in «collection», +/-/iter { «body» }
```
iterates through each object in the collection setting it to token { «body» } `loop` -
``` runs the subroutine a given number of times
while «boolean expression» { «body» }
```
loops until the expression is false «some numeric value» { «body» } `repeat` -
``` runs the subroutine a given number of times
loop { «body» }
```
loops infinitely until break or return
### match
```
match «token» {
'a' -> actionA
'x' -> actionX
'y'..'z' -> {
actionY
actionZ
}
someTransformOfTokensForm -> actionSomeTransform
\«token's form» t { t <= 5 and t > 0 } -> actionLambda
_ -> actionNoMatch
}
```
### exceptions
take a look at error's, but you can panic on an error like this:
```
panic(error("error message"));
panic(error(-3));
panic(«some_error_token»);
```
## Libraries and “includes” ## Libraries and “includes”
@ -491,13 +391,10 @@ In most languages the include or use statements get libraries which link to othe
The other way to do this would be to just specifically “name” the paths using a tunnel and import it. You can even use localization tokens to create config files. The other way to do this would be to just specifically “name” the paths using a tunnel and import it. You can even use localization tokens to create config files.
Since everything is lazily compiled jit anyways it (in theory) doesn't hurt performance much Since everything is lazily compiled jit anyways it (in theory) doesn't hurt performance much
``` "https://raw.githubusercontent.com/some_user/some_library/some_file.zwl" `import`
import `https://raw.githubusercontent.com/some_user/some_library/some_file.zwl`;
``` "./some_local_file.zwl" `import`
```
import `./some_local_file.zwl`;
```
## Universe ## Universe
@ -525,19 +422,6 @@ Message passing can be achieved by using tunnels.
probably should take concurrency stuff from golang; its very nice probably should take concurrency stuff from golang; its very nice
## Testing
Tests are done inside of a `test` block
```
test some_test {
someTransform() -> true
}
```
## Measurement ## Measurement
- forms - forms