/src/tools/interpreter/liberty_interpreter_instructions.e
Specman e | 341 lines | 297 code | 29 blank | 15 comment | 20 complexity | 5e7b80db989f8a968694baba23f3c2f2 MD5 | raw file
1-- This file is part of Liberty Eiffel. 2-- 3-- Liberty Eiffel is free software: you can redistribute it and/or modify 4-- it under the terms of the GNU General Public License as published by 5-- the Free Software Foundation, version 3 of the License. 6-- 7-- Liberty Eiffel is distributed in the hope that it will be useful, 8-- but WITHOUT ANY WARRANTY; without even the implied warranty of 9-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10-- GNU General Public License for more details. 11-- 12-- You should have received a copy of the GNU General Public License 13-- along with Liberty Eiffel. If not, see <http://www.gnu.org/licenses/>. 14-- 15class LIBERTY_INTERPRETER_INSTRUCTIONS 16 17inherit 18 LIBERTY_INSTRUCTION_VISITOR 19 LIBERTY_VARIANT_VISITOR 20 21creation {LIBERTY_INTERPRETER} 22 make 23 24feature {LIBERTY_ASSIGNMENT_ATTEMPT} 25 visit_liberty_assignment_attempt (v: LIBERTY_ASSIGNMENT_ATTEMPT) is 26 local 27 assignment: LIBERTY_INTERPRETER_ASSIGNMENT 28 do 29 v.expression.accept(interpreter.expressions) 30 create assignment.attempt(interpreter, interpreter.expressions.eval_as_right_value) 31 v.writable.accept(assignment) 32 end 33 34feature {LIBERTY_ASSIGNMENT_FORCED} 35 visit_liberty_assignment_forced (v: LIBERTY_ASSIGNMENT_FORCED) is 36 local 37 assignment: LIBERTY_INTERPRETER_ASSIGNMENT 38 do 39 v.expression.accept(interpreter.expressions) 40 create assignment.forced(interpreter, interpreter.expressions.eval_as_right_value) 41 v.writable.accept(assignment) 42 end 43 44feature {LIBERTY_ASSIGNMENT_REGULAR} 45 visit_liberty_assignment_regular (v: LIBERTY_ASSIGNMENT_REGULAR) is 46 local 47 assignment: LIBERTY_INTERPRETER_ASSIGNMENT 48 do 49 v.expression.accept(interpreter.expressions) 50 create assignment.regular(interpreter, interpreter.expressions.eval_as_right_value) 51 v.writable.accept(assignment) 52 end 53 54feature {LIBERTY_CALL_INSTRUCTION} 55 visit_liberty_call_instruction (v: LIBERTY_CALL_INSTRUCTION) is 56 local 57 target: LIBERTY_INTERPRETER_OBJECT 58 target_type: LIBERTY_ACTUAL_TYPE 59 do 60 target_type ::= v.entity.target_type.known_type 61 interpreter.ensure_built(target_type) 62 if v.is_implicit_current then 63 interpreter.call_feature(interpreter.target, v.entity.feature_definition, v.actuals, v.position) 64 else 65 v.target.accept(interpreter.expressions) 66 target := interpreter.expressions.eval_as_target 67 interpreter.call_feature(target, v.entity.feature_definition, v.actuals, v.position) 68 end 69 end 70 71feature {LIBERTY_CHECK_INSTRUCTION} 72 visit_liberty_check_instruction (v: LIBERTY_CHECK_INSTRUCTION) is 73 do 74 interpreter.assertions.validate(v.checks, once "Check") 75 end 76 77feature {LIBERTY_COMPOUND} 78 visit_liberty_compound (v: LIBERTY_COMPOUND) is 79 local 80 i: INTEGER 81 do 82 from 83 i := v.lower 84 until 85 i > v.upper 86 loop 87 v.item(i).accept(Current) 88 i := i + 1 89 end 90 end 91 92feature {LIBERTY_CONDITIONAL} 93 visit_liberty_conditional (v: LIBERTY_CONDITIONAL) is 94 local 95 i: INTEGER 96 do 97 condition_stack.add_last(False) 98 from 99 i := v.conditions.lower 100 until 101 condition_stack.last or else i > v.conditions.upper 102 loop 103 v.conditions.item(i).accept(Current) 104 i := i + 1 105 end 106 107 if not condition_stack.last and then v.else_clause /= Void then 108 v.else_clause.accept(Current) 109 end 110 condition_stack.remove_last 111 ensure 112 condition_stack.count = old condition_stack.count 113 end 114 115feature {LIBERTY_CONDITION} 116 visit_liberty_condition (v: LIBERTY_CONDITION) is 117 local 118 c: LIBERTY_INTERPRETER_OBJECT_NATIVE[BOOLEAN] 119 do 120 v.expression.accept(interpreter.expressions) 121 c ::= interpreter.expressions.eval_memory 122 if c.item then 123 v.instruction.accept(Current) 124 condition_stack.put(True, condition_stack.upper) 125 end 126 ensure 127 condition_stack.count = old condition_stack.count 128 end 129 130feature {LIBERTY_CREATION_INSTRUCTION} 131 visit_liberty_creation_instruction (v: LIBERTY_CREATION_INSTRUCTION) is 132 local 133 assignment: LIBERTY_INTERPRETER_ASSIGNMENT 134 new_object: LIBERTY_INTERPRETER_OBJECT 135 actual_type: LIBERTY_ACTUAL_TYPE 136 do 137 actual_type ::= v.type.known_type 138 new_object := interpreter.new_object(actual_type, v.position) 139 interpreter.call_feature(new_object, v.feature_entity.feature_definition, v.feature_arguments, v.position) 140 create assignment.regular(interpreter, new_object) 141 v.writable.accept(assignment) 142 end 143 144feature {LIBERTY_DEBUG} 145 visit_liberty_debug (v: LIBERTY_DEBUG) is 146 do 147 if options.debug_enabled then --| TODO: use v.keys 148 v.instruction.accept(Current) 149 end 150 end 151 152feature {LIBERTY_DEFAULT} 153 visit_liberty_default (v: LIBERTY_DEFAULT) is 154 do 155 v.instruction.accept(Current) 156 end 157 158feature {LIBERTY_EMPTY} 159 visit_liberty_empty (v: LIBERTY_EMPTY) is 160 do 161 -- well, nothing 162 end 163 164feature {LIBERTY_INSPECT} 165 visit_liberty_inspect (v: LIBERTY_INSPECT) is 166 local 167 exp: LIBERTY_INTERPRETER_OBJECT 168 i, n: INTEGER 169 do 170 v.expression.accept(interpreter.expressions) 171 exp := interpreter.expressions.eval_as_right_value 172 inspect_stack.add_last(exp) 173 n := inspect_stack.count 174 from 175 i := v.clauses.lower 176 until 177 inspect_stack.count < n or else i > v.clauses.upper 178 loop 179 v.clauses.item(i).accept(Current) 180 i := i + 1 181 end 182 if inspect_stack.count = n then 183 if v.else_clause = Void then 184 interpreter.fatal_error("Inspect: nothing selected", v.position) 185 else 186 v.else_clause.accept(Current) 187 check 188 inspect_stack.last = exp 189 end 190 inspect_stack.remove_last 191 end 192 else 193 check 194 inspect_stack.count = n - 1 195 end 196 end 197 ensure 198 inspect_stack.count = old inspect_stack.count 199 end 200 201feature {LIBERTY_INSPECT_CLAUSE} 202 visit_liberty_inspect_clause (v: LIBERTY_INSPECT_CLAUSE) is 203 local 204 i, n: INTEGER; found: BOOLEAN 205 do 206 from 207 n := inspect_stack.count 208 i := v.values.lower 209 until 210 found or else i > v.values.upper 211 loop 212 v.values.item(i).accept(Current) 213 if inspect_stack.count < n then 214 check 215 inspect_stack.count = n - 1 216 end 217 v.instruction.accept(Current) 218 found := True 219 end 220 i := i + 1 221 end 222 ensure 223 inspect_stack.count.in_range(old inspect_stack.count - 1, old inspect_stack.count) 224 end 225 226feature {LIBERTY_INSPECT_SLICE} 227 visit_liberty_inspect_slice (v: LIBERTY_INSPECT_SLICE) is 228 local 229 lower, upper: LIBERTY_INTERPRETER_OBJECT 230 do 231 v.lower.accept(interpreter.expressions) 232 lower := interpreter.expressions.eval_as_right_value 233 if v.lower = v.upper then 234 if inspect_stack.last.is_equal(lower) then 235 inspect_stack.remove_last 236 end 237 else 238 v.upper.accept(interpreter.expressions) 239 upper := interpreter.expressions.eval_as_right_value 240 if inspect_stack.last.is_between(lower, upper, v.position) then 241 inspect_stack.remove_last 242 end 243 end 244 ensure 245 inspect_stack.count.in_range(old inspect_stack.count - 1, old inspect_stack.count) 246 end 247 248feature {LIBERTY_LOOP} 249 visit_liberty_loop (v: LIBERTY_LOOP) is 250 local 251 exp_until: LIBERTY_INTERPRETER_OBJECT_NATIVE[BOOLEAN] 252 done, check_invariant, check_variant: BOOLEAN 253 do 254 check_invariant := options.is_invariant_checked 255 check_variant := v.variant_clause /= Void and then options.is_all_checked 256 257 from 258 v.init.accept(Current) 259 if check_variant then 260 loop_variant_stack.add_last(Void) 261 end 262 until 263 done 264 loop 265 if check_invariant then 266 v.invariant_clause.accept(interpreter.assertions) 267 end 268 v.expression.accept(interpreter.expressions) 269 exp_until ::= interpreter.expressions.eval_as_right_value 270 if exp_until.item then 271 done := True 272 else 273 if check_variant then 274 v.variant_clause.accept(Current) 275 end 276 v.body.accept(Current) 277 end 278 end 279 if check_variant then 280 loop_variant_stack.remove_last 281 end 282 end 283 284feature {LIBERTY_VARIANT} 285 visit_liberty_variant (v: LIBERTY_VARIANT) is 286 local 287 exp_variant: LIBERTY_INTERPRETER_OBJECT_NATIVE[INTEGER_64] 288 do 289 v.expression.accept(interpreter.expressions) 290 exp_variant ::= interpreter.expressions.eval_as_right_value 291 if loop_variant_stack.last = Void then 292 loop_variant_stack.put(exp_variant, loop_variant_stack.upper) 293 elseif exp_variant.item >= loop_variant_stack.last.item then 294 interpreter.fatal_error("Variant failed: was " + loop_variant_stack.last.item.out 295 + ", now " + exp_variant.item.out, v.expression.position) 296 else 297 loop_variant_stack.put(exp_variant, loop_variant_stack.upper) 298 end 299 end 300 301feature {LIBERTY_PRECURSOR_INSTRUCTION} 302 visit_liberty_precursor_instruction (v: LIBERTY_PRECURSOR_INSTRUCTION) is 303 do 304 interpreter.call_precursor(v.the_feature, v.actuals, v.position) 305 end 306 307feature {LIBERTY_RETRY} 308 visit_liberty_retry (v: LIBERTY_RETRY) is 309 do 310 not_yet_implemented 311 end 312 313feature {} 314 make (a_interpreter: like interpreter) is 315 require 316 a_interpreter /= Void 317 do 318 interpreter := a_interpreter 319 create condition_stack.with_capacity(0) 320 create inspect_stack.with_capacity(0) 321 if options.is_all_checked then 322 create loop_variant_stack.with_capacity(0) 323 end 324 ensure 325 interpreter = a_interpreter 326 end 327 328 interpreter: LIBERTY_INTERPRETER 329 330 condition_stack: FAST_ARRAY[BOOLEAN] 331 inspect_stack: FAST_ARRAY[LIBERTY_INTERPRETER_OBJECT] 332 loop_variant_stack: FAST_ARRAY[LIBERTY_INTERPRETER_OBJECT_NATIVE[INTEGER_64]] 333 334 options: LIBERTY_INTERPRETER_OPTIONS 335 336invariant 337 interpreter /= Void 338 condition_stack /= Void 339 options.is_all_checked implies loop_variant_stack /= Void 340 341end -- class LIBERTY_INTERPRETER_INSTRUCTIONS