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

Terminal
git clone https://github.com/darthvader58/knockscript.git
cd knockscript
bundle install
Prerequisite: Ruby 3.2.0 or higher.

Quick Start

Run an example from the command line:

CLI
ruby knockscript.rb examples/hello_world.ks

Or launch the browser compiler:

Web
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:

hello_world.ks
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 extraAddition
withoutSubtraction
on repeatMultiplication
split byDivision
greater thanComparison
less thanComparison
equal toComparison
not equal toComparison
NopeBoolean 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 listlist with 1, 2, 3Literal array value
AppendSherwood who? value to listPush to end
PopIva who? from listRemove last element
Set indexPatcha who? 0 of list to valueReplace element
Get indexWhichy 0 from listRead element
LengthHowie listArray length
ContainsDosset Dave value in listMembership 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 dictionaryOxford with name "Alice" and age 30Literal key-value map
Lookup keyKeysy age from personRead a value
Set keySlotta who? age of person to 31Insert or update a value
Contains keyDosset Dave age in personCheck whether the key exists
Remove keySkipper who? age from personDelete 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

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.

# This line is ignored
Knock knock
Who's there?
Lettuce
Lettuce who? "Commented code still works."

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, and Carryon.
  • 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
PrintLettuce who? expressionOutput a value
AssignAlby-Setin who? name to expressionStore a variable value
IfAnita who? conditionConditional branching
Else ifAnita also conditionSecondary conditional branch
WhileAntil who? conditionLoop while condition is true
ForWanna who? i from 1 to 5Numeric loop
BreakEnough who?Exit current loop
ContinueCarryon who?Skip to next loop iteration
FunctionDoozy who? name with a and bDefine a function
ReturnBackatcha who? expressionReturn a value
ClassKit who? Person with name and ageDefine a class
MethodDewey who? greet for PersonDefine a class method
CallEurope who? greet on personCall method or function
Get attributeJustin who? age from personRead an object attribute
List literallist with 1, 2, 3Create an array
Dictionary literalOxford with name "Alice"Create a key-value map
InputAskem "Prompt"Request user input
TryChance who?Start protected block
CatchUnluckyHandle runtime failure