]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Support for () type in CHR relations 77/277/2
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 19 Jan 2017 11:05:19 +0000 (13:05 +0200)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 19 Jan 2017 11:07:05 +0000 (13:07 +0200)
refs #6901

Change-Id: I95e8e71a30a5fee500a66c95a39ddc3ec9907692

bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/NoRepConstant.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/AccessFactOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateConstraintOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerator.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR4.scl

index c9cbb81531649fc2167b2c431a26e6bb4e3b183b..abe5ea81f103671888941ee37585aa1b5a5f4899 100644 (file)
@@ -11,6 +11,7 @@ import org.simantics.scl.runtime.tuple.Tuple0;
 
 public class NoRepConstant extends Constant {
     public static final NoRepConstant PUNIT = new NoRepConstant(Types.PUNIT);
+    public static final NoRepConstant UNIT = new NoRepConstant(Types.UNIT);
     
     public NoRepConstant(Type type) {
         super(type);
index 3ebbb03cf51bf78d5a52676683d6110ba109f8d1..d2379d7c01c591879e44a0510b65f836ecd8d6a0 100644 (file)
@@ -39,7 +39,7 @@ public class AccessFactOp extends PlanOp {
     public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {
         IVal inputVal = inputFact.toVal(context.environment, w);
         for(int i=0;i<variables.length;++i)
-            variables[i].setVal(w.apply(location, constraint.accessComponent(i), inputVal));
+            variables[i].setVal(constraint.accessComponent(location, w, inputVal, i));
         IVal activeId = w.apply(location, constraint.accessId, inputVal);
         CodeWriter end = constraint.mayBeRemoved() ? w.createBlock() : null;
         planContext.partnerFacts.add(new PartnerFact(true, activeId, constraint, inputVal, constraint.mayBeRemoved(), killAfterMatch, null, null, end == null ? null : end.getContinuation()));
index 9a4e6475ec374ad95e1f59735ac0455533f1aceb..b51ca1e43549659e2afcdac4b2495f6920648758 100644 (file)
@@ -78,7 +78,7 @@ public class IterateConstraintOp extends PlanOp {
 
         for(int i=0;i<variables.length;++i)
             if(((boundMask>>i)&1)==0)
-                variables[i].setVal(body.apply(location, constraint.accessComponent(i), fact));
+                variables[i].setVal(constraint.accessComponent(location, body, fact, i));
         Constant nextElement = constraint.nextElement(context, boundMask);
         planContext.partnerFacts.add(new PartnerFact(false, id, constraint, fact, constraint.mayBeRemoved(), killAfterMatch, nextElement, bodyContinuation, end.getContinuation()));
         planContext.nextOp(body);
index 7a0e27ba24b75735c2cc64a833a86d0106dd028e..4a75a560414ad7c6ce69eea33d377a9738a84cd7 100644 (file)
@@ -6,9 +6,10 @@ import java.util.Collection;
 import org.cojen.classfile.TypeDesc;
 import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.constants.Constant;
-import org.simantics.scl.compiler.constants.JavaConstructor;
 import org.simantics.scl.compiler.constants.JavaMethod;
+import org.simantics.scl.compiler.constants.NoRepConstant;
 import org.simantics.scl.compiler.constants.generic.CallJava;
+import org.simantics.scl.compiler.constants.generic.MethodRef.ConstructorRef;
 import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
 import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef;
 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
@@ -20,6 +21,7 @@ import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;
 import org.simantics.scl.compiler.internal.codegen.references.IVal;
 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
 import org.simantics.scl.compiler.internal.parsing.Symbol;
 import org.simantics.scl.compiler.types.TCon;
 import org.simantics.scl.compiler.types.TPred;
@@ -91,15 +93,30 @@ public class CHRConstraint extends Symbol implements CHRRelation {
         
         Type[] constructorTypes = new Type[parameterTypes.length+1];
         constructorTypes[0] = Types.INTEGER;
-        for(int i=0;i<parameterTypes.length;++i)
-            constructorTypes[i+1] = parameterTypes[i];
-        this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
+        ArrayList<StackItem> stackItems = new ArrayList<StackItem>(constructorTypes.length);
+        stackItems.add(new ParameterStackItem(0, Types.INTEGER));
+        for(int i=0;i<parameterTypes.length;++i) {
+            Type parameterType = parameterTypes[i];
+            constructorTypes[i+1] = parameterType;
+            if(!parameterType.equals(Types.UNIT))
+                stackItems.add(new ParameterStackItem(stackItems.size(), parameterType));
+        }
+        TypeDesc[] constructorTypeDescs = JavaTypeTranslator.filterVoid(jtt.toTypeDescs(constructorTypes));
+        this.constructor = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, constructorTypes,
+                stackItems.toArray(new StackItem[stackItems.size()]),
+                new ConstructorRef(factClassName, constructorTypeDescs),
+                null);
+        //this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
         this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},
                 null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null);
         this.accessors = new Constant[parameterTypes.length];
-        for(int i=0;i<parameterTypes.length;++i)
+        for(int i=0;i<parameterTypes.length;++i) {
+            TypeDesc typeDesc = jtt.toTypeDesc(parameterTypes[i]);
+            if(typeDesc.equals(TypeDesc.VOID))
+                continue;
             this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
-                    null, new FieldRef(factClassName, "c" + i, jtt.toTypeDesc(parameterTypes[i])), null);
+                    null, new FieldRef(factClassName, CHRCodeGenerator.fieldName(i), jtt.toTypeDesc(parameterTypes[i])), null);
+        }
         this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
                 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
                 new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
@@ -158,10 +175,6 @@ public class CHRConstraint extends Symbol implements CHRRelation {
                         null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
                 );
     }
