1 /******************************************************************************** 2 * 3 * Copyright (c) 2008 Fujitsu Services Ltd. 4 * 5 * Author: Nick Battle 6 * 7 * This file is part of VDMJ. 8 * 9 * VDMJ is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation, either version 3 of the License, or 12 * (at your option) any later version. 13 * 14 * VDMJ is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with VDMJ. If not, see <http://www.gnu.org/licenses/>. 21 * 22 ******************************************************************************/ 23 24 package org.overturetool.vdmj.expressions; 25 26 import java.util.List; 27 28 import org.overturetool.vdmj.lex.LexLocation; 29 import org.overturetool.vdmj.pog.CasesExhaustiveObligation; 30 import org.overturetool.vdmj.pog.POContextStack; 31 import org.overturetool.vdmj.pog.ProofObligationList; 32 import org.overturetool.vdmj.runtime.Context; 33 import org.overturetool.vdmj.typechecker.Environment; 34 import org.overturetool.vdmj.typechecker.NameScope; 35 import org.overturetool.vdmj.types.Type; 36 import org.overturetool.vdmj.types.TypeList; 37 import org.overturetool.vdmj.types.TypeSet; 38 import org.overturetool.vdmj.util.Utils; 39 import org.overturetool.vdmj.values.Value; 40 41 42 public class CasesExpression extends Expression 43 { 44 private static final long serialVersionUID = 1L; 45 public final Expression exp; 46 public final List<CaseAlternative> cases; 47 public final Expression others; 48 public Type expType = null; 49 50 public CasesExpression(LexLocation location, Expression exp, 51 List<CaseAlternative> cases, Expression others) 52 { 53 super(location); 54 this.exp = exp; 55 this.cases = cases; 56 this.others = others; 57 } 58 59 @Override 60 public String toString() 61 { 62 return "(cases " + exp + " :\n" + 63 Utils.listToString("", cases, ",\n", "") + 64 (others == null ? "\n" : "others " + others + "\n") + "end)"; 65 } 66 67 @Override 68 public Type typeCheck(Environment env, TypeList qualifiers, NameScope scope) 69 { 70 expType = exp.typeCheck(env, null, scope); 71 TypeSet rtypes = new TypeSet(); 72 73 for (CaseAlternative c: cases) 74 { 75 rtypes.add(c.typeCheck(env, scope, expType)); 76 } 77 78 if (others != null) 79 { 80 rtypes.add(others.typeCheck(env, null, scope)); 81 } 82 83 return rtypes.getType(location); 84 } 85 86 @Override 87 public Expression findExpression(int lineno) 88 { 89 Expression found = super.findExpression(lineno); 90 if (found != null) return found; 91 92 found = exp.findExpression(lineno); 93 if (found != null) return found; 94 95 for (CaseAlternative c: cases) 96 { 97 found = c.result.findExpression(lineno); 98 if (found != null) break; 99 } 100 101 return others != null ? others.findExpression(lineno) : null; 102 } 103 104 @Override 105 public Value eval(Context ctxt) 106 { 107 breakpoint.check(location, ctxt); 108 109 Value val = exp.eval(ctxt); 110 111 for (CaseAlternative c: cases) 112 { 113 Value rv = c.eval(val, ctxt); 114 if (rv != null) return rv; 115 } 116 117 if (others != null) 118 { 119 return others.eval(ctxt); 120 } 121 122 return abort(4004, "No cases apply for " + val, ctxt); 123 } 124 125 @Override 126 public ProofObligationList getProofObligations(POContextStack ctxt) 127 { 128 ProofObligationList obligations = new ProofObligationList(); 129 int pop = 0; 130 131 for (CaseAlternative alt: cases) 132 { 133 obligations.addAll(alt.getProofObligations(ctxt, expType)); 134 pop += alt.plist.size(); 135 } 136 137 if (others != null) 138 { 139 obligations.addAll(others.getProofObligations(ctxt)); 140 } 141 142 for (int i=0; i<pop; i++) 143 { 144 ctxt.pop(); 145 } 146 147 if (others == null) 148 { 149 obligations.add(new CasesExhaustiveObligation(this, ctxt)); 150 } 151 152 return obligations; 153 } 154 155 @Override 156 public String kind() 157 { 158 return "cases"; 159 } 160 }