public class LocalVariableConstant extends Constant {
- LocalVariable var;
+ public LocalVariable var;
public LocalVariableConstant(Type type, LocalVariable var) {
super(type);
import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;
+import org.simantics.scl.compiler.elaboration.java.DynamicConstructor;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.codegen.references.IVal;
context.recursiveReferences.add(placeholder);
return placeholder;
}
- else if(context.isInPattern()) {
+ else if(context.isInPattern() && value.getValue() != DynamicConstructor.INSTANCE /* HACK!! */) {
/* This is little hackish code that handles the following kind of constructors:
* data Thunk a = Thunk s (a -> s)
* in
new Constructor(Locations.NO_LOCATION, MaybeType.INSTANCE, Just.getName(), new Type[] {MaybeType.INSTANCE.parameters[0]}, null)
);
+ // *** Dynamic ***
+
+ addValue("Dynamic", DynamicConstructor.INSTANCE);
+
// *** Vector ***
TypeClass VecCompC = new TypeClass(Locations.NO_LOCATION,
--- /dev/null
+package org.simantics.scl.compiler.elaboration.java;
+
+import org.cojen.classfile.TypeDesc;
+import org.objectweb.asm.Label;
+import org.simantics.scl.compiler.constants.FunctionValue;
+import org.simantics.scl.compiler.constants.LocalVariableConstant;
+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.utils.LocalVariable;
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+/**
+ * Dynamic :: a -> Dynamic
+ */
+public class DynamicConstructor extends FunctionValue {
+ private static final TVar A = Types.var(Kinds.STAR);
+ public static final DynamicConstructor INSTANCE = new DynamicConstructor();
+
+ private DynamicConstructor() {
+ super(new TVar[] {A}, Types.NO_EFFECTS, Types.DYNAMIC, A);
+ }
+
+ @Override
+ public Type applyExact(MethodBuilder mb, Val[] parameters) {
+ mb.pushBoxed(parameters[0]);
+ return Types.DYNAMIC;
+ }
+
+ @Override
+ public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) {
+ Type expectedType = success.getParameterType(0);
+ TypeDesc expectedTypeDesc = mb.getJavaTypeTranslator().toTypeDesc(expectedType);
+ TypeDesc expectedObjectTypeDesc = expectedTypeDesc.toObjectType();
+ LocalVariable cachedParameter = mb.cacheValue(parameter, Types.DYNAMIC);
+ mb.loadLocal(cachedParameter);
+ mb.instanceOf(expectedObjectTypeDesc);
+ mb.ifZeroComparisonBranch(failure, "==");
+
+ mb.loadLocal(cachedParameter);
+ mb.checkCast(expectedObjectTypeDesc);
+ mb.unbox(expectedType);
+ LocalVariable casted = mb.createLocalVariable("dynamicContent", expectedTypeDesc);
+ mb.storeLocal(casted);
+ mb.jump(success, new LocalVariableConstant(expectedType, casted));
+ }
+}
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.constants.LocalVariableConstant;
import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
import org.simantics.scl.compiler.internal.codegen.continuations.ReturnCont;
if(!boundVar.generateOnFly)
return getLocalVariable(boundVar);
}
+ else if(val instanceof LocalVariableConstant) {
+ return ((LocalVariableConstant)val).var;
+ }
push(val, type);
LocalVariable temp = createLocalVariable(null, getJavaTypeTranslator().toTypeDesc(type));
storeLocal(temp);
import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup;
+import org.simantics.scl.compiler.elaboration.java.DynamicConstructor;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
import org.simantics.scl.compiler.internal.codegen.continuations.Branch;
if(constructor_ instanceof EConstant) {
SCLValue constructor = ((EConstant)constructor_).getValue();
- ExpressionMatrix matrix = matrixMap.get(constructor.getName());
+ ExpressionMatrix matrix = constructor.getValue() == DynamicConstructor.INSTANCE ? null : matrixMap.get(constructor.getName());
if(matrix == null) {
CodeWriter newW = w.createBlock(Types.getTypes(parameters));
branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.java.DynamicConstructor;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
import org.simantics.scl.compiler.internal.codegen.continuations.Branch;
if(constructor_ instanceof EConstant) {
SCLValue constructor = ((EConstant)constructor_).getValue();
- ExpressionMatrix matrix = matrixMap.get(constructor.getName());
+ ExpressionMatrix matrix = constructor.getValue() == DynamicConstructor.INSTANCE ? null : matrixMap.get(constructor.getName());
if(matrix == null) {
CodeWriter newW = w.createBlock(Types.getTypes(parameters));
branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));
joinWithSeparator separator values = runProc (
StringBuilder.toString $ printWithSeparator StringBuilder.new separator values)
+
+intercalate :: String -> [String] -> String
+intercalate separator strings = do
+ l = length strings
+ if l == 0
+ then ""
+ else if l == 1
+ then strings!0
+ else runProc do
+ sb = StringBuilder.new
+ sb << strings!0
+ loop i | i == l = ()
+ | otherwise = do
+ sb << separator << strings!i
+ loop (i+1)
+ loop 1
+ StringBuilder.toString sb
+
instance (Show a) => Show [a] where
sb <+ l = do
len = length l
@Test public void DifferentBranchTypes() { test(); }
@Test public void Div() { test(); }
@Test public void DoubleConversion() { test(); }
- @Test public void DoubleEffect() { test(); }
+ @Test public void DoubleEffect() { test(); }
+ @Test public void Dynamic1() { test(); }
@Test public void Effects1() { test(); }
@Test public void Effects2() { test(); }
@Test public void Effects3() { test(); }
--- /dev/null
+import "Prelude"
+
+myShow :: Dynamic -> String
+myShow (Dynamic v) = show (v :: Integer)
+myShow (Dynamic v) = show (v :: Double)
+myShow (Dynamic v) = show (v :: String)
+myShow (Dynamic v) = show (v :: Boolean)
+myShow (Dynamic v) = "[\(intercalate ", " $ map myShow v)]"
+myShow _ = "Unknown"
+
+main = myShow $ Dynamic [Dynamic False, Dynamic (3 :: Integer), Dynamic (3.1 :: Double), Dynamic "Foo"]
+--
+[False, 3, 3.1, "Foo"]
\ No newline at end of file