Skip to main content

Language Basics

Core language features and syntax in the current implementation.

🚧 EXPERIMENTAL LANGUAGE: This documentation describes the current state of Ora's syntax and features. Language design is evolving rapidly and syntax may change without notice.

Overview​

Ora is designed as a smart contract language with formal verification capabilities. The current implementation focuses on basic compilation functionality while advanced features are being developed.

Current Implementation Status​

✅ Implemented:

  • Basic contract structure
  • Function definitions
  • Storage variables
  • Basic types (u256, address, bool)
  • Simple control flow

🚧 In Development:

  • Formal verification syntax
  • Advanced error handling
  • Memory safety features
  • Standard library functions

📋 Planned:

  • Comprehensive type system
  • Advanced compile-time features
  • IDE integration

Contract Structure​

Every Ora program is organized around contracts:

contract MyContract {
// Contract contents
}

Variables and Storage​

Storage Variables​

Persistent state that survives between function calls:

contract Counter {
storage var count: u256;
storage var owner: address;
storage var active: bool;
}

Immutable Variables​

Set once during contract deployment:

contract Token {
immutable name: string;
immutable symbol: string;
immutable decimals: u8;
}

Compile-Time Constants​

Values computed at compile time:

contract Config {
storage const MAX_SUPPLY: u256 = 1000000;
storage const RATE: u256 = 100;
}

Types​

Basic Types​

// Unsigned integers
var small: u8 = 255;
var medium: u32 = 4294967295;
var large: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;

// Signed integers (in development)
var signed: i256 = -1000;

// Boolean
var flag: bool = true;

// Address
var addr: address = 0x742d35Cc6634C0532925a3b8D0C5e0E0f8d7D2;

// Strings (basic support)
var text: string = "Hello, Ora!";

Complex Types​

// Arrays (in development)
var numbers: [10]u256;

// Mappings
var balances: map[address, u256];
var approved: map[address, map[address, u256]];

// Custom struct types
struct User {
name: string,
balance: u256,
active: bool,
}

// Struct usage in storage
storage user_data: User;

For detailed information about struct types, memory management, and optimization, see Struct Types.

Functions​

Function Declaration​

contract Math {
// Public function
pub fn add(a: u256, b: u256) -> u256 {
return a + b;
}

// Private function
fn internal_calc(x: u256) -> u256 {
return x * 2;
}

// Function with no return value
pub fn reset() {
// Implementation
}
}

Function Visibility​

  • pub: Public, callable from outside the contract
  • (no modifier): Private, internal use only

Mathematical Operations​

Division Operations​

Ora provides multiple division operations with explicit rounding behavior:

contract MathOperations {
function demonstrateDivision() public {
let a: u32 = 10;
let b: u32 = 3;

// Truncating division (toward zero)
let trunc_result = @divTrunc(a, b); // 3

// Floor division (toward negative infinity)
let floor_result = @divFloor(a, b); // 3

// Ceiling division (toward positive infinity)
let ceil_result = @divCeil(a, b); // 4

// Exact division (errors if remainder != 0)
let exact_result = @divExact(12, 4); // 3

// Division with remainder (returns tuple)
let (quotient, remainder) = @divmod(a, b); // (3, 1)
}
}

Signed Division Behavior​

Different division operations handle negative numbers differently:

function signedDivision() public {
let a: i32 = -7;
let b: i32 = 3;

let trunc_result = @divTrunc(a, b); // -2 (toward zero)
let floor_result = @divFloor(a, b); // -3 (toward -∞)
let ceil_result = @divCeil(a, b); // -2 (toward +∞)
}

Division Error Handling​

All division operations include safety checks:

function safeDivision() public {
try {
let result = @divExact(10, 3); // Will error - not exact
} catch (error.InexactDivision) {
log("Division is not exact");
}

try {
let result = @divTrunc(10, 0); // Will error - division by zero
} catch (error.DivisionByZero) {
log("Cannot divide by zero");
}
}

Compile-Time Evaluation​

Division operations are evaluated at compile time when operands are known:

comptime {
let compile_result = @divTrunc(100, 4); // Computed at compile time
let (q, r) = @divmod(17, 5); // (3, 2) at compile time
}

Control Flow​

Conditional Statements​

fn check_balance(amount: u256) -> bool {
if (balance >= amount) {
return true;
} else {
return false;
}
}

Loops (Basic Implementation)​

