X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fconstants%2FConstant.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fconstants%2FConstant.java;h=b019c74705bc9c1a668496f49a4012cc5f444594;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/Constant.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/Constant.java new file mode 100644 index 000000000..b019c7470 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/Constant.java @@ -0,0 +1,142 @@ +package org.simantics.scl.compiler.constants; + +import org.cojen.classfile.TypeDesc; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.internal.codegen.continuations.Cont; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.references.Val; +import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply; +import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy; +import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext; +import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder; +import org.simantics.scl.compiler.runtime.MutableClassLoader; +import org.simantics.scl.compiler.top.SCLCompilerConfiguration; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; + +import gnu.trove.map.hash.THashMap; + +/** + * Constant is a subclass of Val that does not need to be + * copied when a function is copied. + * + * @author Hannu Niemistö + */ +public abstract class Constant extends Val { + + public static boolean TRACE_REALIZATION = false; + + protected Type type; + + public Constant(Type type) { + this.type = type; + } + + @Override + public Type getType() { + return type; + } + + public int getArity() { + return 0; + } + + @Override + public void push(MethodBuilder mb) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support push."); + } + + /** + * Deconstructs the parameter and calls continuation with found components. + * If the parameter is not constructed with this constructor the execution jumps + * to failure. If failure is null, the deconstructor assumes that parameter can + * be deconstructed. + * @param mb + * @param parameter + * @param success + * @param failure, label where to jump if deconstruct fails. + * May be null, if deconstructing cannot fail. + */ + public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) { + throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support deconstruct."); + } + + /** + * Returns -1, if the constant does not support deconstructing. Otherwise + * gives the tag of the constructor. + */ + public int constructorTag() { + return -1; + } + + public void inline(SSASimplificationContext context, LetApply apply) { + } + + @Override + public Val copy(THashMap tvarMap) { + return this; + } + + @Override + public int getEffectiveArity() { + return 0; + } + + @Override + public Object realizeValue(TransientClassBuilder builder) { + THashMap valueCache = builder.classLoader.getConstantCache(); + if(valueCache != null) { + Object cachedResult = valueCache.get(this); + if(cachedResult != null) + return cachedResult; + } + + String packageName = builder.classLoader.getFreshPackageName(); + String moduleName = packageName + "/Temp"; + JavaNamingPolicy policy = new JavaNamingPolicy(moduleName); + ModuleBuilder moduleBuilder = new ModuleBuilder(policy, builder.javaTypeTranslator); + + if(SCLCompilerConfiguration.TRACE_METHOD_CREATION) + System.out.println("Create class " + policy.getModuleClassName()); + ClassBuilder classFile = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, policy.getModuleClassName(), "java/lang/Object"); + classFile.setSourceFile("_SCL_RealizedValue"); + + classFile.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "VALUE", TypeDesc.OBJECT); + + MethodBuilder mb = classFile.addInitializer(); + + mb.pushBoxed(this); + mb.storeStaticField(classFile.getClassName(), "VALUE", TypeDesc.OBJECT); + mb.returnVoid(); + mb.finish(); + + moduleBuilder.addClass(classFile); + + MutableClassLoader classLoader = builder.classLoader; + classLoader.addClasses(moduleBuilder.getClasses()); + try { + Object result = classLoader.loadClass(policy.getModuleClassName().replace('/', '.')).getField("VALUE").get(null); + if(valueCache != null) { + valueCache.put(this, result); + if(TRACE_REALIZATION) + System.out.println("/REALIZED/ " + this + " " + getClass().getSimpleName()); + } + return result; + } catch (IllegalAccessException e) { + throw new InternalCompilerError(e); + } catch (ClassNotFoundException e) { + throw new InternalCompilerError(e); + } catch (IllegalArgumentException e) { + throw new InternalCompilerError(e); + } catch (SecurityException e) { + throw new InternalCompilerError(e); + } catch (NoSuchFieldException e) { + throw new InternalCompilerError(e); + } + } +}