Erythro/src/Pointers.c

154 lines
5.5 KiB
C

/*************/
/*GEMWIRE */
/* ERYTHRO*/
/*************/
#include <Defs.h>
#include <Data.h>
/****************************************************************
* 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)
ErrorReport("Unrecognized type in pointerisation: %d\n", 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)
ErrorReport("Unrecognized type in defererencing: %d (%s)\n", Type, TypeNames(Type));
return (Type - 1);
}
/*
* 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)
ErrorReport("Accessing undeclared array: %s\n", CurrentIdentifier);
LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0);
Tokenise();
RightNode = ParsePrecedenceASTNode(0);
VerifyToken(LI_RBRAS, "]");
if (!TypeIsInt(RightNode->ExprType))
ErrorReport("Array index is not integer");
printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", TypeNames(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, Entry, 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)
ErrorReport("Undeclared variable: %s\n", CurrentIdentifier);
if (Deref && (CompositeVar->Type != PointerTo(DAT_STRUCT) && CompositeVar->Type != PointerTo(DAT_UNION)))
ErrorReport("Undeclared struct: %s\n", CurrentIdentifier);
if (!Deref && (CompositeVar->Type != DAT_STRUCT && CompositeVar->Type != DAT_UNION))
ErrorReport("Undeclared struct: %s\n", CurrentIdentifier);
Safe();
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)
ErrorReport("Invalid composite member: %s\n", CurrentIdentifier);
Safe();
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;
}