Azkal Language
A programming language built from scratch in TypeScript, featuring closures, objects, arrays, template strings, pipe operator, destructuring, and more.
Installation
npm install -g azkal-lang
Then run files with azkal myfile.azkal or start the REPL with just azkal.
Hello World
print("Hello, World!")
Save as hello.azkal and run with azkal hello.azkal.
Variables
Declare variables with let. Azkal uses block scoping.
let name = "Azkal"
let age = 1
let active = true
let nothing = null
// Reassign
name = "Azkal v2"
// Block scoping
{
let x = "inner"
print(x) // "inner"
}
// x is not accessible here
Types
Azkal has 7 types: number, string, boolean, null, array, object, function.
type(42) // "number"
type("hello") // "string"
type(true) // "boolean"
type(null) // "null"
type([1,2]) // "array"
type({a:1}) // "object"
type(fn(){}) // "function"
Functions
Functions are first-class values. Declare with fn.
// Named function
fn add(a, b) {
return a + b
}
// Anonymous function
let double = fn(x) { return x * 2 }
// Default parameters
fn greet(name = "World") {
print(`Hello, {name}!`)
}
greet() // Hello, World!
greet("Azkal") // Hello, Azkal!
// Closures
fn counter() {
let n = 0
return fn() {
n = n + 1
return n
}
}
let c = counter()
print(c()) // 1
print(c()) // 2
Control Flow
If / Else
if x > 0 {
print("positive")
} else if x == 0 {
print("zero")
} else {
print("negative")
}
While Loop
let i = 0
while i < 10 {
print(i)
i = i + 1
}
For...In Loop
for item in [1, 2, 3] {
print(item)
}
for ch in "hello" {
print(ch)
}
for key in {a: 1, b: 2} {
print(key)
}
Use break and continue to control loop execution.
Arrays
let nums = [1, 2, 3, 4, 5]
nums[0] // 1
nums.length // 5
// Spread
let merged = [...nums, 6, 7]
| Method | Description |
|---|---|
| .map(f) | Transform each element |
| .filter(f) | Keep matching elements |
| .reduce(f, init) | Combine into single value |
| .find(f) | First matching element |
| .includes(v) | Check if value exists |
| .sort() | Sort ascending (returns new array) |
| .reverse() | Reverse order (returns new array) |
| .flat() | Flatten nested arrays |
| .push(v) | Add to end (mutates) |
| .pop() | Remove from end (mutates) |
| .length | Number of elements |
Objects
let user = {
name: "alky",
level: 99
}
user.name // "alky"
user["level"] // 99
user.hp = 100 // add new property
// Shorthand
let x = 10
let y = 20
let point = { x, y } // { x: 10, y: 20 }
| Method | Description |
|---|---|
| .keys() | Array of keys |
| .values() | Array of values |
| .has(key) | Check if key exists |
| .remove(key) | Delete a key |
Strings
let s = "Hello, World!"
s[0] // "H"
s.length // 13
| Method | Description |
|---|---|
| .upper() | Uppercase |
| .lower() | Lowercase |
| .trim() | Remove whitespace |
| .split(sep) | Split into array |
| .contains(s) | Check substring |
| .replace(a, b) | Replace all occurrences |
| .starts_with(s) | Check prefix |
| .ends_with(s) | Check suffix |
| .chars() | Array of characters |
| .length | String length |
Template Strings
Use backticks with {expr} for interpolation.
let name = "world"
print(`Hello, {name}!`)
print(`2 + 2 = {2 + 2}`)
// Nested expressions
print(`{name.upper()} has {name.length} chars`)
Destructuring
Extract values from arrays and objects into variables.
Array Destructuring
let [a, b, c] = [1, 2, 3]
print(a) // 1
print(b) // 2
print(c) // 3
// Extra names get null
let [x, y] = [10]
print(y) // null
Object Destructuring
let user = { name: "alky", age: 25 }
let { name, age } = user
print(name) // "alky"
print(age) // 25
Pipe Operator
The pipe operator |> passes the left value as the first argument to the right function.
42 |> str // "42"
5 |> fn(x) { return x * 2 }
|> fn(x) { return x + 1 }
|> print // 11
// Great for data pipelines
[1, 2, 3, 4, 5]
.filter(fn(x) { return x > 2 })
.map(fn(x) { return x * 10 })
Error Handling
Use try/catch to handle runtime errors gracefully.
try {
let result = 1 / 0
} catch (e) {
print(`Caught: {e}`)
}
// Catch undefined variables
try {
print(unknown_var)
} catch (e) {
print("Variable not found")
}
The catch variable e contains the error message as a string.
Comments
// Single-line comment
/* Multi-line
block comment */
let x = 1 /* inline */ + 2
Operators
| Operator | Description |
|---|---|
| + - * / % | Arithmetic |
| == != | Equality |
| < > <= >= | Comparison |
| and or ! | Logical |
| |> | Pipe |
| ... | Spread |
String concatenation with + works when either operand is a string.
Standard Library
| Function | Description |
|---|---|
| print(...args) | Output values (space-separated) |
| type(val) | Get type as string |
| len(val) | Length of array, string, or object |
| range(n) | Array [0, 1, ..., n-1] |
| range(a, b) | Array [a, a+1, ..., b-1] |
| range(a, b, step) | Array with step |
| num(val) | Convert to number (null on failure) |
| str(val) | Convert to string |
| bool(val) | Convert to boolean |
| join(arr, sep) | Join array into string |
| slice(val, start, end) | Slice array or string |
| append(arr, val) | Return new array with val appended |
| reverse(val) | Reverse array or string |
| keys(obj) | Object keys as array |
| values(obj) | Object values as array |
| clock() | Current time in seconds |
Math
| Function | Description |
|---|---|
| PI | 3.141592653589793 |
| abs(n) | Absolute value |
| floor(n) | Round down |
| ceil(n) | Round up |
| round(n) | Round to nearest |
| sqrt(n) | Square root |
| pow(a, b) | a raised to power b |
| min(a, b) | Smaller of two numbers |
| max(a, b) | Larger of two numbers |
| random() | Random number between 0 and 1 |