package org.develnext.jphp.core.compiler.common.misc; import php.runtime.memory.KeyValueMemory; import php.runtime.memory.ObjectMemory; import org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken; import php.runtime.memory.ArrayMemory; import php.runtime.Memory; public class StackItem { public enum Type { NULL, BOOL, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, STRING, CHAR, ARRAY, OBJECT, REFERENCE, CLASS, KEY_VALUE; public Class toClass(){ switch (this){ case DOUBLE: return Double.TYPE; case FLOAT: return Float.TYPE; case NULL: return Object.class; case BOOL: return Boolean.TYPE; case SHORT: return Short.TYPE; case CHAR: return Character.TYPE; case INT: return Integer.TYPE; case LONG: return Long.TYPE; case STRING: return String.class; case ARRAY: return Memory.class; // !!! Memory, don't use ArrayMemory!!! case OBJECT: return ObjectMemory.class; case REFERENCE: return Memory.class; case KEY_VALUE: return KeyValueMemory.class; } return null; } public int size(){ switch (this){ case DOUBLE: case LONG: return 2; default: return 1; } } public static Type valueOf(Memory.Type type){ return valueOf(type.toClass()); } public static Type valueOf(Class clazz){ if (clazz == Byte.TYPE) return BYTE; if (clazz == Short.TYPE) return SHORT; if (clazz == Integer.TYPE) return INT; if (clazz == Long.TYPE) return LONG; if (clazz == Double.TYPE) return DOUBLE; if (clazz == Float.TYPE) return FLOAT; if (clazz == String.class) return STRING; if (clazz == Boolean.TYPE) return BOOL; if (clazz == Character.TYPE) return CHAR; if (clazz == ArrayMemory.class) return ARRAY; if (clazz == ObjectMemory.class) return OBJECT; if (clazz == KeyValueMemory.class) return KEY_VALUE; return REFERENCE; } public boolean isConstant(){ return this != REFERENCE && this != ARRAY && this != OBJECT; } public boolean isReference(){ return this == REFERENCE; } public boolean isLikeDouble(){ return this == DOUBLE || this == FLOAT; } public boolean isLikeFloat(){ return this == FLOAT; } public boolean isLikeLong(){ return this == LONG || this == INT || this == SHORT || this == BYTE || this == CHAR; } public boolean isLikeInt(){ return this == INT || this == SHORT || this == BYTE || this == CHAR; } public boolean isLikeNumber(){ return isLikeDouble() || isLikeLong(); } } private int level = -1; public final Type type; public final int size; public boolean immutable; public final Memory memory; public final ValueExprToken token; public StackItem(ValueExprToken token, Type type, boolean immutable) { this.type = type; this.size = type.size(); this.immutable = immutable; this.token = token; this.memory = null; } public StackItem(ValueExprToken token, Type type) { this(token, type, type.isConstant()); } public StackItem(Memory value){ this.type = Type.valueOf(value.type); this.size = type.size(); this.immutable = true; this.memory = value; this.token = null; } public StackItem(ValueExprToken token, Memory value) { this.type = Type.REFERENCE; this.size = type.size(); this.immutable = true; this.memory = value; this.token = token; } public Memory getMemory() { return memory; } public ValueExprToken getToken() { return token; } public boolean isKnown(){ return memory != null || token != null; } public boolean isConstant(){ return memory != null; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public boolean isInvalidForOperations(){ return type == Type.KEY_VALUE; } }