/*************/ /*GEMWIRE */ /* ERYTHRO*/ /*************/ #include #include /**************************************************************** * Types are enumerated by the DataTypes enum. * * They are represented by unsigned integers, where the * * most significant 28 bits differentiate the raw type * * of the data being encoded. * * However, the least significant nibble - that is, * * the lowest 4 bits, represent the count of indirection. * * * * This means that a raw Integer data type, such as an i32, * * has the DataType representation 32. * * However, a pointer to an Integer has DataType value 32+1, * * or 33. * * * * This means that the maximum valid pointer level is 16. * * That's a: * * ****************int * * That ought to be enough for everyone, right? * * * ****************************************************************/ /* * Adds 1 to the input Type, to add a level of indirection. * If the indirection is already at 16 levels, it aborts. * * @param Type: The DataType to pointerise * @return the new pointerised DataType value. */ int PointerTo(int Type) { if ((Type & 0xf) == 0xf) DieDecimal("Unrecognized type in pointerisation", Type); printf("\t\tPointerising a %s\n", TypeNames(Type)); return (Type + 1); } /* * Returns the underlying type behind a pointer. * If the type is not a pointer (the lowest 4 bits are 0), it halts compliation. * * @param Type: The type to un-dereference * @return the underlying Type */ int ValueAt(int Type) { printf("\t\tDereferencing a %s\n", TypeNames(Type)); if ((Type & 0xf) == 0x0) DieDecimal("Unrecognized type in defererencing", Type); return (Type - 1); } /* * Type declarations may be raw, they may be pointers. * If they are pointers, we need to be able to check * how many levels of indirection. * However, being a pointer is optional. * * This can parase in just a lone type specifier, or * any valid level of indirection therefore. * * @param Composite: unused * @return the parsed DataType, with any indirection. * */ int ParseOptionalPointer(struct SymbolTableEntry** Composite) { int Type; switch (CurrentToken.type) { case TY_VOID: Type = RET_VOID; Tokenise(); break; case TY_CHAR: Type = RET_CHAR; Tokenise(); break; case TY_INT: Type = RET_INT; Tokenise(); break; case TY_LONG: Type = RET_LONG; Tokenise(); break; case TY_IDENTIFIER: Type = ParseAlias(CurrentIdentifier, Composite); break; case KW_ALIAS: Type = ReadAlias(Composite); if (CurrentToken.type == LI_SEMIC) Type = DAT_ALIAS; break; case KW_ENUM: Type = RET_INT; BeginEnumDeclaration(); if (CurrentToken.type == LI_SEMIC) Type = DAT_ENUM; break; case KW_STRUCT: Type = DAT_STRUCT; *Composite = BeginCompositeDeclaration(Type); break; case KW_UNION: Type = DAT_UNION; *Composite = BeginCompositeDeclaration(Type); break; default: DieDecimal("Illegal type for pointerisation", CurrentToken.type); } // Recursively scan more *s // This makes things like: // x = **y; // possible. while (1) { printf("\t\t\tType on parsing is %d\n", CurrentToken.type); if (CurrentToken.type != AR_STAR) break; Type = PointerTo(Type); Tokenise(); // Tokenise(); TODO: is this skipping pointers? } return Type; } /* * Array Accesses come in the form of x[y]. * * x must be a pointer type, and an array structure. * y can be any binary expression. * * It is a wrapper around *((imax*)x + y). * * @return the AST Node that represents this statement. */ struct ASTNode* AccessArray() { struct ASTNode* LeftNode, * RightNode; struct SymbolTableEntry* Entry; printf("\tAccessing array %s as requested\r\n", CurrentIdentifier); if ((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_ARR) DieMessage("Accessing undeclared array", CurrentIdentifier); LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0); Tokenise(); RightNode = ParsePrecedenceASTNode(0); VerifyToken(LI_RBRAS, "]"); if (!TypeIsInt(RightNode->ExprType)) Die("Array index is not integer"); printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType), TypeNames(LeftNode->ExprType)); RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD); LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0); printf("\tAccessArray: Preparing LeftNode for dereference.\r\n"); LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, NULL, 0); printf("\tArray Access constructed\r\n"); return LeftNode; } /** * Members of enums and structs are accessed with x.y or *x->y * * x must be enum, struct, or pointer to struct. * y must be a valid member of any of the above. * * It is a wrapper around *((imax*)x + xType.ordinal(y)) * * @return the AST Node representing this statement. */ struct ASTNode* AccessMember(bool Deref) { struct ASTNode* LeftNode, * RightNode; struct SymbolTableEntry* CompositeVar, * TypePtr, * Member; if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL) DieMessage("Undeclared variable", CurrentIdentifier); if (Deref && (CompositeVar->Type != PointerTo(DAT_STRUCT) && CompositeVar->Type != PointerTo(DAT_UNION))) DieMessage("Undeclared struct", CurrentIdentifier); if (!Deref && (CompositeVar->Type != DAT_STRUCT && CompositeVar->Type != DAT_UNION)) DieMessage("Undeclared struct", CurrentIdentifier); if (Deref) LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(CompositeVar->Type), CompositeVar, 0); else LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0); LeftNode->RVal = true; TypePtr = CompositeVar->CompositeType; Tokenise(); VerifyToken(TY_IDENTIFIER, "identifier"); for (Member = TypePtr->Start; Member != NULL; Member = Member->NextSymbol) { printf("\tComparing composite entry %s with the wanted %s. Index %d.\r\n", Member->Name, CurrentIdentifier, Member->SinkOffset); if (!strcmp(Member->Name, CurrentIdentifier)) break; } if (Member == NULL) DieMessage("Invalid composite member", CurrentIdentifier); RightNode = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Member->SinkOffset); LeftNode = ConstructASTNode(OP_ADD, PointerTo(Member->Type), LeftNode, NULL, RightNode, NULL, 0); LeftNode = ConstructASTBranch(OP_DEREF, Member->Type, LeftNode, Member, 0); return LeftNode; }