lpmoo-1.2/etc/
lpmoo-1.2/mudlib/
lpmoo-1.2/mudlib/etc/
lpmoo-1.2/mudlib/include/
lpmoo-1.2/mudlib/include/moo/
lpmoo-1.2/mudlib/lpc/
lpmoo-1.2/mudlib/std/auto/
lpmoo-1.2/mudlib/std/bfuns/
/*
 * NAME:	optimizer.c
 * DESCRIPTION:	perform optimizations to a MOO AST before compilation
 */

# include <moo/tokens.h>

# define PROTO(elt)		static mixed *o_##elt##(mixed *ast)
# define OPTIMIZE(ast, elt)	o_##elt##(ast)

PROTO(program);
PROTO(if);
PROTO(for);
PROTO(while);
PROTO(fork);
PROTO(return);
PROTO(expression);
PROTO(list);
PROTO(lvalue);

/*
 * NAME:	main()
 * DESCRIPTION:	perform optimizations
 */
mixed *main(mixed *ast)
{
# if 1
  return ast;
# else
  return OPTIMIZE(ast, program);
# endif
}

# if 0
/* optimizer proper */

PROTO(program)
{
  int i, sz, tag;
  mixed *new;

  new = allocate(sz = sizeof(ast));

  for (i = 0; i < sz; ++i)
    {
      switch (TAG(ast[i]))
	{
	case TOK_IF:
	  new[i] = OPTIMIZE(ast[i], if);
	  break;
	case TOK_FOR:
	  new[i] = OPTIMIZE(ast[i], for);
	  break;
	case TOK_WHILE:
	  new[i] = OPTIMIZE(ast[i], while);
	  break;
	case TOK_FORK:
	  new[i] = OPTIMIZE(ast[i], fork);
	  break;
	case TOK_RETURN:
	  new[i] = OPTIMIZE(ast[i], return);
	  break;
	default:  /* expression */
	  new[i] = OPTIMIZE(ast[i], expression);
	  tag = TAG(new[i]);
	  if (tag == TOK_LIT_NUM || tag == TOK_LIT_STR ||
	      tag == TOK_LIT_OBJ || tag == TOK_LIT_ERR ||
	      tag == TOK_LIT_FLT)
	    new[i] = ({ TOK_NOP });
	}
    }

  return new;
}

PROTO(expression)
{
  mixed *new;
  int i, sz;

  switch (TAG(ast))
    {
    case TOK_LIT_NUM:
    case TOK_LIT_STR:
    case TOK_LIT_OBJ:
    case TOK_LIT_ERR:
    case TOK_LIT_FLT:
      return ast;

    case TOK_LBRACE:
      return OPTIMIZE(ast[1], list);

    case TOK_PLUS:
      new = ({ TOK_PLUS, OPTIMIZE(ast[1], expression),
		         OPTIMIZE(ast[2], expression) });
      switch (TAG(new[1]))
	{
	case TOK_LIT_NUM:
	  if (TAG(new[2]) == TOK_LIT_NUM)
	    return ({ TOK_LIT_NUM, new[1][1] + new[2][1] });
	  if (TAG(new[2]) == TOK_LIT_FLT)
	    return ({ TOK_LIT_FLT, (float) new[1][1] + new[2][1] });

	  return new;

	case TOK_LIT_STR:
	  if (TAG(new[2]) == TOK_LIT_STR)
	    return ({ TOK_LIT_STR, new[1][1] + new[2][1] });

	  return ast;

	case TOK_LIT_FLT:
	  if (TAG(new[2]) == TOK_LIT_FLT)
	    return ({ TOK_LIT_FLT, new[1][1] + new[2][1] });
	  if (TAG(new[2]) == TOK_LIT_NUM)
	    return ({ TOK_LIT_FLT, new[1][1] + (float) new[2][1] });

	  return ast;

	default:
	  return ast;
	}

    case TOK_MINUS:
      new = ({ TOK_MINUS, OPTIMIZE(
      switch (TAG(ast[1]))
	{
	case TOK_LIT_NUM:
	  if (TAG(ast[2]) == TOK_LIT_NUM)
	    return ({ TOK_LIT_NUM, ast[1][1] - ast[2][1] });
	  if (TAG(ast[2]) == TOK_LIT_FLT)
	    return ({ TOK_LIT_FLT, (float) ast[1][1] - ast[2][1] });

	  return ast;

	case TOK_LIT_FLT:
	  if (TAG(ast[2]) == TOK_LIT_FLT)
	    return ({ TOK_LIT_FLT, ast[1][1] - ast[2][1] });
	  if (TAG(ast[2]) == TOK_LIT_NUM)
	    return ({ TOK_LIT_FLT, ast[1][1] - (float) ast[2][1] });

	  return ast;

	default:
	  return ast;
	}

    case TOK_TIMES:
      switch (TAG(ast[1]))
	{
	case TOK_LIT_NUM:
	  if (TAG(ast[2]) == TOK_LIT_NUM)
	    return ({ TOK_LIT_NUM, ast[1][1] - ast[2][1] });
	  if (TAG(ast[2]) == TOK_LIT_FLT)
	    return ({ TOK_LIT_FLT, (float) ast[1][1] - ast[2][1] });

	  return ast;

	case TOK_LIT_FLT:
	  if (TAG(ast[2]) == TOK_LIT_FLT)
	    return ({ TOK_LIT_FLT, ast[1][1] - ast[2][1] });
	  if (TAG(ast[2]) == TOK_LIT_NUM)
	    return ({ TOK_LIT_FLT, ast[1][1] - (float) ast[2][1] });

	  return ast;

	default:
	  return ast;
	}
    }
}
# endif