-
-    public Constant accessComponent(int i) {
-        return accessors[i];
-    }
     
     public IVal fetchFromIndex(CompilationContext context, int boundMask) {
         IndexInfo indexInfo = indices.get(boundMask);
@@ -206,9 +219,16 @@ public class CHRConstraint extends Symbol implements CHRRelation {
     public boolean isPassive() {
         return plans.isEmpty();
     }
-    
+
     public TPred[] getTypeConstraints() {
         return TPred.EMPTY_ARRAY;
     }
 
+    public IVal accessComponent(long location, CodeWriter w, IVal fact, int i) {
+        Constant accessor = accessors[i];
+        if(accessor == null)
+            return NoRepConstant.UNIT;
+        else
+            return w.apply(location, accessor, fact);
+    }
 }
index af06463bbe7a1672f2bb9fe2e8ea10e97b4b5aa7..c4842ea612a1ac23cf49b3d1ce4418d332715379 100644 (file)
@@ -57,8 +57,12 @@ public class CHRCodeGenerator {
             generateFact(storeClassBuilder, constraint, hashIndexInitializations);
         
         // Fields
-        for(int i=0;i<ruleset.parameterTypeDescs.length;++i)
-            storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "p" + i, ruleset.parameterTypeDescs[i]);
+        for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
+            TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
+            if(typeDesc.equals(TypeDesc.VOID))
+                continue;
+            storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "p" + i, typeDesc);
+        }
         storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);
         for(StoreInitialization ini : hashIndexInitializations)
             storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);
