|
| 1 | +# ParaCL Specification (Draft) |
| 2 | + |
| 3 | +## 1.0 Introduction |
| 4 | + |
| 5 | +**ParaCL** is a statically typed programming language with extensive type deduction and lightweight syntax. |
| 6 | +It is designed primarily for educational purposes and focuses on explicit data flow, structural composition, and strong typing with predictable semantics. |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## 1.1 Keywords and Program Structure |
| 11 | + |
| 12 | +The following keywords are reserved and cannot be used as identifiers: |
| 13 | + |
| 14 | +``` |
| 15 | +input, output, repeat, glue, bind, if, else, for, in, return, char, int, float, double |
| 16 | +``` |
| 17 | + |
| 18 | +Every program consists of one or more **translation units (TUs)**. |
| 19 | +A TU is a sequence of statements that must be executed in the specified order. |
| 20 | + |
| 21 | +Example: |
| 22 | + |
| 23 | +```pcl |
| 24 | +// square.pcl |
| 25 | +v0 : int = input(0); |
| 26 | +output(0, v0); |
| 27 | +``` |
| 28 | + |
| 29 | +As shown above, comments start with `//` and continue to the end of the line. |
| 30 | + |
| 31 | +--- |
| 32 | + |
| 33 | +## 1.2 Types |
| 34 | + |
| 35 | +Every entity (variable, constant, function, etc.) is introduced upon its first mention. |
| 36 | +An entity always has an associated type, which can be either explicitly specified or automatically deduced by the compiler. |
| 37 | + |
| 38 | +The special entities `input` and `output` are generic I/O primitives. |
| 39 | +Conceptually, `input(0)` behaves like a typed standard input stream, and `output(0, value)` behaves like a typed standard output stream. |
| 40 | + |
| 41 | +Example: |
| 42 | + |
| 43 | +```pcl |
| 44 | +v0 = 0; |
| 45 | +v1 : double = v0; |
| 46 | +v2 = input(0) : int; // not input(v0) |
| 47 | +v3 : int; |
| 48 | +output(0, v1); |
| 49 | +``` |
| 50 | + |
| 51 | +For integer types, you can explicitly specify the bit width: |
| 52 | + |
| 53 | +```pcl |
| 54 | +v0 : int(16) = 0; // 16-bit integer |
| 55 | +``` |
| 56 | + |
| 57 | +By default, `int` is a 32-bit signed integer. |
| 58 | + |
| 59 | +Integers use **two’s complement** representation and arithmetic wraps around on overflow—there is no undefined behavior. |
| 60 | + |
| 61 | +The `char` type is a raw byte type, similar to `std::byte` in C++. |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## 1.3 Arrays |
| 66 | + |
| 67 | +An **array** is a contiguous collection of elements of the same type. |
| 68 | +Arrays are stack-allocated. If the size is compile-time known, the array has a fixed length; otherwise, it behaves like a variable-length array (VLA). |
| 69 | + |
| 70 | +A **vector** is a SIMD container that can only hold primitive element types. |
| 71 | +Vectors always have compile-time known sizes and indices. |
| 72 | + |
| 73 | +The `repeat` expression is syntactic sugar for constructing an array with repeated elements: |
| 74 | + |
| 75 | +```pcl |
| 76 | +arr0 = repeat(v0, 5); // array of 5 identical elements |
| 77 | +arr1 : int[5] = {1, 2, 3, 4}; // fixed-size array |
| 78 | +arr2 : vector<int, 5> = {1, 2, 3, 4, 5}; // SIMD vector |
| 79 | +
|
| 80 | +v3 = 3; |
| 81 | +v4 = arr0[v3]; |
| 82 | +v5 = arr2[3]; // vector indexing requires constant index |
| 83 | +arr_inputs = input(0..3) : int[4]; // array of 4 inputs |
| 84 | +``` |
| 85 | + |
| 86 | +--- |
| 87 | + |
| 88 | +## 1.4 Structures |
| 89 | + |
| 90 | +A **structure** is a compound entity that combines multiple entities of possibly different types. |
| 91 | +Structures can be created using the `glue` expression, which aggregates several entities into one. |
| 92 | + |
| 93 | +Members can be accessed by compile-time-known indices or by explicitly assigned names. |
| 94 | + |
| 95 | +Examples: |
| 96 | + |
| 97 | +```pcl |
| 98 | +s0 = glue(v0, v2); |
| 99 | +v3 = s0[0]; |
| 100 | +
|
| 101 | +s1 = glue(s0 : x, v0 : y, arr0 : z); |
| 102 | +v5 = s1.y; // access by name |
| 103 | +v6 = s1.z[0]; |
| 104 | +
|
| 105 | +s2 : { x : int[5], y : double } = glue(repeat(v0, 5), v1); |
| 106 | +s2.x = repeat(0, 5); |
| 107 | +``` |
| 108 | + |
| 109 | +In the last example, a structure with an array field `x` and a scalar field `y` is created. |
| 110 | + |
| 111 | +--- |
| 112 | + |
| 113 | +## 1.5 Functions |
| 114 | + |
| 115 | +A **function** is an abstraction that encapsulates a sequence of expressions. |
| 116 | +The result of a function is the value of its last expression, unless an explicit `return` is used. |
| 117 | + |
| 118 | +Inside a function, the `input` expression returns the value of the corresponding argument. |
| 119 | +If a function argument’s type is not explicitly declared, the function is **generic**. |
| 120 | + |
| 121 | +Examples: |
| 122 | + |
| 123 | +```pcl |
| 124 | +f0 = { v3 = input(0) + 1; v3 * v3; }; |
| 125 | +v7 = f0(2); // but not f0(2, 3) |
| 126 | +
|
| 127 | +f1 : (x) = { v3 = x + 1; v3 * v3; }; // x is generic |
| 128 | +f2 : (x, y) = { v3 = x + y; v3 * v3; }; // both generic |
| 129 | +
|
| 130 | +f3 : (x : int, y : double) : int = { v3 = x + y; v3 * v3; }; |
| 131 | +v8 = f3(v0, v1); |
| 132 | +``` |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +## 1.6 Methods |
| 137 | + |
| 138 | +Functions can be **bound** to structures, turning them into **methods**. |
| 139 | +The `bind` expression associates a function with a structure, optionally pre-filling some of its parameters with structure fields. |
| 140 | + |
| 141 | +If the number of bound members is smaller than the number of parameters, the remaining ones must be passed explicitly when calling the method. |
| 142 | + |
| 143 | +Examples: |
| 144 | + |
| 145 | +```pcl |
| 146 | +s3 : { x : int, g : () } = glue(v0, bind(f1, s3.x)); // bind requires function name |
| 147 | +v9 = s3.g(); // (v0 + 1) * (v0 + 1) |
| 148 | +
|
| 149 | +s4 : { x : int, g : () } = glue(v0, bind(f2, s4.x)); |
| 150 | +v9 = s4.g(v1); // equivalent to f2(s4.x, v1) |
| 151 | +``` |
| 152 | + |
| 153 | +--- |
| 154 | + |
| 155 | +## 1.7 Conditionals |
| 156 | + |
| 157 | +Conditional statements use familiar syntax. |
| 158 | +Both single-statement and block forms are supported: |
| 159 | + |
| 160 | +```pcl |
| 161 | +if (v2 == 0) |
| 162 | + v0 = f1(v0); |
| 163 | +
|
| 164 | +if (v2 == 0) { |
| 165 | + v0 = f1(v0); |
| 166 | +} |
| 167 | +
|
| 168 | +if (v0 == v2) { |
| 169 | + v0 = f1(v0); |
| 170 | +} |
| 171 | +else { |
| 172 | + v2 = f1(v2); |
| 173 | +} |
| 174 | +``` |
| 175 | + |
| 176 | +--- |
| 177 | + |
| 178 | +## 1.8 Function Returns and Abbreviations |
| 179 | + |
| 180 | +Functions can return early using the `return` statement. |
| 181 | + |
| 182 | +Example: |
| 183 | + |
| 184 | +```pcl |
| 185 | +f4 : (x) = { if (x < 2) return 1; x * f4(x - 1); }; |
| 186 | +``` |
| 187 | + |
| 188 | +If a function body contains only a single expression, braces can be omitted: |
| 189 | + |
| 190 | +```pcl |
| 191 | +f5 : (x) = x * x; |
| 192 | +f6 : (x) = { x * x; }; |
| 193 | +f7 : (x) = { return x * x; }; |
| 194 | +``` |
| 195 | + |
| 196 | +Functions with **generic** parameter types cannot be assigned to each other: |
| 197 | + |
| 198 | +```pcl |
| 199 | +f5 = f4; // invalid — types are generic |
| 200 | +``` |
| 201 | + |
| 202 | +However, functions with **concrete** (fully specified) types can be reassigned: |
| 203 | + |
| 204 | +```pcl |
| 205 | +f8 : (x : int) = x + 1; |
| 206 | +f9 : (x : int) = x * x + 1; |
| 207 | +f8 = f9; // valid |
| 208 | +``` |
| 209 | + |
| 210 | +--- |
| 211 | + |
| 212 | +## 1.9 Loops |
| 213 | + |
| 214 | +Loop syntax is conventional and expressive. |
| 215 | +Iteration over arrays is allowed, but **vectors cannot be iterated**. |
| 216 | + |
| 217 | +Example: |
| 218 | + |
| 219 | +```pcl |
| 220 | +v0 = 5; |
| 221 | +for (x in 0:5) // or (x : int), (0:5:1), etc. |
| 222 | + v0 = v0 + x; |
| 223 | +
|
| 224 | +for (x in arr0) { // array iteration |
| 225 | + v0 = v0 + x; |
| 226 | +} |
| 227 | +``` |
| 228 | + |
| 229 | +Additionally, ParaCL provides a `while` loop that executes while a condition remains true (non-zero). |
| 230 | + |
| 231 | +Example: Fibonacci sequence |
| 232 | + |
| 233 | +```pcl |
| 234 | +n = 0; |
| 235 | +a = 0; |
| 236 | +b = 1; |
| 237 | +x : int = input(0); |
| 238 | +
|
| 239 | +while (n < x) { |
| 240 | + n = n + 1; |
| 241 | +
|
| 242 | + if (n == 1) |
| 243 | + output(0, a); |
| 244 | +
|
| 245 | + if (n == 2) |
| 246 | + output(0, b); |
| 247 | +
|
| 248 | + if (n > 2) { |
| 249 | + tmp = b; |
| 250 | + b = a + b; |
| 251 | + a = tmp; |
| 252 | + output(0, b); |
| 253 | + } |
| 254 | +} |
| 255 | +``` |
| 256 | + |
0 commit comments