KnockScript Documentation
KnockScript is a toy programming language where every statement is delivered as a lame knock-knock joke. If you get it, you get it.
So Knock Knock Messieur et Mesdames!
Getting Started
KnockScript is easiest to understand if you treat it as a normal interpreted language with a joke-shaped syntax layer. Variables, functions, classes, lists, dictionaries, loops, input, and error handling are all real features. The joke words are just the surface syntax.
This page explains the mental model first, then walks feature by feature with examples that show what the code is doing and why the syntax is shaped the way it is.
Installation
git clone https://github.com/darthvader58/knockscript.git
cd knockscript
bundle install
Quick Start
Run an example from the command line:
ruby knockscript.rb examples/hello_world.ks
Or launch the browser compiler:
ruby web/app.rb
# Visit http://localhost:4567
Language Model
The fastest way to understand KnockScript is: every statement has a setup line, a response line, a command line, and a payload line. The payload line is the part that carries the actual meaning.
Statement Shape
Most statements look like this:
Knock knock
Who's there?
[Command]
[Command] who? [arguments or expression]
Example:
Knock knock
Who's there?
Lettuce
Lettuce who? "Hello!"
`Lettuce` is the command name. `"Hello!"` is the payload. The interpreter ignores the joke framing and executes the command.
The Full Joke
Since the language insists on the joke frame, the docs should at least show the whole thing once:
Knock knock.
Who's there?
Lettuce.
Lettuce who?
Lettuce write some code.
KnockScript effectively turns that structure into a programming template.
Hello World
This is the smallest useful program:
Knock knock
Who's there?
Lettuce
Lettuce who? "Hello, World!"
Lettuce means “print this expression.” If you know how to print, you already understand the general shape of the language.
Variables & Output
Use Alby-Setin to assign a value to a variable and Lettuce to display it.
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? score to 42
Knock knock
Who's there?
Lettuce
Lettuce who? score
The right-hand side of an assignment can be a literal, another variable, a function call, a list lookup, a dictionary lookup, or a full arithmetic expression.
Arithmetic, Comparisons, and Boolean Logic
KnockScript uses readable phrase operators instead of symbols in source code.
| Phrase | Meaning |
|---|---|
with extra | Addition |
without | Subtraction |
on repeat | Multiplication |
split by | Division |
greater than | Comparison |
less than | Comparison |
equal to | Comparison |
not equal to | Comparison |
Nope | Boolean negation |
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? total to 10 with extra 5 on repeat 2
Knock knock
Who's there?
Lettuce
Lettuce who? total
Knock knock
Who's there?
Lettuce
Lettuce who? Nope false
Operator precedence follows the normal arithmetic expectation: multiplication and division bind tighter than addition and subtraction.
Conditionals
Anita starts an if block. Anita also behaves like else if. Otherwise is the final fallback. Done closes the entire conditional.
Knock knock
Who's there?
Anita
Anita who? temp greater than 90
Knock knock
Who's there?
Lettuce
Lettuce who? "hot"
Anita also temp equal to 90
Knock knock
Who's there?
Lettuce
Lettuce who? "exactly ninety"
Otherwise
Knock knock
Who's there?
Lettuce
Lettuce who? "not hot"
Done
Mentally, read the payload line as the real syntax: “if temp is greater than 90, do these statements.”
Loops
Antil is a while loop. Wanna is a numeric for loop. Enough breaks out of a loop and Carryon skips to the next iteration.
While Loop
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? counter to 1
Knock knock
Who's there?
Antil
Antil who? counter less than 4
Knock knock
Who's there?
Lettuce
Lettuce who? counter
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? counter to counter with extra 1
Done
For Loop
Knock knock
Who's there?
Wanna
Wanna who? i from 1 to 5
Knock knock
Who's there?
Lettuce
Lettuce who? i
Done
Break / Continue
Knock knock
Who's there?
Wanna
Wanna who? i from 1 to 6
Knock knock
Who's there?
Anita
Anita who? i equal to 2
Knock knock
Who's there?
Carryon
Carryon who?
Anita also i equal to 5
Knock knock
Who's there?
Enough
Enough who?
Otherwise
Knock knock
Who's there?
Lettuce
Lettuce who? i
Done
Done
Functions and Return Values
Doozy defines a standalone function. Backatcha returns a value. Europe can call both standalone functions and object methods.
Knock knock
Who's there?
Doozy
Doozy who? addTax with amount and rate
Knock knock
Who's there?
Backatcha
Backatcha who? amount with extra amount on repeat rate
Done
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? total to Europe addTax with 80 and 0.1
Knock knock
Who's there?
Lettuce
Lettuce who? total
The parameters are introduced after with and separated by and. If a function does not return explicitly, its result is nil.
Classes, Methods, Objects, and Attributes
Kit defines a class with named attributes. Fresh creates an instance. Dewey defines a method. Europe calls a method on an object. Justin reads an attribute, and Alby-Setin can also update an attribute directly.
Knock knock
Who's there?
Kit
Kit who? Person with name and age
Knock knock
Who's there?
Dewey
Dewey who? greet for Person
Knock knock
Who's there?
Lettuce
Lettuce who? "Hello, my name is "
Knock knock
Who's there?
Lettuce
Lettuce who? name
Done
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? alice to Fresh Person with name "Alice" and age 30
Knock knock
Who's there?
Europe
Europe who? greet on alice
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? age of alice to 31
Within a method body, attributes behave like local variables. Updating age inside the method updates the object’s attribute when the method finishes.
Lists / Arrays
KnockScript’s array literal is list with. It supports appending, removing from the end, replacing an index, reading an index, checking length, and checking containment.
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? numbers to list with 3, 6, 9
Knock knock
Who's there?
Sherwood
Sherwood who? 12 to numbers
Knock knock
Who's there?
Patcha
Patcha who? 1 of numbers to 99
Knock knock
Who's there?
Lettuce
Lettuce who? Whichy 1 from numbers
Knock knock
Who's there?
Lettuce
Lettuce who? Howie numbers
Knock knock
Who's there?
Lettuce
Lettuce who? Dosset Dave 99 in numbers
Knock knock
Who's there?
Iva
Iva who? from numbers
| Feature | Syntax | Meaning |
|---|---|---|
| Create list | list with 1, 2, 3 | Literal array value |
| Append | Sherwood who? value to list | Push to end |
| Pop | Iva who? from list | Remove last element |
| Set index | Patcha who? 0 of list to value | Replace element |
| Get index | Whichy 0 from list | Read element |
| Length | Howie list | Array length |
| Contains | Dosset Dave value in list | Membership check |
Dictionaries
Dictionaries are key-value maps. In KnockScript, you create one with Oxford. You read a key with Keysy, update a key with Slotta, check key existence with Dosset Dave, and remove a key with Skipper.
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? person to Oxford with name "Alice" and age 30
Knock knock
Who's there?
Lettuce
Lettuce who? Keysy name from person
Knock knock
Who's there?
Slotta
Slotta who? city of person to "Phoenix"
Knock knock
Who's there?
Lettuce
Lettuce who? Dosset Dave age in person
Knock knock
Who's there?
Skipper
Skipper who? age from person
Knock knock
Who's there?
Lettuce
Lettuce who? person
Dictionary keys are usually written as bare words like name or age. Values can be strings, numbers, booleans, lists, function results, or any other expression.
| Feature | Syntax | Meaning |
|---|---|---|
| Create dictionary | Oxford with name "Alice" and age 30 | Literal key-value map |
| Lookup key | Keysy age from person | Read a value |
| Set key | Slotta who? age of person to 31 | Insert or update a value |
| Contains key | Dosset Dave age in person | Check whether the key exists |
| Remove key | Skipper who? age from person | Delete a key from the dictionary |
If you are coming from JavaScript, think “object literal.” If you are coming from Python, think “dict.” If you are coming from Ruby, think “hash.”
Input and Error Handling
Askem prompts the user for input. Chance starts a protected block. Unlucky handles runtime errors from the protected block. This works in both CLI mode and the web compiler.
Knock knock
Who's there?
Alby-Setin
Alby-Setin who? name to Askem "What is your name?"
Knock knock
Who's there?
Chance
Chance who?
Knock knock
Who's there?
Lettuce
Lettuce who? "Hello, "
Knock knock
Who's there?
Lettuce
Lettuce who? name
Knock knock
Who's there?
Lettuce
Lettuce who? 10 split by 0
Unlucky
Knock knock
Who's there?
Lettuce
Lettuce who? "That went sideways."
Done
Worked Examples
The examples shipped with the repo are designed to highlight specific parts of the language.
examples/hello_world.ks: the minimum valid program.examples/classes.ks: classes, methods, instance creation, method calls, and attribute updates.examples/functions.ks: parameters and return values.examples/collections.ks: both lists and dictionaries.examples/flow_control.ks: loops,Anita also,Enough, andCarryon.examples/input_and_errors.ks: interactive input and try/catch behavior.
Feature Summary
Readable Joke Syntax
Every feature is wrapped in a consistent knock-knock frame.
Expressions
Arithmetic, comparisons, booleans, function calls, list lookups, and dictionary lookups.
Control Flow
If/else-if/else, while, for, break, continue, and try/catch.
Structured Data
Lists with indexing and dictionaries with key-based lookup.
Reusable Code
Standalone functions, methods, parameters, and explicit returns.
Interactive Runner
CLI and web compiler both support input-driven programs.
Project Structure
knockscript/
├── knockscript.rb # Main CLI entry point
├── lexer.rb # Tokenizes KnockScript source code
├── parser.rb # Turns tokens into an AST
├── interpreter.rb # Executes programs
├── ast_nodes.rb # AST node definitions
├── environment.rb # Variables, classes, and objects
├── examples/ # Runnable language examples
├── web/ # Sinatra app + browser UI
└── Dockerfile # Container image definition
Syntax Reference
| Feature | Primary Syntax | Purpose |
|---|---|---|
Lettuce who? expression | Output a value | |
| Assign | Alby-Setin who? name to expression | Store a variable value |
| If | Anita who? condition | Conditional branching |
| Else if | Anita also condition | Secondary conditional branch |
| While | Antil who? condition | Loop while condition is true |
| For | Wanna who? i from 1 to 5 | Numeric loop |
| Break | Enough who? | Exit current loop |
| Continue | Carryon who? | Skip to next loop iteration |
| Function | Doozy who? name with a and b | Define a function |
| Return | Backatcha who? expression | Return a value |
| Class | Kit who? Person with name and age | Define a class |
| Method | Dewey who? greet for Person | Define a class method |
| Call | Europe who? greet on person | Call method or function |
| Get attribute | Justin who? age from person | Read an object attribute |
| List literal | list with 1, 2, 3 | Create an array |
| Dictionary literal | Oxford with name "Alice" | Create a key-value map |
| Input | Askem "Prompt" | Request user input |
| Try | Chance who? | Start protected block |
| Catch | Unlucky | Handle runtime failure |
Comments
Single-line comments begin with
#. Use them to annotate examples or explain the punchline when the joke name is not obvious at first glance.