483 lines
9.1 KiB
Org Mode
483 lines
9.1 KiB
Org Mode
* /Undar/ (Reality Engine Language) Design parameters
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: Undar-zongors-reality-engine-language-design-parameters
|
||
:END:
|
||
** What is /Undar/?
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: what-is-undar
|
||
:END:
|
||
/Undar/ is an permacomputing oriented programming language for 3D games with C style syntax.
|
||
The compiler is written in C which should make it easy to port to other
|
||
systems.
|
||
|
||
It is short for "Undarsċieppan" The name comes from the Proto-West-Germanic word [[https://en.wiktionary.org/wiki/Reconstruction:Proto-Germanic/under][Undar]], which means "under" and [[https://en.wiktionary.org/wiki/scieppan][Sċieppan]] meaning "to create". It inspired by the idea of "Sub-creation" from Tolkien and C.S. Lewis, that the developer is sub-creating a reality for their users, whether it be a video game, office software, a website, or a embedded driver.
|
||
|
||
* /Undar/ Grammar and Specification
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: undar-grammar-and-specification
|
||
:END:
|
||
** Plexs
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: plexs
|
||
:END:
|
||
- A =plex= is a **Platonic form** - a structured definition of a kind of being in your program.
|
||
- Not a class: no inheritance, no vtables
|
||
- Methods are functions with implicit =this= argument
|
||
- Instances are **atoms** - persistent, versioned, serializable
|
||
- Stored in the internal graph
|
||
- "A plex defines what a thing is. An atom is its instance in that reality."
|
||
- there are also a list of "substantial plexs" which come with the
|
||
language which are the building blocks for more complex types called "Plexes". If you are coming from object oriented languages you can think of self as "primitive types"
|
||
|
||
#+begin_src ul
|
||
plex «token» {
|
||
init() {
|
||
// values
|
||
}
|
||
}
|
||
|
||
! example
|
||
plex Vec3 {
|
||
init(x real, y real, z real) {
|
||
this.x = x;
|
||
this.y = z;
|
||
this.y = z;
|
||
}
|
||
}
|
||
#+end_src ul
|
||
|
||
* Substantial Plexs
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: substantial-plexs
|
||
:END:
|
||
** numeric
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: numeric
|
||
:END:
|
||
- =real=
|
||
- 32 bit floats
|
||
- =int=
|
||
- 32 bit integer
|
||
- =nat=
|
||
- 32 bit unsigned integer (for loop counting and indexing)
|
||
|
||
** string
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: string
|
||
:END:
|
||
- =str=
|
||
- utf8 / ascii encoded string depending on the language output
|
||
|
||
normal string
|
||
|
||
="«utf8 encoded characters»"=
|
||
|
||
string interpolation
|
||
|
||
="«utf8 encoded characters» ${some_var}"=
|
||
|
||
** binary
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: binary
|
||
:END:
|
||
- =byte=
|
||
- same as uint8 or c char, also used for interop
|
||
|
||
** logical
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: logical
|
||
:END:
|
||
- =bool=
|
||
- =true= / =false=
|
||
|
||
** datastructure
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: datastructure
|
||
:END:
|
||
|
||
*** Array
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: array
|
||
:END:
|
||
|
||
Array of a specific plex
|
||
|
||
#+begin_src ul
|
||
«plex»[«length»] «variable» = [val1, val2, ...];
|
||
#+end_src ul
|
||
|
||
*** Tunnel
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: tunnel
|
||
:END:
|
||
described in "tunnel" section
|
||
|
||
*** Basic operators
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: basic-operators
|
||
:END:
|
||
The following is a list of global operators and their effect:
|
||
|
||
- !
|
||
- comment
|
||
- ??
|
||
- unwrap or
|
||
- .?
|
||
- null check or return error
|
||
- +
|
||
- addition
|
||
- -
|
||
- subtraction
|
||
- negation
|
||
- *
|
||
- multiplication
|
||
- /
|
||
- divisor
|
||
- ^
|
||
- power
|
||
- ==
|
||
- equals
|
||
- <
|
||
- less than
|
||
- >
|
||
- greater than
|
||
- >=
|
||
- greater than or equals
|
||
- <=
|
||
- less than or equals
|
||
- .
|
||
- accessor
|
||
- ++
|
||
- inline add 1
|
||
- --
|
||
- inline subtract 1
|
||
- +=
|
||
- inline add n
|
||
- -=
|
||
- inline subtract n
|
||
- *=
|
||
- inline multiply n
|
||
- \=
|
||
- inline divide n
|
||
|
||
*** logical / bitwise operators
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: logical-bitwise-operators
|
||
:END:
|
||
- =mod=
|
||
- modulo
|
||
- =not=
|
||
- logical not
|
||
- =and=
|
||
- logical and
|
||
- =or=
|
||
- logical or
|
||
- =xor=
|
||
- logical xor
|
||
- =band=
|
||
- bitwise and
|
||
- =bor=
|
||
- bitwise or
|
||
- =bxor=
|
||
- bitwise xor
|
||
- =srl=
|
||
- bit shift right
|
||
- =sll=
|
||
- bit shift left
|
||
|
||
*** keywords
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: keywords
|
||
:END:
|
||
|
||
=let=
|
||
|
||
let operator
|
||
|
||
#+begin_src ul
|
||
let «token» = true;
|
||
#+end_src ul
|
||
|
||
=is=
|
||
|
||
checks if a atom is of that plex
|
||
|
||
#+begin_src ul
|
||
if («token» is real) {
|
||
print("hello yes self is a real?");
|
||
}
|
||
#+end_src ul
|
||
|
||
also used for letting constants
|
||
|
||
=as=
|
||
|
||
coerces a plex as another plex if possible
|
||
|
||
#+begin_src ul
|
||
let «token» = 0; ! default is int
|
||
some_functon(«token» as real); ! needs a real
|
||
#+end_src ul
|
||
|
||
=in=
|
||
|
||
checks if a atom's plex, or a plex implements a contract
|
||
|
||
#+begin_src ul
|
||
if («token» in Tunnel, Drawable) {
|
||
print("im tunnel-able and draw-able");
|
||
}
|
||
#+end_src ul
|
||
|
||
also used inside of the for loops
|
||
|
||
#+begin_src ul
|
||
for («token» in «collection») { «body» }
|
||
#+end_src ul
|
||
|
||
** Atom
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: atom
|
||
:END:
|
||
An atom is an invoked plex.
|
||
|
||
#+begin_src ul
|
||
let «variable» = «plex»(«fields», …);
|
||
#+end_src ul
|
||
|
||
** Tunnel
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: tunnel-1
|
||
:END:
|
||
Represents a path to a file, url endpoint, other process endpoint (like
|
||
a socket, etc.)
|
||
|
||
Tunnels are inspired by translators in gnu/hurd, plan9 9p protocol, and
|
||
unix sockets
|
||
|
||
tunnels are invoked like atoms, but have scope like control flow end
|
||
scope closes the tunnel
|
||
|
||
note the plex must always be of a plex which is "tunnel-able"
|
||
i.e. Files, sockets, etc
|
||
|
||
Tunnels have almost the same interface as 9p since they are closely
|
||
based on 9p.
|
||
|
||
*** transplexs for tunnels
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: transplexs-for-tunnels
|
||
:END:
|
||
=tunnel? : attach(tunnel_atom)= -> open communication
|
||
|
||
=success? : tunnel_atom.clunk()= -> close communication
|
||
|
||
=success? : tunnel_atom.flush()= -> cancels long operation and dumps
|
||
whatever is in buffer
|
||
|
||
=success? : tunnel_atom.open(resource, mode)= -> opens a tunnel for
|
||
doing operations on
|
||
|
||
=success? : tunnel_atom.create(resource)= -> creates the atom from
|
||
the database graph/file from file structure
|
||
|
||
=data? : tunnel_atom.read(resource)= -> reads from a tunnel
|
||
|
||
=success? : tunnel_atom.write(resource, data)= -> writes to a tunnel
|
||
|
||
=success? : tunnel_atom.remove(resource)= -> removes the atom from
|
||
the database graph/file from file structure
|
||
|
||
=stat_data? : tunnel_atom.stat(resource)= -> returns the status of the
|
||
file/resource
|
||
|
||
=version? : tunnel_atom.version()= -> returns the version code for the
|
||
connected tunnel
|
||
|
||
=success? : tunnel_atom.walk(path_or_endpoint)= -> moves around the
|
||
filesystem or through the graph
|
||
|
||
#+begin_src ul
|
||
! client
|
||
let endpoint = Client("tcp://path/to/source");
|
||
let tunnel = endpoint.attach(user, auth);
|
||
let data = tunnel.open("/some/resource").read();
|
||
std.write(data);
|
||
data.flush();
|
||
endpoint.clunk();
|
||
|
||
! server
|
||
let server = Server("tcp://0.0.0.0:25565");
|
||
s.bind("/some/resource", fn () str {
|
||
return "hello world";
|
||
})
|
||
server.start();
|
||
#+end_src ul
|
||
|
||
** Functions
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: functions
|
||
:END:
|
||
Functions are all typechecked statically at compile time. Since we
|
||
always have a "default plex" for all constant values or a developer can
|
||
use the =as= keyword we do not have to define all values like in C,
|
||
while keeping the same plex safety as a more strongly typed language.
|
||
|
||
#+begin_src ul
|
||
fn «token» («parameter» «plex», ...) «return_plex» {
|
||
«body»
|
||
}
|
||
#+end_src ul
|
||
|
||
- Built in transplexs
|
||
- sort
|
||
- filter
|
||
- trig functions
|
||
- calc functions
|
||
- statistical functions
|
||
|
||
** Control flow
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: control-flow
|
||
:END:
|
||
*** loops
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: loops
|
||
:END:
|
||
#+begin_src ul
|
||
for («variable» in «collection») { «body» }
|
||
#+end_src ul
|
||
|
||
iterates through each atom in the collection setting it to variable
|
||
|
||
#+begin_src ul
|
||
while («boolean expression») { «body» }
|
||
#+end_src ul
|
||
|
||
loops until the expression is false
|
||
|
||
#+begin_src ul
|
||
do («variable» = initial_value, end_value, increment) { «body» }
|
||
#+end_src ul
|
||
|
||
loops from initial value to end value by increment value (like a for loop in other languages)
|
||
|
||
*** branching
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: branching
|
||
:END:
|
||
#+begin_src ul
|
||
if («boolean expression») {
|
||
|
||
} else if («boolean expression») {
|
||
|
||
} else {
|
||
|
||
}
|
||
#+end_src ul
|
||
|
||
#+begin_src ul
|
||
switch (value) {
|
||
case A:
|
||
case B:
|
||
case C:
|
||
default:
|
||
}
|
||
#+end_src ul
|
||
|
||
** Error handling
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: error
|
||
:END:
|
||
|
||
Error handling is much like in C/C++ where a try catch can be used.
|
||
|
||
#+begin_src ul
|
||
let rr = nil;
|
||
let var = rr ?? 0; ! value is 0
|
||
try {
|
||
let other_var = 1 / rr; ! will panic
|
||
|
||
} catch (e) {
|
||
print("Caught error ${e}");
|
||
}
|
||
#+end_src ul
|
||
|
||
** Localization
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: localization
|
||
:END:
|
||
will look up the text of «token» in the linked localization.json file
|
||
|
||
#+begin_src ul
|
||
#«token»
|
||
#+end_src ul
|
||
|
||
#+begin_src json
|
||
{
|
||
"some_token": [
|
||
"localization_1": ""
|
||
],
|
||
"some_other_token": [
|
||
"localization_1": "",
|
||
"localization_2": ""
|
||
]
|
||
}
|
||
#+end_src
|
||
|
||
** Libraries and "includes"
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: libraries-and-includes
|
||
:END:
|
||
In most languages the include or use statements get libraries which link
|
||
to other files and so on.
|
||
|
||
#+begin_src ul
|
||
use "./some_local_file.Undar"
|
||
#+end_src ul
|
||
|
||
** Testing
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: testing
|
||
:END:
|
||
*** assertion
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: assertion
|
||
:END:
|
||
#+begin_src ul
|
||
assert(«expression», «expected output») ! returns «error or none»
|
||
#+end_src ul
|
||
|
||
** Measurements
|
||
:PROPERTIES:
|
||
:CUSTOM_ID: measurements
|
||
:END:
|
||
- types
|
||
- time
|
||
- unit
|
||
- seconds (s)
|
||
- subtypes
|
||
- date
|
||
- Default is ISO 8601
|
||
- length
|
||
- unit
|
||
- metre (m)
|
||
- subtypes
|
||
- angle
|
||
- radian (rad)
|
||
- mass
|
||
- unit
|
||
- kilogram (kg)
|
||
- electric current
|
||
- unit
|
||
- ampere (a)
|
||
- temperature
|
||
- unit
|
||
- kelvin (K)
|
||
- amount of substance
|
||
- unit
|
||
- mol (mol)
|
||
- luminous intensity
|
||
- unit
|
||
- candela (candela)
|