| 9346 | } |
| 9347 | |
| 9348 | public static class CaseExpr implements Expr, MaybePrimitiveExpr{ |
| 9349 | public final LocalBindingExpr expr; |
| 9350 | public final int shift, mask, low, high; |
| 9351 | public final Expr defaultExpr; |
| 9352 | public final SortedMap<Integer,Expr> tests; |
| 9353 | public final HashMap<Integer,Expr> thens; |
| 9354 | public final Keyword switchType; |
| 9355 | public final Keyword testType; |
| 9356 | public final Set<Integer> skipCheck; |
| 9357 | public final Class returnType; |
| 9358 | public final int line; |
| 9359 | public final int column; |
| 9360 | |
| 9361 | final static Type NUMBER_TYPE = Type.getType(Number.class); |
| 9362 | final static Method intValueMethod = Method.getMethod("int intValue()"); |
| 9363 | |
| 9364 | final static Method hashMethod = Method.getMethod("int hash(Object)"); |
| 9365 | final static Method hashCodeMethod = Method.getMethod("int hashCode()"); |
| 9366 | final static Method equivMethod = Method.getMethod("boolean equiv(Object, Object)"); |
| 9367 | final static Keyword compactKey = Keyword.intern(null, "compact"); |
| 9368 | final static Keyword sparseKey = Keyword.intern(null, "sparse"); |
| 9369 | final static Keyword hashIdentityKey = Keyword.intern(null, "hash-identity"); |
| 9370 | final static Keyword hashEquivKey = Keyword.intern(null, "hash-equiv"); |
| 9371 | final static Keyword intKey = Keyword.intern(null, "int"); |
| 9372 | //(case* expr shift mask default map<minhash, [test then]> table-type test-type skip-check?) |
| 9373 | public CaseExpr(int line, int column, LocalBindingExpr expr, int shift, int mask, int low, int high, Expr defaultExpr, |
| 9374 | SortedMap<Integer,Expr> tests,HashMap<Integer,Expr> thens, Keyword switchType, Keyword testType, Set<Integer> skipCheck){ |
| 9375 | this.expr = expr; |
| 9376 | this.shift = shift; |
| 9377 | this.mask = mask; |
| 9378 | this.low = low; |
| 9379 | this.high = high; |
| 9380 | this.defaultExpr = defaultExpr; |
| 9381 | this.tests = tests; |
| 9382 | this.thens = thens; |
| 9383 | this.line = line; |
| 9384 | this.column = column; |
| 9385 | if (switchType != compactKey && switchType != sparseKey) |
| 9386 | throw new IllegalArgumentException("Unexpected switch type: "+switchType); |
| 9387 | this.switchType = switchType; |
| 9388 | if (testType != intKey && testType != hashEquivKey && testType != hashIdentityKey) |
| 9389 | throw new IllegalArgumentException("Unexpected test type: "+switchType); |
| 9390 | this.testType = testType; |
| 9391 | this.skipCheck = skipCheck; |
| 9392 | Collection<Expr> returns = new ArrayList(thens.values()); |
| 9393 | returns.add(defaultExpr); |
| 9394 | this.returnType = maybeJavaClass(returns); |
| 9395 | if(RT.count(skipCheck) > 0 && RT.booleanCast(RT.WARN_ON_REFLECTION.deref())) |
| 9396 | { |
| 9397 | RT.errPrintWriter() |
| 9398 | .format("Performance warning, %s:%d:%d - hash collision of some case test constants; if selected, those entries will be tested sequentially.\n", |
| 9399 | SOURCE_PATH.deref(), line, column); |
| 9400 | } |
| 9401 | } |
| 9402 | |
| 9403 | public boolean hasJavaClass(){ |
| 9404 | return returnType != null; |
| 9405 | } |