Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ TSPP++ is an innovative programming language that brings together the familiar s
⚡ **SIMD Operations**: Native vectorization with `#simd`
🔧 **Zero-Cost Abstractions**: `#zerocast` for compile-time optimizations
🛡️ **Safety Controls**: `@unsafe` annotations for explicit unsafe operations
🌐 **Foreign Function Interface**: Call external functions and make syscalls directly
📚 **Self-Hosted Std Libs**: Standard libraries written in TSPP itself using syscalls
🎯 **TypeScript Syntax**: Familiar syntax for web developers
🔄 **Go Semantics**: Goroutine-inspired concurrency model

Expand Down Expand Up @@ -150,6 +152,30 @@ Compile-time optimizations with zero runtime overhead:
#const int result = max(10, 20); // Resolved at compile time
```

### Foreign Function Interface (FFI)

Call external functions and make system calls directly from TSPP:

```typescript
// Declare external functions
extern function puts(str: string): int;
extern function malloc(size: int): string;

// Make system calls
extern function tspp_sys_write(fd: int, buf: string, count: int): int;

function println(message: string): void {
tspp_sys_write(1, message, message.length);
tspp_sys_write(1, "\n", 1);
}

// Standard libraries can be written in TSPP itself!
function openFile(path: string): int {
extern function tspp_sys_open(pathname: string, flags: int, mode: int): int;
return tspp_sys_open(path, 577, 0644); // O_WRONLY | O_CREAT
}
```

## Architecture

TSPP++ follows a modern compiler architecture:
Expand Down Expand Up @@ -179,6 +205,7 @@ flowchart TD
- 📖 **[Language Specification](docs/language_spec.md)** - Complete language reference
- 🔧 **[Compilation Pipeline](docs/pipeline.md)** - How TSPP++ works internally
- 📝 **[Grammar Reference](docs/grammar.md)** - EBNF grammar specification
- 🌐 **[FFI & Syscalls](docs/FFI_SYSCALLS.md)** - Foreign function interface and syscall support
- 🎯 **[Examples](examples/)** - Sample programs and tutorials

## Contributing
Expand Down
210 changes: 108 additions & 102 deletions compile_commands.json

Large diffs are not rendered by default.

149 changes: 149 additions & 0 deletions docs/FFI_SYSCALLS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# TSPP Foreign Function Interface (FFI) and Syscall Support

## Overview

TSPP now supports the ability to declare and call external functions, enabling standard libraries to be written in TSPP itself rather than requiring C++ implementations. This provides a powerful Foreign Function Interface (FFI) that allows TSPP code to make system calls and interface with external libraries.

## External Function Declarations

Use the `extern` keyword to declare functions that are implemented outside of TSPP:

```typescript
// Basic external function declaration
extern function my_function(param1: int, param2: string): int;

// External function with custom library name
extern function print_message(msg: string): void "libc_print";
```

### Syntax

```
extern function <function_name>(<parameters>): <return_type> [<external_name>];
```

- `function_name`: The name used to call the function in TSPP code
- `parameters`: Standard TSPP parameter list with types
- `return_type`: The return type of the function
- `external_name`: Optional string literal specifying the actual external function name (defaults to function_name)

## Syscall Interface

TSPP provides a comprehensive syscall interface that allows direct access to operating system functions:

### Generic Syscalls

```typescript
extern function tspp_syscall0(number: int): int;
extern function tspp_syscall1(number: int, arg1: int): int;
extern function tspp_syscall2(number: int, arg1: int, arg2: int): int;
// ... up to tspp_syscall6
```

### Common Syscall Wrappers

```typescript
extern function tspp_sys_open(pathname: string, flags: int, mode: int): int;
extern function tspp_sys_read(fd: int, buf: string, count: int): int;
extern function tspp_sys_write(fd: int, buf: string, count: int): int;
extern function tspp_sys_close(fd: int): int;
extern function tspp_sys_exit(status: int): int;
```

## Writing Standard Libraries in TSPP

With the FFI and syscall support, you can now write standard library modules entirely in TSPP:

### Example: File I/O Module

```typescript
// File: stdlib/io.tspp

