An experiment in programming languages
- variables and arrays (immutable by default)
- structs (immutable)
- complex expressions (parantheses, precedence, PEMDAS)
- basic type inference for variable declarations
- type checking for if statements and variables with type annotations
- arithmetic (+, -, *, /, %)
- if, else if, else
- functions (local only)
- stack-based interpreter
- JS codegen
- (WIP) WASM codegen
- modern, flexible language
- flexible but strong typing
- multiple compile targets
- interop with existing languages / ecosystems
let a = 1847899 + (301111 * 5) // Complex expressions
let b = "hello" // Type inference
let c = ["hi", "hello", b] // Homogeneous arrays
let d: bool = true // Type annotations
var e = "what" // Mutable variables
e = "so ..."
print(c[2]) // Array indexing
if (d) { // "if - else if - else" chains
print(c)
} else if (false || d) {
print("hi !")
} else {
print("ho !")
}
function hi(a) { // Functions
let array: i32[] = [1, 3, 42, 127, (10 % 3)]
print("Hello world !")
print(array)
print(array.length)
function hello(b) { // Local functions
print("heck")
print(b)
}
}
hi(9)
print(hi)
type Person = struct { // Structs
name: str,
age: i32
}
let p: Person = { "James", 18 }
print(p.name)
The cyan compiler (cyanc
) currently works using an internal representation called FIR (Frontend Intermediate Representation).
FIR is a transformed code format on which type-checking and symbol resolution is performed. Therefore, any outputted FIR is valid code.
Here are the compilation steps :
- The runtime source code (
resources/runtime/runtime.cy
) is compiled using the same steps as normal code; - A
FirDocument
(root node of any FIR tree) is created for the program source code, and the symbols from the compiled runtime are inserted into it; - The source code is lexed and parsed (
cỳan.compiler.parser
) into an AST (abstract syntax tree); - The AST is lowered into FIR (
cyan.lower.ast2fir
), using the previously mentionnedFirDocument
. This is where type-checking and symbol resolutioon happens; - (Temporary) The FIR is turned into generated JS.
- The codegen component consumes cyan FIR, which includes some pretty high-level concepts like structs and for loops. That makes some targets very difficult or impossible to implement.
- Member access expressions only work on structs
Contributions and issues are welcomed and encouraged.
If you encounter any problem with the compiler, or wish to ask about a feature you'd like, feel free to open an issue.