Ora Language v1.0 "Asuka" - Showcase
🚀 First Production Release - Real EVM Smart Contract Compilation
🎯 Status: Production-Ready Compiler Pipeline
🏗️ Compilation Pipeline
The Ora compiler features a complete, robust compilation pipeline from source to deployable EVM bytecode:
graph TD
A["🔤 Ora Source Code<br/>(.ora files)"] --> B["🔍 Lexical Analysis<br/>(353 tokens)"]
B --> C["🌳 Parser<br/>(AST Generation)"]
C --> D["📊 Semantic Analysis<br/>(95% Complete)"]
D --> E["🔍 Type Checking<br/>(Memory Safety)"]
E --> F["🏗️ HIR Generation<br/>(High-level IR)"]
F --> G["✅ IR Validation<br/>(Error Recovery)"]
G --> H["⚡ Yul Generation<br/>(3,961 bytes)"]
H --> I["🎯 EVM Bytecode<br/>(986 bytes)"]
I --> J["🚀 Deployable<br/>Smart Contract"]
style A fill:#e1f5fe
style J fill:#c8e6c9
style D fill:#fff3e0
style E fill:#fff3e0
style F fill:#f3e5f5
style H fill:#e8f5e8
style I fill:#ffebee
🎯 Pipeline Capabilities
- ✅ Complete Source-to-Bytecode: One command compilation
- ✅ Real EVM Output: Deployable smart contracts (986 bytes for ERC20)
- ✅ Memory Safety: Comprehensive validation throughout pipeline
- ✅ Standard Library: Built-in Ethereum context access
- ✅ Error Recovery: Graceful error handling without crashes
🎨 Language Features
📋 Core Type System
// Primitive Types
let balance: u256 = 1000000; // 256-bit integers
let owner: address = 0x742d35cc...; // Ethereum addresses
let active: bool = true; // Booleans
let name: string = "MyToken"; // Dynamic strings
let data: bytes32 = 0xabcd...; // Fixed byte arrays
// Complex Types
let amounts: map[address, u256]; // Mappings
let approvals: doublemap[address, address, u256]; // Nested mappings
let holders: Array[address]; // Dynamic arrays
// Advanced Types
let result: Result[u256, string]; // Result types for error handling
let maybe_error: !u256; // Error unions (!T syntax)
let coordinates: (u256, u256, bool); // Tuple types
🏗️ Contract Structure
contract ERC20 {
// Storage Variables (Persistent State)
storage const name: string; // Immutable after constructor
storage var total_supply: u256; // Mutable contract state
storage var balances: map[address, u256];
// Events (EVM Log Emissions)
log Transfer(from: address, to: address, value: u256);
// Constructor
pub fn init(token_name: string, initial_supply: u256) {
name = token_name; // ✅ Constructor assignment allowed
total_supply = initial_supply;
}
// Public Functions (External Interface)
pub fn transfer(to: address, amount: u256) -> bool {
// ✅ Standard library access
balances from std.transaction.sender -> to : amount;
log Transfer(std.transaction.sender, to, amount);
return true;
}
}
🏗️ Struct Definitions & Memory Packing
// Ora compiler can change the order to better align the data
struct UserProfile {
id: u64, // 8 bytes
active: bool, // 1 byte (packed with next field)
level: u8, // 1 byte (packed efficiently)
balance: u256, // 32 bytes (aligned)
created_at: u64, // 8 bytes
}
// Struct instantiation
let profile = UserProfile{
id: 12345,
active: true,
level: 5,
balance: 1000000,
created_at: std.block.timestamp
};
// Field access with automatic memory layout optimization
let user_balance = profile.balance; // ✅ Efficient field access
profile.level = 10; // ✅ Mutable field update
🎯 Enum Types with Discriminants
// Simple enum with automatic discriminants
enum TokenType {
ERC20, // discriminant: 0
ERC721, // discriminant: 1
ERC1155 // discriminant: 2
}
// Enum with custom base type and explicit values
enum Status : u8 {
Pending = 0,
Active = 1,
Suspended = 2,
Terminated = 255
}
// Enum usage with pattern matching
let token_status = Status.Active;
if (token_status == Status.Pending) {
// Handle pending state
}
// Enum comparison based on discriminant values
let is_higher_priority = Status.Active > Status.Pending; // ✅ true
🔐 Memory Regions
Ora provides explicit memory management with different storage regions:
// Storage Region (Persistent blockchain state)
storage const MAX_SUPPLY: u256 = 1000000; // Contract constants
storage var balances: map[address, u256]; // Persistent mappings
// Stack Region (Temporary function variables)
let temp_value: u256 = calculate_fee(); // Local computations
// Memory Region (Temporary structured data)
memory var temp_array: Array[u256]; // Dynamic temporary data
// Immutable Region (Set once at deployment)
immutable OWNER: address; // Deploy-time constants
🛡️ Safety & Validation
✅ Semantic Analysis (95% Complete)
- Storage Const Validation: Proper constructor initialization checking
- Memory Safety: Comprehensive pointer and memory validation
- Type Compatibility: Full type checking with error recovery
- Standard Library: Complete
std.transaction
andstd.constants
support
🔒 Constructor Validation
contract Token {
storage const name: string; // ✅ Must be initialized in constructor
storage const decimals: u8; // ✅ Cannot be changed after init
pub fn init(token_name: string) {
name = token_name; // ✅ Constructor assignment allowed
decimals = 18; // ✅ One-time initialization
}
pub fn change_name() {
name = "NewName"; // ❌ Error: Cannot assign outside constructor
}
}
🌐 Standard Library Access
pub fn transfer(to: address, amount: u256) -> bool {
// ✅ Transaction context access
let sender = std.transaction.sender; // Current caller address
let value = std.transaction.value; // Sent ETH amount
// ✅ Blockchain constants
let zero_addr = std.constants.ZERO_ADDRESS; // 0x000...000
let max_int = std.constants.MAX_UINT256; // 2^256 - 1
// ✅ Block information
let timestamp = std.block.timestamp; // Current block time
let number = std.block.number; // Current block number
return true;
}
🧮 Advanced Mathematics & Error Handling
🔢 Arithmetic Operations
// Safe arithmetic with overflow protection
let a: u256 = 1000;
let b: u256 = 500;
let sum = a + b; // Addition: 1500
let diff = a - b; // Subtraction: 500
let product = a * b; // Multiplication: 500000
let quotient = a / b; // Division: 2
let remainder = a % b; // Modulo: 0
// Compound assignment
balance += amount; // balance = balance + amount
supply -= burned; // supply = supply - burned
🔢 Specialized Division Operations
// Advanced division functions with safety guarantees
let dividend: i256 = -17;
let divisor: i256 = 5;
// @divTrunc: Truncating division (toward zero) - Default EVM behavior
let trunc_result = @divTrunc(dividend, divisor); // Result: -3
// @divFloor: Floor division (toward negative infinity)
let floor_result = @divFloor(dividend, divisor); // Result: -4
// @divCeil: Ceiling division (toward positive infinity)
let ceil_result = @divCeil(dividend, divisor); // Result: -3
// @divExact: Exact division (panics if not evenly divisible)
let exact_result = @divExact(20, 4); // Result: 5 (safe)
// @divExact(21, 4); // ❌ Panic: not evenly divisible
// @divmod: Combined division and modulus (returns tuple)
let (quotient, remainder) = @divmod(dividend, divisor);
// quotient: -3, remainder: -2
⚖️ Balance Transfer Syntax
// Intuitive balance transfer syntax
balances from sender -> recipient : amount;
// Equivalent to:
// balances[sender] -= amount;
// balances[recipient] += amount;
// With automatic overflow/underflow checks
🛡️ Error Handling Types
// Error declarations (must be declared before use)
error DivisionByZero;
error InvalidAddress;
error InsufficientBalance;
// Error Union Functions (!T syntax)
fn safe_divide(a: u256, b: u256) -> !u256 {
if (b == 0) {
return error.DivisionByZero; // Return specific error
}
return a / b; // Return success value
}
// Result Types (alternative error handling)
fn parse_amount(input: string) -> Result[u256, u8] {
if (valid) {
return Result.ok(parsed_value);
} else {
return Result.error(1); // Error code
}
}
// Error handling with try expression
let balance_result = try getBalance(account); // Unwrap or propagate
// Error handling with try-catch blocks
try {
let result = safe_divide(100, 3);
log Success("Division result", result);
} catch(err) {
log Error("Division failed");
return false;
}
// Function that uses error union
fn transfer(to: address, amount: u256) -> !bool {
if (to == std.constants.ZERO_ADDRESS) {
return error.InvalidAddress;
}
let current_balance = try getBalance(std.transaction.sender);
if (current_balance < amount) {
return error.InsufficientBalance;
}
// Success case
return true;
}
📊 Real-World Example: ERC20 Token
Here's what the Asuka compiler can build today:
contract MyToken {
// Error declarations
error InvalidAddress;
error InsufficientBalance;
error InvalidAmount;
// Storage variables
storage const name: string;
storage const symbol: string;
storage const decimals: u8;
storage var total_supply: u256;
storage var balances: map[address, u256];
storage var allowances: doublemap[address, address, u256];
// Events
log Transfer(from: address, to: address, value: u256);
log Approval(owner: address, spender: address, value: u256);
// Constructor with error handling
pub fn init(token_name: string, token_symbol: string, initial_supply: u256, owner: address) -> !bool {
if (owner == std.constants.ZERO_ADDRESS) {
return error.InvalidAddress;
}
name = token_name;
symbol = token_symbol;
decimals = 18;
total_supply = initial_supply;
balances[owner] = initial_supply;
log Transfer(std.constants.ZERO_ADDRESS, owner, initial_supply);
return true;
}
// Transfer with comprehensive error handling
pub fn transfer(to: address, amount: u256) -> !bool {
if (to == std.constants.ZERO_ADDRESS) {
return error.InvalidAddress;
}
if (amount == 0) {
return error.InvalidAmount;
}
let sender_balance = try balance_of(std.transaction.sender);
if (sender_balance < amount) {
return error.InsufficientBalance;
}
// Safe transfer using try-catch
try {
@lock(balances[to]); // Prevent reentrancy
balances from std.transaction.sender -> to : amount;
log Transfer(std.transaction.sender, to, amount);
return true;
} catch(err) {
return error.InsufficientBalance; // Propagate as balance error
}
}
pub fn approve(spender: address, amount: u256) -> !bool {
if (spender == std.constants.ZERO_ADDRESS) {
return error.InvalidAddress;
}
allowances[std.transaction.sender, spender] = amount;
log Approval(std.transaction.sender, spender, amount);
return true;
}
pub fn balance_of(account: address) -> !u256 {
if (account == std.constants.ZERO_ADDRESS) {
return error.InvalidAddress;
}
return balances[account];
}
}
🔮 Coming Next
While Asuka is "production-ready" for smart contracts with advanced features, upcoming releases will add:
- Enhanced Event System: More sophisticated log handling and filtering
- Gas Optimization: Advanced gas cost analysis and optimization
- Pattern Matching: Match expressions for enums and complex types
- Formal Verification: Mathematical proof generation and SMT solving
- Advanced Generics: Generic structs, enums, and functions
- Developer Tools: Enhanced debugging, testing, and profiling utilities