Documentation

Welcome to the official documentation for the P# language. Dive deeply into how to construct dynamic, compiled network policies using a simple syntax.

CLI Commands

The psh executable is a statically compiled Go binary that contains the compiler, Virtual Machine runtime, and Language Server Protocol (LSP).

# Execute a script dynamically (Lex, Parse, Compile, Execute)
psh run script.psh

# Compile a script into a deterministic bytecode artifact (.pbc)
psh compile script.psh

# Execute a precompiled bytecode file (Ultra-fast startup)
psh exec script.pbc

# Print human-readable VM bytecode instructions for debugging
psh disasm script.pbc

# Start the JSON-RPC Language Server (used by VS Code extensions)
psh lsp

Note: We recommend running psh compile for production environments, then transferring the .pbc file to your target machines for execution using psh exec.

Directives

Directives configure the networking backend before the VM loop starts listening. They are defined at the very top of the file.

@listen 8080
@type tcp

Listeners & Connections

The core of P# is the listener block. Whenever a connection hits the port defined by the directives, the runtime VM injects a conn struct object into the listener's scope.

The script must evaluate the connection and must end by triggering accept or drop keywords.

Connection Object Fields (conn)

Field Type Description
conn.ip string The remote IP address of the incoming connection.
conn.port int The remote port of the connection.
conn.type string The transport layer used (e.g. TCP, UDP).
conn.country string Determined ISO country code. (Simulated functionality)
conn.payload string Initial buffered packet payload.
listener Logger(conn) {
    // Output incoming requests immediately
    println(conn.ip + ":" + conn.port)
    accept
}

Data Types & Literals

P# is strongly typed regarding built-in constructs. Supported literals include:

Control Flow

P# utilizes readable boolean conditionals designed for writing rapid rule engines.

listener Monitor(conn) {
    if conn.ip == '192.168.1.1' and conn.port == 22 then
        drop
    end
    else
        accept
}

Logical operators include and, or, and not.

Standard Library

You can maintain memory and state across connections utilizing global registers defined outside of a listener context. The most prominent structure is the List type.

// Instantiate a list in the global memory pool
global blocklist = new List()

listener Firewall(conn) {
    if conn.country == 'RU' then
        // Native standard library commands
        append conn.ip to blocklist
        drop
    end
    
    // Additional operations available:
    // remove conn.ip from blocklist
    accept
}