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