The GladLang Interpreter
Project description
GladLang
GladLang is a dynamic, interpreted, object-oriented programming language. This is a full interpreter built from scratch in Python, complete with a lexer, parser, and runtime environment. It supports modern programming features like closures, classes, inheritance, and robust error handling.
This is the full overview of the GladLang language, its features, and how to run the interpreter.
Table of Contents
- About The Language
- Key Features
- Getting Started
- Language Tour (Syntax Reference)
- Error Handling
- Running Tests
- License
About The Language
GladLang is an interpreter for a custom scripting language. It was built as a complete system, demonstrating the core components of a programming language:
- Lexer: A tokenizer that scans source code and converts it into a stream of tokens (e.g.,
NUMBER,STRING,IDENTIFIER,KEYWORD,PLUS). - Parser: A parser that takes the token stream and builds an Abstract Syntax Tree (AST), representing the code's structure.
- AST Nodes: A comprehensive set of nodes that define every syntactic structure in the language (e.g.,
BinOpNode,IfNode,FunDefNode,ClassNode). - Runtime: Defines the
ContextandSymbolTablefor managing variable scope, context (for tracebacks), and closures. - Values: Defines the language's internal data types (
Number,String,List,Dict,Function,Class,Instance). - Interpreter: The core engine that walks the AST and executes the program by visiting each node.
- Entry Point: The main file that ties everything together. It handles command-line arguments, runs files, and starts the interactive shell.
Key Features
GladLang supports a rich, modern feature set:
- Data Types: Numbers (int/float), Strings, Lists, Dictionaries, Booleans, and Null.
- Variables: Dynamic variable assignment with
LET. - Advanced Assignments:
- Destructuring: Unpack lists directly (
LET [x, y] = [1, 2]). - Slicing: Access sub-lists or substrings easily (
list[0:3]).
- Destructuring: Unpack lists directly (
- String Manipulation:
- Interpolation: JavaScript-style template strings (
`Hello ${name}`). - Multi-line Strings: Triple-quoted strings (
"""...""") for large text blocks.
- Interpolation: JavaScript-style template strings (
- List Comprehensions: Pythonic one-line list creation (
[x * 2 FOR x IN list]). - Dictionaries: Key-value data structures (
{'key': 'value'}). - Control Flow: Full support for
IF/ELSE IF,SWITCH/CASE,WHILEloops, andFORloops withBREAK/CONTINUE - Functions: First-class citizens, Closures, Recursion, Named/Anonymous support.
- Object-Oriented: Define classes, methods, and inherit behavior using
CLASSandINHERITS. - Error Management: Gracefully handle errors with
TRY,CATCH, andFINALLY. - Constants: Declare immutable values using
FINAL. - Built-ins:
PRINT,INPUT,STR,INT,FLOAT,BOOL,LEN. - Error Handling: Robust, user-friendly runtime error reporting with full tracebacks.
- Advanced Math: Compound assignments (
+=,*=), Power (**), Modulo (%), and automatic float division. - Rich Comparisons: Chained comparisons (
1 < x < 10) and Identity checks (is). - Flexible Logic: Support for
and/or(case-insensitive).
Getting Started
There are several ways to install and run GladLang.
1. Installation
Option A: Install via Pip (Recommended)
If you just want to use the language, install it via pip:
pip install gladlang
Option B: Install from Source (For Developers)
If you want to modify the codebase, clone the repository and install it in editable mode:
git clone --depth 1 https://github.com/gladw-in/gladlang.git
cd gladlang
pip install -e .
2. Usage
Once installed, you can use the global gladlang command.
Interactive Shell (REPL)
Run the interpreter without arguments to start the shell:
gladlang
Running a Script
Pass a file path to execute a script:
gladlang "tests/test.glad"
3. Running Without Installation (Source)
You can run the interpreter directly from the source code without installing it via pip:
python run.py "tests/test.glad"
4. Building the Executable
You can build a standalone executable (no Python required) using PyInstaller:
pip install pyinstaller
pyinstaller run.py --paths src -F --name gladlang --icon=favicon.ico
This will create a single-file executable at dist/gladlang (or gladlang.exe on Windows).
Adding to PATH (Optional): To run the standalone executable from anywhere:
- Windows: Move it to a folder and add that folder to your System PATH variables.
- Mac/Linux: Move it to
/usr/local/bin:sudo mv dist/gladlang /usr/local/bin/
Language Tour (Syntax Reference)
Here is a guide to the GladLang syntax, with examples from the tests/ directory.
1. Comments
Comments start with # and last for the entire line.
# This is a comment.
LET a = 10 # This is an inline comment
2. Variables and Data Types
Variables
Variables are assigned using the LET keyword. You can also unpack lists directly into variables using Destructuring.
# Immutable Constants
FINAL PI = 3.14159
# Variable Assignment
LET a = 10
LET b = "Hello"
LET my_list = [a, b, 123]
# Destructuring Assignment
LET point = [10, 20]
LET [x, y] = point
PRINT x # 10
PRINT y # 20
Numbers
Numbers can be integers or floats. All standard arithmetic operations are supported.
LET math_result = (1 + 2) * 3 # 9
LET float_result = 10 / 4 # 2.5
Strings
Strings can be defined in three ways:
- Double Quotes: Standard strings.
- Triple Quotes: Multi-line strings that preserve formatting.
- Backticks: Template strings supporting interpolation.
# Standard
LET s = "Hello\nWorld"
# Multi-line
LET menu = """
1. Start
2. Settings
3. Exit
"""
# Indexing
LET char = "GladLang"[0] # "G"
PRINT "Hello"[1] # "e"
# Escapes (work in "..." and `...`)
PRINT "Line 1\nLine 2"
PRINT `Column 1\tColumn 2`
# Interpolation (Template Strings)
LET name = "Glad"
PRINT `Welcome back, ${name}!`
PRINT `5 + 10 = ${5 + 10}`
Lists, Slicing & Comprehensions
Lists are ordered collections. You can access elements, slice them, or create new lists dynamically using comprehensions.
LET nums = [0, 1, 2, 3, 4, 5]
# Indexing & Assignment
PRINT nums[1] # 1
LET nums[1] = 100
# Slicing [start:end]
PRINT nums[0:3] # [0, 1, 2]
PRINT nums[3:] # [3, 4, 5]
# List Comprehension
LET squares = [n ** 2 FOR n IN nums]
PRINT squares # [0, 1, 4, 9, 16, 25]
Dictionaries
Dictionaries are key-value pairs enclosed in {}. Keys must be Strings or Numbers.
LET person = {
"name": "Glad",
"age": 25,
"is_admin": TRUE
}
PRINT person["name"] # Access: "Glad"
LET person["age"] = 26 # Modify
LET person["city"] = "NYC" # Add new key
Booleans
Booleans are TRUE and FALSE. They are the result of comparisons and logical operations.
LET t = TRUE
LET f = FALSE
PRINT t AND f # 0 (False)
PRINT t OR f # 1 (True)
PRINT NOT t # 0 (False)
Truthiness: 0, 0.0, "", NULL, and FALSE are "falsy." All other values (including non-empty strings, non-zero numbers, lists, functions, and classes) are "truthy."
Null
The NULL keyword represents a null or "nothing" value. It is falsy and prints as 0. Functions with no RETURN statement implicitly return NULL.
3. Operators
Math Operations
GladLang supports standard arithmetic plus advanced operators like Modulo, Floor Division, and Power.
LET sum = 10 + 5 # 15
LET diff = 20 - 8 # 12
LET prod = 5 * 4 # 20
LET quot = 100 / 2 # 50.0 (Always Float)
PRINT 2 ** 3 # Power: 8
PRINT 10 // 3 # Floor Division: 3
PRINT 10 % 3 # Modulo: 1
# Standard precedence rules apply
PRINT 2 + 3 * 4 # 14
PRINT 1 + 2 * 3 # 7
PRINT (1 + 2) * 3 # 9
Compound Assignments
GladLang supports syntactic sugar for updating variables in place.
LET score = 10
score += 5 # score is now 15
score -= 2 # score is now 13
score *= 2 # score is now 26
score /= 2 # score is now 13.0
score %= 5 # score is now 3.0
Bitwise Operators
Perform binary manipulation on integers.
LET a = 5 # Binary 101
LET b = 3 # Binary 011
PRINT a & b # 1 (AND)
PRINT a | b # 7 (OR)
PRINT a ^ b # 6 (XOR)
PRINT ~a # -6 (NOT)
PRINT 1 << 2 # 4 (Left Shift)
PRINT 8 >> 2 # 2 (Right Shift)
# Compound Assignment
LET x = 1
x <<= 2 # x is now 4
Comparisons & Logic
You can compare values, chain comparisons for ranges, and check object identity.
# Equality & Inequality
PRINT 1 == 1 # True
PRINT 1 != 2 # True
# Chained Comparisons (Ranges)
LET age = 25
IF 18 <= age < 30 THEN
PRINT "Young Adult"
ENDIF
PRINT (10 < 20) AND (10 != 5) # 1 (True)
# Identity ('is' checks if variables refer to the same object)
LET a = [1, 2]
LET b = a
PRINT b is a # True
PRINT b == [1, 2] # True (Values match)
# Boolean Operators (case-insensitive)
IF a and b THEN
PRINT "Both exist"
ENDIF
Increment / Decrement
Supports C-style pre- and post-increment/decrement operators on variables and list elements.
LET i = 5
PRINT i++ # 5
PRINT i # 6
PRINT ++i # 7
PRINT i # 7
LET my_list = [10, 20]
PRINT my_list[1]++ # 20
PRINT my_list[1] # 21
4. Control Flow
IF Statements
Uses IF...THEN...ENDIF syntax.
IF x > 10 THEN
PRINT "Large"
ELSE IF x > 5 THEN
PRINT "Medium"
ELSE
PRINT "Small"
ENDIF
Switch Statements
Use SWITCH to match a value against multiple possibilities. It supports single values, comma-separated lists for multiple matches, and expressions.
LET status = 200
SWITCH status
CASE 200:
PRINT "OK"
CASE 404, 500:
PRINT "Error"
DEFAULT:
PRINT "Unknown Status"
ENDSWITCH
WHILE Loops
Loops while a condition is TRUE.
LET i = 3
WHILE i > 0
PRINT "i = " + i
LET i = i - 1
ENDWHILE
# Prints:
# i = 3
# i = 2
# i = 1
FOR Loops
Iterates over the elements of a list.
LET my_list = ["apple", "banana", "cherry"]
FOR item IN my_list
PRINT "Item: " + item
ENDFOR
BREAK and CONTINUE are supported in both WHILE and FOR loops.
5. Functions
Named Functions
Defined with DEF...ENDEF. Arguments are passed by value. RETURN sends a value back.
DEF add(a, b)
RETURN a + b
ENDEF
LET sum = add(10, 5)
PRINT sum # 15
Anonymous Functions
Functions can be defined without a name, perfect for assigning to variables.
LET double = DEF(x)
RETURN x * 2
ENDEF
PRINT double(5) # 10
Closures
Functions capture variables from their parent scope.
DEF create_greeter(greeting)
DEF greeter_func(name)
# 'greeting' is "closed over" from the parent
RETURN greeting + ", " + name + "!"
ENDEF
RETURN greeter_func
ENDEF
LET say_hello = create_greeter("Hello")
PRINT say_hello("Alex") # "Hello, Alex!"
Recursion
Functions can call themselves.
DEF fib(n)
IF n <= 1 THEN
RETURN n
ENDIF
RETURN fib(n - 1) + fib(n - 2)
ENDEF
PRINT fib(7) # 13
6. Object-Oriented Programming (OOP)
Classes and Instantiation
Use CLASS...ENDCLASS to define classes and NEW to create instances. The constructor is init.
CLASS Counter
DEF init(SELF)
SELF.count = 0 # 'SELF' is the instance
ENDEF
DEF increment(SELF)
SELF.count = SELF.count + 1
ENDEF
DEF get_count(SELF)
RETURN SELF.count
ENDEF
ENDCLASS
The SELF Keyword
SELF is the mandatory first argument for all methods and is used to access instance attributes and methods.
LET c = NEW Counter()
c.increment()
PRINT c.get_count() # 1
Inheritance
Use the INHERITS keyword. Methods can be overridden by the child class.
CLASS Pet
DEF init(SELF, name)
SELF.name = name
ENDEF
DEF speak(SELF)
PRINT SELF.name + " makes a generic pet sound."
ENDEF
ENDCLASS
CLASS Dog INHERITS Pet
# Override the 'speak' method
DEF speak(SELF)
PRINT SELF.name + " says: Woof!"
ENDEF
ENDCLASS
LET my_dog = NEW Dog("Buddy")
my_dog.speak() # "Buddy says: Woof!"
Polymorphism
When a base class method calls another method on SELF, it will correctly use the child's overridden version.
CLASS Pet
DEF introduce(SELF)
PRINT "I am a pet and I say:"
SELF.speak() # This will call the child's 'speak'
ENDEF
DEF speak(SELF)
PRINT "(Generic pet sound)"
ENDEF
ENDCLASS
CLASS Cat INHERITS Pet
DEF speak(SELF)
PRINT "Meow!"
ENDEF
ENDCLASS
LET my_cat = NEW Cat("Whiskers")
my_cat.introduce()
# Prints:
# I am a pet and I say:
# Meow!
7. Built-in Functions
PRINT(value): Prints a value to the console.INPUT(): Reads a line of text from the user as a String.STR(value): Casts a value to a String.INT(value): Casts a String or Float to an Integer.FLOAT(value): Casts a String or Integer to a Float.BOOL(value): Casts a value to its Boolean representation (TRUEorFALSE).LEN(value): Returns the length of a String, List, Dict, or Number. Alias:LENGTH().
Error Handling
You can handle runtime errors gracefully or throw your own exceptions.
TRY
# Attempt dangerous code
LET result = 10 / 0
PRINT result
CATCH error
# Handle the error
PRINT "Caught an error: " + error
FINALLY
# Always runs
PRINT "Cleanup complete."
ENDTRY
# Manually throwing errors
IF age < 0 THEN
THROW "Age cannot be negative!"
ENDIF
GladLang features detailed error handling and prints full tracebacks for runtime errors, making debugging easy.
Example: Name Error (test_name_error.glad)
Traceback (most recent call last):
File test_name_error.glad, line 6, in <program>
Runtime Error: 'b' is not defined
Example: Type Error (test_type_error.glad with input "5")
Traceback (most recent call last):
File test_type_error.glad, line 6, in <program>
Runtime Error: Illegal operation
Example: Argument Error (test_arg_error.glad)
Traceback (most recent call last):
File test_arg_error.glad, line 7, in <program>
File test_arg_error.glad, line 4, in add
Runtime Error: Incorrect argument count for 'add'. Expected 2, got 3
Running Tests
The tests/ directory contains a comprehensive suite of .glad files to test every feature of the language. You can run any test by executing it with the interpreter:
gladlang "test_closures.glad"
gladlang "test_lists.glad"
gladlang "test_polymorphism.glad"
License
You can use this under the MIT License. See LICENSE for more details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gladlang-0.1.4.tar.gz.
File metadata
- Download URL: gladlang-0.1.4.tar.gz
- Upload date:
- Size: 35.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
312117e6b6ec9f3b71f5ec36435bca20ad46c6f3f0abd83b1d1a282686ebad96
|
|
| MD5 |
467b20b376fe508c78e6c214e35f2e2c
|
|
| BLAKE2b-256 |
7e6e6d2c44db11c3cdb5b494f4d026ed5f73e998b4182d498d120aeaad8d3a88
|
File details
Details for the file gladlang-0.1.4-py3-none-any.whl.
File metadata
- Download URL: gladlang-0.1.4-py3-none-any.whl
- Upload date:
- Size: 30.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87f73ce59ae4f00f5c4fc7b1f94a00ba5cdea2d8cd80fe78cb51acad612d4a5e
|
|
| MD5 |
47d4664dfd77aaa23491abccd192d548
|
|
| BLAKE2b-256 |
0da0ac5d26ea1253bf61f79296394e6c536029edbc13fdbeedca85c6b7695182
|