Update SPECIFICATION.MD
This commit is contained in:
parent
5d81bc1bf3
commit
92803e7852
334
SPECIFICATION.MD
334
SPECIFICATION.MD
|
@ -147,24 +147,33 @@ In general the paradigms are designed to be: var'aq-like, Interpreted, Distribut
|
|||
|
||||
# *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
|
||||
|
||||
- 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
|
||||
- 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"
|
||||
- all forms derive from the root form or the "parent of all forms"
|
||||
|
||||
```
|
||||
~ «form_token» {
|
||||
«version» ! version number for auto saving to a database or whatnot
|
||||
«migrate» ! this is to migrate from the previous version to new, in case of interface changes, 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
|
||||
«unit» ! this is for the unit/measures system
|
||||
«display» ! some kind of UI form or None
|
||||
«position» ! a position in space or None
|
||||
} frmdef
|
||||
```
|
||||
"form name" string for the command
|
||||
«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
|
||||
«unit» this is for the unit/measures system
|
||||
«display» some kind of procedure to draw the element in space or None
|
||||
«position» a position in space or None
|
||||
«data» a list containing the data of that form
|
||||
`frmdef`
|
||||
-
|
||||
|
||||
# Substantial Forms
|
||||
|
||||
|
@ -172,155 +181,66 @@ In general the paradigms are designed to be: var'aq-like, Interpreted, Distribut
|
|||
|
||||
### bit (or unsigned units)
|
||||
|
||||
`u8, u16, u32, u64`
|
||||
`u8`, `u16`, `u32`, u64`
|
||||
|
||||
### integer (signed)
|
||||
|
||||
`i8, i16, i32, i64`
|
||||
`i8`, `i16`, `i32`, `i64`
|
||||
|
||||
### real
|
||||
|
||||
`f32, f64`
|
||||
`f32`, `f64`
|
||||
|
||||
## string
|
||||
|
||||
`str`
|
||||
|
||||
matching `''` for char
|
||||
|
||||
matching `""` for string
|
||||
|
||||
strings are always utf8, other formats will need to be done manually
|
||||
|
||||
## logical
|
||||
|
||||
`bool`
|
||||
|
||||
`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
|
||||
|
||||
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
|
||||
|
||||
```
|
||||
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.
|
||||
}
|
||||
```
|
||||
"reason" `panic` -
|
||||
|
||||
## datastructures
|
||||
|
||||
### 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
|
||||
|
||||
```
|
||||
«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)
|
||||
(item1 item2 …)
|
||||
|
||||
### Basic operators
|
||||
|
||||
The following is a list of global operators and their effect:
|
||||
|
||||
```
|
||||
!
|
||||
comment
|
||||
!!
|
||||
block comment (looks for another !! to close)
|
||||
=
|
||||
set operator
|
||||
?
|
||||
unwrap
|
||||
?=
|
||||
unwrap and set
|
||||
\
|
||||
lambda function
|
||||
+
|
||||
addition
|
||||
-
|
||||
subtraction
|
||||
negation
|
||||
*
|
||||
multiplication
|
||||
/
|
||||
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
|
||||
```
|
||||
!
|
||||
line comment
|
||||
!!
|
||||
block comment (looks for another !! to close)
|
||||
{ … }
|
||||
anonymous subtroutine
|
||||
set
|
||||
sets a value in the node's map
|
||||
del
|
||||
delete from node's map
|
||||
add
|
||||
addition
|
||||
sub
|
||||
subtraction
|
||||
mul
|
||||
multiplication
|
||||
div
|
||||
divisor
|
||||
pow
|
||||
power
|
||||
eq
|
||||
equal to
|
||||
ne
|
||||
|
@ -347,7 +267,6 @@ expander
|
|||
bitwise nor
|
||||
bxor
|
||||
bitwise xor
|
||||
```
|
||||
|
||||
## Atom
|
||||
|
||||
|
@ -355,16 +274,11 @@ An atom is an invoked form.
|
|||
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
|
||||
|
||||
Atoms persist in the universe until they are not needed.
|
||||
Each atom has its own "process" with "socket like" i/o.
|
||||
Atoms are pushed onto the stack of the node they are running in.
|
||||
|
||||
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)
|
||||
|
||||
```
|
||||
«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
|
||||
"atom name" («fields», …) `«form»` set
|
||||
|
||||
## Tunnel
|
||||
|
||||
|
@ -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
|
||||
|
||||
### 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();
|
||||
«tunnel-able form» endpoint(endpoint_str);
|
||||
«tunnel» tunnel = endpoint.attach(user, auth);
|
||||
data = tunnel.open(`\some\resource`).read()
|
||||
std.write(data) ! will either write the data or if the data has an error will write the error message instead
|
||||
tunnel.flush()
|
||||
endpoint.clunk()
|
||||
"echo_tunnel" "user" "auth" "http://example.com" url attach set ! create a new tunnel called "echo tunnel" and attach it to the resource
|
||||
"hello world" "/some/rest/echo" echo_tunnel open pop write ! open the endpoint and read write the "hello world" to it
|
||||
echo_tunnel read std write ! syncronously read in the data echoed back from the endpoint and print it to stdout
|
||||
flush
|
||||
clunk pop
|
||||
"echo_tunnel" del
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
## Transforms
|
||||
## subroutines
|
||||
|
||||
```
|
||||
tf «transform_token» («form» «parameter», ...) «return_form», ... {
|
||||
{
|
||||
«instructions»
|
||||
}
|
||||
```
|
||||
|
||||
You can also create a lambda/closure form by using the syntax
|
||||
|
||||
```
|
||||
\«form» «parameter», ... {
|
||||
«instructions»
|
||||
}
|
||||
```
|
||||
|
||||
- Built in transforms
|
||||
- Built in subroutines
|
||||
- sort
|
||||
- filter
|
||||
- trig functions
|
||||
|
@ -441,49 +375,15 @@ You can also create a lambda/closure form by using the syntax
|
|||
|
||||
### loops
|
||||
|
||||
```
|
||||
for «token» in «collection», +/-/iter { «body» }
|
||||
```
|
||||
runs the subroutine infinitely until it breaks or panics
|
||||
|
||||
iterates through each object in the collection setting it to token
|
||||
{ «body» } `loop` -
|
||||
|
||||
```
|
||||
while «boolean expression» { «body» }
|
||||
```
|
||||
runs the subroutine a given number of times
|
||||
|
||||
loops until the expression is false
|
||||
«some numeric value» { «body» } `repeat` -
|
||||
|
||||
```
|
||||
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»);
|
||||
```
|
||||
runs the subroutine a given number of times
|
||||
|
||||
## 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.
|
||||
Since everything is lazily compiled jit anyways it (in theory) doesn't hurt performance much
|
||||
|
||||
```
|
||||
import `https://raw.githubusercontent.com/some_user/some_library/some_file.zwl`;
|
||||
```
|
||||
"https://raw.githubusercontent.com/some_user/some_library/some_file.zwl" `import`
|
||||
|
||||
"./some_local_file.zwl" `import`
|
||||
|
||||
```
|
||||
import `./some_local_file.zwl`;
|
||||
```
|
||||
|
||||
## Universe
|
||||
|
||||
|
@ -525,19 +422,6 @@ Message passing can be achieved by using tunnels.
|
|||
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
|
||||
|
||||
- forms
|
||||
|
|
Loading…
Reference in New Issue