trac-lang 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- trac_lang-0.3.0/LICENSE +21 -0
- trac_lang-0.3.0/MANIFEST.in +5 -0
- trac_lang-0.3.0/PKG-INFO +649 -0
- trac_lang-0.3.0/README.md +610 -0
- trac_lang-0.3.0/requirements.txt +2 -0
- trac_lang-0.3.0/setup.cfg +4 -0
- trac_lang-0.3.0/setup.py +53 -0
- trac_lang-0.3.0/src/__init__.py +0 -0
- trac_lang-0.3.0/src/compiler/__init__.py +0 -0
- trac_lang-0.3.0/src/compiler/compiler.py +1513 -0
- trac_lang-0.3.0/src/compiler/opcodes.py +89 -0
- trac_lang-0.3.0/src/compiler/run_vm.py +43 -0
- trac_lang-0.3.0/src/compiler/vm.py +1020 -0
- trac_lang-0.3.0/src/compiler/vm_objects.py +151 -0
- trac_lang-0.3.0/src/interpret/__init__.py +0 -0
- trac_lang-0.3.0/src/interpret/environment.py +242 -0
- trac_lang-0.3.0/src/interpret/eval_ast.py +1374 -0
- trac_lang-0.3.0/src/interpret/exec.py +60 -0
- trac_lang-0.3.0/src/interpret/repl.py +76 -0
- trac_lang-0.3.0/src/interpret/type.py +230 -0
- trac_lang-0.3.0/src/interpret/type_checker.py +1054 -0
- trac_lang-0.3.0/src/lexical.py +255 -0
- trac_lang-0.3.0/src/opcodes.py +90 -0
- trac_lang-0.3.0/src/std_module/__init__.py +0 -0
- trac_lang-0.3.0/src/std_module/std_argparse.trc +19 -0
- trac_lang-0.3.0/src/std_module/std_array.trc +98 -0
- trac_lang-0.3.0/src/std_module/std_datetime.trc +0 -0
- trac_lang-0.3.0/src/std_module/std_filesys.trc +81 -0
- trac_lang-0.3.0/src/std_module/std_json.trc +9 -0
- trac_lang-0.3.0/src/std_module/std_math.trc +172 -0
- trac_lang-0.3.0/src/std_module/std_request.trc +17 -0
- trac_lang-0.3.0/src/std_module/std_string.trc +68 -0
- trac_lang-0.3.0/src/typr_parser.py +1351 -0
- trac_lang-0.3.0/src/vscode-trac/language-configuration.json +24 -0
- trac_lang-0.3.0/src/vscode-trac/package.json +30 -0
- trac_lang-0.3.0/src/vscode-trac/syntaxes/trac.tmLanguage.json +127 -0
- trac_lang-0.3.0/trac_lang.egg-info/PKG-INFO +649 -0
- trac_lang-0.3.0/trac_lang.egg-info/SOURCES.txt +40 -0
- trac_lang-0.3.0/trac_lang.egg-info/dependency_links.txt +1 -0
- trac_lang-0.3.0/trac_lang.egg-info/entry_points.txt +2 -0
- trac_lang-0.3.0/trac_lang.egg-info/requires.txt +2 -0
- trac_lang-0.3.0/trac_lang.egg-info/top_level.txt +1 -0
trac_lang-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ben Promkaew
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
trac_lang-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trac-lang
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: A modern, statically typed scripting language with bytecode compilation and virtual machine execution
|
|
5
|
+
Home-page: https://github.com/Bennnto/trac
|
|
6
|
+
Author: Ben Promkaew
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Bug Reports, https://github.com/Bennnto/trac/issues
|
|
9
|
+
Project-URL: Source, https://github.com/Bennnto/trac
|
|
10
|
+
Keywords: compiler interpreter scripting language type-system
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Topic :: Software Development :: Compilers
|
|
21
|
+
Classifier: Topic :: Software Development :: Interpreters
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: ply>=3.11
|
|
26
|
+
Requires-Dist: termcolor>=1.1.0
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: classifier
|
|
29
|
+
Dynamic: description
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: home-page
|
|
32
|
+
Dynamic: keywords
|
|
33
|
+
Dynamic: license
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
Dynamic: project-url
|
|
36
|
+
Dynamic: requires-dist
|
|
37
|
+
Dynamic: requires-python
|
|
38
|
+
Dynamic: summary
|
|
39
|
+
|
|
40
|
+
# Trac
|
|
41
|
+
|
|
42
|
+
[](https://github.com/Bennnto/trac/actions)
|
|
43
|
+
[](https://opensource.org/licenses/MIT)
|
|
44
|
+
|
|
45
|
+
**Trac** is a modern, statically typed scripting language featuring robust type inference, Object-Oriented Programming (OOP) capabilities, exception handling, modular imports, and advanced language design safety features. It combines the safety of static typing with the ease of use of a scripting language.
|
|
46
|
+
|
|
47
|
+
## Table of Contents
|
|
48
|
+
|
|
49
|
+
- [Key Features](#-key-features)
|
|
50
|
+
- [Quick Look](#-quick-look)
|
|
51
|
+
- [Data Types](#-data-types)
|
|
52
|
+
- [Syntax & Features Guide](#️-syntax--features-guide)
|
|
53
|
+
- [1. Variables and Constants](#1-variables-and-constants)
|
|
54
|
+
- [2. Control Flow](#2-control-flow)
|
|
55
|
+
- [3. Functions & Lambdas](#3-functions--lambdas)
|
|
56
|
+
- [4. Classes & Inheritance](#4-classes--inheritance)
|
|
57
|
+
- [5. Exception Handling](#5-exception-handling)
|
|
58
|
+
- [6. Pattern Matching](#6-pattern-matching)
|
|
59
|
+
- [7. Generics](#7-generics)
|
|
60
|
+
- [8. String Interpolation](#8-string-interpolation)
|
|
61
|
+
- [9. Async / Await](#9-async--await)
|
|
62
|
+
- [10. Advanced Decorators & Design by Contract](#10-advanced-decorators--design-by-contract)
|
|
63
|
+
- [11. Advanced Verification (Ghost, Converge, Lazy, Pipe)](#11-advanced-verification-ghost-converge-lazy-pipe)
|
|
64
|
+
- [12. Call Stack & Variable Introspection (trac)](#12-call-stack--variable-introspection-trac)
|
|
65
|
+
- [Standard Library Modules](#-standard-library-modules)
|
|
66
|
+
- [std_math.trc](#std_mathstac)
|
|
67
|
+
- [std_array.trc](#std_arraystac)
|
|
68
|
+
- [std_string.trc](#std_stringstac)
|
|
69
|
+
- [std_filesys.trc](#std_filesysstac)
|
|
70
|
+
- [std_json.trc](#std_jsonstac)
|
|
71
|
+
- [std_request.trc](#std_requeststac)
|
|
72
|
+
- [std_argparse.trc](#std_argparsestac)
|
|
73
|
+
- [CLI & Usage](#-cli--usage)
|
|
74
|
+
- [Running Locally](#running-locally)
|
|
75
|
+
- [Compiler Options](#compiler-options)
|
|
76
|
+
- [Project Structure](#️-project-structure)
|
|
77
|
+
- [CI/CD and Building Releases](#-cicd-and-building-releases)
|
|
78
|
+
- [1. Compile Locally](#1-compile-locally)
|
|
79
|
+
- [2. GitHub Release Action](#2-github-release-action)
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Key Features
|
|
84
|
+
|
|
85
|
+
* **Static Type System**: Declares variable types explicitly or infers them automatically.
|
|
86
|
+
* **First-Class Functions & Lambdas**: Full support for closures, anonymous functions, and lambdas with explicit return types.
|
|
87
|
+
* **Object-Oriented Programming**: Clean class declarations, constructors, method definitions, and inheritance using `extend`, `this`, and `parent`.
|
|
88
|
+
* **Built-in Testing & Benchmarking**: Native `test` and `bench` blocks to assert and profile execution speed.
|
|
89
|
+
* **Design by Contract (DbC)**: Pre- and post-condition assertions using `@pre` and `@post`.
|
|
90
|
+
* **Formal Verification Loops**: The `converge` loop enforces proven loop termination at runtime.
|
|
91
|
+
* **Asynchronous execution**: Direct support for `async` and `await` promises.
|
|
92
|
+
* **Standard Library Modules**: Bundled utilities for math and array operations.
|
|
93
|
+
* **Robust Error Handling**: Java-style `try-expect-final` blocks for safe runtime execution.
|
|
94
|
+
* **Modular Imports**: Import external `.trc` source files using `source "path.trc" as alias`.
|
|
95
|
+
* **Multi-Platform Native Binaries**: Built-in support for compiling into standalone binaries for macOS, Linux, and Windows using PyInstaller.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Quick Look
|
|
100
|
+
|
|
101
|
+
<p align="center">
|
|
102
|
+
<img src="docs/images/stac_variables.png" alt="Trac Variables & Types" width="480" />
|
|
103
|
+
<img src="docs/images/stac_functions.png" alt="Trac Functions & Lambdas" width="480" />
|
|
104
|
+
</p>
|
|
105
|
+
<p align="center">
|
|
106
|
+
<img src="docs/images/stac_classes.png" alt="Trac Classes & Inheritance" width="480" />
|
|
107
|
+
</p>
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Syntax & Features Guide
|
|
112
|
+
> [!IMPORTANT]
|
|
113
|
+
> `Semicolon` `;` is `optional` at the end of all statements.
|
|
114
|
+
|
|
115
|
+
### 0. Data Types
|
|
116
|
+
* **Integer**: Represents both signed and unsigned numbers without decimal places.
|
|
117
|
+
* **Floating Point**: Represents numbers with decimal places.
|
|
118
|
+
* **Boolean**: Represents condition `true` or `false`.
|
|
119
|
+
* **String**: Represents characters and words.
|
|
120
|
+
* **Array**: Collection of items of the same type that can shrink and grow.
|
|
121
|
+
* **Set**: Collection of items of the same type with fixed ordering and uniqueness.
|
|
122
|
+
* **Map**: Collection of key-value pairs.
|
|
123
|
+
* **Box**: Collection of mixed-type items that can shrink and grow (unordered).
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### 1. Variables and Constants
|
|
128
|
+
|
|
129
|
+
Variables can be declared statically using `init` (requires explicit type annotations) or dynamically inferred using `let`.
|
|
130
|
+
|
|
131
|
+
```Example
|
|
132
|
+
// Mutable Variable with type specified
|
|
133
|
+
init int: age = 25
|
|
134
|
+
init str: name = "Alice"
|
|
135
|
+
init bool: isActive = true
|
|
136
|
+
|
|
137
|
+
// Immutable Variable with type inferred
|
|
138
|
+
let score = 98.5 // Infers float
|
|
139
|
+
let greeting = "Hello!" // Infers str
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
> [!NOTE]
|
|
143
|
+
> Constant variables can be declared using the `const` prefix.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### 2. Control Flow
|
|
148
|
+
|
|
149
|
+
Trac supports standard `if-else` conditionals, `while` loops, and `for` loops (including foreach iteration).
|
|
150
|
+
|
|
151
|
+
```Example
|
|
152
|
+
// Conditionals
|
|
153
|
+
if age >= 18 {
|
|
154
|
+
disp("Access granted")
|
|
155
|
+
} else {
|
|
156
|
+
disp("Access denied")
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Foreach Loop
|
|
160
|
+
let list = [10, 20, 30]
|
|
161
|
+
for item in list {
|
|
162
|
+
disp(item);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// While Loop
|
|
166
|
+
let count = 5
|
|
167
|
+
while count > 0 {
|
|
168
|
+
disp(count);
|
|
169
|
+
count = count - 1;
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
> [!IMPORTANT]
|
|
174
|
+
> Use `cont` instead of `continue` in loops. The `break` keyword behaves normally.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### 3. Functions & Lambdas
|
|
179
|
+
|
|
180
|
+
Define reusable functions with the `fnc` keyword. You can declare argument types, return types, and default values.
|
|
181
|
+
|
|
182
|
+
```Example
|
|
183
|
+
// Standard function
|
|
184
|
+
fnc add:int(a:int, b:int) {
|
|
185
|
+
return a + b
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Function with default parameter values
|
|
189
|
+
fnc greet:str(name:str = "Guest") {
|
|
190
|
+
return "Hello, " + name
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Lambdas (Anonymous inline functions)
|
|
194
|
+
let multiply = fnc? x:int, y:int -> x * y
|
|
195
|
+
let result = multiply(6, 7) // 42
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### 4. Classes & Inheritance
|
|
201
|
+
|
|
202
|
+
Trac features a clean prototype-based class system. You can define fields, constructors, and extend parent classes.
|
|
203
|
+
|
|
204
|
+
```Example
|
|
205
|
+
class Animal {
|
|
206
|
+
init str: name
|
|
207
|
+
|
|
208
|
+
// Constructor (uses class name as function name)
|
|
209
|
+
fnc Animal(name: str) {
|
|
210
|
+
this.name = name
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
fnc speak() {
|
|
214
|
+
disp(this.name + " makes a sound")
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
class Dog extend Animal {
|
|
219
|
+
fnc Dog(name: str) {
|
|
220
|
+
parent.Animal(name) // Call parent constructor
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
fnc speak() {
|
|
224
|
+
disp(this.name + " barks!")
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
let pet = Dog("Buddy")
|
|
229
|
+
pet.speak() // Prints: "Buddy barks!"
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### 5. Exception Handling
|
|
235
|
+
|
|
236
|
+
Safely capture runtime failures using `try-expect-final` blocks:
|
|
237
|
+
|
|
238
|
+
```Example
|
|
239
|
+
try {
|
|
240
|
+
let result = 10 / 0
|
|
241
|
+
} expect error {
|
|
242
|
+
disp("Error caught: " + error)
|
|
243
|
+
} final {
|
|
244
|
+
disp("Execution complete")
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
### 6. Pattern Matching
|
|
251
|
+
|
|
252
|
+
Use the `match` statement for elegant, conditional branches:
|
|
253
|
+
|
|
254
|
+
```Example
|
|
255
|
+
fnc test_match(x: int) {
|
|
256
|
+
match (x) {
|
|
257
|
+
case 1 -> disp("One")
|
|
258
|
+
case 2 -> disp("Two")
|
|
259
|
+
default -> disp("Other")
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
### 7. Generics
|
|
267
|
+
|
|
268
|
+
Declare parameter types generically using the `*T` notation to support multiple types with static compile-time verification:
|
|
269
|
+
|
|
270
|
+
```Example
|
|
271
|
+
fnc identity(*T, x: *T) {
|
|
272
|
+
return x;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
let int: res_int = identity(42);
|
|
276
|
+
let str: res_str = identity("Hello Generic World!");
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### 8. String Interpolation
|
|
282
|
+
|
|
283
|
+
Embed variables directly inside string literals by prefixing the string with `$` and wrapping variables in curly braces `{}`:
|
|
284
|
+
|
|
285
|
+
```Example
|
|
286
|
+
let str: name = "World"
|
|
287
|
+
let int: age = 25
|
|
288
|
+
let str: greeting = $"Hello {name}, you are {age} years old!"
|
|
289
|
+
disp(greeting)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
### 9. Async / Await
|
|
295
|
+
|
|
296
|
+
Trac supports asynchronous execution using promises and native delayed delays:
|
|
297
|
+
|
|
298
|
+
```Example
|
|
299
|
+
async fnc calculate:int(x: int) {
|
|
300
|
+
let delay_val = await mock_delay(10, x * 2);
|
|
301
|
+
return delay_val;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
let p = calculate(5);
|
|
305
|
+
disp(await p); // Prints 10 after a 10ms non-blocking delay
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### 10. Advanced Decorators & Design by Contract
|
|
311
|
+
|
|
312
|
+
Trac supports method wrapping decorators and pre/post-condition validation:
|
|
313
|
+
|
|
314
|
+
#### Design by Contract (DbC)
|
|
315
|
+
Define function contracts using `@pre` (pre-condition) and `@post` (post-condition). Trac asserts these during runtime:
|
|
316
|
+
```Example
|
|
317
|
+
@pre[b != 0]
|
|
318
|
+
@post[result == a / b]
|
|
319
|
+
fnc div:int(a:int, b:int) {
|
|
320
|
+
return a / b;
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### Code Decorators
|
|
325
|
+
* `@memoize`: Automatically caches function results for unique arguments to speed up recursive computations (e.g. Fibonacci).
|
|
326
|
+
* `@debounce[ms]`: Limits how frequently a function can run, delaying execution until after the specified milliseconds of inactivity.
|
|
327
|
+
```Example
|
|
328
|
+
@memoize
|
|
329
|
+
fnc fib:int(n: int) {
|
|
330
|
+
if n <= 1 { return n; }
|
|
331
|
+
return fib(n - 1) + fib(n - 2);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
@debounce[50]
|
|
335
|
+
fnc log_event(val: int) {
|
|
336
|
+
disp("Logged:", val);
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
### 11. Advanced Verification (Ghost, Converge, Lazy, Pipe)
|
|
343
|
+
|
|
344
|
+
#### Ghost Variables
|
|
345
|
+
`ghost` variables exist only within the static type checker's compile-time phase for verification. They generate zero runtime overhead and do not exist in the executable environment:
|
|
346
|
+
```Example
|
|
347
|
+
ghost let int: maxRetries = 5;
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
#### Converge Loops
|
|
351
|
+
A loop that requires a proven decrease in a specified "variant" value every iteration to guarantee loop termination. If the variant does not decrease, the runtime throws a termination error:
|
|
352
|
+
```Example
|
|
353
|
+
init int: n = 64
|
|
354
|
+
converge (n) while (n > 1) {
|
|
355
|
+
n = n / 2; // n strictly decreases, proving termination
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### Lazy Evaluation
|
|
360
|
+
Defer the computation of an expression until its value is first accessed, after which the calculated value is cached:
|
|
361
|
+
```Example
|
|
362
|
+
lazy let int: result = expensive_computation();
|
|
363
|
+
// ... computation not run yet ...
|
|
364
|
+
let int: x = result; // Evaluated and cached here!
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### Pipeline Operator (`|>`)
|
|
368
|
+
Chain function calls from left to right, passing the left-side expression as the first argument to the right-side function:
|
|
369
|
+
```Example
|
|
370
|
+
let int: result = 2 |> addOne() |> triple() |> square();
|
|
371
|
+
// Equivalent to: square(triple(addOne(2)))
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### 12. Call Stack & Variable Introspection (`trac`)
|
|
377
|
+
|
|
378
|
+
Trac provides a special built-in `trac` object that allows developers to dynamically inspect and modify variables and arguments on the call stack at runtime.
|
|
379
|
+
|
|
380
|
+
#### Features
|
|
381
|
+
* **Writable local slot access**: Read and modify variables by their 0-based local stack slot index using `trac[index]`.
|
|
382
|
+
* **Dynamic name lookup**: Read and modify variables by their string identifier name using `trac["varName"]`.
|
|
383
|
+
* **Stack frame traversal**: Inspect any calling parent stack frame using `trac.caller[index]` (where `trac.caller` traverses up 1 frame, and chaining `trac.caller.caller...` goes deeper).
|
|
384
|
+
* **Metadata queries**: Check a variable's type name using `trac.type(index)` or get its original variable identifier string using `trac.name(index)`.
|
|
385
|
+
|
|
386
|
+
```Example
|
|
387
|
+
fnc my_func:int(a:int) {
|
|
388
|
+
let name_a = trac.name(0);
|
|
389
|
+
disp("First parameter name:", name_a); // Prints: "a"
|
|
390
|
+
|
|
391
|
+
fnc child:int(b:int) {
|
|
392
|
+
// Read caller frame parameter 'a'
|
|
393
|
+
let parent_a = trac.caller[0];
|
|
394
|
+
disp("Parent parameter value:", parent_a); // Prints: 42
|
|
395
|
+
|
|
396
|
+
// Read variable by string name
|
|
397
|
+
let b_val = trac["b"];
|
|
398
|
+
|
|
399
|
+
// Modify local variable 'b' via index
|
|
400
|
+
trac[0] = 99;
|
|
401
|
+
disp("New value of b:", b); // Prints: 99
|
|
402
|
+
|
|
403
|
+
// Modify parent variable 'a' via caller name
|
|
404
|
+
trac.caller["a"] = 123;
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
child(10);
|
|
409
|
+
disp("New value of a:", a); // Prints: 123
|
|
410
|
+
return 0;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
my_func(42);
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Standard Library Modules
|
|
419
|
+
|
|
420
|
+
Trac includes a growing collection of core modules. They are imported via the `source` keyword.
|
|
421
|
+
|
|
422
|
+
### `std_math.trc`
|
|
423
|
+
Includes algebraic operations, range conversions, trigonometry, and statistical utilities.
|
|
424
|
+
|
|
425
|
+
| Function | Signature | Detail |
|
|
426
|
+
| :--- | :--- | :--- |
|
|
427
|
+
| `area` | `area(radius: float) -> float` | Returns the area of a circle. |
|
|
428
|
+
| `deg_to_rad` | `deg_to_rad(deg: float) -> float` | Converts degrees to radians. |
|
|
429
|
+
| `rad_to_deg` | `rad_to_deg(rad: float) -> float` | Converts radians to degrees. |
|
|
430
|
+
| `hypot` | `hypot(a: float, b: float) -> float` | Calculates the hypotenuse $\sqrt{a^2 + b^2}$. |
|
|
431
|
+
| `factorial` | `factorial(n: int) -> int` | Computes the factorial of a positive integer. |
|
|
432
|
+
| `gcd` | `gcd(a: int, b: int) -> int` | Computes the Greatest Common Divisor. |
|
|
433
|
+
| `sin` | `sin(x: float) -> float` | Standard sine trigonometric approximation. |
|
|
434
|
+
| `cos` | `cos(x: float) -> float` | Standard cosine trigonometric approximation. |
|
|
435
|
+
| `tan` | `tan(x: float) -> float` | Standard tangent trigonometric approximation. |
|
|
436
|
+
| `fibonacci` | `fibonacci(n: int) -> int` | Computes the Fibonacci sequence. |
|
|
437
|
+
| `exp` | `exp(x: float) -> float` | Exponential function $e^x$. |
|
|
438
|
+
| `ln` | `ln(x: float) -> float` | Natural logarithm $\ln(x)$. |
|
|
439
|
+
| `log` | `log(x: float, base: float) -> float` | Logarithm with arbitrary base. |
|
|
440
|
+
| `sinh` / `cosh` / `tanh` | `sinh(x: float) -> float` | Hyperbolic trig functions. |
|
|
441
|
+
| `lcm` | `lcm(a: int, b: int) -> int` | Least Common Multiple. |
|
|
442
|
+
| `is_prime` | `is_prime(n: int) -> bool` | Primality check. |
|
|
443
|
+
| `mean` | `mean(array) -> float` | Arithmetic mean of an array. |
|
|
444
|
+
|
|
445
|
+
```Example
|
|
446
|
+
source "std_math.trc" as math
|
|
447
|
+
|
|
448
|
+
let x = math.fibonacci(3) // 2
|
|
449
|
+
let y = math.factorial(3) // 6
|
|
450
|
+
let z = math.area(4.0) // 50.26544
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### `std_array.trc`
|
|
454
|
+
Generic utility module for manipulating list-like collections.
|
|
455
|
+
|
|
456
|
+
| Function | Signature | Detail |
|
|
457
|
+
| :--- | :--- | :--- |
|
|
458
|
+
| `contains` | `contains(array, target) -> bool` | Searches for `target` in the `array`. |
|
|
459
|
+
| `find_index` | `find_index(array, target) -> int` | Returns the zero-based index of `target` or `-1` if not found. |
|
|
460
|
+
| `sum` | `sum(array) -> float` | Returns the mathematical sum of all numeric array elements. |
|
|
461
|
+
| `reverse` | `reverse(array) -> arr` | Returns a reversed copy of the array. |
|
|
462
|
+
| `map_arr` | `map_arr(array, fn) -> arr` | Maps a function over each element of the array. |
|
|
463
|
+
| `filter` | `filter(array, fn) -> arr` | Filters elements matching the predicate function. |
|
|
464
|
+
| `reduce` | `reduce(array, fn, initial) -> int` | Reducer function. |
|
|
465
|
+
| `minimum` | `minimum(array) -> int` | Returns the minimum value in the array. |
|
|
466
|
+
| `maximum` | `maximum(array) -> int` | Returns the maximum value in the array. |
|
|
467
|
+
|
|
468
|
+
```Example
|
|
469
|
+
source "std_array.trc" as array_util
|
|
470
|
+
|
|
471
|
+
let numbers = [1, 2, 3, 4, 5]
|
|
472
|
+
let found = array_util.contains(numbers, 3) // true
|
|
473
|
+
let index = array_util.find_index(numbers, 4) // 3
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### `std_string.trc`
|
|
477
|
+
String processing and manipulation utilities.
|
|
478
|
+
|
|
479
|
+
| Function | Signature | Detail |
|
|
480
|
+
| :--- | :--- | :--- |
|
|
481
|
+
| `split` | `split(s: str, delimiter: str) -> arr` | Splits string into array by delimiter. |
|
|
482
|
+
| `join` | `join(separator: str, parts: arr) -> str` | Joins array elements into string with separator. |
|
|
483
|
+
| `repl` | `repl(s: str, old: str, new: str) -> str` | Replaces all occurrences of `old` with `new`. |
|
|
484
|
+
| `contain` | `contain(s: str, sub: str) -> bool` | Checks if string contains substring. |
|
|
485
|
+
| `startswith` | `startswith(s: str, prefix: str) -> bool` | Checks if string starts with prefix. |
|
|
486
|
+
| `endswith` | `endswith(s: str, suffix: str) -> bool` | Checks if string ends with suffix. |
|
|
487
|
+
| `lookup` | `lookup(s: str, sub: str) -> int` | Returns count of substring occurrences. |
|
|
488
|
+
| `str_index` | `str_index(s: str, sub: str) -> int` | Returns index of first occurrence, or `-1`. |
|
|
489
|
+
| `substr` | `substr(s: str, start: int, end: int) -> str` | Extracts substring from start to end. |
|
|
490
|
+
| `to_arr` | `to_arr(s: str) -> arr` | Converts string to array of characters. |
|
|
491
|
+
| `concat` | `concat(s1: str, s2: str) -> str` | Concatenates two strings. |
|
|
492
|
+
| `len` | `len(s: str) -> int` | Returns length of string. |
|
|
493
|
+
| `trim` | `trim(s: str) -> str` | Removes leading/trailing whitespace. |
|
|
494
|
+
| `upper` | `upper(s: str) -> str` | Converts to uppercase. |
|
|
495
|
+
| `lower` | `lower(s: str) -> str` | Converts to lowercase. |
|
|
496
|
+
| `revert` | `revert(s: str) -> str` | Reverses the string. |
|
|
497
|
+
|
|
498
|
+
```Example
|
|
499
|
+
source "std_string.trc" as str
|
|
500
|
+
|
|
501
|
+
let parts = str.split("a,b,c", ",") // ["a", "b", "c"]
|
|
502
|
+
let upper = str.upper("hello") // "HELLO"
|
|
503
|
+
let has = str.contain("foobar", "bar") // true
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### `std_filesys.trc`
|
|
507
|
+
File system operations for reading, writing, and navigating files and directories.
|
|
508
|
+
|
|
509
|
+
| Function | Signature | Detail |
|
|
510
|
+
| :--- | :--- | :--- |
|
|
511
|
+
| `read_file` | `read_file(path: str) -> str` | Reads entire file content as string. |
|
|
512
|
+
| `write_file` | `write_file(path: str, content: str) -> void` | Writes content to file (overwrites). |
|
|
513
|
+
| `append_file` | `append_file(path: str, content: str) -> void` | Appends content to file. |
|
|
514
|
+
| `exists` | `exists(path: str) -> bool` | Checks if path exists. |
|
|
515
|
+
| `delete_file` | `delete_file(path: str) -> void` | Deletes a file. |
|
|
516
|
+
| `move_file` | `move_file(old: str, new: str) -> void` | Moves/renames a file. |
|
|
517
|
+
| `file_size` | `file_size(path: str) -> int` | Returns file size in bytes. |
|
|
518
|
+
| `mkdir` | `mkdir(path: str) -> void` | Creates a directory. |
|
|
519
|
+
| `rmdir` | `rmdir(path: str) -> void` | Removes a directory. |
|
|
520
|
+
| `listdir` | `listdir(path: str) -> arr` | Lists directory contents. |
|
|
521
|
+
| `isdir` | `isdir(path: str) -> bool` | Checks if path is a directory. |
|
|
522
|
+
| `isfile` | `isfile(path: str) -> bool` | Checks if path is a file. |
|
|
523
|
+
| `pwd` | `pwd() -> str` | Returns current working directory. |
|
|
524
|
+
| `chdir` | `chdir(path: str) -> void` | Changes working directory. |
|
|
525
|
+
| `ext` | `ext(path: str) -> str` | Returns file extension. |
|
|
526
|
+
| `filename` | `filename(path: str) -> str` | Returns file name from path. |
|
|
527
|
+
| `dirname` | `dirname(path: str) -> str` | Returns directory name from path. |
|
|
528
|
+
| `join` | `join(path1: str, path2: str) -> str` | Joins two path segments. |
|
|
529
|
+
|
|
530
|
+
```Example
|
|
531
|
+
source "std_filesys.trc" as fs
|
|
532
|
+
|
|
533
|
+
fs.write_file("output.txt", "Hello Trac!")
|
|
534
|
+
let content = fs.read_file("output.txt")
|
|
535
|
+
let files = fs.listdir(".")
|
|
536
|
+
disp(fs.exists("output.txt")) // true
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### `std_json.trc`
|
|
540
|
+
JSON serialization and deserialization.
|
|
541
|
+
|
|
542
|
+
| Function | Signature | Detail |
|
|
543
|
+
| :--- | :--- | :--- |
|
|
544
|
+
| `load` | `load(data: str) -> map` | Parses JSON string into a map/array. |
|
|
545
|
+
| `dump` | `dump(data) -> str` | Serializes a map/array to JSON string. |
|
|
546
|
+
|
|
547
|
+
```Example
|
|
548
|
+
source "std_json.trc" as json
|
|
549
|
+
|
|
550
|
+
let obj = json.load("{\"name\": \"Alice\", \"age\": 25}")
|
|
551
|
+
let text = json.dump(obj)
|
|
552
|
+
disp(text)
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### `std_request.trc`
|
|
556
|
+
HTTP client for making web requests.
|
|
557
|
+
|
|
558
|
+
| Function | Signature | Detail |
|
|
559
|
+
| :--- | :--- | :--- |
|
|
560
|
+
| `get` | `get(url: str, params: map, headers: map) -> str` | Sends HTTP GET request. |
|
|
561
|
+
| `post` | `post(url: str, body: str, params: map, headers: map) -> str` | Sends HTTP POST request. |
|
|
562
|
+
| `put` | `put(url: str, body: str, params: map, headers: map) -> str` | Sends HTTP PUT request. |
|
|
563
|
+
| `delete` | `delete(url: str, params: map, headers: map) -> str` | Sends HTTP DELETE request. |
|
|
564
|
+
|
|
565
|
+
```Example
|
|
566
|
+
source "std_request.trc" as http
|
|
567
|
+
|
|
568
|
+
let response = http.get("https://api.example.com/data", {}, {})
|
|
569
|
+
disp(response)
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### `std_argparse.trc`
|
|
573
|
+
Command-line argument parser using an OOP-style `Parser` class.
|
|
574
|
+
|
|
575
|
+
| Method | Signature | Detail |
|
|
576
|
+
| :--- | :--- | :--- |
|
|
577
|
+
| `Parser` | `Parser(description: str)` | Creates a new parser instance. |
|
|
578
|
+
| `add_option` | `add_option(name: str, short: str, default: str, help: str)` | Adds a named option with default. |
|
|
579
|
+
| `add_flag` | `add_flag(name: str, short: str, help: str)` | Adds a boolean flag. |
|
|
580
|
+
| `parse` | `parse() -> map` | Parses CLI arguments and returns a map. |
|
|
581
|
+
|
|
582
|
+
```Example
|
|
583
|
+
source "std_argparse.trc" as ap
|
|
584
|
+
|
|
585
|
+
let parser = ap.Parser("My CLI Tool")
|
|
586
|
+
parser.add_option("--name", "-n", "World", "Your name")
|
|
587
|
+
parser.add_flag("--verbose", "-v", "Enable verbose output")
|
|
588
|
+
let args = parser.parse()
|
|
589
|
+
disp(args)
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
## CLI & Usage
|
|
595
|
+
|
|
596
|
+
### Running Locally
|
|
597
|
+
To execute a `.trc` source file, invoke the `trac` runner script or run the interpreter via Python directly:
|
|
598
|
+
|
|
599
|
+
```bash
|
|
600
|
+
./trac script.trc
|
|
601
|
+
# Or
|
|
602
|
+
python3 src/interpret/exec.py script.trc
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Compiler Options
|
|
606
|
+
```text
|
|
607
|
+
Usage: trac <file.trc>
|
|
608
|
+
trac -h/--help Show help guide
|
|
609
|
+
trac -v/--version Show compiler version
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## Project Structure
|
|
615
|
+
|
|
616
|
+
```mermaid
|
|
617
|
+
graph TD
|
|
618
|
+
A[Source Code: *.trc] --> B[Lexer: lexical.py]
|
|
619
|
+
B --> C[Parser: typr_parser.py]
|
|
620
|
+
C --> D[Type Checker: type_checker.py]
|
|
621
|
+
D --> E[AST Evaluator: eval_ast.py]
|
|
622
|
+
E --> F[Runtime Output]
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
* **[lexical.py](file:///Users/ben/40%20Learning/41%20Code/41.01%20Python/interpret/src/lexical_use/src/lexical.py)**: Tokenizes the input stream using PLY.
|
|
626
|
+
* **[typr_parser.py](file:///Users/ben/40%20Learning/41%20Code/41.01%20Python/interpret/src/lexical_use/src/typr_parser.py)**: Generates the Abstract Syntax Tree (AST) using LALR parser tables.
|
|
627
|
+
* **[type_checker.py](file:///Users/ben/40%20Learning/41%20Code/41.01%20Python/interpret/src/lexical_use/src/interpret/type_checker.py)**: Statically analyzes variable and expression types, inferring parameter types where omitted.
|
|
628
|
+
* **[eval_ast.py](file:///Users/ben/40%20Learning/41%20Code/41.01%20Python/interpret/src/lexical_use/src/interpret/eval_ast.py)**: Performs execution by traversing the AST.
|
|
629
|
+
* **[environment.py](file:///Users/ben/40%20Learning/41%20Code/41.01%20Python/interpret/src/lexical_use/src/interpret/environment.py)**: Manages symbol scoping, closures, and class instance states.
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## CI/CD and Building Releases
|
|
634
|
+
|
|
635
|
+
We automate native, standalone builds for macOS, Linux, and Windows using GitHub Actions and PyInstaller.
|
|
636
|
+
|
|
637
|
+
### 1. Compile Locally
|
|
638
|
+
To build a standalone executable locally, run PyInstaller:
|
|
639
|
+
```bash
|
|
640
|
+
pip install -r requirements.txt
|
|
641
|
+
pyinstaller trac-ast.spec --clean
|
|
642
|
+
```
|
|
643
|
+
The compiled executable will be placed in `dist/trac-ast` (or `dist/trac-vm`).
|
|
644
|
+
|
|
645
|
+
### 2. GitHub Release Action
|
|
646
|
+
Our GitHub Actions pipeline is defined in `.github/workflows/release.yml`. On any new git version tag push (e.g. `v0.1.0`), the workflow:
|
|
647
|
+
1. Spins up Ubuntu, macOS, and Windows runners.
|
|
648
|
+
2. Compiles `trac` into a single binary for each platform.
|
|
649
|
+
3. Automatically attaches `trac-linux`, `trac-macos`, and `trac-windows.exe` to a newly drafted GitHub Release.
|