
#include <stdio.h>
#include <math.h>






typedef enum type_class {
  Integer, Real, Pointer, Array, Function,
} TypeClass;


typedef struct array_type {
  int lowerBound;
  int upperBound;
  struct type *type;
} ArrayType;


typedef struct function_type {
  struct type *returnType;
  struct param_list *paramList;
} FunctionType;


typedef struct type {
  TypeClass typeClass;
  union {
    struct type *pointer;
    ArrayType arrayType;
    FunctionType functionType;
  } data;
} Type;


typedef struct param_list {
  char *name;				
  Type *type;
  struct param_list *next;
} ParamList;


typedef union value_union {
  long integer; 
  double real;
  union value_union *ptrdata;		/* for pointers */
  union value_union *elements;		/* for arrays */
  struct statement *code;		/* for functions */
} ValueUnion;


typedef struct value {
  Type *type;
  ValueUnion data;
} Value;

typedef struct variable {
  char *name;
  Value value;
} Variable;


typedef enum expression_class {
  ESum, EProduct, EDifference, EQuotient, EAssignment, EArrayAccess,
  ENegation, EIndirection,
  EFunctionCall,
  EConstant, EVariable,
} ExpressionClass;


typedef struct expression {
  ExpressionClass expressionClass;
  union {
    struct {
      struct expression *left;
      struct expression *right;
    } binary;
    struct expression *unary;
    struct {
      struct expression *function;
      struct expression_list *arglist;
    } functionCall;
    Value constant;
    char *variable;
  } data;
} Expression;



typedef struct expression_list {
  Expression *expression;
  struct expression_list *next;
} ExpressionList;



typedef enum statement_class {
  AnExpression, 
} StatementClass;


typedef struct statement {
  StatementClass statementClass;
  union {
    Expression expression;
  } data;
  struct statement *next;
} Statement;



#define make(type) ((type *) malloc(sizeof(type)))

Expression *MakeExpression();
Expression *MakeUnaryExpression();
Expression *MakeBinaryExpression();
Type *MakeType();

