* /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)