Ember is an interpreted programming language implemented in Go, designed to be simple yet powerful with a focus on readability and expressiveness.
- C-like syntax with modern conveniences
- First-class functions and closures
- Dynamic typing with integers, booleans, arrays, hashes, and functions
- Lexical scoping and proper closures
- Built-in integer arithmetic and boolean operations
- Control structures (
if/else,while,for) - Array operations (
map,reduce,push) - Built-in functions for common operations
- Variables with
letkeyword - Immutability by default with explicit
mutkeyword - Pointers with reference
&and dereference*operators - Return statements
- Operator precedence parsing
- REPL with error reporting
- Comments using
//
Basic examples:
// Variables and arithmetic
let age = 25;
let temperature = 18 + 5;
let isHot = temperature > 20;
// Mutability
let x = 5; // Immutable by default
// x = 10; // Error: Cannot assign to immutable variable: x
let mut y = 5; // Explicitly mutable
y = 10; // Works fine
// For loop
for (let i = 0; i < 5; i++) {
let forIndex = i;
}
print(forIndex);
// While loop
let mut i = 0;
while (i < 5) {
i = i + 1;
}
print(i);
// Arrays
let numbers = [1, 2, 3, 4, 5];
let doubled = map(numbers, fn(x) { x * 2 }); // [2, 4, 6, 8, 10]
let sum = reduce(numbers, add, 0); // 15
let numbers = push(numbers, 6); // [1, 2, 3, 4, 5, 6]
// Hashes
let person = {
"name": "John",
"age": 30,
"city": "New York"
};
let name = person["name"]; // "John"
print(name);
// Functions
let greet = fn(name) {
return "Hello, " + name + "!";
};
let greeting = greet("John"); // Returns "Hello, John!"
print(greeting);
// Conditionals
let max = fn(a, b) {
if (a > b) {
return a;
} else {
return b;
}
};
// Functions and closures
let makeAdder = fn(x) {
return fn(y) {
return x + y;
};
};
let addFive = makeAdder(5);
let mut result = addFive(10); // Returns 15
print(result);
result = addFive(20); // Returns 25
print(result);
// Recursive functions
let fib = fn(n) {
if (n <= 1) {
return n;
}
return fib(n - 1) + fib(n - 2);
};
let mut result = fib(10); // Calculate 10th Fibonacci number
print(result); // 55
// Pointers
let mut x = 5;
let p = &x;
print(*p); // 5
*p = 10;
print(x); // 10Ember treats variables as immutable by default. This means that once a variable is assigned a value, that value cannot be changed. This helps prevent bugs and makes code easier to reason about.
To create a mutable variable that can be reassigned, use the mut keyword:
// Immutable variable (default)
let x = 5;
// x = 10; // Error: Cannot assign to immutable variable: x
// Mutable variable
let mut y = 5;
y = 10; // Works fineEmber supports pointers to variables.
- Create pointers with the
&operator - Dereference pointers with the
*operator - Pointer arithmetic is not supported for memory safety
See the pointers example for more details.
You can use Ember in two ways:
If you just want to try Ember without installing:
cd ember_lang
make runThis will start the REPL (Read-Eval-Print Loop) interactive shell.
For full installation that allows running Ember files from anywhere:
- Clone the repository:
cd ember_lang- Install the Ember binary:
make installThis will install the ember command to /usr/local/bin/ember.
There are two ways to use Ember:
Start the REPL by running:
emberYou'll see:
Ember Programming Language v0.0.1 (prototype)
Type "help" for more information.
⟶
Run Ember files (with .em extension):
ember fibonacci.emCreate a file hello.em:
let greet = fn(name) {
return "Hello, " + name + "!";
};
print(greet("World"));Run it:
ember hello.emember_lang/
├── cmd/ember/ # Command-line interface
├── ember_lang/ # Implementation
│ ├── lexer/ # Tokenization
│ ├── parser/ # Syntax analysis
│ ├── ast/ # Abstract Syntax Tree
│ ├── token/ # Token definitions
│ ├── object/ # Runtime object system
│ ├── evaluator/ # Expression evaluation
│ └── repl/ # Interactive shell
└── docs/ # Documentation
└── examples/ # Example code
Requirements:
- Go 1.21 or later
- Make
Common tasks:
make build # Build the ember binary
make test # Run tests
make lint # Run linter
make run # Start REPL (during development)
make install # Install ember to /usr/local/binYou can enable debug output by setting the DEBUG environment variable:
DEBUG=1 ember fibonacci.emThis will show:
- Source code
- Token stream (lexical analysis)
- Abstract Syntax Tree (AST)
- Final result
The AST visualization shows the hierarchical structure of your code:
└── Program
└── Let Statement
├── Identifier: fibonacci
└── Function: fn(n)
└── Block Statement
├── If Expression
│ ├── Infix: <=
│ │ ├── Identifier: n
│ │ └── Integer: 1
The tree depth indicates:
- Code blocks and scopes
- Expression nesting
- Operator precedence
- Control flow structure