Finished.
This commit is contained in:
commit
e5202c9c85
8
Makefile
Normal file
8
Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
all: test examples
|
||||
|
||||
test:
|
||||
python3 nano.py test.nano
|
||||
|
||||
examples:
|
||||
python3 nano.py examples/*.nano
|
||||
171
README.md
Normal file
171
README.md
Normal file
@ -0,0 +1,171 @@
|
||||
# nano
|
||||
|
||||
A minimal interpreted programming language implemented in Python.
|
||||
|
||||
**Author:** retoor <retoor@molodetz.nl>
|
||||
|
||||
## Overview
|
||||
|
||||
nano is a dynamically typed scripting language with C-like syntax. The interpreter is implemented in approximately 500 lines of Python code. The language supports object-oriented programming with classes, constructors, destructors, and methods.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
python nano.py <filename.nano>
|
||||
```
|
||||
|
||||
## Language Features
|
||||
|
||||
### Data Types
|
||||
|
||||
| Type | Example |
|
||||
|---------|------------------------------|
|
||||
| int | `42` |
|
||||
| float | `3.14` |
|
||||
| string | `"hello"` or `'hello'` |
|
||||
| array | `{1, 2, 3}` |
|
||||
| null | `null` |
|
||||
| object | `new ClassName()` |
|
||||
|
||||
### Operators
|
||||
|
||||
**Arithmetic:** `+`, `-`, `*`, `/`, `%`
|
||||
|
||||
**Comparison:** `==`, `!=`, `<`, `>`, `<=`, `>=`
|
||||
|
||||
**Logical:** `&&`, `||`
|
||||
|
||||
**Assignment:** `=`, `+=`, `-=`, `*=`, `/=`
|
||||
|
||||
**Increment/Decrement:** `++`, `--`
|
||||
|
||||
**Pointer:** `&` (address-of), `*` (dereference)
|
||||
|
||||
### Control Flow
|
||||
|
||||
```
|
||||
if (condition) {
|
||||
// statements
|
||||
} else {
|
||||
// statements
|
||||
}
|
||||
|
||||
while (condition) {
|
||||
// statements
|
||||
}
|
||||
|
||||
for (init; condition; update) {
|
||||
// statements
|
||||
}
|
||||
```
|
||||
|
||||
### Classes
|
||||
|
||||
```
|
||||
class ClassName {
|
||||
property = initialValue;
|
||||
|
||||
ClassName(this, param1, param2) {
|
||||
this.property = param1;
|
||||
}
|
||||
|
||||
~ClassName(this) {
|
||||
// destructor
|
||||
}
|
||||
|
||||
method(this, arg) {
|
||||
return this.property + arg;
|
||||
}
|
||||
}
|
||||
|
||||
obj = new ClassName(value1, value2);
|
||||
obj.method(arg);
|
||||
```
|
||||
|
||||
### Functions
|
||||
|
||||
Methods support default parameters, variable arguments, and keyword arguments:
|
||||
|
||||
```
|
||||
method(this, required, optional = "default", *args, **kwargs) {
|
||||
// body
|
||||
}
|
||||
```
|
||||
|
||||
### Built-in Functions
|
||||
|
||||
| Function | Description |
|
||||
|-------------|--------------------------------------|
|
||||
| `print()` | Output values to console |
|
||||
| `len()` | Return length of string or array |
|
||||
| `str()` | Convert value to string |
|
||||
| `int()` | Convert value to integer |
|
||||
| `bool()` | Convert value to boolean (0 or 1) |
|
||||
| `typeof()` | Return type name as string |
|
||||
|
||||
### String Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------------|--------------------------------------|
|
||||
| `.substr(start, length)` | Extract substring |
|
||||
| `.split(delimiter)` | Split into array |
|
||||
| `.count(substr)` | Count occurrences |
|
||||
| `.indexOf(substr)` | Find first index |
|
||||
| `.toUpper()` | Convert to uppercase |
|
||||
| `.toLower()` | Convert to lowercase |
|
||||
| `.trim()` | Remove whitespace |
|
||||
| `.replace(old, new)` | Replace substring |
|
||||
| `.length` | String length property |
|
||||
|
||||
### Array Methods
|
||||
|
||||
| Method | Description |
|
||||
|------------------------|--------------------------------|
|
||||
| `.push(value)` | Append element |
|
||||
| `.pop()` | Remove and return last element |
|
||||
| `.join(separator)` | Join elements into string |
|
||||
| `.indexOf(value)` | Find index of element |
|
||||
| `.slice(start, end)` | Extract subarray |
|
||||
| `.length` | Array length property |
|
||||
|
||||
### Comments
|
||||
|
||||
```
|
||||
// single line comment
|
||||
|
||||
/* multi-line
|
||||
comment */
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
The `examples/` directory contains demonstrations of language features:
|
||||
|
||||
| File | Description |
|
||||
|-------------------|------------------------------------------|
|
||||
| `arrays.nano` | Array operations and iteration |
|
||||
| `classes.nano` | Class definitions and object creation |
|
||||
| `control_flow.nano` | Conditionals and loops |
|
||||
| `fibonacci.nano` | Fibonacci sequence calculation |
|
||||
| `functions.nano` | Method definitions and recursion |
|
||||
| `json.nano` | JSON encoder/decoder implementation |
|
||||
| `objects.nano` | Object composition and state management |
|
||||
| `operators.nano` | Arithmetic and logical operators |
|
||||
| `pointers.nano` | Pointer operations and references |
|
||||
| `strings.nano` | String manipulation methods |
|
||||
| `sudoku.nano` | Sudoku solver using backtracking |
|
||||
| `types.nano` | Type system and coercion |
|
||||
|
||||
## Implementation
|
||||
|
||||
The interpreter consists of:
|
||||
|
||||
- **Tokenizer:** Converts source code into tokens using regular expressions
|
||||
- **Parser:** Constructs syntax structures from token streams
|
||||
- **Runtime:** Executes parsed statements with scope management
|
||||
|
||||
Classes are stored as `NanoClass` objects containing properties, methods, constructor, and destructor definitions. Instances are `NanoObject` objects with their own property copies.
|
||||
|
||||
## License
|
||||
|
||||
MIT - Like always.
|
||||
101
examples/arrays.nano
Normal file
101
examples/arrays.nano
Normal file
@ -0,0 +1,101 @@
|
||||
print("=== Arrays Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- Array Literals ---");
|
||||
empty = {};
|
||||
print("Empty array length:", len(empty));
|
||||
|
||||
numbers = {1, 2, 3, 4, 5};
|
||||
print("Numbers:", numbers[0], numbers[1], numbers[2], numbers[3], numbers[4]);
|
||||
print("Length:", len(numbers));
|
||||
|
||||
mixed = {42, "hello", 3.14, null};
|
||||
print("Mixed array:");
|
||||
print(" int:", mixed[0]);
|
||||
print(" str:", mixed[1]);
|
||||
print(" float:", mixed[2]);
|
||||
print(" null:", mixed[3]);
|
||||
|
||||
print("");
|
||||
print("--- Array Indexing ---");
|
||||
fruits = {"apple", "banana", "cherry", "date"};
|
||||
print("First element:", fruits[0]);
|
||||
print("Last element:", fruits[3]);
|
||||
|
||||
print("");
|
||||
print("--- Array Modification ---");
|
||||
arr = {10, 20, 30};
|
||||
print("Before:", arr[0], arr[1], arr[2]);
|
||||
arr[1] = 25;
|
||||
print("After arr[1] = 25:", arr[0], arr[1], arr[2]);
|
||||
|
||||
print("");
|
||||
print("--- Array Methods ---");
|
||||
stack = {};
|
||||
stack.push(1);
|
||||
stack.push(2);
|
||||
stack.push(3);
|
||||
print("Stack length:", len(stack));
|
||||
|
||||
popped = stack.pop();
|
||||
print("Popped:", popped);
|
||||
print("After pop length:", len(stack));
|
||||
|
||||
print("");
|
||||
print("--- Array Join ---");
|
||||
words = {"Hello", "World"};
|
||||
sentence = words.join(" ");
|
||||
print("Joined with space:", sentence);
|
||||
|
||||
nums = {1, 2, 3};
|
||||
csv = nums.join(",");
|
||||
print("Joined with comma:", csv);
|
||||
|
||||
print("");
|
||||
print("--- Array indexOf ---");
|
||||
items = {"apple", "banana", "cherry"};
|
||||
idx = items.indexOf("banana");
|
||||
print("Index of 'banana':", idx);
|
||||
|
||||
idx = items.indexOf("grape");
|
||||
print("Index of 'grape' (not found):", idx);
|
||||
|
||||
print("");
|
||||
print("--- Array Slice ---");
|
||||
source = {0, 1, 2, 3, 4, 5};
|
||||
sliced = source.slice(2, 4);
|
||||
print("slice(2, 4):", sliced[0], sliced[1]);
|
||||
|
||||
print("");
|
||||
print("--- Iterating Arrays ---");
|
||||
colors = {"red", "green", "blue"};
|
||||
print("Colors:");
|
||||
for (i = 0; i < len(colors); i++) {
|
||||
print(" ", colors[i]);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Building Arrays ---");
|
||||
squares = {};
|
||||
for (i = 1; i <= 5; i++) {
|
||||
squares.push(i * i);
|
||||
}
|
||||
print("Squares of 1-5:");
|
||||
for (i = 0; i < len(squares); i++) {
|
||||
print(" ", squares[i]);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Nested Arrays ---");
|
||||
matrix = {
|
||||
{1, 2, 3},
|
||||
{4, 5, 6},
|
||||
{7, 8, 9}
|
||||
};
|
||||
print("3x3 Matrix:");
|
||||
for (row = 0; row < len(matrix); row++) {
|
||||
print(" ", matrix[row][0], matrix[row][1], matrix[row][2]);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("All array tests completed");
|
||||
139
examples/classes.nano
Normal file
139
examples/classes.nano
Normal file
@ -0,0 +1,139 @@
|
||||
class Animal {
|
||||
name = "Unknown";
|
||||
age = 0;
|
||||
_species = "Animal";
|
||||
|
||||
Animal(this, name, age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
print("Animal created:", this.name);
|
||||
}
|
||||
|
||||
~Animal(this) {
|
||||
print("Animal destroyed:", this.name);
|
||||
}
|
||||
|
||||
speak(this) {
|
||||
print(this.name, "makes a sound");
|
||||
}
|
||||
|
||||
getInfo(this) {
|
||||
return this.name + " is " + str(this.age) + " years old";
|
||||
}
|
||||
|
||||
birthday(this) {
|
||||
this.age++;
|
||||
print(this.name, "is now", this.age, "years old");
|
||||
}
|
||||
}
|
||||
|
||||
class Dog {
|
||||
name = "";
|
||||
age = 0;
|
||||
breed = "Unknown";
|
||||
_tricks = null;
|
||||
|
||||
Dog(this, name, age, breed = "Mixed") {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.breed = breed;
|
||||
this._tricks = {};
|
||||
print("Dog created:", this.name, "the", this.breed);
|
||||
}
|
||||
|
||||
speak(this) {
|
||||
print(this.name, "says: Woof!");
|
||||
}
|
||||
|
||||
fetch(this, item) {
|
||||
print(this.name, "fetches the", item);
|
||||
}
|
||||
|
||||
learnTrick(this, trick) {
|
||||
this._tricks.push(trick);
|
||||
print(this.name, "learned:", trick);
|
||||
}
|
||||
|
||||
performTricks(this) {
|
||||
if (len(this._tricks) == 0) {
|
||||
print(this.name, "doesn't know any tricks yet");
|
||||
return;
|
||||
}
|
||||
print(this.name + "'s tricks:");
|
||||
for (i = 0; i < len(this._tricks); i++) {
|
||||
print(" -", this._tricks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Cat {
|
||||
name = "";
|
||||
lives = 9;
|
||||
__secretThoughts = "I am plotting world domination";
|
||||
|
||||
Cat(this, name) {
|
||||
this.name = name;
|
||||
print("Cat created:", this.name);
|
||||
}
|
||||
|
||||
speak(this) {
|
||||
print(this.name, "says: Meow!");
|
||||
}
|
||||
|
||||
loseLife(this) {
|
||||
if (this.lives > 0) {
|
||||
this.lives--;
|
||||
print(this.name, "lost a life. Lives remaining:", this.lives);
|
||||
} else {
|
||||
print(this.name, "has no more lives!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print("=== Class System Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- Creating Animals ---");
|
||||
animal = new Animal("Generic", 5);
|
||||
animal.speak();
|
||||
print(animal.getInfo());
|
||||
animal.birthday();
|
||||
|
||||
print("");
|
||||
print("--- Dog Class ---");
|
||||
dog = new Dog("Buddy", 3, "Golden Retriever");
|
||||
dog.speak();
|
||||
dog.fetch("ball");
|
||||
dog.learnTrick("sit");
|
||||
dog.learnTrick("roll over");
|
||||
dog.learnTrick("play dead");
|
||||
dog.performTricks();
|
||||
|
||||
print("");
|
||||
print("--- Cat Class ---");
|
||||
cat = new Cat("Whiskers");
|
||||
cat.speak();
|
||||
print("Cat has", cat.lives, "lives");
|
||||
cat.loseLife();
|
||||
cat.loseLife();
|
||||
print("Cat now has", cat.lives, "lives");
|
||||
|
||||
print("");
|
||||
print("--- Default Parameters ---");
|
||||
mutt = new Dog("Max", 2);
|
||||
print("Breed:", mutt.breed);
|
||||
|
||||
print("");
|
||||
print("--- Property Access ---");
|
||||
print("Dog name:", dog.name);
|
||||
print("Dog age:", dog.age);
|
||||
print("Dog breed:", dog.breed);
|
||||
|
||||
dog.age = 4;
|
||||
print("Updated dog age:", dog.age);
|
||||
|
||||
print("");
|
||||
print("--- Convention-based Privacy ---");
|
||||
print("_species (single underscore):", animal._species);
|
||||
cat.__secretThoughts = "Actually, I just want treats";
|
||||
print("__secretThoughts (double underscore):", cat.__secretThoughts);
|
||||
143
examples/control_flow.nano
Normal file
143
examples/control_flow.nano
Normal file
@ -0,0 +1,143 @@
|
||||
print("=== Control Flow Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- If Statement ---");
|
||||
x = 10;
|
||||
if (x > 5) {
|
||||
print("x is greater than 5");
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- If-Else Statement ---");
|
||||
y = 3;
|
||||
if (y > 5) {
|
||||
print("y is greater than 5");
|
||||
} else {
|
||||
print("y is not greater than 5");
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- If-Else If-Else Chain ---");
|
||||
score = 85;
|
||||
print("Score:", score);
|
||||
if (score >= 90) {
|
||||
print("Grade: A");
|
||||
} else {
|
||||
if (score >= 80) {
|
||||
print("Grade: B");
|
||||
} else {
|
||||
if (score >= 70) {
|
||||
print("Grade: C");
|
||||
} else {
|
||||
if (score >= 60) {
|
||||
print("Grade: D");
|
||||
} else {
|
||||
print("Grade: F");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Nested If ---");
|
||||
a = 10;
|
||||
b = 20;
|
||||
if (a > 0) {
|
||||
if (b > 0) {
|
||||
print("Both a and b are positive");
|
||||
}
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- While Loop ---");
|
||||
print("Counting from 1 to 5:");
|
||||
i = 1;
|
||||
while (i <= 5) {
|
||||
print(" i =", i);
|
||||
i++;
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- While with Break Condition ---");
|
||||
sum = 0;
|
||||
n = 1;
|
||||
while (n <= 100) {
|
||||
sum += n;
|
||||
if (sum > 50) {
|
||||
print("Sum exceeded 50 at n =", n);
|
||||
print("Final sum:", sum);
|
||||
n = 101;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- For Loop ---");
|
||||
print("For loop 0 to 4:");
|
||||
for (i = 0; i < 5; i++) {
|
||||
print(" iteration", i);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- For Loop with Step ---");
|
||||
print("Counting by 2s:");
|
||||
for (i = 0; i <= 10; i += 2) {
|
||||
print(" i =", i);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Nested Loops ---");
|
||||
print("Multiplication table (3x3):");
|
||||
for (i = 1; i <= 3; i++) {
|
||||
row = "";
|
||||
for (j = 1; j <= 3; j++) {
|
||||
row += str(i * j);
|
||||
if (j < 3) {
|
||||
row += "\t";
|
||||
}
|
||||
}
|
||||
print(row);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Loop with Array ---");
|
||||
colors = {"red", "green", "blue", "yellow"};
|
||||
print("Colors:");
|
||||
for (i = 0; i < len(colors); i++) {
|
||||
print(" " + str(i) + ":", colors[i]);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Countdown ---");
|
||||
print("Countdown:");
|
||||
for (i = 5; i >= 1; i--) {
|
||||
print(" ", i);
|
||||
}
|
||||
print(" Blast off!");
|
||||
|
||||
print("");
|
||||
print("--- While True Pattern ---");
|
||||
attempts = 0;
|
||||
maxAttempts = 5;
|
||||
while (1) {
|
||||
attempts++;
|
||||
print("Attempt", attempts);
|
||||
if (attempts >= maxAttempts) {
|
||||
print("Max attempts reached");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Complex Condition ---");
|
||||
age = 25;
|
||||
hasLicense = 1;
|
||||
if (age >= 18 && hasLicense) {
|
||||
print("Can drive");
|
||||
}
|
||||
|
||||
isMember = 0;
|
||||
hasDiscount = 1;
|
||||
if (isMember || hasDiscount) {
|
||||
print("Eligible for discount");
|
||||
}
|
||||
26
examples/fibonacci.nano
Normal file
26
examples/fibonacci.nano
Normal file
@ -0,0 +1,26 @@
|
||||
class Fibonacci {
|
||||
Fibonacci(this) {
|
||||
}
|
||||
|
||||
calc(this, n) {
|
||||
if (n <= 1) {
|
||||
return n;
|
||||
}
|
||||
a = 0;
|
||||
b = 1;
|
||||
for (i = 2; i <= n; i++) {
|
||||
temp = a + b;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
print("Fibonacci Demo");
|
||||
fib = new Fibonacci();
|
||||
|
||||
for (n = 0; n <= 10; n++) {
|
||||
result = fib.calc(n);
|
||||
print("fib(" + str(n) + ") =", result);
|
||||
}
|
||||
254
examples/functions.nano
Normal file
254
examples/functions.nano
Normal file
@ -0,0 +1,254 @@
|
||||
print("=== Functions Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- Methods in Classes ---");
|
||||
class Calculator {
|
||||
Calculator(this) {
|
||||
}
|
||||
|
||||
add(this, a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
subtract(this, a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
multiply(this, a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
divide(this, a, b) {
|
||||
if (b == 0) {
|
||||
return 0;
|
||||
}
|
||||
return a / b;
|
||||
}
|
||||
}
|
||||
|
||||
calc = new Calculator();
|
||||
print("add(5, 3) =", calc.add(5, 3));
|
||||
print("subtract(10, 4) =", calc.subtract(10, 4));
|
||||
print("multiply(6, 7) =", calc.multiply(6, 7));
|
||||
print("divide(20, 4) =", calc.divide(20, 4));
|
||||
|
||||
print("");
|
||||
print("--- Required Parameters ---");
|
||||
class Greeter {
|
||||
Greeter(this) {
|
||||
}
|
||||
|
||||
greet(this, name) {
|
||||
print("Hello,", name + "!");
|
||||
}
|
||||
}
|
||||
|
||||
greeter = new Greeter();
|
||||
greeter.greet("Alice");
|
||||
greeter.greet("Bob");
|
||||
|
||||
print("");
|
||||
print("--- Optional Parameters with Defaults ---");
|
||||
class ConfigurableGreeter {
|
||||
ConfigurableGreeter(this) {
|
||||
}
|
||||
|
||||
greet(this, name, greeting = "Hello", punctuation = "!") {
|
||||
print(greeting + ",", name + punctuation);
|
||||
}
|
||||
}
|
||||
|
||||
cg = new ConfigurableGreeter();
|
||||
cg.greet("Alice");
|
||||
cg.greet("Bob", "Hi");
|
||||
cg.greet("Charlie", "Hey", "?");
|
||||
|
||||
print("");
|
||||
print("--- Null Default Values ---");
|
||||
class Formatter {
|
||||
Formatter(this) {
|
||||
}
|
||||
|
||||
format(this, value, prefix = null, suffix = null) {
|
||||
result = "";
|
||||
if (prefix) {
|
||||
result += prefix;
|
||||
}
|
||||
result += str(value);
|
||||
if (suffix) {
|
||||
result += suffix;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
fmt = new Formatter();
|
||||
print("No prefix/suffix:", fmt.format(42));
|
||||
print("With prefix:", fmt.format(42, "$"));
|
||||
print("With both:", fmt.format(42, "$", ".00"));
|
||||
|
||||
print("");
|
||||
print("--- Variable Arguments (*args) ---");
|
||||
class VarArgs {
|
||||
VarArgs(this) {
|
||||
}
|
||||
|
||||
printAll(this, *args) {
|
||||
print("Received", len(args), "arguments:");
|
||||
for (i = 0; i < len(args); i++) {
|
||||
print(" arg[" + str(i) + "] =", args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
sum(this, *numbers) {
|
||||
total = 0;
|
||||
for (i = 0; i < len(numbers); i++) {
|
||||
total += numbers[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
first(this, required, *rest) {
|
||||
print("Required:", required);
|
||||
print("Rest:", len(rest), "items");
|
||||
}
|
||||
}
|
||||
|
||||
va = new VarArgs();
|
||||
va.printAll(1, 2, 3);
|
||||
va.printAll("a", "b", "c", "d", "e");
|
||||
|
||||
print("sum(1,2,3,4,5) =", va.sum(1, 2, 3, 4, 5));
|
||||
|
||||
va.first("mandatory", "extra1", "extra2");
|
||||
|
||||
print("");
|
||||
print("--- Keyword Arguments (**kwargs) ---");
|
||||
class KwArgs {
|
||||
KwArgs(this) {
|
||||
}
|
||||
|
||||
configure(this, **options) {
|
||||
print("Configuration options:");
|
||||
print(" (kwargs captured as dict)");
|
||||
}
|
||||
}
|
||||
|
||||
kw = new KwArgs();
|
||||
kw.configure();
|
||||
|
||||
print("");
|
||||
print("--- Return Values ---");
|
||||
class Math {
|
||||
Math(this) {
|
||||
}
|
||||
|
||||
square(this, n) {
|
||||
return n * n;
|
||||
}
|
||||
|
||||
factorial(this, n) {
|
||||
if (n <= 1) {
|
||||
return 1;
|
||||
}
|
||||
return n * this.factorial(n - 1);
|
||||
}
|
||||
|
||||
abs(this, n) {
|
||||
if (n < 0) {
|
||||
return 0 - n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
max(this, a, b) {
|
||||
if (a > b) {
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
min(this, a, b) {
|
||||
if (a < b) {
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
math = new Math();
|
||||
print("square(7) =", math.square(7));
|
||||
print("factorial(5) =", math.factorial(5));
|
||||
print("abs(-42) =", math.abs(-42));
|
||||
print("max(10, 20) =", math.max(10, 20));
|
||||
print("min(10, 20) =", math.min(10, 20));
|
||||
|
||||
print("");
|
||||
print("--- Recursion ---");
|
||||
class Recursive {
|
||||
Recursive(this) {
|
||||
}
|
||||
|
||||
fibonacci(this, n) {
|
||||
if (n <= 1) {
|
||||
return n;
|
||||
}
|
||||
return this.fibonacci(n - 1) + this.fibonacci(n - 2);
|
||||
}
|
||||
|
||||
gcd(this, a, b) {
|
||||
if (b == 0) {
|
||||
return a;
|
||||
}
|
||||
return this.gcd(b, a % b);
|
||||
}
|
||||
|
||||
power(this, base, exp) {
|
||||
if (exp == 0) {
|
||||
return 1;
|
||||
}
|
||||
return base * this.power(base, exp - 1);
|
||||
}
|
||||
}
|
||||
|
||||
rec = new Recursive();
|
||||
print("fibonacci(10) =", rec.fibonacci(10));
|
||||
print("gcd(48, 18) =", rec.gcd(48, 18));
|
||||
print("power(2, 8) =", rec.power(2, 8));
|
||||
|
||||
print("");
|
||||
print("--- Method Chaining ---");
|
||||
class StringBuilder {
|
||||
buffer = "";
|
||||
|
||||
StringBuilder(this) {
|
||||
}
|
||||
|
||||
append(this, text) {
|
||||
this.buffer += text;
|
||||
return this;
|
||||
}
|
||||
|
||||
appendLine(this, text) {
|
||||
this.buffer += text + "\n";
|
||||
return this;
|
||||
}
|
||||
|
||||
toString(this) {
|
||||
return this.buffer;
|
||||
}
|
||||
|
||||
clear(this) {
|
||||
this.buffer = "";
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
sb = new StringBuilder();
|
||||
sb.append("Hello").append(" ").append("World").append("!");
|
||||
print("Result:", sb.toString());
|
||||
|
||||
sb.clear();
|
||||
sb.appendLine("Line 1").appendLine("Line 2").append("Line 3");
|
||||
print("Multi-line:");
|
||||
print(sb.toString());
|
||||
157
examples/json.nano
Normal file
157
examples/json.nano
Normal file
@ -0,0 +1,157 @@
|
||||
print("=== JSON Encoder Demo ===");
|
||||
print("");
|
||||
|
||||
class JSONEncoder {
|
||||
JSONEncoder(this) {
|
||||
}
|
||||
|
||||
encode(this, value) {
|
||||
t = typeof(value);
|
||||
if (t == "null") {
|
||||
return "null";
|
||||
}
|
||||
if (t == "int" || t == "float") {
|
||||
return str(value);
|
||||
}
|
||||
if (t == "str") {
|
||||
return "\"" + value + "\"";
|
||||
}
|
||||
if (t == "array") {
|
||||
return this.encodeArray(value);
|
||||
}
|
||||
return "null";
|
||||
}
|
||||
|
||||
encodeArray(this, arr) {
|
||||
result = "[";
|
||||
for (i = 0; i < len(arr); i++) {
|
||||
if (i > 0) {
|
||||
result += ",";
|
||||
}
|
||||
result += this.encode(arr[i]);
|
||||
}
|
||||
result += "]";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
encoder = new JSONEncoder();
|
||||
|
||||
print("Encoding primitives:");
|
||||
print(" null ->", encoder.encode(null));
|
||||
print(" 42 ->", encoder.encode(42));
|
||||
print(" 3.14 ->", encoder.encode(3.14));
|
||||
print(" \"hello\" ->", encoder.encode("hello"));
|
||||
|
||||
print("");
|
||||
print("Encoding arrays:");
|
||||
arr = {1, 2, 3};
|
||||
print(" {1, 2, 3} ->", encoder.encodeArray(arr));
|
||||
|
||||
mixed = {1, "two", 3};
|
||||
print(" {1, \"two\", 3} ->", encoder.encodeArray(mixed));
|
||||
|
||||
print("");
|
||||
print("=== JSON Decoder Demo ===");
|
||||
print("");
|
||||
|
||||
class JSONDecoder {
|
||||
input = "";
|
||||
pos = 0;
|
||||
|
||||
JSONDecoder(this) {
|
||||
}
|
||||
|
||||
decode(this, jsonStr) {
|
||||
this.input = jsonStr;
|
||||
this.pos = 0;
|
||||
return this.parseValue();
|
||||
}
|
||||
|
||||
parseValue(this) {
|
||||
this.skipWhitespace();
|
||||
if (this.pos >= this.input.length) {
|
||||
return null;
|
||||
}
|
||||
c = this.input.substr(this.pos, 1);
|
||||
if (c == "[") {
|
||||
return this.parseArray();
|
||||
}
|
||||
if (c == "n") {
|
||||
this.pos += 4;
|
||||
return null;
|
||||
}
|
||||
return this.parseNumber();
|
||||
}
|
||||
|
||||
parseNumber(this) {
|
||||
start = this.pos;
|
||||
while (this.pos < this.input.length) {
|
||||
c = this.input.substr(this.pos, 1);
|
||||
isDigit = (c == "0" || c == "1" || c == "2" || c == "3" || c == "4" || c == "5" || c == "6" || c == "7" || c == "8" || c == "9" || c == "-");
|
||||
if (isDigit == 0) {
|
||||
break;
|
||||
}
|
||||
this.pos++;
|
||||
}
|
||||
numStr = this.input.substr(start, this.pos - start);
|
||||
return int(numStr);
|
||||
}
|
||||
|
||||
parseArray(this) {
|
||||
this.pos++;
|
||||
result = {};
|
||||
this.skipWhitespace();
|
||||
if (this.pos < this.input.length) {
|
||||
c = this.input.substr(this.pos, 1);
|
||||
if (c == "]") {
|
||||
this.pos++;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
while (this.pos < this.input.length) {
|
||||
value = this.parseValue();
|
||||
result.push(value);
|
||||
this.skipWhitespace();
|
||||
if (this.pos >= this.input.length) {
|
||||
break;
|
||||
}
|
||||
c = this.input.substr(this.pos, 1);
|
||||
if (c == "]") {
|
||||
this.pos++;
|
||||
break;
|
||||
}
|
||||
if (c == ",") {
|
||||
this.pos++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
skipWhitespace(this) {
|
||||
while (this.pos < this.input.length) {
|
||||
c = this.input.substr(this.pos, 1);
|
||||
if (c != " ") {
|
||||
break;
|
||||
}
|
||||
this.pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decoder = new JSONDecoder();
|
||||
|
||||
print("Decoding numbers:");
|
||||
print(" \"123\" ->", decoder.decode("123"));
|
||||
print(" \"456\" ->", decoder.decode("456"));
|
||||
|
||||
print("");
|
||||
print("Decoding arrays:");
|
||||
decoded = decoder.decode("[1,2,3]");
|
||||
print(" \"[1,2,3]\" -> length:", len(decoded));
|
||||
print(" element 0:", decoded[0]);
|
||||
print(" element 1:", decoded[1]);
|
||||
print(" element 2:", decoded[2]);
|
||||
|
||||
print("");
|
||||
print("All JSON tests completed");
|
||||
220
examples/objects.nano
Normal file
220
examples/objects.nano
Normal file
@ -0,0 +1,220 @@
|
||||
print("=== Objects Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- Object Instantiation ---");
|
||||
class Point {
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
Point(this, x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
toString(this) {
|
||||
return "(" + str(this.x) + ", " + str(this.y) + ")";
|
||||
}
|
||||
|
||||
distanceFromOrigin(this) {
|
||||
return this.x * this.x + this.y * this.y;
|
||||
}
|
||||
}
|
||||
|
||||
p1 = new Point(3, 4);
|
||||
p2 = new Point(10, 20);
|
||||
|
||||
print("Point 1:", p1.toString());
|
||||
print("Point 2:", p2.toString());
|
||||
|
||||
print("");
|
||||
print("--- Property Access ---");
|
||||
print("p1.x =", p1.x);
|
||||
print("p1.y =", p1.y);
|
||||
print("p2.x =", p2.x);
|
||||
print("p2.y =", p2.y);
|
||||
|
||||
print("");
|
||||
print("--- Property Modification ---");
|
||||
p1.x = 100;
|
||||
p1.y = 200;
|
||||
print("After modification, p1:", p1.toString());
|
||||
|
||||
print("");
|
||||
print("--- Method Calls ---");
|
||||
print("p2.distanceFromOrigin():", p2.distanceFromOrigin());
|
||||
|
||||
print("");
|
||||
print("--- Multiple Objects ---");
|
||||
class Rectangle {
|
||||
width = 0;
|
||||
height = 0;
|
||||
|
||||
Rectangle(this, w, h) {
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
area(this) {
|
||||
return this.width * this.height;
|
||||
}
|
||||
|
||||
perimeter(this) {
|
||||
return 2 * (this.width + this.height);
|
||||
}
|
||||
}
|
||||
|
||||
rect1 = new Rectangle(5, 10);
|
||||
rect2 = new Rectangle(3, 7);
|
||||
rect3 = new Rectangle(8, 8);
|
||||
|
||||
print("Rectangle 1: " + str(rect1.width) + "x" + str(rect1.height));
|
||||
print(" Area:", rect1.area());
|
||||
print(" Perimeter:", rect1.perimeter());
|
||||
|
||||
print("Rectangle 2: " + str(rect2.width) + "x" + str(rect2.height));
|
||||
print(" Area:", rect2.area());
|
||||
print(" Perimeter:", rect2.perimeter());
|
||||
|
||||
print("Rectangle 3: " + str(rect3.width) + "x" + str(rect3.height));
|
||||
print(" Area:", rect3.area());
|
||||
print(" Perimeter:", rect3.perimeter());
|
||||
|
||||
print("");
|
||||
print("--- Object Composition ---");
|
||||
class Circle {
|
||||
center = null;
|
||||
radius = 0;
|
||||
|
||||
Circle(this, centerX, centerY, radius) {
|
||||
this.center = new Point(centerX, centerY);
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
describe(this) {
|
||||
print("Circle at", this.center.toString(), "with radius", this.radius);
|
||||
}
|
||||
}
|
||||
|
||||
circle = new Circle(5, 5, 10);
|
||||
circle.describe();
|
||||
print("Center x:", circle.center.x);
|
||||
print("Center y:", circle.center.y);
|
||||
|
||||
print("");
|
||||
print("--- Object Arrays ---");
|
||||
class Student {
|
||||
name = "";
|
||||
grade = 0;
|
||||
|
||||
Student(this, name, grade) {
|
||||
this.name = name;
|
||||
this.grade = grade;
|
||||
}
|
||||
}
|
||||
|
||||
students = {};
|
||||
students.push(new Student("Alice", 95));
|
||||
students.push(new Student("Bob", 87));
|
||||
students.push(new Student("Charlie", 92));
|
||||
students.push(new Student("Diana", 88));
|
||||
|
||||
print("Student Grades:");
|
||||
totalGrade = 0;
|
||||
for (i = 0; i < len(students); i++) {
|
||||
print(" " + students[i].name + ":", students[i].grade);
|
||||
totalGrade += students[i].grade;
|
||||
}
|
||||
average = totalGrade / len(students);
|
||||
print("Average grade:", average);
|
||||
|
||||
print("");
|
||||
print("--- Object State ---");
|
||||
class BankAccount {
|
||||
owner = "";
|
||||
balance = 0;
|
||||
transactions = null;
|
||||
|
||||
BankAccount(this, owner, initial) {
|
||||
this.owner = owner;
|
||||
this.balance = initial;
|
||||
this.transactions = {};
|
||||
this.transactions.push("Initial deposit: " + str(initial));
|
||||
}
|
||||
|
||||
deposit(this, amount) {
|
||||
this.balance += amount;
|
||||
this.transactions.push("Deposit: " + str(amount));
|
||||
}
|
||||
|
||||
withdraw(this, amount) {
|
||||
if (amount > this.balance) {
|
||||
print("Insufficient funds!");
|
||||
return 0;
|
||||
}
|
||||
this.balance -= amount;
|
||||
this.transactions.push("Withdrawal: " + str(amount));
|
||||
return 1;
|
||||
}
|
||||
|
||||
getStatement(this) {
|
||||
print("=== Account Statement ===");
|
||||
print("Owner:", this.owner);
|
||||
print("Transactions:");
|
||||
for (i = 0; i < len(this.transactions); i++) {
|
||||
print(" ", this.transactions[i]);
|
||||
}
|
||||
print("Current Balance:", this.balance);
|
||||
}
|
||||
}
|
||||
|
||||
account = new BankAccount("John Doe", 1000);
|
||||
account.deposit(500);
|
||||
account.deposit(250);
|
||||
account.withdraw(300);
|
||||
account.withdraw(100);
|
||||
account.getStatement();
|
||||
|
||||
print("");
|
||||
print("--- Object Equality ---");
|
||||
class Token {
|
||||
type = "";
|
||||
value = "";
|
||||
|
||||
Token(this, type, value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
equals(this, other) {
|
||||
return this.type == other.type && this.value == other.value;
|
||||
}
|
||||
}
|
||||
|
||||
t1 = new Token("NUMBER", "42");
|
||||
t2 = new Token("NUMBER", "42");
|
||||
t3 = new Token("STRING", "hello");
|
||||
|
||||
print("t1 equals t2:", t1.equals(t2));
|
||||
print("t1 equals t3:", t1.equals(t3));
|
||||
|
||||
print("");
|
||||
print("--- Factory Pattern ---");
|
||||
class ShapeFactory {
|
||||
ShapeFactory(this) {
|
||||
}
|
||||
|
||||
createRectangle(this, w, h) {
|
||||
return new Rectangle(w, h);
|
||||
}
|
||||
|
||||
createSquare(this, size) {
|
||||
return new Rectangle(size, size);
|
||||
}
|
||||
}
|
||||
|
||||
factory = new ShapeFactory();
|
||||
rect = factory.createRectangle(4, 6);
|
||||
square = factory.createSquare(5);
|
||||
|
||||
print("Rectangle area:", rect.area());
|
||||
print("Square area:", square.area());
|
||||
136
examples/operators.nano
Normal file
136
examples/operators.nano
Normal file
@ -0,0 +1,136 @@
|
||||
print("=== Operators Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- Arithmetic Operators ---");
|
||||
a = 20;
|
||||
b = 6;
|
||||
print("a =", a, ", b =", b);
|
||||
print("a + b =", a + b);
|
||||
print("a - b =", a - b);
|
||||
print("a * b =", a * b);
|
||||
print("a / b =", a / b);
|
||||
print("a % b =", a % b);
|
||||
|
||||
print("");
|
||||
print("--- Comparison Operators ---");
|
||||
x = 10;
|
||||
y = 20;
|
||||
z = 10;
|
||||
print("x =", x, ", y =", y, ", z =", z);
|
||||
print("x == z:", x == z);
|
||||
print("x != y:", x != y);
|
||||
print("x < y:", x < y);
|
||||
print("y > x:", y > x);
|
||||
print("x <= z:", x <= z);
|
||||
print("y >= x:", y >= x);
|
||||
|
||||
print("");
|
||||
print("--- Logical Operators ---");
|
||||
t = 1;
|
||||
f = 0;
|
||||
print("true (1) && true (1):", t && t);
|
||||
print("true (1) && false (0):", t && f);
|
||||
print("false (0) || true (1):", f || t);
|
||||
print("false (0) || false (0):", f || f);
|
||||
|
||||
print("");
|
||||
print("--- || for Default Values ---");
|
||||
value = null;
|
||||
result = value || "default";
|
||||
print("null || \"default\" =", result);
|
||||
|
||||
value = 0;
|
||||
result = value || 42;
|
||||
print("0 || 42 =", result);
|
||||
|
||||
value = "exists";
|
||||
result = value || "default";
|
||||
print("\"exists\" || \"default\" =", result);
|
||||
|
||||
value = 100;
|
||||
result = value || 0;
|
||||
print("100 || 0 =", result);
|
||||
|
||||
print("");
|
||||
print("--- String Concatenation ---");
|
||||
str1 = "Hello";
|
||||
str2 = "World";
|
||||
print("str1 + \" \" + str2 =", str1 + " " + str2);
|
||||
|
||||
greeting = "Hi";
|
||||
greeting += " there";
|
||||
print("After += :", greeting);
|
||||
|
||||
print("");
|
||||
print("--- Assignment Operators ---");
|
||||
n = 10;
|
||||
print("n =", n);
|
||||
|
||||
n += 5;
|
||||
print("n += 5 ->", n);
|
||||
|
||||
n -= 3;
|
||||
print("n -= 3 ->", n);
|
||||
|
||||
n *= 2;
|
||||
print("n *= 2 ->", n);
|
||||
|
||||
n /= 4;
|
||||
print("n /= 4 ->", n);
|
||||
|
||||
print("");
|
||||
print("--- Increment/Decrement ---");
|
||||
counter = 0;
|
||||
print("counter =", counter);
|
||||
|
||||
counter++;
|
||||
print("counter++ ->", counter);
|
||||
|
||||
counter++;
|
||||
print("counter++ ->", counter);
|
||||
|
||||
counter--;
|
||||
print("counter-- ->", counter);
|
||||
|
||||
++counter;
|
||||
print("++counter ->", counter);
|
||||
|
||||
--counter;
|
||||
print("--counter ->", counter);
|
||||
|
||||
print("");
|
||||
print("--- Operator Precedence ---");
|
||||
result = 2 + 3 * 4;
|
||||
print("2 + 3 * 4 =", result);
|
||||
|
||||
result = (2 + 3) * 4;
|
||||
print("(2 + 3) * 4 =", result);
|
||||
|
||||
result = 10 - 4 - 2;
|
||||
print("10 - 4 - 2 =", result);
|
||||
|
||||
result = 20 / 4 / 2;
|
||||
print("20 / 4 / 2 =", result);
|
||||
|
||||
print("");
|
||||
print("--- Combined Expressions ---");
|
||||
a = 5;
|
||||
b = 3;
|
||||
c = 2;
|
||||
result = a * b + c;
|
||||
print("5 * 3 + 2 =", result);
|
||||
|
||||
result = a + b * c;
|
||||
print("5 + 3 * 2 =", result);
|
||||
|
||||
result = (a + b) * c;
|
||||
print("(5 + 3) * 2 =", result);
|
||||
|
||||
print("");
|
||||
print("--- Comparison Chains ---");
|
||||
val = 15;
|
||||
inRange = val > 10 && val < 20;
|
||||
print("15 > 10 && 15 < 20:", inRange);
|
||||
|
||||
outRange = val < 10 || val > 20;
|
||||
print("15 < 10 || 15 > 20:", outRange);
|
||||
94
examples/pointers.nano
Normal file
94
examples/pointers.nano
Normal file
@ -0,0 +1,94 @@
|
||||
print("=== Pointers Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- Basic Pointer Operations ---");
|
||||
x = 42;
|
||||
print("x =", x);
|
||||
|
||||
ptr = &x;
|
||||
print("ptr = &x (pointer to x)");
|
||||
print("*ptr (dereferenced) =", *ptr);
|
||||
|
||||
print("");
|
||||
print("--- Simulating Pass by Reference ---");
|
||||
class RefDemo {
|
||||
RefDemo(this) {
|
||||
}
|
||||
|
||||
swap(this, a, b) {
|
||||
temp = a[0];
|
||||
a[0] = b[0];
|
||||
b[0] = temp;
|
||||
}
|
||||
|
||||
doubleValue(this, ref) {
|
||||
ref[0] = ref[0] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
demo = new RefDemo();
|
||||
|
||||
val1 = {10};
|
||||
val2 = {20};
|
||||
print("Before swap: val1 =", val1[0], ", val2 =", val2[0]);
|
||||
demo.swap(val1, val2);
|
||||
print("After swap: val1 =", val1[0], ", val2 =", val2[0]);
|
||||
|
||||
num = {50};
|
||||
print("Before double:", num[0]);
|
||||
demo.doubleValue(num);
|
||||
print("After double:", num[0]);
|
||||
|
||||
print("");
|
||||
print("--- Array as Reference Container ---");
|
||||
data = {1, 2, 3, 4, 5};
|
||||
print("Original array:");
|
||||
for (i = 0; i < len(data); i++) {
|
||||
print(" data[" + str(i) + "] =", data[i]);
|
||||
}
|
||||
|
||||
class ArrayModifier {
|
||||
ArrayModifier(this) {
|
||||
}
|
||||
|
||||
multiplyAll(this, arr, factor) {
|
||||
for (j = 0; j < len(arr); j++) {
|
||||
arr[j] = arr[j] * factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modifier = new ArrayModifier();
|
||||
modifier.multiplyAll(data, 10);
|
||||
|
||||
print("After multiplying by 10:");
|
||||
for (i = 0; i < len(data); i++) {
|
||||
print(" data[" + str(i) + "] =", data[i]);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Reference Wrapper Pattern ---");
|
||||
class Ref {
|
||||
value = null;
|
||||
|
||||
Ref(this, v) {
|
||||
this.value = v;
|
||||
}
|
||||
|
||||
get(this) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
set(this, v) {
|
||||
this.value = v;
|
||||
}
|
||||
}
|
||||
|
||||
refInt = new Ref(42);
|
||||
print("Ref value:", refInt.get());
|
||||
|
||||
refInt.set(100);
|
||||
print("After set(100):", refInt.get());
|
||||
|
||||
print("");
|
||||
print("All pointer tests completed");
|
||||
88
examples/strings.nano
Normal file
88
examples/strings.nano
Normal file
@ -0,0 +1,88 @@
|
||||
print("=== Strings Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- String Literals ---");
|
||||
single = 'Single quotes';
|
||||
double = "Double quotes";
|
||||
print(single);
|
||||
print(double);
|
||||
|
||||
print("");
|
||||
print("--- String Concatenation ---");
|
||||
first = "Hello";
|
||||
second = "World";
|
||||
combined = first + " " + second;
|
||||
print("Concatenated:", combined);
|
||||
|
||||
greeting = "Hi";
|
||||
greeting += " there!";
|
||||
print("Using +=:", greeting);
|
||||
|
||||
print("");
|
||||
print("--- String Length ---");
|
||||
text = "Hello, World!";
|
||||
print("Text:", text);
|
||||
print("Length:", text.length);
|
||||
|
||||
print("");
|
||||
print("--- Substring (substr) ---");
|
||||
myStr = "Hello, World!";
|
||||
print("Original:", myStr);
|
||||
print("substr(0, 5):", myStr.substr(0, 5));
|
||||
print("substr(7, 5):", myStr.substr(7, 5));
|
||||
|
||||
print("");
|
||||
print("--- String Split ---");
|
||||
csv = "apple,banana,cherry";
|
||||
parts = csv.split(",");
|
||||
print("CSV:", csv);
|
||||
print("Split result:");
|
||||
for (i = 0; i < len(parts); i++) {
|
||||
print(" ", parts[i]);
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- String Count ---");
|
||||
text = "abracadabra";
|
||||
print("Text:", text);
|
||||
print("Count of 'a':", text.count("a"));
|
||||
print("Count of 'br':", text.count("br"));
|
||||
|
||||
print("");
|
||||
print("--- String indexOf ---");
|
||||
testStr = "Hello, World!";
|
||||
print("String:", testStr);
|
||||
print("indexOf('World'):", testStr.indexOf("World"));
|
||||
print("indexOf('o'):", testStr.indexOf("o"));
|
||||
|
||||
print("");
|
||||
print("--- Case Conversion ---");
|
||||
mixed = "Hello World";
|
||||
print("Original:", mixed);
|
||||
print("toUpper():", mixed.toUpper());
|
||||
print("toLower():", mixed.toLower());
|
||||
|
||||
print("");
|
||||
print("--- String Trim ---");
|
||||
padded = " spaces ";
|
||||
print("Before trim:", padded);
|
||||
print("After trim:", padded.trim());
|
||||
|
||||
print("");
|
||||
print("--- String Replace ---");
|
||||
original = "Hello World";
|
||||
replaced = original.replace("World", "Nano");
|
||||
print("Replace 'World' with 'Nano':", replaced);
|
||||
|
||||
print("");
|
||||
print("--- Type Conversion ---");
|
||||
num = 42;
|
||||
numStr = str(num);
|
||||
print("Number to string:", numStr);
|
||||
|
||||
strNum = "123";
|
||||
parsed = int(strNum);
|
||||
print("String to number:", parsed);
|
||||
|
||||
print("");
|
||||
print("All string tests completed");
|
||||
102
examples/sudoku.nano
Normal file
102
examples/sudoku.nano
Normal file
@ -0,0 +1,102 @@
|
||||
class Sudoku {
|
||||
grid = null;
|
||||
size = 9;
|
||||
boxSize = 3;
|
||||
|
||||
Sudoku(this, puzzle) {
|
||||
this.grid = puzzle;
|
||||
}
|
||||
|
||||
isValid(this, row, col, num) {
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (this.grid[row * 9 + i] == num) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (this.grid[i * 9 + col] == num) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
boxRow = (row / 3) * 3;
|
||||
boxCol = (col / 3) * 3;
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
idx = (boxRow + i) * 9 + (boxCol + j);
|
||||
if (this.grid[idx] == num) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
solve(this) {
|
||||
for (row = 0; row < 9; row++) {
|
||||
for (col = 0; col < 9; col++) {
|
||||
idx = row * 9 + col;
|
||||
if (this.grid[idx] == 0) {
|
||||
for (num = 1; num <= 9; num++) {
|
||||
if (this.isValid(row, col, num)) {
|
||||
this.grid[idx] = num;
|
||||
if (this.solve()) {
|
||||
return 1;
|
||||
}
|
||||
this.grid[idx] = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
printGrid(this) {
|
||||
for (row = 0; row < 9; row++) {
|
||||
line = "";
|
||||
for (col = 0; col < 9; col++) {
|
||||
line += str(this.grid[row * 9 + col]);
|
||||
if (col < 8) {
|
||||
line += " ";
|
||||
}
|
||||
if (col == 2 || col == 5) {
|
||||
line += "| ";
|
||||
}
|
||||
}
|
||||
print(line);
|
||||
if (row == 2 || row == 5) {
|
||||
print("------+-------+------");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puzzle = {
|
||||
5, 3, 0, 0, 7, 0, 0, 0, 0,
|
||||
6, 0, 0, 1, 9, 5, 0, 0, 0,
|
||||
0, 9, 8, 0, 0, 0, 0, 6, 0,
|
||||
8, 0, 0, 0, 6, 0, 0, 0, 3,
|
||||
4, 0, 0, 8, 0, 3, 0, 0, 1,
|
||||
7, 0, 0, 0, 2, 0, 0, 0, 6,
|
||||
0, 6, 0, 0, 0, 0, 2, 8, 0,
|
||||
0, 0, 0, 4, 1, 9, 0, 0, 5,
|
||||
0, 0, 0, 0, 8, 0, 0, 7, 9
|
||||
};
|
||||
|
||||
print("Sudoku Puzzle:");
|
||||
print("==============");
|
||||
sudoku = new Sudoku(puzzle);
|
||||
sudoku.printGrid();
|
||||
|
||||
print("");
|
||||
print("Solving...");
|
||||
print("");
|
||||
|
||||
if (sudoku.solve()) {
|
||||
print("Solution:");
|
||||
print("=========");
|
||||
sudoku.printGrid();
|
||||
} else {
|
||||
print("No solution exists");
|
||||
}
|
||||
118
examples/types.nano
Normal file
118
examples/types.nano
Normal file
@ -0,0 +1,118 @@
|
||||
print("=== Type System Demo ===");
|
||||
print("");
|
||||
|
||||
print("--- Dynamic Typing ---");
|
||||
x = 42;
|
||||
print("x =", x, "type:", typeof(x));
|
||||
|
||||
x = "hello";
|
||||
print("x =", x, "type:", typeof(x));
|
||||
|
||||
x = {1, 2, 3};
|
||||
print("x = array, type:", typeof(x));
|
||||
|
||||
x = null;
|
||||
print("x =", x, "type:", typeof(x));
|
||||
|
||||
print("");
|
||||
print("--- Null Defaults ---");
|
||||
undeclared = null;
|
||||
print("null variable:", undeclared);
|
||||
|
||||
intDefault = int(null);
|
||||
print("int(null) =", intDefault);
|
||||
|
||||
strDefault = str(null);
|
||||
print("str(null) = \"" + strDefault + "\"");
|
||||
|
||||
boolDefault = bool(null);
|
||||
print("bool(null) =", boolDefault);
|
||||
|
||||
print("");
|
||||
print("--- Type Constructors ---");
|
||||
fromStr = int("123");
|
||||
print("int(\"123\") =", fromStr, "type:", typeof(fromStr));
|
||||
|
||||
fromInt = str(456);
|
||||
print("str(456) =", fromInt, "type:", typeof(fromInt));
|
||||
|
||||
fromFloat = int(3.14);
|
||||
print("int(3.14) =", fromFloat);
|
||||
|
||||
print("");
|
||||
print("--- Type Coercion ---");
|
||||
a = "The answer is: ";
|
||||
b = 42;
|
||||
result = a + str(b);
|
||||
print(result);
|
||||
|
||||
c = "10";
|
||||
d = int(c) + 5;
|
||||
print("\"10\" + 5 =", d);
|
||||
|
||||
print("");
|
||||
print("--- Boolean Context ---");
|
||||
print("Boolean evaluation (0 = false, nonzero = true):");
|
||||
|
||||
values = {0, 1, -1, 42, "", "hello"};
|
||||
names = {"0", "1", "-1", "42", "\"\"", "\"hello\""};
|
||||
|
||||
for (i = 0; i < len(values); i++) {
|
||||
if (values[i]) {
|
||||
print(names[i], "-> truthy");
|
||||
} else {
|
||||
print(names[i], "-> falsy");
|
||||
}
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Integer as Boolean ---");
|
||||
flag = 1;
|
||||
if (flag) {
|
||||
print("flag (1) is truthy");
|
||||
}
|
||||
|
||||
flag = 0;
|
||||
if (flag) {
|
||||
print("This won't print");
|
||||
} else {
|
||||
print("flag (0) is falsy");
|
||||
}
|
||||
|
||||
print("");
|
||||
print("--- Type Checking with typeof ---");
|
||||
checkTypes = {42, "text", null};
|
||||
typeNames = {"integer", "string", "null"};
|
||||
for (i = 0; i < len(checkTypes); i++) {
|
||||
print(typeNames[i], "->", typeof(checkTypes[i]));
|
||||
}
|
||||
|
||||
class TestClass {
|
||||
value = 0;
|
||||
TestClass(this) {
|
||||
}
|
||||
}
|
||||
obj = new TestClass();
|
||||
print("object -> type:", typeof(obj));
|
||||
|
||||
print("");
|
||||
print("--- Automatic Initialization ---");
|
||||
class DefaultValues {
|
||||
intVal = 0;
|
||||
strVal = "";
|
||||
boolVal = 0;
|
||||
nullVal = null;
|
||||
|
||||
DefaultValues(this) {
|
||||
}
|
||||
|
||||
showDefaults(this) {
|
||||
print("intVal:", this.intVal);
|
||||
print("strVal: \"" + this.strVal + "\"");
|
||||
print("boolVal:", this.boolVal);
|
||||
print("nullVal:", this.nullVal);
|
||||
}
|
||||
}
|
||||
|
||||
defaults = new DefaultValues();
|
||||
defaults.showDefaults();
|
||||
504
nano.py
Executable file
504
nano.py
Executable file
@ -0,0 +1,504 @@
|
||||
#!/usr/bin/env python3
|
||||
import re, copy
|
||||
|
||||
class Pointer:
|
||||
def __init__(s, v=None): s.val = v
|
||||
|
||||
class NanoClass:
|
||||
def __init__(s, n, p, m, c, d): s.name, s.props, s.methods, s.constructor, s.destructor = n, p, m, c, d
|
||||
|
||||
class NanoObject:
|
||||
def __init__(s, c, p): s._class, s._props = c, p
|
||||
|
||||
class Runtime:
|
||||
def __init__(s):
|
||||
s.classes, s.globals, s.locals_stack = {}, {}, [{}]
|
||||
s.return_value, s.returning = None, False
|
||||
|
||||
@property
|
||||
def locals(s): return s.locals_stack[-1]
|
||||
def push_scope(s): s.locals_stack.append({})
|
||||
def pop_scope(s): len(s.locals_stack) > 1 and s.locals_stack.pop()
|
||||
|
||||
def get_var(s, n):
|
||||
if n in s.locals: return s.locals[n]
|
||||
return s.globals.get(n)
|
||||
|
||||
def set_var(s, n, v):
|
||||
for sc in reversed(s.locals_stack):
|
||||
if n in sc: sc[n] = v; return
|
||||
if n in s.globals: s.globals[n] = v
|
||||
else: s.locals[n] = v
|
||||
|
||||
def set_local(s, n, v):
|
||||
s.locals[n] = v
|
||||
|
||||
def tokenize(s, c):
|
||||
c = re.sub(r'//[^\n]*', '', re.sub(r'/\*.*?\*/', '', c, flags=re.DOTALL))
|
||||
toks, pats = [], [
|
||||
(r'\"[^\"]*\"', 'S'), (r"\'[^\']*\'", 'S'), (r'\d+\.?\d*', 'N'),
|
||||
(r'class\b', 'CL'), (r'new\b', 'NW'), (r'if\b', 'IF'), (r'else\b', 'EL'),
|
||||
(r'while\b', 'WH'), (r'for\b', 'FR'), (r'return\b', 'RT'),
|
||||
(r'null\b', 'NU'), (r'true\b', 'TR'), (r'false\b', 'FA'),
|
||||
(r'\*\*', 'DS'), (r'\|\|', 'OR'), (r'&&', 'AN'), (r'==', 'EQ'), (r'!=', 'NE'),
|
||||
(r'<=', 'LE'), (r'>=', 'GE'), (r'\+=', 'PE'), (r'-=', 'ME'), (r'\*=', 'UE'),
|
||||
(r'/=', 'DE'), (r'\+\+', 'IC'), (r'--', 'DC'),
|
||||
(r'[a-zA-Z_][a-zA-Z0-9_]*', 'I'), (r'[{}()\[\];,.<>+\-*/%=!&|:~]', 'Y'), (r'\s+', None)]
|
||||
i = 0
|
||||
while i < len(c):
|
||||
for p, t in pats:
|
||||
m = re.match(p, c[i:])
|
||||
if m:
|
||||
t and toks.append((t, m.group()))
|
||||
i += len(m.group()); break
|
||||
else: i += 1
|
||||
return toks
|
||||
|
||||
def parse_block(s, t, st):
|
||||
if st >= len(t) or t[st] != ('Y', '{'): return [], st
|
||||
d, i, b = 1, st + 1, []
|
||||
while i < len(t) and d > 0:
|
||||
if t[i] == ('Y', '{'): d += 1
|
||||
elif t[i] == ('Y', '}'): d -= 1
|
||||
d > 0 and b.append(t[i]); i += 1
|
||||
return b, i
|
||||
|
||||
def parse_expr(s, t, st, es=None):
|
||||
es = es or [';', ',', ')', '}', ']']
|
||||
e, d, i = [], 0, st
|
||||
while i < len(t):
|
||||
x = t[i]
|
||||
if d == 0 and x[0] == 'Y' and x[1] in es: break
|
||||
if x[0] == 'Y' and x[1] in '([{': d += 1
|
||||
elif x[0] == 'Y' and x[1] in ')]}': d -= 1
|
||||
e.append(x); i += 1
|
||||
return e, i
|
||||
|
||||
def to_num(s, v):
|
||||
if v is None: return 0
|
||||
if isinstance(v, (int, float)): return v
|
||||
try: return int(v)
|
||||
except:
|
||||
try: return float(v)
|
||||
except: return 0
|
||||
|
||||
def is_truthy(s, v):
|
||||
if v is None: return False
|
||||
if isinstance(v, (int, float)): return v != 0
|
||||
if isinstance(v, (str, list)): return len(v) > 0
|
||||
return True
|
||||
|
||||
def eval_expr(s, t):
|
||||
if not t: return None
|
||||
if len(t) == 1:
|
||||
x = t[0]
|
||||
if x[0] == 'N': return float(x[1]) if '.' in x[1] else int(x[1])
|
||||
if x[0] == 'S': return x[1][1:-1]
|
||||
if x[0] == 'NU': return None
|
||||
if x[0] == 'TR': return 1
|
||||
if x[0] == 'FA': return 0
|
||||
if x[0] == 'I': return s.get_var(x[1])
|
||||
if t[0] == ('NW', 'new'): return s.eval_new(t[1:])
|
||||
if t[0] == ('Y', '*') and len(t) > 1:
|
||||
v = s.eval_expr(t[1:])
|
||||
return v.val if isinstance(v, Pointer) else v
|
||||
if t[0] == ('Y', '&') and len(t) > 1 and t[1][0] == 'I':
|
||||
return Pointer(s.get_var(t[1][1]))
|
||||
if t[0] == ('Y', '{'): return s.eval_array(t)
|
||||
for i, x in enumerate(t):
|
||||
if x == ('OR', '||'):
|
||||
l = s.eval_expr(t[:i])
|
||||
return l if s.is_truthy(l) else s.eval_expr(t[i+1:])
|
||||
for i, x in enumerate(t):
|
||||
if x == ('AN', '&&'):
|
||||
l = s.eval_expr(t[:i])
|
||||
return 0 if not s.is_truthy(l) else (1 if s.is_truthy(s.eval_expr(t[i+1:])) else 0)
|
||||
for op in [('EQ', '=='), ('NE', '!=')]:
|
||||
d = 0
|
||||
for i, x in enumerate(t):
|
||||
if x[0] == 'Y' and x[1] in '([{': d += 1
|
||||
elif x[0] == 'Y' and x[1] in ')]}': d -= 1
|
||||
if d == 0 and x == op:
|
||||
l, r = s.eval_expr(t[:i]), s.eval_expr(t[i+1:])
|
||||
return 1 if (l == r if op[1] == '==' else l != r) else 0
|
||||
for op in [('LE', '<='), ('GE', '>='), ('Y', '<'), ('Y', '>')]:
|
||||
d = 0
|
||||
for i, x in enumerate(t):
|
||||
if x[0] == 'Y' and x[1] in '([{': d += 1
|
||||
elif x[0] == 'Y' and x[1] in ')]}': d -= 1
|
||||
if d == 0 and x == op:
|
||||
l, r = s.to_num(s.eval_expr(t[:i])), s.to_num(s.eval_expr(t[i+1:]))
|
||||
if op[1] == '<': return 1 if l < r else 0
|
||||
if op[1] == '>': return 1 if l > r else 0
|
||||
if op[1] == '<=': return 1 if l <= r else 0
|
||||
if op[1] == '>=': return 1 if l >= r else 0
|
||||
d = 0
|
||||
for i in range(len(t) - 1, -1, -1):
|
||||
x = t[i]
|
||||
if x[0] == 'Y' and x[1] in ')]}': d += 1
|
||||
elif x[0] == 'Y' and x[1] in '([{': d -= 1
|
||||
if d == 0:
|
||||
if x == ('Y', '+') and i > 0:
|
||||
l, r = s.eval_expr(t[:i]), s.eval_expr(t[i+1:])
|
||||
if isinstance(l, str) or isinstance(r, str):
|
||||
return str(l if l is not None else '') + str(r if r is not None else '')
|
||||
return s.to_num(l) + s.to_num(r)
|
||||
if x == ('Y', '-') and i > 0:
|
||||
return s.to_num(s.eval_expr(t[:i])) - s.to_num(s.eval_expr(t[i+1:]))
|
||||
d = 0
|
||||
for i in range(len(t) - 1, -1, -1):
|
||||
x = t[i]
|
||||
if x[0] == 'Y' and x[1] in ')]}': d += 1
|
||||
elif x[0] == 'Y' and x[1] in '([{': d -= 1
|
||||
if d == 0:
|
||||
if x == ('Y', '*') and i > 0:
|
||||
return s.to_num(s.eval_expr(t[:i])) * s.to_num(s.eval_expr(t[i+1:]))
|
||||
if x == ('Y', '/') and i > 0:
|
||||
r = s.to_num(s.eval_expr(t[i+1:]))
|
||||
return s.to_num(s.eval_expr(t[:i])) / r if r else 0
|
||||
if x == ('Y', '%') and i > 0:
|
||||
r = s.to_num(s.eval_expr(t[i+1:]))
|
||||
return s.to_num(s.eval_expr(t[:i])) % r if r else 0
|
||||
if t[0] == ('Y', '('):
|
||||
d, i = 1, 1
|
||||
while i < len(t) and d > 0:
|
||||
if t[i] == ('Y', '('): d += 1
|
||||
elif t[i] == ('Y', ')'): d -= 1
|
||||
i += 1
|
||||
return s.eval_expr(t[1:i-1])
|
||||
if len(t) >= 2 and t[0][0] == 'I':
|
||||
if t[1] == ('Y', '('): return s.eval_call(t)
|
||||
if t[1] == ('Y', '.'): return s.eval_member(t)
|
||||
if t[1] == ('Y', '['): return s.eval_index(t)
|
||||
return None
|
||||
|
||||
def eval_array(s, t):
|
||||
if not t or t[0] != ('Y', '{'): return []
|
||||
items, i = [], 1
|
||||
while i < len(t) and t[i] != ('Y', '}'):
|
||||
e, i = s.parse_expr(t, i, [',', '}'])
|
||||
e and items.append(s.eval_expr(e))
|
||||
i < len(t) and t[i] == ('Y', ',') and (i := i + 1)
|
||||
return items
|
||||
|
||||
def eval_new(s, t):
|
||||
if not t or t[0][0] != 'I': return None
|
||||
c = s.classes.get(t[0][1])
|
||||
if not c: return None
|
||||
o = NanoObject(c, copy.deepcopy(c.props))
|
||||
a = s.parse_args(t, 1) if len(t) > 1 and t[1] == ('Y', '(') else []
|
||||
c.constructor and s.call_method(o, c.constructor, a)
|
||||
return o
|
||||
|
||||
def parse_args(s, t, st):
|
||||
if st >= len(t) or t[st] != ('Y', '('): return []
|
||||
a, i, d = [], st + 1, 1
|
||||
while i < len(t) and d > 0:
|
||||
if t[i] == ('Y', ')'):
|
||||
d -= 1
|
||||
if d == 0: break
|
||||
i += 1; continue
|
||||
if t[i] == ('Y', '('): d += 1
|
||||
e, i = s.parse_expr(t, i, [',', ')'])
|
||||
e and a.append(s.eval_expr(e))
|
||||
i < len(t) and t[i] == ('Y', ',') and (i := i + 1)
|
||||
return a
|
||||
|
||||
def eval_call(s, t):
|
||||
n, a = t[0][1], s.parse_args(t, 1)
|
||||
if n == 'print': print(*a); return
|
||||
if n == 'len': return len(a[0]) if a and a[0] else 0
|
||||
if n == 'str': return str(a[0]) if a and a[0] is not None else ''
|
||||
if n == 'int':
|
||||
if not a or a[0] is None: return 0
|
||||
try: return int(float(a[0]))
|
||||
except: return 0
|
||||
if n == 'bool': return 1 if a and s.is_truthy(a[0]) else 0
|
||||
if n == 'typeof':
|
||||
if not a: return 'null'
|
||||
v = a[0]
|
||||
if v is None: return 'null'
|
||||
if isinstance(v, int): return 'int'
|
||||
if isinstance(v, float): return 'float'
|
||||
if isinstance(v, str): return 'str'
|
||||
if isinstance(v, list): return 'array'
|
||||
if isinstance(v, NanoObject): return v._class.name
|
||||
return 'unknown'
|
||||
f = s.get_var(n)
|
||||
if f and isinstance(f, tuple) and len(f) == 2: return s.call_func(f[0], f[1], a)
|
||||
return None
|
||||
|
||||
def call_func(s, ps, bd, ar):
|
||||
s.push_scope()
|
||||
rp, va, vk = [], None, None
|
||||
for p in ps:
|
||||
if p.startswith('**'): vk = p[2:]
|
||||
elif p.startswith('*'): va = p[1:]
|
||||
else: rp.append(p)
|
||||
for i, p in enumerate(rp):
|
||||
if '=' in p:
|
||||
pn, df = p.split('=', 1)
|
||||
s.set_local(pn.strip(), ar[i] if i < len(ar) else s.eval_expr(s.tokenize(df.strip())))
|
||||
else: s.set_local(p.strip(), ar[i] if i < len(ar) else None)
|
||||
va and s.set_local(va, list(ar[len(rp):]))
|
||||
vk and s.set_local(vk, {})
|
||||
s.returning, s.return_value = False, None
|
||||
s.execute_block(bd)
|
||||
r = s.return_value
|
||||
s.returning, s.return_value = False, None
|
||||
s.pop_scope()
|
||||
return r
|
||||
|
||||
def eval_member(s, t):
|
||||
o, i = s.get_var(t[0][1]), 2
|
||||
while i < len(t):
|
||||
if t[i] == ('Y', '['):
|
||||
e, j = s.parse_expr(t, i + 1, [']'])
|
||||
idx = s.eval_expr(e)
|
||||
if isinstance(o, (list, str)):
|
||||
idx = int(idx) if idx is not None else 0
|
||||
o = o[idx] if 0 <= idx < len(o) else None
|
||||
elif isinstance(o, dict):
|
||||
o = o.get(idx)
|
||||
i = j + 1
|
||||
continue
|
||||
if t[i][0] != 'I': break
|
||||
m = t[i][1]; i += 1
|
||||
if i < len(t) and t[i] == ('Y', '('):
|
||||
a = s.parse_args(t, i)
|
||||
o = s.call_obj_method(o, m, a)
|
||||
d = 1; i += 1
|
||||
while i < len(t) and d > 0:
|
||||
if t[i] == ('Y', '('): d += 1
|
||||
elif t[i] == ('Y', ')'): d -= 1
|
||||
i += 1
|
||||
else:
|
||||
if isinstance(o, NanoObject): o = o._props.get(m)
|
||||
elif isinstance(o, dict): o = o.get(m)
|
||||
elif isinstance(o, str) and m == 'length': o = len(o)
|
||||
elif isinstance(o, list) and m == 'length': o = len(o)
|
||||
if i < len(t) and t[i] == ('Y', '.'): i += 1
|
||||
elif i < len(t) and t[i] == ('Y', '['): pass
|
||||
else: break
|
||||
return o
|
||||
|
||||
def call_obj_method(s, o, m, a):
|
||||
if isinstance(o, str):
|
||||
if m == 'substr': return o[int(a[0]) if a else 0:(int(a[0]) if a else 0)+(int(a[1]) if len(a)>1 else len(o))]
|
||||
if m == 'split': return o.split(a[0] if a else ' ')
|
||||
if m == 'count': return o.count(a[0] if a else '')
|
||||
if m == 'indexOf': return o.find(a[0] if a else '')
|
||||
if m == 'toUpper': return o.upper()
|
||||
if m == 'toLower': return o.lower()
|
||||
if m == 'trim': return o.strip()
|
||||
if m == 'replace': return o.replace(a[0] if a else '', a[1] if len(a)>1 else '')
|
||||
if isinstance(o, list):
|
||||
if m == 'push': o.append(a[0] if a else None); return len(o)
|
||||
if m == 'pop': return o.pop() if o else None
|
||||
if m == 'join': return (str(a[0]) if a else '').join(str(x) for x in o)
|
||||
if m == 'indexOf':
|
||||
try: return o.index(a[0] if a else None)
|
||||
except: return -1
|
||||
if m == 'slice': return o[int(a[0]) if a else 0:int(a[1]) if len(a)>1 else len(o)]
|
||||
if isinstance(o, NanoObject) and m in o._class.methods:
|
||||
return s.call_method(o, o._class.methods[m], a)
|
||||
return None
|
||||
|
||||
def call_method(s, o, md, ar):
|
||||
ps, bd = md
|
||||
s.push_scope()
|
||||
rp, va, vk = [], None, None
|
||||
for p in ps:
|
||||
if p.startswith('**'): vk = p[2:]
|
||||
elif p.startswith('*'): va = p[1:]
|
||||
else: rp.append(p)
|
||||
if rp and rp[0].strip() == 'this': s.set_local('this', o); rp = rp[1:]
|
||||
for i, p in enumerate(rp):
|
||||
if '=' in p:
|
||||
pn, df = p.split('=', 1)
|
||||
s.set_local(pn.strip(), ar[i] if i < len(ar) else s.eval_expr(s.tokenize(df.strip())))
|
||||
else: s.set_local(p.strip(), ar[i] if i < len(ar) else None)
|
||||
va and s.set_local(va, list(ar[len(rp):]))
|
||||
vk and s.set_local(vk, {})
|
||||
s.returning, s.return_value = False, None
|
||||
s.execute_block(bd)
|
||||
r = s.return_value
|
||||
s.returning, s.return_value = False, None
|
||||
s.pop_scope()
|
||||
return r
|
||||
|
||||
def eval_index(s, t):
|
||||
o = s.get_var(t[0][1])
|
||||
i = 1
|
||||
while i < len(t) and t[i] == ('Y', '['):
|
||||
e, j = s.parse_expr(t, i + 1, [']'])
|
||||
idx = s.eval_expr(e)
|
||||
if isinstance(o, (list, str)):
|
||||
idx = int(idx) if idx is not None else 0
|
||||
o = o[idx] if 0 <= idx < len(o) else None
|
||||
elif isinstance(o, dict):
|
||||
o = o.get(idx)
|
||||
else:
|
||||
return None
|
||||
i = j + 1
|
||||
return o
|
||||
|
||||
def execute(s, c): s.execute_tokens(s.tokenize(c))
|
||||
|
||||
def execute_tokens(s, t):
|
||||
i = 0
|
||||
while i < len(t):
|
||||
if s.returning: return s.return_value
|
||||
if t[i] == ('CL', 'class'): i = s.parse_class(t, i)
|
||||
elif t[i] == ('IF', 'if'): i = s.execute_if(t, i)
|
||||
elif t[i] == ('WH', 'while'): i = s.execute_while(t, i)
|
||||
elif t[i] == ('FR', 'for'): i = s.execute_for(t, i)
|
||||
elif t[i] == ('RT', 'return'):
|
||||
e, i = s.parse_expr(t, i + 1, [';'])
|
||||
s.return_value, s.returning = s.eval_expr(e), True
|
||||
return s.return_value
|
||||
else:
|
||||
st, i = s.parse_expr(t, i, [';'])
|
||||
st and s.execute_stmt(st)
|
||||
i < len(t) and t[i] == ('Y', ';') and (i := i + 1)
|
||||
return None
|
||||
|
||||
def execute_block(s, t): return s.execute_tokens(t)
|
||||
|
||||
def parse_class(s, t, st):
|
||||
n = t[st + 1][1]
|
||||
bd, i = s.parse_block(t, st + 2)
|
||||
ps, ms, ct, dt, j = {}, {}, None, None, 0
|
||||
while j < len(bd):
|
||||
if bd[j] == ('Y', '~') and j + 1 < len(bd):
|
||||
j += 1
|
||||
if bd[j][0] == 'I' and bd[j][1] == n:
|
||||
j += 1
|
||||
pm, j = s.parse_params(bd, j)
|
||||
mb, j = s.parse_block(bd, j)
|
||||
dt = (pm, mb)
|
||||
elif bd[j][0] == 'I':
|
||||
pn = bd[j][1]; j += 1
|
||||
if j < len(bd) and bd[j] == ('Y', '('):
|
||||
pm, j = s.parse_params(bd, j)
|
||||
mb, j = s.parse_block(bd, j)
|
||||
if pn == n: ct = (pm, mb)
|
||||
else: ms[pn] = (pm, mb)
|
||||
elif j < len(bd) and bd[j] == ('Y', '='):
|
||||
j += 1
|
||||
e, j = s.parse_expr(bd, j, [';'])
|
||||
ps[pn] = s.eval_expr(e)
|
||||
j < len(bd) and bd[j] == ('Y', ';') and (j := j + 1)
|
||||
else:
|
||||
ps[pn] = None
|
||||
j < len(bd) and bd[j] == ('Y', ';') and (j := j + 1)
|
||||
else: j += 1
|
||||
s.classes[n] = NanoClass(n, ps, ms, ct, dt)
|
||||
return i
|
||||
|
||||
def parse_params(s, t, st):
|
||||
if st >= len(t) or t[st] != ('Y', '('): return [], st
|
||||
ps, i, c, d = [], st + 1, '', 0
|
||||
while i < len(t):
|
||||
x = t[i]
|
||||
if x == ('Y', '('): d += 1; c += x[1]
|
||||
elif x == ('Y', ')'):
|
||||
if d == 0: c.strip() and ps.append(c.strip()); i += 1; break
|
||||
d -= 1; c += x[1]
|
||||
elif x == ('Y', ',') and d == 0: c.strip() and ps.append(c.strip()); c = ''
|
||||
else: c += x[1]
|
||||
i += 1
|
||||
return ps, i
|
||||
|
||||
def execute_if(s, t, st):
|
||||
i = st + 1
|
||||
if i >= len(t) or t[i] != ('Y', '('): return i
|
||||
cd, i = s.parse_expr(t, i + 1, [')']); i += 1
|
||||
bd, i = s.parse_block(t, i)
|
||||
eb = []
|
||||
if i < len(t) and t[i] == ('EL', 'else'):
|
||||
i += 1
|
||||
if i < len(t) and t[i] == ('IF', 'if'):
|
||||
return s.execute_if(t, i) if not s.is_truthy(s.eval_expr(cd)) else i
|
||||
eb, i = s.parse_block(t, i)
|
||||
if s.is_truthy(s.eval_expr(cd)): s.execute_block(bd)
|
||||
elif eb: s.execute_block(eb)
|
||||
return i
|
||||
|
||||
def execute_while(s, t, st):
|
||||
i = st + 1
|
||||
if i >= len(t) or t[i] != ('Y', '('): return i
|
||||
cd, ce = s.parse_expr(t, i + 1, [')'])
|
||||
bd, i = s.parse_block(t, ce + 1)
|
||||
while s.is_truthy(s.eval_expr(cd)):
|
||||
s.execute_block(bd)
|
||||
if s.returning: break
|
||||
return i
|
||||
|
||||
def execute_for(s, t, st):
|
||||
i = st + 1
|
||||
if i >= len(t) or t[i] != ('Y', '('): return i
|
||||
it, i = s.parse_expr(t, i + 1, [';'])
|
||||
it and s.execute_stmt(it); i += 1
|
||||
cd, i = s.parse_expr(t, i, [';']); i += 1
|
||||
up, i = s.parse_expr(t, i, [')']); i += 1
|
||||
bd, i = s.parse_block(t, i)
|
||||
while s.is_truthy(s.eval_expr(cd)):
|
||||
s.execute_block(bd)
|
||||
if s.returning: break
|
||||
up and s.execute_stmt(up)
|
||||
return i
|
||||
|
||||
def execute_stmt(s, t):
|
||||
if not t: return
|
||||
for i, x in enumerate(t):
|
||||
if x == ('PE', '+='):
|
||||
tg, vl = t[:i], s.eval_expr(t[i+1:])
|
||||
cr = s.eval_expr(tg)
|
||||
nv = str(cr if cr is not None else '') + str(vl if vl is not None else '') if isinstance(cr, str) or isinstance(vl, str) else s.to_num(cr) + s.to_num(vl)
|
||||
s.assign(tg, nv); return
|
||||
if x == ('ME', '-='): s.assign(t[:i], s.to_num(s.eval_expr(t[:i])) - s.to_num(s.eval_expr(t[i+1:]))); return
|
||||
if x == ('UE', '*='): s.assign(t[:i], s.to_num(s.eval_expr(t[:i])) * s.to_num(s.eval_expr(t[i+1:]))); return
|
||||
if x == ('DE', '/='):
|
||||
r = s.to_num(s.eval_expr(t[i+1:]))
|
||||
s.assign(t[:i], s.to_num(s.eval_expr(t[:i])) / r if r else 0); return
|
||||
if x == ('Y', '='): s.assign(t[:i], s.eval_expr(t[i+1:])); return
|
||||
for i, x in enumerate(t):
|
||||
if x == ('IC', '++'): tg = t[:i] if i > 0 else t[i+1:]; s.assign(tg, s.to_num(s.eval_expr(tg)) + 1); return
|
||||
if x == ('DC', '--'): tg = t[:i] if i > 0 else t[i+1:]; s.assign(tg, s.to_num(s.eval_expr(tg)) - 1); return
|
||||
s.eval_expr(t)
|
||||
|
||||
def assign(s, tg, v):
|
||||
if not tg: return
|
||||
if len(tg) == 1 and tg[0][0] == 'I': s.set_var(tg[0][1], v); return
|
||||
if len(tg) >= 3 and tg[1] == ('Y', '.'):
|
||||
o, i = s.get_var(tg[0][1]), 2
|
||||
while i < len(tg) - 2:
|
||||
m = tg[i][1]
|
||||
if isinstance(o, NanoObject): o = o._props.get(m)
|
||||
elif isinstance(o, dict): o = o.get(m)
|
||||
i += 2
|
||||
m = tg[i][1]
|
||||
if isinstance(o, NanoObject): o._props[m] = v
|
||||
elif isinstance(o, dict): o[m] = v
|
||||
return
|
||||
if len(tg) >= 3 and tg[1] == ('Y', '['):
|
||||
o = s.get_var(tg[0][1])
|
||||
e, _ = s.parse_expr(tg, 2, [']'])
|
||||
idx = s.eval_expr(e)
|
||||
if isinstance(o, list):
|
||||
idx = int(idx) if idx is not None else 0
|
||||
while len(o) <= idx: o.append(None)
|
||||
o[idx] = v
|
||||
elif isinstance(o, dict): o[idx] = v
|
||||
return
|
||||
if tg[0] == ('Y', '*'):
|
||||
p = s.eval_expr(tg[1:])
|
||||
isinstance(p, Pointer) and setattr(p, 'val', v)
|
||||
|
||||
def run_file(fn):
|
||||
with open(fn) as f: Runtime().execute(f.read())
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
len(sys.argv) > 1 and run_file(sys.argv[1]) or print("Usage: python nano.py <filename>")
|
||||
139
test.nano
Normal file
139
test.nano
Normal file
@ -0,0 +1,139 @@
|
||||
class Person {
|
||||
name = "Unknown";
|
||||
age = 0;
|
||||
_temp = null;
|
||||
|
||||
Person(this, name, age = 18) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
~Person(this) {
|
||||
print("Person destroyed:", this.name);
|
||||
}
|
||||
|
||||
greet(this) {
|
||||
print("Hello, I am", this.name, "and I am", this.age, "years old");
|
||||
}
|
||||
|
||||
setAge(this, newAge) {
|
||||
this.age = newAge;
|
||||
}
|
||||
}
|
||||
|
||||
person = new Person("Alice", 25);
|
||||
person.greet();
|
||||
|
||||
person2 = new Person("Bob");
|
||||
person2.greet();
|
||||
|
||||
person.setAge(30);
|
||||
print("Alice new age:", person.age);
|
||||
|
||||
x = 10;
|
||||
y = 20;
|
||||
print("Sum:", x + y);
|
||||
print("Product:", x * y);
|
||||
|
||||
str1 = "Hello";
|
||||
str2 = " World";
|
||||
result = str1 + str2;
|
||||
print("Concatenation:", result);
|
||||
|
||||
str1 += "!";
|
||||
print("After +=:", str1);
|
||||
|
||||
count = 0;
|
||||
while (count < 3) {
|
||||
print("Count:", count);
|
||||
count++;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
print("For loop i:", i);
|
||||
}
|
||||
|
||||
val = null || 5;
|
||||
print("Default value:", val);
|
||||
|
||||
val2 = 10 || 5;
|
||||
print("Existing value:", val2);
|
||||
|
||||
if (1) {
|
||||
print("Truthy: 1 is true");
|
||||
}
|
||||
|
||||
if (0) {
|
||||
print("This should not print");
|
||||
} else {
|
||||
print("Falsy: 0 is false");
|
||||
}
|
||||
|
||||
arr = {1, 2, 3, 4, 5};
|
||||
print("Array element 0:", arr[0]);
|
||||
print("Array element 2:", arr[2]);
|
||||
|
||||
arr[1] = 10;
|
||||
print("Modified array element 1:", arr[1]);
|
||||
|
||||
testStr = "hello world";
|
||||
print("Substr:", testStr.substr(0, 5));
|
||||
print("Count 'o':", testStr.count("o"));
|
||||
|
||||
parts = testStr.split(" ");
|
||||
print("Split result count:", len(parts));
|
||||
|
||||
numStr = "42";
|
||||
num = int(numStr);
|
||||
print("Converted to int:", num);
|
||||
|
||||
converted = str(123);
|
||||
print("Converted to str:", converted);
|
||||
|
||||
class Counter {
|
||||
value = 0;
|
||||
|
||||
Counter(this, start = 0) {
|
||||
this.value = start;
|
||||
}
|
||||
|
||||
increment(this) {
|
||||
this.value++;
|
||||
}
|
||||
|
||||
decrement(this) {
|
||||
this.value--;
|
||||
}
|
||||
|
||||
getValue(this) {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
counter = new Counter(5);
|
||||
print("Counter initial:", counter.getValue());
|
||||
counter.increment();
|
||||
counter.increment();
|
||||
print("Counter after 2 increments:", counter.getValue());
|
||||
counter.decrement();
|
||||
print("Counter after decrement:", counter.getValue());
|
||||
|
||||
a = 5;
|
||||
b = 5;
|
||||
if (a == b) {
|
||||
print("a equals b");
|
||||
}
|
||||
|
||||
if (a != 10) {
|
||||
print("a is not 10");
|
||||
}
|
||||
|
||||
if (a < 10 && b < 10) {
|
||||
print("Both a and b are less than 10");
|
||||
}
|
||||
|
||||
if (a > 10 || b < 10) {
|
||||
print("Either a > 10 or b < 10");
|
||||
}
|
||||
|
||||
print("All tests completed successfully");
|
||||
Loading…
Reference in New Issue
Block a user