+/* common */
+#include "check.h"
+
+/* cc65 */
+#include "error.h"
#include "exprnode.h"
-void InitExprNode (ExprNode* E)
+ExprNode* InitExprNode (ExprNode* E, nodetype_t NT, type* Type,
+ int LValue, struct ExprHeap* Owner)
/* Initialize a new expression node */
{
- E->Left = 0;
- E->Right = 0;
- E->NT = NT_NONE;
- E->Type = 0;
- E->LValue = 0;
+ /* Intialize basic data */
+ E->MData.Owner = Owner;
+ E->NT = NT;
+ E->Type = Type;
+ E->LValue = LValue;
+ E->IVal = 0;
+ E->FVal = 0.0;
+
+ /* Initialize the expression list in the node */
+ InitCollection (&E->List);
+
+ /* Return the node just initialized */
+ return E;
+}
+
+
+
+void* GetItem (ExprNode* N, unsigned Index)
+/* Return one of the items from the nodes item list */
+{
+ return CollAt (&N->List, Index);
+}
+
+
+
+void AppendItem (ExprNode* N, void* Item)
+/* Append an item to the nodes item list */
+{
+ CollAppend (&N->List, Item);
+}
+
+
+
+void SetItem (ExprNode* N, void* Item, unsigned Index)
+/* Set a specific node item. The item list is filled with null pointers as
+ * needed.
+ */
+{
+ if (Index >= CollCount (&N->List)) {
+ /* Fill up with NULL pointers */
+ while (Index >= CollCount (&N->List)) {
+ CollAppend (&N->List, 0);
+ }
+ /* Append the new item */
+ CollAppend (&N->List, Item);
+ } else {
+ /* There is an item with this index, replace it */
+ CollReplace (&N->List, Item, Index);
+ }
+}
+
+
+
+ExprNode* GetNode (ExprNode* N, unsigned Index)
+/* Get one of the sub-nodes from the list */
+{
+ return GetNode (N, Index);
+}
+
+
+
+ExprNode* GetLeftNode (ExprNode* N)
+/* Get the left sub-node from the list */
+{
+ return GetNode (N, IDX_LEFT);
+}
+
+
+
+void SetLeftNode (ExprNode* Root, ExprNode* Left)
+/* Set the left node in Root */
+{
+ SetItem (Root, Left, IDX_LEFT);
+}
+
+
+
+ExprNode* GetRightNode (ExprNode* N)
+/* Get the right sub-node from the list */
+{
+ return GetNode (N, IDX_RIGHT);
+}
+
+
+
+void SetRightNode (ExprNode* Root, ExprNode* Right)
+/* Set the right node in Root */
+{
+ SetItem (Root, Right, IDX_RIGHT);
+}
+
+
+
+struct SymEntry* GetNodeSym (ExprNode* N)
+/* Get the symbol entry for a NT_SYM node */
+{
+ return (struct SymEntry*) GetItem (N, IDX_SYM);
+}
+
+
+
+void SetNodeSym (ExprNode* N, struct SymEntry* Sym)
+/* Set the symbol entry in a NT_SYM node */
+{
+ SetItem (N, Sym, IDX_SYM);
+}
+
+
+
+int IsLeafNode (const ExprNode* E)
+/* Return true if this is a leaf node */
+{
+ return (E->NT & NT_MASK_LEAF) == NT_LEAF;
+}
+
+
+
+int IsBranchNode (const ExprNode* E)
+/* Return true if this is a branch node */
+{
+ return (E->NT & NT_MASK_LEAF) == NT_BRANCH;
+}
+
+
+
+void DumpExpr (FILE* F, const ExprNode* E)
+/* Dump an expression in UPN notation to the given file */
+{
+ if (IsLeafNode (E)) {
+
+ /* Operand */
+ switch (E->NT) {
+
+ case NT_SYM:
+ /* Symbol */
+ fprintf (F, "SYM ");
+ break;
+
+ case NT_CONST:
+ /* A constant of some sort */
+ if (IsClassInt (E->Type)) {
+ fprintf (F, "%0*lX ", SizeOf (E->Type), E->IVal);
+ } else if (IsClassFloat (E->Type)) {
+ fprintf (F, "%f ", E->FVal);
+ } else {
+ Internal ("Unknown type for NT_CONST");
+ }
+ break;
+
+ case NT_ASM:
+ /* Inline assembler */
+ fprintf (F, "ASM ");
+ break;
+
+ case NT_REG_A:
+ /* A register */
+ fprintf (F, "REG_A ");
+ break;
+
+ case NT_REG_X:
+ /* X register */
+ fprintf (F, "REG_X ");
+ break;
+
+ case NT_REG_Y:
+ /* Y register */
+ fprintf (F, "REG_Y ");
+ break;
+
+ case NT_REG_AX:
+ /* AX register */
+ fprintf (F, "REG_AX ");
+ break;
+
+ case NT_REG_EAX:
+ /* EAX register */
+ fprintf (F, "REG_EAX ");
+ break;
+
+ default:
+ Internal ("Unknown node type: %04X", E->NT);
+ break;
+
+ }
+
+ } else {
+
+ unsigned I, Count;
+
+ /* Dump the operands */
+ switch (E->NT & NT_MASK_LIST) {
+
+ case NT_LIST_EXPR:
+ Count = CollCount (&E->List);
+ for (I = 0; I < Count; ++I) {
+ DumpExpr (F, (const ExprNode*) CollConstAt (&E->List, I));
+ }
+ break;
+
+ default:
+ Internal ("Operator with LIST != NT_LIST_EXPR");
+
+ }
+
+ /* Dump the operator */
+ switch (E->NT) {
+
+ case NT_ARRAY_SUBSCRIPT:
+ /* Array subscript */
+ fprintf (F, "[] ");
+ break;
+
+ case NT_STRUCT_ACCESS:
+ /* Access of a struct field */
+ fprintf (F, ". ");
+ break;
+
+ case NT_STRUCTPTR_ACCESS:
+ /* Access via struct ptr */
+ fprintf (F, "-> ");
+ break;
+
+ case NT_FUNCTION_CALL:
+ /* Call a function */
+ fprintf (F, "CALL ");
+ break;
+
+ case NT_TYPECAST:
+ /* A cast */
+ fprintf (F, "CAST ");
+ break;
+
+ case NT_ADDRESS:
+ /* Address operator (&) */
+ fprintf (F, "ADDR ");
+ break;
+
+ case NT_INDIRECT:
+ /* Indirection operator (*) */
+ fprintf (F, "FETCH ");
+ break;
+
+ case NT_UNARY_MINUS:
+ /* - */
+ fprintf (F, "NEG ");
+ break;
+
+ case NT_COMPLEMENT:
+ /* ~ */
+ fprintf (F, "~ ");
+ break;
+
+ case NT_BOOL_NOT:
+ /* ! */
+ fprintf (F, "! ");
+ break;
+
+ case NT_PLUS:
+ /* + */
+ fprintf (F, "+ ");
+ break;
+
+ case NT_MINUS:
+ /* - */
+ fprintf (F, "- ");
+ break;
+
+ case NT_MUL:
+ /* * */
+ fprintf (F, "* ");
+ break;
+
+ case NT_DIV:
+ /* / */
+ fprintf (F, "/ ");
+ break;
+
+ case NT_SHL:
+ /* << */
+ fprintf (F, "<< ");
+ break;
+
+ case NT_SHR:
+ /* >> */
+ fprintf (F, ">> ");
+ break;
+
+ case NT_AND:
+ /* & */
+ fprintf (F, "& ");
+ break;
+
+ case NT_OR:
+ /* | */
+ fprintf (F, "| ");
+ break;
+
+ case NT_XOR:
+ /* ^ */
+ fprintf (F, "^ ");
+ break;
+
+ case NT_TERNARY:
+ /* ?: */
+ fprintf (F, "?: ");
+ break;
+
+ case NT_ASSIGN:
+ /* = */
+ fprintf (F, "= ");
+ break;
+
+ case NT_PLUS_ASSIGN:
+ /* += */
+ fprintf (F, "+= ");
+ break;
+
+ case NT_MINUS_ASSIGN:
+ /* -= */
+ fprintf (F, "-= ");
+ break;
+
+ case NT_MUL_ASSIGN:
+ /* *= */
+ fprintf (F, "*= ");
+ break;
+
+ case NT_DIV_ASSIGN:
+ /* /= */
+ fprintf (F, "/= ");
+ break;
+
+ case NT_SHL_ASSIGN:
+ /* <<= */
+ fprintf (F, "<<= ");
+ break;
+
+ case NT_SHR_ASSIGN:
+ /* >>= */
+ fprintf (F, ">>= ");
+ break;
+
+ case NT_AND_ASSIGN:
+ /* &= */
+ fprintf (F, "&= ");
+ break;
+
+ case NT_OR_ASSIGN:
+ /* |= */
+ fprintf (F, "|= ");
+ break;
+
+ case NT_XOR_ASSIGN:
+ /* ^= */
+ fprintf (F, "^= ");
+ break;
+
+ case NT_PRE_DEC:
+ /* -- */
+ fprintf (F, "<-- ");
+ break;
+
+ case NT_POST_DEC:
+ /* -- */
+ fprintf (F, "--> ");
+ break;
+
+ case NT_PRE_INC:
+ /* ++ */
+ fprintf (F, "<++ ");
+ break;
+
+ case NT_POST_INC:
+ /* ++ */
+ fprintf (F, "++> ");
+ break;
+
+ case NT_BOOL_OR:
+ /* || */
+ fprintf (F, "|| ");
+ break;
+
+ case NT_BOOL_AND:
+ /* && */
+ fprintf (F, "&& ");
+ break;
+
+ case NT_EQ:
+ /* == */
+ fprintf (F, "== ");
+ break;
+
+ case NT_NE:
+ /* != */
+ fprintf (F, "!= ");
+ break;
+
+ case NT_LT:
+ /* < */
+ fprintf (F, "< ");
+ break;
+
+ case NT_LE:
+ /* <= */
+ fprintf (F, "<= ");
+ break;
+
+ case NT_GT:
+ /* > */
+ fprintf (F, "> ");
+ break;
+
+ case NT_GE:
+ /* >= */
+ fprintf (F, ">= ");
+ break;
+
+ default:
+ Internal ("Unknown node type: %04X", E->NT);
+ break;
+
+ }
+ }
}