Phasor Language
July 2, 2026 · View on GitHub
A statically/dynamically typed, compiled programming language with a fast bytecode virtual machine. Parameter and return types are static for user defined (non FFI / non STDLIB) functions.
Phasor does not have a traditional garbage collector, the entire toolchain makes use of a unified type system, which provides C++ RAII support to the runtime, stdlib, and FFI interfaces.
See Language Features for more info on memory management.
See Building for info on building from source.
Phasor is not considered entirely stable yet, as I wish for a smooth, stable experience for the final language. The existing implementation still needs some work. The ABI is not stable, but conforms to semver most of the time (thus why this is 3.X.X and still in beta.)
You can check out the website as well.
# Run via nix
nix run github:DanielLMcGuire/Phasor -- -- <options>
# Run directly (requires install)
phasor <options>
Language Features
- Dynamic typing with integers, floats (IEEE 754, double-percision), strings, booleans, and null.
var x: any = 21; // int - Structs
struct Point { x: int, y: int } var p: Point = { x: 10, y: 20 }; p.x = 42; - Arrays
var dyn: any[] = [1, "hi", null, 15.1]; var typed: int[] = [15, 12]; var strict: int[10]; strict[0] = 99; var item: int = strict[0]; - Uniform Function Call Syntax for stdlib/builtin/ffi
var x: any = 15; x.len(); "Hello".len().puts() - Type annotations
fn func(input: string) -> void { ... } - JSON Support
var x: string = to_json({ x: 10, y: 20 }); var y: any = from_json(x); - Control flow: if/else, while, for, switch/case, break/continue
- Standard library
using(featureName: string) - Plugin/FFI API PhasorFFI.h
- Runtime API PhasorRT.h
- Rust runtime bindings (capi wrapper)
- Zig runtime bindings (capi wrapper)
- Minimal Windows and POSIX API Bindings
- Supports most C format specifiers
- stdmem stdlib module with free()
using("stdmem"); free("variableName");(same assomething = null;) - AppleScript bindings for phasor
// Print (keyword)
print "Hello World!\n"; // Print to console
// Or via std
using("stdio"); // Import io for puts
puts("Hello World!"); // Print string with newline
using("stdsys", "stdio"); // Import sys, io
// Variables implicitly typed
var code: any = 15; // int
var fmt: any = "Code = %d"; // string
// or explicitly:
var code: int = 15;
var fmt: string = "Code = %d";
// Formatting
printf("Exiting with code %d", code);
putf("%d", code);
var fmtStr: string = c_fmt(fmt, code);
// Exit with a code other than 0
shutdown(code); // from stdsys
Upcoming
Important
Some may appear to work before actual implementation
The existance of a keyword/token type does not imply there is planned support for said feature
- ActiveX Scripting Engine (COM) (partial implementation already in 3.3.0)
- LLVM Jit for hot loops / functions
Quick Start
# Compile and run a program
$ phasor input.phs
# Repl
$ phasor
# Compile to bytecode
$ phasorcompiler input.phs (-o, --output output.phsb)
# Run bytecode
$ phasorvm output.phsb
# Run a script raw
$ echo "print \"Hello World\!\\n\"" | phasor
Hello World!
$
Example Program
using("stdio", "stdtype", "stdmem");
puts("Enter a number:");
var input: string = gets();
var num1: int = to_int(input);
var num2: int = 25;
putf("%d + %d = %d\n", num, num2, num1 + num2);
Documentation
Note
Online docs are always up to date with master (as much as I can at least), offline (installed) docs are always usually up to date with that version.
Feel free to make an issue if something is not right.
- Language Guide - Complete syntax and language features
- VM Internals - Virtual machine architecture details
- Adding Opcodes - Contributor guide for VM extensions
- Doxygen - Documentation and call graphs generated from source code
- Manuals/Man Pages:
https://phasor-docs.pages.dev/man?f=[filename], e.g./man?f=phasor.1See here for all man pages.
Contributing
- Read the VM Internals and Adding Opcodes guides
- Follow the existing code style (see
.clang-format) - Add tests for new features
- Update documentation as needed
Applications
-
Phasor
- phasor - Combines the Scripting Runtime, VM Runtime, and REPL, adds pipe support, and supports shabangs
- phasor-lsp - JSON-RPC 2.0 LSP Protocol Handler for the Phasor Language
- Bytecode Compiler (
phasorcompiler) - Script to bytecode compiler - Native Compiler (
phasornative) - Script to C++ transpiler - VM Runtime (
phasorvm) - Bytecode executor - Disassembler (
phasordecomp) - Assembler (
phasorasm)
-
Pulsar
- pulsar - Scripting runtime and REPL
- Bytecode Compiler (
pulsarcompiler) - Script to bytecode compiler - Uses the Phasor VM Runtime for bytecode (
phasorvm)
Overview
This repo contains:
-
Frontend:
- Phasor Language (Specifications, C++)
- Pulsar Language (C++)
- Phasor Runtime / VM (ISA Specs, C/C++/Assembly)
- Phasor Standard Library (Man pages, C/C++)
-
Backend:
- Phasor Compiler Infrastructure (C++)
- FFI API (C)
- Runtime API (C)
-
Extensions:
-
Phasor Visual Studio Code Extension (Typescript)
-
Python Module
src/Extensions/py/phasorfrom phasor import Bytecode, Value, OpCode, Runtime help(phasor) bc = Bytecode() bc.emit(OpCode.PUSH_CONST, bc.add_constant(Value.from_string("Hello, World!\n"))) bc.emit(OpCode.PRINT) bc.emit(OpCode.HALT) bc.save("hello_world.phsb") Runtime.run(bc) # wraps phasorrt lib -
PowerShell Module (windows only, phasorrt.dll bindings)
src/Extensions/powershell/PhasorImport-Module .\src\Extensions\powershell\Phasor\Phasor.psd1 Get-Help Phasor # Get-Help <cmdlet> # state is always optional (-State is optional) # anything not using state will create thier own Start-PhasorScript -ScriptPath .\hello.phs Start-PulsarScript -ScriptPath .\hello.pul $vm = New-PhasorState # stdlib is already registered if not using your own state Register-PhasorStdlib -State $vm Start-PhasorEval -State $vm -Script 'var x = 42; var y = 53;' # x and y still in scope Start-PhasorEval -State $vm -Script 'print(x + y);' # all states are cleared at powershell shutdown, but to clear them early: Remove-PhasorState $vm $bytecode = Build-PhasorScript -Script 'print("hi\n");' # can also optionally accept state Invoke-PhasorBytecode -Bytecode $bytecode -
phasor-web REST API
src/Extensions/web(Typescript, Node 22)$ curl -d 'using("stdio"); puts("Hi!");' -H "x-api-key: API_KEY" http://0.0.0.0:62811/run {stdout: "Hi!\n", stderr: "", exitCode = 0}
-
Bindings:
-
phasorrt-rs Rust Bindings (runtime)
src/Rust(Rust)// Create a new VM and load the standard library let mut vm = PhasorVM::new()?; vm.init_stdlib()?; // run script vm.evaluate_phs("print(\"Hello, World!\\n\");", "hello", None, false)?; // state is kept vm.evaluate_phs("var x = 42; var y = 53;", "vars", None, false)?; vm.evaluate_phs("print(x + y);", "vars", None, false)?; // prints 95 // reset vars vm.reset(false, true)?; // compile/run bytecode let bytecode = compile_phs("print(\"hi\\n\");", "hi", None)?; vm.exec(&bytecode, "hi", &[])?; // VM is automatically freed when it goes out of scope (Drop) // For static linking, ensure you use clang on macos, msvc on windows and gcc on linux // First build the cmake project under the correct config // Next, use cargo with --no-default-features -
phasorrt-zig Zig bindings (runtime)
src/Zig(Zig)const phasor = @import("phasor.zig"); // create vm (auto inits stdlib) const vm = try phasor.State.create(); defer vm.deinit(); // run a script _ = try vm.evaluatePHS("print(\"Hello, World!\\n\");", "hello", ".", false); // state is kept between calls _ = try vm.evaluatePHS("var x = 42; var y = 53;", "vars", ".", false); _ = try vm.evaluatePHS("print(x + y);", "vars", ".", false); // prints 95 // Reset vars only, keep function definitions try vm.reset(false, true); // compile to bytecode, then execute const bytecode = try phasor.compilePHS(allocator, "print(\"hi\\n\");", "hi", "."); defer allocator.free(bytecode); _ = try vm.exec(bytecode, "hi", &.{}); // VM is freed when deinit() is called (or via defer)
-
Building
Using Arch BTW? Just run makepkg -si, or get phasor-git on the AUR
Note
If you have forked and do not plan to contribute back, you should modify cmake/Version.cmake to match your forks URL!
Prerequisites
- Required:
- Ninja
- CMake 3.21+
- GAS/Clang Assembler (Unix-based System V compliant OS / Darwin (OSX/macOS) 64-bit only)
- MASM Assembler (Windows 64-bit only)
- CC (C 23 Compliant) compiler and CXX (C++ 23 Compliant) compiler supporting GCC/Clang extensions or Windows specific extensions
- Optional:
- Rust Toolchain (latest stable) for the
phasorrt-rslib - CPython 3.9 or later (or another Python compliant interpreter) for the Python API
- PowerShell latest for the PowerShell module
- Node.js 24 or later for the web server, and for building the Visual Studio Code extension
- Docker for the man page to pdf conversions (required only for phasor-help on win32)
- Rust Toolchain (latest stable) for the
Build Steps
See Building Phasor.
See Building Phasor Extensions for info on building Extensions/bindings.
FFI Plugin locations
Available in different locations based on your OS:
- Unix -
/usr/lib/phasor/plugins/ - macOS -
/Library/Application Support/org.Phasor.Phasor/plugins/ - Windows -
C:\Program Files\Phasor Programming Language\bin\plugins\
GitHub GitLab Mirror Codeberg Mirror
Phasor will be moving to Codeberg (or something similar) in the coming months, CI will stay on github as its entire free, but PRs and issues will eventually be disabled.
Mentions of the Free Software Foundation, Inc., 'Java™', Oracle® Corporation, '.NET™', Microsoft® Corporation, Google® LLC, or other third-party companies, products, or trademarks do not imply any affiliation, endorsement, or sponsorship by those third parties, or thier affiliates, unless explicitly stated otherwise.
Phasor Toolchain is licensed for use under the Apache 2.0 License.
Phasor Runtime (phasorrt.dll, libphasorrt.so, libphasorrt.dylib, out/lib/**/*, out/include/**/*, etc) is licensed for use under the Apache 2.0 with LLVM-Exceptions License.
Phasor and the "sinewave Phasor" logo are trademarks of Daniel McGuire.