Evil Lang (Evil Program Language) is a lightweight, expressive interpreted programming language that combines the essence of imperative and functional programming paradigms. It's specifically designed for education and learning programming language implementation principles. It's not just a programming language, but an adventure into the inner workings of programming languages!
// Evil Lang code example: Closures and higher-order functions
func createFibGenerator() {
var a = 0;
var b = 1;
func next() {
var temp = a;
a = b;
b = temp + b;
return temp;
}
return next;
}
var fib = createFibGenerator();
for (var i = 0; i < 10; i = i + 1) {
print(fib() + " "); // Print the first 10 items of the Fibonacci sequence
}
This major update introduces powerful new features that make Evil Lang a more complete programming language:
- โ Module System - Full import/export support for code organization and reuse
- โ Object-Oriented Programming - Classes, inheritance, constructors, and methods
- โ Exception Handling - Complete try/catch/finally support with custom exceptions
- โ Enhanced String Support - String length property and 12 new string functions
- โ Array Manipulation - 10 new array functions including push, pop, slice, and more
- โ Method Calls - Support for calling methods on objects (obj.method())
- โ
String Functions -
toUpper
,toLower
,trim
,split
,join
,substring
,indexOf
,replace
,charAt
- โ
Array Functions -
push
,pop
,shift
,unshift
,slice
,arrayReverse
,arraySort
,includes
,arrayIndexOf
,concat
- โ Math Module - Basic mathematical functions and constants
- โ Array Module - Array manipulation utilities
- โ Enhanced Error Reporting System - Complete call stack tracing with detailed error location
- โ Colorful Error Output - ANSI color codes for better readability
- โ Modular Built-in Function Architecture - Extensible built-in function system
- โ
New
typeof
Function - Runtime type checking - โ Improved REPL Experience - Better interactive environment
- Why Evil Lang?
- Key Features
- Installation and Usage
- Language Features
- Syntax Reference
- Implementation Principles
- Developer's Guide
- Challenges We Overcame
- Design Philosophy
- Future Development
- Contribution Guidelines
- License
Comprehensive documentation is available in multiple languages:
- English Documentation - Complete guide in English
- ไธญๆๆๆกฃ - ๅฎๆด็ไธญๆๆๅ
- Documentation Index - All available documentation
- Quick Start Guide - Get started in 5 minutes
- Language Reference - Complete syntax guide
- Tutorials - Step-by-step tutorials
- API Reference - Built-in functions and modules
In the vast ocean of programming languages, why did we create Evil Lang? Because deeply understanding the design and implementation of programming languages is a crucial milestone in every programmer's growth journey!
Unlike other educational languages, Evil Lang focuses on:
- Balancing Complexity and Comprehensibility - Our codebase has only about 1000 lines of Python code, yet implements a complete programming language
- Visualizing Internal Mechanisms - Providing a
--debug
mode that lets you see the lexical and syntax analysis process step by step - Approachable Syntax - Drawing inspiration from JavaScript and C syntax to lower the learning curve
- Elegant Closure Implementation - We implemented complete closure functionality in less than 100 lines of code, more concisely than many educational implementations
- Unicode Friendly - Built-in support for UTF-8, allowing Chinese and other non-ASCII characters in variable names, strings, and comments
Evil Lang isn't meant to replace any existing language, but to let you see the skeleton of a language and understand its soul!
Though concise, Evil Lang is feature-rich, combining the essence of multiple programming paradigms:
var total = 0;
for (var i = 1; i <= 100; i = i + 1) {
total = total + i;
}
print("Sum from 1 to 100 is: " + total);
func map(arr, fn) {
var result = [];
for (var i = 0; i < arr.length; i = i + 1) {
result[i] = fn(arr[i]);
}
return result;
}
var numbers = [1, 2, 3, 4, 5];
print(map(numbers, func(x) { return x * x; }));
func createLogger(prefix) {
func log(message) {
print(prefix + ": " + message);
}
return log;
}
var debugLogger = createLogger("DEBUG");
var errorLogger = createLogger("ERROR");
debugLogger("Program is running");
errorLogger("Unhandled exception detected");
// Define a class with constructor and methods
class Animal {
constructor(name, sound) {
this.name = name;
this.sound = sound;
}
speak() {
print(this.name + " says: " + this.sound);
}
}
// Inheritance
class Dog extends Animal {
constructor(name) {
this.name = name;
this.sound = "Woof!";
}
wagTail() {
print(this.name + " is wagging its tail!");
}
}
var dog = new Dog("Buddy");
dog.speak(); // Output: Buddy says: Woof!
dog.wagTail(); // Output: Buddy is wagging its tail!
// Try-catch-finally example
func divide(a, b) {
if (b == 0) {
throw "Division by zero error!";
}
return a / b;
}
try {
print(divide(10, 2)); // Output: 5
print(divide(10, 0)); // Throws exception
} catch (e) {
print("Error caught: " + e);
} finally {
print("Cleanup complete");
}
// math_utils.el
export func square(x) {
return x * x;
}
export var PI = 3.14159;
// main.el
import "math_utils" as Math;
print(Math.square(5)); // Output: 25
print(Math.PI); // Output: 3.14159
- Python 3.6 or higher
- Curiosity and an exploratory spirit! โจ
git clone https://github.com/Evil0ctal/Evil-Lang.git
cd Evil-Lang
python evil_lang.py examples/hello_world.el
python evil_lang.py examples/advanced_example.el --debug
python evil_lang.py examples/hello_world.el --no-color
Create a file named hello.el
:
// My first Evil Lang program
print("Hello, Evil World!");
var name = input("Please enter your name: ");
print("Welcome to the world of Evil Lang, " + name + "!");
Then run:
python evil_lang.py hello.el
Evil Lang combines the advantages of several languages while maintaining simplicity and consistency:
Evil Lang is a dynamically typed language supporting these basic types:
- Numbers: Integers and floating-point numbers
- Strings: Supporting Unicode and escape characters
- Booleans:
true
andfalse
- Null:
null
- Arrays: Supporting nested and multi-dimensional arrays
- Objects: Key-value pair structures similar to JavaScript objects
- Functions: First-class citizens, usable as parameters and return values
Unlike Python or JavaScript, Evil Lang's type system is straightforward without complex inheritance or prototype chains, making it easy for beginners to understand basic type concepts.
We also provide the typeof
built-in function for runtime type checking:
print(typeof(42)); // "number"
print(typeof("hello")); // "string"
print(typeof(true)); // "boolean"
print(typeof(null)); // "null"
print(typeof([])); // "array"
print(typeof({})); // "object"
print(typeof(print)); // "function"
Evil Lang provides intuitive control flow statements:
- Conditionals:
if
,else if
,else
- Loops:
while
,for
- Jump Statements:
break
,continue
- Ternary Operator:
condition ? expr1 : expr2
These control structures have syntax similar to C and JavaScript, enabling beginners to easily transition to mainstream languages.
Evil Lang's function system is elegantly designed:
- Function Definition: Using the
func
keyword - Parameter Passing: Supporting pass-by-value
- Return Values: Using the
return
statement - Recursion: Fully supporting recursive calls
- Closures: Functions can capture and retain their outer environment
Closures are a highlight of Evil Langโwe not only implemented them but made them easy to understand and use.
func makeAdder(x) {
func add(y) {
return x + y; // Captures outer variable x
}
return add;
}
var add5 = makeAdder(5);
print(add5(10)); // Outputs 15
Evil Lang supports two main composite data structures:
- Arrays: Defined using square brackets
[]
, zero-indexed - Objects: Defined using curly braces
{}
for key-value pairs
These data structures are simple yet sufficient as building blocks for complex applications.
// Variable declaration
var x = 42;
var name = "Evil Lang";
var isEnabled = true;
// Variable assignment
x = x + 8;
name = name + " Programming Language";
// Arithmetic operators
var sum = a + b;
var diff = a - b;
var product = a * b;
var quotient = a / b;
// Comparison operators
var isEqual = a == b;
var isNotEqual = a != b;
var isGreater = a > b;
var isLess = a < b;
// Logical operators
var andResult = a && b;
var orResult = a || b;
var notResult = !a;
if (score >= 90) {
print("Excellent");
} else if (score >= 80) {
print("Good");
} else if (score >= 70) {
print("Average");
} else if (score >= 60) {
print("Pass");
} else {
print("Fail");
}
// While loop
var i = 0;
while (i < 5) {
print(i);
i = i + 1;
}
// For loop
for (var j = 0; j < 5; j = j + 1) {
print(j);
}
// Creating arrays
var fruits = ["Apple", "Banana", "Orange"];
// Accessing elements
print(fruits[1]); // Outputs "Banana"
// Modifying elements
fruits[0] = "Pear";
// Iterating through arrays
for (var i = 0; i < fruits.length; i = i + 1) {
print(fruits[i]);
}
// Basic function
func greet(name) {
return "Hello, " + name + "!";
}
// Function call
print(greet("John"));
// Recursive function
func factorial(n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
// Higher-order function
func operate(a, b, operation) {
return operation(a, b);
}
func add(x, y) {
return x + y;
}
print(operate(5, 3, add)); // Outputs 8
Evil Lang follows a classic three-step architecture, focusing on simplicity and comprehensibility:
The lexer is Evil Lang's "eyes," scanning source code text and identifying the program's basic building blocks:
# Evil Lang's lexer core principle
class Lexer:
def get_next_token(self):
# Skip whitespace and comments
self.skip_whitespace()
self.skip_comment()
# Process different token types
if self.current_char.isdigit():
return self.get_number()
elif self.current_char.isalpha() or self.current_char == '_':
return self.get_identifier()
elif self.current_char == '"':
return self.get_string()
# ... other token types
Unlike traditional implementations, our lexer:
- Supports Unicode - Handles non-ASCII characters like Chinese
- Intelligently Processes Comments - Distinguishes code from comments, improving readability
- Provides Precise Error Locations - Reports specific line and column numbers when errors occur
The parser is Evil Lang's "brain," organizing token streams into structured abstract syntax trees (AST):
# Evil Lang's recursive descent parsing
class Parser:
def expr(self):
"""Parse expressions"""
node = self.logic_expr()
# Check if it's a ternary expression
if self.current_token.type == TokenType.OPERATOR and self.current_token.value == '?':
self.eat(TokenType.OPERATOR) # Consume the question mark
true_expr = self.expr()
self.eat(TokenType.COLON)
false_expr = self.expr()
node = TernaryOp(node, true_expr, false_expr)
return node
Our parser features:
- Recursive Descent Parsing - Clearly reflects the language grammar structure
- Elegant Operator Precedence Handling - Uses separate functions for different precedence levels
- Robust Error Recovery - Provides meaningful hints when errors occur
The interpreter is Evil Lang's "heart," traversing the AST and executing corresponding operations:
# Evil Lang's interpreter core
class Interpreter:
def visit_FuncCall(self, node):
"""Function call handling"""
# Prepare arguments
arg_values = [self.visit(arg) for arg in node.arguments]
# Find and call the function
if node.name in self.functions:
func_node = self.functions[node.name]
# Create new scope
saved_scope = self.global_scope.copy()
new_scope = saved_scope.copy()
# Bind parameters
for i, param in enumerate(func_node.params):
new_scope[param.value] = arg_values[i]
# Set new scope and execute
self.global_scope = new_scope
try:
self.visit(func_node.body)
except ReturnException as e:
return_value = e.value
finally:
# Restore original scope
self.global_scope = saved_scope
return return_value
Highlights of our interpreter:
- Elegant Closure Implementation - Using lexical scope capturing
- Visitor Pattern - Making code structure clear and extensible
- Exception-based Control Flow - Using exceptions to handle return, break, and continue
Evil Lang's code organization follows modular principles, with main modules including:
Evil-Lang/
โโโ src/
โ โโโ lexer.py # Lexical analyzer
โ โโโ parser.py # Syntax analyzer
โ โโโ ast.py # Abstract syntax tree definitions
โ โโโ interpreter.py # Interpreter core
โ โโโ errors.py # Error handling
โ โโโ builtins/ # Built-in functions
โ โ โโโ __init__.py # Built-in function registration
โ โ โโโ numeric.py # Number-related functions
โ โ โโโ string.py # String-related functions
โ โ โโโ io.py # Input/output functions
โโโ examples/ # Example programs
โโโ evil_lang.py # Main program entry
Evil Lang's built-in function system is designed to be easily extensible. Here are the steps to add a new function:
- Choose or Create an Appropriate Module: Select a suitable module in the
src/builtins/
directory, or create a new one. - Define the Function: The function should accept a parameter list and return a result.
def _my_new_function(args): """Function docstring - explains the function's purpose""" # Parameter validation if len(args) != 2: raise ValueError("myNewFunction requires exactly two arguments") # Implementation logic result = args[0] + args[1] # Example logic # Return result return result
- Register the Function: Use the
register_builtin
function to register your new function in the Evil Lang environment.# Add at the end of the file register_builtin('myNewFunction', _my_new_function)
- Ensure the Module is Imported: Import your module in
src/builtins/__init__.py
.# In __init__.py from .numeric import * from .string import * from .io import * from .your_new_module import * # If you created a new module
- Write Tests: Create test programs to verify your new function.
// In examples/test_my_function.el print(myNewFunction(10, 20)); // Should output 30
Evil Lang version 1.0.1 introduces an enhanced error handling system. When implementing new features, use appropriate error classes:
from ..errors import ValueError, TypeError, RuntimeError
# In your function
if not isinstance(args[0], (int, float)):
raise TypeError("First argument must be a number", line, column)
This will produce consistent, user-friendly error messages and automatically collect call stack information.
- Use the
--debug
Flag: Add--debug
when running to see internal execution details. - Add Debug Output in Built-in Functions:
if '--debug' in sys.argv: print(f"DEBUG: args = {args}")
- Use the
format_error
Method: View formatted error information.try: # Code except EvilLangError as e: print(e.format_error())
During Evil Lang development, we encountered and solved many interesting challenges:
Closures are one of the most complex features in Evil Lang. The main challenge was: how to make functions "remember" the environment they were created in?
Solution: We created a FuncRef
class that not only stores the function definition but also saves a snapshot of the lexical scope at the time of definition:
class FuncRef:
def __init__(self, func_node, lexical_scope=None):
self.func_node = func_node # Function definition
self.lexical_scope = lexical_scope # Lexical scope
When a function returns an inner function, we capture the current environment and bind it to the inner function, making it a true closure.
Locating errors in complex programs is a major challenge, especially for language beginners.
Solution: We implemented a detailed error reporting system:
- Recording line and column numbers for each token
- Providing context-sensitive error messages
- Adding a
--debug
mode to show intermediate results of lexical and syntax analysis - Adding call stack tracing and code snippet highlighting in version 1.0.1
Recursion is an important feature of programming languages, but uncontrolled recursion can lead to stack overflow.
Solution: We used Python's exception mechanism to handle control flow, avoiding deep recursion issues and making implementation more concise.
Many educational interpreters only support ASCII, limiting internationalization.
Solution: We designed complete Unicode support from the beginning:
- Using UTF-8 encoding to read source files
- Correctly handling Unicode identifiers and strings
- Supporting non-ASCII characters like Chinese for variable names and output
Evil Lang's design adheres to the following core principles:
Evil Lang's primary goal is education. We're willing to sacrifice some performance and features to maintain code clarity and comprehensibility. Each component is designed to be "self-explanatory," allowing readers to easily understand how it works.
We borrowed syntax from JavaScript and C to make beginners feel comfortable, while eliminating complex or confusing features to maintain language simplicity and consistency.
Evil Lang features are arranged by complexity, allowing learners to progress gradually:
- Basic variables and expressions
- Conditionals and loops
- Functions and recursion
- Arrays and objects
- Higher-order functions and closures
We value user experience, providing rich output and interactive features:
- Built-in
print
andinput
functions - Detailed error messages
- Visual tracing in debug mode
Evil Lang continues to evolve. Here are our planned enhancements:
- โ Module System - Import and export mechanisms (implemented in v1.0.2)
- โ Class and Object System - Object-oriented programming support (implemented in v1.0.2)
- โ Exception Handling - Try/catch mechanisms (implemented in v1.0.2)
- โณ Enhanced Standard Library - Expanding math, string, and adding file I/O support
- โณ Asynchronous Programming - Implementing Promise or async/await mechanisms
- โณ Pattern Matching - Adding switch/case statements with pattern matching
- โณ Operator Overloading - Allow custom operators for user-defined types
- Improved REPL Environment - Enhancing the interactive interpreter with features like history and auto-completion
- VSCode Extension - Syntax highlighting and auto-completion
- Debugger - Graphical step execution and variable watching
- Package Manager - Sharing and reusing Evil Lang code
- Bytecode Compiler - Compiling AST to intermediate bytecode for faster execution
- Simple JIT Compilation - Implementing just-in-time compilation for hot code
- Memory Optimization - Reducing object allocation and copying
- Interactive Tutorials - Learning language features progressively
- Online Interpreter - Experiencing Evil Lang without installation
- Compiler Principles Course - Using Evil Lang to teach programming language implementation
Evil Lang is a community-driven project, and we welcome contributions in all forms!
- Code Contributions
- Fix bugs or implement new features
- Optimize existing implementations
- Add test cases
- Documentation Improvements
- Enhance tutorials and examples
- Translate documentation
- Create learning resources
- Usage Feedback
- Report issues
- Suggest improvements
- Share experiences
- Fork the repository
- Create a feature branch:
git checkout -b my-new-feature
- Commit changes:
git commit -am 'Add some feature'
- Push branch:
git push origin my-new-feature
- Submit a Pull Request
We especially welcome educators and students to participate in creating better programming language learning tools!
Evil Lang is open-sourced under the MIT License.
MIT License
Copyright (c) 2025 Evil0ctal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files...
See the LICENSE file for details.
Made with โค๏ธ and Python - Evil0ctal