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
thispointer 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
thisis automatically added as a parameter to methods
def getX() -> int {
return this.x;
}
int _point_getX(struct point * this) {
return this->x;
}
Destruction
deletemaps 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
;