# _ztl_ (zongors transpiler language) Design parameters ## What is _ztl_? _ztl_ is an language transpiler with C/Zig/Rust/Lua/Fortran/Javascript/Elixir style syntax. The transpiler bootstrap is written in Lua which should make it easy to port to other systems. # _ztl_ Grammar and Specification ## Trait Describes an interface that can be applied to a type, collisions are not important as the names of traits only carry what needs to be implemented a not any implementation itself. for people coming from OOP you can think of traits similar to an abstract class. ``` trait Hashable { fn hash(self) -> u64 } struct Vec { x: f32, y: f32, z: f32, } ! maybe the worst hash function ever? impl Hashable Vec { fn hash(self: Vec) -> u64 { return (self.x bxor (self.y sll 16) bxor (self.z sll 32) bor (self.z sll 48)) } } ``` ## Types - Types can be either structs, enums, or unions. - struct - holds data - union - holds different kinds of data - enum - holds a key to integer map of data - there are also a list of "substantial types" which come with the language which are the building blocks for more complex types. If you are coming from object oriented languages you can think of self as "primitive types" ``` struct «type_token» { ! values } enum «type_token» { ! values } union «type_token» { ! values } ``` # Substantial Types ## numeric ### bit (or unsigned units) - `u8` - unsigned 8 bit integer (uint8_t) - `u16` - unsigned 16 bit integer (uint16_t) - `u32` - unsigned 32 bit integer (uint32_t) - `u64` - unsigned 64 bit integer (uint64_t) ### integer (signed) - `i8` - signed 8 bit integer (int8_t) - `i16` - signed 16 bit integer (int16_t) - `i32` - signed 32 bit integer (int32_t) - `i64` - signed 64 bit integer (int64_t) ### real - `f32` - 32 bit floating point (float) - `f64` - 64 bit floating point (double) ## string - `str` - utf8 / ascii encoded string depending on the language output normal string `"«utf8 encoded characters»"` multiline literal string (also used for string interpolation like in JS) `` `«utf8 encoded characters» {some_var}` `` ## logical `bool` `true` / `false` Also follows the style boolean 'c' rules of nonzero / zero, but the compiler will make fun of you ## null values ``` let a = 3 let b = nil let c = #"nope!" let x = a let y = b ?? 1 stdout.write("%d%d\n", x, y) ! outputs 3, 1 ``` ## error error is a type 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. You could also think of it as ``` let error = %"something borked" let some_var = error ?? 0; let some_var = error ?? panic(error) ``` ## datastructure Much like Lua, zwl only has tables. Lua's tables are amazing and very unique. Why have five different datastructures to do things when you can just have one that does everything? ### table syntax (yes I was nice and kept the syntax the same as most C like langs) ``` let «variable» = «type»[] ! same as a map of int->«type» !or as an array let «variable» = [val1, val2, ...] ! or as a map let «variable» = {key1: val1, key2: val2, ...} ``` ### tunnel described in "tunnel" section ### Basic operators The following is a list of global operators and their effect: - `!` - comment - `!!` - block comment (looks for another !! to close) - `=` - set operator - `??` - unwrap or - `+` - addition - `-` - subtraction - negation - `*` - multiplication - `/` - divisor - `**` - power - `==` - equals - `<` - less than - `>` - greater than - `>=` - greater than or equals - `<=` - less than or equals - `|>` - curry a function into another function (like haskell shove) - `.` - 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 ### logical / bitwise operators - `eq` - equal to - `ne` - not equals to - `mod` - modulo - `not` - logical not - `and` - logical and - `or` - logical or - `nor` - logical nor - `nand` - logical nand - `xor` - logical xor - `band` - bitwise and - `bor` - bitwise or - `bnor` - bitwise nor - `bxor` - bitwise xor - `srl` - bit shift right - `sll` - bit shift left ### keywords `is` checks if a object is of that type ``` if («token» is i32) { stdout.print("hello yes self is i32?") } ``` `as` coerces a type as another type if possible ``` let «token» = 0 some_functon_that_needs_a_i32(«token» as i32) ``` `impls` checks if a object's type, or a type impls another type ``` if («token» impls Tunnel) { stdout.print("im tunnel-able") } ``` ## Object An object is an invoked type. ``` let «variable» = «type»(«fields», …) ``` ## Tunnel 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 objects, but have scope like control flow end scope closes the tunnel note the type must always be of a type which is "tunnel-able" i.e. Files, sockets, etc ### transtypes for tunnels `tunnel? : attach(tunnel_object)` -> open communication `success? : tunnel_object.clunk()` -> close communication `success? : tunnel_object.flush()` -> cancels long operation and dumps whatever is in buffer `success? : tunnel_object.open(resource, mode)` -> opens a tunnel for doing operations on `success? : tunnel_object.create(resource)` -> creates the object from the database graph/file from file structure `data? : tunnel_object.read(resource)` -> reads from a tunnel `success? : tunnel_object.write(resource, data)` -> writes to a tunnel `success? : tunnel_object.remove(resource)` -> removes the object from the database graph/file from file structure `stat_data? : tunnel_object.stat(resource)` -> returns the status of the file/resource `version? : tunnel_object.version()` -> returns the version code for the connected tunnel `success? : tunnel_object.walk(path_or_endpoint)` -> moves around the filesystem or through the graph ``` let endpoint = «tunnel-able type»(endpoint_str) let tunnel = endpoint.attach(user, auth) let data = tunnel.?open("\some\resource").?read() stdout.write(data) data.flush() endpoint.clunk() ``` in "terminal mode" the default tunnel is stdout in "web mode" the default tunnels are log, info, trace, warn, error, but note these are all special tunnels which only accept write commands ## Functions ``` fn «token» («type» «parameter», ...) -> «return_type» { «instructions» } ``` - Built in transtypes - sort - filter - trig functions - calc functions - statistical functions ## Control flow ### loops ``` for («token» in «collection») { «body» } ``` iterates through each object in the collection setting it to token ``` each («token» in «collection») { «body» } ``` iterates through each key in the collection setting it to token ``` while («boolean expression») { «body» } ``` loops until the expression is false ``` loop { «body» } ``` loops infinitely until break or return ### branching ``` match «token» { 'a' -> actionA 'x' -> actionX 'y'..'z' -> { actionY actionZ } _ -> actionNoMatch } ``` ### exceptions take a look at error's, but you can panic on an error like self: ``` panic(#"error message") panic(#3) panic(«some_error_token») ``` ## Localization will look up the text of «token» in the linked localization.json file ``` $«token» ``` ```json { "some_token": [ "localization_1": "" ], "some_other_token": [ "localization_1": "", "localization_2": "" ] } ``` ## Libraries and “includes” In most languages the include or use statements get libraries which link to other files and so on. Self quickly gets confusing and so requires package managers and installers, etc. The other way to do self 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 pertypeance much ``` use `https://code.example.com/some_library/some_file.ztl` ``` ``` use `./some_local_file.ztl` ``` ## Testing Tests are done inside of a `test` block ``` test some_test { someFunction() => true } ``` ### assertion ``` assert(«expression», «expected output») ! returns «error or none» ``` ## Measurements - 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)