Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Simple language pkglNew to Visual Studio Code? Get it now.
Simple language pkgl

Simple language pkgl

pkgllang

|
2 installs
| (0) | Free
Language support for pkgl - a multi-paradigm programming language with a WASM-style bytecode VM. Supports Java-style OOP (class, interface, extends, implements, this, super, instanceof, abstract, static, final, public/private/protected, ternary operator, type cast, for-each loop, switch/case/default
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

pkgl

pkgl is an original multi-paradigm programming language with a Python-like syntax and a WASM-inspired stack-based bytecode VM. The project ships as a TypeScript-compiled compiler + a VSCode extension that bundles the compiler for in-editor execution, diagnostics, syntax highlighting, and snippets.

pkgl/
├── package.json                 # VSCode extension manifest
├── tsconfig.json
├── language-configuration.json  # bracket / comment pairing rules
├── syntaxes/
│   └── pkgl.tmLanguage.json     # TextMate grammar for highlighting
├── snippets/
│   └── pkgl.json                # code templates
├── src/
│   ├── cli.ts                   # `pkglc` command-line compiler
│   ├── extension.ts             # VSCode extension entry
│   └── compiler/
│       ├── index.ts             # public API
│       ├── tokens.ts            # token types
│       ├── lexer.ts             # source -> tokens (handles INDENT/DEDENT)
│       ├── parser.ts            # tokens -> AST
│       ├── ast.ts               # AST node definitions
│       ├── bytecode.ts          # Op enum, Module, disassembler
│       ├── codegen.ts           # AST -> bytecode
│       ├── vm.ts                # stack-based bytecode VM
│       ├── runtime.ts           # Value types (array, map, struct, ...)
│       ├── builtins.ts          # print, range, len, read_file, ...
│       └── errors.ts            # PkglError + location helpers
├── samples/
│   ├── hello.pkgl
│   ├── fizzbuzz.pkgl
│   ├── functions.pkgl
│   ├── struct.pkgl
│   └── fileio.pkgl
└── build/                       # compiled JS output (gitignore in real use)

Quick start

Build

cd pkgl
npm install
npm run build          # tsc -> ./build/

Run a program (CLI)

node ./build/cli.js samples/fizzbuzz.pkgl
node ./build/cli.js samples/struct.pkgl --disasm     # show bytecode
node ./build/cli.js --help

Install the VSCode extension

This project does not pre-package a .vsix. To use it as an extension during development:

  1. Open the pkgl/ folder in VSCode.
  2. Press F5 to launch an Extension Development Host.
  3. In the host window, open any .pkgl file (try samples/struct.pkgl).
  4. Press F5 again (or run pkgl: Run File from the Command Palette) to compile and execute the file. Output appears in the pkgl output channel.

To produce a distributable .vsix, run:

npm install -g @vscode/vsce
vsce package
# -> pkgl-0.1.0.vsix

Then install with code --install-extension pkgl-0.1.0.vsix.


Language tour

Variables

let x = 10              # immutable binding
mut counter = 0         # mutable binding
counter += 1            # compound assignment
let name: string = "pkgl"   # with type annotation

Functions

func factorial(n: int) -> int:
    if n <= 1:
        return 1
    return n * factorial(n - 1)

# First-class functions + lambdas
let double = func(x):
    return x * 2

print(double(21))           # 42

Control flow

if x > 0:
    print("positive")
elif x == 0:
    print("zero")
else:
    print("negative")

while counter < 10:
    counter += 1

for i in range(5):
    print(i)

for ch in "hello":
    print(ch)

Data structures

let arr = [1, 2, 3]
arr.push(4)
print(arr[0], arr.len())

let m = {"alice": 90, "bob": 75}
for name in m:
    print(name, "->", m[name])

Structs and methods

struct Point:
    x: int
    y: int

    func magnitude(self) -> float:
        return sqrt(self.x * self.x + self.y * self.y)

    func translate(self, dx: int, dy: int) -> Point:
        return Point { x: self.x + dx, y: self.y + dy }

let p = Point { x: 3, y: 4 }
print(p.magnitude())          # 5
print(p.translate(10, 0).x)   # 13

Error handling

try:
    let data = read_file("missing.txt")
catch err:
    print("Failed:", err)

# Custom throw
func divide(a, b):
    if b == 0:
        throw "division by zero"
    return a / b

Comments

# Line comment

/* Block comment
   spanning multiple lines */

Built-in functions

Category Functions
I/O print, println, input, read_file, write_file, append_file
Collections len, range, push, pop, keys, values, has, get
Math sqrt, abs, min, max, sum, floor, ceil
Conversion int, float, str, bool, type
Strings split, join, char_at

Operators

Category Operators
Arithmetic + - * / % **
Comparison == != < <= > >=
Logical and or not
Bitwise & \| ^ ~ << >>
Assignment = += -= *= /=

Bytecode VM

The compiler emits a flat bytecode module containing:

  • A pool of int / float / string constants.
  • A list of function metas (each with its own instruction stream).
  • A list of struct type metas.
  • A list of globals (function refs and builtins).

The VM is a stack machine with per-frame value stack and local slots. Exceptions are implemented with a per-frame try-handler stack. There is a configurable step limit (default 10,000,000) to guard against infinite loops.

Use --disasm to inspect the bytecode:

$ node ./build/cli.js samples/struct.pkgl --disasm | head -30
=== pkgl bytecode module ===
functions: 7, structs: 2
int pool: [0, 3, 4, 10, 20, 30, 1]
...
---- function 0: main (params=0, locals=10) ----
     0  PushInt      #1 = 3
     1  PushInt      #2 = 4
     2  MakeStruct   Point
     3  StoreLocal   slot 0
     ...

VSCode extension features

Feature How
Syntax highlighting TextMate grammar at syntaxes/pkgl.tmLanguage.json — includes do/new keywords, GLFW builtins, C-style function declarations, property access, named-arg patterns
Snippets snippets/pkgl.json — try glfwwindow, cfn, do, new, import-file, glfwcreatewindow, dialog, named-id, named-fullsc, frontmost, plus all the originals (fn, if-elif, try, ...)
Bracket / comment pairing language-configuration.json — also auto-indents after do (x) {, new T(...) {, and int foo(...) {
Run file Command pkgl: Run File or press F5 in a .pkgl file
Run file (GLFW) Command pkgl: Run File (with GLFW) or press Shift+F5 — auto-enables the GLFW library and resolves import (file, "x.ph") headers
Show bytecode Command pkgl: Show Bytecode
Live diagnostics Real-time parse + compile errors in the Problems pane; respects import (file, "x.ph") header resolution
Status bar Click pkgl in the status bar to run the current file

Settings

Setting Default Description
pkgl.diagnostics.enabled true Enable live syntax diagnostics.
pkgl.run.showBytecode false Also print disassembled bytecode when running.
pkgl.run.maxSteps 10000000 VM step limit (infinite-loop guard).
pkgl.run.libglfw false Enable the GLFW builtins when running a file. Equivalent to passing -libglfw to compkg.
pkgl.run.headerSearchPaths [] Extra directories to search for .ph header files (e.g. pkglGLFW.ph). Searched in addition to the source file's directory and the workspace root.

Header file resolution in the extension

When a source file contains import (file, "pkglGLFW.ph"), the extension automatically:

  1. Searches the source file's directory, then every workspace folder, then every entry in pkgl.run.headerSearchPaths.
  2. Parses the .ph file for fn <name>( and <type> <name>( declarations.
  3. Passes the discovered function names to compile() as glfwBuiltins.
  4. Auto-enables libglfw if the file name contains glfw (case-insensitive).

If the header file is missing, a warning is shown in the pkgl output channel (compile-time, not a hard error — so the rest of the file can still be diagnosed).


Architecture notes

  • Lexer (src/compiler/lexer.ts): Produces INDENT/DEDENT/NEWLINE tokens in addition to the usual lexical tokens, following Python's off-side rule. Parentheses, brackets, and braces suppress newlines.
  • Parser (src/compiler/parser.ts): Recursive-descent with precedence climbing for expressions. Block bodies end with a DEDENT token; the parser tracks a justFinishedBlock flag so a lambda body inside an outer statement does not require a redundant trailing newline.
  • Codegen (src/compiler/codegen.ts): Single-pass compilation. Each function gets its own instruction stream. Local slots are allocated sequentially. Jumps are emitted as placeholders and back-patched.
  • VM (src/compiler/vm.ts): Per-frame instruction pointer and try-handler stack. Exceptions propagate across frames via a pendingException field.

Limitations / future work

  • No type checker (type annotations are parsed but not enforced).
  • No upvalues / captured variables in lambdas (lambdas can only reference their own params and globals).
  • Module imports are limited to import (file, "x.ph") (header-file form, used to load builtin function declarations) and import moduleName (declarative only — does not load external source files).
  • No async / concurrency.
  • Integer / float distinction is loose (both are JS numbers).
  • for loop iteration order over maps is insertion order (ES Map).

License

MIT - see headers in source files.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft