2020-09-13 01:26:49 +00:00
|
|
|
|
|
|
|
/*************/
|
|
|
|
/*GEMWIRE */
|
|
|
|
/* ERYTHRO*/
|
|
|
|
/*************/
|
|
|
|
|
|
|
|
#include <Defs.h>
|
|
|
|
#include <Data.h>
|
|
|
|
|
2021-01-21 01:53:00 +00:00
|
|
|
/****************************************************************
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2020-09-13 01:26:49 +00:00
|
|
|
int PointerTo(int Type) {
|
2022-03-03 00:05:10 +00:00
|
|
|
if ((Type & 0xf) == 0xf)
|
2021-01-20 01:05:41 +00:00
|
|
|
DieDecimal("Unrecognized type in pointerisation", Type);
|
|
|
|
printf("\t\tPointerising a %s\n", TypeNames(Type));
|
|
|
|
return (Type + 1);
|
2020-09-13 01:26:49 +00:00
|
|
|
}
|
|
|
|
|
2021-01-21 01:53:00 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2020-09-13 01:26:49 +00:00
|
|
|
int ValueAt(int Type) {
|
2021-01-20 01:05:41 +00:00
|
|
|
printf("\t\tDereferencing a %s\n", TypeNames(Type));
|
2022-03-03 00:05:10 +00:00
|
|
|
if ((Type & 0xf) == 0x0)
|
2021-01-20 01:05:41 +00:00
|
|
|
DieDecimal("Unrecognized type in defererencing", Type);
|
|
|
|
return (Type - 1);
|
2020-09-13 01:26:49 +00:00
|
|
|
}
|
|
|
|
|
2021-01-21 01:53:00 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-01-20 19:22:15 +00:00
|
|
|
int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
|
2020-09-13 01:26:49 +00:00
|
|
|
|
|
|
|
int Type;
|
2022-03-03 00:05:10 +00:00
|
|
|
|
|
|
|
switch (CurrentToken.type) {
|
2021-01-20 01:05:41 +00:00
|
|
|
case TY_VOID:
|
|
|
|
Type = RET_VOID;
|
2021-01-20 19:22:15 +00:00
|
|
|
Tokenise();
|
2021-01-20 01:05:41 +00:00
|
|
|
break;
|
|
|
|
case TY_CHAR:
|
|
|
|
Type = RET_CHAR;
|
2021-01-20 19:22:15 +00:00
|
|
|
Tokenise();
|
2021-01-20 01:05:41 +00:00
|
|
|
break;
|
|
|
|
case TY_INT:
|
|
|
|
Type = RET_INT;
|
2021-01-20 19:22:15 +00:00
|
|
|
Tokenise();
|
2021-01-20 01:05:41 +00:00
|
|
|
break;
|
|
|
|
case TY_LONG:
|
|
|
|
Type = RET_LONG;
|
2021-01-20 19:22:15 +00:00
|
|
|
Tokenise();
|
|
|
|
break;
|
|
|
|
case KW_STRUCT:
|
|
|
|
Type = DAT_STRUCT;
|
2022-03-03 02:44:07 +00:00
|
|
|
*Composite = BeginCompositeDeclaration(Type);
|
|
|
|
break;
|
|
|
|
case KW_UNION:
|
|
|
|
Type = DAT_UNION;
|
|
|
|
*Composite = BeginCompositeDeclaration(Type);
|
2021-01-20 01:05:41 +00:00
|
|
|
break;
|
2022-03-03 00:05:10 +00:00
|
|
|
default:
|
2021-01-20 01:05:41 +00:00
|
|
|
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
|
2020-09-13 01:26:49 +00:00
|
|
|
}
|
|
|
|
// Recursively scan more *s
|
|
|
|
// This makes things like:
|
|
|
|
// x = **y;
|
|
|
|
// possible.
|
2022-03-03 00:05:10 +00:00
|
|
|
while (1) {
|
2020-09-13 01:26:49 +00:00
|
|
|
printf("\t\t\tType on parsing is %d\n", CurrentToken.type);
|
2022-03-03 00:05:10 +00:00
|
|
|
if (CurrentToken.type != AR_STAR)
|
2020-09-13 01:26:49 +00:00
|
|
|
break;
|
2022-03-03 00:05:10 +00:00
|
|
|
|
2020-09-13 01:26:49 +00:00
|
|
|
Type = PointerTo(Type);
|
2021-02-22 17:43:06 +00:00
|
|
|
Tokenise();
|
2021-01-21 01:53:00 +00:00
|
|
|
// Tokenise(); TODO: is this skipping pointers?
|
2020-09-13 01:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Type;
|
|
|
|
}
|
|
|
|
|
2021-01-21 01:53:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2020-11-19 02:31:40 +00:00
|
|
|
struct ASTNode* AccessArray() {
|
2022-03-03 00:05:10 +00:00
|
|
|
struct ASTNode* LeftNode, * RightNode;
|
2021-01-20 01:05:41 +00:00
|
|
|
struct SymbolTableEntry* Entry;
|
2020-11-19 02:31:40 +00:00
|
|
|
|
|
|
|
printf("\tAccessing array %s as requested\r\n", CurrentIdentifier);
|
2021-01-20 01:05:41 +00:00
|
|
|
if ((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_ARR)
|
2020-11-19 02:31:40 +00:00
|
|
|
DieMessage("Accessing undeclared array", CurrentIdentifier);
|
2022-03-03 00:05:10 +00:00
|
|
|
|
2021-01-20 01:05:41 +00:00
|
|
|
LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0);
|
2021-01-20 19:22:15 +00:00
|
|
|
Tokenise();
|
2020-11-19 02:31:40 +00:00
|
|
|
|
|
|
|
RightNode = ParsePrecedenceASTNode(0);
|
|
|
|
|
|
|
|
VerifyToken(LI_RBRAS, "]");
|
|
|
|
|
2022-03-03 00:05:10 +00:00
|
|
|
if (!TypeIsInt(RightNode->ExprType))
|
2020-11-19 02:31:40 +00:00
|
|
|
Die("Array index is not integer");
|
2022-03-03 00:05:10 +00:00
|
|
|
|
|
|
|
printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType),
|
|
|
|
TypeNames(LeftNode->ExprType));
|
2020-11-19 02:31:40 +00:00
|
|
|
RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD);
|
|
|
|
|
2021-01-20 01:05:41 +00:00
|
|
|
LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0);
|
2020-11-21 02:32:46 +00:00
|
|
|
printf("\tAccessArray: Preparing LeftNode for dereference.\r\n");
|
2021-01-20 01:05:41 +00:00
|
|
|
LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, NULL, 0);
|
2020-11-21 02:07:44 +00:00
|
|
|
printf("\tArray Access constructed\r\n");
|
2021-07-04 23:07:04 +00:00
|
|
|
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) {
|
2022-03-03 00:05:10 +00:00
|
|
|
struct ASTNode* LeftNode, * RightNode;
|
|
|
|
struct SymbolTableEntry* CompositeVar, * TypePtr, * Member;
|
2021-07-04 23:07:04 +00:00
|
|
|
|
|
|
|
|
2022-03-03 00:05:10 +00:00
|
|
|
if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL)
|
|
|
|
DieMessage("Undeclared variable", CurrentIdentifier);
|
2022-03-03 02:44:07 +00:00
|
|
|
if (Deref && (CompositeVar->Type != PointerTo(DAT_STRUCT) && CompositeVar->Type != PointerTo(DAT_UNION)))
|
2021-07-04 23:07:04 +00:00
|
|
|
DieMessage("Undeclared struct", CurrentIdentifier);
|
2022-03-03 02:44:07 +00:00
|
|
|
if (!Deref && (CompositeVar->Type != DAT_STRUCT && CompositeVar->Type != DAT_UNION))
|
2021-07-04 23:07:04 +00:00
|
|
|
DieMessage("Undeclared struct", CurrentIdentifier);
|
|
|
|
|
2022-03-03 00:05:10 +00:00
|
|
|
if (Deref)
|
2022-03-03 02:44:07 +00:00
|
|
|
LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(CompositeVar->Type), CompositeVar, 0);
|
2021-07-04 23:07:04 +00:00
|
|
|
else
|
|
|
|
LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0);
|
2022-03-03 00:05:10 +00:00
|
|
|
|
2021-07-04 23:07:04 +00:00
|
|
|
LeftNode->RVal = true;
|
|
|
|
|
|
|
|
TypePtr = CompositeVar->CompositeType;
|
|
|
|
|
|
|
|
Tokenise();
|
|
|
|
VerifyToken(TY_IDENTIFIER, "identifier");
|
|
|
|
|
2022-03-03 00:05:10 +00:00
|
|
|
for (Member = TypePtr->Start; Member != NULL; Member = Member->NextSymbol) {
|
2022-03-03 02:44:07 +00:00
|
|
|
printf("\tComparing composite entry %s with the wanted %s. Index %d.\r\n", Member->Name, CurrentIdentifier,
|
2022-03-03 00:05:10 +00:00
|
|
|
Member->SinkOffset);
|
|
|
|
if (!strcmp(Member->Name, CurrentIdentifier))
|
2021-07-04 23:07:04 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-03-03 00:05:10 +00:00
|
|
|
|
|
|
|
if (Member == NULL)
|
2022-03-03 02:44:07 +00:00
|
|
|
DieMessage("Invalid composite member", CurrentIdentifier);
|
2022-03-03 00:05:10 +00:00
|
|
|
|
2021-07-04 23:07:04 +00:00
|
|
|
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);
|
|
|
|
|
2020-11-19 02:31:40 +00:00
|
|
|
return LeftNode;
|
|
|
|
}
|