Phasor Language

July 2, 2026 · View on GitHub

Release AUR Version GitHub branch check runs GitHub commit activity

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.

Download Latest Stable

Download Latest Beta

Download Latest Nightly

# 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 as something = 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.1 See here for all man pages.

Contributing

  1. Read the VM Internals and Adding Opcodes guides
  2. Follow the existing code style (see .clang-format)
  3. Add tests for new features
  4. 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:

  • Backend:

  • Extensions:

    • Phasor & Phasor IR TextMate Grammar

    • Phasor Visual Studio Code Extension (Typescript)

    • Python Module src/Extensions/py/phasor

      from 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/Phasor

      Import-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

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.