This document outlines the fundamental syntax rules and conventions that govern the TechLang programming language.
| Topic | Details |
|---|---|
| Case Sensitivity | Commands are lowercase (print, set, add); variables are case-sensitive (counter and Counter are different variables) |
| Statement Termination | One command per line; no semicolons required |
| Strings | Double quotes only: "text" (single quotes are not supported) |
| Comments | Three styles supported: # for single-line, // for C-style single-line, /* */ for multi-line blocks |
| Blocks | Begin with a keyword (loop, if, def, while, switch, match, try, macro) and end with end |
| Whitespace | Whitespace is used for separation but is otherwise ignored |
| Errors | Printed as [Error: message] (non-fatal); execution continues |
| Inputs | input <var> reads queued inputs (CLI/tests) or prompts user in interactive mode |
TechLang has a powerful Python-like module system that supports both file-based modules and folder-based packages.
Use package use <module> to execute another .tl file in a namespaced scope. Modules are resolved relative to the current script's base_dir, so package use utils/helpers loads utils/helpers.tl next to the caller. Any functions defined inside the module are invoked with a qualified name:
package use utils.helpers
call utils.helpers::greet
call utils.helpers.greet # double-colon or dot both work
TechLang also supports Python-style import syntax for more flexibility:
import mymodule # Load mymodule.tl or mymodule/__init__.tl
import mymodule as m # Load with alias
import parent.child # Load parent/child.tl or parent/child/__init__.tl
from mymodule import func1 # Import specific function
from mymodule import func1 as f # Import with alias
from mymodule import func1 func2 # Import multiple
from mymodule import * # Import all exported functions
from mypackage import submodule # Import submodule from package
Create a folder with an __init__.tl file to make it a package:
myutils/
├── __init__.tl # Package initialization file
├── math.tl # Submodule
├── text.tl # Submodule
└── helpers/ # Subpackage
└── __init__.tl
import myutils # Loads myutils/__init__.tl
import myutils.math # Loads myutils/math.tl
from myutils import text # Loads myutils/text.tl as 'text'
from myutils import helpers # Loads myutils/helpers/__init__.tl as 'helpers'
Functions defined in modules are private by default. Use export to make them available:
# In mymodule.tl
def public_function x
add x 1
return x
end
export public_function
def private_function
# This cannot be called from outside
end
Modules run in a child InterpreterState that shares variables, strings, arrays, dictionaries, structs, and output with the caller. The runtime keeps state.modules / state.loaded_modules so each module is evaluated once per run.
Use macro <name> [params...] do ... end to capture reusable snippets that expand before execution. Inside the body, reference parameters with $param. Invoke the macro with inline <name> <args...>; the generated tokens are inserted directly into the surrounding code. Recursive macro expansion is prevented to avoid infinite loops.
Variables in TechLang:
- Must start with a letter or underscore
- Can contain letters, numbers, and underscores
- Are case-sensitive
- Cannot use reserved keywords
set counter 1 # Valid
set Counter 2 # Different from 'counter'
set _temp 3 # Valid
set 1st_value 4 # Invalid - cannot start with a number
TechLang supports these basic data types:
- Integers: Whole numbers (
42,-7) - Strings: Text data (
"Hello, world!") - Floats: Decimal numbers (
3.14,-0.5) - Booleans:
trueorfalse - Arrays: Ordered collections (
[1, 2, 3]) - Maps: Key-value pairs (
{"name": "Alice", "age": 30})
set age 30 # Integer
set name "Alice" # String
set pi 3.14159 # Float
set is_active true # Boolean
set numbers [1, 2, 3, 4, 5] # Array
set person {"name": "Bob", "age": 25} # Map
TechLang supports three comment styles to make your code more readable and maintainable:
Use # (hash) or // (double-slash) for single-line comments:
# This is a hash-style comment
set x 10
// This is a C-style comment
set y 20
set z 30 # Inline comment after code
add x y // This also works inline
Use /* ... */ for comments that span multiple lines:
/*
This is a multi-line comment block.
It can span as many lines as you need.
Useful for longer explanations or documentation.
*/
set total 0
/*
Calculate the sum of values
Loop iteration starts here
*/
loop 5
add total 1
end
Comments inside quoted strings are preserved as literal text:
str_create url "https://example.com" # // in string is NOT a comment
str_create note "Use # for comments" # The # inside quotes stays
print url # Prints: https://example.com
print note # Prints: Use # for comments
- Use comments to explain why code does something, not what it does
- Keep comments concise and up-to-date with code changes
- Use multi-line comments for file headers and function documentation
- Use inline comments sparingly for complex operations
All blocks in TechLang follow this pattern:
keyword [condition] {
# code inside block
}
Examples of different blocks:
# If block
if x > 5 {
print "x is greater than 5"
}
# While loop
while counter < 10 {
add counter 1
print counter
}
# Function definition
fn greet(name) {
print "Hello, " + name
}
Blocks can be nested within other blocks:
if x > 0 {
print "Positive"
if x > 10 {
print "Greater than 10"
} else {
print "Not greater than 10"
}
} else {
print "Non-positive"
}
Errors in TechLang are non-fatal by default:
print 10 / 0 # [Error: Division by zero]
print "Program continues" # This still executes
Use try-catch blocks for explicit error handling:
try {
print 10 / 0
} catch error {
print "Caught error: " + error
}
catch can optionally bind two identifiers: the first receives the error message without the [Error: prefix, and the second (if provided) receives a stringified snapshot of the operand stack.
print "What is your name?"
input name
print "Hello, " + name
- Interactive Mode: Prompts the user for input
- Script Mode: Reads from predefined inputs provided at runtime
- Test Mode: Uses inputs specified in test cases
set name "Alice"
set age 30
print name + " is " + string(age) + " years old"
# Format strings
print "Name: ${name}, Age: ${age}"
# This is a comment
print "Hello" # This is an end-of-line comment
Good practice for documenting functions:
# Calculate the factorial of a number
# Params:
# n: The number to calculate factorial for
# Returns:
# The factorial of n
fn factorial(n) {
if n <= 1 {
return 1
}
return n * factorial(n - 1)
}
For simple conditions and loops, you can use one-line syntax:
if x > 10 { print "Greater than 10" }
for i in 1..5 { print i }
Some commands can be chained for conciseness:
# Instead of:
set x 5
add x 3
print x
# You can write:
set x 5 add x 3 print x # Output: 8
Some commands operate on an implicit current value:
boot ping ping print # Output: 2
TechLang includes a comprehensive debugger that helps you understand and troubleshoot your programs. See docs/debugging.md for complete documentation.
| Command | Description |
|---|---|
breakpoint |
Set a breakpoint at the current command position |
step |
Enable step-through mode (pause after each command) |
continue |
Resume execution from paused state |
inspect |
Show detailed state snapshot (stack, vars, arrays, dicts, strings, breakpoints, watched vars) |
watch <var> |
Add variable to watch list for monitoring |
unwatch <var> |
Remove variable from watch list |
clear_breakpoints |
Remove all breakpoints |
set counter 0
watch counter
loop 5
breakpoint # Pause here each iteration
add counter 1
inspect # Show current state
end
clear_breakpoints
- Consistent Indentation: Use 2 or 4 spaces for indentation inside blocks
- Meaningful Variable Names: Use descriptive names that indicate purpose
- Comment Complex Logic: Add comments to explain non-obvious code
- Modular Structure: Break large programs into smaller, reusable functions
- Error Checking: Validate inputs and handle potential errors gracefully
- Use the Debugger: Set breakpoints and watches to understand program flow
- Test with JSON: Use
json_writeto save program state for debugging - Leverage Comments: Use all three comment styles (
#,//,/* */) appropriately
# Simple temperature converter program
print "Temperature Converter"
print "---------------------"
print "1. Celsius to Fahrenheit"
print "2. Fahrenheit to Celsius"
print "Enter your choice (1 or 2):"
input choice
set choice int(choice)
if choice == 1 {
print "Enter temperature in Celsius:"
input celsius
set celsius float(celsius)
set fahrenheit (celsius * 9/5) + 32
print string(celsius) + "°C = " + string(fahrenheit) + "°F"
} else if choice == 2 {
print "Enter temperature in Fahrenheit:"
input fahrenheit
set fahrenheit float(fahrenheit)
set celsius (fahrenheit - 32) * 5/9
print string(fahrenheit) + "°F = " + string(celsius) + "°C"
} else {
print "Invalid choice!"
}
See the Examples Index for more code samples.