@@ -71,6 +75,9 @@ public class CHRCodeGenerator {
             mb.loadThis();
             mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
             for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
+                TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
+                if(typeDesc.equals(TypeDesc.VOID))
+                    continue;
                 mb.loadThis();
                 mb.loadLocal(mb.getParameter(i));
                 mb.storeField(ruleset.storeClassName, "p" + i, ruleset.parameterTypeDescs[i]);
@@ -136,8 +143,13 @@ public class CHRCodeGenerator {
          */
         TypeDesc[] parameterTypeDescs = jtt.toTypeDescs(constraint.parameterTypes);
         factClassBuilder.addField(Opcodes.ACC_PUBLIC, "id", FACT_ID_TYPE);
-        for(int i=0;i<constraint.parameterTypes.length;++i)
-            factClassBuilder.addField(Opcodes.ACC_PUBLIC, "c" + i, parameterTypeDescs[i]);
+        for(int i=0;i<constraint.parameterTypes.length;++i) {
+            TypeDesc typeDesc = parameterTypeDescs[i];
+            if(typeDesc.equals(TypeDesc.VOID))
+                continue;
+            if(parameterTypeDescs[i] != TypeDesc.VOID)
+                factClassBuilder.addField(Opcodes.ACC_PUBLIC, fieldName(i), typeDesc);
+        }
         
         for(IndexInfo indexInfo : constraint.getIndices()) {
             if(supportsRemoval)
@@ -191,9 +203,13 @@ public class CHRCodeGenerator {
                     int parameterId=0;
                     for(int i=0;i<constraint.parameterTypes.length;++i)
                         if(((indexInfo.indexMask>>i)&1)==1) {
-                            mb.loadLocal(tempFactVar);
-                            mb.loadLocal(mb.getParameter(parameterId++));
-                            mb.storeField(factClassName, "c"+i, parameterTypeDescs[i]);
+                            TypeDesc typeDesc = parameterTypeDescs[i];
+                            if(!typeDesc.equals(TypeDesc.VOID)) {
+                                mb.loadLocal(tempFactVar);
+                                mb.loadLocal(mb.getParameter(parameterId));
+                                mb.storeField(factClassName, fieldName(i), typeDesc);
+                            }
+                            ++parameterId;
                         }
 
                     mb.loadThis();
@@ -521,20 +537,26 @@ public class CHRCodeGenerator {
             //     this.c1 = c1;
             // }
             
-            TypeDesc[] constructorParameters = new TypeDesc[parameterTypeDescs.length+1];
-            constructorParameters[0] = FACT_ID_TYPE;
-            for(int i=0;i<parameterTypeDescs.length;++i)
-                constructorParameters[i+1] = parameterTypeDescs[i];
-            MethodBuilderBase mb = factClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, constructorParameters);
+            ArrayList<TypeDesc> constructorParameters = new ArrayList<TypeDesc>(parameterTypeDescs.length+1);
+            constructorParameters.add(FACT_ID_TYPE);
+            for(TypeDesc typeDesc : parameterTypeDescs) {
+                if(typeDesc.equals(TypeDesc.VOID))
+                    continue;
+                constructorParameters.add(typeDesc);
+            }
+            MethodBuilderBase mb = factClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, constructorParameters.toArray(new TypeDesc[constructorParameters.size()]));
             mb.loadThis();
             mb.invokeConstructor(factClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
             mb.loadThis();
             mb.loadLocal(mb.getParameter(0));
             mb.storeField(factClassName, "id", FACT_ID_TYPE);
-            for(int i=0;i<constraint.parameterTypes.length;++i) {
+            for(int i=0,parameterId=1;i<constraint.parameterTypes.length;++i) {
+                TypeDesc typeDesc = parameterTypeDescs[i];
+                if(typeDesc.equals(TypeDesc.VOID))
+                    continue;
                 mb.loadThis();
-                mb.loadLocal(mb.getParameter(i+1));
-                mb.storeField(factClassName, "c" + i, parameterTypeDescs[i]);
+                mb.loadLocal(mb.getParameter(parameterId++));
+                mb.storeField(factClassName, fieldName(i), typeDesc);
             }
             mb.returnVoid();
             mb.finish();
@@ -591,10 +613,10 @@ public class CHRCodeGenerator {
                     if(fieldTypeDesc.equals(TypeDesc.VOID))
                         continue;
                     mb.loadLocal(aVar);
-                    mb.loadField(factClassName, "c"+i, fieldTypeDesc);
+                    mb.loadField(factClassName, fieldName(i), fieldTypeDesc);
                     
                     mb.loadLocal(bVar);
-                    mb.loadField(factClassName, "c"+i, fieldTypeDesc);
+                    mb.loadField(factClassName, fieldName(i), fieldTypeDesc);
 
                     CodeBuilderUtils.equals(mb, fieldTypeDesc, failure);
                 }
@@ -630,7 +652,7 @@ public class CHRCodeGenerator {
                     if(fieldTypeDesc.equals(TypeDesc.VOID))
                         continue;
                     mb.loadLocal(factVar);
-                    mb.loadField(factClassName, "c"+i, fieldTypeDesc);
+                    mb.loadField(factClassName, fieldName(i), fieldTypeDesc);
                     CodeBuilderUtils.hashCode(mb, fieldTypeDesc);
                     mb.math(Opcodes.IXOR);
                     mb.loadConstant(16777619);
@@ -645,4 +667,8 @@ public class CHRCodeGenerator {
         
         return hashIndexClassBuilder;
     }
+    
+    public static String fieldName(int id) {
+        return "c" + id;
+    }
 }
index 5518cb4878fec54a1d384b406f4d767e169427be..0fe185e611df41ae90efad7e394b77119b0328f4 100644 (file)
@@ -42,6 +42,9 @@ public class ClassBuilder {
             String methodName,
             TypeDesc ret,
             TypeDesc[] params) {
+        for(TypeDesc param : params)
+            if(param.equals(TypeDesc.VOID))
+                throw new IllegalArgumentException();
         MethodVisitor methodVisitor = classVisitor.visitMethod(access, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(),
                 null, null);
@@ -68,6 +71,9 @@ public class ClassBuilder {
             String methodName,
             TypeDesc ret,
             TypeDesc[] params) {
+        for(TypeDesc param : params)
+            if(param.equals(TypeDesc.VOID))
+                throw new IllegalArgumentException();
         MethodVisitor methodVisitor = classVisitor.visitMethod(access, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(),
                 null, null);
@@ -79,6 +85,9 @@ public class ClassBuilder {
             String methodName,
             TypeDesc ret,
             TypeDesc[] params) {
+        for(TypeDesc param : params)
+            if(param.equals(TypeDesc.VOID))
+                throw new IllegalArgumentException();
         MethodVisitor methodVisitor = classVisitor.visitMethod(access, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(),
                 null, null);
@@ -101,6 +110,8 @@ public class ClassBuilder {
 
     public void addField(int access, String fieldName,
             TypeDesc type) {
+        if(type.equals(TypeDesc.VOID))
+            throw new IllegalArgumentException();
         FieldVisitor fieldVisitor = classVisitor.visitField(access, fieldName, type.getDescriptor(), null, null);
         fieldVisitor.visitEnd();
     }
index 7fb83fb49e3fd210dddd0ed7228a9febdaa792da..843659d6c12abe1f86fad86c0fda9b16e11e89f3 100644 (file)
@@ -379,6 +379,7 @@ public class MethodBuilderBase {
     public void invokeInterface(String className, String methodName,
             TypeDesc ret, TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, className, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(), true);
     }
@@ -391,6 +392,7 @@ public class MethodBuilderBase {
     public void invokeVirtual(String className, String methodName,
             TypeDesc ret, TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(), false);
     }
@@ -402,6 +404,7 @@ public class MethodBuilderBase {
 
     public void invokeConstructor(String className, TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>",
                 MethodDesc.forArguments(TypeDesc.VOID, params).getDescriptor(), false);
     }
@@ -417,6 +420,7 @@ public class MethodBuilderBase {
     public void invokeStatic(String className, String methodName, TypeDesc ret,
             TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, className, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(), false);
     }
@@ -606,4 +610,10 @@ public class MethodBuilderBase {
         else
             methodVisitor.visitLookupSwitchInsn(defaultLabel, values, labels);
     }
+    
+    private static void checkParameters(TypeDesc[] params) {
+        for(TypeDesc param : params)
+            if(param.equals(TypeDesc.VOID))
+                throw new IllegalArgumentException();
+    }
 }
index a2abc6eb50e8dc704f10d5223b62a74557e6f531..dc0714973abbbd9da901fe4d91df7e94442bcd0e 100644 (file)
@@ -4,3 +4,17 @@ main = ()
     then True
 --
 3:10-3:18: Cannot solve the query.
+--
+import "Prelude"
+
+main = getRef r
+  where
+    r = ref 1
+  
+    when True
+    then Foo ()
+    
+    when Foo _
+    then r := 2
+--
+2