]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/Constant.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / Constant.java
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 (file)
index 0000000..b019c74
--- /dev/null
@@ -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<TVar, TVar> tvarMap) {
+        return this;
+    }
+
+    @Override
+    public int getEffectiveArity() {     
+        return 0;
+    }
+    
+    @Override
+    public Object realizeValue(TransientClassBuilder builder) {
+        THashMap<Constant, Object> 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);
+        }
+    }
+}