// External syscall declarations
extern function tspp_sys_open(pathname: string, flags: int, mode: int): int;
extern function tspp_sys_write(fd: int, buf: string, count: int): int;
extern function tspp_sys_close(fd: int): int;

// Constants
const STDOUT_FILENO = 1;
const O_WRONLY = 1;
const O_CREAT = 64;

// High-level TSPP functions
function createFile(path: string): int {
return tspp_sys_open(path, O_WRONLY | O_CREAT, 0644);
}

function writeToFile(fd: int, data: string): void {
tspp_sys_write(fd, data, data.length);
}

function println(message: string): void {
tspp_sys_write(STDOUT_FILENO, message, message.length);
tspp_sys_write(STDOUT_FILENO, "\n", 1);
}
```

### Example: Memory Management Module

```typescript
// File: stdlib/memory.tspp

extern function tspp_syscall6(number: int, arg1: int, arg2: int,
arg3: int, arg4: int, arg5: int, arg6: int): int;

const SYS_mmap = 9;
const SYS_munmap = 11;
const PROT_READ = 1;
const PROT_WRITE = 2;
const MAP_PRIVATE = 2;
const MAP_ANONYMOUS = 32;

function allocateMemory(size: int): int {
return tspp_syscall6(SYS_mmap, 0, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}

function deallocateMemory(addr: int, size: int): int {
return tspp_syscall2(SYS_munmap, addr, size);
}
```

## Implementation Details

### How It Works

1. **Parser Extension**: The parser now recognizes `extern function` declarations and marks them as external
2. **Code Generation**: External functions are declared in LLVM but not defined, allowing the linker to resolve them
3. **Runtime Linking**: External functions are linked at compile/runtime against the TSPP standard library or system libraries
4. **Type Safety**: Full type checking is maintained for external function calls

### Syscall Implementation

The syscall interface is implemented in C++ (`src/packages/tspp_std/syscall.cpp`) and provides:

- Generic syscall functions that accept varying numbers of arguments
- Common syscall wrappers for frequently used system calls
- Platform-specific implementations (currently Linux x86_64)

### Benefits

1. **Flexibility**: Standard libraries can be written in TSPP itself
2. **Performance**: Direct syscall access eliminates C++ wrapper overhead
3. **Maintainability**: Standard library code in TSPP is easier to understand and modify
4. **Extensibility**: Users can easily add new system interfaces

## Examples

See the `examples/` directory for complete examples:

- `examples/syscall_demo.tspp`: Demonstrates basic syscall usage
- `examples/stdlib/io.tspp`: File I/O operations using syscalls
- `examples/stdlib/memory.tspp`: Memory management using syscalls

## Future Enhancements

- Module import system for TSPP standard libraries
- Automatic binding generation for C libraries
- Cross-platform syscall abstraction
- Dynamic library loading support
192 changes: 192 additions & 0 deletions examples/comprehensive_ffi_demo.tspp
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// Comprehensive example demonstrating TSPP FFI and syscall capabilities
// This shows how standard libraries can be implemented in TSPP itself

// ============================================================================
// System Call Declarations
// ============================================================================

// Generic syscall interface
extern function tspp_syscall0(number: int): int;
extern function tspp_syscall1(number: int, arg1: int): int;
extern function tspp_syscall2(number: int, arg1: int, arg2: int): int;
extern function tspp_syscall3(number: int, arg1: int, arg2: int, arg3: int): int;

// Common syscall wrappers
extern function tspp_sys_open(pathname: string, flags: int, mode: int): int;
extern function tspp_sys_read(fd: int, buf: string, count: int): int;
extern function tspp_sys_write(fd: int, buf: string, count: int): int;
extern function tspp_sys_close(fd: int): int;

// ============================================================================
// Constants
// ============================================================================

// File operation flags (Linux)
const O_RDONLY = 0;
const O_WRONLY = 1;
const O_RDWR = 2;
const O_CREAT = 64;
const O_TRUNC = 512;
const O_APPEND = 1024;

// Standard file descriptors
const STDIN_FILENO = 0;
const STDOUT_FILENO = 1;
const STDERR_FILENO = 2;

// Syscall numbers (Linux x86_64)
const SYS_mmap = 9;
const SYS_munmap = 11;
const SYS_getpid = 39;

// Memory protection flags
const PROT_READ = 1;
const PROT_WRITE = 2;
const MAP_PRIVATE = 2;
const MAP_ANONYMOUS = 32;

// ============================================================================
// TSPP Standard Library Implementation
// ============================================================================

// Console I/O module
namespace Console {
function print(message: string): void {
tspp_sys_write(STDOUT_FILENO, message, 100); // simplified length
}

function println(message: string): void {
print(message);
tspp_sys_write(STDOUT_FILENO, "\n", 1);
}

function error(message: string): void {
tspp_sys_write(STDERR_FILENO, "Error: ", 7);
tspp_sys_write(STDERR_FILENO, message, 100);
tspp_sys_write(STDERR_FILENO, "\n", 1);
}
}

// File system module
namespace FileSystem {
function openForReading(path: string): int {
return tspp_sys_open(path, O_RDONLY, 0);
}

function openForWriting(path: string): int {
return tspp_sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
}

function openForAppending(path: string): int {
return tspp_sys_open(path, O_WRONLY | O_CREAT | O_APPEND, 0644);
}

function close(fd: int): int {
return tspp_sys_close(fd);
}

function write(fd: int, data: string): int {
return tspp_sys_write(fd, data, 100); // simplified
}

function read(fd: int, buffer: string, size: int): int {
return tspp_sys_read(fd, buffer, size);
}
}

// Process utilities module
namespace Process {
function getProcessId(): int {
return tspp_syscall0(SYS_getpid);
}
}

// Memory management module
namespace Memory {
function allocate(size: int): int {
return tspp_syscall3(SYS_mmap, 0, size, PROT_READ | PROT_WRITE);
}

function deallocate(addr: int, size: int): int {
return tspp_syscall2(SYS_munmap, addr, size);
}
}

// ============================================================================
// Application Code
// ============================================================================

function demonstrateFileIO(): void {
Console.println("=== File I/O Demo ===");

// Create and write to a file
let fd = FileSystem.openForWriting("/tmp/tspp_demo.txt");
if (fd != -1) {
FileSystem.write(fd, "Hello from TSPP standard library!\n");
FileSystem.write(fd, "This file was created using syscalls.\n");
FileSystem.close(fd);
Console.println("File created successfully!");
} else {
Console.error("Failed to create file");
}
}

function demonstrateProcessInfo(): void {
Console.println("=== Process Info Demo ===");

let pid = Process.getProcessId();
Console.print("Process ID: ");
// Note: In a real implementation, we'd have integer to string conversion
Console.println("(integer conversion would be here)");
}

function demonstrateMemoryManagement(): void {
Console.println("=== Memory Management Demo ===");

let size = 4096;
let memory = Memory.allocate(size);

if (memory != -1) {
Console.println("Memory allocated successfully!");
// Use the memory here...
Memory.deallocate(memory, size);
Console.println("Memory deallocated successfully!");
} else {
Console.error("Failed to allocate memory");
}
}

// Main function demonstrating the complete system
function main(): int {
Console.println("TSPP Standard Library Demo");
Console.println("Showcasing FFI and syscall capabilities");
Console.println("========================================");

demonstrateFileIO();
demonstrateProcessInfo();
demonstrateMemoryManagement();

Console.println("========================================");
Console.println("Demo completed successfully!");

return 0;
}

// ============================================================================
// Notes:
//
// This example demonstrates how TSPP's FFI and syscall support enables:
//
// 1. Direct system call access from TSPP code
// 2. Standard library implementation in TSPP itself
// 3. Modular organization using namespaces
// 4. Type-safe external function declarations
// 5. Zero-overhead abstraction over system calls
//
// Benefits:
// - No C++ wrapper overhead
// - Standard libraries are readable and modifiable
// - Easy extension of system capabilities
// - Better debugging and maintenance
// - Platform-specific optimizations possible in TSPP
// ============================================================================
Loading