Umka is a statically typed embeddable scripting language. It combines the simplicity and flexibility needed for scripting with a compile-time protection against type errors. Its aim is to follow the Python Zen principle Explicit is better than implicit more consistently than dynamically typed languages generally do.
- Clean syntax inspired by Go
- Cross-platform bytecode compiler and virtual machine
- Garbage collection
- Polymorphism via interfaces
- Multitasking based on fibers
- Type inference
- Distribution as a dynamic library with a simple C API
- C99 source
Due to the efficient for
loop implementation and support for static data structures, Umka demonstrates high performance in multidimensional array operations and similar tasks.
400 x 400 matrix multiplication (AMD A4-3300M @ 1.9 GHz, Windows 7)
- Download the latest release for Windows and Linux (Note: both versions use
/
as path separator) - Take a tour of Umka
- Explore the raytracer example that demonstrates many language features like fibers, interfaces and dynamic arrays
- Try the more realistic C+Umka embedded scripting example (Note: raylib is required to compile and run it)
- Look at the language grammar to better understand Umka capabilities
Raytracer example
C+Umka 3D camera example
fn main() {
printf("Hello Umka!\n")
}
const a = 3
const b* = 2.38 // Exported identifier
const (
c = sin(b) / 5
d = "Hello" + " World"
)
Built-in constants
true false
null
type IntPtr = ^uint16 // Pointer
type Arr = [a]real // Array
type (
DynArr = [][5]int // Dynamic array
String = str // String
Quat = struct { // Structure
q: [4]real
normalized: bool
}
Printable = interface { // Interface
print(): int
}
ErrFn = fn(code: int) // Function
)
Built-in types
void
int8 int16 int32 int
uint8 uint16 uint32
bool
char
real32 real
fiber
var e: int
var f: String = d + "!"
var (
g: Arr = [3]real{2.3, -4.1 / 2, b}
h: DynArr
)
q := Quat{q: [4]real{1, 0, 0, 0}, normalized: true}
fn tan(x: real): real {return sin(x) / cos(x)}
Built-in functions
printf fprintf sprintf scanf fscanf sscanf
round trunc fabs sqrt sin cos atan exp log
new make append delete len sizeof
fiberspawn fibercall fiberalive
error
fn (a: ^Arr) print(): int {
printf("Arr: {8.3lf} {8.3lf} {8.3lf}\n", a[0], a[1], a[2])
return 0
}
h = make([][5]int, 3) // Dynamic arrays are initialized with make()
sum := 0.0
y := tan(30 * std.pi / 180)
h = append(h, [5]int{10, 20, 30, 40, 50})
h = delete(h, 1)
g.print()
if err := getError(); !err {
std.println("Done")
}
switch a {
case 1, 3, 5, 7: std.println(std.itoa(a) + " is odd")
case 2, 4, 6, 8: std.println(std.itoa(a) + " is even")
default: std.println("I don't know")
}
for i := 0; i < len(g); i++ {
if fabs(g[i]) > 1e12 {break}
if g[i] < 0 {continue}
sum += g[i]
}
fn childFunc(parent: ^fiber, buf: ^int) {
for i := 0; i < 5; i++ {
std.println("Child : i=" + std.itoa(i) + " buf=" + std.itoa(buf^))
buf^ = i * 3
fibercall(parent)
}
}
fn parentFunc() {
a := 0
child := fiberspawn(childFunc, &a)
for i := 0; i < 10; i++ {
std.println("Parent: i=" + std.itoa(i) + " buf=" + std.itoa(a))
a = i * 7
if fiberalive(child) {
fibercall(child)
}
}
}
program = module.
module = [import ";"] decls.
import = "import" (importItem | "(" {importItem ";"} ")").
importItem = stringLiteral.
decls = decl {";" decl}.
decl = typeDecl | constDecl | varDecl | fnDecl.
typeDecl = "type" (typeDeclItem | "(" {typeDeclItem ";"} ")").
typeDeclItem = ident exportMark "=" type.
constDecl = "const" (constDeclItem | "(" {constDeclItem ";"} ")").
constDeclItem = ident exportMark "=" expr.
varDecl = "var" (varDeclItem | "(" {varDeclItem ";"} ")").
varDeclItem = typedIdentList | ident ":" type "=" expr.
shortVarDecl = declAssignmentStmt.
fnDecl = "fn" [rcvSignature] ident exportMark signature [block].
rcvSignature = "(" ident ":" type ")".
signature = "(" [typedIdentList ["=" expr] {"," typedIdentList ["=" expr]}] ")" [":" type].
exportMark = ["*"].
identList = ident exportMark {"," ident exportMark}.
typedIdentList = identList ":" type.
type = qualIdent | ptrType | arrayType | dynArrayType | strType | structType | fnType.
ptrType = "^" type.
arrayType = "[" expr "]" type.
dynArrayType = "[" "]" type.
strType = "str" ["[" expr "]"].
structType = "struct" "{" {typedIdentList ";"} "}".
interfaceType = "interface" "{" {ident signature ";"} "}".
fnType = "fn" signature.
block = "{" StmtList "}".
fnBlock = block.
fnPrototype = .
stmtList = Stmt {";" Stmt}.
stmt = decl | block | simpleStmt |
ifStmt | switchStmt | forStmt | breakStmt | continueStmt | returnStmt.
simpleStmt = assignmentStmt | shortAssignmentStmt | incDecStmt | callStmt.
assignmentStmt = designator "=" expr.
shortAssignmentStmt = designator ("+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "~=") expr.
declAssignmentStmt = ident ":=" expr.
incDecStmt = designator ("++" | "--").
callStmt = designator.
ifStmt = "if" [shortVarDecl ";"] expr block ["else" (ifStmt | block)].
switchStmt = "switch" [shortVarDecl ";"] expr "{" {case} [default] "}".
case = "case" expr {"," expr} ":" stmtList.
default = "default" ":" stmtList.
forStmt = "for" [shortVarDecl ";"] expr [";" simpleStmt] block.
breakStmt = "break".
continueStmt = "continue".
returnStmt = "return" [expr].
expr = logicalTerm {"||" logicalTerm}.
logicalTerm = relation {"&&" relation}.
relation = relationTerm [("==" | "!=" | "<" | "<=" | ">" | ">=") relationTerm].
relationTerm = term {("+" | "-" | "|" | "~") term}.
term = factor {("*" | "/" | "%" | "<<" | ">>" | "&") factor}.
factor = designator | intNumber | realNumber |
charLiteral | stringLiteral | compositeLiteral | typeCast |
("+" | "-" | "!" | "~" | "&") factor | "(" expr ")".
designator = primary selectors.
primary = qualIdent | builtinCall.
qualIdent = [ident "."] ident.
builtinCall = qualIdent "(" [expr {"," expr}] ")".
selectors = {derefSelector | indexSelector | fieldSelector | callSelector}.
derefSelector = "^".
indexSelector = "[" expr "]".
fieldSelector = "." ident.
callSelector = actualParams.
actualParams = "(" [expr {"," expr}] ")".
compositeLiteral = arrayLiteral | structLiteral.
arrayLiteral = "{" [expr {"," expr}] "}".
structLiteral = "{" [ident ":" expr {"," ident ":" expr}] "}".
typeCast = type "(" expr ")".
ident = (letter | "_") {letter | "_" | digit}.
intNumber = decNumber | hexHumber.
decNumber = digit {digit}.
hexNumber = "0" "x" hexDigit {hexDigit}.
realNumber = decNumber ["." decNumber] [("E" | "e") decNumber].
charLiteral = "'" (char | escSeq) "'".
stringLiteral = """ {char | escSeq} """.
escSeq = "\" ("a" | "b" | "e" | "f" | "n" | "r" | "t" | "v" | "x" hexNumber).
letter = "A".."Z" | "a".."z".
digit = "0".."9".
hexDigit = digit | "A".."F" | "a"..f".
char = "\x00".."\xFF".