00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "RangeChecker.h"
00010 #include "TypeCheck.h"
00011 #include "comma/ast/Expr.h"
00012 #include "comma/ast/Range.h"
00013
00014 using namespace comma;
00015
00016 using llvm::dyn_cast;
00017 using llvm::cast;
00018 using llvm::isa;
00019
00020 DiagnosticStream &RangeChecker::report(Location loc, diag::Kind kind)
00021 {
00022 AstResource &resource = TC.getAstResource();
00023 SourceLocation sloc = resource.getTextProvider().getSourceLocation(loc);
00024 return TC.getDiagnostic().report(sloc, kind);
00025 }
00026
00027 bool RangeChecker::checkDeclarationRange(Expr *lower, Expr *upper)
00028 {
00029
00030
00031 if (!TC.checkExprInContext(lower, Type::CLASS_Integer))
00032 return false;
00033 if (!TC.checkExprInContext(upper, Type::CLASS_Integer))
00034 return false;
00035
00036
00037 if (!(TC.ensureStaticIntegerExpr(lower) &&
00038 TC.ensureStaticIntegerExpr(upper)))
00039 return false;
00040
00041 return true;
00042 }
00043
00044 DiscreteType *RangeChecker::checkDSTRange(Expr *lower, Expr *upper)
00045 {
00046
00047
00048
00049 if (!lower->hasResolvedType() && !upper->hasResolvedType()) {
00050 if (!TC.checkExprInContext(lower, Type::CLASS_Discrete))
00051 return 0;
00052 if (!(upper = TC.checkExprInContext(upper, lower->getType())))
00053 return 0;
00054 }
00055 else if (lower->hasResolvedType() && !upper->hasResolvedType()) {
00056 if (!isa<DiscreteType>(lower->getType())) {
00057 report(lower->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE);
00058 return 0;
00059 }
00060 if (!(upper = TC.checkExprInContext(upper, lower->getType())))
00061 return 0;
00062 }
00063 else if (upper->hasResolvedType() && !lower->hasResolvedType()) {
00064 if (!isa<DiscreteType>(upper->getType())) {
00065 report(upper->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE);
00066 return 0;
00067 }
00068 if (!(lower = TC.checkExprInContext(lower, upper->getType())))
00069 return 0;
00070 }
00071 else {
00072
00073 if (!isa<DiscreteType>(lower->getType())) {
00074 report(lower->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE);
00075 return 0;
00076 }
00077
00078 if (!isa<DiscreteType>(upper->getType())) {
00079 report(upper->getLocation(), diag::EXPECTED_DISCRETE_SUBTYPE);
00080 return 0;
00081 }
00082
00083 if (!TC.covers(upper->getType(), lower->getType())) {
00084 report(lower->getLocation(), diag::INCOMPATIBLE_RANGE_TYPES);
00085 return 0;
00086 }
00087 }
00088
00089 DiscreteType *rangeTy = cast<DiscreteType>(lower->getType());
00090
00091
00092
00093 if (rangeTy == TC.getAstResource().getTheRootIntegerType()) {
00094 rangeTy = TC.getAstResource().getTheIntegerType();
00095 lower = new ConversionExpr(lower, rangeTy, lower->getLocation());
00096 upper = new ConversionExpr(upper, rangeTy, upper->getLocation());
00097 }
00098
00099
00100 rangeTy = TC.getAstResource().createDiscreteSubtype(rangeTy, lower, upper);
00101
00102 return rangeTy;
00103 }
00104
00105 DiscreteType *RangeChecker::checkSubtypeRange(DiscreteType *base,
00106 Expr *lower, Expr *upper)
00107 {
00108 if (!(lower = TC.checkExprInContext(lower, base)) ||
00109 !(upper = TC.checkExprInContext(upper, base)))
00110 return 0;
00111
00112 return TC.getAstResource().createDiscreteSubtype(base, lower, upper);
00113 }
00114
00115 bool RangeChecker::resolveRange(Range *range, DiscreteType *type)
00116 {
00117 assert(!range->hasType() && "Range already has a resolved type!");
00118
00119 Expr *lower = range->getLowerBound();
00120 Expr *upper = range->getUpperBound();
00121
00122 if (!(lower = TC.checkExprInContext(lower, type)) ||
00123 !(upper = TC.checkExprInContext(upper, type)))
00124 return false;
00125
00126 range->setLowerBound(lower);
00127 range->setUpperBound(upper);
00128 range->setType(cast<DiscreteType>(lower->getType()));
00129 return true;
00130 }