This commit is contained in:
Marek Maskarinec 2024-11-06 10:21:55 +05:30 committed by GitHub
commit 14346d5a17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

178
umka.html.markdown Normal file
View File

@ -0,0 +1,178 @@
---
language: Umka
filename: learnumka.um
contributors:
- ["Marek Maškarinec", "https://mrms.cz"]
---
Umka is a statically typed scripting language meant to be embedded into
programs, useful in cases like mod support in games, or user scripting.
It draws inspiration from Pascal and Go.
```
// Single line comment
/* Multi line comments
they can't be nested */
// The import statement can import other files
import (
"std.um" // the standard library - included in the interpreter
"map.um" // hashmaps
"utf8.um" // utf8 encoding and decoding
)
// Functions are declared with the fn keyword. They have to be declared before
// usage. To combat this, umka allows function prototypes.
// The main function serves as an entry point when running the file.
// Included files can contain main too.
fn main() {
// printf works the same as in c. It is builtin, so you don't need to
// import any file to use it.
printf("Hello world!\n")
// Variables have to be declared before use. There are multiple ways to do so.
var x: int = 3 // full declaration
var y: uint32 // you can ignore the value
var z = 5 // you can also ignore the type
a := 6 // umka also allows short declarations like in go
y = 4 // variable assignment
// there aren't doubles or floats in umka. They are called real and
// real32 instead.
var pi: real = 3.14
// if statements
if pi == 3.14 {
printf("Close enough.\n")
} else if pi == 3 {
printf("You should learn about real values.\n")
} else {
printf("You live in a strange world.\n")
}
// Umka has only one key word for loops.
// Traditional while loop:
for z > 0 {
printf("%d\n", z)
z--
}
// for loop:
for i:=0; i < y; i++ {
printf("%d\n", i)
}
// the string type is called str
var name: str = "John"
// string concatenation
name += " Doe"
// Umka has two types of arrays - fixed and dynamic. Fixed have fixed size,
// are stored on the stack and passed by value. Dynamic are the opposite.
// You can append and slice them, they are stored on the heap and passed by
// reference.
// A fixed array
names := [4]str{"Jonathan", "Joseph", "Jotaro", "Josuke"}
// Making a dynamic array is done by just removing the number
dynNames := []str{"Jonathan", "Joseph", "Jotaro", "Josuke"}
// It is also possible to create a zero initialized dynamic array of a given
// length. The length doesn't have to be a constant.
arr := make([]int, 23)
// Dynamic arrays can be appended. Be aware, that the array is always newly
// allocated, and the old elements are copied. This makes the process of
// appending very slow.
dynNames = append(dynNames, "Giorno")
// You can also delete an element from an array.
dynNames = delete(dynNames, 3) // => { "Jonathan", "Joseph", "Jotaro", "Giorno" }
// You can also slice them. Start inclusive, end exclusive.
part1 := slice(dynNames, 0, 2)
// You can ommit the ending index and it will be replaced by the length
// of the array.
part2 := slice(dynNames, 2)
// You can iterate over a string, array and a dynamic array
// using the "for in" loop.
for index, value in dynNames {
printf("%d: %s\n", index, value)
}
// Umka supports pointers. You can make a pointer type by writing a ^ before
// the base type.
var xPointer: ^int
// Values are referenced using an &
xPointer = &x
// You can dereference them by writing a ^ after the value
printf("%s: %d\n", repr(xPointer), xPointer^) // => 0xaddress : 3
}
// Functions are declared using the fn keyword. Parameters are in parenthesis,
// the return type follows after a :. Functions don't have to take parameters,
// or return any values.
fn learnFunctions(a, b: int, c: real): real {
return a + b * c
}
// Functions can return multiple values.
fn learnMultiple(): (int, int) {
x, y := getPosition()
x *= 2
y *= 2
return x, y
}
// The type keywords allows type aliases
type Number int
// You can use it to define your own structure types.
type Vector2 = struct {
x, y: real
}
fn newVector2(x, y: real): Vector2 {
// Structure literals
return Vector2{ x, y }
}
// You can define methods on any type from the current module.
fn (v: ^Vector2) multiply(x: real) {
v.x *= x
v.y *= x
}
// An interface is a form of duck typing in Umka. It defines a set of methods,
// that must be implemented by a type to implement said interface.
type Representable = interface {
toStr(): str
}
// Vector2 now implements Representable
fn (v: ^Vector2) toStr(): str {
return "[ " + repr(v.x) + repr(v.y) + "]"
}
// This function takes a variadic number of Representable values
fn println(args ...Representable) {
// variadic arguments act like an array inside a function
for arg in args {
printf("%s", repr(arg))
}
printf("\n")
}
```
## Further reading
You can learn more details in the [documentation](https://github.com/vtereshkov/umka-lang/tree/master/doc).
If you want to read real Umka code, read some of the [examples](https://github.com/vtereshkov/umka-lang/tree/master/examples).