/** * MVEL 2.0 * Copyright (C) 2007 The Codehaus * Mike Brock, Dhanji Prasanna, John Graham, Mark Proctor * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mvel2.util; import org.mvel2.ScriptRuntimeException; import static java.lang.String.valueOf; import static org.mvel2.math.MathProcessor.doOperations; public class ExecutionStack { private StackElement element; private int size = 0; public boolean isEmpty() { return size == 0; } public void add(Object o) { size++; StackElement el = element; if (el != null) { while (el.next != null) { el = el.next; } el.next = new StackElement(null, o); } else { element = new StackElement(null, o); } } public void push(Object o) { size++; element = new StackElement(element, o); assert size == deepCount(); } public void push(Object obj1, Object obj2) { size += 2; element = new StackElement(new StackElement(element, obj1), obj2); assert size == deepCount(); } public void push(Object obj1, Object obj2, Object obj3) { size += 3; element = new StackElement(new StackElement(new StackElement(element, obj1), obj2), obj3); assert size == deepCount(); } public Object peek() { if (size == 0) return null; else return element.value; } public void dup() { size++; element = new StackElement(element, element.value); assert size == deepCount(); } public Boolean peekBoolean() { if (size == 0) return null; if (element.value instanceof Boolean) return (Boolean) element.value; throw new ScriptRuntimeException("expected Boolean; but found: " + (element.value == null ? "null" : element.value.getClass().getName())); } public void copy2(ExecutionStack es) { element = new StackElement(new StackElement(element, es.element.value), es.element.next.value); es.element = es.element.next.next; size += 2; es.size -= 2; } public void copyx2(ExecutionStack es) { element = new StackElement(new StackElement(element, es.element.next.value), es.element.value); es.element = es.element.next.next; size += 2; es.size -= 2; } public Object peek2() { return element.next.value; } public Object pop() { if (size == 0) { return null; } try { size--; return element.value; } finally { element = element.next; assert size == deepCount(); } } public Boolean popBoolean() { if (size-- == 0) { return null; } try { if (element.value instanceof Boolean) return (Boolean) element.value; throw new ScriptRuntimeException("expected Boolean; but found: " + (element.value == null ? "null" : element.value.getClass().getName())); } finally { element = element.next; assert size == deepCount(); } } public Object pop2() { try { size -= 2; return element.value; } finally { element = element.next.next; assert size == deepCount(); } } public void discard() { if (size != 0) { size--; element = element.next; } } public int size() { return size; } public boolean isReduceable() { return size > 1; } public void clear() { size = 0; element = null; } public void xswap_op() { element = new StackElement(element.next.next.next, doOperations(element.next.next.value, (Integer) element.next.value, element.value)); size -= 2; assert size == deepCount(); } public void op() { element = new StackElement(element.next.next.next, doOperations(element.next.next.value, (Integer) element.value, element.next.value)); size -= 2; assert size == deepCount(); } public void op(int operator) { element = new StackElement(element.next.next, doOperations(element.next.value, operator, element.value)); size--; assert size == deepCount(); } public void xswap() { StackElement e = element.next; StackElement relink = e.next; e.next = element; (element = e).next.next = relink; } public void xswap2() { StackElement node2 = element.next; StackElement node3 = node2.next; (node2.next = element).next = node3.next; element = node3; element.next = node2; } public int deepCount() { int count = 0; if (element == null) { return 0; } else { count++; } StackElement element = this.element; while ((element = element.next) != null) { count++; } return count; } public String toString() { StackElement el = element; if (element == null) return "<EMPTY>"; StringBuilder appender = new StringBuilder().append("["); do { appender.append(valueOf(el.value)); if (el.next != null) appender.append(", "); } while ((el = el.next) != null); appender.append("]"); return appender.toString(); } }