001 /* 002 // $Id: //open/mondrian/src/main/mondrian/calc/impl/BetterExpCompiler.java#9 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2006-2007 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package mondrian.calc.impl; 011 012 import mondrian.olap.*; 013 import mondrian.olap.type.*; 014 import mondrian.calc.*; 015 016 import java.util.List; 017 import java.util.ArrayList; 018 019 /** 020 * Enhanced expression compiler. It can generate code to convert between 021 * scalar types. 022 * 023 * @author jhyde 024 * @version $Id: //open/mondrian/src/main/mondrian/calc/impl/BetterExpCompiler.java#9 $ 025 * @since Sep 29, 2005 026 */ 027 public class BetterExpCompiler extends AbstractExpCompiler { 028 public BetterExpCompiler(Evaluator evaluator, Validator validator) { 029 super(evaluator, validator); 030 } 031 032 public BetterExpCompiler( 033 Evaluator evaluator, 034 Validator validator, 035 List<ResultStyle> resultStyles) 036 { 037 super(evaluator, validator, resultStyles); 038 } 039 040 public DoubleCalc compileDouble(Exp exp) { 041 final Calc calc = compileScalar(exp, false); 042 if (calc instanceof DoubleCalc) { 043 return (DoubleCalc) calc; 044 } else if (calc instanceof IntegerCalc) { 045 final IntegerCalc integerCalc = (IntegerCalc) calc; 046 return new AbstractDoubleCalc(exp, new Calc[] {integerCalc}) { 047 public double evaluateDouble(Evaluator evaluator) { 048 final int result = integerCalc.evaluateInteger(evaluator); 049 return (double) result; 050 } 051 }; 052 } else { 053 throw Util.newInternal("cannot cast " + exp); 054 } 055 } 056 057 public TupleCalc compileTuple(Exp exp) { 058 final Calc calc = compile(exp); 059 final Type type = exp.getType(); 060 if (type instanceof TupleType) { 061 assert calc instanceof TupleCalc; 062 return (TupleCalc) calc; 063 } else if (type instanceof MemberType) { 064 assert calc instanceof MemberCalc; 065 final MemberCalc memberCalc = (MemberCalc) calc; 066 return new AbstractTupleCalc(exp, new Calc[] {memberCalc}) { 067 public Member[] evaluateTuple(Evaluator evaluator) { 068 return new Member[] {memberCalc.evaluateMember(evaluator)}; 069 } 070 }; 071 } else { 072 throw Util.newInternal("cannot cast " + exp); 073 } 074 } 075 076 public ListCalc compileList(Exp exp, boolean mutable) { 077 final ListCalc listCalc = super.compileList(exp, mutable); 078 if (mutable && listCalc.getResultStyle() == ResultStyle.LIST) { 079 // Wrap the expression in an expression which creates a mutable 080 // copy. 081 return new CopyListCalc(listCalc); 082 } 083 return listCalc; 084 } 085 086 private static class CopyListCalc extends AbstractListCalc { 087 private final ListCalc listCalc; 088 089 public CopyListCalc(ListCalc listCalc) { 090 super(new DummyExp(listCalc.getType()), new Calc[]{listCalc}); 091 this.listCalc = listCalc; 092 } 093 094 public List evaluateList(Evaluator evaluator) { 095 List list = listCalc.evaluateList(evaluator); 096 return new ArrayList(list); 097 } 098 } 099 } 100 101 // End BetterExpCompiler.java