# Constant expression code parsing

This unit parses the same AST as [comp/c/expr], that is, the ones from
[comp/c/ast] but never compiles anything.

## API

?cexpr ( ast -- ?n f )
  Tries to solve "ast" without compiling anything. If possible, yield f=1 and
  "n" is the result

cexpr# ( ast -- n )
  Expect "ast" to be a constant expression and aborts with error if not.

?ari* ( binopast -- ast )
  Provided that "binopast" is a binary operation AST, check if it's appropriate
  to apply the pointer arithmetic logic, that if one side is a pointer and the
  other is an integer, multiply the integer side by the size of the type the
  pointer points to. This word yields a new AST, the input AST staying
  untouched.

  It might look weird to do things thus, but it's actually simpler than more
  direct alternatives when one want to apply the logic consistently in constant
  exprs and regular exprs.

noopexpr? ( ast -- f )
  Yields whether "ast" is a "noop" expression, that is, an expression that
  doesn't generate any code. A constant expression is always a noop, but other
  expressions are. For example, a straight "sym" is a noop even though it's not
  a constant. A typecast on a sym that doesn't result in mask being applied to
  its target is also a noop.

  In other words, a "noop" expression is an expression that would return a
  "halop" other than the W register.

constoptimize ( ast -- ast )
  Do what we call "constant optimizations", that is, propagate constants in
  binops. For example, "x+0" is equivalent to "x", "x*0" to "0", "x*1", to "x",
  etc..

  This does not drill down the AST. It only does its thing on the shallow binop.
