feat: add object field mutation support with dot-assignment syntax and setter methods

Add parser support for direct field mutation via `obj.field = expr` syntax, enabling mutable object state after creation. Extend the OOP test suite with dedicated mutation tests (`oop_mutation_test.rc`) and advanced examples (`oop_advanced.rc`) covering BankAccount, Player, and Rectangle classes. Update `oop_working.rc` with mutation test cases and revise TUTORIAL.md documentation to describe field mutation, setter methods, and complete OOP examples with mutation. Add Makefile targets for running the new mutation and advanced tests.
This commit is contained in:
2025-11-23 22:23:17 +00:00
parent 0ea0f8e9eb
commit 8c5de5ee9d
6 changed files with 654 additions and 11 deletions
+217
View File
@@ -0,0 +1,217 @@
class BankAccount {
int balance = 0;
int transactions = 0;
void deposit(int obj, int amount) {
obj.balance = obj.balance + amount;
obj.transactions = obj.transactions + 1;
}
void withdraw(int obj, int amount) {
if (obj.balance >= amount) {
obj.balance = obj.balance - amount;
obj.transactions = obj.transactions + 1;
}
}
int getBalance(int obj) {
return obj.balance;
}
int getTransactions(int obj) {
return obj.transactions;
}
void printStatement(int obj) {
printf("Balance: $%d, Transactions: %d\n", obj.balance, obj.transactions);
}
}
class Player {
int health = 100;
int score = 0;
int level = 1;
void takeDamage(int obj, int damage) {
obj.health = obj.health - damage;
if (obj.health < 0) {
obj.health = 0;
}
}
void heal(int obj, int amount) {
obj.health = obj.health + amount;
if (obj.health > 100) {
obj.health = 100;
}
}
void addScore(int obj, int points) {
obj.score = obj.score + points;
if (obj.score >= obj.level * 100) {
obj.level = obj.level + 1;
printf("Level up! Now level %d\n", obj.level);
}
}
void printStatus(int obj) {
printf("HP: %d/%d, Score: %d, Level: %d\n", obj.health, 100, obj.score, obj.level);
}
}
class Rectangle {
int width = 0;
int height = 0;
int area(int obj) {
return obj.width * obj.height;
}
int perimeter(int obj) {
return 2 * (obj.width + obj.height);
}
void resize(int obj, int w, int h) {
obj.width = w;
obj.height = h;
}
void scale(int obj, int factor) {
obj.width = obj.width * factor;
obj.height = obj.height * factor;
}
void print(int obj) {
printf("Rectangle(%dx%d) - Area: %d, Perimeter: %d\n",
obj.width, obj.height, obj.area(), obj.perimeter());
}
}
class Timer {
int seconds = 0;
int running = 0;
void start(int obj) {
obj.running = 1;
obj.seconds = 0;
}
void stop(int obj) {
obj.running = 0;
}
void tick(int obj) {
if (obj.running) {
obj.seconds = obj.seconds + 1;
}
}
void reset(int obj) {
obj.seconds = 0;
}
void print(int obj) {
char *status = "stopped";
if (obj.running) {
status = "running";
}
printf("Timer: %d seconds (%s)\n", obj.seconds, status);
}
}
int main() {
printf("=== Advanced OOP Examples ===\n\n");
printf("Example 1: Bank Account\n");
int account = new BankAccount();
account.printStatement();
account.deposit(100);
account.deposit(50);
account.withdraw(30);
account.printStatement();
printf("Final balance: $%d\n", account.getBalance());
printf("\n");
printf("Example 2: Game Player\n");
int player = new Player();
player.printStatus();
player.addScore(50);
player.printStatus();
player.takeDamage(30);
player.printStatus();
player.addScore(60);
player.printStatus();
player.heal(20);
player.printStatus();
player.addScore(100);
player.printStatus();
printf("\n");
printf("Example 3: Rectangle Operations\n");
int rect = new Rectangle();
rect.width = 5;
rect.height = 10;
rect.print();
rect.resize(8, 6);
rect.print();
rect.scale(2);
rect.print();
printf("\n");
printf("Example 4: Timer\n");
int timer = new Timer();
timer.print();
timer.start();
timer.print();
timer.tick();
timer.tick();
timer.tick();
timer.print();
timer.stop();
timer.print();
timer.tick();
timer.print();
timer.reset();
timer.print();
printf("\n");
printf("Example 5: Multiple Accounts\n");
int acc1 = new BankAccount();
int acc2 = new BankAccount();
acc1.deposit(1000);
acc2.deposit(500);
printf("Account 1: ");
acc1.printStatement();
printf("Account 2: ");
acc2.printStatement();
acc1.withdraw(200);
acc2.deposit(300);
printf("After transactions:\n");
printf("Account 1: ");
acc1.printStatement();
printf("Account 2: ");
acc2.printStatement();
printf("\n");
printf("Example 6: Complex State Management\n");
int player2 = new Player();
player2.health = 50;
player2.score = 150;
player2.level = 2;
printf("Initial state: ");
player2.printStatus();
int i = 0;
while (i < 5) {
player2.addScore(30);
player2.takeDamage(10);
i = i + 1;
}
printf("After 5 rounds: ");
player2.printStatus();
printf("\n");
printf("=== All Advanced Examples Completed ===\n");
return 0;
}
+163
View File
@@ -0,0 +1,163 @@
class Point {
int x = 0;
int y = 0;
void print(int obj) {
printf("Point(%d, %d)\n", obj.x, obj.y);
}
void setX(int obj, int newX) {
obj.x = newX;
}
void setY(int obj, int newY) {
obj.y = newY;
}
void move(int obj, int dx, int dy) {
obj.x = obj.x + dx;
obj.y = obj.y + dy;
}
}
class Counter {
int count = 0;
void increment(int obj) {
obj.count = obj.count + 1;
}
void decrement(int obj) {
obj.count = obj.count - 1;
}
void reset(int obj) {
obj.count = 0;
}
void add(int obj, int value) {
obj.count = obj.count + value;
}
}
class Person {
int age = 0;
int score = 0;
void birthday(int obj) {
obj.age = obj.age + 1;
}
void setAge(int obj, int newAge) {
obj.age = newAge;
}
void addScore(int obj, int points) {
obj.score = obj.score + points;
}
}
int main() {
printf("=== OOP Mutation Tests ===\n\n");
printf("Test 1: Direct field mutation\n");
int p = new Point();
printf("Initial: ");
p.print();
p.x = 100;
p.y = 200;
printf("After mutation: ");
p.print();
printf("\n");
printf("Test 2: Mutation via setter methods\n");
int p2 = new Point();
printf("Initial: ");
p2.print();
p2.setX(50);
p2.setY(75);
printf("After setters: ");
p2.print();
printf("\n");
printf("Test 3: Mutation via move method\n");
int p3 = new Point();
p3.x = 10;
p3.y = 20;
printf("Initial: ");
p3.print();
p3.move(5, 10);
printf("After move(5, 10): ");
p3.print();
p3.move(-3, -7);
printf("After move(-3, -7): ");
p3.print();
printf("\n");
printf("Test 4: Counter with increment/decrement\n");
int counter = new Counter();
printf("Initial count: %d\n", counter.count);
counter.increment();
printf("After increment: %d\n", counter.count);
counter.increment();
counter.increment();
printf("After 2 more increments: %d\n", counter.count);
counter.decrement();
printf("After decrement: %d\n", counter.count);
counter.add(10);
printf("After add(10): %d\n", counter.count);
counter.reset();
printf("After reset: %d\n", counter.count);
printf("\n");
printf("Test 5: Multiple field mutations\n");
int person = new Person();
printf("Initial - Age: %d, Score: %d\n", person.age, person.score);
person.age = 25;
person.score = 100;
printf("After direct mutation - Age: %d, Score: %d\n", person.age, person.score);
person.birthday();
printf("After birthday - Age: %d, Score: %d\n", person.age, person.score);
person.addScore(50);
printf("After addScore(50) - Age: %d, Score: %d\n", person.age, person.score);
person.birthday();
person.addScore(25);
printf("After birthday and addScore(25) - Age: %d, Score: %d\n", person.age, person.score);
printf("\n");
printf("Test 6: Multiple objects with independent state\n");
int p4 = new Point();
int p5 = new Point();
p4.x = 10;
p4.y = 20;
p5.x = 30;
p5.y = 40;
printf("p4: ");
p4.print();
printf("p5: ");
p5.print();
p4.move(5, 5);
printf("After p4.move(5, 5):\n");
printf("p4: ");
p4.print();
printf("p5: ");
p5.print();
printf("\n");
printf("Test 7: Complex mutation chain\n");
int c1 = new Counter();
c1.increment();
c1.increment();
c1.add(5);
printf("c1 count after increment, increment, add(5): %d\n", c1.count);
c1.count = c1.count * 2;
printf("c1 count after *= 2: %d\n", c1.count);
c1.decrement();
c1.decrement();
c1.decrement();
printf("c1 count after 3 decrements: %d\n", c1.count);
printf("\n");
printf("=== All Mutation Tests Passed ===\n");
return 0;
}
+33
View File
@@ -9,6 +9,19 @@ class Point {
int getX(int obj) {
return obj.x;
}
void setX(int obj, int newX) {
obj.x = newX;
}
void setY(int obj, int newY) {
obj.y = newY;
}
void move(int obj, int dx, int dy) {
obj.x = obj.x + dx;
obj.y = obj.y + dy;
}
}
int main() {
@@ -34,6 +47,26 @@ int main() {
int n = null;
printf("null value = %d\n\n", n);
printf("Test 6: Field mutation (direct)\n");
p.x = 100;
p.y = 200;
printf("After p.x=100, p.y=200: ");
p.print();
printf("\n");
printf("Test 7: Field mutation (via setters)\n");
p.setX(50);
p.setY(75);
printf("After setX(50), setY(75): ");
p.print();
printf("\n");
printf("Test 8: Method with mutation\n");
p.move(10, 20);
printf("After move(10, 20): ");
p.print();
printf("\n");
printf("=== All Tests Passed ===\n");
return 0;
}