Classes and objects II
Lecture 14
Table of Contents
Review
Questions about the last class?
Quiz
Why do many object-oriented languages have a "this" or "self" keyword?
Quiz Discussion
ClassC: Object-Oriented SimpleC
- Class declarations
class point { ... }
- Declare objects with fields and methods
- Class implementation
impl point { ... }
- Define member methods
- Instantiation
p: class point; init p;
- Destruction
delete p;
Limitations
- No inheritance
- No visibility rules (public, private, etc.)
- No virtual methods
All our possibilities for a personal project
Example: ClassC (SimpleC with Classes)
class point { x : int; y : int; setX : (int) -> int; getX : () -> int; setY : (int) -> int; getY : () -> int; add : (class point) -> class point; } impl point { def setX(x : int) -> int { this.x = x; return x; } def getX() -> int { return this.x; } def setY(y : int) -> int { this.y = y; return y; } def getY() -> int { return this.y; } def add(p : class point) -> class point { this.setX(this.x + p.x); this.setY(this.y + p.y); return this; } } def main() -> int { p1 : class point; p2 : class point; init p1; init p2; p1.setX(1); p1.setY(1); p2.setX(2); p2.setY(2); p1.add(p2); printInt(p1.getX()); printString("\n"); printInt(p2.getX()); printString("\n"); delete p1; delete p2; return 0; }
java ClassCompiler ../../tests/point.classc | tee ../../tests/point.c gcc -o ../../tests/point.bin ../../tests/point.c ../../runtime/io.c ../../tests/point.bin
#include "stdbool.h" #include "malloc.h" int printInt(int); int printBool(bool); int printString(char *); int readInt(); bool readBool(); char * readString(); struct point { int x; int y; int (* setX) (struct point *, int); int (* getX) (struct point *); int (* setY) (struct point *, int); int (* getY) (struct point *); struct point * (* add) (struct point *, struct point *); }; int _point_setX(struct point * this, int x) { this->x = x; return x; } int _point_getX(struct point * this) { return this->x; } int _point_setY(struct point * this, int y) { this->y = y; return y; } int _point_getY(struct point * this) { return this->y; } struct point * _point_add(struct point * this, struct point * p) { this->setX(this, this->x + p->x); this->setY(this, this->y + p->y); return this; } int main() { struct point * p1; struct point * p2; p1 = malloc(sizeof(* p1)); p1->add = _point_add; p1->getX = _point_getX; p1->setY = _point_setY; p1->setX = _point_setX; p1->getY = _point_getY; p2 = malloc(sizeof(* p2)); p2->add = _point_add; p2->getX = _point_getX; p2->setY = _point_setY; p2->setX = _point_setX; p2->getY = _point_getY; p1->setX(p1, 1); p1->setY(p1, 1); p2->setX(p2, 2); p2->setY(p2, 2); p1->add(p1, p2); printInt(p1->getX(p1)); printString("\n"); printInt(p1->getX(p1)); printString("\n"); return 0; }
Class declaration
- Classes map to structs
- Fields map to struct fields
- Methods map to function pointer struct fields
class point { x : int; y : int; setX : (int) -> int; getX : () -> int; setY : (int) -> int; getY : () -> int; add : (class point) -> class point; }
struct point { // fields int x; int y; // methods int (* setX) (struct point *, int); int (* getX) (struct point *); int (* setY) (struct point *, int); int (* getY) (struct point *); struct point * (* add) (struct point *, struct point *); };
Class implementation
- Methods map to C functions
- Name is mangled to include class name
- Functions take
this
pointer to instance
impl point { def setX(x : int) -> int { this.x = x; return x; } def getX() -> int { return this.x; } def setY(y : int) -> int { this.y = y; return y; } def getY() -> int { return this.y; } def add(p : class point) -> class point { this.setX(this.x + p.x); this.setY(this.y + p.y); return this; } }
int _point_setX(struct point * this, int x) { this->x = x; return x; } int _point_getX(struct point * this) { return this->x; } int _point_setY(struct point * this, int y) { this->y = y; return y; } int _point_getY(struct point * this) { return this->y; } struct point * _point_add(struct point * this, struct point * p) { this->setX(this, this->x + p->x); this->setY(this, this->y + p->y); return this; }
Note that class point
is a struct reference struct point *
Instantiation
- Declarations map to struct pointer declarations
- Initialization
- allocates memory and
- sets pointers to methods.
p1 : class point; p2 : class point; init p1; init p2;
struct point * p1; struct point * p2; p1 = malloc(sizeof(* p1)); p1->add = _point_add; p1->getX = _point_getX; p1->setY = _point_setY; p1->setX = _point_setX; p1->getY = _point_getY;
Accessing fields and methods
- Since objects are pointers to structs, accesses dereference the struct
p1.setX(1);
p1->setX(p1, 1);
Using this
this
is automatically added as a parameter to methods
def getX() -> int { return this.x; }
int _point_getX(struct point * this) { return this->x; }
Destruction
delete
maps to free
delete p1; delete p2;
free(p1); free(p2);
ANTLR's grammar imports
import SimpleC
- Brings in existing grammar rules
Any rules with a new nonterminal are added to the grammar
toplevel: classDef | classImpl | decl | def ; // UPDATED
Any rules on an existing nonterminal update the rule
classDef: 'class' ID '{' decl* '}' ; // NEW
Grammar
grammar Grammar; import SimpleC; toplevel: classDef | classImpl | decl | def ; // UPDATED classDef: 'class' ID '{' decl* '}' ; // NEW classImpl: 'impl' ID '{' def* '}' ; // NEW type: 'int' # IntType | 'bool' # BoolType | 'string' # StringType | '(' paramTypes? ')' '->' returnType=type # FunType | 'class' ID # ClassType // NEW ; stmt: name '=' expr ';' # Assignment | 'while' '(' expr ')' stmt # While // resolve dangling-else by attempting to match ifthenelse first first | 'if' '(' expr ')' stmt 'else' stmt # IfThenElse | 'if' '(' expr ')' stmt # IfThen | 'return' expr ';' # Return | expr ';' # ExprStmt | ';' # Empty | '{' stmt* '}' # Compound | 'init' ID ';' # Init // NEW | 'delete' ID ';' # Delete // NEW ; name: ID # Simple | ID '.' name # Qualified // NEW ;