
#include "calc.h"

Expression *MakeExpression (class)
     ExpressionClass class;
{
  Expression *exp = make(Expression);

  exp->expressionClass = class;
  return exp;
}

Expression *MakeUnaryExpression (class, unary)
     ExpressionClass class;
     Expression *unary;
{
  Expression *exp = MakeExpression(class);
  exp->data.unary = unary;
  return exp;
}

Expression *MakeBinaryExpression (class, left, right)
     ExpressionClass class;
     Expression *left;
     Expression *right;
{
  Expression *exp = MakeExpression(class);
  exp->data.binary.left = left;
  exp->data.binary.right = right;
  return exp;
}



PrintExpression (e)
     Expression *e;
{
  char *ch;
  ExpressionList *el;
  
  if (!e) {
    printf ("<Null expression>");
  } else {
    printf ("(");
    switch (e->expressionClass) {
    case ESum:
    case EProduct:
    case EQuotient:
    case EDifference:
    case EAssignment:
      switch (e->expressionClass) {
      case ESum: ch = "+"; break;
      case EProduct: ch = "*"; break;
      case EQuotient: ch = "/"; break;
      case EDifference: ch = "-"; break;
      case EAssignment: ch = "="; break;
      }
      PrintExpression (e->data.binary.left);
      printf (" %s ", ch);
      PrintExpression (e->data.binary.right);
      break;
      
    case EArrayAccess:
      PrintExpression (e->data.binary.left);
      printf ("[");
      PrintExpression (e->data.binary.right);
      printf ("]");
      break;
      
    case ENegation:
    case EIndirection:
      switch (e->expressionClass) {
      case ENegation: ch = "-"; break;
      case EIndirection: ch = "*"; break;
      }
      printf ("%s", ch);
      PrintExpression (e->data.unary);
      break;

    case EFunctionCall:
      PrintExpression(e->data.functionCall.function);
      printf ("(");
      for (el = e->data.functionCall.arglist; el; el = el->next) {
	PrintExpression(el->expression);
	if (el->next) printf (", ");
      }
      break;

    case EConstant:
      PrintValue (&e->data.constant);
      break;

    case EVariable:
      PrintVariable (e->data.variable);
      break;

    default:
      printf ("<Garbled Expression>");
      break;
      
    }
    printf (")");
  }
}



Value Eval (e)
     Expression *e;
{
  switch (e->expressionClass) {
  case ESum:
    return EvalAdd(
  case EProduct:
  case EQuotient:
  case EDifference:
  case EAssignment:
    switch (e->expressionClass) {
    case ESum: ch = "+"; break;
      case EProduct: ch = "*"; break;
      case EQuotient: ch = "/"; break;
      case EDifference: ch = "-"; break;
      case EAssignment: ch = "="; break;
      }
    PrintExpression (e->data.binary.left);
    printf (" %s ", ch);
    PrintExpression (e->data.binary.right);
    break;
    
    case EArrayAccess:
      PrintExpression (e->data.binary.left);
      printf ("[");
      PrintExpression (e->data.binary.right);
      printf ("]");
      break;
      
    case ENegation:
    case EIndirection:
      switch (e->expressionClass) {
      case ENegation: ch = "-"; break;
      case EIndirection: ch = "*"; break;
      }
      printf ("%s", ch);
      PrintExpression (e->data.unary);
      break;

    case EFunctionCall:
      PrintExpression(e->data.functionCall.function);
      printf ("(");
      for (el = e->data.functionCall.arglist; el; el = el->next) {
	PrintExpression(el->expression);
	if (el->next) printf (", ");
      }
      break;

    case EConstant:
      PrintValue (&e->data.constant);
      break;

    case EVariable:
      PrintVariable (e->data.variable);
      break;

  
}
     
