Program Listing for File builtins.h

Return to documentation for file (src/builtins.h)

/*
 * The Quack runtime needs a base class Obj and a handful
 * of built-in classes  (Int, String, Nothing, Boolean)
 *
 * 2018 note (FIXME): The class structure needs a field that
 * points to the supertype.
 */
#ifndef Builtins_h
#define Builtins_h

#include <stdbool.h>

/* Naming conventions:
 * class_X means a reference to the class structure for class X,
 * i.e., pointer to the struct that contains the method table.
 *
 * obj_X means the corresponding object structure reference,
 * i.e., a pointer to the struct where instance variables live.
 *
 * For each, we'll define a struct tag with *_struct and
 * and then define a reference to that struct with a typedef,
 * e.g., class_Obj will be typedefed to struct class_Obj_struct *.
 * Each class will have a single instantiation as the_class_X.
 * the_class_X is a pointer to a statically allocated structure.
 *
 * All programmer-visible fields of objects are references to
 * other objects. Boolean, Int, and String have "hidden" fields
 * that contain their unboxed primitives.
 * Classes are essentially vectors of function pointers, but for
 * convenience and checking we declare them as (pointers to)
 * structs containing function pointers with particular signatures.
 * The receiver object ('this' in Quack) is an implicit argument
 * in Quack but an explicit argument in the runtime.
 */

/* The following object types are "known" from Obj, in the
 * sense that there are Obj methods that return these types.
 */
struct obj_String_struct;
typedef struct obj_String_struct* obj_String;

struct obj_Boolean_struct;
typedef struct obj_Boolean_struct* obj_Boolean;

/* ==============
 * Obj
 * Fields: None
 * Methods:
 *    Constructor  (called after allocation)
 *    STR
 *    PRINT
 *    EQUALS
 *
 * ==============
 */

struct class_Obj_struct;
typedef struct class_Obj_struct* class_Obj;

typedef struct obj_Obj_struct {
  struct class_Obj_struct *clazz;
} * obj_Obj;

struct class_Obj_struct {
  class_Obj super_;

  /* Method table */
  obj_Obj (*constructor) ( void );
  obj_Boolean (*EQUALS) (obj_Obj, obj_Obj);
  obj_Obj (*PRINT) (obj_Obj);
  obj_String (*STR) (obj_Obj);
};

extern class_Obj the_class_Obj; /* Initialized in Builtins.c */
extern struct class_Obj_struct 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.)
 * ==================
 */

struct class_String_struct;
typedef struct class_String_struct* class_String;

typedef struct obj_String_struct {
  class_String clazz;
  char *text;     /* FIXME: Make this a garbage-collectable rope */
} * obj_String;

struct class_String_struct {
  class_Obj super_;

  /* Method table: Inherited or overridden */
  obj_String (*constructor) ( void );
  obj_Boolean (*EQUALS) (obj_String, obj_Obj);
//  obj_String (*PRINT) (obj_String);
  obj_Obj (*PRINT) (obj_Obj);
  obj_String (*STR) (obj_String);

  /* Method table: Introduced in String */
  obj_Boolean (*ATLEAST) (obj_String, obj_String);
  obj_Boolean (*ATMOST) (obj_String, obj_String);
  obj_Boolean (*LESS) (obj_String, obj_String);
  obj_Boolean (*MORE) (obj_String, obj_String);

  obj_String (*PLUS) (obj_String, obj_String);
};

extern class_String the_class_String;
extern struct class_String_struct the_class_String_struct;

/* Construct an object from a string literal.
 * This is not available to the Quack programmer, but
 * is used by the compiler to create a literal string
 * from a Quack literal string.
 */
extern obj_String str_literal(char *s);

/* ================
 * Boolean
 * Fields:
 *    One hidden field, an int (0 for False, -1 for True)
 * Methods:
 *
 * =================
 */

struct class_Boolean_struct;
typedef struct class_Boolean_struct* class_Boolean;

typedef struct obj_Boolean_struct {
  class_Boolean  clazz;
  int value;
} * obj_Boolean;

struct class_Boolean_struct {
  class_Obj super_;

  /* Method table: Inherited or overridden */
  obj_Boolean (*constructor) ( void );
  obj_Boolean (*EQUALS) (obj_Obj, obj_Obj); /* Inherit */
  obj_Obj (*PRINT) (obj_Obj);               /* Inherit */
  obj_String (*STR) (obj_Boolean);
};

extern class_Boolean the_class_Boolean;
extern struct class_Boolean_struct the_class_Boolean_struct;

/* There are only two instances of Boolean,
 * lit_true and lit_false
 * (i.e., the values of the literals true and false)
 * The constructor should return one of them;
 * maybe lit_false.
 */
extern obj_Boolean lit_false;
extern obj_Boolean lit_true;


