Static copy
Copied from docs/en/getting-started/first-program.md in https://github.com/poppy-team/aipo-lang (MIT). Pinned to revision ce47c4e070404fc41722ccd8e2b7b808b99062a8, blob 7ceb54a94b84425ba8ff050c4dc0d70a0bb81bb6. The source repository remains canonical; this copy is refreshed through a sync pull request, not live.
In this quick walkthrough, you will write, verify, compile, and execute your first program in Aipo.
Create a file named hello.aipo:
# hello.aipo
io.println("Hello from Aipo!")Run it directly with the CLI:
aipo run hello.aipoExpected output:
Hello from Aipo!Let's model a bank account with an invariant guaranteeing a non-negative balance. Create account.aipo:
# account.aipo
struct Account {
holder: String
account_number: Int
var balance: Float = 0.0
}
Account:init(holder: String, account_number: Int = 0, balance: Float = 0.0) {
self.holder = holder
self.account_number = account_number
self.balance = balance
}
# Invariant: executed upon construction and every field mutation
Account:invariant {
self.balance >= 0.0
}
Account:deposit(var self, amount: Float) {
if amount <= 0.0 {
return fail("Deposit amount must be positive")
}
self.balance += amount
}
Account:withdraw(var self, amount: Float) {
if amount <= 0.0 {
return fail("Withdrawal amount must be positive")
}
# Tries to execute the withdrawal. If self.balance >= 0.0 fails,
# the attempt block rolls back the mutation automatically!
attempt {
self.balance -= amount
} failed err {
return fail("Withdrawal rejected: insufficient balance")
}
}
# Instantiating the account using consistent colon (:) syntax
var acc = Account{ holder: "Alice Johnson", account_number: 1042, balance: 150.0 }
io.println(f"Account created for: {acc.holder}")
io.println(f"Initial balance: {acc.balance}")
acc.deposit(50.0)
io.println(f"Balance after deposit: {acc.balance}")
acc.withdraw(75.0)
io.println(f"Balance after withdrawal: {acc.balance}")Run the program:
aipo run account.aipoExpected output:
Account created for: Alice Johnson
Initial balance: 150.0
Balance after deposit: 200.0
Balance after withdrawal: 125.0Aipo provides full transparency into compiler output. You can disassemble the bytecode for any file:
aipo disasm account.aipoThe output shows bytecode mnemonics annotated with corresponding source line and column numbers.
You can transpile the exact same program to JavaScript for Node.js or browser execution:
aipo build account.aipo -o dist/account.js
node dist/account.jsThe emitted JavaScript provides bit-for-bit behavioral parity with the native Rust VM.