Skip to content

williamalexakis/phase

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Phase

A statically-typed language bridging high-level clarity with low-level control



              

For detailed insight into the design process behind Phase, look at my blog post.

Features

  • Clean Semantics – Syntax is clear, balanced, and predictable.
  • Static Typing – Variable declarations have consistent syntax and type safety is ensured through compile-time checking.
  • Bytecode Compilation – Source code is compiled into a portable instruction set executed by a fast handwritten VM.
  • Error Manager – Errors are handled by a diagnostic system that displays clear and informative reports.
  • Debug Modes – Token streams and AST structures are easily viewable for effective diagnostics of source code.

Motivation

I created Phase to bridge a gap between high-level languages and low-level ones. High-level languages are expressive but obscure their mechanics, while low-level languages are explicit but heavy; I wanted a middleground that's clear, predictable, and simple.

I also spent time designing an error system that tells you exactly what you need to know – without excessive noise or missing context. I think that good diagnostics are as important as good semantics, and I wanted Phase to reflect that.

Architecture

Interpreter Pipeline

flowchart LR
    A(Source Code) --> B(Lexer)
    B --> C(Parser)
    C --> D(Type Checker)
    D --> E(Bytecode Generator)
    E --> F(Virtual Machine)
Loading

Project Structure

phase/
  ├─ src/
  │   ├─ lexer.c
  │   ├─ lexer.h
  │   ├─ parser.c
  │   ├─ parser.h
  │   ├─ codegen.c
  │   ├─ codegen.h
  │   ├─ errors.c
  │   ├─ errors.h
  │   ├─ main.c
  │   └─ colours.h
  ├─ examples/
  │   ├─ conditionals.phase
  │   ├─ fibonacci.phase
  │   ├─ full_demo.phase
  │   ├─ functions.phase
  │   ├─ helloworld.phase
  │   ├─ loops.phase
  │   ├─ state_machine.phase
  │   └─ variables.phase
  ├─ tests/
  │   ├─ apostrophe_string.phase
  │   ├─ arithmetic.phase
  │   ├─ compound_assign.phase
  │   ├─ if_else.phase
  │   ├─ invalid_token_global.phase
  │   ├─ logic.phase
  │   ├─ missing_expression.phase
  │   ├─ missing_paren.phase
  │   ├─ missing_return.phase
  │   ├─ multiple_entry.phase
  │   ├─ no_entry.phase
  │   ├─ open_string.phase
  │   ├─ type_mismatch.phase
  │   ├─ undefined_var.phase
  │   ├─ while_basic.phase
  │   └─ wrong_var_init_count.phase
  ├─ CMakeLists.txt
  ├─ build.sh
  ├─ LICENSE
  └─ README.md

Type System

Phase currently supports int, float, bool, and str.

Types are checked at compile-time, and all variables must explicitly declare their type.

Type-checking ensures operands match expected types and prevents invalid operations before bytecode generation.

Virtual Machine

Phase compiles programs into a compact bytecode instruction set, executed by a handwritten stack-based VM.

Each instruction operates on a shared stack and uses a small and predictable opcode set.

This source code:

entry {
    out("Hello world!")
}

Compiles into this bytecode:

00 00 00   ; OP_PUSH_CONST 0
01         ; OP_PRINT
18         ; OP_HALT

Installation

Prerequisites

  • CMake 3.20+
  • C17-compatible compiler

Building

  1. Clone the repo in your desired directory:

    git clone https://github.com/williamalexakis/phase.git
    cd phase
  2. Run the Automated Build Script (Recommended):

    Quick Build

    ./build.sh

    Run with --debug for Debug Build or --run to immediately run after building.

    Or Build Manually:

    mkdir build
    cd build
    cmake ..
    cmake --build .

Usage

Command Description
phase --help Display available commands and flags
phase <file.phase> --tokens Display token stream
phase <file.phase> --ast Display AST
phase <file.phase> --loud Display a success message when programs finish

Syntax Examples

Hello World

entry {
    out("Hello world!")
}

Variables

entry {
    let (name, surname): str = ("Arthur", "Ford")
    let age: int = 25
    let employed: bool = true

    age += 1

    out("Name:")
    out(name)
    out(surname)
    out("Age:")
    out(age)
    out("Employed:")
    out(employed)
}

Functions + Logic

func greet(name: str, excited: bool): void {
    if excited and name == "Alora" {
        out("HELLO")
    } else {
        out("Hello")
    }
    out(name)
}

entry {
    greet("Alora", true)
}

Conditionals + Arithmetic

entry {
    let score: int = 9

    if score >= 10 {
        out("Top tier")
    } else if score > 5 {
        out("Good")
    } else {
        out("Needs work")
    }
}

Loops (while)

entry {
    let keep: bool = true
    let counter: int = 0

    while keep {
        out(counter)
        counter += 1
        if counter == 3 {
            keep = false
        }
    }
}

See examples/ for more

Diagnostics Examples

Error Reporting

Token Display

AST Display

Roadmap

  • Lexer
  • Parser
  • Bytecode generator
  • VM execution loop
  • Token and AST diagnostics
  • Floats and booleans
  • Error manager
  • Declaration keywords & annotations
  • Functions
  • Conditionals
  • Basic loops

License

Phase is released under the MIT License.

See the LICENSE for full details.