Sesi is a concise and highly legible programming language. It uses a high-performance bytecode compilation model built in TypeScript. The architecture features a compiler that lowers the AST to a flat bytecode chunk, executed by a register-based virtual machine, with the original tree-walking interpreter retained as a fallback path. The architecture is optimized for simplicity and eliminating the need for async/await syntax or heavy module imports. By acting as a minimal orchestration layer, Sesi allows developers to write clean, straightforward logic that natively handles background processes and API or Reasoning calls without SDK overhead.
┌─────────────────────────────────────────────┐
│ Sesi Program (.sesi file) │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Lexer (src/lexer.ts) │
│ Converts source text → Tokens │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Parser (src/parser.ts) │
│ Converts Tokens → Abstract Syntax Tree │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ Compiler (src/compiler.ts) │
│ Lowers AST → Bytecode Chunk │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼──────────────────────────┐
│ VM (src/vm.ts) │
│ Bytecode virtual machine │
│ - Executes OpCode instructions │
│ - Manages call frames & value stack │
│ - Supports closures, try/catch, imports │
└──────┬───────────────────────┬──────────────┘
│ │
│ │
┌──────▼──────────────┐ ┌────▼────────────────┐
│ Builtins │ │ AI Runtime │
│ (src/builtins.ts) │ │ (src/ai-runtime.ts) │
│ │ │ │
│ - print() │ │ - Gemini API calls │
│ - len() │ │ - Memory mgmt │
│ - read_file() │ │ - Structured output │
│ - write_file() │ │ - Tool calling │
│ - spawn() │ │ │
│ - exec() │ │ │
│ - sesi() │ │ │
│ - time() │ │ │
│ - random() │ │ │
│ - etc. │ │ │
└─────────────────────┘ └────┬────────────────┘
│
┌─────────▼──────────┐
│ Gemini API │
│ (@google/genai) │
└────────────────────┘
- Input: Source code string
- Process: Character-by-character tokenization
- Identifier and keyword recognition
- Number and string literal parsing
- Operator and delimiter recognition
- Comment stripping
- Output: Token stream
Example:
Source: let x = 10
Tokens: [LET, IDENTIFIER("x"), EQUAL, NUMBER(10), EOF]
- Input: Token stream
- Process: Recursive descent parsing
- Statement parsing (declarations, control flow)
- Expression parsing (operators, function calls, Reasoning constructs)
- AST construction
- Error recovery
- Output: Abstract Syntax Tree (AST)
Example AST Node:
{
type: 'LetStatement',
name: 'x',
value: {
type: 'Literal',
value: 10,
rawType: 'number'
}
}- Input: AST
- Compiler process: Single-pass AST lowering
- Emits flat OpCode instructions into a
Chunk - Resolves local variable slots at compile time
- Compiles closures, loops, conditionals, and try/catch
- Emits flat OpCode instructions into a
- VM process: Stack-based execution
- Dispatches OpCode instructions in a tight loop
- Maintains a value stack and call frame stack
- Calls into builtins and AI runtime as needed
- Output: Program side effects (print, Reasoning calls, etc.)
Note: The original tree-walking interpreter (
src/interpreter.ts) is retained as a fallback execution path for any constructs not yet supported by the compiler.
Sesi uses lexical scoping with an environment chain:
┌─────────────────────────┐
│ Global Environment │
│ - Built-in functions │
│ - Global variables │
└────────┬────────────────┘
│
┌────▼────────────────┐
│ Function Environment│
│ - Parameters │
│ - Local variables │
└────┬────────────────┘
│
┌────▼────────────────┐
│ Block Environment │
│ - Block variables │
└─────────────────────┘
- Check current environment
- Walk up parent chain until found
- If not found anywhere, error
- Try to update in current scope
- If not in current scope, try parent scopes
- Update in the scope where variable was found
Sesi has a dynamic type system with runtime type checking:
RuntimeValue =
| number
| string
| boolean
| null
| Array<RuntimeValue>
| Object<string, RuntimeValue>
| RuntimeFunction
| RuntimeModule
String Concatenation (operator +):
"Hello" + 5 → "Hello5"
"Age:" 30 → "Age: 30"
any + string → toString(any) + string
string + any → string + toString(any)
Numeric Operations:
10 + 20 → 30
"10" + 20 → "1020" (not numeric!)
10 20 → "10 20" (not numeric!)
Truthiness:
null → false
false → false
0 → false
"" → false
[] → true
{} → true
- Initialization:
- Load @google/genai SDK
- Validate GEMINI_API_KEY environment variable
- During Execution:
- Parse model calls from AST
- Construct prompt from string concatenation
- Make async API call to Gemini
- Wait for response (blocking in v1.x)
- Validate finish reason and non-empty text
- Return text response to program or throw
- Memory Management:
- Simple string buffers per memory ID
- Append/update operations
- Passed to next model call
ModelCallExpression (AST)
│
├─ Evaluate prompt expression
├─ Extract configuration (`thinkingLevel`, `max_tokens`, `cache`, etc.)
├─ Call AIRuntime.callModel()
│ │
│ ├─ Create Gemini interaction request
│ ├─ Send to Gemini API
│ ├─ Wait for response
│ ├─ Validate finish reason == STOP
│ └─ Extract text from response
│
└─ Return text to program or throw
Sesi now has basic exception-style error handling in v1:
- Parse Errors: Parser logs the error and synchronizes to continue parsing later statements.
- Runtime Errors: Interpreter errors throw and can be caught with
try/catch. - Built-in I/O Errors:
read_file(),write_file(), andlist_dir()throw on filesystem failure. - Reasoning Errors:
model()throws when the SDK fails, when no text is returned. (Note:MAX_TOKENSfinish reasons are now handled natively via an automatic async polling loop that prompts the model to continue where it left off, and therefore does not throw errors). - Structured Output:
structured_output()attempts recovery, but currently logs parsing failures and returns{}if coercion still fails.
- Local variables
- Function parameters
- Scope frames
- Arrays (dynamic)
- Objects (key-value maps)
- Strings (immutable)
- Conversation memory per memory ID
- String buffers, not structured storage
| Operation | Time | Notes |
|---|---|---|
| Variable lookup | O(n) | n = scope depth |
| Array access | O(1) | Direct indexing |
| Object access | O(1) | Map lookup |
| Function call | O(1) | + body execution |
| Model call | ~2-5s | Depends on Gemini latency |
| Array iteration | O(n) | Foreach loop |
- VM Single-threaded: Each individual Sesi process is single-threaded.
- Process-level Concurrency: Sesi uses a multi-process model via
spawn()for concurrent task execution. - Bytecode coverage: The compiler covers expressions, loops, functions, closures, try/catch, and imports; edge-case constructs fall back to the tree-walking interpreter.
- No JIT: The VM executes bytecode directly; JIT compilation is a V4+ goal.
- Simple type system: Runtime checking only.
- No macro system: No compile-time code generation
- No introspection: Can't inspect function bodies
- Limited error info: Basic error messages
- Bytecode compiler (
src/compiler.ts) that lowers the AST to a flatChunk - Stack-based virtual machine (
src/vm.ts) with OpCode dispatch - Closures, loops, try/catch, and imports handled natively by the VM
- Legacy interpreter flag (
-t) to enable the tree-walking execution path - Streaming response support
- Advanced error handling with stack traces
- Agent framework with state machines
- Knowledge base integration
- Advanced memory with embedding search
- Multi-agent orchestration
- Custom type definitions
- Macro system
SKILLS.md # AI-agent workspace context and repo guardrails
eslint.config.mjs # ESLint configuration
dist/ # Compiled TypeScript output
example.js # Helper script to run basic examples
example-ai.js # Helper script to run Reasoning examples
examples.sesi # Central execution suite for examples
package.json # Dependencies & scripts
tsconfig.json # TypeScript configuration
QUICKSTART.md # Quick start guide
IMPLEMENTATION_SUMMARY.md # Progress and tracking
README.md # Project overview
src/
├── types.ts # Type definitions and AST
├── lexer.ts # Tokenization
├── parser.ts # AST generation
├── compiler.ts # AST → Bytecode compiler
├── chunk.ts # Bytecode Chunk & OpCode definitions
├── vm.ts # Bytecode virtual machine
├── interpreter.ts # Tree-walking interpreter (fallback)
├── ai-runtime.ts # Gemini integration
├── builtins.ts # Built-in functions
└── index.ts # Main entry point
bin/
└── sesi.js # CLI executable
main/ # Main user scripts and debugging
├── build_website.sesi # Sesi-generated landing page builder
└── tests/ # Additional syntax validation scripts
examples/
├── main/ # Core language & systems feature examples
│ ├── 01_hello.sesi # Hello World
│ ├── 02_variables.sesi # Variables & operations
│ ├── 03_functions.sesi # Functions with parameters
│ ├── 04_conditionals.sesi # If/else control flow
│ ├── 05_loops.sesi # While, for, for-in loops
│ ├── 06_arrays_objects.sesi # Collections
│ ├── 07_prompts.sesi # Prompt blocks composition
│ ├── 09_structured_output.sesi # Type-safe reasoning responses
│ ├── 11_memory_storage.sesi # Multi-turn stateful reasoning
│ ├── 12_classification.sesi # Systems classification loop
│ ├── 13_data_pipeline.sesi # Complete systems pipeline
│ ├── 16_modules.sesi # Modules & standard library imports
│ ├── 17_http_client.sesi # Native HTTP client (web_get/web_send)
│ ├── 18_parallel_requests.sesi # Parallel request concurrency (multi_req)
│ ├── 19_search_web.sesi # Built-in search_web integration
│ ├── 21_custom_tools.sesi # Declaring and using custom tools
│ ├── 23_file_conversion.sesi # File and format conversions
│ ├── 24_http_handler.sesi # Native HTTP server request routing
│ ├── 24_http_server.sesi # Non-blocking native HTTP server
│ ├── 25_webpage_server.sesi # Native webpage hosting
│ ├── 26_database.sesi # Embedded document database operations
│ ├── 27_robust_web_db.sesi # Dynamic database-backed web analytics
│ ├── 29_tool_piping.sesi # Functional piping operator (|)
│ ├── 30_error_recovery.sesi # Error retry backoff handling
│ ├── 31_synthesizer.sesi # Sound/music synthesis & SVG drawing
│ ├── 32_browser_automation.sesi # Headless browser automation with Playwright
│ ├── 33_base64.sesi # Base64
│ └── 34_sesi_api.sesi # SwaggerUI API setup
│
└── optional/ # Optional reasoning & advanced AI examples
│ ├── 08_model_call.sesi # Basic reasoning model calls
│ ├── 10_code_generation.sesi # Code generation logic
│ ├── 14_folder_explainer.sesi # Workspace directory analyzer
│ ├── 15_image_generation.sesi # Image generation API
│ ├── 20_model_aliases.sesi # Custom model naming aliases
│ ├── 22_reasoning_plus_custom_tools.sesi # Reasoning composed with custom tools
│ └── 28_streaming.sesi # Real-time response streaming
docs/
├── SPECIFICATION.md # Language spec
├── ARCHITECTURE.md # This file
├── BUILTINS.md # Built-in reference
├── CLI.md # Comprehensive CLI & Parametric Eval guide
├── IMAGE_GENERATION.md # Image generation guide
├── COMPARISON.md # Language comparison showcase
├── REASONING.md # Reasoning and simple logic guide
└── ROADMAP.md # Future plans
tests/
├── basic.test.ts # Core parsing & evaluation tests
├── cache.test.ts # Execution caching tests
├── http.test.ts # Web request builtins testing
├── module.test.ts # Imports & module loading tests
├── parallel.test.ts # Concurrent execution tests
├── security.test.ts # Sandbox & guardrail tests
├── test-gemini.ts # Base model integration test
├── test-gemini2.ts # Extended model integration test
└── workflow.test.ts # Complex sequence workflows tests
The root-level SKILLS.md file is part of the practical repo architecture. It is not consumed by the Sesi runtime, but it is intended to guide AI-assisted development in this workspace.
Unit Tests (per component):
// Lexer: tokenization correctness
// Parser: AST structure correctness
// Interpreter: evaluation correctness
// AI Runtime: Gemini integrationIntegration Tests:
// Full program execution
// Complex Reasoning workflows
// Error handlingExample Programs:
- Basic arithmetic and control flow
- Functions and scoping
- Arrays and objects
- Reasoning model calls
- Structured output parsing
- Memory-based conversations
Enable debug statement tracing:
SESI_DEBUG=1 sesi program.sesiPrint the pretty-printed AST tree:
sesi --ast program.sesiPrint the scanned token stream table:
sesi --tokens program.sesiSesi's architecture has evolved from a simple tree-walking interpreter to a dual-mode engine. The bytecode compiler + VM is now the primary execution path, delivering faster startup and lower per-instruction overhead. The tree-walking interpreter is retained as a well-understood fallback. Both paths share the same Lexer, Parser, builtins, and AI Runtime.
- High-throughput execution via bytecode VM
- Easy extensibility via the shared AST and builtin layer
- Smooth Reasoning integration regardless of execution path
As the language matures, JIT compilation and further VM optimizations can be added without changing the Sesi API.