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 }