void Parser :: CheckReturn(FuncSymbol *func ){ ReturnStatement *ret = nullptr; SymbolType *real_type = func->value->getType(); int size = func->body->body.size(); for(int i = 0; i < size && !ret; i++) ret = dynamic_cast<ReturnStatement*>(func->body->body[i]); if(!ret || !ret->value ){ errorIf((func->name != "main" && real_type->name != "void") , "Wrong return type", scan.Get()); return; } SymbolType *a = ret->value->getType(); errorIf(!a->canConvertTo(real_type), "Wrong return type", scan.Get()); }
SymbolType* FuncCallNode::getType(){ if(nodeType) return nodeType; FuncSymbol* sym = dynamic_cast<FuncSymbol*>(symbol); int formalParametersCount = sym->params->size(); int realParametersCount = args.size(); if (formalParametersCount != realParametersCount) throw MyException("Incorrect parameters count", token); for (int i = 0; i < formalParametersCount; i++) { SymbolType* realParamType = args[i]->getType(); SymbolType* formalParamType = sym->params->sym_ptr[i]->getType(); if (!realParamType->canConvertTo(formalParamType)) throw MyException("Invalid type of parameter", args[i]->token); args[i] = makeTypeCoerce(args[i], realParamType, formalParamType); } return symbol->getType(); }
SymbolType *UnaryOpNode::getType(){ if(nodeType) return nodeType; SymbolType *type = operand->getType(); Values operation = token->value; switch(operation){ case factor: if(!dynamic_cast<PointerSymbol*>(type)) throw MyException("Type of unary operation is not a pointer", token); nodeType = dynamic_cast<PointerSymbol*>(type)->pointer; return nodeType; case b_and: if(!operand->isLvalue()) throw MyException("Expression must be a modifiable lvalue", token->line, token->start); nodeType = new PointerSymbol(type); return nodeType; case b_not: operand = makeTypeCoerce(operand, type, IntType); break; case l_not: if(dynamic_cast<StructSymbol*>(type)) throw MyException("No operator \"!\" matches these operands operand types are: !" + type->name, token); break; case incr: case decr: if(!operand->isModifiableLvalue()) throw MyException("Expression must be a modifiable lvalue", token); break; case Values::minus: if(!type->canConvertTo(FloatType)) throw MyException("Expression must have arithmetical type", token); } nodeType = type; return type; }
SymbolType *BinaryOpNode::getType(){ if(nodeType) return nodeType; SymbolType *leftType = left->getType(); SymbolType *rightType = right->getType(); if(rightType == VoidType) throw MyException("Type casting error", token); Values operation = token->value; SymbolType *maxType = 0; if(operationTypeOperands.count(operation)) maxType = operationTypeOperands[operation]; else maxType = typePriority[leftType] > typePriority[rightType] ? leftType : rightType; PointerSymbol *l_pointer = dynamic_cast<PointerSymbol*>(leftType); PointerSymbol *r_pointer= dynamic_cast<PointerSymbol*>(rightType); ArraySymbol *l_array = dynamic_cast<ArraySymbol*>(leftType); ArraySymbol *r_array = dynamic_cast<ArraySymbol*>(rightType); switch(operation){ case per_eql: case or_eql: case and_eql: case xor_eql: case sr_eql: case sl_eql: if(!leftType->canConvertTo(IntType) || !rightType->canConvertTo(IntType)) throw MyException("Expression must have integral type", token); case assign: if(leftType->isStruct() && *leftType == rightType){ nodeType = leftType; return leftType; } case pl_eql: case mn_eql: case fct_eql: case div_eql: if(!left->isModifiableLvalue()) throw MyException("Expression must be a modifiable lvalue", token); right = makeTypeCoerce(right, rightType, leftType); nodeType = rightType; return rightType; case point: if(!dynamic_cast<StructSymbol*>(leftType)) throw MyException("Left operand of . must be a structure", token); nodeType = rightType; return rightType; case arrow: if(!l_pointer || !dynamic_cast<StructSymbol*>(l_pointer->upType())) throw MyException("Left operand of -> must be of pointer-to-structure type", left->token); nodeType = rightType; return rightType; case Values::minus: if(l_pointer && r_pointer || l_array && r_array){ if( l_pointer && r_pointer && (*l_pointer->pointer != r_pointer->pointer) || l_array && r_array && (*l_array->type != r_array->type)) throw MyException("Operand types are incompatible", token); nodeType = IntType; return IntType; } case Values::plus: if(l_pointer && r_pointer || l_array && r_array) throw MyException("Can't add two pointers"); if(l_pointer || r_pointer) return l_pointer == 0 ? r_pointer : l_pointer; if(l_array || r_array){ nodeType = new PointerSymbol(l_array == 0 ? r_array->type : l_array->type); return nodeType; } default: if(leftType->isStruct() || rightType->isStruct()) throw MyException("Can't perform operation over two structures", token); if(typePriority[maxType] < max(typePriority[leftType], typePriority[rightType])) throw MyException("Invalid type of operands", token); left = makeTypeCoerce(left, leftType, maxType); right = makeTypeCoerce(right, rightType, maxType); if (operationReturningType.count(operation)){ nodeType = operationReturningType[operation]; return nodeType; } else{ nodeType = maxType; return maxType; } } }