.
-
-
Save kittech0/4e615e4e5df1cf355cb55a8c10297957 to your computer and use it in GitHub Desktop.
Welcome to the idea of language based around Kotlin and Rust!
Comments in this language use C-like syntax.
// One-liner
function(/* Insides */) // Description of it!
/*
Multiple lines!
*/There are multiple ways of declaring variables in this language. By default, every variable is immutable, and you need to specify mutability. The syntax for declaring variables is Rust-like, with an optional let keyword.
Example of an immutable variable:
variable: i32 = 2
let variable: i32 = 2 // `let` is optional and not required; it will work the same in the example aboveExample of mutable variable:
mut variable: i32 = 2 //you just put `mut` before name!
let mut variable: i32 = 2 // same here but after `let`There are also constant values, which are strictly immutable and only allow primitive values. They require the const keyword before the name. They are automatically inlined by the compiler.
const CONSTANT_VARIABLE: i32 = 2Uses rust-like types
- Signed integers:
i8,i16,i32,i64,i128andisize - Unsigned integer:
u8,u16,u32,u64,u128andusize - Floating-point numbers:
f8,f16,f32,f64,f128andfsize - Characters:
char(to create character use''example:'a') - Boolean:
bool(trueorfalse)
Tuples have a Rust-like syntax. They are groups with multiple types of values inside and have a fixed size. Tuples can be destructured. Example way of creating:
tuple: (fsize:u16:bool) = (1.0, 24, true)Accessing values is different from Rust. Instead of tuple.i (where i is the index/place of the value in the tuple), it uses array-like syntax for accessing elements.
Example way of accessing value:
//tuple: (fsize, u16, bool) = (1.0, 24, true)
value: fsize = tuple[0] //returns 1.0 of type fsize
// remember `tuple` variable is (1.0, 24, true)You can also destructure tuples using a different variable syntax, which destructures the tuple into multiple variables. Example of destruction:
//tuple: (fsize, u16, bool) = (1.0, 24, true)
(float: fsize, number: u16, answer: bool) = tuple
float //returns 1.0 with type fsize
number //returns 24 with type u16
answer //returns true with type bool Arrays in this language have a Kotlin-like syntax. They are collections of elements of the same type and have a fixed size. Example way of creating:
array: char[5] = ['h','e','l','l','o']In the above example, char[5] specifies the type of the array (char) and its fixed size (5).
You can access values inside an array using the indexing syntax, similar to tuples. Example of accessing value:
array: char[5] = ['h','e','l','l','o']
letter: &char = array[3] //returns `l` with reference of charYou can also modify values in array.
mut array: char[5] = ['h','e','l','l','o']
array[2] := 'w'Sets in this language have a math-like syntax. They are collections of elements of the same type and have a dynamic size. Sets only allow unique values. Example use:
set: char{} = {'a','b','c','d','e','f','g','h'} Example of adding new values:
mut set: char{} = {'a','b','c','d','e','f','g','h'}
set.add('i') // adds one value on the end of set
set.push('j') //adds one value on the start of set
set[1] := 'l' //replaces value in this indexExample of removing values:
mut set: char{} = {'j','a','b','c','d','e','f','g','h','i'}
set.removeFirst() //removes first value in set
set.removeLast() //removes last value in set
set.remove(2) //removes value with index 2 which is 'a'Getting values from a set is done in the same way as accessing values in an array Example of getting value:
set: char{} = {'a','b','c','d','e','f','g','h'}
letter: &char = set[0] //'a'Maps in this language have a JavaScript-like syntax. They have key-value pairs, where the keys are unique and the values can be of any type. Maps are created by specifying the key and value types inside curly braces. Example use:
map: {char:i32} = { //char is key type, i32 is value type
'a' : 1
'b' : 2
'c' : 3
'g' : 1
}You can also modify values in map.
mut map: {char:i32} = {
'a' : 1
'b' : 2
'c' : 3
'g' : 1
}
map['g'] := 2 //modifying value based on key!
map.remove('a') //removes value from map by keyTables in this language are similar to maps but allow multiple values per key. The syntax for creating a table is the same as for maps, but with additional types specified inside the curly braces. Example use:
table: {char:i32:bool} = {
'a' : 64 : true
'b' : 32 : false
'c' : 16 : true
}When getting a value from a table, you receive a reference to a tuple containing the values associated with the key. Example of getting value:
table: {char:i32:bool} = {
'a' : 64 : true
'b' : 32 : false
'c' : 16 : true
}
value: &(&i32,&bool) = table['a'] //returns (64,true)Example of modifying value:
table: {char: i32: bool} = {
'a' : 64 : true,
'b' : 32 : false,
'c' : 16 : true
}
table['a'] := (18, false) // modifies the entire tuple associated with the key 'a'
table['a'][0] := 24 // modifies a specific value in the tuple associated with the key 'a'List is similiar to set, but instead it doesn't require values to be unique. Getting value is exactly the same. Example use:
list: [[char]] = [['a','a','g','f']]Lambdas are a replacement for functions in this language. They use a different syntax from other languages. To create a lambda, you use ||. By default, they return nothing. Lambdas are executed like C functions. They also support compact one-line execution, similar to Kotlin.
Example use of lambda in variable
lambda: || = something()Lambdas can span multiple lines by using {}.
Example use:
lambda: || = {
something()
something()
}Lambdas can also have a return type, which is specified after ||, like || -> i32.
Example use:
lambda: || -> i32 = 2 //will return `2`You can also specify when the lambda should return, if required; otherwise, it will return the last statement in the block. Instead of using return as in other languages, you use <- to indicate a return.
Example use:
lambda: || -> i32 = {
2+2 //won't be returned
<- 4+4 //will return 8 and stop lambda here
5-5 //won't be reached
}Lambdas also support arguments. Arguments are specified inside ||, similar to other languages' function syntax.
Example use:
lambda: |x: i32| -> i32 = x^2 //if executed `lambda(2)` will return `4`
//You can also specify which argument you pass value by using `lambda(x=2)`Arguments also support default values, as you would see in Kotlin. Example use:
lambda: |x: i32 = 2| -> i32 = x^2 //If not passed anything by doing `lambda()` it will return 4, if did for example `lambda(6)` it will return 36.Lambdas can be used as arguments, and there is a shorthand syntax for it. Example use:
lambda: |lam: || | = lam()
//without shorting syntax
lambda(|| = std@println("Hello world!"))
//with shorting syntax
lambda || = std@println("hello world!")When multiple arguments are used, the shorthand syntax can be applied to each argument. Example of a lambda with multiple arguments and shorthand syntax:
lambda: |x: i32, lam: |y: i32|| = lam(x)
lambda(32) |x| = std@println("Hello {x}") //you do exactly same thing but instead you add the value in `()`This language supports creating modules and importing them. The standard library is included by default and can be used. Modules use a syntax similar to Rust, and the namespace specifier is @.
Example module:
mod MyModule
pub powerMe: |x: i128| -> i128 = x^2 // Use `pub` keyword to make something public!
//to use it you would write MyModule@powerMe(2) (returns 4)
//Also before using module, you need to import it using `import MyModule`Structures are used to create more complex data types from existing types. The language combines Rust's structure syntax with Kotlin's implementation of function syntax. Example usage:
struct Person {
mut name: std@String = "Jane" // To make a mutable variable in a structure, use `mut`
pub age: u16 // By default, values in a structure are only available for implemented functions. Using `pub` makes them accessible internally and externally.
} // You can initialize it using `Person("Kittech", 20)` or `Person(age = 16)`
Person.sayHello: || = std@out.println("{$.name}: Hello!") // Implements a function for the structure
// To access values from inside the structure, use `$` (similar to `self` in Rust or `this` in Kotlin)
mut Person.setName: |name: std@String| = $.name = name // To mutate any value in the structure, the implemented lambda also needs to be mutable
*Person.new: |name: std@String, age: u16| -> it = it(name, age)
// This is a static variable on Person. You create it by putting `Person` between `||`.
// `it` is used for returning itself and only stores the constructor and static variables.
// Static variables are immutable and cannot be changed.A DSL is a building pattern commonly found in Groovy or Kotlin. It makes it easy for developers to create builder functions, and for users to use them without problems. In this language, we can implement a builder using lambda-like syntax with some differences. Example implementation:
// Example structure
struct ExampleBuild {
mut number: isize
}
mut ExampleBuild.addNumber: |num: isize| = $.number += num
// DSL builder implementation
builder: |num: isize, example: ExampleBuild.|| | = ExampleBuild(num).apply(example)
// `ExampleBuild.||` is similar to a lambda but provides DSL abilities
// Example usage
builder(100) || = {
$.addNumber(1)
$.addNumber(100)
} // Returns ExampleBuild with `number` equal to 201Every struct has an .apply function that can be called by passing the builder DSL lambda as an argument.
In this language, the entry point of a program is defined using the init keyword which is DSL builder This is similar to the main function in other languages.
Example of an initializer:
init || = {
std@println("Hello world!")
}The code inside the initializer block will be executed when the program starts.
- Addition:
+ - Subtraction:
- - Multiplication:
* - Power:
^ - Modulo:
% - Root:
^^ - Approximate:
~ - Equal:
== - Not equal:
!= - Greater than:
> - Lesser than:
< - Greater or equal than:
>= - Lesser or equal than:
<= - Division:
\ - Bitwise logic:
~,&,|,** - Bitwise shifts:
<<,>>
This language supports references that can be found in Rust programming language. They have exactly the same syntax like you would found in rust. To modify reference, use :=.
Example use:
foo: |x: &mut i128| = x := x^2
bar: |x: &i128| = std@println("{x}")
init || = {
mut fooBar: i128 = 1234567890
std@println("{fooBar}") //prints 1234567890
bar(&fooBar) //prints 1234567890
foo(&mut foodBar) //modifes the reference
bar(&fooBar) //prints 1524157875019052100
std@println("{fooBar}") //prints 1524157875019052100
}This language by default is not nullable, but it has nullability syntax exact the same for kotlin ?.
Example use:
foo: |x: i32| -> i32? = null
bar: |x: i32?| -> i32 = x!! //will panic if x is null
init || = {
num: i32 = 10
nullableNum: i32? = foo(num)
notNullableNum: i32 = bar(nullableNum) //panics.
}