1 package org.simantics.scl.compiler.constants;
3 import org.cojen.classfile.TypeDesc;
4 import org.objectweb.asm.Label;
5 import org.objectweb.asm.Opcodes;
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
8 import org.simantics.scl.compiler.internal.codegen.references.IVal;
9 import org.simantics.scl.compiler.internal.codegen.references.Val;
10 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
11 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
12 import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
13 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
14 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
15 import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
16 import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
17 import org.simantics.scl.compiler.runtime.MutableClassLoader;
18 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
19 import org.simantics.scl.compiler.types.TVar;
20 import org.simantics.scl.compiler.types.Type;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
24 import gnu.trove.map.hash.THashMap;
27 * Constant is a subclass of Val that does not need to be
28 * copied when a function is copied.
30 * @author Hannu Niemistö
32 public abstract class Constant extends Val {
34 private static final Logger LOGGER = LoggerFactory.getLogger(Constant.class);
36 public static boolean TRACE_REALIZATION = false;
40 public Constant(Type type) {
45 public Type getType() {
49 public int getArity() {
54 public void push(MethodBuilder mb) {
55 throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support push.");
59 * Deconstructs the parameter and calls continuation with found components.
60 * If the parameter is not constructed with this constructor the execution jumps
61 * to failure. If failure is null, the deconstructor assumes that parameter can
66 * @param failure, label where to jump if deconstruct fails.
67 * May be null, if deconstructing cannot fail.
69 public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) {
70 throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support deconstruct.");
74 * Returns -1, if the constant does not support deconstructing. Otherwise
75 * gives the tag of the constructor.
77 public int constructorTag() {
81 public void inline(SSASimplificationContext context, LetApply apply) {
85 public Val copy(THashMap<TVar, TVar> tvarMap) {
90 public int getEffectiveArity() {
95 public Object realizeValue(TransientClassBuilder builder) {
96 THashMap<Constant, Object> valueCache = builder.classLoader.getConstantCache();
97 if(valueCache != null) {
98 Object cachedResult = valueCache.get(this);
99 if(cachedResult != null)
103 String packageName = builder.classLoader.getFreshPackageName();
104 String moduleName = packageName + "/Temp";
105 JavaNamingPolicy policy = new JavaNamingPolicy(moduleName);
106 ModuleBuilder moduleBuilder = new ModuleBuilder(policy, builder.javaTypeTranslator);
108 if(SCLCompilerConfiguration.TRACE_METHOD_CREATION)
109 LOGGER.info("Create class " + policy.getModuleClassName());
110 ClassBuilder classFile = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, policy.getModuleClassName(), "java/lang/Object");
111 classFile.setSourceFile("_SCL_RealizedValue");
113 classFile.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "VALUE", TypeDesc.OBJECT);
115 MethodBuilder mb = classFile.addInitializer();
118 mb.storeStaticField(classFile.getClassName(), "VALUE", TypeDesc.OBJECT);
122 moduleBuilder.addClass(classFile);
124 MutableClassLoader classLoader = builder.classLoader;
125 classLoader.addClasses(moduleBuilder.getClasses());
127 Object result = classLoader.loadClass(policy.getModuleClassName().replace('/', '.')).getField("VALUE").get(null);
128 if(valueCache != null) {
129 valueCache.put(this, result);
130 if(TRACE_REALIZATION)
131 LOGGER.info("/REALIZED/ " + this + " " + getClass().getSimpleName());
134 } catch (IllegalAccessException e) {
135 throw new InternalCompilerError(e);
136 } catch (ClassNotFoundException e) {
137 throw new InternalCompilerError(e);
138 } catch (IllegalArgumentException e) {
139 throw new InternalCompilerError(e);
140 } catch (SecurityException e) {
141 throw new InternalCompilerError(e);
142 } catch (NoSuchFieldException e) {
143 throw new InternalCompilerError(e);