Use `constant` instead of `const`
c92591c97b99e5ab1a677d5c98c941651324ff6970b92acd2a8e424cac4df18a
1 parent
52b9cccc
compiler/radiance.rad
+14 -14
| 20 | 20 | use std::sys; |
|
| 21 | 21 | use std::sys::unix; |
|
| 22 | 22 | use std::collections::dict; |
|
| 23 | 23 | ||
| 24 | 24 | /// Maximum number of modules we can load per package. |
|
| 25 | - | const MAX_LOADED_MODULES: u32 = 64; |
|
| 25 | + | constant MAX_LOADED_MODULES: u32 = 64; |
|
| 26 | 26 | /// Maximum number of packages we can compile. |
|
| 27 | - | const MAX_PACKAGES: u32 = 4; |
|
| 27 | + | constant MAX_PACKAGES: u32 = 4; |
|
| 28 | 28 | /// Total module entries across all packages. |
|
| 29 | - | const MAX_TOTAL_MODULES: u32 = 192; |
|
| 29 | + | constant MAX_TOTAL_MODULES: u32 = 192; |
|
| 30 | 30 | /// Source code buffer arena (2 MB). |
|
| 31 | - | const MAX_SOURCES_SIZE: u32 = 2097152; |
|
| 31 | + | constant MAX_SOURCES_SIZE: u32 = 2097152; |
|
| 32 | 32 | /// Maximum number of test functions we can discover. |
|
| 33 | - | const MAX_TESTS: u32 = 1024; |
|
| 33 | + | constant MAX_TESTS: u32 = 1024; |
|
| 34 | 34 | ||
| 35 | 35 | /// Temporary arena size (32 MB) - retains all parsed AST until resolution. |
|
| 36 | 36 | /// Used for: AST during parsing, then codegen scratch space. |
|
| 37 | - | const TEMP_ARENA_SIZE: u32 = 33554432; |
|
| 37 | + | constant TEMP_ARENA_SIZE: u32 = 33554432; |
|
| 38 | 38 | /// Main arena size (128 MB) - lives throughout compilation. |
|
| 39 | 39 | /// Used for: resolver data, types, symbols, lowered IL. |
|
| 40 | - | const MAIN_ARENA_SIZE: u32 = 134217728; |
|
| 40 | + | constant MAIN_ARENA_SIZE: u32 = 134217728; |
|
| 41 | 41 | ||
| 42 | 42 | /// Temporary storage arena - reusable between phases. |
|
| 43 | 43 | static TEMP_ARENA: [u8; TEMP_ARENA_SIZE] = undefined; |
|
| 44 | 44 | /// Main storage arena - persists throughout compilation. |
|
| 45 | 45 | static MAIN_ARENA: [u8; MAIN_ARENA_SIZE] = undefined; |
| 60 | 60 | static CODEGEN_DATA_SYMS: [data::DataSym; data::MAX_DATA_SYMS] = undefined; |
|
| 61 | 61 | /// Hash table entries for data symbol lookup. |
|
| 62 | 62 | static CODEGEN_DATA_SYM_ENTRIES: [dict::Entry; data::DATA_SYM_TABLE_SIZE] = undefined; |
|
| 63 | 63 | ||
| 64 | 64 | /// Debug info file extension. |
|
| 65 | - | const DEBUG_EXT: *[u8] = ".debug"; |
|
| 65 | + | constant DEBUG_EXT: *[u8] = ".debug"; |
|
| 66 | 66 | ||
| 67 | 67 | /// Read-only data file extension. |
|
| 68 | - | const RO_DATA_EXT: *[u8] = ".ro.data"; |
|
| 68 | + | constant RO_DATA_EXT: *[u8] = ".ro.data"; |
|
| 69 | 69 | /// Read-write data file extension. |
|
| 70 | - | const RW_DATA_EXT: *[u8] = ".rw.data"; |
|
| 70 | + | constant RW_DATA_EXT: *[u8] = ".rw.data"; |
|
| 71 | 71 | /// Maximum rodata size (1MB). |
|
| 72 | - | const MAX_RO_DATA_SIZE: u32 = 1048576; |
|
| 72 | + | constant MAX_RO_DATA_SIZE: u32 = 1048576; |
|
| 73 | 73 | /// Maximum rwdata size (1MB). |
|
| 74 | - | const MAX_RW_DATA_SIZE: u32 = 1048576; |
|
| 74 | + | constant MAX_RW_DATA_SIZE: u32 = 1048576; |
|
| 75 | 75 | /// Maximum path length. |
|
| 76 | - | const MAX_PATH_LEN: u32 = 256; |
|
| 76 | + | constant MAX_PATH_LEN: u32 = 256; |
|
| 77 | 77 | /// Read-only data buffer. |
|
| 78 | 78 | static RO_DATA_BUF: [u8; MAX_RO_DATA_SIZE] = undefined; |
|
| 79 | 79 | /// Read-write data buffer. |
|
| 80 | 80 | static RW_DATA_BUF: [u8; MAX_RW_DATA_SIZE] = undefined; |
|
| 81 | 81 | ||
| 82 | 82 | /// Usage string. |
|
| 83 | - | const USAGE: *[u8] = |
|
| 83 | + | constant USAGE: *[u8] = |
|
| 84 | 84 | "usage: radiance -pkg <name> -mod <input>.. [-pkg <name> -mod <input>..] -entry <pkg> -o <output>\n"; |
|
| 85 | 85 | ||
| 86 | 86 | /// Compiler error. |
|
| 87 | 87 | union Error { |
|
| 88 | 88 | Other, |
lib/std/arch/rv64.rad
+50 -50
| 30 | 30 | ||
| 31 | 31 | //////////////// |
|
| 32 | 32 | // Registers // |
|
| 33 | 33 | //////////////// |
|
| 34 | 34 | ||
| 35 | - | export const ZERO: gen::Reg = gen::Reg(0); /// Hard-wired zero. |
|
| 36 | - | export const RA: gen::Reg = gen::Reg(1); /// Return address. |
|
| 37 | - | export const SP: gen::Reg = gen::Reg(2); /// Stack pointer. |
|
| 38 | - | export const GP: gen::Reg = gen::Reg(3); /// Global pointer. |
|
| 39 | - | export const TP: gen::Reg = gen::Reg(4); /// Thread pointer. |
|
| 40 | - | export const T0: gen::Reg = gen::Reg(5); /// Temporary/alternate link register. |
|
| 41 | - | export const T1: gen::Reg = gen::Reg(6); /// Temporary. |
|
| 42 | - | export const T2: gen::Reg = gen::Reg(7); /// Temporary. |
|
| 43 | - | export const S0: gen::Reg = gen::Reg(8); /// Saved register/frame pointer. |
|
| 44 | - | export const FP: gen::Reg = gen::Reg(8); /// Frame pointer (alias for S0). |
|
| 45 | - | export const S1: gen::Reg = gen::Reg(9); /// Saved register. |
|
| 46 | - | export const A0: gen::Reg = gen::Reg(10); /// Function argument/return. |
|
| 47 | - | export const A1: gen::Reg = gen::Reg(11); /// Function argument/return. |
|
| 48 | - | export const A2: gen::Reg = gen::Reg(12); /// Function argument. |
|
| 49 | - | export const A3: gen::Reg = gen::Reg(13); /// Function argument. |
|
| 50 | - | export const A4: gen::Reg = gen::Reg(14); /// Function argument. |
|
| 51 | - | export const A5: gen::Reg = gen::Reg(15); /// Function argument. |
|
| 52 | - | export const A6: gen::Reg = gen::Reg(16); /// Function argument. |
|
| 53 | - | export const A7: gen::Reg = gen::Reg(17); /// Function argument. |
|
| 54 | - | export const S2: gen::Reg = gen::Reg(18); /// Saved register. |
|
| 55 | - | export const S3: gen::Reg = gen::Reg(19); /// Saved register. |
|
| 56 | - | export const S4: gen::Reg = gen::Reg(20); /// Saved register. |
|
| 57 | - | export const S5: gen::Reg = gen::Reg(21); /// Saved register. |
|
| 58 | - | export const S6: gen::Reg = gen::Reg(22); /// Saved register. |
|
| 59 | - | export const S7: gen::Reg = gen::Reg(23); /// Saved register. |
|
| 60 | - | export const S8: gen::Reg = gen::Reg(24); /// Saved register. |
|
| 61 | - | export const S9: gen::Reg = gen::Reg(25); /// Saved register. |
|
| 62 | - | export const S10: gen::Reg = gen::Reg(26); /// Saved register. |
|
| 63 | - | export const S11: gen::Reg = gen::Reg(27); /// Saved register. |
|
| 64 | - | export const T3: gen::Reg = gen::Reg(28); /// Temporary. |
|
| 65 | - | export const T4: gen::Reg = gen::Reg(29); /// Temporary. |
|
| 66 | - | export const T5: gen::Reg = gen::Reg(30); /// Temporary. |
|
| 67 | - | export const T6: gen::Reg = gen::Reg(31); /// Temporary. |
|
| 35 | + | export constant ZERO: gen::Reg = gen::Reg(0); /// Hard-wired zero. |
|
| 36 | + | export constant RA: gen::Reg = gen::Reg(1); /// Return address. |
|
| 37 | + | export constant SP: gen::Reg = gen::Reg(2); /// Stack pointer. |
|
| 38 | + | export constant GP: gen::Reg = gen::Reg(3); /// Global pointer. |
|
| 39 | + | export constant TP: gen::Reg = gen::Reg(4); /// Thread pointer. |
|
| 40 | + | export constant T0: gen::Reg = gen::Reg(5); /// Temporary/alternate link register. |
|
| 41 | + | export constant T1: gen::Reg = gen::Reg(6); /// Temporary. |
|
| 42 | + | export constant T2: gen::Reg = gen::Reg(7); /// Temporary. |
|
| 43 | + | export constant S0: gen::Reg = gen::Reg(8); /// Saved register/frame pointer. |
|
| 44 | + | export constant FP: gen::Reg = gen::Reg(8); /// Frame pointer (alias for S0). |
|
| 45 | + | export constant S1: gen::Reg = gen::Reg(9); /// Saved register. |
|
| 46 | + | export constant A0: gen::Reg = gen::Reg(10); /// Function argument/return. |
|
| 47 | + | export constant A1: gen::Reg = gen::Reg(11); /// Function argument/return. |
|
| 48 | + | export constant A2: gen::Reg = gen::Reg(12); /// Function argument. |
|
| 49 | + | export constant A3: gen::Reg = gen::Reg(13); /// Function argument. |
|
| 50 | + | export constant A4: gen::Reg = gen::Reg(14); /// Function argument. |
|
| 51 | + | export constant A5: gen::Reg = gen::Reg(15); /// Function argument. |
|
| 52 | + | export constant A6: gen::Reg = gen::Reg(16); /// Function argument. |
|
| 53 | + | export constant A7: gen::Reg = gen::Reg(17); /// Function argument. |
|
| 54 | + | export constant S2: gen::Reg = gen::Reg(18); /// Saved register. |
|
| 55 | + | export constant S3: gen::Reg = gen::Reg(19); /// Saved register. |
|
| 56 | + | export constant S4: gen::Reg = gen::Reg(20); /// Saved register. |
|
| 57 | + | export constant S5: gen::Reg = gen::Reg(21); /// Saved register. |
|
| 58 | + | export constant S6: gen::Reg = gen::Reg(22); /// Saved register. |
|
| 59 | + | export constant S7: gen::Reg = gen::Reg(23); /// Saved register. |
|
| 60 | + | export constant S8: gen::Reg = gen::Reg(24); /// Saved register. |
|
| 61 | + | export constant S9: gen::Reg = gen::Reg(25); /// Saved register. |
|
| 62 | + | export constant S10: gen::Reg = gen::Reg(26); /// Saved register. |
|
| 63 | + | export constant S11: gen::Reg = gen::Reg(27); /// Saved register. |
|
| 64 | + | export constant T3: gen::Reg = gen::Reg(28); /// Temporary. |
|
| 65 | + | export constant T4: gen::Reg = gen::Reg(29); /// Temporary. |
|
| 66 | + | export constant T5: gen::Reg = gen::Reg(30); /// Temporary. |
|
| 67 | + | export constant T6: gen::Reg = gen::Reg(31); /// Temporary. |
|
| 68 | 68 | ||
| 69 | 69 | /// Create a register from a number. Panics if `n > 31`. |
|
| 70 | 70 | export fn reg(n: u8) -> gen::Reg { |
|
| 71 | 71 | assert n < 32; |
|
| 72 | 72 | return gen::Reg(n); |
| 75 | 75 | //////////////////////////// |
|
| 76 | 76 | // Architecture constants // |
|
| 77 | 77 | //////////////////////////// |
|
| 78 | 78 | ||
| 79 | 79 | /// Total number of general-purpose registers. |
|
| 80 | - | export const NUM_REGISTERS: u8 = 32; |
|
| 80 | + | export constant NUM_REGISTERS: u8 = 32; |
|
| 81 | 81 | /// Number of saved registers. |
|
| 82 | - | export const NUM_SAVED_REGISTERS: u8 = 11; |
|
| 82 | + | export constant NUM_SAVED_REGISTERS: u8 = 11; |
|
| 83 | 83 | /// Word size in bytes (32-bit). |
|
| 84 | - | export const WORD_SIZE: i32 = 4; |
|
| 84 | + | export constant WORD_SIZE: i32 = 4; |
|
| 85 | 85 | /// Doubleword size in bytes (64-bit). |
|
| 86 | - | export const DWORD_SIZE: i32 = 8; |
|
| 86 | + | export constant DWORD_SIZE: i32 = 8; |
|
| 87 | 87 | /// Instruction size in bytes. |
|
| 88 | - | export const INSTR_SIZE: i32 = 4; |
|
| 88 | + | export constant INSTR_SIZE: i32 = 4; |
|
| 89 | 89 | /// Stack alignment requirement in bytes. |
|
| 90 | - | export const STACK_ALIGNMENT: i32 = 16; |
|
| 90 | + | export constant STACK_ALIGNMENT: i32 = 16; |
|
| 91 | 91 | ||
| 92 | 92 | /// Minimum blit size (in bytes) to use a loop instead of inline copy. |
|
| 93 | 93 | /// Blits below this threshold are fully unrolled as LD/SD pairs. |
|
| 94 | - | export const BLIT_LOOP_THRESHOLD: i32 = 256; |
|
| 94 | + | export constant BLIT_LOOP_THRESHOLD: i32 = 256; |
|
| 95 | 95 | ||
| 96 | 96 | ///////////////////////// |
|
| 97 | 97 | // Codegen Allocation // |
|
| 98 | 98 | ///////////////////////// |
|
| 99 | 99 | ||
| 100 | 100 | /// Argument registers for function calls. |
|
| 101 | - | export const ARG_REGS: [gen::Reg; 8] = [A0, A1, A2, A3, A4, A5, A6, A7]; |
|
| 101 | + | export constant ARG_REGS: [gen::Reg; 8] = [A0, A1, A2, A3, A4, A5, A6, A7]; |
|
| 102 | 102 | ||
| 103 | 103 | /// Scratch register for code gen. Never allocated to user values. |
|
| 104 | - | export const SCRATCH1: gen::Reg = T5; |
|
| 104 | + | export constant SCRATCH1: gen::Reg = T5; |
|
| 105 | 105 | ||
| 106 | 106 | /// Second scratch register for operations needing two temporaries. |
|
| 107 | - | export const SCRATCH2: gen::Reg = T6; |
|
| 107 | + | export constant SCRATCH2: gen::Reg = T6; |
|
| 108 | 108 | ||
| 109 | 109 | /// Dedicated scratch for address offset adjustment. Never allocated to user |
|
| 110 | 110 | /// values and never used for operand materialization, so it can never |
|
| 111 | 111 | /// conflict with `rd`, `rs`, or `base` in load/store helpers. |
|
| 112 | - | export const ADDR_SCRATCH: gen::Reg = T4; |
|
| 112 | + | export constant ADDR_SCRATCH: gen::Reg = T4; |
|
| 113 | 113 | ||
| 114 | 114 | /// Callee-saved registers that need save/restore if used. |
|
| 115 | - | export const CALLEE_SAVED: [gen::Reg; NUM_SAVED_REGISTERS] = [S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11]; |
|
| 115 | + | export constant CALLEE_SAVED: [gen::Reg; NUM_SAVED_REGISTERS] = [S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11]; |
|
| 116 | 116 | ||
| 117 | 117 | /// Maximum 12-bit signed immediate value. |
|
| 118 | - | export const MAX_IMM: i32 = 2047; |
|
| 118 | + | export constant MAX_IMM: i32 = 2047; |
|
| 119 | 119 | ||
| 120 | 120 | /// Minimum 12-bit signed immediate value. |
|
| 121 | - | export const MIN_IMM: i32 = -2048; |
|
| 121 | + | export constant MIN_IMM: i32 = -2048; |
|
| 122 | 122 | ||
| 123 | 123 | /// Allocatable registers for register allocation. |
|
| 124 | - | const ALLOCATABLE_REGS: [gen::Reg; 23] = [ |
|
| 124 | + | constant ALLOCATABLE_REGS: [gen::Reg; 23] = [ |
|
| 125 | 125 | T0, T1, T2, T3, // Temporaries |
|
| 126 | 126 | A0, A1, A2, A3, A4, A5, A6, A7, // Arguments |
|
| 127 | 127 | S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, // Saved |
|
| 128 | 128 | ]; |
|
| 129 | 129 |
| 141 | 141 | /////////////////////// |
|
| 142 | 142 | // Codegen Constants // |
|
| 143 | 143 | /////////////////////// |
|
| 144 | 144 | ||
| 145 | 145 | /// Base address where read-only data is loaded. |
|
| 146 | - | export const RO_DATA_BASE: u32 = 0x10000; |
|
| 146 | + | export constant RO_DATA_BASE: u32 = 0x10000; |
|
| 147 | 147 | ||
| 148 | 148 | /// Base address where read-write data is loaded. |
|
| 149 | - | export const RW_DATA_BASE: u32 = 0xFFFFF0; |
|
| 149 | + | export constant RW_DATA_BASE: u32 = 0xFFFFF0; |
|
| 150 | 150 | ||
| 151 | 151 | /// Storage buffers passed from driver for code generation. |
|
| 152 | 152 | export record Storage { |
|
| 153 | 153 | /// Buffer for data symbols. |
|
| 154 | 154 | dataSyms: *mut [data::DataSym], |
lib/std/arch/rv64/emit.rad
+5 -5
| 11 | 11 | use std::mem; |
|
| 12 | 12 | ||
| 13 | 13 | use super::encode; |
|
| 14 | 14 | ||
| 15 | 15 | /// Maximum number of instructions in code buffer. |
|
| 16 | - | const MAX_INSTRS: u32 = 2097152; |
|
| 16 | + | constant MAX_INSTRS: u32 = 2097152; |
|
| 17 | 17 | /// Maximum code length before byte offset overflows signed 32-bits. |
|
| 18 | - | const MAX_CODE_LEN: u32 = 0x7FFFFFFF / super::INSTR_SIZE as u32; |
|
| 18 | + | constant MAX_CODE_LEN: u32 = 0x7FFFFFFF / super::INSTR_SIZE as u32; |
|
| 19 | 19 | /// Maximum number of pending branches awaiting patching. |
|
| 20 | - | const MAX_PENDING: u32 = 65536; |
|
| 20 | + | constant MAX_PENDING: u32 = 65536; |
|
| 21 | 21 | /// Maximum number of function entries. |
|
| 22 | - | const MAX_FUNCS: u32 = 4096; |
|
| 22 | + | constant MAX_FUNCS: u32 = 4096; |
|
| 23 | 23 | /// Maximum number of debug entries. |
|
| 24 | - | const MAX_DEBUG_ENTRIES: u32 = 524288; |
|
| 24 | + | constant MAX_DEBUG_ENTRIES: u32 = 524288; |
|
| 25 | 25 | ||
| 26 | 26 | ////////////////////// |
|
| 27 | 27 | // Emission Context // |
|
| 28 | 28 | ////////////////////// |
|
| 29 | 29 |
lib/std/arch/rv64/encode.rad
+37 -37
| 6 | 6 | ||
| 7 | 7 | ////////////////////// |
|
| 8 | 8 | // Opcode Constants // |
|
| 9 | 9 | ////////////////////// |
|
| 10 | 10 | ||
| 11 | - | export const OP_LOAD: u32 = 0x03; |
|
| 12 | - | export const OP_STORE: u32 = 0x23; |
|
| 13 | - | export const OP_BRANCH: u32 = 0x63; |
|
| 14 | - | export const OP_JALR: u32 = 0x67; |
|
| 15 | - | export const OP_JAL: u32 = 0x6F; |
|
| 16 | - | export const OP_OP: u32 = 0x33; |
|
| 17 | - | export const OP_IMM: u32 = 0x13; |
|
| 18 | - | export const OP_AUIPC: u32 = 0x17; |
|
| 19 | - | export const OP_LUI: u32 = 0x37; |
|
| 20 | - | export const OP_SYSTEM: u32 = 0x73; |
|
| 21 | - | export const OP_OP32: u32 = 0x3B; // RV64: 32-bit operations |
|
| 22 | - | export const OP_IMM32: u32 = 0x1B; // RV64: 32-bit immediate operations |
|
| 11 | + | export constant OP_LOAD: u32 = 0x03; |
|
| 12 | + | export constant OP_STORE: u32 = 0x23; |
|
| 13 | + | export constant OP_BRANCH: u32 = 0x63; |
|
| 14 | + | export constant OP_JALR: u32 = 0x67; |
|
| 15 | + | export constant OP_JAL: u32 = 0x6F; |
|
| 16 | + | export constant OP_OP: u32 = 0x33; |
|
| 17 | + | export constant OP_IMM: u32 = 0x13; |
|
| 18 | + | export constant OP_AUIPC: u32 = 0x17; |
|
| 19 | + | export constant OP_LUI: u32 = 0x37; |
|
| 20 | + | export constant OP_SYSTEM: u32 = 0x73; |
|
| 21 | + | export constant OP_OP32: u32 = 0x3B; // RV64: 32-bit operations |
|
| 22 | + | export constant OP_IMM32: u32 = 0x1B; // RV64: 32-bit immediate operations |
|
| 23 | 23 | ||
| 24 | 24 | ////////////////////// |
|
| 25 | 25 | // Funct3 Constants // |
|
| 26 | 26 | ////////////////////// |
|
| 27 | 27 | ||
| 28 | 28 | // Memory operations |
|
| 29 | 29 | ||
| 30 | - | export const F3_BYTE: u32 = 0x0; // LB/SB |
|
| 31 | - | export const F3_HALF: u32 = 0x1; // LH/SH |
|
| 32 | - | export const F3_WORD: u32 = 0x2; // LW/SW |
|
| 33 | - | export const F3_DWORD: u32 = 0x3; // LD/SD (RV64) |
|
| 34 | - | export const F3_BYTE_U: u32 = 0x4; // LBU |
|
| 35 | - | export const F3_HALF_U: u32 = 0x5; // LHU |
|
| 36 | - | export const F3_WORD_U: u32 = 0x6; // LWU (RV64) |
|
| 30 | + | export constant F3_BYTE: u32 = 0x0; // LB/SB |
|
| 31 | + | export constant F3_HALF: u32 = 0x1; // LH/SH |
|
| 32 | + | export constant F3_WORD: u32 = 0x2; // LW/SW |
|
| 33 | + | export constant F3_DWORD: u32 = 0x3; // LD/SD (RV64) |
|
| 34 | + | export constant F3_BYTE_U: u32 = 0x4; // LBU |
|
| 35 | + | export constant F3_HALF_U: u32 = 0x5; // LHU |
|
| 36 | + | export constant F3_WORD_U: u32 = 0x6; // LWU (RV64) |
|
| 37 | 37 | ||
| 38 | 38 | // ALU operations |
|
| 39 | 39 | ||
| 40 | - | export const F3_ADD: u32 = 0x0; // ADD/SUB/ADDI |
|
| 41 | - | export const F3_SLL: u32 = 0x1; // SLL/SLLI |
|
| 42 | - | export const F3_SLT: u32 = 0x2; // SLT/SLTI |
|
| 43 | - | export const F3_SLTU: u32 = 0x3; // SLTU/SLTIU |
|
| 44 | - | export const F3_XOR: u32 = 0x4; // XOR/XORI |
|
| 45 | - | export const F3_SRL: u32 = 0x5; // SRL/SRA/SRLI/SRAI |
|
| 46 | - | export const F3_OR: u32 = 0x6; // OR/ORI |
|
| 47 | - | export const F3_AND: u32 = 0x7; // AND/ANDI |
|
| 40 | + | export constant F3_ADD: u32 = 0x0; // ADD/SUB/ADDI |
|
| 41 | + | export constant F3_SLL: u32 = 0x1; // SLL/SLLI |
|
| 42 | + | export constant F3_SLT: u32 = 0x2; // SLT/SLTI |
|
| 43 | + | export constant F3_SLTU: u32 = 0x3; // SLTU/SLTIU |
|
| 44 | + | export constant F3_XOR: u32 = 0x4; // XOR/XORI |
|
| 45 | + | export constant F3_SRL: u32 = 0x5; // SRL/SRA/SRLI/SRAI |
|
| 46 | + | export constant F3_OR: u32 = 0x6; // OR/ORI |
|
| 47 | + | export constant F3_AND: u32 = 0x7; // AND/ANDI |
|
| 48 | 48 | ||
| 49 | 49 | // Branch operations |
|
| 50 | 50 | ||
| 51 | - | export const F3_BEQ: u32 = 0x0; |
|
| 52 | - | export const F3_BNE: u32 = 0x1; |
|
| 53 | - | export const F3_BLT: u32 = 0x4; |
|
| 54 | - | export const F3_BGE: u32 = 0x5; |
|
| 55 | - | export const F3_BLTU: u32 = 0x6; |
|
| 56 | - | export const F3_BGEU: u32 = 0x7; |
|
| 51 | + | export constant F3_BEQ: u32 = 0x0; |
|
| 52 | + | export constant F3_BNE: u32 = 0x1; |
|
| 53 | + | export constant F3_BLT: u32 = 0x4; |
|
| 54 | + | export constant F3_BGE: u32 = 0x5; |
|
| 55 | + | export constant F3_BLTU: u32 = 0x6; |
|
| 56 | + | export constant F3_BGEU: u32 = 0x7; |
|
| 57 | 57 | ||
| 58 | 58 | ////////////////////// |
|
| 59 | 59 | // Funct7 Constants // |
|
| 60 | 60 | ////////////////////// |
|
| 61 | 61 | ||
| 62 | - | export const F7_NORMAL: u32 = 0b0000000; |
|
| 63 | - | export const F7_SUB: u32 = 0b0100000; // Bit 5 set |
|
| 64 | - | export const F7_SRA: u32 = 0b0100000; // Bit 5 set |
|
| 65 | - | export const F7_MUL: u32 = 0b0000001; // Bit 0 set |
|
| 62 | + | export constant F7_NORMAL: u32 = 0b0000000; |
|
| 63 | + | export constant F7_SUB: u32 = 0b0100000; // Bit 5 set |
|
| 64 | + | export constant F7_SRA: u32 = 0b0100000; // Bit 5 set |
|
| 65 | + | export constant F7_MUL: u32 = 0b0000001; // Bit 0 set |
|
| 66 | 66 | ||
| 67 | 67 | ///////////////////////// |
|
| 68 | 68 | // Validation Helpers // |
|
| 69 | 69 | ///////////////////////// |
|
| 70 | 70 |
lib/std/arch/rv64/isel.rad
+15 -15
| 40 | 40 | /////////////// |
|
| 41 | 41 | // Constants // |
|
| 42 | 42 | /////////////// |
|
| 43 | 43 | ||
| 44 | 44 | /// Shift amount for byte sign/zero extension. |
|
| 45 | - | const SHIFT_W8: i32 = 64 - 8; |
|
| 45 | + | constant SHIFT_W8: i32 = 64 - 8; |
|
| 46 | 46 | /// Shift amount for halfword sign/zero extension. |
|
| 47 | - | const SHIFT_W16: i32 = 64 - 16; |
|
| 47 | + | constant SHIFT_W16: i32 = 64 - 16; |
|
| 48 | 48 | /// Shift amount for word sign/zero extension. |
|
| 49 | - | const SHIFT_W32: i32 = 64 - 32; |
|
| 49 | + | constant SHIFT_W32: i32 = 64 - 32; |
|
| 50 | 50 | /// Mask for extracting byte value. |
|
| 51 | - | const MASK_W8: i32 = 0xFF; |
|
| 51 | + | constant MASK_W8: i32 = 0xFF; |
|
| 52 | 52 | /// Maximum number of block arguments supported. |
|
| 53 | - | const MAX_BLOCK_ARGS: u32 = 16; |
|
| 53 | + | constant MAX_BLOCK_ARGS: u32 = 16; |
|
| 54 | 54 | ||
| 55 | 55 | /// Signed integer range limits. |
|
| 56 | - | const I8_MIN: i64 = -128; |
|
| 57 | - | const I8_MAX: i64 = 127; |
|
| 58 | - | const I16_MIN: i64 = -32768; |
|
| 59 | - | const I16_MAX: i64 = 32767; |
|
| 60 | - | const I32_MIN: i64 = -2147483648; |
|
| 61 | - | const I32_MAX: i64 = 2147483647; |
|
| 56 | + | constant I8_MIN: i64 = -128; |
|
| 57 | + | constant I8_MAX: i64 = 127; |
|
| 58 | + | constant I16_MIN: i64 = -32768; |
|
| 59 | + | constant I16_MAX: i64 = 32767; |
|
| 60 | + | constant I32_MIN: i64 = -2147483648; |
|
| 61 | + | constant I32_MAX: i64 = 2147483647; |
|
| 62 | 62 | ||
| 63 | 63 | /// Unsigned integer range limits. |
|
| 64 | - | const U8_MAX: i64 = 255; |
|
| 65 | - | const U16_MAX: i64 = 65535; |
|
| 66 | - | const U32_MAX: i64 = 4294967295; |
|
| 64 | + | constant U8_MAX: i64 = 255; |
|
| 65 | + | constant U16_MAX: i64 = 65535; |
|
| 66 | + | constant U32_MAX: i64 = 4294967295; |
|
| 67 | 67 | ||
| 68 | 68 | /// Binary operation. |
|
| 69 | 69 | union BinOp { Add, And, Or, Xor } |
|
| 70 | 70 | /// Shift operation. |
|
| 71 | 71 | union ShiftOp { Sll, Srl, Sra } |
| 750 | 750 | } |
|
| 751 | 751 | }, |
|
| 752 | 752 | case il::Instr::Ecall { dst, num, a0, a1, a2, a3 } => { |
|
| 753 | 753 | // Move arguments using parallel move. |
|
| 754 | 754 | // TODO: Can't use slice literals here because the lowerer doesn't |
|
| 755 | - | // support const-evaluating struct/union values in them. |
|
| 755 | + | // support constant-evaluating struct/union values in them. |
|
| 756 | 756 | let ecallDsts: [gen::Reg; 5] = [super::A7, super::A0, super::A1, super::A2, super::A3]; |
|
| 757 | 757 | let ecallArgs: [il::Val; 5] = [num, a0, a1, a2, a3]; |
|
| 758 | 758 | ||
| 759 | 759 | emitParallelMoves(s, &ecallDsts[..], &ecallArgs[..]); |
|
| 760 | 760 | emit::emit(s.e, encode::ecall()); |
lib/std/arch/rv64/printer.rad
+2 -2
| 15 | 15 | ///////////////////// |
|
| 16 | 16 | // Register Names // |
|
| 17 | 17 | ///////////////////// |
|
| 18 | 18 | ||
| 19 | 19 | /// ABI register names. |
|
| 20 | - | const REG_NAMES: [*[u8]; 32] = [ |
|
| 20 | + | constant REG_NAMES: [*[u8]; 32] = [ |
|
| 21 | 21 | "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", |
|
| 22 | 22 | "fp", "s1", "a0", "a1", "a2", "a3", "a4", "a5", |
|
| 23 | 23 | "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", |
|
| 24 | 24 | "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6" |
|
| 25 | 25 | ]; |
| 66 | 66 | /////////////////////////////// |
|
| 67 | 67 | // Instruction Printing // |
|
| 68 | 68 | /////////////////////////////// |
|
| 69 | 69 | ||
| 70 | 70 | /// Mnemonic column width for alignment. |
|
| 71 | - | const MNEMONIC_WIDTH: u32 = 8; |
|
| 71 | + | constant MNEMONIC_WIDTH: u32 = 8; |
|
| 72 | 72 | ||
| 73 | 73 | /// Write text wrapped in parentheses. |
|
| 74 | 74 | fn writeParens(out: *mut sexpr::Output, s: *[u8]) { |
|
| 75 | 75 | write(out, "("); |
|
| 76 | 76 | write(out, s); |
lib/std/fmt.rad
+5 -5
| 1 | 1 | //! Formatting utilities for converting values to strings. |
|
| 2 | 2 | use super::mem; |
|
| 3 | 3 | ||
| 4 | 4 | /// Maximum string length for a formatted u32 (eg. "4294967295"). |
|
| 5 | - | export const U32_STR_LEN: u32 = 10; |
|
| 5 | + | export constant U32_STR_LEN: u32 = 10; |
|
| 6 | 6 | /// Maximum string length for a formatted i32 (eg. "-2147483648"). |
|
| 7 | - | export const I32_STR_LEN: u32 = U32_STR_LEN + 1; |
|
| 7 | + | export constant I32_STR_LEN: u32 = U32_STR_LEN + 1; |
|
| 8 | 8 | /// Maximum string length for a formatted u64 (eg. "18446744073709551615"). |
|
| 9 | - | export const U64_STR_LEN: u32 = 20; |
|
| 9 | + | export constant U64_STR_LEN: u32 = 20; |
|
| 10 | 10 | /// Maximum string length for a formatted i64 (eg. "-9223372036854775808"). |
|
| 11 | - | export const I64_STR_LEN: u32 = 20; |
|
| 11 | + | export constant I64_STR_LEN: u32 = 20; |
|
| 12 | 12 | /// Maximum string length for a formatted bool (eg. "false"). |
|
| 13 | - | export const BOOL_STR_LEN: u32 = 5; |
|
| 13 | + | export constant BOOL_STR_LEN: u32 = 5; |
|
| 14 | 14 | ||
| 15 | 15 | /// Format a u32 by writing it to the provided buffer. |
|
| 16 | 16 | export fn formatU32(val: u32, buffer: *mut [u8]) -> *[u8] { |
|
| 17 | 17 | assert buffer.len >= U32_STR_LEN; |
|
| 18 | 18 |
lib/std/lang/ast.rad
+1 -1
| 3 | 3 | ||
| 4 | 4 | use std::io; |
|
| 5 | 5 | use std::lang::alloc; |
|
| 6 | 6 | ||
| 7 | 7 | /// Maximum number of trait methods. |
|
| 8 | - | export const MAX_TRAIT_METHODS: u32 = 8; |
|
| 8 | + | export constant MAX_TRAIT_METHODS: u32 = 8; |
|
| 9 | 9 | ||
| 10 | 10 | /// Arena for all parser allocations. |
|
| 11 | 11 | /// |
|
| 12 | 12 | /// Uses a bump allocator for both AST nodes and node pointer arrays. |
|
| 13 | 13 | export record NodeArena { |
lib/std/lang/ast/printer.rad
+1 -1
| 346 | 346 | toExprOrNull(a, decl.type), |
|
| 347 | 347 | toExpr(a, decl.value) |
|
| 348 | 348 | ]); |
|
| 349 | 349 | } |
|
| 350 | 350 | case super::NodeValue::ConstDecl(decl) => |
|
| 351 | - | return sexpr::list(a, "const", &[toExpr(a, decl.ident), toExpr(a, decl.type), toExpr(a, decl.value)]), |
|
| 351 | + | return sexpr::list(a, "constant", &[toExpr(a, decl.ident), toExpr(a, decl.type), toExpr(a, decl.value)]), |
|
| 352 | 352 | case super::NodeValue::StaticDecl(decl) => |
|
| 353 | 353 | return sexpr::list(a, "static", &[toExpr(a, decl.ident), toExpr(a, decl.type), toExpr(a, decl.value)]), |
|
| 354 | 354 | case super::NodeValue::Assign(a_) => |
|
| 355 | 355 | return sexpr::list(a, "assign", &[toExpr(a, a_.left), toExpr(a, a_.right)]), |
|
| 356 | 356 | case super::NodeValue::Return { value } => |
lib/std/lang/gen/bitset.rad
+2 -2
| 215 | 215 | /// Count trailing zeros in a 32-bit value. |
|
| 216 | 216 | /// Returns the bit position of the lowest set bit (0-31). |
|
| 217 | 217 | /// Behavior is undefined if `x` is 0. |
|
| 218 | 218 | fn ctz(x: u32) -> u32 { |
|
| 219 | 219 | // De Bruijn sequence for 32-bit CTZ. |
|
| 220 | - | const DEBRUIJN: u32 = 0x077CB531; |
|
| 221 | - | const TABLE: [u8; 32] = [ |
|
| 220 | + | constant DEBRUIJN: u32 = 0x077CB531; |
|
| 221 | + | constant TABLE: [u8; 32] = [ |
|
| 222 | 222 | 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, |
|
| 223 | 223 | 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, |
|
| 224 | 224 | ]; |
|
| 225 | 225 | // Isolate lowest set bit, multiply by de Bruijn constant, look up. |
|
| 226 | 226 | let isolated = x & (~x + 1); |
lib/std/lang/gen/data.rad
+2 -2
| 7 | 7 | use std::collections::dict; |
|
| 8 | 8 | use std::lang::il; |
|
| 9 | 9 | use std::lang::gen::labels; |
|
| 10 | 10 | ||
| 11 | 11 | /// Maximum number of data symbols. |
|
| 12 | - | export const MAX_DATA_SYMS: u32 = 8192; |
|
| 12 | + | export constant MAX_DATA_SYMS: u32 = 8192; |
|
| 13 | 13 | ||
| 14 | 14 | /// Size of the data symbol hash table. Must be a power of two |
|
| 15 | 15 | /// and at least twice the size of [`MAX_DATA_SYMS`]. |
|
| 16 | - | export const DATA_SYM_TABLE_SIZE: u32 = MAX_DATA_SYMS * 2; |
|
| 16 | + | export constant DATA_SYM_TABLE_SIZE: u32 = MAX_DATA_SYMS * 2; |
|
| 17 | 17 | ||
| 18 | 18 | /// Data symbol entry mapping name to address. |
|
| 19 | 19 | export record DataSym { |
|
| 20 | 20 | /// Symbol name. |
|
| 21 | 21 | name: *[u8], |
lib/std/lang/gen/labels.rad
+3 -3
| 3 | 3 | //! Provides target-independent block/label tracking for branch resolution. |
|
| 4 | 4 | ||
| 5 | 5 | use std::collections::dict; |
|
| 6 | 6 | ||
| 7 | 7 | /// Maximum number of blocks per function. |
|
| 8 | - | export const MAX_BLOCKS_PER_FN: u32 = 4096; |
|
| 8 | + | export constant MAX_BLOCKS_PER_FN: u32 = 4096; |
|
| 9 | 9 | /// Maximum number of functions. |
|
| 10 | - | export const MAX_FUNCS: u32 = 8192; |
|
| 10 | + | export constant MAX_FUNCS: u32 = 8192; |
|
| 11 | 11 | /// Size of the function hash table. Must be a power of two. |
|
| 12 | - | export const FUNC_TABLE_SIZE: u32 = MAX_FUNCS * 2; |
|
| 12 | + | export constant FUNC_TABLE_SIZE: u32 = MAX_FUNCS * 2; |
|
| 13 | 13 | ||
| 14 | 14 | /// Label tracking for code emission. |
|
| 15 | 15 | export record Labels { |
|
| 16 | 16 | /// Block offsets indexed by block index. |
|
| 17 | 17 | /// Per-function, reset each function. |
lib/std/lang/gen/regalloc/assign.rad
+1 -1
| 12 | 12 | use std::lang::gen::bitset; |
|
| 13 | 13 | use std::lang::gen::regalloc::liveness; |
|
| 14 | 14 | use std::lang::gen::regalloc::spill; |
|
| 15 | 15 | ||
| 16 | 16 | /// Maximum number of active register mappings. |
|
| 17 | - | const MAX_ACTIVE: u32 = 64; |
|
| 17 | + | constant MAX_ACTIVE: u32 = 64; |
|
| 18 | 18 | ||
| 19 | 19 | /// Register mapping at a program point. |
|
| 20 | 20 | /// Maps SSA registers to physical registers. |
|
| 21 | 21 | export record RegMap { |
|
| 22 | 22 | /// SSA (virtual) registers that have mappings. |
lib/std/lang/gen/regalloc/liveness.rad
+1 -1
| 27 | 27 | use std::lang::il; |
|
| 28 | 28 | use std::lang::alloc; |
|
| 29 | 29 | use std::lang::gen::bitset; |
|
| 30 | 30 | ||
| 31 | 31 | /// Maximum number of SSA registers supported. |
|
| 32 | - | export const MAX_SSA_REGS: u32 = 8192; |
|
| 32 | + | export constant MAX_SSA_REGS: u32 = 8192; |
|
| 33 | 33 | ||
| 34 | 34 | /// Liveness information for a function. |
|
| 35 | 35 | export record LiveInfo { |
|
| 36 | 36 | /// Per-block live-in sets (indexed by block index). |
|
| 37 | 37 | liveIn: *mut [bitset::Bitset], |
lib/std/lang/gen/regalloc/spill.rad
+2 -2
| 34 | 34 | use std::lang::alloc; |
|
| 35 | 35 | use std::lang::gen::bitset; |
|
| 36 | 36 | use std::lang::gen::regalloc::liveness; |
|
| 37 | 37 | ||
| 38 | 38 | /// Maximum number of candidates for spill sorting. |
|
| 39 | - | const MAX_CANDIDATES: u32 = 256; |
|
| 39 | + | constant MAX_CANDIDATES: u32 = 256; |
|
| 40 | 40 | /// Maximum loop depth for cost weighting (2^10 = 1024). |
|
| 41 | - | const MAX_LOOP_WEIGHT: u32 = 10; |
|
| 41 | + | constant MAX_LOOP_WEIGHT: u32 = 10; |
|
| 42 | 42 | ||
| 43 | 43 | /// Spill cost for a single SSA register. |
|
| 44 | 44 | record SpillCost { |
|
| 45 | 45 | /// Number of definitions (weighted by loop depth). |
|
| 46 | 46 | defs: u32, |
lib/std/lang/il.rad
+2 -2
| 77 | 77 | /////////////////////// |
|
| 78 | 78 | // Name Formatting // |
|
| 79 | 79 | /////////////////////// |
|
| 80 | 80 | ||
| 81 | 81 | /// Separator for qualified symbol names. |
|
| 82 | - | export const PATH_SEPARATOR: *[u8] = "::"; |
|
| 82 | + | export constant PATH_SEPARATOR: *[u8] = "::"; |
|
| 83 | 83 | ||
| 84 | 84 | /// Format a qualified symbol name: `pkg::mod::path::name`. |
|
| 85 | 85 | export fn formatQualifiedName(arena: *mut alloc::Arena, path: *[*[u8]], name: *[u8]) -> *[u8] { |
|
| 86 | 86 | let mut totalLen: u32 = name.len; |
|
| 87 | 87 | for segment in path { |
| 373 | 373 | /// Size in bytes. |
|
| 374 | 374 | size: u32, |
|
| 375 | 375 | /// Alignment requirement. |
|
| 376 | 376 | alignment: u32, |
|
| 377 | 377 | /// Whether this is read-only data. |
|
| 378 | - | /// Typically, `const` declaration are read-only, while `static` |
|
| 378 | + | /// Typically, `constant` declaration are read-only, while `static` |
|
| 379 | 379 | /// declarations are not. |
|
| 380 | 380 | readOnly: bool, |
|
| 381 | 381 | /// Whether the data is entirely undefined. |
|
| 382 | 382 | /// Undefined data doesn't need to be written since memory is zero-initialized. |
|
| 383 | 383 | isUndefined: bool, |
lib/std/lang/lower.rad
+12 -12
| 199 | 199 | /////////////// |
|
| 200 | 200 | // Constants // |
|
| 201 | 201 | /////////////// |
|
| 202 | 202 | ||
| 203 | 203 | /// Maximum nesting depth of loops. |
|
| 204 | - | const MAX_LOOP_DEPTH: u32 = 16; |
|
| 204 | + | constant MAX_LOOP_DEPTH: u32 = 16; |
|
| 205 | 205 | /// Maximum number of `catch` clauses per `try`. |
|
| 206 | - | const MAX_CATCH_CLAUSES: u32 = 32; |
|
| 206 | + | constant MAX_CATCH_CLAUSES: u32 = 32; |
|
| 207 | 207 | ||
| 208 | 208 | // Slice Layout |
|
| 209 | 209 | // |
|
| 210 | 210 | // A slice is a fat pointer consisting of a data pointer and length. |
|
| 211 | 211 | // `{ ptr: u32, len: u32 }`. |
|
| 212 | 212 | ||
| 213 | 213 | /// Slice data pointer offset. |
|
| 214 | - | const SLICE_PTR_OFFSET: i32 = 0; |
|
| 214 | + | constant SLICE_PTR_OFFSET: i32 = 0; |
|
| 215 | 215 | /// Offset of slice length in slice data structure. |
|
| 216 | - | const SLICE_LEN_OFFSET: i32 = resolver::PTR_SIZE as i32; |
|
| 216 | + | constant SLICE_LEN_OFFSET: i32 = resolver::PTR_SIZE as i32; |
|
| 217 | 217 | /// Offset of slice capacity in slice data structure. |
|
| 218 | - | const SLICE_CAP_OFFSET: i32 = resolver::PTR_SIZE as i32 + 4; |
|
| 218 | + | constant SLICE_CAP_OFFSET: i32 = resolver::PTR_SIZE as i32 + 4; |
|
| 219 | 219 | ||
| 220 | 220 | // Trait Object Layout |
|
| 221 | 221 | // |
|
| 222 | 222 | // A trait object is a fat pointer consisting of a data pointer and a |
|
| 223 | 223 | // v-table pointer. `{ data: *T, vtable: *VTable }`. |
|
| 224 | 224 | ||
| 225 | 225 | /// Trait object data pointer offset. |
|
| 226 | - | const TRAIT_OBJ_DATA_OFFSET: i32 = 0; |
|
| 226 | + | constant TRAIT_OBJ_DATA_OFFSET: i32 = 0; |
|
| 227 | 227 | /// Trait object v-table pointer offset. |
|
| 228 | - | const TRAIT_OBJ_VTABLE_OFFSET: i32 = resolver::PTR_SIZE as i32; |
|
| 228 | + | constant TRAIT_OBJ_VTABLE_OFFSET: i32 = resolver::PTR_SIZE as i32; |
|
| 229 | 229 | ||
| 230 | 230 | // Tagged Value Layout (optionals, tagged unions) |
|
| 231 | 231 | // |
|
| 232 | 232 | // Optionals and unions use 1-byte tags. Results use 8-byte tags. |
|
| 233 | 233 | // |
| 237 | 237 | // When `T` is a pointer, the entire optional is stored as a single pointer. |
|
| 238 | 238 | // |
|
| 239 | 239 | // Tagged unions have a payload the size of the maximum variant size. |
|
| 240 | 240 | ||
| 241 | 241 | /// Offset of tag in tagged value data structure. |
|
| 242 | - | const TVAL_TAG_OFFSET: i32 = 0; |
|
| 242 | + | constant TVAL_TAG_OFFSET: i32 = 0; |
|
| 243 | 243 | /// Offset of value in result data structure (8-byte tag). |
|
| 244 | - | const RESULT_VAL_OFFSET: i32 = resolver::PTR_SIZE as i32; |
|
| 244 | + | constant RESULT_VAL_OFFSET: i32 = resolver::PTR_SIZE as i32; |
|
| 245 | 245 | ||
| 246 | 246 | ////////////////////////// |
|
| 247 | 247 | // Core Data Structures // |
|
| 248 | 248 | ////////////////////////// |
|
| 249 | 249 |
| 1174 | 1174 | ||
| 1175 | 1175 | /////////////////////////////// |
|
| 1176 | 1176 | // Data Section Construction // |
|
| 1177 | 1177 | /////////////////////////////// |
|
| 1178 | 1178 | ||
| 1179 | - | // Functions for building the data section from const/static |
|
| 1179 | + | // Functions for building the data section from constant/static |
|
| 1180 | 1180 | // declarations and inline literals. |
|
| 1181 | 1181 | ||
| 1182 | 1182 | /// Convert a constant integer payload to a signed 64-bit value. |
|
| 1183 | 1183 | fn constIntToI64(intVal: resolver::ConstInt) -> i64 { |
|
| 1184 | 1184 | return (0 - intVal.magnitude as i64) if intVal.negative else intVal.magnitude as i64; |
| 1215 | 1215 | irTyp = ilType(self, typ); |
|
| 1216 | 1216 | } |
|
| 1217 | 1217 | return il::DataItem::Val { typ: irTyp, val: constToScalar(val) }; |
|
| 1218 | 1218 | } |
|
| 1219 | 1219 | ||
| 1220 | - | /// Lower a const or static declaration to the data section. |
|
| 1220 | + | /// Lower a constant or static declaration to the data section. |
|
| 1221 | 1221 | fn lowerDataDecl( |
|
| 1222 | 1222 | self: *mut Lowerer, |
|
| 1223 | 1223 | node: *ast::Node, |
|
| 1224 | 1224 | value: *ast::Node, |
|
| 1225 | 1225 | readOnly: bool |
| 1687 | 1687 | } |
|
| 1688 | 1688 | } |
|
| 1689 | 1689 | return nil; |
|
| 1690 | 1690 | } |
|
| 1691 | 1691 | ||
| 1692 | - | /// Find existing const data entry with matching content. |
|
| 1692 | + | /// Find existing constant data entry with matching content. |
|
| 1693 | 1693 | /// Handles both string data and slice data. |
|
| 1694 | 1694 | fn findConstData(self: *Lowerer, values: *[il::DataValue], alignment: u32) -> ?*[u8] { |
|
| 1695 | 1695 | // Fast path for strings. |
|
| 1696 | 1696 | if values.len == 1 and alignment == 1 { |
|
| 1697 | 1697 | if let case il::DataItem::Str(s) = values[0].item { |
lib/std/lang/module.rad
+5 -5
| 12 | 12 | use std::lang::alloc; |
|
| 13 | 13 | use std::lang::ast; |
|
| 14 | 14 | use std::lang::strings; |
|
| 15 | 15 | ||
| 16 | 16 | /// Maximum number of modules tracked in a single compilation graph. |
|
| 17 | - | export const MAX_MODULES: u32 = 128; |
|
| 17 | + | export constant MAX_MODULES: u32 = 128; |
|
| 18 | 18 | /// Maximum number of characters for a module path. |
|
| 19 | - | const MAX_PATH_LEN: u32 = 256; |
|
| 19 | + | constant MAX_PATH_LEN: u32 = 256; |
|
| 20 | 20 | /// Maximum number of components that make up a logical module path. |
|
| 21 | - | const MAX_MODULE_PATH_DEPTH: u32 = 16; |
|
| 21 | + | constant MAX_MODULE_PATH_DEPTH: u32 = 16; |
|
| 22 | 22 | /// Filesystem separator used when constructing child paths. |
|
| 23 | - | const PATH_SEP: u8 = '/'; |
|
| 23 | + | constant PATH_SEP: u8 = '/'; |
|
| 24 | 24 | /// Source file extension handled by the loader. |
|
| 25 | - | const SOURCE_EXT: *[u8] = ".rad"; |
|
| 25 | + | constant SOURCE_EXT: *[u8] = ".rad"; |
|
| 26 | 26 | ||
| 27 | 27 | /// Lifecycle state for modules in the dependency graph. |
|
| 28 | 28 | export union ModuleState { |
|
| 29 | 29 | /// Slot unused or yet to be initialized. |
|
| 30 | 30 | Vacant, |
lib/std/lang/package.rad
+1 -1
| 4 | 4 | use std::lang::ast; |
|
| 5 | 5 | use std::lang::module; |
|
| 6 | 6 | use std::lang::strings; |
|
| 7 | 7 | ||
| 8 | 8 | /// Maximum number of packages processed in a single invocation. |
|
| 9 | - | export const MAX_PACKAGES: u32 = 4; |
|
| 9 | + | export constant MAX_PACKAGES: u32 = 4; |
|
| 10 | 10 | ||
| 11 | 11 | /// A compilation unit. |
|
| 12 | 12 | export record Package { |
|
| 13 | 13 | /// Package identifier (index in the package array). |
|
| 14 | 14 | id: u16, |
lib/std/lang/parser.rad
+9 -9
| 7 | 7 | use std::lang::ast; |
|
| 8 | 8 | use std::lang::strings; |
|
| 9 | 9 | use std::lang::scanner; |
|
| 10 | 10 | ||
| 11 | 11 | /// Maximum `u32` value. |
|
| 12 | - | export const U32_MAX: u32 = 0xFFFFFFFF; |
|
| 12 | + | export constant U32_MAX: u32 = 0xFFFFFFFF; |
|
| 13 | 13 | /// Maximum representable `u64` value. |
|
| 14 | - | export const U64_MAX: u64 = 0xFFFFFFFFFFFFFFFF; |
|
| 14 | + | export constant U64_MAX: u64 = 0xFFFFFFFFFFFFFFFF; |
|
| 15 | 15 | /// Maximum number of fields in a record. |
|
| 16 | - | export const MAX_RECORD_FIELDS: u32 = 32; |
|
| 16 | + | export constant MAX_RECORD_FIELDS: u32 = 32; |
|
| 17 | 17 | ||
| 18 | 18 | /// Maximum number of parser errors before aborting. |
|
| 19 | - | const MAX_ERRORS: u32 = 8; |
|
| 19 | + | constant MAX_ERRORS: u32 = 8; |
|
| 20 | 20 | ||
| 21 | 21 | /// Parser error type. |
|
| 22 | 22 | export union ParseError { |
|
| 23 | 23 | /// Encountered a token that was not expected in the current context. |
|
| 24 | 24 | UnexpectedToken, |
| 926 | 926 | p.current.kind == scanner::TokenKind::Fn or |
|
| 927 | 927 | p.current.kind == scanner::TokenKind::Union or |
|
| 928 | 928 | p.current.kind == scanner::TokenKind::Record or |
|
| 929 | 929 | p.current.kind == scanner::TokenKind::Mod or |
|
| 930 | 930 | p.current.kind == scanner::TokenKind::Static or |
|
| 931 | - | p.current.kind == scanner::TokenKind::Const or |
|
| 931 | + | p.current.kind == scanner::TokenKind::Constant or |
|
| 932 | 932 | p.current.kind == scanner::TokenKind::Use or |
|
| 933 | 933 | p.current.kind == scanner::TokenKind::Trait; |
|
| 934 | 934 | ||
| 935 | 935 | if not allowed { |
|
| 936 | 936 | throw failParsing(p, "attributes are not allowed in this context"); |
| 984 | 984 | if consume(p, scanner::TokenKind::Mut) { |
|
| 985 | 985 | return try parseLet(p, true); |
|
| 986 | 986 | } |
|
| 987 | 987 | return try parseLet(p, false); |
|
| 988 | 988 | } |
|
| 989 | - | case scanner::TokenKind::Const => { |
|
| 989 | + | case scanner::TokenKind::Constant => { |
|
| 990 | 990 | return try parseConst(p, attrs); |
|
| 991 | 991 | } |
|
| 992 | 992 | case scanner::TokenKind::Static => { |
|
| 993 | 993 | return try parseStatic(p, attrs); |
|
| 994 | 994 | } |
| 2119 | 2119 | ||
| 2120 | 2120 | /// Parse a constant declaration. |
|
| 2121 | 2121 | fn parseConst(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node |
|
| 2122 | 2122 | throws (ParseError) |
|
| 2123 | 2123 | { |
|
| 2124 | - | try expect(p, scanner::TokenKind::Const, "expected `const`"); |
|
| 2124 | + | try expect(p, scanner::TokenKind::Constant, "expected `constant`"); |
|
| 2125 | 2125 | ||
| 2126 | - | let ident = try parseIdent(p, "expected identifier in const declaration"); |
|
| 2126 | + | let ident = try parseIdent(p, "expected identifier in constant declaration"); |
|
| 2127 | 2127 | try expect(p, scanner::TokenKind::Colon, "expected `:` after identifier"); |
|
| 2128 | 2128 | ||
| 2129 | 2129 | let type = try parseType(p); |
|
| 2130 | - | try expect(p, scanner::TokenKind::Equal, "expected `=` in const declaration"); |
|
| 2130 | + | try expect(p, scanner::TokenKind::Equal, "expected `=` in constant declaration"); |
|
| 2131 | 2131 | ||
| 2132 | 2132 | let value = try parseExpr(p); |
|
| 2133 | 2133 | ||
| 2134 | 2134 | return node(p, ast::NodeValue::ConstDecl( |
|
| 2135 | 2135 | ast::ConstDecl { ident, type, value, attrs } |
lib/std/lang/parser/tests.rad
+3 -3
| 5 | 5 | use std::lang::ast; |
|
| 6 | 6 | use std::lang::scanner; |
|
| 7 | 7 | use std::lang::strings; |
|
| 8 | 8 | ||
| 9 | 9 | /// Unified arena size. |
|
| 10 | - | const ARENA_SIZE: u32 = 2097152; |
|
| 10 | + | constant ARENA_SIZE: u32 = 2097152; |
|
| 11 | 11 | /// Unified arena storage for all AST allocations. |
|
| 12 | 12 | static ARENA_STORAGE: [u8; ARENA_SIZE] = undefined; |
|
| 13 | 13 | /// String pool. |
|
| 14 | 14 | static STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 }; |
|
| 15 | 15 |
| 746 | 746 | try expectType(type, ast::TypeSig::Integer { |
|
| 747 | 747 | width: 4, sign: ast::Signedness::Signed |
|
| 748 | 748 | }); |
|
| 749 | 749 | } |
|
| 750 | 750 | ||
| 751 | - | /// Test parsing a `const` declaration. |
|
| 751 | + | /// Test parsing a `constant` declaration. |
|
| 752 | 752 | @test fn testParseConst() throws (testing::TestError) { |
|
| 753 | - | let node = try! parseStmtStr("const ANSWER: i32 = 42;"); |
|
| 753 | + | let node = try! parseStmtStr("constant ANSWER: i32 = 42;"); |
|
| 754 | 754 | let case ast::NodeValue::ConstDecl(decl) = node.value |
|
| 755 | 755 | else throw testing::TestError::Failed; |
|
| 756 | 756 | ||
| 757 | 757 | try expectIdent(decl.ident, "ANSWER"); |
|
| 758 | 758 | try expectType(decl.type, ast::TypeSig::Integer { |
lib/std/lang/resolver.rad
+26 -26
| 19 | 19 | use std::lang::ast; |
|
| 20 | 20 | use std::lang::parser; |
|
| 21 | 21 | use std::lang::module; |
|
| 22 | 22 | ||
| 23 | 23 | /// Maximum number of diagnostics recorded. |
|
| 24 | - | export const MAX_ERRORS: u32 = 64; |
|
| 24 | + | export constant MAX_ERRORS: u32 = 64; |
|
| 25 | 25 | ||
| 26 | 26 | /// Synthetic function name used when wrapping a bare expression for analysis. |
|
| 27 | - | export const ANALYZE_EXPR_FN_NAME: *[u8] = "__expr__"; |
|
| 27 | + | export constant ANALYZE_EXPR_FN_NAME: *[u8] = "__expr__"; |
|
| 28 | 28 | /// Synthetic function name used when wrapping a block for analysis. |
|
| 29 | - | export const ANALYZE_BLOCK_FN_NAME: *[u8] = "__block__"; |
|
| 29 | + | export constant ANALYZE_BLOCK_FN_NAME: *[u8] = "__block__"; |
|
| 30 | 30 | ||
| 31 | 31 | /// Maximum number of symbols stored within a module scope. |
|
| 32 | - | export const MAX_MODULE_SYMBOLS: u32 = 512; |
|
| 32 | + | export constant MAX_MODULE_SYMBOLS: u32 = 512; |
|
| 33 | 33 | /// Maximum number of symbols stored within a local scope. |
|
| 34 | - | export const MAX_LOCAL_SYMBOLS: u32 = 32; |
|
| 34 | + | export constant MAX_LOCAL_SYMBOLS: u32 = 32; |
|
| 35 | 35 | /// Maximum function parameters. |
|
| 36 | - | export const MAX_FN_PARAMS: u32 = 8; |
|
| 36 | + | export constant MAX_FN_PARAMS: u32 = 8; |
|
| 37 | 37 | /// Maximum function thrown types. |
|
| 38 | - | export const MAX_FN_THROWS: u32 = 8; |
|
| 38 | + | export constant MAX_FN_THROWS: u32 = 8; |
|
| 39 | 39 | /// Maximum number of variants in a union. |
|
| 40 | 40 | /// Nb. This should not be raised above `255`, |
|
| 41 | 41 | /// as tags are stored using 8-bits only. |
|
| 42 | - | export const MAX_UNION_VARIANTS: u32 = 128; |
|
| 42 | + | export constant MAX_UNION_VARIANTS: u32 = 128; |
|
| 43 | 43 | /// Maximum nesting of loops. |
|
| 44 | - | export const MAX_LOOP_DEPTH: u32 = 16; |
|
| 44 | + | export constant MAX_LOOP_DEPTH: u32 = 16; |
|
| 45 | 45 | /// Maximum trait instances. |
|
| 46 | - | export const MAX_INSTANCES: u32 = 128; |
|
| 46 | + | export constant MAX_INSTANCES: u32 = 128; |
|
| 47 | 47 | /// Maximum standalone methods (across all types). |
|
| 48 | - | export const MAX_METHODS: u32 = 256; |
|
| 48 | + | export constant MAX_METHODS: u32 = 256; |
|
| 49 | 49 | ||
| 50 | 50 | /// Trait definition stored in the resolver. |
|
| 51 | 51 | export record TraitType { |
|
| 52 | 52 | /// Trait name. |
|
| 53 | 53 | name: *[u8], |
| 98 | 98 | /// Symbol for the method. |
|
| 99 | 99 | symbol: *mut Symbol, |
|
| 100 | 100 | } |
|
| 101 | 101 | ||
| 102 | 102 | /// Identifier for the synthetic `len` field. |
|
| 103 | - | export const LEN_FIELD: *[u8] = "len"; |
|
| 103 | + | export constant LEN_FIELD: *[u8] = "len"; |
|
| 104 | 104 | /// Identifier for the synthetic `ptr` field. |
|
| 105 | - | export const PTR_FIELD: *[u8] = "ptr"; |
|
| 105 | + | export constant PTR_FIELD: *[u8] = "ptr"; |
|
| 106 | 106 | /// Identifier for the synthetic `cap` field. |
|
| 107 | - | export const CAP_FIELD: *[u8] = "cap"; |
|
| 107 | + | export constant CAP_FIELD: *[u8] = "cap"; |
|
| 108 | 108 | ||
| 109 | 109 | /// Maximum `u16` value. |
|
| 110 | - | const U16_MAX: u16 = 0xFFFF; |
|
| 110 | + | constant U16_MAX: u16 = 0xFFFF; |
|
| 111 | 111 | /// Maximum `u8` value. |
|
| 112 | - | const U8_MAX: u16 = 0xFF; |
|
| 112 | + | constant U8_MAX: u16 = 0xFF; |
|
| 113 | 113 | ||
| 114 | 114 | /// Minimum `i8` value. |
|
| 115 | - | const I8_MIN: i32 = -128; |
|
| 115 | + | constant I8_MIN: i32 = -128; |
|
| 116 | 116 | /// Maximum `i8` value. |
|
| 117 | - | const I8_MAX: i32 = 127; |
|
| 117 | + | constant I8_MAX: i32 = 127; |
|
| 118 | 118 | /// Minimum `i16` value. |
|
| 119 | - | const I16_MIN: i32 = -32768; |
|
| 119 | + | constant I16_MIN: i32 = -32768; |
|
| 120 | 120 | /// Maximum `i16` value. |
|
| 121 | - | const I16_MAX: i32 = 32767; |
|
| 121 | + | constant I16_MAX: i32 = 32767; |
|
| 122 | 122 | ||
| 123 | 123 | /// Minimum `i32` value. |
|
| 124 | - | const I32_MIN: i32 = -2147483648; |
|
| 124 | + | constant I32_MIN: i32 = -2147483648; |
|
| 125 | 125 | /// Maximum `i32` value. |
|
| 126 | - | const I32_MAX: i32 = 2147483647; |
|
| 126 | + | constant I32_MAX: i32 = 2147483647; |
|
| 127 | 127 | /// Minimum `i64` value: -(2^63). |
|
| 128 | - | const I64_MIN: i64 = -9223372036854775808; |
|
| 128 | + | constant I64_MIN: i64 = -9223372036854775808; |
|
| 129 | 129 | /// Maximum `i64` value: 2^63 - 1. |
|
| 130 | - | const I64_MAX: i64 = 9223372036854775807; |
|
| 130 | + | constant I64_MAX: i64 = 9223372036854775807; |
|
| 131 | 131 | ||
| 132 | 132 | /// Size of a pointer in bytes. |
|
| 133 | - | export const PTR_SIZE: u32 = 8; |
|
| 133 | + | export constant PTR_SIZE: u32 = 8; |
|
| 134 | 134 | ||
| 135 | 135 | /// Information about a record or tuple field. |
|
| 136 | 136 | export record RecordField { |
|
| 137 | 137 | /// Field name, `nil` for positional fields. |
|
| 138 | 138 | name: ?*[u8], |
| 2975 | 2975 | actual: args.len, |
|
| 2976 | 2976 | })); |
|
| 2977 | 2977 | } |
|
| 2978 | 2978 | } |
|
| 2979 | 2979 | ||
| 2980 | - | /// Helper for analyzing `const` and `static` declarations. |
|
| 2980 | + | /// Helper for analyzing `constant` and `static` declarations. |
|
| 2981 | 2981 | fn resolveConstOrStatic( |
|
| 2982 | 2982 | self: *mut Resolver, |
|
| 2983 | 2983 | node: *ast::Node, |
|
| 2984 | 2984 | ident: *ast::Node, |
|
| 2985 | 2985 | typeNode: *ast::Node, |
lib/std/lang/resolver/tests.rad
+52 -52
| 8 | 8 | use std::lang::scanner; |
|
| 9 | 9 | use std::lang::module; |
|
| 10 | 10 | use std::lang::strings; |
|
| 11 | 11 | ||
| 12 | 12 | /// Synthetic file path used for resolver tests. |
|
| 13 | - | const MODULE_PATH: *[u8] = "/dev/test.rad"; |
|
| 13 | + | constant MODULE_PATH: *[u8] = "/dev/test.rad"; |
|
| 14 | 14 | ||
| 15 | 15 | static AST_ARENA: [u8; 2097152] = undefined; |
|
| 16 | 16 | static ARENA_STORAGE: [u8; 2097152] = undefined; |
|
| 17 | 17 | static NODE_DATA_STORAGE: [super::NodeData; 256] = undefined; |
|
| 18 | 18 | static ERROR_STORAGE: [super::Error; 16] = undefined; |
| 22 | 22 | static MODULE_ARENA_STORAGE: [u8; 4096] = undefined; |
|
| 23 | 23 | static MODULE_ARENA: ast::NodeArena = undefined; |
|
| 24 | 24 | static STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 }; |
|
| 25 | 25 | ||
| 26 | 26 | /// String literals used in tests. |
|
| 27 | - | const LITERALS: [*[u8]; 15] = [ |
|
| 27 | + | constant LITERALS: [*[u8]; 15] = [ |
|
| 28 | 28 | "Ok", "Error", "R", "S", |
|
| 29 | 29 | "f", "Status", "Pending", |
|
| 30 | 30 | "Some", "None", "First", |
|
| 31 | 31 | "Second", "Opt", "x", |
|
| 32 | 32 | "value", "idx" |
| 545 | 545 | try expectErrorKind(&result, super::ErrorKind::DuplicateBinding("x")); |
|
| 546 | 546 | } |
|
| 547 | 547 | ||
| 548 | 548 | @test fn testResolveConstLiteralValue() throws (testing::TestError) { |
|
| 549 | 549 | let mut a = testResolver(); |
|
| 550 | - | let program = "const ANSWER: i32 = 42;"; |
|
| 550 | + | let program = "constant ANSWER: i32 = 42;"; |
|
| 551 | 551 | let result = try resolveProgramStr(&mut a, program); |
|
| 552 | 552 | try expectNoErrors(&result); |
|
| 553 | 553 | ||
| 554 | 554 | let constNode = try getBlockStmt(result.root, 0); |
|
| 555 | 555 | let sym = super::symbolFor(&a, constNode) |
| 559 | 559 | try testing::expect(constType == super::Type::I32); |
|
| 560 | 560 | } |
|
| 561 | 561 | ||
| 562 | 562 | @test fn testResolveConstRequiresConstantExpr() throws (testing::TestError) { |
|
| 563 | 563 | let mut a = testResolver(); |
|
| 564 | - | let program = "fn value() -> i32 { return 1 } fn main() { const ANSWER: i32 = value(); }"; |
|
| 564 | + | let program = "fn value() -> i32 { return 1 } fn main() { constant ANSWER: i32 = value(); }"; |
|
| 565 | 565 | let result = try resolveProgramStr(&mut a, program); |
|
| 566 | 566 | let err = try expectErrorKind(&result, super::ErrorKind::ConstExprRequired); |
|
| 567 | 567 | ||
| 568 | 568 | let errNode = err.node |
|
| 569 | 569 | else throw testing::TestError::Failed; |
| 979 | 979 | } |
|
| 980 | 980 | } |
|
| 981 | 981 | ||
| 982 | 982 | @test fn testResolveArrayLenConstValue() throws (testing::TestError) { |
|
| 983 | 983 | let mut a = testResolver(); |
|
| 984 | - | let program = "let xs: [i32; 3] = [1, 2, 3]; const LEN: u32 = xs.len;"; |
|
| 984 | + | let program = "let xs: [i32; 3] = [1, 2, 3]; constant LEN: u32 = xs.len;"; |
|
| 985 | 985 | let result = try resolveBlockStr(&mut a, program); |
|
| 986 | 986 | try expectNoErrors(&result); |
|
| 987 | 987 | ||
| 988 | 988 | let constStmt = try getBlockStmt(result.root, 1); |
|
| 989 | 989 | let case ast::NodeValue::ConstDecl(decl) = constStmt.value |
| 1791 | 1791 | try expectAnalyzeOk("let x: u16 = 0xFFFF;"); |
|
| 1792 | 1792 | try expectAnalyzeOk("let x: i32 = 2147483647;"); |
|
| 1793 | 1793 | try expectAnalyzeOk("let x: i32 = -2147483648;"); |
|
| 1794 | 1794 | try expectAnalyzeOk("let x: u32 = 0xFFFFFFFF;"); |
|
| 1795 | 1795 | ||
| 1796 | - | try expectAnalyzeOk("const LIMIT: u8 = 0xFF;"); |
|
| 1796 | + | try expectAnalyzeOk("constant LIMIT: u8 = 0xFF;"); |
|
| 1797 | 1797 | ||
| 1798 | 1798 | try expectIntMismatch("let x: i8 = 128;", super::Type::I8); |
|
| 1799 | 1799 | try expectIntMismatch("let x: i8 = -129;", super::Type::I8); |
|
| 1800 | 1800 | try expectIntMismatch("let x: i8 = 0x80;", super::Type::I8); |
|
| 1801 | 1801 | try expectIntMismatch("let x: i8 = 0b10000000;", super::Type::I8); |
| 1809 | 1809 | try expectIntMismatch("let x: i32 = 2147483648;", super::Type::I32); |
|
| 1810 | 1810 | try expectIntMismatch("let x: i32 = -2147483649;", super::Type::I32); |
|
| 1811 | 1811 | try expectIntMismatch("let x: i32 = 0xFFFFFFFF;", super::Type::I32); |
|
| 1812 | 1812 | try expectIntMismatch("let x: u32 = -1;", super::Type::U32); |
|
| 1813 | 1813 | try expectIntMismatch("let x: u32 = 0x100000000;", super::Type::U32); |
|
| 1814 | - | try expectIntMismatch("const LIMIT: u8 = 512;", super::Type::U8); |
|
| 1815 | - | try expectIntMismatch("const LIMIT: u8 = -5;", super::Type::U8); |
|
| 1814 | + | try expectIntMismatch("constant LIMIT: u8 = 512;", super::Type::U8); |
|
| 1815 | + | try expectIntMismatch("constant LIMIT: u8 = -5;", super::Type::U8); |
|
| 1816 | 1816 | } |
|
| 1817 | 1817 | ||
| 1818 | 1818 | @test fn testNilCoercions() throws (testing::TestError) { |
|
| 1819 | 1819 | { |
|
| 1820 | 1820 | let mut a = testResolver(); |
| 1936 | 1936 | } |
|
| 1937 | 1937 | ||
| 1938 | 1938 | /// Test that arrays of anonymous records with labeled fields are allowed. |
|
| 1939 | 1939 | @test fn testResolveAnonRecordArray() throws (testing::TestError) { |
|
| 1940 | 1940 | let mut a = testResolver(); |
|
| 1941 | - | let program = "record Pt { x: i32, y: i32 } const ARR: [Pt; 2] = [{ x: 1, y: 2 }, { x: 3, y: 4 }];"; |
|
| 1941 | + | let program = "record Pt { x: i32, y: i32 } constant ARR: [Pt; 2] = [{ x: 1, y: 2 }, { x: 3, y: 4 }];"; |
|
| 1942 | 1942 | let result = try resolveProgramStr(&mut a, program); |
|
| 1943 | 1943 | try expectNoErrors(&result); |
|
| 1944 | 1944 | } |
|
| 1945 | 1945 | ||
| 1946 | 1946 | /// Test that arrays of anonymous records with extra fields cause count mismatch. |
|
| 1947 | 1947 | @test fn testResolveAnonRecordArrayMismatch() throws (testing::TestError) { |
|
| 1948 | 1948 | let mut a = testResolver(); |
|
| 1949 | - | let program = "record Pt { x: i32, y: i32 } const ARR: [Pt; 2] = [{ x: 1, y: 2 }, { x: 3, y: 4, z: 5 }];"; |
|
| 1949 | + | let program = "record Pt { x: i32, y: i32 } constant ARR: [Pt; 2] = [{ x: 1, y: 2 }, { x: 3, y: 4, z: 5 }];"; |
|
| 1950 | 1950 | let result = try resolveProgramStr(&mut a, program); |
|
| 1951 | 1951 | let err = try expectError(&result); |
|
| 1952 | 1952 | let case super::ErrorKind::RecordFieldCountMismatch(_) = err.kind |
|
| 1953 | 1953 | else throw testing::TestError::Failed; |
|
| 1954 | 1954 | } |
| 3090 | 3090 | let mut a = testResolver(); |
|
| 3091 | 3091 | let mut arena = ast::nodeArena(&mut AST_ARENA[..]); |
|
| 3092 | 3092 | ||
| 3093 | 3093 | // Register root with constants module. |
|
| 3094 | 3094 | let rootId = try registerModule(&mut MODULE_GRAPH, nil, "root", "export mod consts; mod app;", &mut arena); |
|
| 3095 | - | let constantsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export const MAX_SIZE: i32 = 100;", &mut arena); |
|
| 3095 | + | let constantsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export constant MAX_SIZE: i32 = 100;", &mut arena); |
|
| 3096 | 3096 | let appId = try registerModule(&mut MODULE_GRAPH, rootId, "app", "use root::consts; fn main() -> i32 { return consts::MAX_SIZE; }", &mut arena); |
|
| 3097 | 3097 | ||
| 3098 | 3098 | // Resolve should succeed: constants can be accessed. |
|
| 3099 | 3099 | let result = try resolveModuleTree(&mut a, rootId); |
|
| 3100 | 3100 | try expectNoErrors(&result); |
| 3630 | 3630 | ||
| 3631 | 3631 | let rootId = try registerModule(&mut MODULE_GRAPH, nil, "root", "mod a; export mod b;", &mut arena); |
|
| 3632 | 3632 | let aId = try registerModule(&mut MODULE_GRAPH, rootId, "a", "use root::b; fn main() -> i32 { return b::helper() + b::MAX; }", &mut arena); |
|
| 3633 | 3633 | let bId = try registerModule(&mut MODULE_GRAPH, rootId, "b", "mod c; export use c::*;", &mut arena); |
|
| 3634 | 3634 | let cId = try registerModule(&mut MODULE_GRAPH, bId, "c", "mod d; export use d::*; export fn helper() -> i32 { return 42; }", &mut arena); |
|
| 3635 | - | let dId = try registerModule(&mut MODULE_GRAPH, cId, "d", "export const MAX: i32 = 100;", &mut arena); |
|
| 3635 | + | let dId = try registerModule(&mut MODULE_GRAPH, cId, "d", "export constant MAX: i32 = 100;", &mut arena); |
|
| 3636 | 3636 | ||
| 3637 | 3637 | let result = try resolveModuleTree(&mut a, rootId); |
|
| 3638 | 3638 | try expectNoErrors(&result); |
|
| 3639 | 3639 | } |
|
| 3640 | 3640 |
| 3665 | 3665 | } |
|
| 3666 | 3666 | ||
| 3667 | 3667 | /// Test that a constant array can use another constant as its length. |
|
| 3668 | 3668 | @test fn testConstArrayWithConstLength() throws (testing::TestError) { |
|
| 3669 | 3669 | let mut a = testResolver(); |
|
| 3670 | - | let program = "const LEN: u32 = 3; const ARR: [i32; LEN] = [1, 2, 3];"; |
|
| 3670 | + | let program = "constant LEN: u32 = 3; constant ARR: [i32; LEN] = [1, 2, 3];"; |
|
| 3671 | 3671 | let result = try resolveProgramStr(&mut a, program); |
|
| 3672 | 3672 | try expectNoErrors(&result); |
|
| 3673 | 3673 | ||
| 3674 | 3674 | // Verify the array constant has the correct type with length 3. |
|
| 3675 | 3675 | let arrStmt = try getBlockStmt(result.root, 1); |
| 3681 | 3681 | } |
|
| 3682 | 3682 | ||
| 3683 | 3683 | /// Test that a record field can use a constant as its array length. |
|
| 3684 | 3684 | @test fn testRecordFieldWithConstArrayLength() throws (testing::TestError) { |
|
| 3685 | 3685 | let mut a = testResolver(); |
|
| 3686 | - | let program = "const SIZE: u32 = 4; record Buffer { data: [i32; SIZE], }"; |
|
| 3686 | + | let program = "constant SIZE: u32 = 4; record Buffer { data: [i32; SIZE], }"; |
|
| 3687 | 3687 | let result = try resolveProgramStr(&mut a, program); |
|
| 3688 | 3688 | try expectNoErrors(&result); |
|
| 3689 | 3689 | } |
|
| 3690 | 3690 | ||
| 3691 | 3691 | /// Test that a constant can have a record literal value (lazy record body resolution). |
|
| 3692 | 3692 | @test fn testConstWithRecordLiteral() throws (testing::TestError) { |
|
| 3693 | 3693 | let mut a = testResolver(); |
|
| 3694 | - | let program = "record Point { x: i32, y: i32 } const ORIGIN: Point = Point { x: 0, y: 0 };"; |
|
| 3694 | + | let program = "record Point { x: i32, y: i32 } constant ORIGIN: Point = Point { x: 0, y: 0 };"; |
|
| 3695 | 3695 | let result = try resolveProgramStr(&mut a, program); |
|
| 3696 | 3696 | try expectNoErrors(&result); |
|
| 3697 | 3697 | } |
|
| 3698 | 3698 | ||
| 3699 | 3699 | /// Test that a constant can have a union variant value (lazy union body resolution). |
|
| 3700 | 3700 | @test fn testConstWithUnionVariant() throws (testing::TestError) { |
|
| 3701 | 3701 | let mut a = testResolver(); |
|
| 3702 | - | let program = "union Color { Red, Green, Blue } const DEFAULT: Color = Color::Red;"; |
|
| 3702 | + | let program = "union Color { Red, Green, Blue } constant DEFAULT: Color = Color::Red;"; |
|
| 3703 | 3703 | let result = try resolveProgramStr(&mut a, program); |
|
| 3704 | 3704 | try expectNoErrors(&result); |
|
| 3705 | 3705 | } |
|
| 3706 | 3706 | ||
| 3707 | 3707 | /// Test that record field types can reference imported types. |
| 3727 | 3727 | @test fn testImportedConstantInArraySize() throws (testing::TestError) { |
|
| 3728 | 3728 | let mut a = testResolver(); |
|
| 3729 | 3729 | let mut arena = ast::nodeArena(&mut AST_ARENA[..]); |
|
| 3730 | 3730 | ||
| 3731 | 3731 | let rootId = try registerModule(&mut MODULE_GRAPH, nil, "root", "export mod consts; mod app;", &mut arena); |
|
| 3732 | - | let constsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export const SIZE: u32 = 8;", &mut arena); |
|
| 3732 | + | let constsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export constant SIZE: u32 = 8;", &mut arena); |
|
| 3733 | 3733 | let appId = try registerModule(&mut MODULE_GRAPH, rootId, "app", "use root::consts; static BUFFER: [u8; consts::SIZE] = undefined;", &mut arena); |
|
| 3734 | 3734 | ||
| 3735 | 3735 | let result = try resolveModuleTree(&mut a, rootId); |
|
| 3736 | 3736 | try expectNoErrors(&result); |
|
| 3737 | 3737 | } |
| 4931 | 4931 | try testing::expect(intVal.magnitude == expected); |
|
| 4932 | 4932 | } |
|
| 4933 | 4933 | ||
| 4934 | 4934 | /// Test arithmetic constant folding: add, sub, mul, div. |
|
| 4935 | 4935 | @test fn testConstExprArithmetic() throws (testing::TestError) { |
|
| 4936 | - | try expectConstFold("const A: i32 = 10; const B: i32 = 20; const C: i32 = A + B;", 2, 30); |
|
| 4937 | - | try expectConstFold("const A: i32 = 50; const B: i32 = 20; const C: i32 = A - B;", 2, 30); |
|
| 4938 | - | try expectConstFold("const A: i32 = 6; const B: i32 = 7; const C: i32 = A * B;", 2, 42); |
|
| 4939 | - | try expectConstFold("const A: i32 = 100; const B: i32 = 5; const C: i32 = A / B;", 2, 20); |
|
| 4936 | + | try expectConstFold("constant A: i32 = 10; constant B: i32 = 20; constant C: i32 = A + B;", 2, 30); |
|
| 4937 | + | try expectConstFold("constant A: i32 = 50; constant B: i32 = 20; constant C: i32 = A - B;", 2, 30); |
|
| 4938 | + | try expectConstFold("constant A: i32 = 6; constant B: i32 = 7; constant C: i32 = A * B;", 2, 42); |
|
| 4939 | + | try expectConstFold("constant A: i32 = 100; constant B: i32 = 5; constant C: i32 = A / B;", 2, 20); |
|
| 4940 | 4940 | } |
|
| 4941 | 4941 | ||
| 4942 | 4942 | /// Test bitwise constant folding: and, or, xor. |
|
| 4943 | 4943 | @test fn testConstExprBitwise() throws (testing::TestError) { |
|
| 4944 | - | try expectConstFold("const A: i32 = 0xFF; const B: i32 = 0x0F; const C: i32 = A & B;", 2, 0x0F); |
|
| 4945 | - | try expectConstFold("const A: i32 = 0xF0; const B: i32 = 0x0F; const C: i32 = A | B;", 2, 0xFF); |
|
| 4946 | - | try expectConstFold("const A: i32 = 0xFF; const B: i32 = 0x0F; const C: i32 = A ^ B;", 2, 0xF0); |
|
| 4944 | + | try expectConstFold("constant A: i32 = 0xFF; constant B: i32 = 0x0F; constant C: i32 = A & B;", 2, 0x0F); |
|
| 4945 | + | try expectConstFold("constant A: i32 = 0xF0; constant B: i32 = 0x0F; constant C: i32 = A | B;", 2, 0xFF); |
|
| 4946 | + | try expectConstFold("constant A: i32 = 0xFF; constant B: i32 = 0x0F; constant C: i32 = A ^ B;", 2, 0xF0); |
|
| 4947 | 4947 | } |
|
| 4948 | 4948 | ||
| 4949 | 4949 | /// Test shift constant folding. |
|
| 4950 | 4950 | @test fn testConstExprShift() throws (testing::TestError) { |
|
| 4951 | - | try expectConstFold("const A: i32 = 1; const B: i32 = A << 4;", 1, 16); |
|
| 4952 | - | try expectConstFold("const A: i32 = 32; const B: i32 = A >> 2;", 1, 8); |
|
| 4951 | + | try expectConstFold("constant A: i32 = 1; constant B: i32 = A << 4;", 1, 16); |
|
| 4952 | + | try expectConstFold("constant A: i32 = 32; constant B: i32 = A >> 2;", 1, 8); |
|
| 4953 | 4953 | } |
|
| 4954 | 4954 | ||
| 4955 | 4955 | /// Test chained constant expressions (C depends on A + B, D depends on C). |
|
| 4956 | 4956 | @test fn testConstExprChained() throws (testing::TestError) { |
|
| 4957 | - | try expectConstFold("const A: i32 = 10; const B: i32 = 20; const C: i32 = A + B; const D: i32 = C * 2;", 3, 60); |
|
| 4957 | + | try expectConstFold("constant A: i32 = 10; constant B: i32 = 20; constant C: i32 = A + B; constant D: i32 = C * 2;", 3, 60); |
|
| 4958 | 4958 | } |
|
| 4959 | 4959 | ||
| 4960 | 4960 | /// Test constant expression used as array size. |
|
| 4961 | 4961 | @test fn testConstExprAsArraySize() throws (testing::TestError) { |
|
| 4962 | 4962 | let mut a = testResolver(); |
|
| 4963 | - | let program = "const A: u32 = 2; const B: u32 = 3; const SIZE: u32 = A + B; const ARR: [i32; SIZE] = [1, 2, 3, 4, 5];"; |
|
| 4963 | + | let program = "constant A: u32 = 2; constant B: u32 = 3; constant SIZE: u32 = A + B; constant ARR: [i32; SIZE] = [1, 2, 3, 4, 5];"; |
|
| 4964 | 4964 | let result = try resolveProgramStr(&mut a, program); |
|
| 4965 | 4965 | try expectNoErrors(&result); |
|
| 4966 | 4966 | ||
| 4967 | 4967 | let arrStmt = try getBlockStmt(result.root, 3); |
|
| 4968 | 4968 | let sym = super::symbolFor(&a, arrStmt) |
| 4977 | 4977 | @test fn testCrossModuleConstExpr() throws (testing::TestError) { |
|
| 4978 | 4978 | let mut a = testResolver(); |
|
| 4979 | 4979 | let mut arena = ast::nodeArena(&mut AST_ARENA[..]); |
|
| 4980 | 4980 | ||
| 4981 | 4981 | let rootId = try registerModule(&mut MODULE_GRAPH, nil, "root", "export mod consts; mod app;", &mut arena); |
|
| 4982 | - | let constsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export const BASE: i32 = 100;", &mut arena); |
|
| 4983 | - | let appId = try registerModule(&mut MODULE_GRAPH, rootId, "app", "use root::consts; const DERIVED: i32 = consts::BASE + 50;", &mut arena); |
|
| 4982 | + | let constsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export constant BASE: i32 = 100;", &mut arena); |
|
| 4983 | + | let appId = try registerModule(&mut MODULE_GRAPH, rootId, "app", "use root::consts; constant DERIVED: i32 = consts::BASE + 50;", &mut arena); |
|
| 4984 | 4984 | ||
| 4985 | 4985 | let result = try resolveModuleTree(&mut a, rootId); |
|
| 4986 | 4986 | try expectNoErrors(&result); |
|
| 4987 | 4987 | } |
|
| 4988 | 4988 |
| 4990 | 4990 | @test fn testCrossModuleConstExprArraySize() throws (testing::TestError) { |
|
| 4991 | 4991 | let mut a = testResolver(); |
|
| 4992 | 4992 | let mut arena = ast::nodeArena(&mut AST_ARENA[..]); |
|
| 4993 | 4993 | ||
| 4994 | 4994 | let rootId = try registerModule(&mut MODULE_GRAPH, nil, "root", "export mod consts; mod app;", &mut arena); |
|
| 4995 | - | let constsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export const WIDTH: u32 = 8; export const HEIGHT: u32 = 4;", &mut arena); |
|
| 4996 | - | let appId = try registerModule(&mut MODULE_GRAPH, rootId, "app", "use root::consts; const TOTAL: u32 = consts::WIDTH * consts::HEIGHT; static BUF: [u8; TOTAL] = undefined;", &mut arena); |
|
| 4995 | + | let constsId = try registerModule(&mut MODULE_GRAPH, rootId, "consts", "export constant WIDTH: u32 = 8; export constant HEIGHT: u32 = 4;", &mut arena); |
|
| 4996 | + | let appId = try registerModule(&mut MODULE_GRAPH, rootId, "app", "use root::consts; constant TOTAL: u32 = consts::WIDTH * consts::HEIGHT; static BUF: [u8; TOTAL] = undefined;", &mut arena); |
|
| 4997 | 4997 | ||
| 4998 | 4998 | let result = try resolveModuleTree(&mut a, rootId); |
|
| 4999 | 4999 | try expectNoErrors(&result); |
|
| 5000 | 5000 | } |
|
| 5001 | 5001 | ||
| 5002 | - | /// Test that non-constant expressions in const declarations are still rejected. |
|
| 5002 | + | /// Test that non-constant expressions in constant declarations are still rejected. |
|
| 5003 | 5003 | @test fn testConstExprNonConstRejected() throws (testing::TestError) { |
|
| 5004 | 5004 | let mut a = testResolver(); |
|
| 5005 | - | let program = "fn value() -> i32 { return 1; } const BAD: i32 = value() + 1;"; |
|
| 5005 | + | let program = "fn value() -> i32 { return 1; } constant BAD: i32 = value() + 1;"; |
|
| 5006 | 5006 | let result = try resolveProgramStr(&mut a, program); |
|
| 5007 | 5007 | let err = try expectError(&result); |
|
| 5008 | 5008 | let case super::ErrorKind::ConstExprRequired = err.kind |
|
| 5009 | 5009 | else throw testing::TestError::Failed; |
|
| 5010 | 5010 | } |
|
| 5011 | 5011 | ||
| 5012 | 5012 | /// Test unary negation in constant expressions. |
|
| 5013 | 5013 | @test fn testConstExprUnaryNeg() throws (testing::TestError) { |
|
| 5014 | 5014 | let mut a = testResolver(); |
|
| 5015 | - | let program = "const A: i32 = 10; const B: i32 = -A;"; |
|
| 5015 | + | let program = "constant A: i32 = 10; constant B: i32 = -A;"; |
|
| 5016 | 5016 | let result = try resolveProgramStr(&mut a, program); |
|
| 5017 | 5017 | try expectNoErrors(&result); |
|
| 5018 | 5018 | } |
|
| 5019 | 5019 | ||
| 5020 | 5020 | /// Test unary not in constant expressions. |
|
| 5021 | 5021 | @test fn testConstExprUnaryNot() throws (testing::TestError) { |
|
| 5022 | 5022 | let mut a = testResolver(); |
|
| 5023 | - | let program = "const A: bool = true; const B: bool = not A;"; |
|
| 5023 | + | let program = "constant A: bool = true; constant B: bool = not A;"; |
|
| 5024 | 5024 | let result = try resolveProgramStr(&mut a, program); |
|
| 5025 | 5025 | try expectNoErrors(&result); |
|
| 5026 | 5026 | } |
|
| 5027 | 5027 | ||
| 5028 | 5028 | /// Test `as` casts in constant expressions: widening, narrowing, sign changes, chaining. |
|
| 5029 | 5029 | @test fn testConstExprCast() throws (testing::TestError) { |
|
| 5030 | - | try expectConstFold("const A: i32 = 42; const B: u64 = A as u64;", 1, 42); |
|
| 5031 | - | try expectConstFold("const A: u64 = 10; const B: u8 = A as u8;", 1, 10); |
|
| 5032 | - | try expectConstFold("const A: i32 = 7; const B: u32 = A as u32;", 1, 7); |
|
| 5033 | - | try expectConstFold("const A: u32 = 100; const B: i32 = A as i32;", 1, 100); |
|
| 5034 | - | try expectConstFold("const A: u8 = 5; const B: u64 = (A as u32) as u64;", 1, 5); |
|
| 5035 | - | try expectConstFold("const A: u8 = 3; const B: u8 = 4; const C: i32 = (A as i32) + (B as i32);", 2, 7); |
|
| 5030 | + | try expectConstFold("constant A: i32 = 42; constant B: u64 = A as u64;", 1, 42); |
|
| 5031 | + | try expectConstFold("constant A: u64 = 10; constant B: u8 = A as u8;", 1, 10); |
|
| 5032 | + | try expectConstFold("constant A: i32 = 7; constant B: u32 = A as u32;", 1, 7); |
|
| 5033 | + | try expectConstFold("constant A: u32 = 100; constant B: i32 = A as i32;", 1, 100); |
|
| 5034 | + | try expectConstFold("constant A: u8 = 5; constant B: u64 = (A as u32) as u64;", 1, 5); |
|
| 5035 | + | try expectConstFold("constant A: u8 = 3; constant B: u8 = 4; constant C: i32 = (A as i32) + (B as i32);", 2, 7); |
|
| 5036 | 5036 | // Cast of unsuffixed literal arithmetic. |
|
| 5037 | - | try expectConstFold("const A: u32 = (3 + 4) as u32;", 0, 7); |
|
| 5038 | - | try expectConstFold("const A: u32 = ((3 + 4) as u64) as u32;", 0, 7); |
|
| 5039 | - | try expectConstFold("const A: u32 = (3 + 4) as u32 + 1;", 0, 8); |
|
| 5040 | - | try expectConstFold("const A: i32 = (2 as i32) * (3 + 4);", 0, 14); |
|
| 5037 | + | try expectConstFold("constant A: u32 = (3 + 4) as u32;", 0, 7); |
|
| 5038 | + | try expectConstFold("constant A: u32 = ((3 + 4) as u64) as u32;", 0, 7); |
|
| 5039 | + | try expectConstFold("constant A: u32 = (3 + 4) as u32 + 1;", 0, 8); |
|
| 5040 | + | try expectConstFold("constant A: i32 = (2 as i32) * (3 + 4);", 0, 14); |
|
| 5041 | 5041 | } |
|
| 5042 | 5042 | ||
| 5043 | 5043 | /// Test `as` cast in constant expressions used as array size. |
|
| 5044 | 5044 | @test fn testConstExprCastAsArraySize() throws (testing::TestError) { |
|
| 5045 | 5045 | let mut a = testResolver(); |
|
| 5046 | - | let program = "const LEN: u64 = 4; const SIZE: u32 = LEN as u32; const ARR: [i32; SIZE] = [1, 2, 3, 4];"; |
|
| 5046 | + | let program = "constant LEN: u64 = 4; constant SIZE: u32 = LEN as u32; constant ARR: [i32; SIZE] = [1, 2, 3, 4];"; |
|
| 5047 | 5047 | let result = try resolveProgramStr(&mut a, program); |
|
| 5048 | 5048 | try expectNoErrors(&result); |
|
| 5049 | 5049 | ||
| 5050 | 5050 | let arrStmt = try getBlockStmt(result.root, 2); |
|
| 5051 | 5051 | let sym = super::symbolFor(&a, arrStmt) |
| 5055 | 5055 | try testing::expect(arrType.length == 4); |
|
| 5056 | 5056 | } |
|
| 5057 | 5057 | ||
| 5058 | 5058 | /// Test unsuffixed integer literals in constant expressions. |
|
| 5059 | 5059 | @test fn testConstExprUnsuffixedLiterals() throws (testing::TestError) { |
|
| 5060 | - | try expectConstFold("const A: u32 = 4 * 4;", 0, 16); |
|
| 5061 | - | try expectConstFold("const B: u32 = 10; const C: u32 = B * 2;", 1, 20); |
|
| 5062 | - | try expectConstFold("const D: u32 = 3 + 7;", 0, 10); |
|
| 5063 | - | try expectConstFold("const E: u32 = 2 * 3 + 4;", 0, 10); |
|
| 5064 | - | try expectConstFold("const F: i32 = -(3 + 4);", 0, 7); |
|
| 5060 | + | try expectConstFold("constant A: u32 = 4 * 4;", 0, 16); |
|
| 5061 | + | try expectConstFold("constant B: u32 = 10; constant C: u32 = B * 2;", 1, 20); |
|
| 5062 | + | try expectConstFold("constant D: u32 = 3 + 7;", 0, 10); |
|
| 5063 | + | try expectConstFold("constant E: u32 = 2 * 3 + 4;", 0, 10); |
|
| 5064 | + | try expectConstFold("constant F: i32 = -(3 + 4);", 0, 7); |
|
| 5065 | 5065 | } |
lib/std/lang/scanner.rad
+3 -4
| 89 | 89 | Continue, While, For, In, |
|
| 90 | 90 | Loop, Match, Case, Try, Catch, |
|
| 91 | 91 | Throw, Throws, Panic, Assert, |
|
| 92 | 92 | ||
| 93 | 93 | // Variable binding tokens. |
|
| 94 | - | Let, Mut, Const, Align, |
|
| 94 | + | Let, Mut, Constant, Align, |
|
| 95 | 95 | ||
| 96 | 96 | // Module-related tokens. |
|
| 97 | 97 | Mod, Use, Super, |
|
| 98 | 98 | ||
| 99 | 99 | // Type or function attributes. |
| 114 | 114 | /// Corresponding token. |
|
| 115 | 115 | tok: TokenKind, |
|
| 116 | 116 | } |
|
| 117 | 117 | ||
| 118 | 118 | /// Sorted keyword table for binary search. |
|
| 119 | - | const KEYWORDS: [Keyword; 51] = [ |
|
| 119 | + | constant KEYWORDS: [Keyword; 50] = [ |
|
| 120 | 120 | { name: "align", tok: TokenKind::Align }, |
|
| 121 | 121 | { name: "and", tok: TokenKind::And }, |
|
| 122 | 122 | { name: "as", tok: TokenKind::As }, |
|
| 123 | 123 | { name: "assert", tok: TokenKind::Assert }, |
|
| 124 | 124 | { name: "bool", tok: TokenKind::Bool }, |
|
| 125 | 125 | { name: "break", tok: TokenKind::Break }, |
|
| 126 | 126 | { name: "case", tok: TokenKind::Case }, |
|
| 127 | 127 | { name: "catch", tok: TokenKind::Catch }, |
|
| 128 | - | { name: "const", tok: TokenKind::Const }, |
|
| 129 | - | { name: "constant", tok: TokenKind::Const }, |
|
| 128 | + | { name: "constant", tok: TokenKind::Constant }, |
|
| 130 | 129 | { name: "continue", tok: TokenKind::Continue }, |
|
| 131 | 130 | { name: "else", tok: TokenKind::Else }, |
|
| 132 | 131 | { name: "export", tok: TokenKind::Export }, |
|
| 133 | 132 | { name: "false", tok: TokenKind::False }, |
|
| 134 | 133 | { name: "fn", tok: TokenKind::Fn }, |
lib/std/lang/strings.rad
+1 -1
| 8 | 8 | ||
| 9 | 9 | use std::mem; |
|
| 10 | 10 | use std::collections::dict; |
|
| 11 | 11 | ||
| 12 | 12 | /// Table size. |
|
| 13 | - | const TABLE_SIZE: u32 = 8192; |
|
| 13 | + | constant TABLE_SIZE: u32 = 8192; |
|
| 14 | 14 | ||
| 15 | 15 | /// String interning pool using open-addressed hash table. |
|
| 16 | 16 | /// |
|
| 17 | 17 | /// Each unique string content is stored only once, allowing pointer equality |
|
| 18 | 18 | /// to be used instead of content comparison for symbol lookups and module names. |
lib/std/sys/unix.rad
+9 -9
| 3 | 3 | ||
| 4 | 4 | /// File access modes. |
|
| 5 | 5 | export record OpenFlags(i64); |
|
| 6 | 6 | ||
| 7 | 7 | /// Open file for reading only. |
|
| 8 | - | export const O_RDONLY: OpenFlags = OpenFlags(0); |
|
| 8 | + | export constant O_RDONLY: OpenFlags = OpenFlags(0); |
|
| 9 | 9 | ||
| 10 | 10 | /// Open file for writing only. |
|
| 11 | - | export const O_WRONLY: OpenFlags = OpenFlags(1); |
|
| 11 | + | export constant O_WRONLY: OpenFlags = OpenFlags(1); |
|
| 12 | 12 | ||
| 13 | 13 | /// Open file for reading and writing. |
|
| 14 | - | export const O_RDWR: OpenFlags = OpenFlags(2); |
|
| 14 | + | export constant O_RDWR: OpenFlags = OpenFlags(2); |
|
| 15 | 15 | ||
| 16 | 16 | /// Create file if it doesn't exist. |
|
| 17 | - | export const O_CREAT: OpenFlags = OpenFlags(64); |
|
| 17 | + | export constant O_CREAT: OpenFlags = OpenFlags(64); |
|
| 18 | 18 | ||
| 19 | 19 | /// Truncate file to zero length. |
|
| 20 | - | export const O_TRUNC: OpenFlags = OpenFlags(512); |
|
| 20 | + | export constant O_TRUNC: OpenFlags = OpenFlags(512); |
|
| 21 | 21 | ||
| 22 | 22 | /// Standard file descriptor for stdin. |
|
| 23 | - | export const STDIN: i64 = 0; |
|
| 23 | + | export constant STDIN: i64 = 0; |
|
| 24 | 24 | ||
| 25 | 25 | /// Standard file descriptor for stdout. |
|
| 26 | - | export const STDOUT: i64 = 1; |
|
| 26 | + | export constant STDOUT: i64 = 1; |
|
| 27 | 27 | ||
| 28 | 28 | /// Standard file descriptor for stderr. |
|
| 29 | - | export const STDERR: i64 = 2; |
|
| 29 | + | export constant STDERR: i64 = 2; |
|
| 30 | 30 | ||
| 31 | 31 | /// Special value representing current working directory for `openat()`. |
|
| 32 | - | const AT_FDCWD: i64 = -100; |
|
| 32 | + | constant AT_FDCWD: i64 = -100; |
|
| 33 | 33 | ||
| 34 | 34 | /// Opens a file at the given path and returns a file descriptor. |
|
| 35 | 35 | /// Returns a negative value on error. |
|
| 36 | 36 | export fn open(path: *[u8], flags: OpenFlags) -> i64 { |
|
| 37 | 37 | return intrinsics::ecall(56, AT_FDCWD, path.ptr as i64, *flags, 0); |
test/runner.rad
+7 -7
| 16 | 16 | use std::lang::resolver; |
|
| 17 | 17 | use std::lang::strings; |
|
| 18 | 18 | use std::lang::lower; |
|
| 19 | 19 | ||
| 20 | 20 | /// Buffer size for reading source files (8 KB). |
|
| 21 | - | const SOURCE_BUF_SIZE: u32 = 8192; |
|
| 21 | + | constant SOURCE_BUF_SIZE: u32 = 8192; |
|
| 22 | 22 | /// Buffer size for reading expected IL files (32 KB). |
|
| 23 | - | const EXPECTED_BUF_SIZE: u32 = 32768; |
|
| 23 | + | constant EXPECTED_BUF_SIZE: u32 = 32768; |
|
| 24 | 24 | /// Buffer size for generated IL output (32 KB). |
|
| 25 | - | const OUTPUT_BUF_SIZE: u32 = 32768; |
|
| 25 | + | constant OUTPUT_BUF_SIZE: u32 = 32768; |
|
| 26 | 26 | /// Arena size for AST/IL allocations (512 KB). |
|
| 27 | - | const ARENA_SIZE: u32 = 524288; |
|
| 27 | + | constant ARENA_SIZE: u32 = 524288; |
|
| 28 | 28 | /// Maximum path length for expected IL file path. |
|
| 29 | - | const MAX_PATH_LEN: u32 = 256; |
|
| 29 | + | constant MAX_PATH_LEN: u32 = 256; |
|
| 30 | 30 | ||
| 31 | 31 | /// String pool. |
|
| 32 | 32 | static STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 }; |
|
| 33 | 33 | ||
| 34 | 34 | /// Maximum number of AST nodes per test file. |
|
| 35 | - | const MAX_NODE_DATA: u32 = 4096; |
|
| 35 | + | constant MAX_NODE_DATA: u32 = 4096; |
|
| 36 | 36 | /// Maximum number of resolver errors per test file. |
|
| 37 | - | const MAX_ERRORS: u32 = 16; |
|
| 37 | + | constant MAX_ERRORS: u32 = 16; |
|
| 38 | 38 | ||
| 39 | 39 | // Static storage for large buffers to avoid stack overflow. |
|
| 40 | 40 | // Tests run serially so sharing these is safe. |
|
| 41 | 41 | static SOURCE_BUF: [u8; SOURCE_BUF_SIZE] = undefined; |
|
| 42 | 42 | static EXPECTED_BUF: [u8; EXPECTED_BUF_SIZE] = undefined; |
test/tests/const-expr-array-size.rad
+3 -3
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | ||
| 3 | 3 | /// Test that constant expressions referencing other constants |
|
| 4 | 4 | /// can be used as array sizes. |
|
| 5 | 5 | ||
| 6 | - | const ROWS: u32 = 3; |
|
| 7 | - | const COLS: u32 = 4; |
|
| 8 | - | const TOTAL: u32 = ROWS * COLS; |
|
| 6 | + | constant ROWS: u32 = 3; |
|
| 7 | + | constant COLS: u32 = 4; |
|
| 8 | + | constant TOTAL: u32 = ROWS * COLS; |
|
| 9 | 9 | ||
| 10 | 10 | static DATA: [i32; TOTAL] = undefined; |
|
| 11 | 11 | ||
| 12 | 12 | @default fn main() -> i32 { |
|
| 13 | 13 | // Verify the array has the expected length. |
test/tests/const-expr-cast.rad
+17 -17
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | ||
| 3 | 3 | /// Test that `as` casts work in constant expressions. |
|
| 4 | 4 | ||
| 5 | 5 | // Widening, narrowing, sign changes. |
|
| 6 | - | const A: i32 = 42; |
|
| 7 | - | const B: u64 = A as u64; |
|
| 8 | - | const C: u8 = 10; |
|
| 9 | - | const D: i32 = C as i32; |
|
| 10 | - | const SHIFTED: u64 = 4 as u64; |
|
| 6 | + | constant A: i32 = 42; |
|
| 7 | + | constant B: u64 = A as u64; |
|
| 8 | + | constant C: u8 = 10; |
|
| 9 | + | constant D: i32 = C as i32; |
|
| 10 | + | constant SHIFTED: u64 = 4 as u64; |
|
| 11 | 11 | ||
| 12 | 12 | // Chained casts. |
|
| 13 | - | const LEN: u32 = 8; |
|
| 14 | - | const LEN2: u32 = (LEN as u64) as u32; |
|
| 13 | + | constant LEN: u32 = 8; |
|
| 14 | + | constant LEN2: u32 = (LEN as u64) as u32; |
|
| 15 | 15 | static BUF: [u8; LEN2] = undefined; |
|
| 16 | 16 | ||
| 17 | 17 | // Cast of unsuffixed literal arithmetic. |
|
| 18 | - | const E: u32 = (3 + 4) as u32; |
|
| 18 | + | constant E: u32 = (3 + 4) as u32; |
|
| 19 | 19 | // Nested casts of literal arithmetic. |
|
| 20 | - | const F: u32 = ((3 + 4) as u64) as u32; |
|
| 20 | + | constant F: u32 = ((3 + 4) as u64) as u32; |
|
| 21 | 21 | // Cast + arithmetic. |
|
| 22 | - | const G: u32 = (3 + 4) as u32 + 1; |
|
| 22 | + | constant G: u32 = (3 + 4) as u32 + 1; |
|
| 23 | 23 | // Arithmetic with cast subexprs. |
|
| 24 | - | const H: i32 = (2 as i32) * (3 + 4); |
|
| 24 | + | constant H: i32 = (2 as i32) * (3 + 4); |
|
| 25 | 25 | ||
| 26 | 26 | // Cast in static data initializer. |
|
| 27 | - | const INIT_VAL: u8 = 0xFF; |
|
| 28 | - | const WIDE: u32 = INIT_VAL as u32; |
|
| 27 | + | constant INIT_VAL: u8 = 0xFF; |
|
| 28 | + | constant WIDE: u32 = INIT_VAL as u32; |
|
| 29 | 29 | ||
| 30 | - | // Typed const * typed const through cast. |
|
| 31 | - | const X: u8 = 3; |
|
| 32 | - | const Y: u8 = 4; |
|
| 33 | - | const Z: i32 = (X as i32) * (Y as i32); |
|
| 30 | + | // Typed constant * typed constant through cast. |
|
| 31 | + | constant X: u8 = 3; |
|
| 32 | + | constant Y: u8 = 4; |
|
| 33 | + | constant Z: i32 = (X as i32) * (Y as i32); |
|
| 34 | 34 | ||
| 35 | 35 | @default fn main() -> i32 { |
|
| 36 | 36 | assert BUF.len == 8; |
|
| 37 | 37 | assert WIDE == 255; |
|
| 38 | 38 | assert Z == 12; |
test/tests/const-expr-literal.rad
+8 -8
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | ||
| 3 | - | /// Test that unsuffixed integer literals work in const expressions. |
|
| 3 | + | /// Test that unsuffixed integer literals work in constant expressions. |
|
| 4 | 4 | ||
| 5 | 5 | // Literal * literal. |
|
| 6 | - | const A: u32 = 4 * 4; |
|
| 6 | + | constant A: u32 = 4 * 4; |
|
| 7 | 7 | // Const * literal. |
|
| 8 | - | const B: u32 = 10; |
|
| 9 | - | const C: u32 = B * 2; |
|
| 8 | + | constant B: u32 = 10; |
|
| 9 | + | constant C: u32 = B * 2; |
|
| 10 | 10 | // Literal + literal. |
|
| 11 | - | const D: u32 = 3 + 7; |
|
| 11 | + | constant D: u32 = 3 + 7; |
|
| 12 | 12 | // Chained with literals. |
|
| 13 | - | const E: u32 = 2 * 3 + 4; |
|
| 13 | + | constant E: u32 = 2 * 3 + 4; |
|
| 14 | 14 | // Unary negation with literal. |
|
| 15 | - | const F: i32 = -5; |
|
| 16 | - | const G: i32 = F * 2; |
|
| 15 | + | constant F: i32 = -5; |
|
| 16 | + | constant G: i32 = F * 2; |
|
| 17 | 17 | ||
| 18 | 18 | static BUF: [u8; A] = undefined; |
|
| 19 | 19 | static BUF2: [u8; C] = undefined; |
|
| 20 | 20 | ||
| 21 | 21 | @default fn main() -> i32 { |
test/tests/const-expr-refs.rad
+12 -12
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | ||
| 3 | 3 | /// Test that constant expressions can reference other constants, |
|
| 4 | 4 | /// including arithmetic on constants. |
|
| 5 | 5 | ||
| 6 | - | const A: i32 = 10; |
|
| 7 | - | const B: i32 = 20; |
|
| 8 | - | const C: i32 = A + B; |
|
| 9 | - | const D: i32 = C * 2; |
|
| 10 | - | const E: i32 = D - A; |
|
| 11 | - | const F: i32 = E / 5; |
|
| 12 | - | const G: i32 = A % 3; |
|
| 13 | - | const H: i32 = A | B; |
|
| 14 | - | const I: i32 = A & B; |
|
| 15 | - | const J: i32 = A ^ B; |
|
| 16 | - | const K: i32 = A << 2; |
|
| 17 | - | const L: i32 = B >> 1; |
|
| 6 | + | constant A: i32 = 10; |
|
| 7 | + | constant B: i32 = 20; |
|
| 8 | + | constant C: i32 = A + B; |
|
| 9 | + | constant D: i32 = C * 2; |
|
| 10 | + | constant E: i32 = D - A; |
|
| 11 | + | constant F: i32 = E / 5; |
|
| 12 | + | constant G: i32 = A % 3; |
|
| 13 | + | constant H: i32 = A | B; |
|
| 14 | + | constant I: i32 = A & B; |
|
| 15 | + | constant J: i32 = A ^ B; |
|
| 16 | + | constant K: i32 = A << 2; |
|
| 17 | + | constant L: i32 = B >> 1; |
|
| 18 | 18 | ||
| 19 | 19 | @default fn main() -> i32 { |
|
| 20 | 20 | if C != 30 { return 1; } |
|
| 21 | 21 | if D != 60 { return 2; } |
|
| 22 | 22 | if E != 50 { return 3; } |
test/tests/const.array.copy.mutate.rad
+1 -1
| 1 | 1 | //! returns: 22 |
|
| 2 | 2 | //! Test copying and mutating constant arrays. |
|
| 3 | 3 | ||
| 4 | - | const SEED: [i32; 4] = [1, 2, 3, 4]; |
|
| 4 | + | constant SEED: [i32; 4] = [1, 2, 3, 4]; |
|
| 5 | 5 | ||
| 6 | 6 | fn crunch() -> i32 { |
|
| 7 | 7 | let mut working: [i32; 4] = SEED; |
|
| 8 | 8 | ||
| 9 | 9 | working[0] += 5; |
test/tests/const.array.ident.rad
+3 -3
| 1 | 1 | /// Test constant array containing references to other constants. |
|
| 2 | - | /// This tests that identifiers referencing constants are treated as const expressions. |
|
| 2 | + | /// This tests that identifiers referencing constants are treated as constant expressions. |
|
| 3 | 3 | ||
| 4 | - | const A: i32 = 42; |
|
| 5 | - | const B: [i32; 1] = [A]; |
|
| 4 | + | constant A: i32 = 42; |
|
| 5 | + | constant B: [i32; 1] = [A]; |
|
| 6 | 6 | ||
| 7 | 7 | fn test() -> i32 { |
|
| 8 | 8 | return B[0]; |
|
| 9 | 9 | } |
test/tests/const.array.rad
+1 -1
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | // Test array constants. |
|
| 3 | 3 | ||
| 4 | - | const NUMBERS: [i32; 4] = [1, 2, 3, 4]; |
|
| 4 | + | constant NUMBERS: [i32; 4] = [1, 2, 3, 4]; |
|
| 5 | 5 | ||
| 6 | 6 | @default fn main() -> i32 { |
|
| 7 | 7 | let mut sum: i32 = 0; |
|
| 8 | 8 | for n in (NUMBERS) { |
|
| 9 | 9 | sum += n; |
test/tests/const.array.record.ident.rad
+4 -4
| 1 | 1 | /// Test constant array containing references to other record constants. |
|
| 2 | - | /// This tests that identifiers referencing record constants work in const arrays. |
|
| 2 | + | /// This tests that identifiers referencing record constants work in constant arrays. |
|
| 3 | 3 | ||
| 4 | 4 | record Point { |
|
| 5 | 5 | x: i32, |
|
| 6 | 6 | y: i32, |
|
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | - | const P1: Point = Point { x: 1, y: 2 }; |
|
| 10 | - | const P2: Point = Point { x: 3, y: 4 }; |
|
| 11 | - | const POINTS: [Point; 2] = [P1, P2]; |
|
| 9 | + | constant P1: Point = Point { x: 1, y: 2 }; |
|
| 10 | + | constant P2: Point = Point { x: 3, y: 4 }; |
|
| 11 | + | constant POINTS: [Point; 2] = [P1, P2]; |
|
| 12 | 12 | ||
| 13 | 13 | fn getSum() -> i32 { |
|
| 14 | 14 | return POINTS[0].x + POINTS[1].y; |
|
| 15 | 15 | } |
test/tests/const.array.repeat.record.rad
+1 -1
| 1 | 1 | /// Test constant array repeat with record elements. |
|
| 2 | 2 | record Point { x: i32, y: i32 } |
|
| 3 | 3 | ||
| 4 | - | const POINTS: [Point; 3] = [Point { x: 1, y: 2 }; 3]; |
|
| 4 | + | constant POINTS: [Point; 3] = [Point { x: 1, y: 2 }; 3]; |
|
| 5 | 5 | ||
| 6 | 6 | fn getSum() -> i32 { |
|
| 7 | 7 | return POINTS[0].x + POINTS[1].y + POINTS[2].x; |
|
| 8 | 8 | } |
test/tests/const.array.strings.slice.rad
+1 -1
| 1 | 1 | /// Const array of string slices lowers to slice headers (sym+len+padding) |
|
| 2 | 2 | /// and reuses deduplicated string storage. |
|
| 3 | - | const WORDS: [*[u8]; 3] = [ |
|
| 3 | + | constant WORDS: [*[u8]; 3] = [ |
|
| 4 | 4 | "apple", |
|
| 5 | 5 | "pencil", |
|
| 6 | 6 | "apple", |
|
| 7 | 7 | ]; |
|
| 8 | 8 |
test/tests/const.basic.rad
+3 -3
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | // Test constant declarations with literals only (no expressions). |
|
| 3 | - | const N: i32 = 3; |
|
| 4 | - | const MAX: i32 = 4; |
|
| 5 | - | const DEBUG: bool = true; |
|
| 3 | + | constant N: i32 = 3; |
|
| 4 | + | constant MAX: i32 = 4; |
|
| 5 | + | constant DEBUG: bool = true; |
|
| 6 | 6 | ||
| 7 | 7 | @default fn main() -> i32 { |
|
| 8 | 8 | let n: i32 = N; |
|
| 9 | 9 | let area: i32 = (n * 10); |
|
| 10 | 10 | let result: i32 = MAX * 2; |
test/tests/const.char.rad
+2 -2
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | ||
| 3 | - | const LETTER: u8 = 'A'; |
|
| 4 | - | const DIGIT: u8 = '0'; |
|
| 3 | + | constant LETTER: u8 = 'A'; |
|
| 4 | + | constant DIGIT: u8 = '0'; |
|
| 5 | 5 | ||
| 6 | 6 | @default fn main() -> u8 { |
|
| 7 | 7 | if (DIGIT == '0') { |
|
| 8 | 8 | return (LETTER) - 65; |
|
| 9 | 9 | } |
test/tests/const.fn.array.rad
+2 -2
| 1 | - | //! Test function pointers stored in const/static arrays. |
|
| 1 | + | //! Test function pointers stored in constant/static arrays. |
|
| 2 | 2 | //! Verifies that function references are properly emitted as |
|
| 3 | 3 | //! data items and can be called through the array. |
|
| 4 | 4 | //! returns: 0 |
|
| 5 | 5 | ||
| 6 | 6 | fn add(a: i32, b: i32) -> i32 { |
| 13 | 13 | ||
| 14 | 14 | fn mul(a: i32, b: i32) -> i32 { |
|
| 15 | 15 | return a * b; |
|
| 16 | 16 | } |
|
| 17 | 17 | ||
| 18 | - | const OPS: [fn(i32, i32) -> i32; 3] = [add, sub, mul]; |
|
| 18 | + | constant OPS: [fn(i32, i32) -> i32; 3] = [add, sub, mul]; |
|
| 19 | 19 | ||
| 20 | 20 | @default fn main() -> i32 { |
|
| 21 | 21 | // add(10, 3) == 13 |
|
| 22 | 22 | let r0 = OPS[0](10, 3); |
|
| 23 | 23 | assert r0 == 13; |
test/tests/const.negative.rad
+3 -3
| 1 | 1 | // Test negative constant values |
|
| 2 | 2 | ||
| 3 | - | const NEG_ONE: i32 = -1; |
|
| 4 | - | const NEG_FORTY_TWO: i32 = -42; |
|
| 5 | - | const NEG_MAX: i32 = -2147483648; |
|
| 3 | + | constant NEG_ONE: i32 = -1; |
|
| 4 | + | constant NEG_FORTY_TWO: i32 = -42; |
|
| 5 | + | constant NEG_MAX: i32 = -2147483648; |
|
| 6 | 6 | ||
| 7 | 7 | fn getNegOne() -> i32 { |
|
| 8 | 8 | return NEG_ONE; |
|
| 9 | 9 | } |
|
| 10 | 10 |
test/tests/const.record.array.rad
+1 -1
| 5 | 5 | x: i32, |
|
| 6 | 6 | y: i32, |
|
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | 9 | // A constant array of structs |
|
| 10 | - | const POINTS: [Point; 3] = [ |
|
| 10 | + | constant POINTS: [Point; 3] = [ |
|
| 11 | 11 | Point { x: 1, y: 2 }, |
|
| 12 | 12 | Point { x: 3, y: 4 }, |
|
| 13 | 13 | Point { x: 5, y: 6 } |
|
| 14 | 14 | ]; |
|
| 15 | 15 |
test/tests/const.record.array.simple.rad
+1 -1
| 5 | 5 | x: i32, |
|
| 6 | 6 | y: i32, |
|
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | 9 | // Define an array of record constants |
|
| 10 | - | const POINTS: [Point; 3] = [ |
|
| 10 | + | constant POINTS: [Point; 3] = [ |
|
| 11 | 11 | Point { x: 1, y: 2 }, |
|
| 12 | 12 | Point { x: 3, y: 4 }, |
|
| 13 | 13 | Point { x: 5, y: 6 } |
|
| 14 | 14 | ]; |
|
| 15 | 15 |
test/tests/const.record.ctor.rad
+1 -1
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Constant unlabeled record constructor. |
|
| 3 | 3 | record Pair(i32, i32); |
|
| 4 | 4 | ||
| 5 | - | const P: Pair = Pair(40, 2); |
|
| 5 | + | constant P: Pair = Pair(40, 2); |
|
| 6 | 6 | ||
| 7 | 7 | @default fn main() -> i32 { |
|
| 8 | 8 | assert P == Pair(40, 2); |
|
| 9 | 9 | return 0; |
|
| 10 | 10 | } |
test/tests/const.record.fn.rad
+1 -1
| 4 | 4 | record Point { |
|
| 5 | 5 | x: i32, |
|
| 6 | 6 | y: i32, |
|
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | - | const ORIGIN: Point = Point { x: 3, y: 4 }; |
|
| 9 | + | constant ORIGIN: Point = Point { x: 3, y: 4 }; |
|
| 10 | 10 | ||
| 11 | 11 | fn getX(p: Point) -> i32 { |
|
| 12 | 12 | return p.x; |
|
| 13 | 13 | } |
|
| 14 | 14 |
test/tests/const.record.mutcopy.rad
+2 -2
| 1 | 1 | /// Test that accessing an aggregate constant produces a mutable copy |
|
| 2 | 2 | /// (via Reserve + Blit) so that code can safely assign through the pointer. |
|
| 3 | 3 | ||
| 4 | 4 | record Reg { n: u8 } |
|
| 5 | 5 | ||
| 6 | - | const SCRATCH1: Reg = { n: 30 }; |
|
| 7 | - | const SCRATCH2: Reg = { n: 31 }; |
|
| 6 | + | constant SCRATCH1: Reg = { n: 30 }; |
|
| 7 | + | constant SCRATCH2: Reg = { n: 31 }; |
|
| 8 | 8 | ||
| 9 | 9 | /// Returns a scratch register, avoiding the one already used by `rs`. |
|
| 10 | 10 | fn test(rs: Reg) -> Reg { |
|
| 11 | 11 | let mut scratch = SCRATCH1; |
|
| 12 | 12 | if rs.n == SCRATCH1.n { |
test/tests/const.record.nested.rad
+1 -1
| 8 | 8 | x: u8, |
|
| 9 | 9 | inner: Inner, |
|
| 10 | 10 | y: u8, |
|
| 11 | 11 | } |
|
| 12 | 12 | ||
| 13 | - | const O: Outer = Outer { x: 1, inner: Inner { a: 2, b: 3 }, y: 4 }; |
|
| 13 | + | constant O: Outer = Outer { x: 1, inner: Inner { a: 2, b: 3 }, y: 4 }; |
|
| 14 | 14 | ||
| 15 | 15 | fn getX() -> u8 { |
|
| 16 | 16 | return O.x; |
|
| 17 | 17 | } |
|
| 18 | 18 |
test/tests/const.record.packed.rad
+1 -1
| 3 | 3 | a: u8, |
|
| 4 | 4 | b: u8, |
|
| 5 | 5 | c: u8, |
|
| 6 | 6 | } |
|
| 7 | 7 | ||
| 8 | - | const P: Packed = Packed { a: 1, b: 2, c: 3 }; |
|
| 8 | + | constant P: Packed = Packed { a: 1, b: 2, c: 3 }; |
|
| 9 | 9 | ||
| 10 | 10 | fn getA() -> u8 { |
|
| 11 | 11 | return P.a; |
|
| 12 | 12 | } |
|
| 13 | 13 |
test/tests/const.record.padded.rad
+1 -1
| 3 | 3 | a: u8, |
|
| 4 | 4 | b: i32, |
|
| 5 | 5 | c: u8, |
|
| 6 | 6 | } |
|
| 7 | 7 | ||
| 8 | - | const P: Padded = Padded { a: 1, b: 2, c: 3 }; |
|
| 8 | + | constant P: Padded = Padded { a: 1, b: 2, c: 3 }; |
|
| 9 | 9 | ||
| 10 | 10 | fn getA() -> u8 { |
|
| 11 | 11 | return P.a; |
|
| 12 | 12 | } |
|
| 13 | 13 |
test/tests/const.record.rad
+1 -1
| 4 | 4 | record Point { |
|
| 5 | 5 | x: i32, |
|
| 6 | 6 | y: i32, |
|
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | - | const ORIGIN: Point = Point { x: 3, y: 4 }; |
|
| 9 | + | constant ORIGIN: Point = Point { x: 3, y: 4 }; |
|
| 10 | 10 | ||
| 11 | 11 | @default fn main() -> i32 { |
|
| 12 | 12 | return (ORIGIN.x + ORIGIN.y) - 7; |
|
| 13 | 13 | } |
test/tests/const.record.union.rad
+1 -1
| 9 | 9 | record Keyword { |
|
| 10 | 10 | name: *[u8], |
|
| 11 | 11 | tok: TokenKind, |
|
| 12 | 12 | } |
|
| 13 | 13 | ||
| 14 | - | const KEYWORDS: [Keyword; 3] = [ |
|
| 14 | + | constant KEYWORDS: [Keyword; 3] = [ |
|
| 15 | 15 | Keyword { name: "fn", tok: TokenKind::Fn }, |
|
| 16 | 16 | Keyword { name: "let", tok: TokenKind::Let }, |
|
| 17 | 17 | Keyword { name: "if", tok: TokenKind::If }, |
|
| 18 | 18 | ]; |
|
| 19 | 19 |
test/tests/const.scalar.rad
+1 -1
| 1 | 1 | /// Test scalar constant lowering. |
|
| 2 | - | const VALUE: i32 = 42; |
|
| 2 | + | constant VALUE: i32 = 42; |
|
| 3 | 3 | ||
| 4 | 4 | fn getValue() -> i32 { |
|
| 5 | 5 | return VALUE; |
|
| 6 | 6 | } |
test/tests/const.slice.of.slices.rad
+2 -2
| 1 | - | /// Const nested slices should lower through generic const `&[...]` support. |
|
| 2 | - | const GROUPS: [*[*[u8]]; 2] = [ |
|
| 1 | + | /// Const nested slices should lower through generic constant `&[...]` support. |
|
| 2 | + | constant GROUPS: [*[*[u8]]; 2] = [ |
|
| 3 | 3 | &["ab", "cd"], |
|
| 4 | 4 | &["efg"], |
|
| 5 | 5 | ]; |
|
| 6 | 6 | ||
| 7 | 7 | fn totalLen() -> u32 { |
test/tests/const.slice.param.rad
+1 -1
| 1 | 1 | //! returns: 36 |
|
| 2 | 2 | ||
| 3 | - | const DATA: [i32; 4] = [3, 5, 7, 9]; |
|
| 3 | + | constant DATA: [i32; 4] = [3, 5, 7, 9]; |
|
| 4 | 4 | ||
| 5 | 5 | fn sumPair(slice: *[i32]) -> i32 { |
|
| 6 | 6 | return slice[0] + slice[1]; |
|
| 7 | 7 | } |
|
| 8 | 8 |
test/tests/const.string.rad
+1 -1
| 1 | 1 | /// Test string constant lowering. |
|
| 2 | - | const HELLO: *[u8] = "hello"; |
|
| 2 | + | constant HELLO: *[u8] = "hello"; |
|
| 3 | 3 | ||
| 4 | 4 | fn getLen() -> u32 { |
|
| 5 | 5 | return HELLO.len; |
|
| 6 | 6 | } |
test/tests/const.string.scoped.names.rad
+3 -3
| 1 | 1 | /// Backing string symbols should be declaration-scoped. |
|
| 2 | - | const HELLO1: *[u8] = "hello"; |
|
| 3 | - | const HELLO2: *[u8] = "hello"; |
|
| 4 | - | const MSGS: [*[u8]; 2] = ["hello", "world"]; |
|
| 2 | + | constant HELLO1: *[u8] = "hello"; |
|
| 3 | + | constant HELLO2: *[u8] = "hello"; |
|
| 4 | + | constant MSGS: [*[u8]; 2] = ["hello", "world"]; |
|
| 5 | 5 | ||
| 6 | 6 | fn totalLen() -> u32 { |
|
| 7 | 7 | return HELLO1.len + HELLO2.len + MSGS[0].len + MSGS[1].len; |
|
| 8 | 8 | } |
test/tests/const.union.payload.ctor.rad
+1 -1
| 4 | 4 | Int(i32), |
|
| 5 | 5 | Bool(bool), |
|
| 6 | 6 | None, |
|
| 7 | 7 | } |
|
| 8 | 8 | ||
| 9 | - | const V: Value = Value::Int(42); |
|
| 9 | + | constant V: Value = Value::Int(42); |
|
| 10 | 10 | ||
| 11 | 11 | @default fn main() -> i32 { |
|
| 12 | 12 | match V { |
|
| 13 | 13 | case Value::Int(x) => { |
|
| 14 | 14 | assert x == 42; |
test/tests/const.union.record.literal.rad
+1 -1
| 3 | 3 | union Expr { |
|
| 4 | 4 | Nil, |
|
| 5 | 5 | Pair { first: i32, second: i32 }, |
|
| 6 | 6 | } |
|
| 7 | 7 | ||
| 8 | - | const E: Expr = Expr::Pair { first: 20, second: 22 }; |
|
| 8 | + | constant E: Expr = Expr::Pair { first: 20, second: 22 }; |
|
| 9 | 9 | ||
| 10 | 10 | @default fn main() -> i32 { |
|
| 11 | 11 | match E { |
|
| 12 | 12 | case Expr::Nil => return 1, |
|
| 13 | 13 | case Expr::Pair { first, second } => { |
test/tests/data.array.rad
+7 -7
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for arrays of various types. |
|
| 3 | - | const U8S: [u8; 2] = [10, 20]; |
|
| 4 | - | const U16S: [u16; 2] = [1000, 2000]; |
|
| 5 | - | const U32S: [u32; 2] = [100000, 200000]; |
|
| 6 | - | const I8S: [i8; 2] = [-10, 10]; |
|
| 7 | - | const I16S: [i16; 2] = [-1000, 1000]; |
|
| 8 | - | const I32S: [i32; 2] = [-100000, 100000]; |
|
| 9 | - | const BOOLS: [bool; 2] = [true, false]; |
|
| 3 | + | constant U8S: [u8; 2] = [10, 20]; |
|
| 4 | + | constant U16S: [u16; 2] = [1000, 2000]; |
|
| 5 | + | constant U32S: [u32; 2] = [100000, 200000]; |
|
| 6 | + | constant I8S: [i8; 2] = [-10, 10]; |
|
| 7 | + | constant I16S: [i16; 2] = [-1000, 1000]; |
|
| 8 | + | constant I32S: [i32; 2] = [-100000, 100000]; |
|
| 9 | + | constant BOOLS: [bool; 2] = [true, false]; |
|
| 10 | 10 | ||
| 11 | 11 | @default fn main() -> i32 { |
|
| 12 | 12 | assert U8S[0] == 10; |
|
| 13 | 13 | assert U8S[1] == 20; |
|
| 14 | 14 |
test/tests/data.bool.rad
+2 -2
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for `bool` type. |
|
| 3 | - | const T: bool = true; |
|
| 4 | - | const F: bool = false; |
|
| 3 | + | constant T: bool = true; |
|
| 4 | + | constant F: bool = false; |
|
| 5 | 5 | ||
| 6 | 6 | @default fn main() -> i32 { |
|
| 7 | 7 | assert T == true; |
|
| 8 | 8 | assert F == false; |
|
| 9 | 9 | assert T; |
test/tests/data.i16.rad
+4 -4
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for `i16` type. |
|
| 3 | - | const A: i16 = 0; |
|
| 4 | - | const B: i16 = 32767; |
|
| 5 | - | const C: i16 = -32768; |
|
| 6 | - | const D: i16 = -1; |
|
| 3 | + | constant A: i16 = 0; |
|
| 4 | + | constant B: i16 = 32767; |
|
| 5 | + | constant C: i16 = -32768; |
|
| 6 | + | constant D: i16 = -1; |
|
| 7 | 7 | ||
| 8 | 8 | @default fn main() -> i32 { |
|
| 9 | 9 | assert A == 0; |
|
| 10 | 10 | assert B == 32767; |
|
| 11 | 11 | assert C == -32768; |
test/tests/data.i32.rad
+4 -4
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for `i32` type. |
|
| 3 | - | const A: i32 = 0; |
|
| 4 | - | const B: i32 = 2147483647; |
|
| 5 | - | const C: i32 = -2147483648; |
|
| 6 | - | const D: i32 = -1; |
|
| 3 | + | constant A: i32 = 0; |
|
| 4 | + | constant B: i32 = 2147483647; |
|
| 5 | + | constant C: i32 = -2147483648; |
|
| 6 | + | constant D: i32 = -1; |
|
| 7 | 7 | ||
| 8 | 8 | @default fn main() -> i32 { |
|
| 9 | 9 | assert A == 0; |
|
| 10 | 10 | assert B == 2147483647; |
|
| 11 | 11 | assert C == -2147483648; |
test/tests/data.i8.rad
+4 -4
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for `i8` type. |
|
| 3 | - | const A: i8 = 0; |
|
| 4 | - | const B: i8 = 127; |
|
| 5 | - | const C: i8 = -128; |
|
| 6 | - | const D: i8 = -1; |
|
| 3 | + | constant A: i8 = 0; |
|
| 4 | + | constant B: i8 = 127; |
|
| 5 | + | constant C: i8 = -128; |
|
| 6 | + | constant D: i8 = -1; |
|
| 7 | 7 | ||
| 8 | 8 | @default fn main() -> i32 { |
|
| 9 | 9 | assert A == 0; |
|
| 10 | 10 | assert B == 127; |
|
| 11 | 11 | assert C == -128; |
test/tests/data.record.rad
+3 -3
| 10 | 10 | b: u16, |
|
| 11 | 11 | c: u32, |
|
| 12 | 12 | d: bool, |
|
| 13 | 13 | } |
|
| 14 | 14 | ||
| 15 | - | const ORIGIN: Point = Point { x: 0, y: 0 }; |
|
| 16 | - | const P1: Point = Point { x: 100, y: -50 }; |
|
| 17 | - | const M1: Mixed = Mixed { a: 255, b: 1000, c: 100000, d: true }; |
|
| 15 | + | constant ORIGIN: Point = Point { x: 0, y: 0 }; |
|
| 16 | + | constant P1: Point = Point { x: 100, y: -50 }; |
|
| 17 | + | constant M1: Mixed = Mixed { a: 255, b: 1000, c: 100000, d: true }; |
|
| 18 | 18 | ||
| 19 | 19 | @default fn main() -> i32 { |
|
| 20 | 20 | assert ORIGIN.x == 0; |
|
| 21 | 21 | assert ORIGIN.y == 0; |
|
| 22 | 22 |
test/tests/data.simple.rad
+1 -1
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Simple test for data symbol access. |
|
| 3 | - | const DATA: [u8; 4] = [10, 20, 30, 40]; |
|
| 3 | + | constant DATA: [u8; 4] = [10, 20, 30, 40]; |
|
| 4 | 4 | ||
| 5 | 5 | @default fn main() -> i32 { |
|
| 6 | 6 | if DATA[0] == 10 and |
|
| 7 | 7 | DATA[1] == 20 and |
|
| 8 | 8 | DATA[2] == 30 and |
test/tests/data.u16.rad
+3 -3
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for `u16` type. |
|
| 3 | - | const A: u16 = 0; |
|
| 4 | - | const B: u16 = 32767; |
|
| 5 | - | const C: u16 = 65535; |
|
| 3 | + | constant A: u16 = 0; |
|
| 4 | + | constant B: u16 = 32767; |
|
| 5 | + | constant C: u16 = 65535; |
|
| 6 | 6 | ||
| 7 | 7 | @default fn main() -> i32 { |
|
| 8 | 8 | assert A == 0; |
|
| 9 | 9 | assert B == 32767; |
|
| 10 | 10 | assert C == 65535; |
test/tests/data.u32.rad
+3 -3
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for `u32` type. |
|
| 3 | - | const A: u32 = 0; |
|
| 4 | - | const B: u32 = 2147483647; |
|
| 5 | - | const C: u32 = 4294967295; |
|
| 3 | + | constant A: u32 = 0; |
|
| 4 | + | constant B: u32 = 2147483647; |
|
| 5 | + | constant C: u32 = 4294967295; |
|
| 6 | 6 | ||
| 7 | 7 | @default fn main() -> i32 { |
|
| 8 | 8 | assert A == 0; |
|
| 9 | 9 | assert B == 2147483647; |
|
| 10 | 10 | assert C == 4294967295; |
test/tests/data.u8.rad
+3 -3
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Test read-only data access for `u8` type. |
|
| 3 | - | const A: u8 = 0; |
|
| 4 | - | const B: u8 = 127; |
|
| 5 | - | const C: u8 = 255; |
|
| 3 | + | constant A: u8 = 0; |
|
| 4 | + | constant B: u8 = 127; |
|
| 5 | + | constant C: u8 = 255; |
|
| 6 | 6 | ||
| 7 | 7 | @default fn main() -> i32 { |
|
| 8 | 8 | assert A == 0; |
|
| 9 | 9 | assert B == 127; |
|
| 10 | 10 | assert C == 255; |
test/tests/data.union.rad
+6 -6
| 10 | 10 | None, |
|
| 11 | 11 | Small, |
|
| 12 | 12 | Large, |
|
| 13 | 13 | } |
|
| 14 | 14 | ||
| 15 | - | const C1: Color = Color::Red; |
|
| 16 | - | const C2: Color = Color::Green; |
|
| 17 | - | const C3: Color = Color::Blue; |
|
| 15 | + | constant C1: Color = Color::Red; |
|
| 16 | + | constant C2: Color = Color::Green; |
|
| 17 | + | constant C3: Color = Color::Blue; |
|
| 18 | 18 | ||
| 19 | - | const V1: Value = Value::None; |
|
| 20 | - | const V2: Value = Value::Small; |
|
| 21 | - | const V3: Value = Value::Large; |
|
| 19 | + | constant V1: Value = Value::None; |
|
| 20 | + | constant V2: Value = Value::Small; |
|
| 21 | + | constant V3: Value = Value::Large; |
|
| 22 | 22 | ||
| 23 | 23 | @default fn main() -> i32 { |
|
| 24 | 24 | match C1 { |
|
| 25 | 25 | case Color::Red => {}, |
|
| 26 | 26 | else => { return 1; }, |
test/tests/prog.ackermann.rad
+2 -2
| 5 | 5 | //! verify against known results. Also implements a memoized iterative |
|
| 6 | 6 | //! version and cross-checks the two. |
|
| 7 | 7 | ||
| 8 | 8 | /// Maximum memo table dimensions. |
|
| 9 | 9 | /// We memoize for m <= 3 and n <= MAX_N. |
|
| 10 | - | const MAX_M: u32 = 4; |
|
| 11 | - | const MAX_N: u32 = 128; |
|
| 10 | + | constant MAX_M: u32 = 4; |
|
| 11 | + | constant MAX_N: u32 = 128; |
|
| 12 | 12 | ||
| 13 | 13 | /// Classic recursive Ackermann function. |
|
| 14 | 14 | /// Only call with small arguments to avoid stack overflow. |
|
| 15 | 15 | fn ack(m: u32, n: u32) -> i32 { |
|
| 16 | 16 | if m == 0 { |
test/tests/prog.bignum.rad
+1 -1
| 3 | 3 | //! Implement multi-word unsigned integer arithmetic using arrays of u32 limbs |
|
| 4 | 4 | //! (little-endian). Operations: add, subtract, multiply, compare, shift. |
|
| 5 | 5 | //! Verify using known large-number identities and cross-checks. |
|
| 6 | 6 | ||
| 7 | 7 | /// Number of limbs per big number (128 bits = 4 x 32-bit words). |
|
| 8 | - | const LIMBS: u32 = 4; |
|
| 8 | + | constant LIMBS: u32 = 4; |
|
| 9 | 9 | ||
| 10 | 10 | /// Set a big number to a u32 value. |
|
| 11 | 11 | fn bnFromU32(dst: *mut [u32], val: u32) { |
|
| 12 | 12 | dst[0] = val; |
|
| 13 | 13 | let mut i: u32 = 1; |
test/tests/prog.cordic.rad
+5 -5
| 4 | 4 | //! fixed-point arithmetic (Q16.16 format). This is a classic embedded |
|
| 5 | 5 | //! systems / DSP benchmark that stress-tests shift, multiply, and |
|
| 6 | 6 | //! table-driven computation without floating point. |
|
| 7 | 7 | ||
| 8 | 8 | /// Fixed-point scale factor: 1.0 = 65536 (Q16.16). |
|
| 9 | - | const SCALE: i32 = 65536; |
|
| 9 | + | constant SCALE: i32 = 65536; |
|
| 10 | 10 | ||
| 11 | 11 | /// Number of CORDIC iterations (more = more precision). |
|
| 12 | - | const ITERATIONS: u32 = 16; |
|
| 12 | + | constant ITERATIONS: u32 = 16; |
|
| 13 | 13 | ||
| 14 | 14 | /// CORDIC gain factor in Q16.16. After 16 iterations, the gain is |
|
| 15 | 15 | /// approximately 1/K = 1/1.6468 = 0.60725 * 65536 = 39797. |
|
| 16 | - | const CORDIC_GAIN: i32 = 39797; |
|
| 16 | + | constant CORDIC_GAIN: i32 = 39797; |
|
| 17 | 17 | ||
| 18 | 18 | /// Pi in Q16.16: 3.14159 * 65536 = 205887 |
|
| 19 | - | const PI: i32 = 205887; |
|
| 19 | + | constant PI: i32 = 205887; |
|
| 20 | 20 | ||
| 21 | 21 | /// Pi/2 in Q16.16. |
|
| 22 | - | const HALF_PI: i32 = 102944; |
|
| 22 | + | constant HALF_PI: i32 = 102944; |
|
| 23 | 23 | ||
| 24 | 24 | /// Result record for cos and sin. |
|
| 25 | 25 | record CosSin { |
|
| 26 | 26 | cos: i32, |
|
| 27 | 27 | sin: i32, |
test/tests/prog.dijkstra.rad
+2 -2
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Dijkstra's shortest path algorithm. |
|
| 3 | 3 | //! Find shortest paths in a weighted directed graph using an adjacency matrix |
|
| 4 | 4 | //! and a min-heap priority queue. Reconstruct paths and verify distances. |
|
| 5 | 5 | ||
| 6 | - | const MAX_NODES: u32 = 16; |
|
| 7 | - | const INF: u32 = 0xFFFFFFFF; |
|
| 6 | + | constant MAX_NODES: u32 = 16; |
|
| 7 | + | constant INF: u32 = 0xFFFFFFFF; |
|
| 8 | 8 | ||
| 9 | 9 | record HeapEntry { |
|
| 10 | 10 | dist: u32, |
|
| 11 | 11 | node: u32, |
|
| 12 | 12 | } |
test/tests/prog.hanoi.rad
+2 -2
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Tower of Hanoi. |
|
| 3 | 3 | //! Solve Tower of Hanoi for N disks, recording moves into an array. |
|
| 4 | 4 | //! Verify the move count and specific moves are correct. |
|
| 5 | 5 | ||
| 6 | - | const NUM_DISKS: u32 = 6; |
|
| 6 | + | constant NUM_DISKS: u32 = 6; |
|
| 7 | 7 | /// 2^6 - 1 = 63 moves. |
|
| 8 | - | const MAX_MOVES: u32 = 63; |
|
| 8 | + | constant MAX_MOVES: u32 = 63; |
|
| 9 | 9 | ||
| 10 | 10 | /// A single move: move a disk from one peg to another. |
|
| 11 | 11 | record Move { |
|
| 12 | 12 | disk: u32, |
|
| 13 | 13 | from: u32, |
test/tests/prog.huffman.rad
+4 -4
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Huffman encoding. |
|
| 3 | 3 | //! Build a Huffman tree from character frequencies, generate prefix codes, |
|
| 4 | 4 | //! encode a message, decode it, and verify round-trip correctness. |
|
| 5 | 5 | ||
| 6 | - | const MAX_SYMBOLS: u32 = 32; |
|
| 7 | - | const MAX_NODES: u32 = 63; |
|
| 8 | - | const MAX_BITS: u32 = 512; |
|
| 6 | + | constant MAX_SYMBOLS: u32 = 32; |
|
| 7 | + | constant MAX_NODES: u32 = 63; |
|
| 8 | + | constant MAX_BITS: u32 = 512; |
|
| 9 | 9 | ||
| 10 | 10 | /// A node in the Huffman tree. |
|
| 11 | 11 | union HNodeKind { |
|
| 12 | 12 | /// Leaf node with a symbol index. |
|
| 13 | 13 | Leaf(u32), |
| 20 | 20 | kind: HNodeKind, |
|
| 21 | 21 | left: u32, |
|
| 22 | 22 | right: u32, |
|
| 23 | 23 | } |
|
| 24 | 24 | ||
| 25 | - | const NIL: u32 = 0xFFFFFFFF; |
|
| 25 | + | constant NIL: u32 = 0xFFFFFFFF; |
|
| 26 | 26 | ||
| 27 | 27 | record HuffState { |
|
| 28 | 28 | nodes: *mut [HNode], |
|
| 29 | 29 | nodeCount: u32, |
|
| 30 | 30 | heap: *mut [u32], |
test/tests/prog.lzw.rad
+4 -4
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! LZW compression and decompression. |
|
| 3 | 3 | //! Implement the Lempel-Ziv-Welch algorithm with a fixed-size dictionary. |
|
| 4 | 4 | //! Encode a byte buffer, decode it, and verify perfect round-trip. |
|
| 5 | 5 | ||
| 6 | - | const MAX_DICT: u32 = 512; |
|
| 7 | - | const INIT_DICT: u32 = 258; |
|
| 8 | - | const CLEAR_CODE: u32 = 256; |
|
| 9 | - | const EOI_CODE: u32 = 257; |
|
| 6 | + | constant MAX_DICT: u32 = 512; |
|
| 7 | + | constant INIT_DICT: u32 = 258; |
|
| 8 | + | constant CLEAR_CODE: u32 = 256; |
|
| 9 | + | constant EOI_CODE: u32 = 257; |
|
| 10 | 10 | ||
| 11 | 11 | record DictEntry { |
|
| 12 | 12 | prefix: u32, |
|
| 13 | 13 | suffix: u8, |
|
| 14 | 14 | } |
test/tests/prog.matmul.rad
+1 -1
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Matrix multiplication. |
|
| 3 | 3 | //! Multiply two 4x4 integer matrices and verify the result against |
|
| 4 | 4 | //! a known expected output. Classic benchmark kernel. |
|
| 5 | 5 | ||
| 6 | - | const N: u32 = 4; |
|
| 6 | + | constant N: u32 = 4; |
|
| 7 | 7 | ||
| 8 | 8 | /// A 4x4 integer matrix (row-major). |
|
| 9 | 9 | record Mat4 { |
|
| 10 | 10 | rows: [[i32; 4]; 4], |
|
| 11 | 11 | } |
test/tests/prog.mersenne.rad
+8 -8
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Mersenne Twister PRNG with statistical testing. |
|
| 3 | 3 | ||
| 4 | - | const N: u32 = 624; |
|
| 5 | - | const M: u32 = 397; |
|
| 6 | - | const MATRIX_A: u32 = 0x9908B0DF; |
|
| 7 | - | const UPPER_MASK: u32 = 0x80000000; |
|
| 8 | - | const LOWER_MASK: u32 = 0x7FFFFFFF; |
|
| 4 | + | constant N: u32 = 624; |
|
| 5 | + | constant M: u32 = 397; |
|
| 6 | + | constant MATRIX_A: u32 = 0x9908B0DF; |
|
| 7 | + | constant UPPER_MASK: u32 = 0x80000000; |
|
| 8 | + | constant LOWER_MASK: u32 = 0x7FFFFFFF; |
|
| 9 | 9 | ||
| 10 | 10 | record MtState { |
|
| 11 | 11 | mt: *mut [u32], |
|
| 12 | 12 | mti: u32, |
|
| 13 | 13 | } |
| 146 | 146 | } |
|
| 147 | 147 | ||
| 148 | 148 | fn testChiSquared(s: *mut MtState) -> i32 { |
|
| 149 | 149 | mtInit(s, 12345); |
|
| 150 | 150 | ||
| 151 | - | const NUM_BINS: u32 = 16; |
|
| 152 | - | const NUM_SAMPLES: u32 = 1600; |
|
| 153 | - | const EXPECTED: u32 = 100; |
|
| 151 | + | constant NUM_BINS: u32 = 16; |
|
| 152 | + | constant NUM_SAMPLES: u32 = 1600; |
|
| 153 | + | constant EXPECTED: u32 = 100; |
|
| 154 | 154 | ||
| 155 | 155 | let mut bins: [u32; 16] = [0; 16]; |
|
| 156 | 156 | ||
| 157 | 157 | let mut i: u32 = 0; |
|
| 158 | 158 | while i < NUM_SAMPLES { |
test/tests/prog.nqueens.rad
+1 -1
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! N-Queens solver. |
|
| 3 | 3 | //! Solve the N-Queens problem using backtracking. Count all valid placements |
|
| 4 | 4 | //! for boards of size 1 through 8 and verify against known solution counts. |
|
| 5 | 5 | ||
| 6 | - | const MAX_N: u32 = 8; |
|
| 6 | + | constant MAX_N: u32 = 8; |
|
| 7 | 7 | ||
| 8 | 8 | record Board { |
|
| 9 | 9 | queens: *mut [i32], |
|
| 10 | 10 | solutionCount: u32, |
|
| 11 | 11 | boardSize: u32, |
test/tests/prog.rbtree.rad
+4 -4
| 1 | 1 | //! returns: 0 |
|
| 2 | 2 | //! Red-black tree. |
|
| 3 | 3 | //! Implement a red-black tree (balanced BST) using a stack-allocated node pool. |
|
| 4 | 4 | ||
| 5 | - | const POOL_SIZE: u32 = 128; |
|
| 6 | - | const NIL: u32 = 0; |
|
| 5 | + | constant POOL_SIZE: u32 = 128; |
|
| 6 | + | constant NIL: u32 = 0; |
|
| 7 | 7 | ||
| 8 | - | const RED: u32 = 0; |
|
| 9 | - | const BLACK: u32 = 1; |
|
| 8 | + | constant RED: u32 = 0; |
|
| 9 | + | constant BLACK: u32 = 1; |
|
| 10 | 10 | ||
| 11 | 11 | record RBNode { |
|
| 12 | 12 | key: i32, |
|
| 13 | 13 | color: u32, |
|
| 14 | 14 | left: u32, |
test/tests/prog.regex.rad
+6 -6
| 2 | 2 | //! NFA-based regex matcher. |
|
| 3 | 3 | //! Implement a simple regular expression engine using Thompson's NFA |
|
| 4 | 4 | //! construction. Supports: literal characters, '.', '*', '+', '?', |
|
| 5 | 5 | //! and concatenation. |
|
| 6 | 6 | ||
| 7 | - | const MAX_STATES: u32 = 128; |
|
| 8 | - | const MAX_TRANSITIONS: u32 = 256; |
|
| 9 | - | const NIL: u32 = 0xFFFFFFFF; |
|
| 7 | + | constant MAX_STATES: u32 = 128; |
|
| 8 | + | constant MAX_TRANSITIONS: u32 = 256; |
|
| 9 | + | constant NIL: u32 = 0xFFFFFFFF; |
|
| 10 | 10 | ||
| 11 | - | const TRANS_CHAR: u32 = 0; |
|
| 12 | - | const TRANS_EPSILON: u32 = 1; |
|
| 13 | - | const TRANS_DOT: u32 = 2; |
|
| 11 | + | constant TRANS_CHAR: u32 = 0; |
|
| 12 | + | constant TRANS_EPSILON: u32 = 1; |
|
| 13 | + | constant TRANS_DOT: u32 = 2; |
|
| 14 | 14 | ||
| 15 | 15 | record Trans { |
|
| 16 | 16 | kind: u32, |
|
| 17 | 17 | ch: u8, |
|
| 18 | 18 | to: u32, |
test/tests/prog.sha256.rad
+1 -1
| 9 | 9 | w: [u32; 64], |
|
| 10 | 10 | } |
|
| 11 | 11 | ||
| 12 | 12 | /// SHA-256 initial hash values (first 32 bits of fractional parts of square |
|
| 13 | 13 | /// roots of the first 8 primes). |
|
| 14 | - | const INIT_H: [u32; 8] = [ |
|
| 14 | + | constant INIT_H: [u32; 8] = [ |
|
| 15 | 15 | 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, |
|
| 16 | 16 | 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 |
|
| 17 | 17 | ]; |
|
| 18 | 18 | ||
| 19 | 19 | /// Right-rotate a 32-bit value by `n` bits. |
test/tests/prog.symtab.rad
+4 -4
| 3 | 3 | //! Implement a multi-scope symbol table with hash-based lookup, scope |
|
| 4 | 4 | //! push/pop, and symbol resolution. Exercises: optionals, if-let, |
|
| 5 | 5 | //! while-let, let-else, for-in with indexing, records with pointer |
|
| 6 | 6 | //! fields, and complex interactions between data structures. |
|
| 7 | 7 | ||
| 8 | - | const MAX_SYMBOLS: u32 = 256; |
|
| 9 | - | const MAX_SCOPES: u32 = 16; |
|
| 10 | - | const HASH_SIZE: u32 = 64; |
|
| 11 | - | const NIL: u32 = 0xFFFFFFFF; |
|
| 8 | + | constant MAX_SYMBOLS: u32 = 256; |
|
| 9 | + | constant MAX_SCOPES: u32 = 16; |
|
| 10 | + | constant HASH_SIZE: u32 = 64; |
|
| 11 | + | constant NIL: u32 = 0xFFFFFFFF; |
|
| 12 | 12 | ||
| 13 | 13 | /// A symbol entry in the table. |
|
| 14 | 14 | record Symbol { |
|
| 15 | 15 | /// Name of the symbol (hash for comparison). |
|
| 16 | 16 | nameHash: u32, |
test/tests/prog.vm.rad
+4 -4
| 3 | 3 | //! Implement a bytecode interpreter for a simple stack machine with |
|
| 4 | 4 | //! arithmetic, comparisons, jumps, local variables, and function calls. |
|
| 5 | 5 | //! Exercises: tagged unions, match, throw/try/catch, error handling, |
|
| 6 | 6 | //! records with slice fields, and complex interacting state. |
|
| 7 | 7 | ||
| 8 | - | const MAX_STACK: u32 = 64; |
|
| 9 | - | const MAX_CODE: u32 = 256; |
|
| 10 | - | const MAX_LOCALS: u32 = 16; |
|
| 11 | - | const MAX_FRAMES: u32 = 8; |
|
| 8 | + | constant MAX_STACK: u32 = 64; |
|
| 9 | + | constant MAX_CODE: u32 = 256; |
|
| 10 | + | constant MAX_LOCALS: u32 = 16; |
|
| 11 | + | constant MAX_FRAMES: u32 = 8; |
|
| 12 | 12 | ||
| 13 | 13 | /// Bytecode instructions. |
|
| 14 | 14 | union Op { |
|
| 15 | 15 | /// Push an immediate value. |
|
| 16 | 16 | Push(i32), |
test/tests/slice.runtime.literal.rad
+1 -1
| 1 | - | /// Create a slice literal with a runtime (non-const) element. |
|
| 1 | + | /// Create a slice literal with a runtime (non-constant) element. |
|
| 2 | 2 | fn sliceWithVar(c: u8) -> *[u8] { |
|
| 3 | 3 | return &[c]; |
|
| 4 | 4 | } |
|
| 5 | 5 | ||
| 6 | 6 | /// Create a slice literal with multiple runtime elements. |
test/tests/static.local.decl.rad
+2 -2
| 1 | - | /// Test lowering of function-local static and const declarations. |
|
| 1 | + | /// Test lowering of function-local static and constant declarations. |
|
| 2 | 2 | fn localStaticAndConst() -> i32 { |
|
| 3 | 3 | static LOCAL: i32 = 7; |
|
| 4 | - | const ADD: i32 = 5; |
|
| 4 | + | constant ADD: i32 = 5; |
|
| 5 | 5 | ||
| 6 | 6 | LOCAL += ADD; |
|
| 7 | 7 | return LOCAL; |
|
| 8 | 8 | } |
test/tests/unsigned.compare.rad
+1 -1
| 1 | 1 | //! returns: 1 |
|
| 2 | 2 | //! Test unsigned integer comparisons. |
|
| 3 | 3 | ||
| 4 | - | const MAX_U32: u32 = 0xFFFFFFFF; |
|
| 4 | + | constant MAX_U32: u32 = 0xFFFFFFFF; |
|
| 5 | 5 | ||
| 6 | 6 | /// Test expression-level unsigned comparisons. |
|
| 7 | 7 | fn testExpressionComparisons() -> bool { |
|
| 8 | 8 | let zero: u32 = 0; |
|
| 9 | 9 | let one: u32 = 1; |