Skip to content

Commit 8be675d

Browse files
author
Konstantin Vladimirov
committed
Adding paracl spec
1 parent 80ff33f commit 8be675d

File tree

1 file changed

+256
-0
lines changed

1 file changed

+256
-0
lines changed

paracl/paracl.md

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
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

Comments
 (0)