UP | HOME

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
                ;

Author: Paul Gazzillo

Created: 2023-04-13 Thu 14:59