+/* common */
+#include "check.h"
+
+/* cc65 */
+#include "error.h"
#include "exprnode.h"
+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, 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;
+
+ }
+ }
+}
+
+
NT_MASK_LIST = 0x0300,
/* Two bits telling if this is a leaf or a branch */
- NT_BRANCH = 0x4000, /* Branch */
- NT_LEAF = 0x8000, /* Leaf */
+ NT_LEAF = 0x0000, /* Leaf */
+ NT_BRANCH = 0x8000, /* Branch */
+ NT_MASK_LEAF = 0x8000,
/* Special node type */
NT_NONE = 0x0000, /* None (invalid) op */
NT_LT = 0x0037 | NT_BRANCH | NT_LIST_EXPR, /* < */
NT_LE = 0x0038 | NT_BRANCH | NT_LIST_EXPR, /* <= */
NT_GT = 0x0039 | NT_BRANCH | NT_LIST_EXPR, /* > */
- NT_GE = 0x003A | NT_BRANCH | NT_LIST_EXPR /* >= */
+ NT_GE = 0x003A | NT_BRANCH | NT_LIST_EXPR, /* >= */
+
+ NT_MASK_TYPE = 0x00FF
} nodetype_t;
void SetNodeSym (ExprNode* N, struct SymEntry* Sym);
/* Set the symbol entry in a NT_SYM node */
+int IsLeafNode (const ExprNode* E);
+/* Return true if this is a leaf node */
+int IsBranchNode (const ExprNode* E);
+/* Return true if this is a branch node */
-/* End of exprnode.h */
-#endif
+/* End of exprnode.h */
+#endif
/* Call to non function */
Error (ERR_ILLEGAL_FUNC_CALL);
- /* Free the old node */
- FreeExprNode (Left);
+ /* Free the old tree */
+ FreeExprTree (Left);
/* Return something safe */
return GetIntNode (0);
/* Type check */
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
- /* Display diagnostic */
+ /* Output diagnostic */
Error (ERR_SYNTAX);
/* Free the errorneous node */
- FreeExprNode (Op);
+ FreeExprTree (Op);
/* Return something that makes sense later */
return GetIntNode (0);
Error (ERR_OP_NOT_ALLOWED);
/* Free the errorneous node */
- FreeExprNode (Op);
+ FreeExprTree (Op);
/* Return something that makes sense later */
return GetIntNode (0);
/* Print diagnostics */
Error (ERR_ILLEGAL_ADDRESS);
- /* Free the problematic node */
- FreeExprNode (Op);
+ /* Free the problematic tree */
+ FreeExprTree (Op);
/* Return something that is safe later */
Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
/* Print diagnostics */
Error (ERR_ILLEGAL_INDIRECT);
- /* Free the problematic node */
- FreeExprNode (Op);
+ /* Free the problematic tree */
+ FreeExprTree (Op);
/* Return something that is safe later ### */
return GetIntNode (0);
Size = SizeOf (N->Type);
/* Free the node */
- FreeExprNode (N);
+ FreeExprTree (N);
}
} else {
- /* Must be casted. Setup the expression tree and return the new node */
- Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
+ /* Must be casted. Setup the expression tree and return the new node */
+ Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
SetLeftNode (Root, Op);
return Root;
case TOK_PLUS:
case TOK_MINUS:
- return DoUnaryPlusMinus ();
+ return DoUnaryPlusMinus ();
case TOK_COMP:
return DoComplement ();
case TOK_SIZEOF:
return DoSizeOf ();
- default:
- /* Type cast */
- return DoTypeCast ();
+ default:
+ /* Type cast */
+ return DoTypeCast ();
- }
+ }
} else {
- /* Call the lower level */
- return PostfixExpr ();
+ /* Call the lower level */
+ return PostfixExpr ();
+
+ }
+}
+
+
+
+static ExprNode* DoMul (ExprNode* Left)
+/* Handle multiplication */
+{
+ type TargetType[MAXTYPELEN];
+ ExprNode* Right;
+ ExprNode* Root;
+
+ /* Check the type of the left operand */
+ if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
+ MError ("Invalid left operand to binary operator `*'");
+ FreeExprTree (Left);
+ Left = GetIntNode (0);
+ }
+
+ /* Skip the operator token */
+ NextToken ();
+
+ /* Read the right expression */
+ Right = UnaryExpr ();
+ /* Check the type of the right operand */
+ if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
+ MError ("Invalid right operand to binary operator `*'");
+ FreeExprTree (Right);
+ Right = GetIntNode (0);
}
+
+ /* Do minor optimizations ### */
+
+ /* Make the root node */
+ Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
+ SetLeftNode (Root, Left);
+ SetRightNode (Root, Right);
+
+ return Root;
}
switch (CurTok.Tok) {
case TOK_MUL:
+ Root = DoMul (Root);
break;
case TOK_DIV:
Error (ERR_OP_NOT_ALLOWED);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create something safe */
Root = GetIntNode (0);
int Result = GetBoolRep (Left) & GetBoolRep (Right);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create a constant result */
Root = GetIntNode (Result);
Error (ERR_OP_NOT_ALLOWED);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create something safe */
Root = GetIntNode (0);
int Result = GetBoolRep (Left) ^ GetBoolRep (Right);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create a constant result */
Root = GetIntNode (Result);
Error (ERR_OP_NOT_ALLOWED);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create something safe */
Root = GetIntNode (0);
int Result = GetBoolRep (Left) | GetBoolRep (Right);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create a constant result */
Root = GetIntNode (Result);
int Result = GetBoolRep (Left) && GetBoolRep (Right);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create a constant result */
Root = GetIntNode (Result);
int Result = GetBoolRep (Left) && GetBoolRep (Right);
/* Remove the unneeded nodes */
- FreeExprNode (Right);
- FreeExprNode (Left);
+ FreeExprTree (Right);
+ FreeExprTree (Left);
/* Create a constant result */
Root = GetIntNode (Result);