fn sum_range(n: u256) -> u256 {
var result: u256 = 0;
var i: u256 = 0;

while (i < n) {
result = result + i;
i = i + 1;
}

return result;
}

Error Handling (In Development)​

Error Unions​

// Error declarations
error InsufficientBalance;
error InvalidAddress;
error Overflow;

// Function returning error union
fn transfer(to: address, amount: u256) -> !u256 {
if (to == std.constants.ZERO_ADDRESS) {
return error.InvalidAddress;
}

if (balance < amount) {
return error.InsufficientBalance;
}

// Success case
balance = balance - amount;
return balance;
}

Try-Catch (Planned)​

fn safe_transfer(to: address, amount: u256) {
try {
let new_balance = transfer(to, amount);
// Success handling
} catch (error.InsufficientBalance) {
// Handle insufficient balance
} catch (error.InvalidAddress) {
// Handle invalid address
}
}

Memory Regions​

Storage Region​

Persistent contract state:

contract Token {
storage var total_supply: u256;
storage var balances: map[address, u256];
}

Memory Region (Planned)​

Temporary data for function execution:

fn process_data() {
memory var temp_array: [100]u256;
memory var calculation: u256;
// Process data
}

Events and Logging​

Event Declaration​

contract Token {
log Transfer(from: address, to: address, amount: u256);
log Approval(owner: address, spender: address, amount: u256);
}

Event Emission​

fn transfer(to: address, amount: u256) {
// Transfer logic

log Transfer(std.transaction.sender, to, amount);
}

Standard Library (In Development)​

Transaction Context​

fn get_sender() -> address {
return std.transaction.sender;
}

fn get_value() -> u256 {
return std.transaction.value;
}

Constants​

fn check_zero_address(addr: address) -> bool {
return addr == std.constants.ZERO_ADDRESS;
}

Formal Verification (Planned)​

Preconditions and Postconditions​

fn transfer(to: address, amount: u256) -> bool
requires balances[std.transaction.sender] >= amount
requires to != std.constants.ZERO_ADDRESS
ensures balances[std.transaction.sender] + balances[to] ==
old(balances[std.transaction.sender]) + old(balances[to])
{
balances[std.transaction.sender] -= amount;
balances[to] += amount;
return true;
}

Invariants​

contract Token {
storage var total_supply: u256;
storage var balances: map[address, u256];

invariant sum_balances_equals_total_supply() {
// Sum of all balances equals total supply
}
}

Comments​

// Single-line comment

/*
Multi-line comment
Can span multiple lines
*/

contract Example {
/// Documentation comment for functions
pub fn documented_function() {
// Implementation
}
}

Compilation Phases​

Understanding how Ora processes your code:

  1. Lexical Analysis: Source code → Token stream
  2. Syntax Analysis: Tokens → Abstract Syntax Tree (AST)
  3. Semantic Analysis: AST → Validated AST with type information
  4. HIR Generation: AST → High-level Intermediate Representation
  5. Yul Generation: HIR → Yul code
  6. Bytecode Generation: Yul → EVM bytecode

Best Practices (Current)​

Code Organization​

contract WellOrganized {
// 1. Constants first
storage const MAX_USERS: u256 = 1000;

// 2. State variables
storage var user_count: u256;
storage var users: map[address, bool];

// 3. Events
log UserAdded(user: address);

// 4. Functions (public first, then private)
pub fn add_user(user: address) {
// Implementation
}

fn validate_user(user: address) -> bool {
// Implementation
return true;
}
}

Error Handling​

// Use descriptive error names
error UserNotFound;
error UserAlreadyExists;
error ExceedsMaxUsers;

// Check preconditions early
fn remove_user(user: address) -> !bool {
if (!users[user]) {
return error.UserNotFound;
}

// Main logic
users[user] = false;
user_count = user_count - 1;

return true;
}

Current Limitations​

Not Yet Implemented​

  • Advanced type system features
  • Comprehensive standard library
  • Formal verification execution
  • Advanced memory management
  • Optimization passes

Syntax Subject to Change​

  • Error handling syntax
  • Formal verification syntax
  • Memory region declarations
  • Advanced type annotations

Next Steps​

  1. Try the Examples: See Examples for working code patterns
  2. Read the Specifications: Check Technical Specifications for detailed design
  3. Experiment: Modify existing examples to understand current capabilities
  4. Report Issues: Help improve the language by reporting bugs

Last updated: December 2024 - Reflects current implementation status