Introduction
This book is being rewritten. Most pages describe a mix of planned and legacy syntax, and many of their examples do not run on the current interpreter. Pages marked Legacy page will be rewritten in P7 Docs truth. Until then, trust the example on this page and
examples/app.pooin the repository over the rest of the book.
The name Poo comes from the Burmese word for guinea pig (ပူး).
Where PooLang is today
PooLang v0.1.11 is a small tree-walking interpreter written in Rust with no
third-party dependencies. Source code goes through three stages: a lexer turns
it into tokens, a parser builds an abstract syntax tree, and an interpreter
walks that tree to run the program. The poo command runs a .poo file.
This program runs on v0.1.11:
use std::poutln;
// Comments open and close with two slashes. //
poo name <: "Guinea Pig";
mut count int = 0;
count = count + 1;
poof add(a int, b int) >> int {
return a + b;
}
if count > 0 and not false {
poutln("Hello, ", name, "! 2 + 3 = ", add(2, 3));
} elif count == 0 {
poutln("unreachable");
}
It prints:
Hello, Guinea Pig! 2 + 3 = 5
A few rules of v0.1 syntax that the older pages get wrong:
- Output functions must be imported before use, for example
use std::poutln;. poodeclares an immutable variable andmutdeclares a mutable one.<:infers the type (poo x <: 5;);=follows an explicit type (poo x int = 5;). Reassignment uses=(x = 1;).- Functions are declared with
poof, parameters need types, and>>gives the return type:poof add(a int, b int) >> int { ... }. - Comments are paired:
// like this //. - Logical operators are
and,or, andnot(!also works);&&and||do not exist.
Where PooLang is going
PooLang is being repositioned as a sandboxed scripting language for AI agents: an LLM agent writes the script and a host program runs it safely. The goals for that design are explicit capabilities granted by the host, resource budgets, deterministic execution, an interpreter that reports errors instead of panicking, and diagnostics that an LLM can read and act on.
Version 0.2 will move to a more conventional syntax while keeping the poo and
poof keywords. Because of that change, this book will be rewritten against
v0.2 rather than patched page by page.
Getting Started
Installation
Using Automated Installers
The fastest way to install PooLang is via our universal installers:
Linux / macOS
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/shayyz-code/poolang/releases/latest/download/poo-installer.sh | sh
Windows
powershell -c "irm https://github.com/shayyz-code/poolang/releases/latest/download/poo-installer.ps1 | iex"
From Source
If you have Rust and Cargo installed, you can build from source:
git clone https://github.com/shayyz-code/poolang.git
cd poolang
cargo build --release
The binary will be available at ./target/release/poo.
Running your first program
Create a file named hello.poo:
use std::pout;
pout("Hello, Guinea Pig!");
Run it using the PooLang CLI:
poo hello.poo
Next Steps
Check out the Variables & Types section to learn more about PooLang syntax.
Variables & Types
Legacy page. This page predates the v0.2 redesign and may show syntax the v0.1.11 interpreter does not accept. It will be rewritten in P7 Docs truth.
Variable Declarations
PooLang uses the poo keyword to declare variables. By default, variables are immutable, meaning their value cannot be changed after assignment.
poo age << 5;
If you need to reassign a value, you must use the mut keyword:
poo mut score << 0;
score << 10; # This is allowed
Assignment Operator
Note that PooLang uses the << operator for assignment instead of the traditional =. This helps distinguish PooLang code at a glance.
Supported Types
- Integer: Whole numbers (e.g.,
42,-10). - Float: Decimal numbers (e.g.,
3.14,2.0). - String: Text enclosed in double quotes (e.g.,
"Hello"). - Boolean: Truth values (
trueorfalse). - Vector: A collection of values (e.g.,
[1, 2, 3]).
Type Inference
PooLang automatically infers the type of a variable based on the value assigned to it. You do not need to explicitly declare types for variables.
Operators & Math
Legacy page. This page predates the v0.2 redesign and may show syntax the v0.1.11 interpreter does not accept. It will be rewritten in P7 Docs truth.
PooLang supports standard arithmetic operations with proper mathematical precedence (PEMDAS).
Arithmetic Operators
| Operator | Description | Example |
|---|---|---|
+ | Addition | 5 + 2 |
- | Subtraction | 10 - 4 |
* | Multiplication | 3 * 3 |
/ | Division | 20 / 5 |
Precedence Example
poo result << 10 + 5 * 2; # result is 20 (5*2=10, 10+10=20)
Comparison Operators
These operators return a Boolean (true or false).
| Operator | Description |
|---|---|
== | Equal to |
!= | Not equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
Logical Operators
| Operator | Description |
|---|---|
&& | Logical AND |
| ` | |
! | Logical NOT |
Comments
In PooLang v0.1.11 a comment opens with // and closes with another //.
Everything between the two markers is ignored, so a comment can sit between
statements on one line or span several lines.
use std::poutln;
// A comment opens and closes with two slashes. //
poutln("before"); // A comment can sit between statements. // poutln("after");
// It can also
span several lines. //
This program prints before and then after.
Conditionals
Legacy page. This page predates the v0.2 redesign and may show syntax the v0.1.11 interpreter does not accept. It will be rewritten in P7 Docs truth.
PooLang uses if, elif, and else to control the flow of execution based on boolean conditions.
If Statements
The simplest form is a single if block:
if x > 10 {
pout("x is large");
}
If-Else
You can provide an alternative path using else:
if x > 10 {
pout("x is large");
} else {
pout("x is small");
}
Elif (Else If)
For multiple conditions, use elif:
if x > 100 {
pout("Huge");
} elif x > 10 {
pout("Large");
} else {
pout("Small");
}
Scoping
Variables declared inside a conditional block are scoped to that block and are not accessible outside.
if true {
poo temp << 1;
}
# temp is no longer accessible here
Loops
Legacy page. This page predates the v0.2 redesign and may show syntax the v0.1.11 interpreter does not accept. It will be rewritten in P7 Docs truth.
PooLang provides two primary ways to repeat logic: while loops and for loops.
While Loops
The while loop continues to execute as long as its condition remains true.
poo mut count << 0;
while count < 5 {
pout("Count: ", count);
count << count + 1;
}
For Loops
PooLang supports for loops that iterate over a range or a collection.
Range Iteration
You can iterate over a range of numbers using the .. syntax:
for i in 0..5 {
pout(i); # Prints 0, 1, 2, 3, 4
}
Vector Iteration
You can also iterate over elements in a vector:
poo items << [10, 20, 30];
for item in items {
pout(item);
}
Scoping
The loop variable (like i or item) is only accessible within the body of the loop.
Functions
Legacy page. This page predates the v0.2 redesign and may show syntax the v0.1.11 interpreter does not accept. It will be rewritten in P7 Docs truth.
Functions in PooLang allow you to encapsulate logic into reusable blocks. They are defined using the poof keyword.
Defining a Function
A basic function looks like this:
poof sayHello() {
pout("Hello!");
}
Return Types
PooLang uses the >> operator to specify the return type of a function.
poof getNumber() >> int {
return 42;
}
Common return types include int, float, string, bool, and void (if no value is returned).
Parameters
You can pass data into functions via parameters:
poof add(a, b) >> int {
return a + b;
}
poo sum << add(5, 5); # sum is 10
Function Scope
Functions create their own scope. Variables declared inside a function are not accessible outside. Functions can, however, access variables in the global scope if they are defined before the function is called.
Standard Library
Legacy page. This page predates the v0.2 redesign and may show syntax the v0.1.11 interpreter does not accept. It will be rewritten in P7 Docs truth.
PooLang includes a small built-in standard library to handle common tasks like output.
Printing to Console
The pout function is used to print values to the standard output.
use std::pout;
pout("Hello, World");
pout("The result is: ", 42);
Import Syntax
Note the use std::pout; line. pout is not available by default: calling it without importing it first fails with the runtime error Undefined function: pout.
Future Plans
The standard library is currently minimal. Planned additions include:
std::math: Advanced math functions (sin, cos, etc.)std::fs: File system operationsstd::str: String manipulation utilities
Lexer
Legacy page. This page predates the v0.2 redesign and may show syntax the v0.1.11 interpreter does not accept. It will be rewritten in P7 Docs truth.
The Lexer (also known as a Tokenizer) is the first stage of the PooLang pipeline. Its job is to take raw source code (a string of characters) and turn it into a sequence of meaningful Tokens.
How it works
The Lexer scans the input character by character and groups them into tokens like:
- Keywords:
poo,mut,if,while - Operators:
<<,+,-,*,/ - Literals: Integers (
10), Strings ("hi"), Booleans (true) - Identifiers: Variable and function names
Implementation
The implementation is located in src/lexer.rs. It uses a simple state-machine approach to recognize different patterns of text.
Example
Input:
poo x << 5;
Tokens produced:
Keyword(Poo)Identifier("x")Operator(Assign)Literal(Integer(5))Semicolon
Parser
The Parser takes the stream of tokens produced by the Lexer and organizes them into a hierarchical structure called an Abstract Syntax Tree (AST).
How it works
PooLang uses a Recursive Descent parser. It looks at the current token and decides which rule of the language grammar to apply next.
For example, if the parser see the poo token, it knows it is starting a variable declaration and expects an identifier followed by an assignment operator.
Abstract Syntax Tree (AST)
The AST is a tree-like representation of your code. For example, the expression 1 + 2 * 3 would be parsed into a tree where + is the root, 1 is the left child, and another tree representing 2 * 3 is the right child.
The AST node definitions can be found in src/ast.rs.
Implementation
The parser logic resides in src/parser.rs. It handles:
- Statement parsing
- Expression parsing (with operator precedence)
- Error reporting for syntax errors
Interpreter
The Interpreter is the final stage of the PooLang pipeline. It takes the Abstract Syntax Tree (AST) produced by the Parser and executes the logic it represents.
How it works
PooLang uses a Tree-Walking Interpreter. It traverses the AST recursively, "visiting" each node and performing the corresponding action in the real world (e.g., adding two numbers, updating a variable in memory).
Environment and State
The interpreter maintains an Environment (or Scope) which maps variable names to their current values. When you declare a variable with poo, it is added to the current environment.
Implementation
The interpreter is located in src/interpreter.rs. Key features include:
- Value system: Defines how integers, floats, and strings are stored in memory.
- Scope management: Handles nested scopes for loops and functions.
- Runtime Errors: Detects issues like dividing by zero or using an undefined variable.