void ArrayIndexNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo) { if (!array || !index) return; array->computeType (lcontext, initInfo); index->computeType (lcontext, initInfo); if (!array->type || !index->type) return; ArrayTypePtr arrayType = array->type.cast<ArrayType>(); if (!arrayType) { string name = ""; if( NameNodePtr arrayName = array.cast<NameNode>() ) { name = arrayName->name; MESSAGE_LE (lcontext, ERR_NON_ARR_IND, array->lineNumber, "Applied [] operator to non-array (" << name << " " "is of type " << array->type->asString() << ")."); } else { MESSAGE_LE (lcontext, ERR_NON_ARR_IND, array->lineNumber, "Applied [] operator to non-array of type " << array->type->asString() << "."); } type = lcontext.newIntType(); return; } IntTypePtr intType = lcontext.newIntType (); if (!intType->canPromoteFrom (index->type)) { string name = ""; if( NameNodePtr arrayName = array.cast<NameNode>() ) name = arrayName->name; MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber, "Index into array " << name << " is not an iteger " "(index is of type " << index->type->asString() << ")."); type = lcontext.newIntType(); return; } type = arrayType->elementType(); }
void MemberNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo) { obj->computeType (lcontext, initInfo); if (!obj->type) { type = lcontext.newIntType(); return; } StructTypePtr structType = obj->type.cast<StructType>(); if (!structType) { MESSAGE_LE (lcontext, ERR_NON_STRUCT, lineNumber, "Applied member access operator to non-struct " "of type " << obj->type->asString() << "."); type = lcontext.newIntType(); return; } // // check that the member exists and gets its type // for (MemberVectorConstIterator it = structType->members().begin(); it != structType->members().end(); it++) { if (it->name == member) { type = it->type; offset = it->offset; return; } } if (!type) { MESSAGE_LE (lcontext, ERR_MEMBER_ACCESS, lineNumber, "Unable to find member \"" << member << "\"."); type = lcontext.newIntType(); } }
IntLiteralNode::IntLiteralNode (int lineNumber, const LContext &lcontext, int value) : LiteralNode (lineNumber), value (value) { type = lcontext.newIntType (); }
ExprNodePtr ArrayIndexNode::evaluate (LContext &lcontext) { IntTypePtr intType = lcontext.newIntType (); array = array->evaluate (lcontext); index = index->evaluate (lcontext); if( IntLiteralNodePtr literal = index.cast<IntLiteralNode>()) { if(literal->value < 0) { string name = ""; if( NameNodePtr arrayName = array.cast<NameNode>() ) name = arrayName->name; MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber, "Index into array " << name << " is negative " "(" << literal->value << ")."); } ArrayTypePtr arrayType = array->type.cast<ArrayType>(); if(!arrayType) return this; if( literal->value >= arrayType->size() && arrayType->size() != 0) { string name = ""; if( NameNodePtr arrayName = array.cast<NameNode>() ) name = arrayName->name; MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber, "Index into array " << name << " is out of range " "(index = " << literal->value << ", " "array size = " << arrayType->size() << ")."); } } if (index->type && !intType->isSameTypeAs (index->type)) index = intType->castValue (lcontext, index); return this; }
void SizeNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo) { obj->computeType (lcontext, initInfo); ArrayTypePtr arrayType = obj->type.cast<ArrayType>(); if( !arrayType) { string type = "unknown"; if( obj && obj->type) type = obj->type->asString(); MESSAGE_LE (lcontext, ERR_NON_ARRAY, lineNumber, "Applied size operator to non-array " " of type " << type << "."); } type = lcontext.newIntType (); }
void UnaryOpNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo) { if (!operand) return; operand->computeType (lcontext, initInfo); if (!operand->type) return; if (op == TK_BITNOT) { // // Operator ~ can only be applied to operands of type bool int, or // unsigned int. The operator produces a result of the same type as // the operand. // BoolTypePtr boolType = lcontext.newBoolType (); if (boolType->isSameTypeAs (operand->type)) { type = boolType; return; } IntTypePtr intType = lcontext.newIntType (); if (intType->isSameTypeAs (operand->type)) { type = intType; return; } UIntTypePtr uIntType = lcontext.newUIntType (); if (uIntType->isSameTypeAs (operand->type)) { type = uIntType; return; } } else if (op == TK_MINUS) { // // Operator - can only be applied to operands of type int, unsigned // int, half or float. The operator produces a result of the same // type as the operand, except for unsigned int where it produces a // result of type int. // IntTypePtr intType = lcontext.newIntType (); if (intType->isSameTypeAs (operand->type)) { type = intType; return; } UIntTypePtr uIntType = lcontext.newUIntType (); if (uIntType->isSameTypeAs (operand->type)) { type = intType; // not uIntType! return; } HalfTypePtr halfType = lcontext.newHalfType (); if (halfType->isSameTypeAs (operand->type)) { type = halfType; return; } FloatTypePtr floatType = lcontext.newFloatType (); if (floatType->isSameTypeAs (operand->type)) { type = floatType; return; } } else if (op == TK_NOT) { // // Operator ! can be applied to operands that can be converted // to type bool. The operator produces a result of type bool. // BoolTypePtr boolType = lcontext.newBoolType (); if (boolType->canCastFrom (operand->type)) { type = boolType; return; } } MESSAGE_LE (lcontext, ERR_OP_TYPE, lineNumber, "Invalid operand type for " << tokenAsString (op) << " operator " "(" << tokenAsString (op) << operand->type->asString() << ")."); }