Advanced Guide
This guide covers advanced features of the Zamin language including extending Zamin with C, interopping with Python, leveraging GPU acceleration via CUDA, embedding Zamin in Rust applications, and using the built-in LSP server.
C Extensions
Zamin supports native C extensions for performance-critical code or wrapping existing C libraries. Extensions are compiled as shared objects and loaded automatically at runtime.
Header File
Include the main header in your C source:
#include "zamin.h"
The header is located at include/zamin.h in the Zamin source tree.
Zamin Types
Zamin exposes the following C type constants for use with the ZaminValue union:
| Constant | Description |
|---|---|
ZAMIN_NIL | Nil / null value |
ZAMIN_INT | Integer (64-bit signed) |
ZAMIN_FLOAT | Double-precision float |
ZAMIN_BOOL | Boolean true/false |
ZAMIN_STRING | Heap-allocated string |
ZaminValue Struct
The ZaminValue struct is a tagged union that represents all values that can cross the C/Zamin boundary:
typedef struct {
int type;
union {
int64_t i;
double f;
int b;
const char *s;
} as;
} ZaminValue;
ZaminModuleFunc Struct
Each exported function is described by a ZaminModuleFunc entry:
typedef struct {
const char *name;
ZaminValue (*func)(int argc, ZaminValue *argv);
int arity; // -1 for variadic
} ZaminModuleFunc;
Exporting a Module
Every C extension must export a zamin_module_init function that returns a ZaminModuleFunc array and sets the count via the provided pointer:
ZaminModuleFunc *zamin_module_init(int *count) {
static ZaminModuleFunc funcs[] = { ... };
*count = sizeof(funcs) / sizeof(funcs[0]);
return funcs;
}
Building
Compile your extension as a shared library:
gcc -shared -fPIC -O2 -I../include -o mymod.so mymod.c
Place the resulting .so file in your project's modules/ directory. Zamin will auto-load it when you write use mymod.
Full Example: math_ext
#include "zamin.h"
static ZaminValue math_add(int argc, ZaminValue *argv) {
if (argc != 2) {
return (ZaminValue){ ZAMIN_NIL, { .i = 0 } };
}
int64_t a = argv[0].as.i;
int64_t b = argv[1].as.i;
return (ZaminValue){ ZAMIN_INT, { .i = a + b } };
}
static ZaminValue math_multiply(int argc, ZaminValue *argv) {
if (argc != 2) {
return (ZaminValue){ ZAMIN_NIL, { .i = 0 } };
}
int64_t a = argv[0].as.i;
int64_t b = argv[1].as.i;
return (ZaminValue){ ZAMIN_INT, { .i = a * b } };
}
ZaminModuleFunc *zamin_module_init(int *count) {
static ZaminModuleFunc funcs[] = {
{ "add", math_add, 2 },
{ "multiply", math_multiply, 2 },
};
*count = sizeof(funcs) / sizeof(funcs[0]);
return funcs;
}
Usage in Zamin:
use math_ext
let result = math_ext.add(10, 20)
print(result) // 30
let product = math_ext.multiply(6, 7)
print(product) // 42
Python Interop
Zamin can call Python modules directly when compiled with the python feature. This enables reusing the vast Python ecosystem from Zamin code.
Building with Python Support
cargo build --features python
Importing Python Modules
Use py.import() to bring a Python module into scope:
let np = py.import("numpy")
let arr = np.array([1, 2, 3, 4, 5])
print(arr.mean()) // 3.0
Checking the Python Version
print(py.version()) // e.g. "3.14.0"
Type Marshalling
Zamin automatically converts types between the two languages:
| Zamin Type | Python Type |
|---|---|
int | int |
float | float |
string | str |
bool | bool |
list | list |
nil | None |
dict | dict |
Examples
Using requests to fetch a URL:
let requests = py.import("requests")
let resp = requests.get("https://httpbin.org/json")
print(resp.status_code)
print(resp.json())
Using numpy for matrix operations:
let np = py.import("numpy")
let a = np.array([[1, 2], [3, 4]])
let b = np.array([[5, 6], [7, 8]])
let c = np.dot(a, b)
print(c)
// [[19 22]
// [43 50]]
CUDA / GPU Acceleration
Zamin can leverage NVIDIA GPUs for computation when CUDA is available. The build system automatically detects CUDA during compilation via build.rs.
Automatic Detection
During cargo build, build.rs checks for the nvcc compiler and CUDA toolkit. If found, GPU modules are compiled and linked automatically. No extra flags are needed.
LINUM Module
The LINUM (Zamin Numerical) module provides GPU-accelerated neural network primitives:
linum.tensor()- Create GPU tensorslinum.matmul()- Matrix multiplication on GPUlinum.relu()/linum.sigmoid()- Activation functionslinum.softmax()- Softmax for classificationlinum.cross_entropy()- Loss functions
GPU Memory API
print(linum.gpu_name()) // "NVIDIA GeForce RTX 4090"
print(linum.gpu_memory()) // 24576 (MB)
print(linum.gpu_memory_used()) // 512 (MB)
Example: Neural Network
use linum
let model = linum.Sequential([
linum.Linear(784, 256),
linum.ReLU(),
linum.Linear(256, 128),
linum.ReLU(),
linum.Linear(128, 10),
linum.Softmax()
])
let optimizer = linum.Adam(model.parameters(), lr: 0.001)
let loss_fn = linum.CrossEntropyLoss()
for epoch in 0..10 {
let pred = model.forward(train_data)
let loss = loss_fn(pred, train_labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("Epoch {epoch}, Loss: {loss.item():.4f}")
}
Embedding in Rust
Zamin can be embedded as a library in Rust applications. This is useful for building tools, IDEs, or applications that need scripting capabilities.
Cargo.toml Dependency
[dependencies]
zamin = { path = "../zamin" }
API
Two primary functions are provided:
zamin::execute_source(code: &str)- Execute a Zamin source stringzamin::execute_file(path: &str)- Execute a Zamin file from disk
Full Rust Embedding Example
func main() {
// Execute a Zamin source string
zamin::execute_source(r#"
let greeting = "Hello from Zamin!"
print(greeting)
let result = 2 + 3
print("2 + 3 = {result}")
"#).expect("Failed to execute Zamin source");
// Execute a Zamin file
zamin::execute_file("scripts/app.zamin").expect("Failed to execute file");
// Access Zamin values from Rust
let mut vm = zamin::Vm::new();
vm.execute("let x = 42").unwrap();
let value = vm.get_global("x").unwrap();
println!("Zamin returned: {:?}", value);
}
LSP Server
Zamin ships with a built-in Language Server Protocol (LSP) implementation that provides IDE features for any editor with LSP support.
The zamin-lsp Binary
After building Zamin, the zamin-lsp binary will be available in the output directory. It communicates over stdio using the LSP protocol.
Features
- Completion - Context-aware autocompletion for keywords, built-in functions, module APIs, and user-defined variables
- Hover - Type information and documentation on hover for all symbols
- Diagnostics - Real-time syntax errors, type mismatches, and undefined references
VS Code Extension
A VS Code extension is available. Install it from the marketplace and add the following to your settings.json:
{
"zamin.server.path": "/path/to/zamin-lsp"
}
The extension provides syntax highlighting, error squiggles, autocompletion popups, and hover documentation out of the box.