/* ==============
 * Nothing (really just a singleton Obj)
 * Fields: None
 * Methods:
 *    Constructor  (called after allocation)
 *    STR
 *    PRINT
 *    EQUALS
 *
 * ==============
 */

struct class_Nothing_struct;
typedef struct class_Nothing_struct* class_Nothing;

typedef struct obj_Nothing_struct {
  class_Nothing clazz;
} * obj_Nothing;

/* Although there is little reason to call methods on the none
 * object, the only instance of Nothing, we could call PRINT on
 * it or compare it to something.  It's STR method should return
 * "None".
 */
struct class_Nothing_struct {
  class_Obj super_;

  /* Method table */
  obj_Nothing (*constructor) ( void );
  obj_Boolean (*EQUALS) (obj_Obj, obj_Obj); /* Inherited */
  obj_Obj (*PRINT) (obj_Obj);               /* Inherited */
  obj_String (*STR) (obj_Nothing);
};

extern class_Nothing the_class_Nothing;
extern struct class_Nothing_struct the_class_Nothing_struct;

/* There is a single instance of Nothing,
 * called nothing
 */
extern obj_Nothing none;

/* ================
 * Int
 * Fields:
 *    One hidden field, an int
 * Methods:
 *    STR  (override)
 *    PRINT   (inherit)
 *    EQUALS  (override)
 *    LESS
 *    MORE
 *    ATLEAST
 *    ATMOST
 *    PLUS
 *    MINUS
 *    DIVIDE
 *    TIMES
 * =================
 */

struct class_Int_struct;
typedef struct class_Int_struct* class_Int;

typedef struct obj_Int_struct {
  class_Int  clazz;
  int value;
} * obj_Int;

struct class_Int_struct {
  class_Obj super_;

  /* Method table: Inherited or overridden */
  obj_Int (*constructor) ( void );

  obj_Boolean (*EQUALS) (obj_Int, obj_Obj); /* Overridden */
  obj_Obj (*PRINT) (obj_Obj);      /* Inherited */
  obj_String (*STR) (obj_Int);  /* Overridden */

  obj_Boolean (*ATLEAST) (obj_Int, obj_Int);   /* Introduced */
  obj_Boolean (*ATMOST) (obj_Int, obj_Int);   /* Introduced */
  obj_Int (*DIVIDE) (obj_Int, obj_Int);       /* Introduced */
  obj_Boolean (*LESS) (obj_Int, obj_Int);   /* Introduced */
  obj_Int (*MINUS) (obj_Int, obj_Int);       /* Introduced */
  obj_Boolean (*MORE) (obj_Int, obj_Int);   /* Introduced */
  obj_Int (*PLUS) (obj_Int, obj_Int);       /* Introduced */
  obj_Int (*TIMES) (obj_Int, obj_Int);       /* Introduced */
};

extern class_Int the_class_Int;
extern struct class_Int_struct the_class_Int_struct;

/* Integer literals constructor,
 * used by compiler and not otherwise available in
 * Quack programs.
 */
extern obj_Int int_literal(int n);


/* ===============================
 * Make all the methods we might
 * inherit visible to user code
 *================================
 */
obj_Obj new_Obj();
obj_String Obj_method_STR(obj_Obj this);
obj_Obj Obj_method_PRINT(obj_Obj this);
obj_Boolean Obj_method_EQUALS(obj_Obj this, obj_Obj other);

obj_String new_String();
obj_String String_method_STR(obj_String this);
//obj_String String_method_PRINT(obj_String this);
obj_Boolean String_method_EQUALS(obj_String this, obj_Obj other);
obj_String String_method_PLUS(obj_String this, obj_String other);
obj_Boolean String_method_LESS(obj_String this, obj_String other);
obj_Boolean String_method_MORE(obj_String this, obj_String other);
obj_Boolean String_method_ATLEAST(obj_String this, obj_String other);
obj_Boolean String_method_ATMOST(obj_String this, obj_String other);

obj_String Nothing_method_STR(obj_Nothing this);

obj_Boolean new_Boolean();
obj_String Boolean_method_STR(obj_Boolean this);

obj_Int new_Int();
obj_String Int_method_STR(obj_Int this);
obj_Boolean Int_method_EQUALS(obj_Int this, obj_Obj other);
obj_Boolean Int_method_LESS(obj_Int this, obj_Int other);
obj_Boolean Int_method_MORE(obj_Int this, obj_Int other);
obj_Boolean Int_method_ATLEAST(obj_Int this, obj_Int other);
obj_Boolean Int_method_ATMOST(obj_Int this, obj_Int other);
obj_Int Int_method_PLUS(obj_Int this, obj_Int other);
obj_Int Int_method_MINUS(obj_Int this, obj_Int other);
obj_Int Int_method_DIVIDE(obj_Int this, obj_Int other);
obj_Int Int_method_TIMES(obj_Int this, obj_Int other);

bool is_subtype(class_Obj obj, class_Obj other);

#endif