Complete reference for the TempleCode programming language — a fusion of BASIC, PILOT, and Logo that has grown from educational roots into a practical, modern programming language.
File Extension: .tc
Executor: TempleCodeExecutor in core/languages/templecode.py
- Overview
- BASIC Commands
- PILOT Commands
- Logo Turtle Graphics
- Variables & Data Types
- Operators
- String Functions
- Math Functions
- Control Flow
- Procedures & Functions
- Lists (Dynamic Arrays)
- Dictionaries (Maps)
- File I/O
- Error Handling
- Functional Programming
- JSON Support
- Regular Expressions
- Structs & Enums
- Constants & Type System
- Modules (IMPORT)
- Formatted Output
- Mixing Styles
- Example Programs
TempleCode is a unified language that blends three classic educational languages and extends them with modern programming features:
| Heritage | Era | What it contributes |
|---|---|---|
| BASIC | 1964 | Variables, arithmetic, control flow, I/O, line numbers |
| PILOT | 1968 | Interactive text output, input, pattern matching, labels |
| Logo | 1967 | Turtle graphics, visual drawing, procedures |
| Modern | 2025+ | Functions, lists, dicts, file I/O, JSON, regex, error handling |
All styles can be freely mixed in a single .tc program. The interpreter auto-detects which sub-system handles each line.
Output text or expressions to the console.
PRINT "Hello, World!"
PRINT 2 + 3
PRINT "Name: "; nameAssign a value to a variable.
LET x = 10
LET name = "Alice"
LET result = x * 2 + 5Read user input into a variable.
INPUT "Enter your name: "; name
INPUT xConditional execution (single-line and block forms).
IF x > 10 THEN PRINT "Big"
IF x > 10 THEN
PRINT "Big"
ELSEIF x > 5 THEN
PRINT "Medium"
ELSE
PRINT "Small"
END IFCounted loop.
FOR i = 1 TO 10
PRINT i
NEXT i
FOR j = 10 TO 1 STEP -1
PRINT j
NEXT jWHILE x < 100
LET x = x * 2
WENDDO WHILE x < 100
LET x = x + 1
LOOP
DO
LET x = x + 1
LOOP UNTIL x >= 100WRITE "Progress: "
WRITELN "Done"
LET x = 5
INC x
DEC x
PRINT SQR(x)
PRINT ROUND(3.7)
PRINT TRUNC(3.7)
PRINT PARAMCOUNT()
PRINT PARAMSTR(1)
READLN xASSERTZ "parent(john, mary)"
ASSERTA "parent(mary, susan)"
QUERY "parent(john, mary)" // TRUE
RETRACT "parent(john, mary)"
FACTSLOAD "data.txt", CONTENT
SAVE "output.txt", "hello"
CHAIN "startup.tc", PROGRAM
PAUSE 500
PRINT INKEY()SELECT CASE grade
CASE "A"
PRINT "Excellent!"
CASE "B"
PRINT "Good"
CASE ELSE
PRINT "Keep trying"
END SELECT10 PRINT "Hello"
20 GOTO 10
100 GOSUB 500
110 END
500 PRINT "In subroutine"
510 RETURNDeclare an array.
DIM numbers(10)
LET numbers(1) = 42Embed data values in the program.
DATA 10, 20, 30, "Hello"
READ A
READ B
READ C
READ D$
RESTORESWAP A, B
INCR counter
DECR lives, 2Break out of a loop.
EXIT FOR
EXIT WHILE
EXIT DOBreak out of a FOREACH or other loop.
FOREACH item IN mylist
IF item = "stop" THEN BREAK
NEXT item| Command | Description |
|---|---|
CLS |
Clear the output screen |
BEEP |
Emit a system bell |
DELAY n |
Pause for n milliseconds |
SLEEP n |
Pause for n seconds |
TAB n |
Move to column n |
SPC n |
Print n spaces |
UNSET var |
Remove variable/list/dict from scope |
EVAL expr [AS var] |
Evaluate an expression dynamically |
PROGRAMINFO |
Print runtime program info (lines, variables, arrays, dicts) |
REM / ' |
Comment |
END |
End program execution |
STOP |
Stop program execution |
RANDOMIZE TIMER |
Seed the random number generator |
PILOT commands use a single letter followed by a colon. They are ideal for interactive lessons and quizzes.
| Command | Description |
|---|---|
T:text |
Type / print text (with $VAR interpolation) |
A: / A:prompt |
Accept user input (numeric strings are auto-converted to numbers) |
M:pattern |
Match input against pattern(s) |
Y:command |
Execute if last match succeeded |
N:command |
Execute if last match failed |
J:label |
Jump to label |
C:expr / C:*label |
Compute expression or call subroutine |
E: |
End program/subroutine |
R:text |
Remark (comment) |
U:var=expr |
Use / set variable |
L:label |
Label definition |
G:command |
Graphics (inline turtle command) |
S:OP var |
String operation (UPPER, LOWER, LEN, REVERSE, TRIM) |
D:ARR(n) |
Dimension an array |
P:ms |
Pause for milliseconds |
X:command |
Execute BASIC or Logo command |
When the user enters a value via A:, the input is automatically converted to a number if it looks numeric. This means you can use ANSWER directly in arithmetic without calling TONUM():
T:How many seconds to count down?
A:
C:SECONDS = ANSWER
If the input is "10", ANSWER will hold the integer 10, not the string "10". Non-numeric text remains a string. This matches the behaviour of the BASIC INPUT command.
*start
T:Welcome!
J:start
| Command | Alias | Description |
|---|---|---|
FORWARD n |
FD n |
Move forward n pixels |
BACK n |
BK n |
Move backward n pixels |
LEFT n |
LT n |
Turn left n degrees |
RIGHT n |
RT n |
Turn right n degrees |
HOME |
Return to center, heading north | |
SETXY x y |
SETPOS |
Move to position (x, y) |
SETX x |
Set x coordinate | |
SETY y |
Set y coordinate | |
SETHEADING n |
SETH n |
Set heading in degrees |
TOWARDS x y |
Point towards (x, y) |
| Command | Alias | Description |
|---|---|---|
PENUP |
PU |
Lift pen (stop drawing) |
PENDOWN |
PD |
Lower pen (start drawing) |
SETCOLOR name |
SETPC |
Set pen color |
SETPENSIZE n |
SETWIDTH |
Set pen width |
SETFILLCOLOR color |
SETFC |
Set fill color |
SETBACKGROUND color |
SETBG |
Set background color |
SHOWTURTLE |
ST |
Show the turtle cursor |
HIDETURTLE |
HT |
Hide the turtle cursor |
| Command | Description |
|---|---|
CIRCLE r |
Draw circle with radius r |
CIRCLEFILL r |
Draw filled circle with radius r |
ARC angle [radius] |
Draw an arc |
DOT [size] |
Draw a dot |
SQUARE side |
Draw a square |
TRIANGLE side |
Draw equilateral triangle |
POLYGON sides length |
Draw regular polygon |
STAR points length |
Draw a star |
RECT width [height] |
Draw rectangle |
RECTANGLE width [height] |
Alias for RECT |
RECTFILL width [height] |
Draw filled rectangle |
PSET x,y |
Set pixel at coordinates to pen color |
PRESET x,y |
Reset pixel at coordinates to background color |
POINT x,y |
Returns 1 if point is on screen, else 0 |
LABEL "text" [size] |
Draw text at turtle position |
REPEAT 4 [FORWARD 100 RIGHT 90]
REPEAT 36 [FORWARD 10 RIGHT 10]
TO SQUARE :size
REPEAT 4 [FORWARD :size RIGHT 90]
END
SQUARE 100
| Type | Examples |
|---|---|
| Integer | 42, -7, 0 |
| Float | 3.14, -0.5 |
| String | "Hello", "world" |
| List | Created with LIST command |
| Dictionary | Created with DICT command |
Mathematical constants available in expressions:
| Constant | Value |
|---|---|
PI |
3.14159265... |
E |
2.71828182... |
TAU |
6.28318530... (2π) |
INF |
Infinity |
| Variable | Description |
|---|---|
TIMER |
Seconds since program start |
DATE$ |
Current date (YYYY-MM-DD) |
TIME$ |
Current time (HH:MM:SS) |
RESULT |
Return value of last FUNCTION call |
ERROR$ |
Message from last caught error |
EOF |
End-of-file flag (1 = end reached) |
| Operator | Description |
|---|---|
+ |
Addition / string concatenation |
- |
Subtraction |
* |
Multiplication |
/ |
Division |
MOD |
Modulo (remainder) |
^ |
Exponentiation |
| Operator | Description |
|---|---|
= / == |
Equal to |
<> / != |
Not equal to |
< |
Less than |
> |
Greater than |
<= |
Less than or equal |
>= |
Greater than or equal |
| Operator | Description |
|---|---|
AND |
Logical AND |
OR |
Logical OR |
NOT |
Logical NOT |
| Function | Description | Example |
|---|---|---|
LEN(s) |
Length of string | LEN("Hello") → 5 |
LEFT$(s, n) |
First n characters | LEFT$("Hello", 3) → "Hel" |
RIGHT$(s, n) |
Last n characters | RIGHT$("Hello", 3) → "llo" |
MID$(s, pos, n) |
Substring | MID$("Hello", 2, 3) → "ell" |
UCASE$(s) |
Uppercase | UCASE$("hello") → "HELLO" |
LCASE$(s) |
Lowercase | LCASE$("HELLO") → "hello" |
INSTR(s, sub) |
Find substring (1-based) | INSTR("Hello", "ll") → 3 |
STR$(n) |
Number to string | STR$(42) → "42" |
VAL(s) |
String to number | VAL("42") → 42 |
CHR$(n) |
ASCII code to character | CHR$(65) → "A" |
ASC(s) |
Character to ASCII code | ASC("A") → 65 |
| Function | Description | Example |
|---|---|---|
TRIM$(s) |
Remove leading/trailing whitespace | TRIM$(" hi ") → "hi" |
REPLACE$(s, old, new) |
Replace occurrences | REPLACE$("hello", "l", "r") → "herro" |
STARTSWITH(s, prefix) |
Check prefix (1/0) | STARTSWITH("Hello", "He") → 1 |
ENDSWITH(s, suffix) |
Check suffix (1/0) | ENDSWITH("Hello", "lo") → 1 |
CONTAINS(s, sub) |
Check contains (1/0) | CONTAINS("Hello", "ell") → 1 |
REPEAT$(s, n) |
Repeat string n times | REPEAT$("ab", 3) → "ababab" |
FORMAT$(val, spec) |
Format a value | FORMAT$(3.14159, ".2f") → "3.14" |
SPLIT(s, delim) |
Split into list | SPLIT("a,b,c", ",") → list |
JOIN(list, delim) |
Join list to string | JOIN(ITEMS, ", ") → string |
| Function | Description |
|---|---|
ABS(x) |
Absolute value |
INT(x) |
Integer part (truncate) |
SQR(x) / SQRT(x) |
Square root |
SIN(x) / COS(x) / TAN(x) |
Trigonometry (radians) |
ATN(x) / ATAN(x) |
Arctangent |
LOG(x) |
Natural logarithm |
EXP(x) |
e^x |
RND / RND(n) |
Random number (0–1 or 1–n) |
SGN(x) |
Sign (-1, 0, 1) |
CEIL(x) |
Ceiling |
FIX(x) |
Truncate towards zero |
| Function | Description | Example |
|---|---|---|
ROUND(x [, d]) |
Round to d decimal places | ROUND(3.456, 2) → 3.46 |
FLOOR(x) |
Floor (round down) | FLOOR(3.7) → 3 |
POWER(base, exp) |
Exponentiation | POWER(2, 10) → 1024 |
CLAMP(x, lo, hi) |
Constrain to range | CLAMP(15, 0, 10) → 10 |
LERP(a, b, t) |
Linear interpolation | LERP(0, 100, 0.5) → 50 |
RANDOM(lo, hi) |
Random integer in range | RANDOM(1, 6) → 1–6 |
LOG2(x) |
Log base 2 | LOG2(256) → 8 |
LOG10(x) |
Log base 10 | LOG10(1000) → 3 |
EXP2(x) |
2^x | EXP2(8) → 256 |
| Function | Description |
|---|---|
BIN(n) |
Integer to binary string |
OCT(n) |
Integer to octal string |
HEX(n) |
Integer to hex string |
TONUM(s) |
Convert to number |
TOSTR(x) |
Convert to string |
IF x > 0 THEN PRINT "Positive"
IF x > 0 THEN PRINT "yes" ELSE PRINT "no"IF score >= 90 THEN
PRINT "A"
ELSEIF score >= 80 THEN
PRINT "B"
ELSEIF score >= 70 THEN
PRINT "C"
ELSE
PRINT "F"
END IFFOR i = 1 TO 10 STEP 2
PRINT i
NEXT iIterate over lists or dictionaries.
LIST items = "apple", "banana", "cherry"
FOREACH item IN items
PRINT item
NEXT item
DICT scores = "Alice":95, "Bob":82
FOREACH name, score IN scores
PRINT name; " = "; score
NEXT nameWHILE condition
REM body
WENDDO WHILE condition
REM body
LOOP
DO
REM body
LOOP UNTIL conditionSELECT CASE x
CASE 1
PRINT "One"
CASE 2
PRINT "Two"
CASE ELSE
PRINT "Other"
END SELECTON choice GOTO label1, label2, label3
ON choice GOSUB sub1, sub2, sub3REPEAT 4 [FORWARD 100 RIGHT 90]
SUB Greet(name)
PRINT "Hello, "; name; "!"
PRINT "Welcome!"
END SUB
CALL Greet("Alice")
CALL Greet("Bob")FUNCTION Double(x)
RETURN x * 2
END FUNCTION
LET result = Double(21)
PRINT result ' prints 42FUNCTION Factorial(n)
IF n <= 1 THEN RETURN 1
RETURN n * Factorial(n - 1)
END FUNCTION
PRINT Factorial(10)LAMBDA Square(x) = x * x
LAMBDA Add(a, b) = a + b
PRINT Square(5) ' prints 25
PRINT Add(10, 20) ' prints 30CALL MySub(arg1, arg2)
LET result = MyFunc(arg1)TO HEXAGON :size
REPEAT 6 [FORWARD :size RIGHT 60]
END
HEXAGON 80
GOSUB MySub
END
MySub:
PRINT "In subroutine"
RETURNLists are ordered, resizable collections that can hold mixed types.
LIST fruits = "apple", "banana", "cherry"
LIST empty
LIST numbers = 1, 2, 3, 4, 5| Command | Description | Example |
|---|---|---|
PUSH lst, val |
Append to end | PUSH fruits, "date" |
POP lst [, var] |
Remove from end | POP fruits, last |
UNSHIFT lst, val |
Prepend to front | UNSHIFT fruits, "avocado" |
SHIFT lst [, var] |
Remove from front | SHIFT fruits, first |
SPLICE lst, i, n |
Remove n items at index i | SPLICE fruits, 1, 2 |
SORT lst [DESC] |
Sort in place | SORT numbers DESC |
REVERSE lst |
Reverse in place | REVERSE fruits |
| Function | Description |
|---|---|
LENGTH(lst) |
Number of elements |
INDEXOF(lst, val) |
Index of value (-1 if not found) |
CONTAINS(lst, val) |
Check membership (1/0) |
SLICE(lst, start, end) |
Extract sub-list |
JOIN(lst, delim) |
Join elements into string |
LIST scores = 95, 82, 91, 78, 88
FOREACH score IN scores
PRINT score
NEXT scoreLET fruits[0] = "apricot"After modifying a list, LISTNAME_LENGTH is automatically set:
PUSH items, "new"
PRINT items_LENGTH ' prints updated lengthDictionaries store key-value pairs.
DICT config = "theme":"dark", "fontSize":"14"
DICT emptySET config.language = "en"
SET config, "maxLines", "1000"
GET config.theme INTO myTheme
GET config, "fontSize", mySize
DELETE config.maxLines
DELETE config, "fontSize"| Function | Description |
|---|---|
LENGTH(dict) |
Number of keys |
HASKEY(dict, key) |
Check if key exists (1/0) |
KEYS(dict) |
Get list of keys |
VALUES(dict) |
Get list of values |
FOREACH key, value IN config
PRINT key; " = "; value
NEXT keyOPEN "data.txt" FOR INPUT AS #1
READLINE #1, line$
CLOSE #1
OPEN "output.txt" FOR OUTPUT AS #2
WRITELINE #2, "Hello, file!"
CLOSE #2
OPEN "log.txt" FOR APPEND AS #3
WRITELINE #3, "New log entry"
CLOSE #3WRITEFILE "data.txt", "File contents here"
READFILE "data.txt", contents$
APPENDFILE "log.txt", "Appended line"| Function | Description |
|---|---|
FILEEXISTS("path") |
Check if file exists (1/0) |
EOF |
End-of-file flag after READLINE |
Close all open file handles at once:
CLOSE ALLTRY
LET x = 10 / 0
PRINT "This won't execute"
CATCH err
PRINT "Caught error: "; err
END TRY
PRINT "Program continues normally"Raise a custom error:
FUNCTION Divide(a, b)
IF b = 0 THEN THROW "Division by zero!"
RETURN a / b
END FUNCTION
TRY
PRINT Divide(10, 0)
CATCH e
PRINT "Error: "; e
END TRYValidate conditions (useful for testing):
ASSERT x > 0, "x must be positive"
ASSERT LEN(name) > 0, "name required"After a CATCH, ERROR$ contains the error message:
TRY
THROW "something went wrong"
CATCH e
PRINT ERROR$ ' same as e
END TRYDefine inline functions (single-line):
LAMBDA Double(x) = x * 2
LAMBDA IsEven(x) = x - INT(x / 2) * 2 = 0Multi-line LAMBDA blocks (for complex logic):
LAMBDA Factorial(n)
IF n <= 1 THEN RETURN 1
LET result = n * Factorial(n - 1)
RETURN result
END LAMBDA
PRINT Factorial(5) ' prints 120Apply a function to every element of a list:
LAMBDA Square(x) = x * x
LIST nums = 1, 2, 3, 4, 5
MAP Square ON nums INTO squared
' squared = [1, 4, 9, 16, 25]Keep only elements where the function returns true:
LAMBDA IsPositive(x) = x > 0
LIST data = -5, 3, -1, 7, 0, 4
FILTER IsPositive ON data INTO positives
' positives = [3, 7, 4]Accumulate list elements into a single value:
LAMBDA Add(a, b) = a + b
LIST values = 10, 20, 30, 40
REDUCE Add ON values INTO total FROM 0
PRINT total ' prints 100Parse a JSON string into a dictionary or list:
LET data$ = '{"name":"Alice","score":95}'
JSON PARSE data$ INTO record
GET record.name INTO n
PRINT n ' prints AliceConvert a dict or list to a JSON string:
DICT user = "name":"Bob", "age":"30"
JSON STRINGIFY user INTO jsonStr
PRINT jsonStrQuick access to parsed JSON fields:
JSON GET record.name INTO playerNameFind the first match of a pattern:
LET text = "Call 555-1234 today"
REGEX MATCH "\d{3}-\d{4}" IN text INTO phone
PRINT phone ' prints 555-1234
PRINT phone_POS ' prints character positionReplace all matches of a pattern:
LET html = "<b>Hello</b>"
REGEX REPLACE "<[^>]+>" WITH "" IN html INTO plain
PRINT plain ' prints HelloFind all matches (results stored in a list):
LET text = "a1 b2 c3 d4"
REGEX FIND "\w\d" IN text INTO matches
FOREACH m IN matches
PRINT m
NEXT mSplit a string using a regex delimiter:
LET csv = "one,two,,three"
REGEX SPLIT "," IN csv INTO partsDefine a record type with named fields (single-line):
STRUCT Point = X, Y
NEW Point AS p1
SET p1.X = 10
SET p1.Y = 20
GET p1.X INTO px
PRINT "x="; pxMulti-line STRUCT with FIELD and METHOD:
STRUCT Dog
FIELD Name
FIELD Breed
FIELD Age
METHOD Speak()
PRINT Name; " says Woof!"
END METHOD
METHOD Summary()
PRINT Name; " ("; Breed; "), age "; Age
END METHOD
END STRUCT
NEW Dog AS rex
SET rex.Name = "Rex"
SET rex.Breed = "Labrador"
SET rex.Age = 5
CALL rex.Speak() ' Rex says Woof!
CALL rex.Summary() ' Rex (Labrador), age 5Define a set of named constants:
ENUM Color = RED, GREEN, BLUE, YELLOW
LET myColor = COLOR_GREEN
IF myColor = COLOR_GREEN THEN PRINT "Green!"
PRINT "Total colors: "; COLOR_COUNTEnum values are auto-numbered starting from 0. Each value creates a constant ENUMNAME_VALUENAME.
Declare immutable variables:
CONST MAX_SIZE = 100
CONST APP_NAME = "MyApp"
LET MAX_SIZE = 200 ' ERROR: Cannot reassign constantIntrospect the type of a value:
TYPEOF 42 ' prints INTEGER
TYPEOF "hello" ' prints STRING
TYPEOF 3.14 ' prints FLOAT
TYPEOF myVar INTO typeStr
IF typeStr = "STRING" THEN PRINT "It's a string"| Function | Description |
|---|---|
ISNUMBER(x) |
Returns 1 if numeric, 0 otherwise |
ISSTRING(x) |
Returns 1 if string, 0 otherwise |
TONUM(x) |
Convert to number |
TOSTR(x) |
Convert to string |
TYPE(x) |
Returns type name |
Include and execute another TempleCode file:
IMPORT "mathlib.tc"
IMPORT "utils/helpers.tc"- Imported files are executed once (duplicate imports are skipped)
- SUB/FUNCTION definitions from imported files become available
- Variables set in imported files are accessible
C-style formatted output with positional and variable interpolation:
LET name = "Alice"
LET score = 95
PRINTF "Hello {NAME}, you scored {1}!", score
PRINTF "Pi ≈ {0}", 3.14159
PRINTF "{0} + {1} = {2}", 10, 20, 30Supports:
{0},{1}, ... — positional arguments{VAR_NAME}— variable interpolation\n,\t— escape sequences
TempleCode's power comes from mixing BASIC, PILOT, and Logo plus modern features:
REM A fully mixed TempleCode program
CONST PI = 3.14159
FUNCTION CircleArea(r)
RETURN PI * r * r
END FUNCTION
T:Welcome to the Circle Calculator!
A:Enter radius
TRY
LET R = ANSWER
LET AREA = CircleArea(R)
PRINTF "Area of circle with radius {0}: {1}", R, ROUND(AREA, 2)
REM Draw the circle with Logo
SETCOLOR blue
CIRCLE R * 2
PRINT "Circle drawn!"
CATCH ERR
T:Error: $ERR
END TRY
END
- Lines starting with a digit are parsed as BASIC (with line numbers)
- Lines with a letter + colon (e.g.,
T:,A:,M:) are PILOT commands - Logo keywords (
FORWARD,REPEAT,TO, etc.) trigger the turtle graphics - Modern commands (
LIST,DICT,SUB,FUNCTION,TRY, etc.) extend BASIC REM,', and;start comments in any context- All styles can be freely mixed in a single program
See the examples/templecode/ directory:
| File | Description |
|---|---|
hello.tc |
Hello World demo mixing all three styles |
spiral.tc |
Colorful spiral with Logo turtle graphics |
quiz.tc |
Geography quiz using PILOT interaction |
guess.tc |
Number guessing game in BASIC |
mandelbrot.tc |
Fractal art with nested REPEAT |
todo_list.tc |
Todo list manager with lists, subs, file I/O |
data_pipeline.tc |
Data processing with lambdas, map/filter/reduce |
gradebook.tc |
Student grades with structs, dicts, functions |
text_processor.tc |
Text analysis with regex and string functions |
config_manager.tc |
JSON config file manager with error handling |
TempleCode — Three heritages, one modern language.