Program Listing for File builtins.c¶
↰ Return to documentation for file (src/builtins.c)
/*
* The built-in classes of Quack
* (incomplete implementation)
*
*/
#include <stdio.h>
#include <stdlib.h> /* Malloc lives here; might replace with gc.h */
#include <string.h> /* For strcpy; might replace with cords.h from gc */
#include <stdbool.h>
#include "builtins.h"
/* ==============
* Obj
* Fields: None
* Methods:
* Constructor (called after allocation)
* STR
* PRINT
* EQUALS
*
* ==============
*/
class_Obj the_class_Obj;
/* Constructor */
obj_Obj new_Obj() {
obj_Obj new_thing = (obj_Obj) malloc(sizeof(struct obj_Obj_struct));
new_thing->clazz = the_class_Obj;
return new_thing;
}
/* Obj:STR */
obj_String Obj_method_STR(obj_Obj this) {
char * rep;
asprintf(&rep, "<Object at %08x>", (unsigned)this);
obj_String str = str_literal(rep);
return str;
}
/* Obj:PRINT */
obj_Obj Obj_method_PRINT(obj_Obj this) {
obj_String str = this->clazz->STR(this);
fprintf(stdout, "%s", str->text);
return this;
}
/* Obj:EQUALS (Note we may want to replace this */
obj_Boolean Obj_method_EQUALS(obj_Obj this, obj_Obj other) {
if (this == other) {
return lit_true;
} else {
return lit_false;
}
}
/* The Obj Class (a singleton) */
struct class_Obj_struct the_class_Obj_struct = {
NULL,
new_Obj, /* Constructor */
Obj_method_EQUALS,
Obj_method_PRINT,
Obj_method_STR
};
class_Obj the_class_Obj = &the_class_Obj_struct;
/* ================
* String
* Fields:
* One hidden field, currently holding char*
* (change later to a rope for garbage collection)
* Methods:
* Those of Obj, plus ordering, concatenation
* (Incomplete for now.)
* ==================
*/
/* Constructor */
obj_String new_String( ) {
obj_String new_thing = (obj_String) malloc(sizeof(struct obj_String_struct));
new_thing->clazz = the_class_String;
return new_thing;
}
/* String:STR */
obj_String String_method_STR(obj_String this) {
return this;
}
//obj_String String_method_PRINT(obj_String this) {
// fprintf(stdout, "%s", this->text);
// return this;
//}
/* String:EQUALS (Note we may want to replace this */
obj_Boolean String_method_EQUALS(obj_String this, obj_Obj other) {
obj_String other_str = (obj_String) other;
/* But is it really? */
if (other_str->clazz == the_class_String && strcmp(this->text, other_str->text) == 0)
return lit_true;
return lit_false;
}
obj_String String_method_PLUS(obj_String this, obj_String other) {
char* combo;
asprintf(&combo, "%s%s", this->text, other->text);
return str_literal(combo);
}
obj_Boolean String_method_LESS(obj_String this, obj_String other) {
return (strcmp(this->text, other->text) < 0) ? lit_true : lit_false;
}
obj_Boolean String_method_MORE(obj_String this, obj_String other) {
return (strcmp(this->text, other->text) > 0) ? lit_true : lit_false;
}
obj_Boolean String_method_ATLEAST(obj_String this, obj_String other) {
return (strcmp(this->text, other->text) <= 0) ? lit_true : lit_false;
}
obj_Boolean String_method_ATMOST(obj_String this, obj_String other) {
return (strcmp(this->text, other->text) >= 0) ? lit_true : lit_false;
}
/* The String Class (a singleton) */
struct class_String_struct the_class_String_struct = {
&the_class_Obj_struct,
new_String, /* Constructor */
String_method_EQUALS,
Obj_method_PRINT,
String_method_STR,
String_method_ATLEAST,
String_method_ATMOST,
String_method_LESS,
String_method_MORE,
String_method_PLUS
};
class_String the_class_String = &the_class_String_struct;
/*
* Internal use function for creating String objects
* from char*. Use this to create string literals.
*/
obj_String str_literal(char *s) {
char *rep;
obj_String str = the_class_String->constructor();
str->text = s;
return str;
}
/* ================
* Boolean
* Fields:
* One hidden field, an int (0 for False, -1 for True)
* Methods:
* Those of Obj
* =================
*/
/* Constructor */
obj_Boolean new_Boolean( ) {
obj_Boolean new_thing = (obj_Boolean)
malloc(sizeof(struct obj_Boolean_struct));
new_thing->clazz = the_class_Boolean;
return new_thing;
}
/* Boolean:STR */
obj_String Boolean_method_STR(obj_Boolean this) {
if (this == lit_true) {
return str_literal("true");
} else if (this == lit_false) {
return str_literal("false");
} else {
fprintf(stderr, "Unknown boolean object");
exit(EXIT_FAILURE);
// return str_literal("!!!BOGUS BOOLEAN");
}
}
/* Inherit Obj:EQUAL, since we have only two
* objects of class Boolean.
*/
/* Inherit Obj:PRINT, which will call Boolean:STR */
/* The Boolean Class (a singleton) */
struct class_Boolean_struct the_class_Boolean_struct = {
&the_class_Obj_struct,
new_Boolean, /* Constructor */
Obj_method_EQUALS,
Obj_method_PRINT,
Boolean_method_STR
};
class_Boolean the_class_Boolean = &the_class_Boolean_struct;
/*
* These are the only two objects of type Boolean that
* should ever exist. The constructor just picks one of
* them.
*/
struct obj_Boolean_struct lit_false_struct = { &the_class_Boolean_struct, 0 };
obj_Boolean lit_false = &lit_false_struct;
struct obj_Boolean_struct lit_true_struct = { &the_class_Boolean_struct, 1 };
obj_Boolean lit_true = &lit_true_struct;
/* ==============
* Nothing (really just a singleton Obj)
* Fields: None
* Methods:
* Constructor (called after allocation)
* STR
* PRINT
* EQUALS
*
* ==============
*/
/* Constructor */
obj_Nothing new_Nothing( ) {
return none;
}
/* Boolean:STR */
obj_String Nothing_method_STR(obj_Nothing this) {
return str_literal("<nothing>");
}
/* Inherit Obj:EQUAL, since we have only one
* object of class None
*/
/* Inherit Obj:PRINT, which will call Nothing:STR */
/* The Nothing Class (a singleton) */
struct class_Nothing_struct the_class_Nothing_struct = {
&the_class_Obj_struct,
new_Nothing, /* Constructor */
Obj_method_EQUALS,
Obj_method_PRINT,
Nothing_method_STR
};
class_Nothing the_class_Nothing = &the_class_Nothing_struct;
/*
* This is the only instance of class Nothing that
* should ever exist
*/
struct obj_Nothing_struct nothing_struct = { &the_class_Nothing_struct };
obj_Nothing none = ¬hing_struct;
/* ================
* Int
* Fields:
* One hidden field, an int
* Methods:
* Those of Obj
* PLUS
* LESS
* (add more later)
* =================
*/
/* Constructor */
obj_Int new_Int( ) {
obj_Int new_thing = (obj_Int)malloc(sizeof(struct obj_Int_struct));
new_thing->clazz = the_class_Int;
new_thing->value = 0;
return new_thing;
}
/* Int:STR */
obj_String Int_method_STR(obj_Int this) {
char *rep;
asprintf(&rep, "%d", this->value);
return str_literal(rep);
}
/* Int:EQUALS */
obj_Boolean Int_method_EQUALS(obj_Int this, obj_Obj other) {
obj_Int other_int = (obj_Int) other;
/* But is it? */
if (other_int->clazz != this->clazz || this->value != other_int->value) {
return lit_false;
}
return lit_true;
}
/* Inherit Obj:PRINT, which will call Int:STR */
// FixMe Inherit Obj::Print
/* LESS (new method) */
obj_Boolean Int_method_LESS(obj_Int this, obj_Int other) {
return this->value < other->value ? lit_true: lit_false;
}
/* MORE (new method) */
obj_Boolean Int_method_MORE(obj_Int this, obj_Int other) {
return this->value > other->value ? lit_true: lit_false;
}
/* ATLEAST (new method) */
obj_Boolean Int_method_ATMOST(obj_Int this, obj_Int other) {
return this->value <= other->value ? lit_true: lit_false;
}
/* ATMOST (new method) */
obj_Boolean Int_method_ATLEAST(obj_Int this, obj_Int other) {
return this->value >= other->value ? lit_true: lit_false;
}
/* PLUS (new method) */
obj_Int Int_method_PLUS(obj_Int this, obj_Int other) {
return int_literal(this->value + other->value);
}
/* SUBTRACT (new method) */
obj_Int Int_method_MINUS(obj_Int this, obj_Int other) {
return int_literal(this->value - other->value);
}
/* PLUS (new method) */
obj_Int Int_method_TIMES(obj_Int this, obj_Int other) {
return int_literal(this->value * other->value);
}
/* SUBTRACT (new method) */
obj_Int Int_method_DIVIDE(obj_Int this, obj_Int other) {
return int_literal(this->value / other->value);
}
/* The Int Class (a singleton) */
struct class_Int_struct the_class_Int_struct = {
&the_class_Obj_struct,
new_Int, /* Constructor */
Int_method_EQUALS,
Obj_method_PRINT,
Int_method_STR,
Int_method_ATLEAST,
Int_method_ATMOST,
Int_method_DIVIDE,
Int_method_LESS,
Int_method_MINUS,
Int_method_MORE,
Int_method_PLUS,
Int_method_TIMES
};
class_Int the_class_Int = &the_class_Int_struct;
/* Integer literals constructor,
* used by compiler and not otherwise available in
* Quack programs.
*/
obj_Int int_literal(int n) {
obj_Int boxed = new_Int();
boxed->value = n;
return boxed;
}
bool is_subtype(class_Obj obj, class_Obj other) {
if (obj == other)
return true;
if (obj->super_ == NULL)
return false;
return is_subtype(obj->super_, other);
}
bool is_bool_true(obj_Boolean cond_val) {
return cond_val == lit_true;
}