Metadata-Version: 2.4
Name: tress-lang
Version: 0.1.2
Summary: A modern, statically typed scripting language with bytecode compilation and virtual machine execution
Home-page: https://github.com/Bennnto/tress
Author: Ben Promkaew
License: MIT
Project-URL: Bug Reports, https://github.com/Bennnto/tress/issues
Project-URL: Source, https://github.com/Bennnto/tress
Keywords: compiler interpreter scripting language type-system
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development :: Compilers
Classifier: Topic :: Software Development :: Interpreters
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ply>=3.11
Requires-Dist: termcolor>=1.1.0
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# Tress

[![Release](https://github.com/Bennnto/tress/actions/workflows/release.yml/badge.svg)](https://github.com/Bennnto/tress/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**Tress** 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.

## Table of Contents

- [Key Features](#-key-features)
- [Quick Look](#-quick-look)
- [Data Types](#-data-types)
- [Syntax & Features Guide](#️-syntax--features-guide)
  - [1. Variables and Constants](#1-variables-and-constants)
  - [2. Control Flow](#2-control-flow)
  - [3. Functions & Lambdas](#3-functions--lambdas)
  - [4. Classes & Inheritance](#4-classes--inheritance)
  - [5. Exception Handling](#5-exception-handling)
  - [6. Pattern Matching](#6-pattern-matching)
  - [7. Generics](#7-generics)
  - [8. String Interpolation](#8-string-interpolation)
  - [9. Async / Await](#9-async--await)
  - [10. Advanced Decorators & Design by Contract](#10-advanced-decorators--design-by-contract)
  - [11. Advanced Verification (Ghost, Converge, Lazy, Pipe)](#11-advanced-verification-ghost-converge-lazy-pipe)
  - [12. Call Stack & Variable Introspection (tress)](#12-call-stack--variable-introspection-tress)
- [Standard Library Modules](#-standard-library-modules)
  - [std_math.trs](#std_mathtrs)
  - [std_array.trs](#std_arraytrs)
  - [std_string.trs](#std_stringtrs)
  - [std_filesys.trs](#std_filesystrs)
  - [std_json.trs](#std_jsontrs)
  - [std_request.trs](#std_requesttrs)
  - [std_argparse.trs](#std_argparsetrs)
- [CLI & Usage](#-cli--usage)
  - [Running Locally](#running-locally)
  - [Compiler Options](#compiler-options)
- [Project Structure](#️-project-structure)
- [CI/CD and Building Releases](#-cicd-and-building-releases)
  - [1. Compile Locally](#1-compile-locally)
  - [2. GitHub Release Action](#2-github-release-action)

---

## Key Features

* **Static Type System**: Declares variable types explicitly or infers them automatically.
* **First-Class Functions & Lambdas**: Full support for closures, anonymous functions, and lambdas with explicit return types.
* **Object-Oriented Programming**: Clean class declarations, constructors, method definitions, and inheritance using `extend`, `this`, and `parent`.
* **Built-in Testing & Benchmarking**: Native `test` and `bench` blocks to assert and profile execution speed.
* **Design by Contract (DbC)**: Pre- and post-condition assertions using `@pre` and `@post`.
* **Formal Verification Loops**: The `converge` loop enforces proven loop termination at runtime.
* **Asynchronous execution**: Direct support for `async` and `await` promises.
* **Standard Library Modules**: Bundled utilities for math and array operations.
* **Robust Error Handling**: Java-style `try-expect-final` blocks for safe runtime execution.
* **Modular Imports**: Import external `.trs` source files using `source "path.trs" as alias`.
* **Multi-Platform Native Binaries**: Built-in support for compiling into standalone binaries for macOS, Linux, and Windows using PyInstaller.

---

## Quick Look

<p align="center">
  <img src="docs/images/tress_variables.png" alt="Tress Variables & Types" width="480" />
  <img src="docs/images/tress_functions.png" alt="Tress Functions & Lambdas" width="480" />
</p>
<p align="center">
  <img src="docs/images/tress_classes.png" alt="Tress Classes & Inheritance" width="480" />
</p>

---

## Syntax & Features Guide
> [!IMPORTANT]
> `Semicolon` `;` is `optional` at the end of all statements.

### 0. Data Types
* **Integer**: Represents both signed and unsigned numbers without decimal places.
* **Floating Point**: Represents numbers with decimal places.
* **Boolean**: Represents condition `true` or `false`.
* **String**: Represents characters and words.
* **Array**: Collection of items of the same type that can shrink and grow.
* **Set**: Collection of items of the same type with fixed ordering and uniqueness.
* **Map**: Collection of key-value pairs.
* **Box**: Collection of mixed-type items that can shrink and grow (unordered).

---

### 1. Variables and Constants

Variables can be declared statically using `init` (requires explicit type annotations) or dynamically inferred using `let`. 

```Example
// Mutable Variable with type specified
init int: age = 25
init str: name = "Alice"
init bool: isActive = true

// Immutable Variable with type inferred
let score = 98.5          // Infers float
let greeting = "Hello!"   // Infers str
```

> [!NOTE]
> Constant variables can be declared using the `const` prefix.

---

### 2. Control Flow

Tress supports standard `if-else` conditionals, `while` loops, and `for` loops (including foreach iteration).

```Example
// Conditionals
if age >= 18 {
    disp("Access granted")
} else {
    disp("Access denied")
}

// Foreach Loop
let list = [10, 20, 30]
for item in list {
    disp(item);
}

// While Loop
let count = 5
while count > 0 {
    disp(count);
    count = count - 1;
}
```

> [!IMPORTANT]
> Use `cont` instead of `continue` in loops. The `break` keyword behaves normally.

---

### 3. Functions & Lambdas

Define reusable functions with the `fnc` keyword. You can declare argument types, return types, and default values.

```Example
// Standard function
fnc add:int(a:int, b:int) {
    return a + b
}

// Function with default parameter values
fnc greet:str(name:str = "Guest") {
    return "Hello, " + name
}

// Lambdas (Anonymous inline functions)
let multiply = fnc? x:int, y:int -> x * y
let result = multiply(6, 7) // 42
```

---

### 4. Classes & Inheritance

Tress features a clean prototype-based class system. You can define fields, constructors, and extend parent classes.

```Example
class Animal {
    init str: name
    
    // Constructor (uses class name as function name)
    fnc Animal(name: str) {
        this.name = name
    }
    
    fnc speak() {
        disp(this.name + " makes a sound")
    }
}

class Dog extend Animal {
    fnc Dog(name: str) {
        parent.Animal(name) // Call parent constructor
    }
    
    fnc speak() {
        disp(this.name + " barks!")
    }
}

let pet = Dog("Buddy")
pet.speak() // Prints: "Buddy barks!"
```

---

### 5. Exception Handling

Safely capture runtime failures using `try-expect-final` blocks:

```Example
try {
    let result = 10 / 0
} expect error {
    disp("Error caught: " + error)
} final {
    disp("Execution complete")
}
```

---

### 6. Pattern Matching

Use the `match` statement for elegant, conditional branches:

```Example
fnc test_match(x: int) {
    match (x) {
        case 1 -> disp("One")
        case 2 -> disp("Two")
        default -> disp("Other")
    }
}
```

---

### 7. Generics

Declare parameter types generically using the `*T` notation to support multiple types with static compile-time verification:

```Example
fnc identity(*T, x: *T) {
    return x;
}

let int: res_int = identity(42);
let str: res_str = identity("Hello Generic World!");
```

---

### 8. String Interpolation

Embed variables directly inside string literals by prefixing the string with `$` and wrapping variables in curly braces `{}`:

```Example
let str: name = "World"
let int: age = 25
let str: greeting = $"Hello {name}, you are {age} years old!"
disp(greeting)
```

---

### 9. Async / Await

Tress supports asynchronous execution using promises and native delayed delays:

```Example
async fnc calculate:int(x: int) {
    let delay_val = await mock_delay(10, x * 2);
    return delay_val;
}

let p = calculate(5);
disp(await p); // Prints 10 after a 10ms non-blocking delay
```

---

### 10. Advanced Decorators & Design by Contract

Tress supports method wrapping decorators and pre/post-condition validation:

#### Design by Contract (DbC)
Define function contracts using `@pre` (pre-condition) and `@post` (post-condition). Tress asserts these during runtime:
```Example
@pre[b != 0]
@post[result == a / b]
fnc div:int(a:int, b:int) {
    return a / b;
}
```

#### Code Decorators
* `@memoize`: Automatically caches function results for unique arguments to speed up recursive computations (e.g. Fibonacci).
* `@debounce[ms]`: Limits how frequently a function can run, delaying execution until after the specified milliseconds of inactivity.
```Example
@memoize
fnc fib:int(n: int) {
    if n <= 1 { return n; }
    return fib(n - 1) + fib(n - 2);
}

@debounce[50]
fnc log_event(val: int) {
    disp("Logged:", val);
}
```

---

### 11. Advanced Verification (Ghost, Converge, Lazy, Pipe)

#### Ghost Variables
`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:
```Example
ghost let int: maxRetries = 5;
```

#### Converge Loops
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:
```Example
init int: n = 64
converge (n) while (n > 1) {
    n = n / 2; // n strictly decreases, proving termination
}
```

#### Lazy Evaluation
Defer the computation of an expression until its value is first accessed, after which the calculated value is cached:
```Example
lazy let int: result = expensive_computation();
// ... computation not run yet ...
let int: x = result; // Evaluated and cached here!
```

#### Pipeline Operator (`|>`)
Chain function calls from left to right, passing the left-side expression as the first argument to the right-side function:
```Example
let int: result = 2 |> addOne() |> triple() |> square();
// Equivalent to: square(triple(addOne(2)))
```

---

### 12. Call Stack & Variable Introspection (`tress`)

Tress provides a special built-in `tress` object that allows developers to dynamically inspect and modify variables and arguments on the call stack at runtime.

#### Features
* **Writable local slot access**: Read and modify variables by their 0-based local stack slot index using `tress[index]`.
* **Dynamic name lookup**: Read and modify variables by their string identifier name using `tress["varName"]`.
* **Stack frame traversal**: Inspect any calling parent stack frame using `tress.caller[index]` (where `tress.caller` traverses up 1 frame, and chaining `tress.caller.caller...` goes deeper).
* **Metadata queries**: Check a variable's type name using `tress.type(index)` or get its original variable identifier string using `tress.name(index)`.

```Example
fnc my_func:int(a:int) {
    let name_a = tress.name(0);
    disp("First parameter name:", name_a); // Prints: "a"

    fnc child:int(b:int) {
        // Read caller frame parameter 'a'
        let parent_a = tress.caller[0];
        disp("Parent parameter value:", parent_a); // Prints: 42

        // Read variable by string name
        let b_val = tress["b"];

        // Modify local variable 'b' via index
        tress[0] = 99;
        disp("New value of b:", b); // Prints: 99

        // Modify parent variable 'a' via caller name
        tress.caller["a"] = 123;
        return 0;
    }

    child(10);
    disp("New value of a:", a); // Prints: 123
    return 0;
}

my_func(42);
```

---

## Standard Library Modules

Tress includes a growing collection of core modules. They are imported via the `source` keyword.

### `std_math.trs`
Includes algebraic operations, range conversions, trigonometry, and statistical utilities.

| Function | Signature | Detail |
| :--- | :--- | :--- |
| `area` | `area(radius: float) -> float` | Returns the area of a circle. |
| `deg_to_rad` | `deg_to_rad(deg: float) -> float` | Converts degrees to radians. |
| `rad_to_deg` | `rad_to_deg(rad: float) -> float` | Converts radians to degrees. |
| `hypot` | `hypot(a: float, b: float) -> float` | Calculates the hypotenuse $\sqrt{a^2 + b^2}$. |
| `factorial` | `factorial(n: int) -> int` | Computes the factorial of a positive integer. |
| `gcd` | `gcd(a: int, b: int) -> int` | Computes the Greatest Common Divisor. |
| `sin` | `sin(x: float) -> float` | Standard sine trigonometric approximation. |
| `cos` | `cos(x: float) -> float` | Standard cosine trigonometric approximation. |
| `tan` | `tan(x: float) -> float` | Standard tangent trigonometric approximation. |
| `fibonacci` | `fibonacci(n: int) -> int` | Computes the Fibonacci sequence. |
| `exp` | `exp(x: float) -> float` | Exponential function $e^x$. |
| `ln` | `ln(x: float) -> float` | Natural logarithm $\ln(x)$. |
| `log` | `log(x: float, base: float) -> float` | Logarithm with arbitrary base. |
| `sinh` / `cosh` / `tanh` | `sinh(x: float) -> float` | Hyperbolic trig functions. |
| `lcm` | `lcm(a: int, b: int) -> int` | Least Common Multiple. |
| `is_prime` | `is_prime(n: int) -> bool` | Primality check. |
| `mean` | `mean(array) -> float` | Arithmetic mean of an array. |

```Example
source "std_math.trs" as math

let x = math.fibonacci(3) // 2
let y = math.factorial(3) // 6
let z = math.area(4.0) // 50.26544
```

### `std_array.trs`
Generic utility module for manipulating list-like collections.

| Function | Signature | Detail |
| :--- | :--- | :--- |
| `contains` | `contains(array, target) -> bool` | Searches for `target` in the `array`. |
| `find_index` | `find_index(array, target) -> int` | Returns the zero-based index of `target` or `-1` if not found. |
| `sum` | `sum(array) -> float` | Returns the mathematical sum of all numeric array elements. |
| `reverse` | `reverse(array) -> arr` | Returns a reversed copy of the array. |
| `map_arr` | `map_arr(array, fn) -> arr` | Maps a function over each element of the array. |
| `filter` | `filter(array, fn) -> arr` | Filters elements matching the predicate function. |
| `reduce` | `reduce(array, fn, initial) -> int` | Reducer function. |
| `minimum` | `minimum(array) -> int` | Returns the minimum value in the array. |
| `maximum` | `maximum(array) -> int` | Returns the maximum value in the array. |

```Example
source "std_array.trs" as array_util

let numbers = [1, 2, 3, 4, 5]
let found = array_util.contains(numbers, 3) // true
let index = array_util.find_index(numbers, 4) // 3
```

### `std_string.trs`
String processing and manipulation utilities.

| Function | Signature | Detail |
| :--- | :--- | :--- |
| `split` | `split(s: str, delimiter: str) -> arr` | Splits string into array by delimiter. |
| `join` | `join(separator: str, parts: arr) -> str` | Joins array elements into string with separator. |
| `repl` | `repl(s: str, old: str, new: str) -> str` | Replaces all occurrences of `old` with `new`. |
| `contain` | `contain(s: str, sub: str) -> bool` | Checks if string contains substring. |
| `startswith` | `startswith(s: str, prefix: str) -> bool` | Checks if string starts with prefix. |
| `endswith` | `endswith(s: str, suffix: str) -> bool` | Checks if string ends with suffix. |
| `lookup` | `lookup(s: str, sub: str) -> int` | Returns count of substring occurrences. |
| `str_index` | `str_index(s: str, sub: str) -> int` | Returns index of first occurrence, or `-1`. |
| `substr` | `substr(s: str, start: int, end: int) -> str` | Extracts substring from start to end. |
| `to_arr` | `to_arr(s: str) -> arr` | Converts string to array of characters. |
| `concat` | `concat(s1: str, s2: str) -> str` | Concatenates two strings. |
| `len` | `len(s: str) -> int` | Returns length of string. |
| `trim` | `trim(s: str) -> str` | Removes leading/trailing whitespace. |
| `upper` | `upper(s: str) -> str` | Converts to uppercase. |
| `lower` | `lower(s: str) -> str` | Converts to lowercase. |
| `revert` | `revert(s: str) -> str` | Reverses the string. |

```Example
source "std_string.trs" as str

let parts = str.split("a,b,c", ",")   // ["a", "b", "c"]
let upper = str.upper("hello")         // "HELLO"
let has = str.contain("foobar", "bar") // true
```

### `std_filesys.trs`
File system operations for reading, writing, and navigating files and directories.

| Function | Signature | Detail |
| :--- | :--- | :--- |
| `read_file` | `read_file(path: str) -> str` | Reads entire file content as string. |
| `write_file` | `write_file(path: str, content: str) -> void` | Writes content to file (overwrites). |
| `append_file` | `append_file(path: str, content: str) -> void` | Appends content to file. |
| `exists` | `exists(path: str) -> bool` | Checks if path exists. |
| `delete_file` | `delete_file(path: str) -> void` | Deletes a file. |
| `move_file` | `move_file(old: str, new: str) -> void` | Moves/renames a file. |
| `file_size` | `file_size(path: str) -> int` | Returns file size in bytes. |
| `mkdir` | `mkdir(path: str) -> void` | Creates a directory. |
| `rmdir` | `rmdir(path: str) -> void` | Removes a directory. |
| `listdir` | `listdir(path: str) -> arr` | Lists directory contents. |
| `isdir` | `isdir(path: str) -> bool` | Checks if path is a directory. |
| `isfile` | `isfile(path: str) -> bool` | Checks if path is a file. |
| `pwd` | `pwd() -> str` | Returns current working directory. |
| `chdir` | `chdir(path: str) -> void` | Changes working directory. |
| `ext` | `ext(path: str) -> str` | Returns file extension. |
| `filename` | `filename(path: str) -> str` | Returns file name from path. |
| `dirname` | `dirname(path: str) -> str` | Returns directory name from path. |
| `join` | `join(path1: str, path2: str) -> str` | Joins two path segments. |

```Example
source "std_filesys.trs" as fs

fs.write_file("output.txt", "Hello Tress!")
let content = fs.read_file("output.txt")
let files = fs.listdir(".")
disp(fs.exists("output.txt"))  // true
```

### `std_json.trs`
JSON serialization and deserialization.

| Function | Signature | Detail |
| :--- | :--- | :--- |
| `load` | `load(data: str) -> map` | Parses JSON string into a map/array. |
| `dump` | `dump(data) -> str` | Serializes a map/array to JSON string. |

```Example
source "std_json.trs" as json

let obj = json.load("{\"name\": \"Alice\", \"age\": 25}")
let text = json.dump(obj)
disp(text)
```

### `std_request.trs`
HTTP client for making web requests.

| Function | Signature | Detail |
| :--- | :--- | :--- |
| `get` | `get(url: str, params: map, headers: map) -> str` | Sends HTTP GET request. |
| `post` | `post(url: str, body: str, params: map, headers: map) -> str` | Sends HTTP POST request. |
| `put` | `put(url: str, body: str, params: map, headers: map) -> str` | Sends HTTP PUT request. |
| `delete` | `delete(url: str, params: map, headers: map) -> str` | Sends HTTP DELETE request. |

```Example
source "std_request.trs" as http

let response = http.get("https://api.example.com/data", {}, {})
disp(response)
```

### `std_argparse.trs`
Command-line argument parser using an OOP-style `Parser` class.

| Method | Signature | Detail |
| :--- | :--- | :--- |
| `Parser` | `Parser(description: str)` | Creates a new parser instance. |
| `add_option` | `add_option(name: str, short: str, default: str, help: str)` | Adds a named option with default. |
| `add_flag` | `add_flag(name: str, short: str, help: str)` | Adds a boolean flag. |
| `parse` | `parse() -> map` | Parses CLI arguments and returns a map. |

```Example
source "std_argparse.trs" as ap

let parser = ap.Parser("My CLI Tool")
parser.add_option("--name", "-n", "World", "Your name")
parser.add_flag("--verbose", "-v", "Enable verbose output")
let args = parser.parse()
disp(args)
```

---

## CLI & Usage

### Running Locally
To execute a `.trs` source file, invoke the `tress` runner script or run the interpreter via Python directly:

```bash
./tress script.trs
# Or
python3 src/interpret/exec.py script.trs
```

### Compiler Options
```text
Usage: tress <file.trs>
       tress -h/--help     Show help guide
       tress -v/--version  Show compiler version
```

---

## Project Structure

```mermaid
graph TD
    A[Source Code: *.trs] --> B[Lexer: lexical.py]
    B --> C[Parser: typr_parser.py]
    C --> D[Type Checker: type_checker.py]
    D --> E[AST Evaluator: eval_ast.py]
    E --> F[Runtime Output]
```

* **[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.
* **[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.
* **[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.
* **[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.
* **[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.

---

## CI/CD and Building Releases

We automate native, standalone builds for macOS, Linux, and Windows using GitHub Actions and PyInstaller.

### 1. Compile Locally
To build a standalone executable locally, run PyInstaller:
```bash
pip install -r requirements.txt
pyinstaller tress-ast.spec --clean
```
The compiled executable will be placed in `dist/tress-ast` (or `dist/tress-vm`).

### 2. GitHub Release Action
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:
1. Spins up Ubuntu, macOS, and Windows runners.
2. Compiles `tress` into a single binary for each platform.
3. Automatically attaches `tress-linux`, `tress-macos`, and `tress-windows.exe` to a newly drafted GitHub Release.
