Here are some code examples to help you get started with Ovum.
StringArray
)// .ovum file
fun Main(args: StringArray): Int {
val count: Int = args.Length() // Built-in returns Int
sys::Print("Args count: " + count.ToString())
return 0
}
fun DemoNulls(): Void {
val a: Int? = null
val b: Int? = 5
val aVal: int = a ?: 0
val bVal: int = b ?: 0
val sum: int = aVal + bVal
sys::Print("Sum = " + Int(sum).ToString())
val name: String? = null
val length: int = (name?.Length() ?: 0) as int // Built-in returns Int
sys::Print("Name length = " + Int(length).ToString())
}
interface IGreeter {
fun Greet(name: String): String // public + virtual by default
}
class FriendlyGreeter implements IGreeter {
private val Prefix: String = "Hello"
public var Suffix: String = "!"
public fun FriendlyGreeter(prefix: String, suffix: String): FriendlyGreeter {
this.Prefix = prefix
this.Suffix = suffix
return this
}
public override fun Greet(name: String): String {
return Prefix + ", " + name + Suffix
}
// Optional destructor (finalization logic)
public destructor(): Void {
// release non-memory resources if any (files, handles, etc.)
}
}
IStringConvertible
, IComparable
, IHashable
)interface IStringConvertible { fun ToString(): String }
interface IComparable { fun IsLess(other: Object): Bool }
interface IHashable { fun GetHash(): Int }
class Point implements IStringConvertible, IComparable, IHashable {
public val X: int
public val Y: int
public fun Point(x: int, y: int): Point { this.X = x; this.Y = y; return this; }
public override fun ToString(): String {
return "(" + Int(X).ToString() + ", " + Int(Y).ToString() + ")"
}
public override fun IsLess(other: Object): Bool {
if (!(other is Point)) return false
val p: Point? = other as Point
if (p != null) {
val nonNullP: Point = p ?: Point(0, 0) // Use Elvis operator
if (this.X != nonNullP.X) return this.X < nonNullP.X
return this.Y < nonNullP.Y
}
return false
}
public override fun GetHash(): Int {
val hash: int = (X * 1315423911) ^ (Y * 2654435761)
return Int(hash)
}
}
pure fun Fib(n: int): int {
if (n <= 1) return n
val fib1: int = Fib(n - 1)
val fib2: int = Fib(n - 2)
return fib1 + fib2
}
// For user-defined reference types as parameters, implement IComparable.
is
, as
, and ByteArray Castsfun DemoCasts(obj: Object): Void {
if (obj is Point) {
val p: Point? = obj as Point
if (p != null) {
val nonNullP: Point = p ?: Point(0, 0) // Use Elvis operator
sys::Print(nonNullP.ToString())
}
}
// bool cast
val b1: Bool = 0 as bool // false
val b2: Bool = 42 as bool // true
val b3: Bool = obj as bool // always true
val b4: Bool = (obj as Point) as bool // true if obj is a Point
// Unsafe: raw byte views
unsafe {
val bytesConst: ByteArray = (obj as ByteArray)
val bytesMut : ByteArray = (obj as var ByteArray)
}
}
call
) & Literalsinterface CustomFunctional {
call(a: Int?, b: Int?): Int
}
class DefinedFunctional {
public var Multiplier: Int
public fun DefinedFunctional(multiplier: Int): DefinedFunctional {
this.Multiplier = multiplier
return this
}
public call(secondMultiplier: Int): Int = fun(secondMultiplier: Int): Int {
return Multiplier * secondMultiplier
}
}
val AddNullable: CustomFunctional = pure fun(a: Int?, b: Int?): Int {
return (a ?: 0) + (b ?: 0)
}
fun Main(args: StringArray): Int {
return AddNullable(2, DefinedFunctional(-1)(2))
}
fun DemoControlFlow(): Void {
var i: int = 0
// While loop with break and continue
while (i < 10) {
if (i == 3) {
i = i + 1
continue // Skip to next iteration
}
if (i == 7) {
break // Exit loop
}
sys::Print("i = " + Int(i).ToString())
i = i + 1
}
// For loop over array
val numbers: IntArray = IntArray(3)
numbers[0] := 10
numbers[1] := 20
numbers[2] := 30
for (num in numbers) {
sys::Print("Number: " + num.ToString())
}
}
fun DemoUnsafeOperations(): Void {
// Unsafe block for low-level operations
unsafe {
// Global mutable state (unsafe)
static var globalCounter: int = 0
globalCounter = globalCounter + 1
// Pointer operations (unsafe)
val obj: Point = Point(10, 20)
val ptr: pointer = &obj // address-of
val deref: Object = *ptr // dereference to Object, pointer is not typed
// ByteArray casting (unsafe)
val bytes: ByteArray = (obj as ByteArray)
val mutableBytes: ByteArray = (obj as var ByteArray)
// Foreign function interface (unsafe)
val input: ByteArray = "Hello".ToUtf8Bytes()
val output: ByteArray = ByteArray(8)
val result: int = sys::Interope("libc.so", "strlen", input, output)
}
}
// Define type aliases for better readability
typealias UserId = Int
typealias UserName = String
typealias UserList = ObjectArray
class User {
public val Id: UserId
public val Name: UserName
public fun User(id: UserId, name: UserName): User {
this.Id = id
this.Name = name
return this
}
}
fun ProcessUsers(users: UserList): Void {
for (i in 0..users.Length()) {
val user: User? = users[i] as User
if (user != null) {
val nonNullUser: User = user ?: User(0, "Unknown") // Use Elvis operator
sys::Print("User " + nonNullUser.Id.ToString() + ": " + nonNullUser.Name)
}
}
}
class DatabaseConnection {
private val ConnectionId: int
private val IsConnected: bool
public fun DatabaseConnection(id: int): DatabaseConnection {
this.ConnectionId = id
this.IsConnected = true
// Establish database connection
return this
}
public fun Query(sql: String): String {
if (!IsConnected) return "Not connected"
// Execute query
return "Query result"
}
// Destructor called automatically by GC
public destructor(): Void {
if (IsConnected) {
// Close database connection
sys::Print("Closing connection " + Int(ConnectionId).ToString())
}
}
}
fun DemoMemoryManagement(): Void {
val db: DatabaseConnection = DatabaseConnection(1)
val result: String = db.Query("SELECT * FROM users")
sys::Print("Query result: " + result)
// db will be garbage collected automatically
// destructor will be called by GC
}
// Complete Ovum program demonstrating key features
interface ICalculator {
fun Calculate(a: Int, b: Int): Int
}
class Adder implements ICalculator {
public override fun Calculate(a: Int, b: Int): Int {
return a + b
}
}
class Multiplier implements ICalculator {
public override fun Calculate(a: Int, b: Int): Int {
return a * b
}
}
pure fun ProcessNumbers(calc: ICalculator, numbers: IntArray): int {
var result: int = 0
for (num in numbers) {
val calcResult: Int = calc.Calculate(num, 2)
result = result + calcResult
}
return result
}
fun Main(args: StringArray): int {
val numbers: IntArray = IntArray(3)
numbers[0] := 5
numbers[1] := 10
numbers[2] := 15
val adder: ICalculator = Adder()
val multiplier: ICalculator = Multiplier()
val sumResult: int = ProcessNumbers(adder, numbers)
val productResult: int = ProcessNumbers(multiplier, numbers)
sys::Print("Sum result: " + Int(sumResult).ToString())
sys::Print("Product result: " + Int(productResult).ToString())
return 0
}