bool Type::Compare(Type *left, Type *right) { if (left == right) return true; if (left->kind() != right->kind()) return false; switch (left->kind()) { case Type::PRIMITIVE: return left->primitive() == right->primitive(); case Type::ARRAY: { ArrayType *aleft = left->toArray(); ArrayType *aright = right->toArray(); if (aleft->levels() != aright->levels()) return false; if (aleft->isFixedLength() != aright->isFixedLength()) return false; if (aleft->isFixedLength() && aleft->fixedLength() != aright->fixedLength()) return false; return Compare(aleft->contained(), aright->contained()); } case Type::FUNCTION: { FunctionType *fleft = left->toFunction(); FunctionType *fright = right->toFunction(); if (!Compare(fleft->returnType(), fright->returnType())) return false; if (fleft->parameters()->length() != fright->parameters()->length()) return false; if (fleft->isNative() != fright->isNative()) return false; if (fleft->isNative() && (fleft->isNativeVariadic() != fright->isNativeVariadic())) return false; for (unsigned i = 0; i < fleft->parameters()->length(); i++) { Type *leftparam = fleft->parameterAt(i); Type *rightparam = fright->parameterAt(i); if (!Compare(leftparam, rightparam)) return false; } return true; } case Type::ENUM: return false; case Type::VOID: return true; default: assert(left->kind() == Type::REFERENCE); return Compare(left->toReference()->contained(), right->toReference()->contained()); } }
void SemanticAnalysis::visitCallExpr(CallExpr *node) { #if 0 HIR *callee = rvalue(node->callee()); if (!callee) return; if (!callee->type()->isFunction()) { cc_.reportError(node->loc(), Message_CalleeNotFunction); return; } FunctionType *fun = callee->type()->toFunction(); if (!checkArgumentCount(fun, node->arguments()->length())) { cc_.reportError(node->loc(), Message_ArgumentCountMismatch); return; } if (fun->isForward()) { cc_.reportError(node->loc(), Message_ForwardNotImplemented, fun->name()->chars()); return; } HIRList *args = new (pool_) HIRList; for (unsigned i = 0; i < node->arguments()->length(); i++) { Expression *expression = node->arguments()->at(i); Type *actual = nullptr; bool needs_reference = false; if (i >= fun->parameters()->length()) { assert(fun->isNative() && fun->isNativeVariadic()); needs_reference = true; } else { actual = fun->parameterAt(i); needs_reference = actual->isReference() || actual->isArray(); } HIR *hir = nullptr; if (!needs_reference) { if ((hir = rvalue(expression)) == nullptr) return; if ((hir = coerce(hir, actual, Coerce_Arg)) == nullptr) return; } else { SValue arg; if (!svalue(expression, &arg)) return; // :TODO: assert(!arg.isRValue()); if (arg.isLValue()) { const LValue &lval = arg.lvalue(); if (actual && actual->isReference() && lval.isBaseIndex()) { // Disabled - this feature is dangerous. cc_.reportError(expression->loc(), Message_CannotComputeIndexRef); return; } // :TODO: need to type check. hir = new (pool_) HAddressOf(expression, lval); } } args->append(hir); } hir_ = new (pool_) HCall(node, fun->returnType(), callee, args); #endif }