include "Simantics/Entity" hiding (nameOf)\r
import "Simantics/Misc"\r
import "Simantics/Library"\r
-import "Simantics/DrawingTemplate"\r
\r
type Image = Resource\r
\r
"""\r
ACTION_COMPARATOR :: Comparator Action\r
\r
-instance Eq Action where\r
- a == b = compareWithComparator ACTION_COMPARATOR a b == 0\r
-\r
instance Ord Action where\r
compare = compareWithComparator ACTION_COMPARATOR\r
\r
\r
import org.simantics.db.Resource;\r
import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;\r
import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;\r
import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;\r
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.environment.Environment;\r
import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.Types;\r
Expression possibleValue = new EApply(\r
Locations.NO_LOCATION,\r
Types.READ_GRAPH,\r
- context.getTypingContext().getConstant(POSSIBLE_RELATED_VALUE, valueType),\r
+ context.getCompilationContext().getConstant(POSSIBLE_RELATED_VALUE, valueType),\r
context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),\r
new EVariable(parameters[0]),\r
new EExternalConstant(propertyRelation, RESOURCE)\r
case BB: {\r
Variable temp = new Variable("temp", valueType);\r
context.condition(new EApply(\r
- context.getTypingContext().getConstant(Name.create("Prelude", "=="), valueType),\r
+ context.getCompilationContext().getConstant(Names.Builtin_equals, valueType),\r
new Expression[] {\r
- context.getEvidence(location, Types.pred(Types.EQ, valueType)),\r
new EVariable(temp),\r
new EVariable(parameters[1])\r
}\r
return new EApply(\r
Locations.NO_LOCATION,\r
Types.WRITE_GRAPH,\r
- context.getTypingContext().getConstant(CLAIM_RELATED_VALUE, valueType),\r
+ context.getCompilationContext().getConstant(CLAIM_RELATED_VALUE, valueType),\r
context.getEvidence(location, Types.pred(Types.SERIALIZABLE, valueType)),\r
new EVariable(parameters[0]),\r
new EExternalConstant(propertyRelation, RESOURCE),\r
return 0;\r
}\r
\r
+ @Override\r
+ public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) {\r
+ throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce.");\r
+ }\r
+ \r
+ @Override\r
+ public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,\r
+ Expression[] expressions) {\r
+ throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate.");\r
+ }\r
}\r
\r
import org.simantics.db.Resource;\r
import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;\r
import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;\r
import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;\r
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.environment.Environment;\r
import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.Types;\r
context.iterateList(parameters[1], new EApply(\r
Locations.NO_LOCATION,\r
Types.READ_GRAPH,\r
- context.getTypingContext().getConstant(GET_OBJECTS),\r
+ context.getCompilationContext().getConstant(GET_OBJECTS),\r
new EVariable(parameters[0]),\r
new EExternalConstant(relation, Types.RESOURCE)\r
));\r
context.iterateList(parameters[0], new EApply(\r
Locations.NO_LOCATION,\r
Types.READ_GRAPH,\r
- context.getTypingContext().getConstant(GET_OBJECTS),\r
+ context.getCompilationContext().getConstant(GET_OBJECTS),\r
new EVariable(parameters[1]),\r
new EExternalConstant(inverseRelation, Types.RESOURCE)\r
));\r
? new EApply(\r
Locations.NO_LOCATION,\r
Types.READ_GRAPH,\r
- context.getTypingContext().getConstant(HAS_STATEMENT),\r
+ context.getCompilationContext().getConstant(HAS_STATEMENT),\r
new Expression[] {\r
new EVariable(parameters[0]),\r
new EExternalConstant(relation, Types.RESOURCE),\r
: new EApply(\r
Locations.NO_LOCATION,\r
Types.READ_GRAPH,\r
- context.getTypingContext().getConstant(HAS_STATEMENT),\r
+ context.getCompilationContext().getConstant(HAS_STATEMENT),\r
new Expression[] {\r
new EVariable(parameters[1]),\r
new EExternalConstant(inverseRelation, Types.RESOURCE),\r
return new EApply(\r
Locations.NO_LOCATION,\r
Types.WRITE_GRAPH,\r
- context.getTypingContext().getConstant(CLAIM),\r
+ context.getCompilationContext().getConstant(CLAIM),\r
new EVariable(parameters[0]),\r
new EExternalConstant(relation, Types.RESOURCE),\r
new EVariable(parameters[1])\r
return 0;\r
}\r
\r
+ @Override\r
+ public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,\r
+ Expression[] expressions) {\r
+ Environment env = context.context.environment;\r
+ switch(boundMask) {\r
+ case BF:\r
+ context.iterateList(location, w, variables[1],\r
+ w.apply(location,\r
+ env.getValue(GET_OBJECTS).getValue(),\r
+ expressions[0].toVal(env, w),\r
+ w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE)));\r
+ break;\r
+ case FB:\r
+ if(inverseRelation == null)\r
+ throw new IllegalArgumentException();\r
+ context.iterateList(location, w, variables[0],\r
+ w.apply(location,\r
+ env.getValue(GET_OBJECTS).getValue(),\r
+ expressions[1].toVal(env, w),\r
+ w.getModuleWriter().getExternalConstant(inverseRelation, Types.RESOURCE)));\r
+ break;\r
+ case BB:\r
+ context.check(location, w, \r
+ inverseRelation == null || relationSelectivity <= inverseRelationSelectivity\r
+ ? w.apply(location, env.getValue(HAS_STATEMENT).getValue(), \r
+ expressions[0].toVal(env, w),\r
+ w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE),\r
+ expressions[1].toVal(env, w))\r
+ : w.apply(location, env.getValue(HAS_STATEMENT).getValue(), \r
+ expressions[1].toVal(env, w),\r
+ w.getModuleWriter().getExternalConstant(inverseRelation, Types.RESOURCE),\r
+ expressions[0].toVal(env, w)));\r
+ break;\r
+ default: throw new IllegalArgumentException();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) {\r
+ Environment env = context.context.environment;\r
+ w.apply(location,\r
+ env.getValue(CLAIM).getValue(),\r
+ parameters[0].toVal(env, w),\r
+ w.getModuleWriter().getExternalConstant(relation, Types.RESOURCE),\r
+ parameters[1].toVal(env, w));\r
+ }\r
}\r
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
<classpathentry kind="src" path="src"/>\r
- <classpathentry kind="src" path="tests"/>\r
- <classpathentry exported="true" kind="lib" path="tools/procyon-decompiler-0.5.29.jar"/>\r
<classpathentry kind="output" path="bin"/>\r
</classpath>\r
+++ /dev/null
-eclipse.preferences.version=1\r
-encoding//tests/org/simantics/scl/compiler/tests/scl/InvalidEncoding.scl=ISO-8859-1\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">\r
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">\r
-<listEntry value="/org.simantics.scl.compiler/tests/org/simantics/scl/compiler/tests/ActiveTests.java"/>\r
-</listAttribute>\r
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">\r
-<listEntry value="1"/>\r
-</listAttribute>\r
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>\r
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>\r
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>\r
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>\r
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.simantics.scl.compiler.tests.ActiveTests"/>\r
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.simantics.scl.compiler"/>\r
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:-UseSplitVerifier"/>\r
-</launchConfiguration>\r
Bundle-ManifestVersion: 2
Bundle-Name: SCL Compiler
Bundle-SymbolicName: org.simantics.scl.compiler
-Bundle-Version: 0.5.0.qualifier
+Bundle-Version: 0.6.1.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: gnu.trove3;bundle-version="3.0.0",
org.simantics.scl.runtime;bundle-version="0.1.4";visibility:=reexport,
org.junit;bundle-version="4.12.0";resolution:=optional,
org.objectweb.asm;bundle-version="[5.0.0,6.0.0)",
org.objectweb.asm.commons;bundle-version="[5.0.0,6.0.0)",
- org.objectweb.asm.util;bundle-version="[5.0.0,6.0.0)"
+ org.objectweb.asm.util;bundle-version="[5.0.0,6.0.0)",
+ org.slf4j.api;bundle-version="1.7.2"
Export-Package: org.cojen.classfile,
org.simantics.scl.compiler.commands,
org.simantics.scl.compiler.common.datatypes,
org.simantics.scl.compiler.compilation,
org.simantics.scl.compiler.constants,
org.simantics.scl.compiler.constants.generic,
+ org.simantics.scl.compiler.elaboration.chr,
+ org.simantics.scl.compiler.elaboration.chr.plan,
+ org.simantics.scl.compiler.elaboration.chr.planning,
+ org.simantics.scl.compiler.elaboration.chr.relations;x-friends:="org.simantics.scl.compiler.tests",
org.simantics.scl.compiler.elaboration.contexts,
org.simantics.scl.compiler.elaboration.equation,
org.simantics.scl.compiler.elaboration.errors,
org.simantics.scl.compiler.environment.filter,
org.simantics.scl.compiler.environment.specification,
org.simantics.scl.compiler.errors,
+ org.simantics.scl.compiler.internal.codegen.chr;x-friends:="org.simantics.scl.compiler.tests",
+ org.simantics.scl.compiler.internal.codegen.references,
+ org.simantics.scl.compiler.internal.codegen.types;x-friends:="org.simantics.scl.compiler.tests",
+ org.simantics.scl.compiler.internal.codegen.utils;x-friends:="org.simantics.scl.compiler.tests",
+ org.simantics.scl.compiler.internal.codegen.writer,
org.simantics.scl.compiler.internal.elaboration.constraints2,
org.simantics.scl.compiler.internal.elaboration.subsumption,
org.simantics.scl.compiler.internal.parsing,
org.simantics.scl.compiler.types.exceptions,
org.simantics.scl.compiler.types.kinds,
org.simantics.scl.compiler.types.util
-Bundle-ClassPath: tools/procyon-decompiler-0.5.29.jar,
- .
+Bundle-ClassPath: .
Service-Component: OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml
Import-Package: org.osgi.service.component.annotations
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
-<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">\r
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">\r
-<listEntry value="/org.simantics.scl.compiler/tests/org/simantics/scl/compiler/tests/RegressionTests.java"/>\r
-</listAttribute>\r
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">\r
-<listEntry value="1"/>\r
-</listAttribute>\r
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>\r
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>\r
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>\r
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>\r
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.simantics.scl.compiler.tests.RegressionTests"/>\r
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.simantics.scl.compiler"/>\r
-</launchConfiguration>\r
output.. = bin/\r
bin.includes = META-INF/,\\r
.,\\r
- tools/procyon-decompiler-0.5.29.jar,\\r
OSGI-INF/org.simantics.scl.compiler.source.repository.BuiltinModuleSourceRepository.xml\r
package org.cojen.classfile;
-import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.lang.reflect.Array;
import java.util.Collections;
* @author Brian S O'Neill
*/
@SuppressWarnings("rawtypes")
-public abstract class TypeDesc extends Descriptor implements Serializable {
+public abstract class TypeDesc extends Descriptor {
/**
* Type code returned from getTypeCode, which can be used with the
* newarray instruction.
+++ /dev/null
-/*
- * Copyright 2004-2010 Brian S O'Neill
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.cojen.util;
-
-import java.util.Arrays;
-
-/**
- * KeyFactory generates keys which can be hashed or compared for any kind of
- * object including arrays, arrays of arrays, and null. All hashcode
- * computations, equality tests, and ordering comparsisons fully recurse into
- * arrays.
- *
- * @author Brian S O'Neill
- */
-@SuppressWarnings({ "rawtypes", "unused", "unchecked", "serial" })
-public class KeyFactory {
- static final Object NULL = new Comparable() {
- public int compareTo(Object obj) {
- return obj == this || obj == null ? 0 : 1;
- }
- };
-
- public static Object createKey(boolean[] obj) {
- return obj == null ? NULL : new BooleanArrayKey(obj);
- }
-
- public static Object createKey(byte[] obj) {
- return obj == null ? NULL : new ByteArrayKey(obj);
- }
-
- public static Object createKey(char[] obj) {
- return obj == null ? NULL : new CharArrayKey(obj);
- }
-
- public static Object createKey(double[] obj) {
- return obj == null ? NULL : new DoubleArrayKey(obj);
- }
-
- public static Object createKey(float[] obj) {
- return obj == null ? NULL : new FloatArrayKey(obj);
- }
-
- public static Object createKey(int[] obj) {
- return obj == null ? NULL : new IntArrayKey(obj);
- }
-
- public static Object createKey(long[] obj) {
- return obj == null ? NULL : new LongArrayKey(obj);
- }
-
- public static Object createKey(short[] obj) {
- return obj == null ? NULL : new ShortArrayKey(obj);
- }
-
- public static Object createKey(Object[] obj) {
- return obj == null ? NULL : new ObjectArrayKey(obj);
- }
-
- public static Object createKey(Object obj) {
- if (obj == null) {
- return NULL;
- }
- if (!obj.getClass().isArray()) {
- return obj;
- }
- if (obj instanceof Object[]) {
- return createKey((Object[])obj);
- } else if (obj instanceof int[]) {
- return createKey((int[])obj);
- } else if (obj instanceof float[]) {
- return createKey((float[])obj);
- } else if (obj instanceof long[]) {
- return createKey((long[])obj);
- } else if (obj instanceof double[]) {
- return createKey((double[])obj);
- } else if (obj instanceof byte[]) {
- return createKey((byte[])obj);
- } else if (obj instanceof char[]) {
- return createKey((char[])obj);
- } else if (obj instanceof boolean[]) {
- return createKey((boolean[])obj);
- } else if (obj instanceof short[]) {
- return createKey((short[])obj);
- } else {
- return obj;
- }
- }
-
- static int hashCode(boolean[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- hash = (hash << 1) + (a[i] ? 0 : 1);
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(byte[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- hash = (hash << 1) + a[i];
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(char[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- hash = (hash << 1) + a[i];
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(double[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- long v = Double.doubleToLongBits(a[i]);
- hash = hash * 31 + (int)(v ^ v >>> 32);
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(float[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- hash = hash * 31 + Float.floatToIntBits(a[i]);
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(int[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- hash = (hash << 1) + a[i];
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(long[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- long v = a[i];
- hash = hash * 31 + (int)(v ^ v >>> 32);
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(short[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- hash = (hash << 1) + a[i];
- }
- return hash == 0 ? -1 : hash;
- }
-
- static int hashCode(Object[] a) {
- int hash = 0;
- for (int i = a.length; --i >= 0; ) {
- hash = hash * 31 + hashCode(a[i]);
- }
- return hash == 0 ? -1 : hash;
- }
-
- // Compute object or array hashcode and recurses into arrays within.
- static int hashCode(Object a) {
- if (a == null) {
- return -1;
- }
- if (!a.getClass().isArray()) {
- return a.hashCode();
- }
- if (a instanceof Object[]) {
- return hashCode((Object[])a);
- } else if (a instanceof int[]) {
- return hashCode((int[])a);
- } else if (a instanceof float[]) {
- return hashCode((float[])a);
- } else if (a instanceof long[]) {
- return hashCode((long[])a);
- } else if (a instanceof double[]) {
- return hashCode((double[])a);
- } else if (a instanceof byte[]) {
- return hashCode((byte[])a);
- } else if (a instanceof char[]) {
- return hashCode((char[])a);
- } else if (a instanceof boolean[]) {
- return hashCode((boolean[])a);
- } else if (a instanceof short[]) {
- return hashCode((short[])a);
- } else {
- int hash = a.getClass().hashCode();
- return hash == 0 ? -1 : hash;
- }
- }
-
- // Compares object arrays and recurses into arrays within.
- static boolean equals(Object[] a, Object[] b) {
- if (a == b) {
- return true;
- }
- if (a == null || b == null) {
- return false;
- }
- int i;
- if ((i = a.length) != b.length) {
- return false;
- }
- while (--i >= 0) {
- if (!equals(a[i], b[i])) {
- return false;
- }
- }
- return true;
- }
-
- // Compares objects or arrays and recurses into arrays within.
- static boolean equals(Object a, Object b) {
- if (a == b) {
- return true;
- }
- if (a == null || b == null) {
- return false;
- }
- Class ac = a.getClass();
- if (!(ac.isArray())) {
- return a.equals(b);
- }
- if (ac != b.getClass()) {
- return false;
- }
- if (a instanceof Object[]) {
- return equals((Object[])a, (Object[])b);
- } else if (a instanceof int[]) {
- return Arrays.equals((int[])a, (int[])b);
- } else if (a instanceof float[]) {
- return Arrays.equals((float[])a, (float[])b);
- } else if (a instanceof long[]) {
- return Arrays.equals((long[])a, (long[])b);
- } else if (a instanceof double[]) {
- return Arrays.equals((double[])a, (double[])b);
- } else if (a instanceof byte[]) {
- return Arrays.equals((byte[])a, (byte[])b);
- } else if (a instanceof char[]) {
- return Arrays.equals((char[])a, (char[])b);
- } else if (a instanceof boolean[]) {
- return Arrays.equals((boolean[])a, (boolean[])b);
- } else if (a instanceof short[]) {
- return Arrays.equals((short[])a, (short[])b);
- } else {
- return a.equals(b);
- }
- }
-
- static int compare(boolean[] a, boolean[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- int av = a[i] ? 0 : 1;
- int bv = b[i] ? 0 : 1;
- return av < bv ? -1 : (av > bv ? 1 : 0);
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- static int compare(byte[] a, byte[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- byte av = a[i];
- byte bv = b[i];
- return av < bv ? -1 : (av > bv ? 1 : 0);
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- static int compare(char[] a, char[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- char av = a[i];
- char bv = b[i];
- return av < bv ? -1 : (av > bv ? 1 : 0);
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- static int compare(double[] a, double[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- int v = Double.compare(a[i], b[i]);
- if (v != 0) {
- return v;
- }
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- static int compare(float[] a, float[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- int v = Float.compare(a[i], b[i]);
- if (v != 0) {
- return v;
- }
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- static int compare(int[] a, int[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- int av = a[i];
- int bv = b[i];
- return av < bv ? -1 : (av > bv ? 1 : 0);
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- static int compare(long[] a, long[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- long av = a[i];
- long bv = b[i];
- return av < bv ? -1 : (av > bv ? 1 : 0);
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- static int compare(short[] a, short[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- short av = a[i];
- short bv = b[i];
- return av < bv ? -1 : (av > bv ? 1 : 0);
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- // Compares object arrays and recurses into arrays within.
- static int compare(Object[] a, Object[] b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- int length = Math.min(a.length, b.length);
- for (int i=0; i<length; i++) {
- int v = compare(a[i], b[i]);
- if (v != 0) {
- return v;
- }
- }
- return a.length < b.length ? -1 : (a.length > b.length ? 1 : 0);
- }
-
- // Compares objects or arrays and recurses into arrays within.
- static int compare(Object a, Object b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- Class ac = a.getClass();
- if (!(ac.isArray())) {
- return ((Comparable)a).compareTo(b);
- }
- if (ac != b.getClass()) {
- throw new ClassCastException();
- }
- if (a instanceof Object[]) {
- return compare((Object[])a, (Object[])b);
- } else if (a instanceof int[]) {
- return compare((int[])a, (int[])b);
- } else if (a instanceof float[]) {
- return compare((float[])a, (float[])b);
- } else if (a instanceof long[]) {
- return compare((long[])a, (long[])b);
- } else if (a instanceof double[]) {
- return compare((double[])a, (double[])b);
- } else if (a instanceof byte[]) {
- return compare((byte[])a, (byte[])b);
- } else if (a instanceof char[]) {
- return compare((char[])a, (char[])b);
- } else if (a instanceof boolean[]) {
- return compare((boolean[])a, (boolean[])b);
- } else if (a instanceof short[]) {
- return compare((short[])a, (short[])b);
- } else {
- throw new ClassCastException();
- }
- }
-
- protected KeyFactory() {
- }
-
- private static interface ArrayKey extends Comparable, java.io.Serializable {
- int hashCode();
-
- boolean equals(Object obj);
-
- int compareTo(Object obj);
- }
-
- private static class BooleanArrayKey implements ArrayKey {
- protected final boolean[] mArray;
- private transient int mHash;
-
- BooleanArrayKey(boolean[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof BooleanArrayKey ?
- Arrays.equals(mArray, ((BooleanArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((BooleanArrayKey) obj).mArray);
- }
- }
-
- private static class ByteArrayKey implements ArrayKey {
- protected final byte[] mArray;
- private transient int mHash;
-
- ByteArrayKey(byte[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof ByteArrayKey ?
- Arrays.equals(mArray, ((ByteArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((ByteArrayKey) obj).mArray);
- }
- }
-
- private static class CharArrayKey implements ArrayKey {
- protected final char[] mArray;
- private transient int mHash;
-
- CharArrayKey(char[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof CharArrayKey ?
- Arrays.equals(mArray, ((CharArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((CharArrayKey) obj).mArray);
- }
- }
-
- private static class DoubleArrayKey implements ArrayKey {
- protected final double[] mArray;
- private transient int mHash;
-
- DoubleArrayKey(double[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof DoubleArrayKey ?
- Arrays.equals(mArray, ((DoubleArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((DoubleArrayKey) obj).mArray);
- }
- }
-
- private static class FloatArrayKey implements ArrayKey {
- protected final float[] mArray;
- private transient int mHash;
-
- FloatArrayKey(float[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof FloatArrayKey ?
- Arrays.equals(mArray, ((FloatArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((FloatArrayKey) obj).mArray);
- }
- }
-
- private static class IntArrayKey implements ArrayKey {
- protected final int[] mArray;
- private transient int mHash;
-
- IntArrayKey(int[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof IntArrayKey ?
- Arrays.equals(mArray, ((IntArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((IntArrayKey) obj).mArray);
- }
- }
-
- private static class LongArrayKey implements ArrayKey {
- protected final long[] mArray;
- private transient int mHash;
-
- LongArrayKey(long[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof LongArrayKey ?
- Arrays.equals(mArray, ((LongArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((LongArrayKey) obj).mArray);
- }
- }
-
- private static class ShortArrayKey implements ArrayKey {
- protected final short[] mArray;
- private transient int mHash;
-
- ShortArrayKey(short[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof ShortArrayKey ?
- Arrays.equals(mArray, ((ShortArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((ShortArrayKey) obj).mArray);
- }
- }
-
- private static class ObjectArrayKey implements ArrayKey {
- protected final Object[] mArray;
- private transient int mHash;
-
- ObjectArrayKey(Object[] array) {
- mArray = array;
- }
-
- public int hashCode() {
- int hash = mHash;
- return hash == 0 ? mHash = KeyFactory.hashCode(mArray) : hash;
- }
-
- public boolean equals(Object obj) {
- return this == obj ? true :
- (obj instanceof ObjectArrayKey ?
- KeyFactory.equals(mArray, ((ObjectArrayKey) obj).mArray) : false);
- }
-
- public int compareTo(Object obj) {
- return compare(mArray, ((ObjectArrayKey) obj).mArray);
- }
- }
-}
public abstract class ReferencedValueHashMap<K, V> extends AbstractMap<K, V>
implements Map<K, V>, Cloneable
{
+ static final Object NULL = new Comparable() {
+ public int compareTo(Object obj) {
+ return obj == this || obj == null ? 0 : 1;
+ }
+ };
+
private transient Entry<K, V>[] table;
private transient int count;
private int threshold;
public boolean containsValue(Object value) {
if (value == null) {
- value = KeyFactory.NULL;
+ value = NULL;
}
Entry[] tab = this.table;
}
count--;
} else if (e.hash == hash && key.equals(e.key)) {
- return (entryValue == KeyFactory.NULL) ? null : entryValue;
+ return (entryValue == NULL) ? null : entryValue;
} else {
prev = e;
}
}
this.count--;
} else if (e.key == null) {
- return (entryValue == KeyFactory.NULL) ? null : entryValue;
+ return (entryValue == NULL) ? null : entryValue;
} else {
prev = e;
}
public V put(K key, V value) {
if (value == null) {
- value = (V) KeyFactory.NULL;
+ value = (V) NULL;
}
// Makes sure the key is not already in the HashMap.
this.count--;
} else if (e.hash == hash && key.equals(e.key)) {
e.setValue(value);
- return (entryValue == KeyFactory.NULL) ? null : entryValue;
+ return (entryValue == NULL) ? null : entryValue;
} else {
prev = e;
}
this.count--;
} else if (e.key == null) {
e.setValue(value);
- return (entryValue == KeyFactory.NULL) ? null : entryValue;
+ return (entryValue == NULL) ? null : entryValue;
} else {
prev = e;
}
this.count--;
e.setValue(null);
- return (entryValue == KeyFactory.NULL) ? null : entryValue;
+ return (entryValue == NULL) ? null : entryValue;
} else {
prev = e;
}
this.count--;
e.setValue(null);
- return (entryValue == KeyFactory.NULL) ? null : entryValue;
+ return (entryValue == NULL) ? null : entryValue;
} else {
prev = e;
}
public V getValue() {
V value = this.value.get();
- return value == KeyFactory.NULL ? null : value;
+ return value == NULL ? null : value;
}
public V setValue(V value) {
V oldValue = getValue();
- this.value = newReference(value == null ? ((V) KeyFactory.NULL) : value);
+ this.value = newReference(value == null ? ((V) NULL) : value);
return oldValue;
}
Object thisValue = get();
if (thisValue == null) {
return false;
- } else if (thisValue == KeyFactory.NULL) {
+ } else if (thisValue == NULL) {
thisValue = null;
}
return (this.key == null ? e.getKey() == null : this.key.equals(e.getKey())) &&
public boolean containsKey(Object key) {
if (key == null) {
- key = KeyFactory.NULL;
+ key = ReferencedValueHashMap.NULL;
}
Entry[] tab = this.table;
public V get(Object key) {
if (key == null) {
- key = KeyFactory.NULL;
+ key = ReferencedValueHashMap.NULL;
}
Entry<K, V>[] tab = this.table;
public V put(K key, V value) {
if (key == null) {
- key = (K) KeyFactory.NULL;
+ key = (K) ReferencedValueHashMap.NULL;
}
cleanup();
public V remove(Object key) {
if (key == null) {
- key = KeyFactory.NULL;
+ key = ReferencedValueHashMap.NULL;
}
Entry<K, V>[] tab = this.table;
public K getKey() {
K key = Entry.this.get();
- return key == KeyFactory.NULL ? null : key;
+ return key == ReferencedValueHashMap.NULL ? null : key;
}
public V getValue() {
Object thisKey = get();
if (thisKey == null) {
return false;
- } else if (thisKey == KeyFactory.NULL) {
+ } else if (thisKey == ReferencedValueHashMap.NULL) {
thisKey = null;
}
return (thisKey == e.getKey()) &&
import java.util.Map;
import java.util.Set;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.constants.StringConstant;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EBlock;
import org.simantics.scl.compiler.top.ExpressionEvaluator;
import org.simantics.scl.compiler.top.LocalStorage;
import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
-import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.runtime.SCLContext;
PrintStream fileOutput;
- private static final String CONTEXT_MODULE = "Expressions/Context";
- private static final TCon CONTEXT_TYPE = Types.con(CONTEXT_MODULE, "Context");
- private static final Name CONTEXT_GET = Name.create(CONTEXT_MODULE, "contextGet");
-
public CommandSession(ModuleRepository moduleRepository, SCLReportingHandler handler) {
this.moduleRepository = moduleRepository;
this.defaultHandler = new PrintDecorator(
}, Types.functionE(Types.STRING, Types.PROC, Types.UNIT)));
LOCAL_FUNCTIONS.put("reset", new LocalFunction(new FunctionImpl2<CommandSession, Tuple0, Tuple0>() {
@Override
- public Tuple0 apply(CommandSession commandSession, Tuple0 _) {
+ public Tuple0 apply(CommandSession commandSession, Tuple0 dummy) {
commandSession.removeTransientImports();
commandSession.removeVariables();
commandSession.moduleRepository.getSourceRepository().checkUpdates();
}, Types.functionE(Types.UNIT, Types.PROC, Types.UNIT)));
LOCAL_FUNCTIONS.put("variables", new LocalFunction(new FunctionImpl2<CommandSession, Tuple0, List<String>>() {
@Override
- public List<String> apply(CommandSession commandSession, Tuple0 _) {
+ public List<String> apply(CommandSession commandSession, Tuple0 dummy) {
ArrayList<String> result = new ArrayList<String>(commandSession.variableTypes.keySet());
Collections.sort(result);
return result;
}, Types.functionE(Types.STRING, Types.PROC, Types.UNIT)));
LOCAL_FUNCTIONS.put("stopPrintingToFile", new LocalFunction(new FunctionImpl2<CommandSession, Tuple0, Tuple0>() {
@Override
- public Tuple0 apply(final CommandSession commandSession, Tuple0 _) {
+ public Tuple0 apply(final CommandSession commandSession, Tuple0 dummy) {
if(commandSession.fileOutput != null) {
commandSession.fileOutput.close();
commandSession.fileOutput = null;
private LocalEnvironment createLocalEnvironment() {
return new AbstractLocalEnvironment() {
- Variable contextVariable = new Variable("context", CONTEXT_TYPE);
+ Variable contextVariable = new Variable("context", Names.Expressions_Context_Context);
@Override
public Expression resolve(Environment environment, String localName) {
Type type = variableTypes.get(localName);
if(type != null)
return new EApply(
- new EConstant(environment.getValue(CONTEXT_GET), type),
+ new EConstant(environment.getValue(Names.Expressions_Context_contextGet), type),
new EVariable(contextVariable),
new ELiteral(new StringConstant(localName))
);
--- /dev/null
+package org.simantics.scl.compiler.common.names;\r
+\r
+import org.simantics.scl.compiler.types.TCon;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class Names {\r
+ \r
+ public static final Name ArrayList_add = Name.create("ArrayList", "add");\r
+ public static final Name ArrayList_freeze = Name.create("ArrayList", "freeze");\r
+ public static final Name ArrayList_new = Name.create("ArrayList", "new");\r
+ public static final Name Builtin_equals = Name.create(Types.BUILTIN, "==");\r
+ public static final Name Builtin_fail = Name.create(Types.BUILTIN, "fail");\r
+ public static final Name Builtin_runProc = Name.create(Types.BUILTIN, "runProc");\r
+ public static final Name Data_XML_createElement = Name.create("Data/XML", "createElement");\r
+ public static final Type Data_XML_Element = Types.con("Data/XML", "Element");\r
+ public static final TCon Expressions_Context_Context = Types.con("Expressions/Context", "Context"); \r
+ public static final Name Expressions_Context_contextGet = Name.create("Expressions/Context", "contextGet");\r
+ public static final Name JavaBuiltin_unsafeCoerce = Name.create("JavaBuiltin", "unsafeCoerce");\r
+ public static final Name MList_add = Name.create("MList", "add");\r
+ public static final Name MList_create = Name.create("MList", "create");\r
+ public static final Name MList_removeLast = Name.create("MList", "removeLast");\r
+ public static final TCon MList_T = Types.con("MList", "T");\r
+ public static final Name MSet_add = Name.create("MSet", "add");\r
+ public static final Name MSet_contains = Name.create("MSet", "contains");\r
+ public static final Name MSet_create = Name.create("MSet", "create");\r
+ public static final Name MSet_iter = Name.create("MSet", "iter");\r
+ public static final Name MSet_mapFirst = Name.create("MSet", "mapFirst");\r
+ public static final TCon MSet_T = Types.con("MSet", "T");\r
+ public static final Name Prelude_addList = Name.create("Prelude", "addList");\r
+ public static final Name Prelude_any = Name.create("Prelude", "any");\r
+ public static final Name Prelude_appendList = Name.create("Prelude", "appendList");\r
+ public static final Name Prelude_bind = Name.create("Prelude", ">>=");\r
+ public static final Name Prelude_build = Name.create("Prelude", "build");\r
+ public static final Name Prelude_concatMap = Name.create("Prelude", "concatMap");\r
+ public static final Name Prelude_elem = Name.create("Prelude", "elem");\r
+ public static final Name Prelude_elemMaybe = Name.create("Prelude", "elemMaybe");\r
+ public static final Name Prelude_emptyList = Name.create("Prelude", "emptyList");\r
+ public static final Name Prelude_foldl = Name.create("Prelude", "foldl");\r
+ public static final Name Prelude_fromDouble = Name.create("Prelude", "fromDouble"); \r
+ public static final Name Prelude_fromInteger = Name.create("Prelude", "fromInteger"); \r
+ public static final Name Prelude_guardList = Name.create("Prelude", "guardList");\r
+ public static final Name Prelude_iterList = Name.create("Prelude", "iterList");\r
+ public static final Name Prelude_mapFirst = Name.create("Prelude", "mapFirst");\r
+ public static final Name Prelude_mapList = Name.create("Prelude", "mapList");\r
+ public static final Name Prelude_neg = Name.create("Prelude", "neg");\r
+ public static final Name Prelude_not = Name.create("Prelude", "not");\r
+ public static final Name Prelude_range = Name.create("Prelude", "range");\r
+ public static final Name Prelude_showForPrinting = Name.create("Prelude", "showForPrinting");\r
+ public static final Name Prelude_singletonList = Name.create("Prelude", "singletonList");\r
+ public static final Name R_R_runR = Name.create("R/R", "runR");\r
+ public static final Name Random_runRandom = Name.create("Random", "runRandom");\r
+ public static final Name Serialization_ioSize = Name.create("Serialization", "ioSize");\r
+ public static final Name Serialization_read = Name.create("Serialization", "read");\r
+ public static final Name Serialization_write = Name.create("Serialization", "write");\r
+ public static final Name Simantics_DB_newResource = Name.create("Simantics/DB", "newResource");\r
+ public static final Name Simantics_DB_syncRead = Name.create("Simantics/DB", "syncRead");\r
+ public static final Name Simantics_DB_syncWrite = Name.create("Simantics/DB", "syncWrite");\r
+ public static final Name Simantics_Variables_child_ = Name.create("Simantics/Variables", "child_");\r
+ public static final Name Simantics_Variables_property = Name.create("Simantics/Variables", "property");\r
+ public static final Name Simantics_Variables_untypedPropertyValue = Name.create("Simantics/Variables", "untypedPropertyValue");\r
+ public static final Name Unifiable_createUMap = Name.create("Unification", "createUMap");\r
+ public static final Name Unifiable_extractWithDefault = Name.create("Unification", "extractWithDefault");\r
+ public static final Name Unifiable_getUMapWithDefault = Name.create("Unification", "getUMapWithDefault");\r
+ public static final Name Unifiable_putUMap = Name.create("Unification", "putUMap");\r
+ public static final Name Unifiable_putUMapC = Name.create("Unification", "putUMapC");\r
+ public static final Name Unifiable_uCons = Name.create("Unification", "uCons");\r
+ public static final Name Unifiable_uId = Name.create("Unification", "uId");\r
+ public static final TCon Unifiable_UMap = Types.con("Unification", "UMap");\r
+ public static final TCon Unifiable_Unifiable = Types.con("Unification", "Unifiable");\r
+ public static final Name Unifiable_uPending = Name.create("Unification", "uPending");\r
+ public static final Name Unifiable_uTag = Name.create("Unification", "uTag");\r
+ public static final TCon Unifiable_UTag = Types.con("Unification", "UTag");\r
+ public static final Name Unifiable_uVar = Name.create("Unification", "uVar");\r
+ public static final Name Vector_anyVector = Name.create("Vector", "anyVector");\r
+ public static final Name Vector_concatMapVector = Name.create("Vector", "concatMapVector");\r
+ public static final Name Vector_iterVector = Name.create("Vector", "iterVector");\r
+ public static final Name Vector_mapFirstVector = Name.create("Vector", "mapFirstVector");\r
+ \r
+}\r
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
import org.simantics.scl.compiler.elaboration.modules.TypeClassMethod;
-import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.errors.ErrorLog;
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.CodeBuilderUtils;
import org.simantics.scl.compiler.internal.codegen.utils.CodeBuildingException;
import org.simantics.scl.compiler.internal.codegen.utils.Constants;
-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.MethodBuilderBase;
import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
public static final int OPTIMIZATION_PHASES = 2;
+ CompilationContext compilationContext;
ErrorLog errorLog;
- Environment environment;
- JavaNamingPolicy namingPolicy;
- JavaTypeTranslator javaTypeTranslator;
JavaReferenceValidator<Object, Object, Object, Object> validator;
ConcreteModule module;
ModuleBuilder moduleBuilder;
Map<String, byte[]> classes;
@SuppressWarnings("unchecked")
- public CodeGeneration(ErrorLog errorLog,
- Environment environment,
- JavaNamingPolicy namingPolicy, JavaTypeTranslator javaTypeTranslator,
+ public CodeGeneration(CompilationContext compilationContext,
JavaReferenceValidator<?, ?, ?, ?> javaReferenceValidator,
- ConcreteModule module) {
- this.errorLog = errorLog;
- this.environment = environment;
- this.namingPolicy = namingPolicy;
- this.javaTypeTranslator = javaTypeTranslator;
+ ConcreteModule module) {
+ this.compilationContext = compilationContext;
+ this.errorLog = compilationContext.errorLog;
this.module = module;
this.validator = (JavaReferenceValidator<Object, Object, Object, Object>) javaReferenceValidator;
- moduleBuilder = new ModuleBuilder(namingPolicy, javaTypeTranslator);
+ moduleBuilder = new ModuleBuilder(compilationContext.namingPolicy, compilationContext.javaTypeTranslator);
}
public void simplifyValues() {
//System.out.println("===== Simplify values =====");
Collection<SCLValue> values = module.getValues();
- SimplificationContext simplificationContext =
- new SimplificationContext(environment, errorLog,
- javaTypeTranslator, validator);
+ SimplificationContext simplificationContext = new SimplificationContext(compilationContext, validator);
//System.out.println("-----------------------------------------------");
SCLValue[] valueArray = values.toArray(new SCLValue[values.size()]);
}
public void convertToSSA() {
- ModuleWriter mw = new ModuleWriter(namingPolicy.getModuleClassName());
+ ModuleWriter mw = new ModuleWriter(compilationContext.namingPolicy.getModuleClassName());
for(SCLValue value : module.getValues()) {
//System.out.println(value.getName().name + " :: " + value.getType());
Expression expression = value.getExpression();
continue;
Name name = value.getName();
- DecomposedExpression decomposed =
- DecomposedExpression.decompose(expression);
SCLConstant constant = new SCLConstant(name, value.getType());
value.setValue(constant);
IVal[] parameterVals = w.getParameters();
for(int i=0;i<decomposed.parameters.length;++i)
decomposed.parameters[i].setVal(parameterVals[i]);
- w.return_(decomposed.body.toVal(environment, w));
+ w.return_(decomposed.body.toVal(compilationContext.environment, w));
} catch(RuntimeException e) {
errorLog.setExceptionPosition(value.getExpression().location);
throw e;
ssaModule.validate();
int optCount = 0;
for(int phase=0;phase<OPTIMIZATION_PHASES;++phase) {
- while(optCount++ < 100 && ssaModule.simplify(environment, phase)) {
+ while(optCount++ < 100 && ssaModule.simplify(compilationContext.environment, phase)) {
//System.out.println("simplify " + optCount);
//System.out.println("================================================================");
//System.out.println(ssaModule);
cf.setSourceFile("_SCL_DataType");
CodeBuilderUtils.makeRecord(cf, constructor.name.name,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "c",
- javaTypeTranslator.toTypeDescs(constructor.parameterTypes),
+ compilationContext.javaTypeTranslator.toTypeDescs(constructor.parameterTypes),
true);
moduleBuilder.addClass(cf);
}
cf.setSourceFile("_SCL_DataType");
CodeBuilderUtils.makeRecord(cf, constructor.name.name,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "c",
- javaTypeTranslator.toTypeDescs(constructor.parameterTypes),
+ compilationContext.javaTypeTranslator.toTypeDescs(constructor.parameterTypes),
true);
moduleBuilder.addClass(cf);
}
MethodImplementation implementation =
instance.methodImplementations.get(method.getName());
if(implementation.isDefault) {
- IVal function = environment.getValue(implementation.name).getValue();
+ IVal function = compilationContext.environment.getValue(implementation.name).getValue();
Val[] parameters = new Val[method.getArity() + 1];
MultiFunction mfun2;
--- /dev/null
+package org.simantics.scl.compiler.compilation;\r
+\r
+import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EError;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
+import org.simantics.scl.compiler.environment.Environment;\r
+import org.simantics.scl.compiler.errors.ErrorLog;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;\r
+import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;\r
+import org.simantics.scl.compiler.module.ConcreteModule;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+public class CompilationContext implements EnvironmentalContext {\r
+ public final ErrorLog errorLog = new ErrorLog();\r
+ public Environment environment;\r
+ public JavaTypeTranslator javaTypeTranslator;\r
+ public JavaNamingPolicy namingPolicy;\r
+ public ConcreteModule module;\r
+ \r
+ private THashMap<Name, SCLValue> valueCache = new THashMap<Name, SCLValue>();\r
+\r
+ public SCLValue getValue(Name name) {\r
+ if(valueCache.containsKey(name))\r
+ return valueCache.get(name);\r
+ SCLValue value = environment.getValue(name);\r
+ if(value == null)\r
+ errorLog.log(Locations.NO_LOCATION, "Couldn't find " + name + ".");\r
+ valueCache.put(name, value);\r
+ return value;\r
+ }\r
+ \r
+ public Expression getConstant(Name name, Type ... typeParameters) {\r
+ SCLValue value = getValue(name);\r
+ if(value == null)\r
+ return new EError(Locations.NO_LOCATION);\r
+ return new EConstant(value, typeParameters);\r
+ }\r
+}\r
ErrorLog errorLog;
- public DeclarationClassification(ErrorLog errorLog) {
- this.errorLog = errorLog;
+ public DeclarationClassification(CompilationContext compilationContext) {
+ this.errorLog = compilationContext.errorLog;
}
public void handle(DeclarationAst declaration) {
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.internal.parsing.declarations.DDocumentationAst;
import org.simantics.scl.compiler.module.ConcreteModule;
import org.simantics.scl.compiler.types.TCon;
value.setDocumentation(doc.documentation);
}
for(String name : typeDocumentation.keySet()) {
- TypeConstructor typeConstructor = module.getTypeConstructor(name);
+ TypeDescriptor typeConstructor = module.getTypeDescriptor(name);
DDocumentationAst doc = typeDocumentation.get(name);
if(typeConstructor != null && doc != null)
typeConstructor.setDocumentation(doc.documentation);
import org.simantics.scl.compiler.constants.generic.MethodRef;
import org.simantics.scl.compiler.constants.generic.OutputFilter;
import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
+import org.simantics.scl.compiler.constants.generic.Pop2OutputFilter;
import org.simantics.scl.compiler.constants.generic.PopOutputFilter;
import org.simantics.scl.compiler.constants.generic.StackItem;
import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem;
public class Elaboration {
// inputs
- ErrorLog errorLog;
- String moduleName;
- ArrayList<ImportDeclaration> importsAst;
- JavaReferenceValidator<Object, Object, Object, Object> javaReferenceValidator;
- ValueRepository valueDefinitionsAst;
- RelationRepository relationDefinitionsAst;
+ private final CompilationContext compilationContext;
+ private final ErrorLog errorLog;
+ private final String moduleName;
+ private final ArrayList<ImportDeclaration> importsAst;
+ final JavaReferenceValidator<Object, Object, Object, Object> javaReferenceValidator;
+ private final ValueRepository valueDefinitionsAst;
+ private final RelationRepository relationDefinitionsAst;
// creates
ConcreteModule module;
Environment importedEnvironment;
- Environment environment;
- JavaNamingPolicy namingPolicy;
ArrayList<SupplementedValueType> supplementedTypeAnnotations = new ArrayList<SupplementedValueType>();
JavaTypeTranslator javaTypeTranslator;
THashMap<String, BranchPoint[]> branchPoints;
@SuppressWarnings("unchecked")
- public Elaboration(ErrorLog errorLog, CompilationTimer timer, EnvironmentFactory localEnvironmentFactory,
+ public Elaboration(CompilationContext compilationContext, CompilationTimer timer, EnvironmentFactory localEnvironmentFactory,
String moduleName, ArrayList<ImportDeclaration> importsAst,
JavaReferenceValidator<?, ?, ?, ?> javaReferenceValidator,
ValueRepository valueDefinitionsAst,
RelationRepository relationDefinitionsAst) {
- this.errorLog = errorLog;
+ this.compilationContext = compilationContext;
+ this.errorLog = compilationContext.errorLog;
this.moduleName = moduleName;
importsAst = processRelativeImports(importsAst);
this.importsAst = importsAst;
this.relationDefinitionsAst = relationDefinitionsAst;
module = new ConcreteModule(moduleName);
+ compilationContext.module = module;
try {
if(timer != null)
timer.suspendTimer();
importsAst.toArray(new ImportDeclaration[importsAst.size()]));
if(timer != null)
timer.continueTimer();
- this.environment = new EnvironmentOfModule(importedEnvironment, module);
+ compilationContext.environment = new EnvironmentOfModule(importedEnvironment, module);
} catch (ImportFailureException e) {
for(ImportFailure failure : e.failures)
errorLog.log(failure.location, failure.toString());
false,
importAst.spec));
localEnvironmentFactory.addBuiltinDependencies(module);
- namingPolicy = new JavaNamingPolicy(moduleName);
+ compilationContext.namingPolicy = new JavaNamingPolicy(moduleName);
}
private ArrayList<ImportDeclaration> processRelativeImports(ArrayList<ImportDeclaration> relativeImports) {
NameExistenceChecks.checkIfTypeExists(errorLog,
dataType.location, importedEnvironment, dataType.name);
- if(module.addTypeConstructor(dataType.name, typeConstructor))
+ if(module.addTypeDescriptor(dataType.name, typeConstructor))
errorLog.log(dataType.location, "Type "+dataType.name+" has already been defined in this module.");
dataType.typeConstructor = typeConstructor;
}
TypeAlias alias = new TypeAlias(Types.con(moduleName, typeAlias.name), typeAlias.parameters.length);
NameExistenceChecks.checkIfTypeExists(errorLog,
typeAlias.location, importedEnvironment, typeAlias.name);
- if(module.addTypeAlias(typeAlias.name, alias)) {
+ if(module.addTypeDescriptor(typeAlias.name, alias)) {
errorLog.log(typeAlias.location, "Type alias "+typeAlias.name+" has already been defined in this module.");
}
}
if(module.addEffectConstructor(effect.name, effectConstructor))
errorLog.log(effect.location, "Type "+effect.name+" has already been defined in this module.");
}
- javaTypeTranslator = new JavaTypeTranslator(environment);
+ javaTypeTranslator = new JavaTypeTranslator(compilationContext.environment);
+ compilationContext.javaTypeTranslator = javaTypeTranslator;
}
private static final int[] EMPTY_INT_ARRAY = new int[0];
if(errorLog.isEmpty()) {
for(DTypeAst typeAlias : orderedTypeAliases) {
- TypeAlias alias = module.getTypeAlias(typeAlias.name);
+ TypeAlias alias = (TypeAlias)module.getTypeDescriptor(typeAlias.name);
TypeTranslationContext context = createTypeTranslationContext();
for(int i=0;i<typeAlias.parameters.length;++i)
context.pushTypeVar(typeAlias.parameters[i]);
boolean trivialDataType = dataTypeAst.constructors.length == 1 &&
dataTypeAst.constructors[0].parameters.length == 1;
if(className == null && !trivialDataType)
- className = namingPolicy.getDataTypeClassName(dataTypeAst.name);
+ className = compilationContext.namingPolicy.getDataTypeClassName(dataTypeAst.name);
StandardTypeConstructor dataType = dataTypeAst.typeConstructor;
for(int i=constructor.parameters.length-1;i>=0;--i)
parameterTypes[i] = context.toType(constructor.parameters[i]);
String javaName = constructors.length == 1 ? className
- : namingPolicy.getConstructorClassName(name);
+ : compilationContext.namingPolicy.getConstructorClassName(name);
String[] fieldNames = null;
for(DAnnotationAst annotation : constructor.annotations)
if(annotation.id.text.equals("@JavaType")) {
TypeClass typeClass = new TypeClass(classAst.location,
classContext,
con,
- namingPolicy.getTypeClassInterfaceName(con),
+ compilationContext.namingPolicy.getTypeClassInterfaceName(con),
parameters,
Fundep.mapFundeps(classAst.parameters, classAst.fundeps));
typeClass.methodNames.add(name.name);
methods.put(name.name,
new TypeClassMethod(typeClass, name.name,
- namingPolicy.getMethodName(name.name),
+ compilationContext.namingPolicy.getMethodName(name.name),
type, Types.getArity(type),
name.location)
);
}
private TypeTranslationContext createTypeTranslationContext() {
- return new TypeTranslationContext(errorLog, environment);
+ return new TypeTranslationContext(compilationContext);
}
public void processDerivingInstances(ArrayList<DDerivingInstanceAst> derivingInstancesAst,
String name = derivingInstance.name.name;
TCon con;
try {
- con = Environments.getTypeClassName(environment, name);
+ con = Environments.getTypeClassName(compilationContext.environment, name);
} catch (AmbiguousNameException e) {
errorLog.log(derivingInstance.name.location, e.getMessage());
continue;
if(deriver == null)
errorLog.log(derivingInstance.location, "Doesn't know how to derive " + name + ".");
else
- deriver.derive(errorLog, environment, instancesAst, derivingInstance);
+ deriver.derive(errorLog, compilationContext.environment, instancesAst, derivingInstance);
}
}
String name = instanceAst.name.name;
TCon typeClassCon;
try {
- typeClassCon = Environments.getTypeClassName(environment, name);
+ typeClassCon = Environments.getTypeClassName(compilationContext.environment, name);
} catch (AmbiguousNameException e) {
errorLog.log(instanceAst.name.location, e.getMessage());
continue;
errorLog.log(instanceAst.name.location, "Couldn't resolve class " + name + ".");
continue;
}
- TypeClass typeClass = environment.getTypeClass(typeClassCon);
+ TypeClass typeClass = compilationContext.environment.getTypeClass(typeClassCon);
pInstanceAst.typeClass = typeClass;
if(instanceAst.types.length != typeClass.parameters.length) {
for(int i=0;i<instanceContext.length;++i)
instanceContext[i] = context.toTFuncApply(instanceAst.context[i]);
- String javaName = namingPolicy.getInstanceClassName(instance);
+ String javaName = compilationContext.namingPolicy.getInstanceClassName(instance);
String instancePrefix = instance.toName() + "$";
ValueRepository valueDefs = pInstanceAst.valueDefs;
Expression expression = new EGetConstraint(instance.location, type);
value.setExpression(expression);
value.setType(Types.forAll(instance.generatorParameters, Types.constrained(instance.context, type)));
+ value.getProperties().add(new InlineProperty(instance.context.length, 0xffffffff));
//TypeUnparsingContext tuc = new TypeUnparsingContext();
// TODO error handling
instance.superExpressions[i] = value;
effect.collectConcreteEffects(concreteEffects);
for(TCon eff : concreteEffects) {
- EffectConstructor effC = environment.getEffectConstructor(eff);
+ EffectConstructor effC = compilationContext.environment.getEffectConstructor(eff);
for(ThreadLocalVariable var : effC.getThreadLocalVariables()) {
for(int i=0;i<unresolvedItems.size();++i) {
int id = unresolvedItems.get(i);
javaTypeTranslator.toTypeDesc(returnType);
if(!javaReferenceValidator.isAssignableFrom(expectedReturnType,
providedReturnType)) {
- if(expectedReturnType.equals(TypeDesc.VOID))
- filter = PopOutputFilter.INSTANCE;
+ if(expectedReturnType.equals(TypeDesc.VOID)) {
+ if(providedReturnType.equals(TypeDesc.DOUBLE) || providedReturnType.equals(TypeDesc.LONG))
+ filter = Pop2OutputFilter.INSTANCE;
+ else
+ filter = PopOutputFilter.INSTANCE;
+ }
else if(expectedReturnType.equals(Constants.LIST)
&& providedReturnType.equals(Constants.COLLECTION))
filter = ConvertToListFilter.INSTANCE;
if(ruleAstMap.containsKey(extendsName))
extendsRule = processRule(extendsName);
else {
- extendsRule = Environments.getRule(environment, extendsName);
+ extendsRule = Environments.getRule(compilationContext.environment, extendsName);
if(extendsRule == null)
errorLog.log(ruleAst.location,
"Couldn't resolve rule name " + extendsName + ".");
}
private TranslationContext createTranslationContext() {
- return new TranslationContext(errorLog, environment, null);
+ return new TranslationContext(compilationContext, null);
}
private void handleAnnotation(SCLValue value, ArrayList<DValueAst> defs, DAnnotationAst annotation) {
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
return base.getEntityType(name);
}
@Override
- public TypeConstructor getTypeConstructor(TCon type) {
+ public TypeDescriptor getTypeDescriptor(TCon type) {
if(type.module.equals(module.getName()))
- return module.getTypeConstructor(type.name);
+ return module.getTypeDescriptor(type.name);
else
- return base.getTypeConstructor(type);
+ return base.getTypeDescriptor(type);
}
@Override
public EffectConstructor getEffectConstructor(TCon type) {
return base.getEffectConstructor(type);
}
@Override
- public TypeAlias getTypeAlias(TCon type) {
- if(type.module.equals(module.getName()))
- return module.getTypeAlias(type.name);
- else
- return base.getTypeAlias(type);
- }
- @Override
public TypeClass getTypeClass(TCon type) {
if(type.module.equals(module.getName()))
return module.getTypeClass(type.name);
package org.simantics.scl.compiler.compilation;\r
\r
import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;\r
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;\r
import org.simantics.scl.compiler.environment.AmbiguousNameException;\r
import org.simantics.scl.compiler.environment.Environment;\r
import org.simantics.scl.compiler.errors.ErrorLog;\r
public static void checkIfTypeExists(ErrorLog errorLog, long location,\r
Environment environment, String name) {\r
try {\r
- TypeConstructor value = environment.getLocalNamespace().getTypeConstructor(name);\r
- if(value != null)\r
+ TypeDescriptor tdesc = environment.getLocalNamespace().getTypeDescriptor(name);\r
+ if(tdesc != null)\r
errorLog.log(location,\r
"Type " + name + " is already defined in the module " + \r
- value.name.module + \r
+ tdesc.name.module + \r
" that is imported to the default namespace.");\r
} catch(AmbiguousNameException e) {\r
errorLog.log(location,\r
import java.util.function.Consumer;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
throw new AmbiguousNameException(Arrays.asList(value.getName().module, value2.getName().module), value.getName().name);
}
else {
- if(value != null)
- return value;
- return base.getValue(name);
+ if(value != null)
+ return value;
+ return base.getValue(name);
}
}
}
@Override
- public TypeConstructor getTypeConstructor(String name)
+ public TypeDescriptor getTypeDescriptor(String name)
throws AmbiguousNameException {
- TypeConstructor typeConstructor = module.getTypeConstructor(name);
- if(typeConstructor != null)
- return typeConstructor;
- return base.getTypeConstructor(name);
+ TypeDescriptor typeDescriptor = module.getTypeDescriptor(name);
+ if(typeDescriptor != null)
+ return typeDescriptor;
+ return base.getTypeDescriptor(name);
}
@Override
return typeClass;
return base.getTypeClass(name);
}
-
- @Override
- public TypeAlias getTypeAlias(String name) throws AmbiguousNameException {
- TypeAlias typeAlias = module.getTypeAlias(name);
- if(typeAlias != null)
- return typeAlias;
- return base.getTypeAlias(name);
- }
@Override
public MappingRelation getMappingRelation(String name)
import org.simantics.scl.compiler.top.StandardModuleInitializer;
public class SCLCompiler {
- ErrorLog errorLog = new ErrorLog();
- DeclarationClassification declarations = new DeclarationClassification(errorLog);
+ CompilationContext compilationContext = new CompilationContext();
+ DeclarationClassification declarations = new DeclarationClassification(compilationContext);
// publishable results
Map<String, byte[]> classes;
for(DeclarationAst declaration : (ArrayList<DeclarationAst>)parser.parseModule())
declarations.handle(declaration);
} catch(SCLSyntaxErrorException e) {
- errorLog.log(e.location, e.getMessage());
+ compilationContext.errorLog.log(e.location, e.getMessage());
} catch(Exception e) {
- errorLog.log(e);
+ compilationContext.errorLog.log(e);
} finally {
try {
sourceReader.close();
if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Parsing");
}
+ private boolean hasErrors() {
+ return !compilationContext.errorLog.isEmpty();
+ }
+
public void compile(
EnvironmentFactory localEnvironmentFactory,
String moduleName,
JavaReferenceValidator<?, ?, ?, ?> javaReferenceValidator) {
try {
- if(!errorLog.isEmpty()) return;
- Elaboration elaboration = new Elaboration(errorLog,
+ if(hasErrors()) return;
+ Elaboration elaboration = new Elaboration(compilationContext,
timer,
localEnvironmentFactory,
moduleName,
if(options.computeCoverage)
elaboration.addCoverageBranchPoints();
// Elaboration
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.addTypesToEnvironment(
declarations.dataTypesAst,
declarations.typeAliasesAst,
declarations.effectsAst);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.processTypeAliases(declarations.typeAliasesAst);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.processDataTypes(declarations.dataTypesAst);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.processTypeClasses(declarations.typeClassesAst);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.processDerivingInstances(declarations.derivingInstancesAst, declarations.instancesAst);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.processInstances(declarations.instancesAst);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.processJavaMethods(declarations.javaMethodDeclarations);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
elaboration.addDataTypesToEnvironment();
elaboration.addTypeClassesToEnvironment();
elaboration.preprocessValueDefinitions(declarations.typeAnnotationsAst);
if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Elaboration");
// Type checking
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
//new TypeChecking(errorLog, elaboration.environment, elaboration.module).typeCheck();
- new TypeChecking(errorLog, elaboration.environment, elaboration.module).typeCheck();
+ new TypeChecking(compilationContext, elaboration.module).typeCheck();
if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Type checking");
this.declarations = null;
// Code generation
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
CodeGeneration codeGeneration = new CodeGeneration(
- errorLog,
- elaboration.environment,
- elaboration.namingPolicy,
- elaboration.javaTypeTranslator,
+ compilationContext,
elaboration.javaReferenceValidator,
elaboration.module);
codeGeneration.simplifyValues();
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
codeGeneration.convertToSSA();
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
codeGeneration.optimizeSSA();
if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("SSA conversion and optimization");
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
codeGeneration.generateCode();
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
codeGeneration.generateDataTypes(elaboration.dataTypes);
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
codeGeneration.generateTypeClasses();
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
codeGeneration.generateTypeClassInstances();
- if(!errorLog.isEmpty()) return;
+ if(hasErrors()) return;
classes = codeGeneration.classes;
module = codeGeneration.module;
moduleInitializer = StandardModuleInitializer.create(
- codeGeneration.namingPolicy.getModuleClassName(),
+ compilationContext.namingPolicy.getModuleClassName(),
codeGeneration.externalConstants);
module.setClasses(classes);
reportTiming(moduleName);
}
} catch(Exception e) {
- errorLog.log(e);
+ compilationContext.errorLog.log(e);
}
}
public ErrorLog getErrorLog() {
- return errorLog;
+ return compilationContext.errorLog;
}
public Map<String, byte[]> getClasses() {
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
import org.simantics.scl.compiler.environment.Environment;
-import org.simantics.scl.compiler.errors.ErrorLog;
import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint;
import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintEnvironment;
import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintSolver;
import gnu.trove.set.hash.TIntHashSet;
public class TypeChecking {
- final ErrorLog errorLog;
+ final CompilationContext compilationContext;
final Environment environment;
final ConcreteModule module;
ConstraintEnvironment ce;
TypeCheckingScheduler scheduler;
- public TypeChecking(ErrorLog errorLog, Environment environment,
- ConcreteModule module) {
- this.errorLog = errorLog;
- this.environment = environment;
+ public TypeChecking(CompilationContext compilationContext, ConcreteModule module) {
+ this.compilationContext = compilationContext;
+ this.environment = compilationContext.environment;
this.module = module;
}
expression = expression.checkType(context, value.getType());
context.popEffectUpperBound();
for(EAmbiguous overloaded : context.overloadedExpressions)
- overloaded.assertResolved(errorLog);
+ overloaded.assertResolved(compilationContext.errorLog);
value.setExpression(expression);
ArrayList<EVariable> constraintDemand = context.getConstraintDemand();
for(Constraint c : red.unsolvedConstraints)
if(c.constraint.isGround())
- errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">.");
+ compilationContext.errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">.");
ArrayList<Variable> fe = new ArrayList<Variable>(red.unsolvedConstraints.size());
for(Constraint c : red.unsolvedConstraints)
ArrayList<TPred> givenConstraints = new ArrayList<TPred>();
type = Types.removePred(type, givenConstraints);
- TypingContext context = new TypingContext(errorLog, environment);
+ TypingContext context = new TypingContext(compilationContext);
context.pushEffectUpperBound(expression.location, Types.PROC);
expression = expression.checkType(context, type);
context.popEffectUpperBound();
for(EAmbiguous overloaded : context.overloadedExpressions)
- overloaded.assertResolved(errorLog);
+ overloaded.assertResolved(compilationContext.errorLog);
expression.getType().addPolarity(Polarity.POSITIVE);
context.solveSubsumptions(expression.getLocation());
ArrayList<EVariable> demands = context.getConstraintDemand();
ConstraintSolver.solve(ce, givenConstraints, demands, true);
givenConstraints.clear();
for(Constraint c : red.unsolvedConstraints) {
- errorLog.log(c.getDemandLocation(),
+ compilationContext.errorLog.log(c.getDemandLocation(),
"Constraint <"+c.constraint+"> is not given and cannot be derived.");
}
- if(errorLog.isEmpty()) { // To prevent exceptions
+ if(compilationContext.errorLog.isEmpty()) { // To prevent exceptions
expression = ExpressionAugmentation.augmentSolved(
red.solvedConstraints,
expression);
}
}
else {
- if(errorLog.isEmpty()) // To prevent exceptions
+ if(compilationContext.errorLog.isEmpty()) // To prevent exceptions
expression = expression.decomposeMatching();
}
expression = expression.closure(vars.toArray(new TVar[vars.size()]));
value.setExpression(expression);
} catch(Exception e) {
- errorLog.log(expression.location, e);
+ compilationContext.errorLog.log(expression.location, e);
}
}
});
public void typeCheck() {
ce = new ConstraintEnvironment(environment);
- scheduler = new TypeCheckingScheduler(errorLog, environment);
+ scheduler = new TypeCheckingScheduler(compilationContext);
typeCheckValues();
typeCheckRelations();
for(MappingRelation mappingRelation : module.getMappingRelations())
for(Type parameterType : mappingRelation.parameterTypes)
if(!parameterType.isGround()) {
- errorLog.log(mappingRelation.location, "Parameter types of the mapping relation are not completely determined.");
+ compilationContext.errorLog.log(mappingRelation.location, "Parameter types of the mapping relation are not completely determined.");
break;
}
}
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.environment.Environment;
-import org.simantics.scl.compiler.errors.ErrorLog;
import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint;
import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
import org.simantics.scl.compiler.types.TPred;
* @author Hannu Niemistö
*/
public class TypeCheckingScheduler {
- final ErrorLog errorLog;
- final Environment environment;
+ private final CompilationContext compilationContext;
- ArrayList<TypeInferableDefinition> definitions = new ArrayList<TypeInferableDefinition>();
- ArrayList<Runnable> postTypeCheckingRunnables = new ArrayList<Runnable>();
+ private final ArrayList<TypeInferableDefinition> definitions = new ArrayList<TypeInferableDefinition>();
+ private final ArrayList<Runnable> postTypeCheckingRunnables = new ArrayList<Runnable>();
- public TypeCheckingScheduler(ErrorLog errorLog, Environment environment) {
- this.errorLog = errorLog;
- this.environment = environment;
+ public TypeCheckingScheduler(CompilationContext compilationContext) {
+ this.compilationContext = compilationContext;
}
public void addTypeInferableDefinition(TypeInferableDefinition definition) {
}
private void typeCheck(int[] component) {
- TypingContext context = new TypingContext(errorLog, environment);
+ TypingContext context = new TypingContext(compilationContext);
context.recursiveValues = new THashSet<SCLValue>();
for(int c : component)
constraintMap.put(cons.constraint, cons);
}
Constraint cons = constraintMap.get(constraint);
- errorLog.log(cons.getDemandLocation(),
+ compilationContext.errorLog.log(cons.getDemandLocation(),
"Constrain " + constraint +
" contains free variables not mentioned in the type of the value.");
}
import org.simantics.scl.compiler.types.Types;
public class BooleanConstant extends Constant {
+ public static final BooleanConstant TRUE = new BooleanConstant(true);
+ public static final BooleanConstant FALSE = new BooleanConstant(false);
+
boolean value;
public BooleanConstant(boolean value) {
--- /dev/null
+package org.simantics.scl.compiler.constants;\r
+\r
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+\r
+public interface ComparisonFunction {\r
+\r
+ void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_);\r
+\r
+}\r
import org.objectweb.asm.Label;
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
import org.simantics.scl.compiler.internal.codegen.references.Val;
import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
-public class JavaComparisonOperation extends FunctionValue {
+public class JavaComparisonOperation extends FunctionValue implements ComparisonFunction {
+ public static final JavaComparisonOperation IEQUAL = new JavaComparisonOperation("==", Types.INTEGER);
+ public static final JavaComparisonOperation INOT_EQUAL = new JavaComparisonOperation("!=", Types.INTEGER);
+ public static final JavaComparisonOperation ILESS = new JavaComparisonOperation("<", Types.INTEGER);
+ public static final JavaComparisonOperation ILESS_OR_EQUAL = new JavaComparisonOperation("<=", Types.INTEGER);
+ public static final JavaComparisonOperation IGREATER = new JavaComparisonOperation(">", Types.INTEGER);
+ public static final JavaComparisonOperation IGREATER_OR_EQUAL = new JavaComparisonOperation(">=", Types.INTEGER);
String op;
JavaTypeTranslator tt = mb.getJavaTypeTranslator();
Label thenBranch = mb.createLabel();
Label joinPoint = mb.createLabel();
+ Type type = parameterTypes[0];
mb.push(parameters[0], type);
mb.push(parameters[1], type);
- mb.ifComparisonBranch(thenBranch, op, tt.toTypeDesc(parameterTypes[0]));
+ mb.ifComparisonBranch(thenBranch, op, tt.toTypeDesc(type));
mb.loadConstant(false);
mb.branch(joinPoint);
return "(" + op + ")";
}
+ @Override
+ public void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_) {
+ JavaTypeTranslator tt = mb.getJavaTypeTranslator();
+ Type type = parameterTypes[0];
+ mb.push(parameters[0], type);
+ mb.push(parameters[1], type);
+ mb.ifComparisonBranch(mb.getLabel(then_), op, tt.toTypeDesc(type));
+ mb.jump(else_);
+ mb.ensureExists(then_);
+ }
+
}
package org.simantics.scl.compiler.constants;
import org.objectweb.asm.Label;
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
import org.simantics.scl.compiler.internal.codegen.references.Val;
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;
-public class JavaComparisonToZeroOperation extends FunctionValue {
+public class JavaComparisonToZeroOperation extends FunctionValue implements ComparisonFunction {
+ public static final JavaComparisonToZeroOperation IEQUAL = new JavaComparisonToZeroOperation("==");
+ public static final JavaComparisonToZeroOperation INOT_EQUAL = new JavaComparisonToZeroOperation("!=");
+ public static final JavaComparisonToZeroOperation ILESS = new JavaComparisonToZeroOperation("<");
+ public static final JavaComparisonToZeroOperation ILESS_OR_EQUAL = new JavaComparisonToZeroOperation("<=");
+ public static final JavaComparisonToZeroOperation IGREATER = new JavaComparisonToZeroOperation(">");
+ public static final JavaComparisonToZeroOperation IGREATER_OR_EQUAL = new JavaComparisonToZeroOperation(">=");
String op;
return getReturnType();
}
+ @Override
+ public void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_) {
+ mb.push(parameters[0], Types.INTEGER);
+ mb.ifZeroComparisonBranch(mb.getLabel(then_), op);
+ mb.jump(else_);
+ mb.ensureExists(then_);
+ }
+
@Override
public String toString() {
return op;
if(isPrivate && !hasMoreThanOneOccurences())\r
context.removeConstant(name);\r
else\r
- def = def.copy();\r
+ def = (SSAFunction)def.copy();\r
\r
if(parameters.length >= def.getArity()) {\r
if(parameters.length != def.getArity())\r
definition.simplify(context);\r
if(inlineArity == Integer.MAX_VALUE && definition.isSimpleEnoughForInline()) {\r
inlineArity = definition.getArity();\r
- inlinableDefinition = definition.copy();\r
+ inlinableDefinition = (SSAFunction)definition.copy();\r
context.markModified("mark inlineable " + name);\r
// FIXME this will make self calling function inlinable that may crash the compiler\r
}\r
\r
public void saveInlinableDefinition() {\r
if(inlineArity < Integer.MAX_VALUE)\r
- inlinableDefinition = definition.copy();\r
+ inlinableDefinition = (SSAFunction)definition.copy();\r
}\r
}\r
package org.simantics.scl.compiler.constants;\r
\r
+import java.util.Arrays;\r
+\r
import org.cojen.classfile.TypeDesc;\r
+import org.objectweb.asm.Label;\r
+import org.objectweb.asm.Opcodes;\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
import org.simantics.scl.compiler.internal.codegen.references.Val;\r
import org.simantics.scl.compiler.internal.codegen.utils.Constants;\r
+import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;\r
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
public StringInterpolation(String[] textParts) {\r
this(stringTypeArray(textParts.length-1), textParts);\r
}\r
+ \r
+ @Override\r
+ public String toString() {\r
+ StringBuilder b = new StringBuilder();\r
+ b.append('"');\r
+ boolean first = true;\r
+ for(String textPart : textParts) {\r
+ if(first)\r
+ first = false;\r
+ else\r
+ b.append("\\(.)");\r
+ b.append(textPart);\r
+ }\r
+ b.append('"');\r
+ return b.toString();\r
+ }\r
\r
private static Type[] stringTypeArray(int length) {\r
Type[] result = new Type[length];\r
\r
@Override\r
public Type applyExact(MethodBuilder mb, Val[] parameters) {\r
+ if(textParts.length==1) {\r
+ mb.loadConstant(textParts[0]);\r
+ }\r
+ else if(textParts.length==2) {\r
+ if(parameters[0].getType() == Types.STRING) {\r
+ // Optimized special cases "asd" + x, x + "asd"\r
+ if(textParts[0].isEmpty()) {\r
+ mb.push(parameters[0], Types.STRING);\r
+ if(!textParts[1].isEmpty()) {\r
+ mb.loadConstant(textParts[1]);\r
+ mb.invokeVirtual("java/lang/String", "concat", TypeDesc.STRING, new TypeDesc[] {TypeDesc.STRING});\r
+ }\r
+ return Types.STRING;\r
+ }\r
+ else if(textParts[1].isEmpty()) {\r
+ mb.loadConstant(textParts[0]);\r
+ mb.push(parameters[0], Types.STRING);\r
+ mb.invokeVirtual("java/lang/String", "concat", TypeDesc.STRING, new TypeDesc[] {TypeDesc.STRING});\r
+ return Types.STRING;\r
+ }\r
+ }\r
+ }\r
+ else if(textParts.length==3) {\r
+ if(parameters[0].getType() == Types.STRING && parameters[1].getType() == Types.STRING\r
+ && textParts[0].isEmpty() && textParts[1].isEmpty() && textParts[2].isEmpty()) {\r
+ mb.push(parameters[0], Types.STRING);\r
+ mb.push(parameters[1], Types.STRING);\r
+ mb.invokeVirtual("java/lang/String", "concat", TypeDesc.STRING, new TypeDesc[] {TypeDesc.STRING});\r
+ return Types.STRING;\r
+ }\r
+ }\r
mb.newObject(STRING_BUILDER);\r
mb.dup();\r
mb.invokeConstructor(STRING_BUILDER, Constants.EMPTY_TYPEDESC_ARRAY);\r
\r
return Types.STRING;\r
}\r
+ \r
+ @Override\r
+ public int hashCode() {\r
+ return Arrays.hashCode(textParts) ^ Arrays.hashCode(parameterTypes);\r
+ }\r
\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if(this == obj)\r
+ return true;\r
+ if(obj == null || obj.getClass() != getClass())\r
+ return false;\r
+ StringInterpolation other = (StringInterpolation)obj;\r
+ return Arrays.equals(textParts, other.textParts) && Arrays.equals(parameterTypes, other.parameterTypes);\r
+ }\r
+ \r
+ @Override\r
+ public int constructorTag() {\r
+ return textParts.length == 2 && parameterTypes[0] == Types.STRING ? 0 : -1;\r
+ }\r
+ \r
+ @Override\r
+ public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) {\r
+ if(textParts.length != 2)\r
+ throw new InternalCompilerError("String interpolation with more than one open string parts cannot be used as a pattern.");\r
+ mb.push(parameter, Types.STRING);\r
+ LocalVariable temp = mb.createLocalVariable(null, TypeDesc.STRING);\r
+ mb.storeLocal(temp);\r
+ if(!textParts[0].isEmpty()) {\r
+ mb.loadLocal(temp);\r
+ mb.loadConstant(textParts[0]);\r
+ mb.invokeVirtual("java/lang/String", "startsWith", TypeDesc.BOOLEAN, new TypeDesc[] {TypeDesc.STRING});\r
+ mb.ifZeroComparisonBranch(failure, "==");\r
+ }\r
+ if(!textParts[1].isEmpty()) {\r
+ mb.loadLocal(temp);\r
+ mb.loadConstant(textParts[1]);\r
+ mb.invokeVirtual("java/lang/String", "endsWith", TypeDesc.BOOLEAN, new TypeDesc[] {TypeDesc.STRING});\r
+ mb.ifZeroComparisonBranch(failure, "==");\r
+ }\r
+ mb.loadLocal(temp);\r
+ mb.loadConstant(textParts[0].length());\r
+ mb.loadLocal(temp);\r
+ mb.invokeVirtual("java/lang/String", "length", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);\r
+ mb.loadConstant(textParts[1].length());\r
+ mb.math(Opcodes.ISUB);\r
+ mb.invokeVirtual("java/lang/String", "substring", TypeDesc.STRING, new TypeDesc[] {TypeDesc.INT, TypeDesc.INT});\r
+ mb.storeLocal(temp);\r
+ mb.jump(success, new LocalVariableConstant(Types.STRING, temp));\r
+ }\r
+ \r
}\r
+++ /dev/null
-package org.simantics.scl.compiler.constants;\r
-\r
-import org.simantics.scl.compiler.internal.codegen.references.Val;\r
-import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
-import org.simantics.scl.compiler.types.TVar;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\r
-\r
-public class UnsafeCoerce extends FunctionValue { \r
- private static TVar A = Types.var(Kinds.STAR);\r
- private static TVar B = Types.var(Kinds.STAR);\r
- public static final UnsafeCoerce INSTANCE = new UnsafeCoerce();\r
- \r
- private UnsafeCoerce() {\r
- super(new TVar[] {A, B}, Types.NO_EFFECTS, B, A);\r
- }\r
- \r
- @Override\r
- public Type applyExact(MethodBuilder mb, Val[] parameters) {\r
- mb.pushBoxed(parameters[0]);\r
- return getReturnType();\r
- }\r
-}\r
Type[] parameterTypes, StackItem[] stackItems, MethodRef methodRef,\r
OutputFilter filter) {\r
super(typeParameters, effect, returnType, parameterTypes);\r
+ if(stackItems == null) {\r
+ stackItems = new StackItem[parameterTypes.length];\r
+ for(int i=0;i<parameterTypes.length;++i)\r
+ stackItems[i] = new ParameterStackItem(i, parameterTypes[i]);\r
+ }\r
this.stackItems = stackItems;\r
this.methodRef = methodRef;\r
this.filter = filter;\r
--- /dev/null
+package org.simantics.scl.compiler.constants.generic;\r
+\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+\r
+public enum Pop2OutputFilter implements OutputFilter {\r
+ INSTANCE;\r
+\r
+ @Override\r
+ public void filter(MethodBuilder mb) {\r
+ mb.pop2();\r
+ }\r
+}\r
public void filter(MethodBuilder mb) {
mb.pop();
}
-
}
--- /dev/null
+package org.simantics.scl.compiler.constants.singletons;\r
+\r
+import org.objectweb.asm.Opcodes;\r
+import org.simantics.scl.compiler.constants.FunctionValue;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class IncreaseByOne extends FunctionValue {\r
+\r
+ public static final IncreaseByOne INSTANCE = new IncreaseByOne();\r
+ \r
+ private IncreaseByOne() {\r
+ super(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, Types.INTEGER);\r
+ }\r
+ \r
+ @Override\r
+ public Type applyExact(MethodBuilder mb, Val[] parameters) {\r
+ parameters[0].push(mb);\r
+ mb.loadConstant(1);\r
+ mb.math(Opcodes.IADD);\r
+ return Types.INTEGER;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "increaseByOne";\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.constants.singletons;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.simantics.scl.compiler.constants.FunctionValue;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.kinds.Kinds;\r
+\r
+public class ListElement extends FunctionValue { \r
+ private static TVar A = Types.var(Kinds.STAR);\r
+ public static final ListElement INSTANCE = new ListElement();\r
+ \r
+ private ListElement() {\r
+ super(new TVar[] {A}, Types.NO_EFFECTS, A, Types.list(A), Types.INTEGER);\r
+ }\r
+ \r
+ @Override\r
+ public Type applyExact(MethodBuilder mb, Val[] parameters) {\r
+ parameters[0].push(mb);\r
+ parameters[1].push(mb);\r
+ mb.invokeInterface("java/util/List", "get", TypeDesc.OBJECT, new TypeDesc[] {TypeDesc.INT});\r
+ return getReturnType();\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "get";\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.constants.singletons;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.simantics.scl.compiler.constants.FunctionValue;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.utils.Constants;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.kinds.Kinds;\r
+\r
+public class ListLength extends FunctionValue { \r
+ private static TVar A = Types.var(Kinds.STAR);\r
+ public static final ListLength INSTANCE = new ListLength();\r
+ \r
+ private ListLength() {\r
+ super(new TVar[] {A}, Types.NO_EFFECTS, Types.INTEGER, Types.list(A));\r
+ }\r
+ \r
+ @Override\r
+ public Type applyExact(MethodBuilder mb, Val[] parameters) {\r
+ parameters[0].push(mb);\r
+ mb.invokeInterface("java/util/List", "size", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);\r
+ return getReturnType();\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "length";\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.constants.singletons;\r
+\r
+import org.objectweb.asm.Label;\r
+import org.simantics.scl.compiler.constants.ComparisonFunction;\r
+import org.simantics.scl.compiler.constants.FunctionValue;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.kinds.Kinds;\r
+\r
+public class NullCheck extends FunctionValue implements ComparisonFunction {\r
+ private static final TVar A = Types.var(Kinds.STAR);\r
+ public static final NullCheck INSTANCE = \r
+ new NullCheck();\r
+ \r
+ private NullCheck() {\r
+ super(new TVar[] {A}, Types.NO_EFFECTS, Types.BOOLEAN, A);\r
+ }\r
+ \r
+ @Override\r
+ public Type applyExact(MethodBuilder mb, Val[] parameters) {\r
+ parameters[0].push(mb);\r
+ Label join = mb.createLabel();\r
+ Label isNull = mb.createLabel();\r
+ mb.ifNullBranch(isNull, true);\r
+ mb.loadConstant(false);\r
+ mb.branch(join);\r
+ mb.setLocation(isNull);\r
+ mb.loadConstant(true);\r
+ mb.setLocation(join);\r
+ return getReturnType();\r
+ }\r
+ \r
+ @Override\r
+ public void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_) {\r
+ parameters[0].push(mb);\r
+ mb.ifNullBranch(mb.getLabel(then_), true);\r
+ mb.jump(else_);\r
+ mb.ensureExists(then_);\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "nullCheck";\r
+ }\r
+}\r
mb.pushBoxed(parameters[0]);\r
return getReturnType();\r
}\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "unsafeCoerce";\r
+ }\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.ExternalCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;\r
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.parsing.Symbol;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.kinds.Kinds;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class CHRLiteral extends Symbol {\r
+ \r
+ public CHRRelation relation;\r
+ public Type[] typeParameters;\r
+ public Expression[] parameters;\r
+ public boolean killAfterMatch;\r
+ public boolean negated;\r
+ public boolean passive = true;\r
+ \r
+ public CHRLiteral(long location, CHRRelation relation, Expression[] parameters, boolean remove, boolean negated) {\r
+ this.location = location;\r
+ this.relation = relation;\r
+ this.parameters = parameters;\r
+ this.killAfterMatch = remove;\r
+ this.negated = negated;\r
+ }\r
+\r
+ public void resolve(TranslationContext context) {\r
+ if(relation instanceof UnresolvedCHRRelation) {\r
+ UnresolvedCHRRelation unresolved = (UnresolvedCHRRelation)relation;\r
+ CHRConstraint constraint = context.resolveCHRConstraint(unresolved.name);\r
+ if(constraint != null) {\r
+ relation = constraint;\r
+ passive = false;\r
+ }\r
+ else {\r
+ SCLRelation sclRelation = context.resolveRelation(unresolved.location, unresolved.name);\r
+ if(sclRelation != null)\r
+ relation = new ExternalCHRRelation(sclRelation);\r
+ else {\r
+ Type[] parameterTypes = new Type[parameters.length];\r
+ for(int i=0;i<parameterTypes.length;++i)\r
+ parameterTypes[i] = Types.metaVar(Kinds.STAR);\r
+ constraint = new CHRConstraint(location, unresolved.name, parameterTypes);\r
+ constraint.implicitlyDeclared = true;\r
+ context.newCHRConstraint(constraint.name, constraint);\r
+ relation = constraint;\r
+ passive = false;\r
+ //context.getErrorLog().log(unresolved.location, "Couldn't resolve constraint " + unresolved.name + ".");\r
+ }\r
+ }\r
+ }\r
+ for(int i=0;i<parameters.length;++i)\r
+ parameters[i] = parameters[i].resolve(context);\r
+ }\r
+\r
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
+ for(Expression parameter : parameters)\r
+ parameter.collectRefs(allRefs, refs);\r
+ }\r
+\r
+ public void checkType(TypingContext context) {\r
+ if(relation == SpecialCHRRelation.EXECUTE) {\r
+ if(parameters.length != 1)\r
+ throw new InternalCompilerError("Wrong number of parameters for EXECUTE constraint.");\r
+ parameters[0] = parameters[0].checkIgnoredType(context);\r
+ }\r
+ else {\r
+ TVar[] typeVariables = relation.getTypeVariables();\r
+ typeParameters = typeVariables.length == 0 ? Type.EMPTY_ARRAY : new Type[typeVariables.length];\r
+ for(int i=0;i<typeVariables.length;++i)\r
+ typeParameters[i] = Types.metaVar(typeVariables[i].getKind());\r
+ Type[] parameterTypes = Types.replace(relation.getParameterTypes(), typeVariables, typeParameters);\r
+ if(parameterTypes.length != parameters.length)\r
+ context.getErrorLog().log(location, "Constraint is applied with wrong number of parameters");\r
+ else\r
+ for(int i=0;i<parameters.length;++i)\r
+ parameters[i] = parameters[i].checkType(context, parameterTypes[i]);\r
+ }\r
+ }\r
+\r
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
+ for(Expression parameter : parameters)\r
+ parameter.collectVars(allVars, vars);\r
+ }\r
+\r
+ public void forVariables(VariableProcedure procedure) {\r
+ for(Expression parameter : parameters)\r
+ parameter.forVariables(procedure);\r
+ }\r
+\r
+ public void collectFreeVariables(THashSet<Variable> vars) {\r
+ for(Expression parameter : parameters)\r
+ parameter.collectFreeVariables(vars);\r
+ }\r
+\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ this.location = loc;\r
+ for(Expression parameter : parameters)\r
+ parameter.setLocationDeep(loc);\r
+ }\r
+ }\r
+ \r
+ public void simplify(SimplificationContext context) {\r
+ for(int i=0;i<parameters.length;++i)\r
+ parameters[i] = parameters[i].simplify(context);\r
+ }\r
+ \r
+ public String toString() {\r
+ StringBuilder b = new StringBuilder();\r
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
+ visitor.visit(this);\r
+ return b.toString();\r
+ }\r
+\r
+ public void collectQueryEffects(THashSet<Type> effects) {\r
+ }\r
+\r
+ public void collectEnforceEffects(THashSet<Type> effects) {\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PostCommitOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PreCommitOp;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;\r
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.parsing.Symbol;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class CHRQuery extends Symbol {\r
+ public CHRLiteral[] literals;\r
+\r
+ public CHRQuery(CHRLiteral[] literals) {\r
+ this.literals = literals;\r
+ }\r
+\r
+ public void resolve(TranslationContext context) {\r
+ for(CHRLiteral literal : literals)\r
+ literal.resolve(context);\r
+ }\r
+\r
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
+ for(CHRLiteral literal : literals)\r
+ literal.collectRefs(allRefs, refs);\r
+ }\r
+\r
+ public void checkType(TypingContext context) {\r
+ for(CHRLiteral literal : literals)\r
+ literal.checkType(context);\r
+ }\r
+ \r
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
+ for(CHRLiteral literal : literals)\r
+ literal.collectVars(allVars, vars);\r
+ }\r
+\r
+ public void forVariables(VariableProcedure procedure) {\r
+ for(CHRLiteral literal : literals)\r
+ literal.forVariables(procedure);\r
+ }\r
+\r
+ public void collectFreeVariables(THashSet<Variable> vars) {\r
+ for(CHRLiteral literal : literals)\r
+ literal.collectFreeVariables(vars);\r
+ }\r
+\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ this.location = loc;\r
+ for(CHRLiteral literal : literals)\r
+ literal.setLocationDeep(loc);\r
+ }\r
+ }\r
+ \r
+ public void createQueryPlan(QueryPlanningContext context, Expression inputFact, int activeLiteralId) {\r
+ for(int i=0;i<literals.length;++i) {\r
+ CHRLiteral literal = literals[i];\r
+ if(i == activeLiteralId)\r
+ context.activate(literal, inputFact, i);\r
+ else\r
+ context.add(literal, i);\r
+ }\r
+ context.createQueryPlan();\r
+ }\r
+ \r
+ public void simplify(SimplificationContext context) {\r
+ for(CHRLiteral literal : literals)\r
+ literal.simplify(context);\r
+ }\r
+\r
+ public void createEnforcePlan(QueryPlanningContext context, int priority) {\r
+ context.addPlanOp(new PreCommitOp(location));\r
+ for(CHRLiteral literal : literals)\r
+ context.claim(context, literal);\r
+ context.addPlanOp(new PostCommitOp(location, priority));\r
+ }\r
+ \r
+ public String toString() {\r
+ StringBuilder b = new StringBuilder();\r
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
+ visitor.visit(this);\r
+ return b.toString();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr;\r
+\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.kinds.Kinds;\r
+\r
+public interface CHRRelation {\r
+ public static final TVar A = Types.var(Kinds.STAR);\r
+ \r
+ TVar[] getTypeVariables();\r
+ Type[] getParameterTypes();\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;\r
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.parsing.Symbol;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.kinds.Kinds;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class CHRRule extends Symbol {\r
+ public int priority;\r
+ public CHRQuery head;\r
+ public CHRQuery body;\r
+ public Variable[] existentialVariables;\r
+ \r
+ // Analysis\r
+ public int firstPriorityExecuted;\r
+ public int lastPriorityExecuted;\r
+ \r
+ public CHRRule(long location, CHRQuery head, CHRQuery body, Variable[] existentialVariables) {\r
+ this.location = location;\r
+ this.head = head;\r
+ this.body = body;\r
+ this.existentialVariables = existentialVariables;\r
+ }\r
+\r
+ public void resolve(TranslationContext context) {\r
+ context.pushExistentialFrame();\r
+ head.resolve(context);\r
+ body.resolve(context);\r
+ existentialVariables = context.popExistentialFrame();\r
+ }\r
+\r
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
+ head.collectRefs(allRefs, refs);\r
+ body.collectRefs(allRefs, refs);\r
+ }\r
+\r
+ public void checkType(TypingContext context) {\r
+ for(Variable variable : existentialVariables)\r
+ variable.setType(Types.metaVar(Kinds.STAR));\r
+ head.checkType(context);\r
+ body.checkType(context);\r
+ }\r
+ \r
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
+ head.collectVars(allVars, vars);\r
+ body.collectVars(allVars, vars);\r
+ }\r
+\r
+ public void forVariables(VariableProcedure procedure) {\r
+ head.forVariables(procedure);\r
+ body.forVariables(procedure);\r
+ }\r
+\r
+ public void collectFreeVariables(THashSet<Variable> vars) {\r
+ head.collectFreeVariables(vars);\r
+ body.collectFreeVariables(vars);\r
+ }\r
+\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ this.location = loc;\r
+ head.setLocationDeep(loc);\r
+ body.setLocationDeep(loc);\r
+ }\r
+ }\r
+ \r
+ public void simplify(SimplificationContext context) {\r
+ head.simplify(context);\r
+ body.simplify(context);\r
+ }\r
+\r
+ public void compile(CompilationContext compilationContext, CHRConstraint initConstraint) {\r
+ boolean hasActiveLiteral = false;\r
+ for(int i=0;i<head.literals.length;++i) {\r
+ CHRLiteral literal = head.literals[i];\r
+ if(literal.passive)\r
+ continue;\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ \r
+ Variable activeFact = new Variable("activeFact", constraint.factType);\r
+ QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);\r
+ head.createQueryPlan(context, new EVariable(activeFact), i);\r
+ body.createEnforcePlan(context, priority);\r
+ constraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));\r
+ \r
+ hasActiveLiteral = true;\r
+ }\r
+ if(!hasActiveLiteral) {\r
+ Variable activeFact = new Variable("activeFact", initConstraint.factType);\r
+ QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);\r
+ head.createQueryPlan(context, null, -1);\r
+ body.createEnforcePlan(context, priority);\r
+ /*System.out.println(this);\r
+ for(PlanOp planOp : context.getPlanOps())\r
+ System.out.println(" " + planOp);*/\r
+ initConstraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));\r
+ }\r
+ }\r
+ \r
+ public String toString() {\r
+ StringBuilder b = new StringBuilder();\r
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
+ visitor.visit(this);\r
+ return b.toString();\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.constants.BooleanConstant;\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.constants.IntegerConstant;\r
+import org.simantics.scl.compiler.constants.JavaMethod;\r
+import org.simantics.scl.compiler.constants.generic.CallJava;\r
+import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;\r
+import org.simantics.scl.compiler.constants.generic.MethodRef.SetFieldRef;\r
+import org.simantics.scl.compiler.elaboration.chr.analysis.UsageAnalysis;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanRealizer;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.internal.parsing.Symbol;\r
+import org.simantics.scl.compiler.types.TCon;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class CHRRuleset extends Symbol {\r
+ \r
+ public static final String INIT_CONSTRAINT = "__INIT__";\r
+ \r
+ public ArrayList<CHRConstraint> constraints = new ArrayList<CHRConstraint>();\r
+ public ArrayList<CHRRule> rules = new ArrayList<CHRRule>();\r
+ \r
+ public CHRConstraint initConstraint;\r
+ public int priorityCount;\r
+ \r
+ public String storeClassName;\r
+ public TCon storeType;\r
+ public BoundVar storeVariable;\r
+ public TypeDesc storeTypeDesc;\r
+ public Constant activateProcedure;\r
+ public Constant readCurrentId;\r
+ public Constant writeCurrentId;\r
+ \r
+ // FIXME remove and change the parameter of Expression.toVal\r
+ private CompilationContext cachedContext;\r
+ \r
+ // For code generation\r
+ public BoundVar this_;\r
+ public BoundVar[] parameters;\r
+ public TypeDesc[] parameterTypeDescs;\r
+ \r
+ public CHRRuleset() {\r
+ initConstraint = new CHRConstraint(Locations.NO_LOCATION, INIT_CONSTRAINT, Type.EMPTY_ARRAY);\r
+ constraints.add(initConstraint);\r
+ }\r
+ \r
+ public void resolve(TranslationContext context) {\r
+ for(CHRConstraint constraint : constraints)\r
+ context.newCHRConstraint(constraint.name, constraint);\r
+ priorityCount = 0;\r
+ for(CHRRule rule : rules) {\r
+ rule.resolve(context);\r
+ rule.priority = priorityCount++;\r
+ }\r
+ /*for(CHRConstraint constraint : constraints) {\r
+ Variable newVariable = context.newVariable("claim" + constraint.factClassName);\r
+ }*/\r
+ }\r
+\r
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
+ for(CHRRule rule : rules)\r
+ rule.collectRefs(allRefs, refs);\r
+ }\r
+\r
+ public void checkType(TypingContext context) {\r
+ for(CHRRule rule : rules)\r
+ rule.checkType(context);\r
+ }\r
+\r
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
+ for(CHRRule rule : rules)\r
+ rule.collectVars(allVars, vars);\r
+ }\r
+\r
+ public void forVariables(VariableProcedure procedure) {\r
+ for(CHRRule rule : rules)\r
+ rule.forVariables(procedure);\r
+ }\r
+\r
+ public void collectFreeVariables(THashSet<Variable> vars) {\r
+ for(CHRRule rule : rules)\r
+ rule.collectFreeVariables(vars);\r
+ }\r
+\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ this.location = loc;\r
+ for(CHRRule rule : rules)\r
+ rule.setLocationDeep(loc);\r
+ }\r
+ }\r
+\r
+ public void compile(SimplificationContext context) {\r
+ initializeCodeGeneration(context.getCompilationContext());\r
+ UsageAnalysis.analyzeUsage(this);\r
+ for(CHRRule rule : rules)\r
+ rule.compile(context.getCompilationContext(), initConstraint);\r
+ // remove init constraint if it is not useful\r
+ if(initConstraint.plans.isEmpty()) {\r
+ constraints.remove(0);\r
+ initConstraint = null;\r
+ }\r
+ for(CHRConstraint constraint : constraints) {\r
+ constraint.plans.sort((PrioritizedPlan a, PrioritizedPlan b) -> {\r
+ return Integer.compare(a.priority, b.priority);\r
+ });\r
+ /*System.out.println(constraint.name);\r
+ for(PrioritizedPlan plan : constraint.plans) {\r
+ System.out.println(" priority " + plan.priority);\r
+ for(PlanOp op : plan.ops)\r
+ System.out.println(" " + op);\r
+ }*/\r
+ }\r
+ }\r
+\r
+ public void simplify(SimplificationContext context) {\r
+ for(CHRRule rule : rules)\r
+ rule.simplify(context);\r
+ }\r
+ \r
+ public void initializeCodeGeneration(CompilationContext context) {\r
+ cachedContext = context; // FIXME remove\r
+ \r
+ String suffix = context.namingPolicy.getFreshClosureClassNameSuffix();\r
+ storeType = Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix);\r
+ storeClassName = context.namingPolicy.getModuleClassName() + suffix;\r
+ storeTypeDesc = TypeDesc.forClass(storeClassName);\r
+ storeVariable = new BoundVar(storeType); \r
+ for(CHRConstraint constraint : constraints)\r
+ constraint.initializeCodeGeneration(context, this);\r
+ activateProcedure = new JavaMethod(true, storeClassName, "activate", Types.PROC, Types.UNIT, storeType, Types.INTEGER);\r
+ readCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {storeType},\r
+ null, new FieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null);\r
+ writeCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {storeType, Types.INTEGER},\r
+ null, new SetFieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null);\r
+ if(context.module != null) // for unit testing\r
+ context.module.addTypeDescriptor(storeType.name, new StandardTypeConstructor(storeType, TVar.EMPTY_ARRAY, storeTypeDesc));\r
+ }\r
+ \r
+ public void generateCode(CodeWriter w) {\r
+ CHRRulesetObject object = new CHRRulesetObject(storeVariable, this);\r
+ w.defineObject(object);\r
+ for(CHRConstraint constraint : constraints) {\r
+ //System.out.println(constraint);\r
+ for(PrioritizedPlan plan : constraint.plans) {\r
+ /*System.out.println(" plan " + plan.priority);\r
+ for(PlanOp planOp : plan.ops)\r
+ System.out.println(" " + planOp);*/\r
+ PlanRealizer realizer = new PlanRealizer(cachedContext, this, storeVariable, plan.ops);\r
+ CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.BOOLEAN, new Type[] {constraint.factType});\r
+ plan.implementation = methodWriter.getFunction();\r
+ plan.activeFact.setVal(methodWriter.getParameters()[0]);\r
+ realizer.nextOp(methodWriter);\r
+ if(methodWriter.isUnfinished())\r
+ methodWriter.return_(BooleanConstant.TRUE);\r
+ }\r
+ }\r
+ if(initConstraint != null) {\r
+ IVal initFact = w.apply(location, initConstraint.constructor, IntegerConstant.ZERO);\r
+ w.apply(location, initConstraint.addProcedure, storeVariable, initFact);\r
+ w.apply(location, activateProcedure, storeVariable, new IntegerConstant(Integer.MAX_VALUE));\r
+ }\r
+ }\r
+\r
+ public void collectEffects(THashSet<Type> effects) {\r
+ for(CHRRule rule : rules) {\r
+ for(CHRLiteral literal : rule.head.literals)\r
+ literal.collectQueryEffects(effects);\r
+ for(CHRLiteral literal : rule.head.literals)\r
+ literal.collectEnforceEffects(effects);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr;\r
+\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.constants.JavaConstructor;\r
+import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class CHRRulesetObject extends SSAObject {\r
+ CHRRuleset ruleset;\r
+\r
+ public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) {\r
+ super(ruleset.storeType);\r
+ this.setTarget(target);\r
+ this.ruleset = ruleset;\r
+ }\r
+ \r
+ @Override\r
+ public Constant liftClosure(BoundVar newTarget, BoundVar[] parameters) {\r
+ ruleset.this_ = newTarget;\r
+ ruleset.parameters = parameters;\r
+ return new JavaConstructor(ruleset.storeClassName, Types.PROC, ruleset.storeType, Types.getTypes(parameters));\r
+ }\r
+ \r
+ @Override\r
+ public void generateCode(ModuleBuilder moduleBuilder) {\r
+ CHRCodeGenerator.generateStore(moduleBuilder, ruleset);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.analysis;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+public class UsageAnalysis {\r
+ public static void analyzeUsage(CHRRuleset ruleset) {\r
+ THashMap<CHRConstraint,ArrayList<CHRRule>> headConstraintMap = createHeadConstraintMap(ruleset);\r
+ calculateFirstPriorities(ruleset, headConstraintMap);\r
+ calculateLastPriorities(ruleset, headConstraintMap);\r
+ for(CHRRule rule : ruleset.rules)\r
+ determinePassiveLiterals(rule);\r
+ //printPriorities(ruleset);\r
+ }\r
+\r
+ private static void calculateFirstPriorities(CHRRuleset ruleset,\r
+ THashMap<CHRConstraint, ArrayList<CHRRule>> headConstraintMap) {\r
+ for(CHRRule rule : ruleset.rules)\r
+ rule.firstPriorityExecuted = Integer.MAX_VALUE;\r
+ for(CHRConstraint constraint : ruleset.constraints) {\r
+ constraint.firstPriorityAdded = Integer.MAX_VALUE;\r
+ constraint.firstPriorityRemoved = Integer.MAX_VALUE;\r
+ }\r
+ for(CHRRule rule : ruleset.rules)\r
+ calculateFirstPriority(headConstraintMap, rule);\r
+ }\r
+\r
+ private static void calculateFirstPriority(THashMap<CHRConstraint, ArrayList<CHRRule>> headConstraintMap, CHRRule rule) {\r
+ int result = rule.priority;\r
+ for(CHRLiteral literal : rule.head.literals)\r
+ if(literal.relation instanceof CHRConstraint) {\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ int constraintPriority = constraint.firstPriorityAdded;\r
+ if(constraintPriority == Integer.MAX_VALUE)\r
+ return;\r
+ result = Math.max(result, constraint.firstPriorityAdded);\r
+ }\r
+ rule.firstPriorityExecuted = result;\r
+ for(CHRLiteral literal : rule.head.literals)\r
+ if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) {\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ if(constraint.firstPriorityRemoved != Integer.MAX_VALUE)\r
+ continue;\r
+ constraint.firstPriorityRemoved = result;\r
+ }\r
+ for(CHRLiteral literal : rule.body.literals)\r
+ if(literal.relation instanceof CHRConstraint) {\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ if(constraint.firstPriorityAdded != Integer.MAX_VALUE)\r
+ continue;\r
+ constraint.firstPriorityAdded = result;\r
+ ArrayList<CHRRule> list = headConstraintMap.get(constraint);\r
+ if(list == null)\r
+ continue;\r
+ for(CHRRule lowerPriorityRule : list)\r
+ if(lowerPriorityRule.priority < rule.priority)\r
+ calculateFirstPriority(headConstraintMap, lowerPriorityRule);\r
+ }\r
+ }\r
+\r
+ private static void calculateLastPriorities(CHRRuleset ruleset,\r
+ THashMap<CHRConstraint, ArrayList<CHRRule>> headConstraintMap) {\r
+ for(CHRRule rule : ruleset.rules)\r
+ rule.lastPriorityExecuted = Integer.MIN_VALUE;\r
+ for(CHRConstraint constraint : ruleset.constraints) {\r
+ constraint.lastPriorityAdded = Integer.MIN_VALUE;\r
+ constraint.lastPriorityRemoved = Integer.MIN_VALUE;\r
+ }\r
+ for(int i=ruleset.rules.size()-1;i>=0;--i) {\r
+ CHRRule rule = ruleset.rules.get(i);\r
+ if(rule.lastPriorityExecuted == Integer.MIN_VALUE)\r
+ calculateLastPriority(headConstraintMap, rule, rule.priority);\r
+ }\r
+ }\r
+\r
+ private static void calculateLastPriority(THashMap<CHRConstraint, ArrayList<CHRRule>> headConstraintMap,\r
+ CHRRule rule, int priority) {\r
+ rule.lastPriorityExecuted = priority;\r
+ for(CHRLiteral literal : rule.head.literals)\r
+ if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) {\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ if(constraint.lastPriorityRemoved != Integer.MIN_VALUE)\r
+ continue;\r
+ constraint.lastPriorityRemoved = priority;\r
+ }\r
+ for(CHRLiteral literal : rule.body.literals)\r
+ if(literal.relation instanceof CHRConstraint) {\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ if(constraint.lastPriorityAdded != Integer.MIN_VALUE)\r
+ continue;\r
+ constraint.lastPriorityAdded = priority;\r
+ ArrayList<CHRRule> list = headConstraintMap.get(constraint);\r
+ if(list == null)\r
+ continue;\r
+ for(CHRRule lowerPriorityRule : list)\r
+ if(lowerPriorityRule.lastPriorityExecuted == Integer.MIN_VALUE)\r
+ calculateLastPriority(headConstraintMap, lowerPriorityRule, priority);\r
+ }\r
+ }\r
+\r
+ private static THashMap<CHRConstraint, ArrayList<CHRRule>> createHeadConstraintMap(CHRRuleset ruleset) {\r
+ THashMap<CHRConstraint, ArrayList<CHRRule>> map = new THashMap<CHRConstraint, ArrayList<CHRRule>>(); \r
+ for(CHRRule rule : ruleset.rules)\r
+ for(CHRLiteral literal : rule.head.literals)\r
+ if(literal.relation instanceof CHRConstraint) {\r
+ ArrayList<CHRRule> list = map.get(literal.relation);\r
+ if(list == null) {\r
+ list = new ArrayList<CHRRule>();\r
+ map.put((CHRConstraint)literal.relation, list);\r
+ list.add(rule);\r
+ }\r
+ else if(list.get(list.size()-1) != rule)\r
+ list.add(rule);\r
+ }\r
+ return map;\r
+ }\r
+ \r
+ private static void printPriorities(CHRRuleset ruleset) {\r
+ System.out.println("-------------------------------");\r
+ for(CHRConstraint constraint : ruleset.constraints) {\r
+ System.out.print(" [" + constraint.firstPriorityAdded + ".." + constraint.lastPriorityAdded + "]");\r
+ if(constraint.firstPriorityRemoved != Integer.MAX_VALUE)\r
+ System.out.print("R[" + constraint.firstPriorityRemoved + ".." + constraint.lastPriorityRemoved + "]");\r
+ System.out.print(" ");\r
+ System.out.println(constraint);\r
+ }\r
+ for(CHRRule rule : ruleset.rules) {\r
+ System.out.print(rule.priority);\r
+ System.out.print(" [" + rule.firstPriorityExecuted + ".." + rule.lastPriorityExecuted + "] ");\r
+ System.out.println(rule);\r
+ }\r
+ }\r
+\r
+ private static void determinePassiveLiterals(CHRRule rule) {\r
+ for(CHRLiteral literal : rule.head.literals) {\r
+ if(literal.passive)\r
+ continue;\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ if(constraint.lastPriorityAdded < rule.priority)\r
+ literal.passive = true;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.constants.BooleanConstant;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class AccessFactOp extends PlanOp {\r
+\r
+ Expression inputFact;\r
+ CHRConstraint constraint;\r
+ Variable[] variables;\r
+ boolean killAfterMatch;\r
+ \r
+ public AccessFactOp(long location, Expression inputFact, CHRConstraint constraint, Variable[] variables,\r
+ boolean killAfterMatch) {\r
+ super(location);\r
+ this.inputFact = inputFact;\r
+ this.constraint = constraint;\r
+ this.variables = variables;\r
+ this.killAfterMatch = killAfterMatch;\r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("ACCESS ");\r
+ if(killAfterMatch)\r
+ b.append("- ");\r
+ b.append(constraint);\r
+ for(Variable variable : variables)\r
+ b.append(' ').append(variable);\r
+ b.append(" = ").append(inputFact);\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ IVal inputVal = inputFact.toVal(context.environment, w);\r
+ for(int i=0;i<variables.length;++i)\r
+ variables[i].setVal(w.apply(location, constraint.accessComponent(i), inputVal));\r
+ IVal activeId = w.apply(location, constraint.accessId, inputVal);\r
+ CodeWriter end = constraint.mayBeRemoved() ? w.createBlock() : null;\r
+ planContext.partnerFacts.add(new PartnerFact(true, activeId, constraint, inputVal, constraint.mayBeRemoved(), killAfterMatch, null, null, end == null ? null : end.getContinuation()));\r
+ planContext.nextOp(w);\r
+ if(end != null)\r
+ end.return_(BooleanConstant.FALSE);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class AssignOp extends PlanOp {\r
+ public Variable variable;\r
+ public Expression expression;\r
+ \r
+ public AssignOp(long location, Variable variable, Expression expression) {\r
+ super(location);\r
+ this.variable = variable;\r
+ this.expression = expression;\r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("ASSIGN ").append(variable).append(" = ").append(expression);\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ variable.setVal(expression.toVal(context.environment, w));\r
+ planContext.nextOp(w);\r
+ }\r
+\r
+ \r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class CheckOp extends PlanOp {\r
+ public Expression condition;\r
+\r
+ public CheckOp(long location, Expression condition) {\r
+ super(location);\r
+ this.condition = condition;\r
+ }\r
+ \r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("CHECK ").append(condition);\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ planContext.check(location, w, condition.toVal(context.environment, w));\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class ClaimOp extends PlanOp {\r
+\r
+ CHRConstraint constraint;\r
+ Expression[] parameters;\r
+\r
+ public ClaimOp(long location, CHRConstraint constraint, Expression[] parameters) {\r
+ super(location);\r
+ this.constraint = constraint;\r
+ this.parameters = parameters;\r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("CLAIM ").append(constraint);\r
+ for (Expression parameter : parameters)\r
+ b.append(" (").append(parameter).append(')');\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ IVal[] parameterVars = new IVal[parameters.length+1];\r
+ parameterVars[0] = planContext.generateNewId(location, w);\r
+ for(int i=0;i<parameters.length;++i)\r
+ parameterVars[i+1] = parameters[i].toVal(context.environment, w);\r
+ IVal newFact = w.apply(location, constraint.constructor, parameterVars);\r
+ w.apply(location, constraint.addProcedure, planContext.storeVar, newFact);\r
+ planContext.nextOp(w);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class ExecuteOp extends PlanOp {\r
+ Expression expression;\r
+ \r
+ public ExecuteOp(long location, Expression expression) {\r
+ super(location);\r
+ this.expression = expression;\r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("EXECUTE ").append(expression);\r
+\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ expression.toVal(context.environment, w);\r
+ planContext.nextOp(w);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.constants.JavaComparisonOperation;\r
+import org.simantics.scl.compiler.constants.singletons.NullCheck;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class IterateConstraintOp extends PlanOp {\r
+ \r
+ public CHRConstraint constraint;\r
+ public Variable[] variables;\r
+ public Expression[] expressions;\r
+ public int boundMask;\r
+ public boolean killAfterMatch;\r
+ public boolean passive;\r
+ \r
+ public IterateConstraintOp(long location, CHRConstraint constraint, Variable[] variables, Expression[] expressions,\r
+ int boundMask, boolean killAfterMatch, boolean passive) {\r
+ super(location);\r
+ this.constraint = constraint;\r
+ this.variables = variables;\r
+ this.expressions = expressions;\r
+ this.boundMask = boundMask;\r
+ this.killAfterMatch = killAfterMatch;\r
+ this.passive = passive;\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("ITERATE ").append(constraint);\r
+ for(int i=0;i<expressions.length;++i)\r
+ if((boundMask & (1 << i)) != 0) {\r
+ b.append(" (").append(expressions[i]).append(")");\r
+ }\r
+ else {\r
+ b.append(" ").append(variables[i]);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ CodeWriter body = w.createBlock(constraint.factType);\r
+ CodeWriter nextFact = w.createBlock();\r
+ ICont bodyContinuation = body.getContinuation();\r
+ CodeWriter end = w.createBlock();\r
+ IVal fact = body.getParameters()[0];\r
+\r
+ ArrayList<IVal> parameters = new ArrayList<IVal>(expressions.length+1);\r
+ parameters.add(planContext.storeVar);\r
+ for(int i=0;i<expressions.length;++i)\r
+ if(((boundMask>>i)&1)==1)\r
+ parameters.add(expressions[i].toVal(context.environment, w));\r
+ w.jump(bodyContinuation, w.apply(location,\r
+ constraint.fetchFromIndex(context, boundMask), parameters.toArray(new IVal[parameters.size()])));\r
+\r
+ body.branchAwayIf(body.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact),\r
+ end.getContinuation());\r
+ IVal id = body.apply(location, constraint.accessId, fact);\r
+ for(PartnerFact partnerFact : planContext.partnerFacts)\r
+ if(partnerFact.active && !passive) {\r
+ body.branchAwayUnless(body.apply(location, JavaComparisonOperation.ILESS, id, partnerFact.id),\r
+ nextFact.getContinuation());\r
+ }\r
+ else if(partnerFact.constraint == constraint) {\r
+ body.branchAwayIf(body.apply(location, JavaComparisonOperation.IEQUAL, id, partnerFact.id),\r
+ nextFact.getContinuation());\r
+ }\r
+\r
+ for(int i=0;i<variables.length;++i)\r
+ if(((boundMask>>i)&1)==0)\r
+ variables[i].setVal(body.apply(location, constraint.accessComponent(i), fact));\r
+ Constant nextElement = constraint.nextElement(context, boundMask);\r
+ planContext.partnerFacts.add(new PartnerFact(false, id, constraint, fact, constraint.mayBeRemoved(), killAfterMatch, nextElement, bodyContinuation, end.getContinuation()));\r
+ planContext.nextOp(body);\r
+ if(body.isUnfinished()) \r
+ body.jump(nextFact.getContinuation());\r
+ nextFact.jump(bodyContinuation, nextFact.apply(location, nextElement, fact));\r
+\r
+ w.continueAs(end);\r
+ } \r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class IterateListOp extends PlanOp {\r
+ public Variable variable;\r
+ public Expression list;\r
+ \r
+ public IterateListOp(long location, Variable variable, Expression list) {\r
+ super(location);\r
+ this.variable = variable;\r
+ this.list = list;\r
+ } \r
+ \r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("ITERATE ").append(variable).append(" <- ").append(list);\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ IVal listValue = list.toVal(context.environment, w);\r
+ planContext.iterateList(location, w, variable, listValue);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class IterateRelationOp extends PlanOp {\r
+ \r
+ public SCLRelation relation;\r
+ public Variable[] variables;\r
+ public Expression[] expressions;\r
+ public int boundMask;\r
+ \r
+ public IterateRelationOp(long location, SCLRelation relation, Variable[] variables, Expression[] expressions,\r
+ int boundMask) {\r
+ super(location);\r
+ this.relation = relation;\r
+ this.variables = variables;\r
+ this.expressions = expressions;\r
+ this.boundMask = boundMask;\r
+ \r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("ITERATE ").append(relation);\r
+ for(int i=0;i<expressions.length;++i)\r
+ if((boundMask & (1 << i)) != 0) {\r
+ b.append(" (").append(expressions[i]).append(")");\r
+ }\r
+ else {\r
+ b.append(" ").append(variables[i]);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ relation.generateIterate(planContext, w, location, boundMask, variables, expressions);\r
+ } \r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.internal.elaboration.matching2.PatternMatchingCompiler2;\r
+import org.simantics.scl.compiler.internal.elaboration.matching2.Row2;\r
+\r
+public class MatchOp extends PlanOp {\r
+ public Expression scrutinee;\r
+ public Expression pattern;\r
+ \r
+ public MatchOp(long location, Expression scrutinee, Expression pattern) {\r
+ super(location);\r
+ this.scrutinee = scrutinee;\r
+ this.pattern = pattern;\r
+ }\r
+ \r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("MATCH ").append(pattern).append(" = ").append(scrutinee);\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ CodeWriter body = w.createBlock();\r
+ CodeWriter end = w.createBlock();\r
+ \r
+ IVal[] scrutineeVals = new IVal[1];\r
+ scrutineeVals[0] = scrutinee.toVal(context.environment, w);\r
+\r
+ ArrayList<Row2> rows = new ArrayList<Row2>(1);\r
+ rows.add(new Row2(new Expression[] {pattern}, body.getContinuation()));\r
+\r
+ PatternMatchingCompiler2.split(w, context.environment, scrutineeVals, end.getContinuation(), rows);\r
+ \r
+ planContext.nextOp(body);\r
+ if(body.isUnfinished())\r
+ body.jump(end.getContinuation());\r
+ \r
+ w.continueAs(end);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.constants.JavaComparisonOperation;\r
+import org.simantics.scl.compiler.constants.JavaComparisonToZeroOperation;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class PartnerFact {\r
+ public final boolean active;\r
+ public final IVal id;\r
+ public final CHRConstraint constraint;\r
+ public final IVal factVar;\r
+ public final boolean mayBeRemoved;\r
+ public final boolean killAfterMatch;\r
+\r
+ public final Constant nextFact;\r
+ public final ICont continueCont;\r
+ public final ICont finishCont;\r
+ \r
+ public PartnerFact(boolean active, IVal id, CHRConstraint constraint, IVal factVar, boolean mayBeRemoved, boolean killAfterMatch,\r
+ Constant nextFact, ICont continueCont, ICont finishCont) {\r
+ this.active = active;\r
+ this.id = id;\r
+ this.constraint = constraint;\r
+ this.factVar = factVar;\r
+ this.mayBeRemoved = mayBeRemoved;\r
+ this.killAfterMatch = killAfterMatch;\r
+ this.nextFact = nextFact;\r
+ this.continueCont = continueCont;\r
+ this.finishCont = finishCont;\r
+ }\r
+ \r
+ public IVal isAlive(long location, CodeWriter w) {\r
+ return w.apply(location, JavaComparisonOperation.IEQUAL, w.apply(location, constraint.accessId, factVar), id);\r
+ }\r
+ \r
+ public IVal isAlive(long location, CodeWriter w, IVal fact) {\r
+ return w.apply(location, JavaComparisonToZeroOperation.IGREATER_OR_EQUAL, w.apply(location, constraint.accessId, fact));\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.constants.IntegerConstant;\r
+import org.simantics.scl.compiler.constants.JavaComparisonOperation;\r
+import org.simantics.scl.compiler.constants.singletons.IncreaseByOne;\r
+import org.simantics.scl.compiler.constants.singletons.ListElement;\r
+import org.simantics.scl.compiler.constants.singletons.ListLength;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public abstract class PlanContext {\r
+ public CompilationContext context;\r
+ public CHRRuleset ruleset;\r
+ public IVal storeVar;\r
+ public ArrayList<PartnerFact> partnerFacts = new ArrayList<PartnerFact>();\r
+ public IVal currentId;\r
+ \r
+ public PlanContext(CompilationContext context, CHRRuleset ruleset, IVal storeVar) {\r
+ this.context = context;\r
+ this.ruleset = ruleset;\r
+ this.storeVar = storeVar;\r
+ }\r
+\r
+ public abstract void nextOp(CodeWriter w);\r
+\r
+ public IVal generateNewId(long location, CodeWriter w) {\r
+ if(currentId == null)\r
+ currentId = w.apply(location, ruleset.readCurrentId, storeVar);\r
+ IVal result = currentId;\r
+ currentId = w.apply(location, IncreaseByOne.INSTANCE, currentId);\r
+ return result;\r
+ }\r
+ \r
+ public void iterateList(long location, CodeWriter w, Variable variable, IVal listValue) {\r
+ Type componentType = variable.getType();\r
+ IVal listLength = w.apply(location, ListLength.INSTANCE.createSpecialization(componentType), listValue);\r
+ \r
+ CodeWriter body = w.createBlock(Types.INTEGER);\r
+ ICont bodyContinuation = body.getContinuation();\r
+ CodeWriter end = w.createBlock();\r
+ \r
+ w.jump(body.getContinuation(), IntegerConstant.ZERO);\r
+ \r
+ IVal index = body.getParameters()[0];\r
+ body.branchAwayIf(body.apply(location, JavaComparisonOperation.IEQUAL, index, listLength),\r
+ end.getContinuation());\r
+ variable.setVal(body.apply(location, ListElement.INSTANCE.createSpecialization(componentType), listValue, index));\r
+ nextOp(body);\r
+ if(body.isUnfinished())\r
+ body.jump(bodyContinuation, body.apply(location, IncreaseByOne.INSTANCE, index));\r
+ \r
+ w.continueAs(end);\r
+ }\r
+\r
+ public void check(long location, CodeWriter w, IVal booleanValue) {\r
+ CodeWriter end = w.createBlock();\r
+ w.branchAwayUnless(booleanValue, end.getContinuation());\r
+ nextOp(w);\r
+ if(w.isUnfinished())\r
+ w.jump(end.getContinuation());\r
+ w.continueAs(end);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public abstract class PlanOp {\r
+ public long location;\r
+\r
+ public PlanOp(long location) {\r
+ this.location = location;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ StringBuilder b = new StringBuilder();\r
+ toString(b);\r
+ return b.toString();\r
+ }\r
+\r
+ public abstract void toString(StringBuilder b);\r
+ public abstract void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w);\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import java.util.List;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class PlanRealizer extends PlanContext {\r
+ List<PlanOp> ops;\r
+ int id = 0;\r
+\r
+ public PlanRealizer(CompilationContext context, CHRRuleset ruleset, IVal storeVar, List<PlanOp> ops) {\r
+ super(context, ruleset, storeVar);\r
+ this.ops = ops;\r
+ }\r
+\r
+ @Override\r
+ public void nextOp(CodeWriter w) {\r
+ PlanOp planOp = ops.get(id);\r
+ ++id;\r
+ planOp.generateCode(context, this, w);\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.constants.IntegerConstant;\r
+import org.simantics.scl.compiler.constants.singletons.NullCheck;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class PostCommitOp extends PlanOp {\r
+ int priority;\r
+ \r
+ public PostCommitOp(long location, int priority) {\r
+ super(location);\r
+ this.priority = priority;\r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("POST_COMMIT " + priority);\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ if(planContext.currentId != null) {\r
+ w.apply(location, planContext.ruleset.writeCurrentId, planContext.storeVar, planContext.currentId);\r
+ planContext.currentId = null;\r
+ w.apply(location, planContext.ruleset.activateProcedure, planContext.storeVar, new IntegerConstant(priority));\r
+ }\r
+ for(PartnerFact activeFact : planContext.partnerFacts) {\r
+ if(activeFact.killAfterMatch) {\r
+ if(activeFact.nextFact == null)\r
+ w.jump(activeFact.finishCont);\r
+ else {\r
+ CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType);\r
+ w.jump(iterateAlive.getContinuation(), w.apply(location, activeFact.nextFact, activeFact.factVar));\r
+ iterateUntilLiveFactFound(iterateAlive, activeFact); \r
+ }\r
+ break;\r
+ }\r
+ else if(activeFact.mayBeRemoved) {\r
+ if(activeFact.nextFact == null) {\r
+ w.branchAwayUnless(activeFact.isAlive(location, w), activeFact.finishCont);\r
+ }\r
+ else {\r
+ CodeWriter failure = w.createBlock();\r
+ CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType);\r
+ w.branchAwayUnless(activeFact.isAlive(location, w), failure.getContinuation());\r
+ failure.jump(iterateAlive.getContinuation(), failure.apply(location, activeFact.nextFact, activeFact.factVar));\r
+ iterateUntilLiveFactFound(iterateAlive, activeFact); \r
+ }\r
+ }\r
+ }\r
+ // PostCommit does not call nextOp\r
+ }\r
+ \r
+ private void iterateUntilLiveFactFound(CodeWriter w, PartnerFact activeFact) {\r
+ ICont initialContinuation = w.getContinuation();\r
+ CHRConstraint constraint = activeFact.constraint;\r
+ IVal fact = w.getParameters()[0];\r
+ CodeWriter dead = w.createBlock();\r
+ w.branchAwayIf(w.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), activeFact.finishCont);\r
+ w.branchAwayUnless(activeFact.isAlive(location, w, fact), dead.getContinuation());\r
+ w.jump(activeFact.continueCont, fact);\r
+ dead.jump(initialContinuation, dead.apply(location, activeFact.nextFact, fact));\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+\r
+public class PreCommitOp extends PlanOp {\r
+ public PreCommitOp(long location) {\r
+ super(location);\r
+ }\r
+\r
+ @Override\r
+ public void toString(StringBuilder b) {\r
+ b.append("PRE_COMMIT");\r
+ }\r
+\r
+ @Override\r
+ public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {\r
+ for(PartnerFact activeFact : planContext.partnerFacts) {\r
+ if(activeFact.killAfterMatch)\r
+ w.apply(location, activeFact.constraint.removeProcedure, planContext.storeVar, activeFact.factVar);\r
+ }\r
+ planContext.nextOp(w);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.plan;\r
+\r
+import java.util.List;\r
+\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
+\r
+public class PrioritizedPlan {\r
+ public int priority;\r
+ public Variable activeFact;\r
+ public List<PlanOp> ops;\r
+ public SSAFunction implementation;\r
+ \r
+ public PrioritizedPlan(int priority, Variable activeFact, List<PlanOp> ops) {\r
+ this.priority = priority;\r
+ this.activeFact = activeFact;\r
+ this.ops = ops;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning;\r
+\r
+import java.util.Arrays;\r
+\r
+public class PlanPriorityQueue {\r
+ PrePlanItem[] items = new PrePlanItem[16];\r
+ int size = 0;\r
+\r
+ public PrePlanItem head() {\r
+ return items[0];\r
+ }\r
+\r
+ public void pop() {\r
+ items[0].queuePos = -1;\r
+ --size;\r
+ if (size > 0) {\r
+ PrePlanItem e = items[size];\r
+ items[0] = e;\r
+ e.queuePos = 0;\r
+ adjustDown(e);\r
+ }\r
+ items[size] = null;\r
+ }\r
+\r
+ public void add(PrePlanItem e) {\r
+ if (size == items.length)\r
+ items = Arrays.copyOf(items, size + size / 2);\r
+ items[size] = e;\r
+ e.queuePos = size;\r
+ ++size;\r
+ adjustUp(e);\r
+ }\r
+\r
+ private boolean adjustUp(PrePlanItem e) {\r
+ int pos = e.queuePos;\r
+ while (pos > 0) {\r
+ int upId = (pos - 1) / 2;\r
+ PrePlanItem upE = items[upId];\r
+ if (e.compare(upE) >= 0)\r
+ break;\r
+ items[pos] = upE;\r
+ upE.queuePos = pos;\r
+ pos = upId;\r
+ }\r
+ if (e.queuePos != pos) {\r
+ items[pos] = e;\r
+ e.queuePos = pos;\r
+ return true;\r
+ } else\r
+ return false;\r
+ }\r
+\r
+ private void adjustDown(PrePlanItem e) {\r
+ int pos = e.queuePos;\r
+ while (true) {\r
+ int downId = pos * 2 + 1;\r
+ if (downId >= size)\r
+ break;\r
+ if (downId + 1 < size\r
+ && items[downId].compare(items[downId + 1]) > 0)\r
+ ++downId;\r
+ PrePlanItem downE = items[downId];\r
+ if (e.compare(downE) > 0) {\r
+ items[pos] = downE;\r
+ downE.queuePos = pos;\r
+ pos = downId;\r
+ } else\r
+ break;\r
+ }\r
+ if (e.queuePos != pos) {\r
+ items[pos] = e;\r
+ e.queuePos = pos;\r
+ }\r
+ }\r
+\r
+ public void adjust(PrePlanItem e) {\r
+ if(e.queuePos == -1)\r
+ return;\r
+ if (!adjustUp(e))\r
+ adjustDown(e);\r
+ }\r
+\r
+ public boolean isEmpty() {\r
+ return size == 0;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning;\r
+\r
+public abstract class PrePlanItem {\r
+ int queuePos;\r
+ /* Primary priorities:\r
+ * 0 = check\r
+ * 1 = functional calculation\r
+ * 2 = almost completely bound relation\r
+ * 3 = completely inbound relation\r
+ */\r
+ public double primaryPriority = Double.POSITIVE_INFINITY;\r
+ public int secondaryPriority;\r
+ public long location;\r
+ \r
+ public PrePlanItem(int secondaryPriority) {\r
+ this.secondaryPriority = secondaryPriority;\r
+ }\r
+\r
+ public int compare(PrePlanItem other) {\r
+ if(primaryPriority < other.primaryPriority)\r
+ return -1;\r
+ if(primaryPriority > other.primaryPriority)\r
+ return 1;\r
+ return Integer.compare(secondaryPriority, other.secondaryPriority); \r
+ }\r
+\r
+ public abstract void initializeListeners(QueryPlanningContext context);\r
+ public abstract void variableSolved(QueryPlanningContext context, int variableId);\r
+\r
+ public abstract void generate(QueryPlanningContext context);\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.AccessFactOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.ClaimOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.ExecuteOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.items.CheckPrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.items.EqualsPrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.items.GenericPrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.items.MemberPrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApplyType;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+\r
+import gnu.trove.impl.Constants;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.procedure.TIntProcedure;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class QueryPlanningContext {\r
+ CompilationContext compilationContext;\r
+ public PlanPriorityQueue priorityQueue = new PlanPriorityQueue();\r
+ ArrayList<Variable> variables;\r
+ TObjectIntHashMap<Variable> variableMap;\r
+ ArrayList<ArrayList<PrePlanItem>> itemsContainingVariable;\r
+ ArrayList<PlanOp> planOps = new ArrayList<PlanOp>(); \r
+ \r
+ public QueryPlanningContext(CompilationContext compilationContext, Variable[] variables) {\r
+ this.compilationContext = compilationContext;\r
+ this.variables = new ArrayList<Variable>(variables.length*2);\r
+ this.variableMap = new TObjectIntHashMap<Variable>(variables.length, Constants.DEFAULT_LOAD_FACTOR, -1);\r
+ itemsContainingVariable = new ArrayList<ArrayList<PrePlanItem>>(variables.length*2);\r
+ for(Variable variable : variables)\r
+ addVariable(variable);\r
+ }\r
+ \r
+ private void addVariable(Variable variable) {\r
+ int id = variables.size();\r
+ variables.add(variable);\r
+ variableMap.put(variable, id);\r
+ itemsContainingVariable.add(new ArrayList<PrePlanItem>(2));\r
+ }\r
+\r
+ public void add(CHRLiteral literal, int secondaryPriority) {\r
+ if(literal.relation instanceof SpecialCHRRelation) {\r
+ switch((SpecialCHRRelation)literal.relation) {\r
+ case CHECK:\r
+ addCheck(literal.location, literal.parameters[0], secondaryPriority);\r
+ return;\r
+ case EQUALS:\r
+ addGenericEquals(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority);\r
+ return;\r
+ case MEMBER:\r
+ addMember(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority);\r
+ return;\r
+ case EXECUTE:\r
+ throw new InternalCompilerError(literal.location, "EXECUTE constraint is not allowed in query compilation.");\r
+ }\r
+ }\r
+ \r
+ addGenericConstraint(literal, secondaryPriority);\r
+ }\r
+ \r
+ private TIntHashSet getVars(Expression expression, int initialCapacity) {\r
+ TIntHashSet variableSet = new TIntHashSet(initialCapacity);\r
+ expression.collectVars(variableMap, variableSet);\r
+ return variableSet;\r
+ }\r
+ \r
+ private TIntHashSet[] getVars(Expression[] expressions, int initialCapacity) {\r
+ TIntHashSet[] variableSets = new TIntHashSet[expressions.length];\r
+ for(int i=0;i<expressions.length;++i)\r
+ variableSets[i] = getVars(expressions[i], initialCapacity);\r
+ return variableSets;\r
+ }\r
+ \r
+ /**\r
+ * Returns true, if the expression is so simple, it does not involve any computation.\r
+ */\r
+ private static boolean isSimpleExpression(Expression expression) {\r
+ while(expression instanceof EApplyType)\r
+ expression = ((EApplyType)expression).getExpression();\r
+ return expression instanceof EVariable \r
+ || expression instanceof EConstant\r
+ || expression instanceof ELiteral\r
+ || expression instanceof EExternalConstant;\r
+ }\r
+ \r
+ private Expression toSimpleExpression(Expression expression, int secondaryPriority) {\r
+ if(isSimpleExpression(expression)) \r
+ return expression;\r
+ else {\r
+ Variable temp = new Variable("temp", expression.getType());\r
+ addVariable(temp);\r
+ addOneSidedEquals(expression.location, new EVariable(temp), expression, secondaryPriority);\r
+ return new EVariable(temp);\r
+ }\r
+ }\r
+ \r
+ private Expression[] toSimpleExpressions(Expression[] expressions, int secondaryPriority) {\r
+ Expression[] result = new Expression[expressions.length];\r
+ for(int i=0;i<expressions.length;++i)\r
+ result[i] = toSimpleExpression(expressions[i], secondaryPriority);\r
+ return result;\r
+ }\r
+\r
+ private void addGenericConstraint(CHRLiteral literal, int secondaryPriority) {\r
+ if(literal.killAfterMatch)\r
+ ((CHRConstraint)literal.relation).setMayBeRemoved();\r
+ Expression[] parameters = toSimpleExpressions(literal.parameters, secondaryPriority);\r
+ add(literal.location, new GenericPrePlanItem(literal, literal.relation, parameters, getVars(parameters, 1), secondaryPriority));\r
+ }\r
+\r
+ private void addMember(long location, Expression p1, Expression p2, int secondaryPriority) {\r
+ Expression expression1 = toSimpleExpression(p1, secondaryPriority);\r
+ Expression expression2 = toSimpleExpression(p2, secondaryPriority);\r
+ add(location, new MemberPrePlanItem(expression1, expression2,\r
+ getVars(expression1, 1), getVars(expression2, 1), secondaryPriority));\r
+ }\r
+ \r
+ private void addOneSidedEquals(long location, Expression expression1, Expression expression2, int secondaryPriority) {\r
+ add(location, new EqualsPrePlanItem(expression1, expression2,\r
+ getVars(expression1, 1), getVars(expression2, 4), secondaryPriority));\r
+ }\r
+\r
+ private void addGenericEquals(long location, Expression p1, Expression p2, int secondaryPriority) {\r
+ if(isSimpleExpression(p1))\r
+ addOneSidedEquals(location, p1, p2, secondaryPriority);\r
+ else if(isSimpleExpression(p2))\r
+ addOneSidedEquals(location, p2, p1, secondaryPriority);\r
+ else {\r
+ Variable temp = new Variable("temp", p1.getType());\r
+ addVariable(temp);\r
+ addOneSidedEquals(p1.location, new EVariable(temp), p1, secondaryPriority);\r
+ addOneSidedEquals(p2.location, new EVariable(temp), p2, secondaryPriority);\r
+ }\r
+ }\r
+\r
+ private void addCheck(long location, Expression condition, int secondaryPriority) {\r
+ TIntHashSet variableSet = new TIntHashSet(4);\r
+ condition.collectVars(variableMap, variableSet);\r
+ add(location, new CheckPrePlanItem(condition, variableSet, secondaryPriority));\r
+ }\r
+\r
+ private void add(long location, PrePlanItem item) {\r
+ priorityQueue.add(item);\r
+ item.initializeListeners(this);\r
+ item.location = location;\r
+ }\r
+\r
+ public void listen(TIntHashSet variableSet, PrePlanItem item) {\r
+ variableSet.forEach(new TIntProcedure() {\r
+ @Override\r
+ public boolean execute(int variableId) {\r
+ listen(variableId, item);\r
+ return true;\r
+ }\r
+ });\r
+ }\r
+\r
+ public void listen(int variableId, PrePlanItem item) {\r
+ itemsContainingVariable.get(variableId).add(item);\r
+ }\r
+\r
+ public void createQueryPlan() {\r
+ while(!priorityQueue.isEmpty()) {\r
+ PrePlanItem head = priorityQueue.head();\r
+ priorityQueue.pop();\r
+ head.generate(this);\r
+ }\r
+ }\r
+ \r
+ public ArrayList<PlanOp> getPlanOps() {\r
+ return planOps;\r
+ }\r
+ \r
+ private final TIntProcedure BIND_PROCEDURE = new TIntProcedure() {\r
+ @Override\r
+ public boolean execute(int variableId) {\r
+ ArrayList<PrePlanItem> l = itemsContainingVariable.get(variableId);\r
+ for(PrePlanItem item : l)\r
+ item.variableSolved(QueryPlanningContext.this, variableId);\r
+ l.clear();\r
+ return true;\r
+ }\r
+ };\r
+\r
+ public void bind(TIntHashSet variableSet) {\r
+ variableSet.forEach(BIND_PROCEDURE);\r
+ }\r
+\r
+ public void addPlanOp(PlanOp planOp) {\r
+ planOps.add(planOp);\r
+ }\r
+\r
+ public CompilationContext getCompilationContext() {\r
+ return compilationContext;\r
+ }\r
+\r
+ public void activate(CHRLiteral literal, Expression inputFact, int secondaryPriority) {\r
+ Variable[] variables = new Variable[literal.parameters.length];\r
+ for(int i=0;i<literal.parameters.length;++i)\r
+ variables[i] = new Variable("activeFactComponent" + i, literal.parameters[i].getType());\r
+ if(literal.killAfterMatch)\r
+ ((CHRConstraint)literal.relation).setMayBeRemoved();\r
+ planOps.add(new AccessFactOp(literal.location, inputFact, (CHRConstraint)literal.relation, variables, literal.killAfterMatch));\r
+ for(int i=0;i<literal.parameters.length;++i)\r
+ addOneSidedEquals(literal.parameters[i].location, new EVariable(variables[i]), literal.parameters[i], secondaryPriority);\r
+ }\r
+\r
+ public void claim(QueryPlanningContext context, CHRLiteral literal) {\r
+ if(literal.relation instanceof CHRConstraint) {\r
+ CHRConstraint constraint = (CHRConstraint)literal.relation;\r
+ addPlanOp(new ClaimOp(literal.location, constraint, literal.parameters));\r
+ }\r
+ else if(literal.relation instanceof SpecialCHRRelation) {\r
+ switch((SpecialCHRRelation)literal.relation) {\r
+ case EXECUTE:\r
+ addPlanOp(new ExecuteOp(literal.location, literal.parameters[0]));\r
+ break;\r
+ default:\r
+ context.getCompilationContext().errorLog.log(\r
+ literal.location,\r
+ "Cannot enforce this constraint.");\r
+ }\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning.items;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class CheckPrePlanItem extends PrePlanItem {\r
+ public Expression condition;\r
+ public TIntHashSet variableSet;\r
+\r
+ public CheckPrePlanItem(Expression condition, TIntHashSet variableSet, int secondaryPriority) {\r
+ super(secondaryPriority);\r
+ this.variableSet = variableSet;\r
+ this.condition = condition;\r
+ if(variableSet.isEmpty())\r
+ primaryPriority = 0.0;\r
+ }\r
+\r
+ @Override\r
+ public void initializeListeners(QueryPlanningContext context) {\r
+ context.listen(variableSet, this);\r
+ }\r
+\r
+ @Override\r
+ public void variableSolved(QueryPlanningContext context, int variableId) {\r
+ variableSet.remove(variableId);\r
+ if(variableSet.isEmpty()) {\r
+ primaryPriority = 0.0;\r
+ context.priorityQueue.adjust(this);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void generate(QueryPlanningContext context) {\r
+ context.addPlanOp(new CheckOp(location, condition));\r
+ context.bind(variableSet);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning.items;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.AssignOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.MatchOp;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.java.Builtins;\r
+\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class EqualsPrePlanItem extends PrePlanItem {\r
+ public Expression expression1, expression2;\r
+ public TIntHashSet variableSet1, variableSet2;\r
+\r
+ public EqualsPrePlanItem(Expression expression1, Expression expression2, TIntHashSet variableSet1, TIntHashSet variableSet2, int secondaryPriority) {\r
+ super(secondaryPriority);\r
+ this.expression1 = expression1;\r
+ this.expression2 = expression2;\r
+ this.variableSet1 = variableSet1;\r
+ this.variableSet2 = variableSet2;\r
+ updatePrimaryPriority();\r
+ }\r
+\r
+ private void updatePrimaryPriority() {\r
+ if(variableSet2.isEmpty()) {\r
+ if(variableSet1.isEmpty())\r
+ primaryPriority = 0;\r
+ else \r
+ primaryPriority = 1;\r
+ }\r
+ else {\r
+ if(variableSet1.isEmpty() && expression2.isPattern(0))\r
+ primaryPriority = 0.0;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void initializeListeners(QueryPlanningContext context) {\r
+ context.listen(variableSet1, this);\r
+ context.listen(variableSet2, this);\r
+ }\r
+\r
+ @Override\r
+ public void variableSolved(QueryPlanningContext context, int variableId) {\r
+ variableSet1.remove(variableId);\r
+ variableSet2.remove(variableId);\r
+ updatePrimaryPriority();\r
+ context.priorityQueue.adjust(this);\r
+ }\r
+ \r
+ @Override\r
+ public void generate(QueryPlanningContext context) {\r
+ if(variableSet1.isEmpty() && variableSet2.isEmpty()) {\r
+ context.addPlanOp(new CheckOp(location, new EApply(location, new EConstant(Builtins.EQUALS, expression1.getType()), expression1, expression2)));\r
+ }\r
+ else if(variableSet2.isEmpty()) {\r
+ Variable variable = ((EVariable)expression1).getVariable();\r
+ context.addPlanOp(new AssignOp(location, variable, expression2));\r
+ context.bind(variableSet1);\r
+ }\r
+ else if(variableSet1.isEmpty()) {\r
+ if(expression2 instanceof EVariable) {\r
+ Variable variable = ((EVariable)expression2).getVariable();\r
+ context.addPlanOp(new AssignOp(location, variable, expression1));\r
+ }\r
+ else {\r
+ context.addPlanOp(new MatchOp(location, expression1, expression2));\r
+ }\r
+ context.bind(variableSet2);\r
+ }\r
+ else\r
+ throw new InternalCompilerError("Unsolvable query.");\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning.items;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.IterateConstraintOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.IterateRelationOp;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.ExternalCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.java.Builtins;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class GenericPrePlanItem extends PrePlanItem {\r
+ public CHRLiteral literal;\r
+ public CHRRelation relation;\r
+ public Expression[] expressions;\r
+ public TIntHashSet[] variableSets;\r
+ TIntHashSet allVars;\r
+\r
+ public GenericPrePlanItem(CHRLiteral literal, CHRRelation relation, Expression[] expressions,\r
+ TIntHashSet[] variableSets, int secondaryPriority) {\r
+ super(secondaryPriority);\r
+ this.literal = literal;\r
+ this.relation = relation;\r
+ this.expressions = expressions;\r
+ this.variableSets = variableSets;\r
+ allVars = new TIntHashSet();\r
+ for(TIntHashSet variableSet : variableSets)\r
+ allVars.addAll(variableSet);\r
+ updatePrimaryPriority();\r
+ }\r
+\r
+ private void updatePrimaryPriority() {\r
+ int boundCount = 0;\r
+ int boundMask = 0;\r
+ for(int i=0;i<variableSets.length;++i)\r
+ if(variableSets[i].isEmpty()) {\r
+ ++boundCount;\r
+ boundMask |= 1 << i;\r
+ }\r
+ if(boundCount == variableSets.length)\r
+ primaryPriority = 0;\r
+ else {\r
+ if(relation instanceof ExternalCHRRelation) {\r
+ SCLRelation sclRelation = ((ExternalCHRRelation)relation).relation;\r
+ double selectivity = sclRelation.getSelectivity(boundMask);\r
+ if(selectivity == Double.POSITIVE_INFINITY)\r
+ primaryPriority = Double.POSITIVE_INFINITY;\r
+ else if(selectivity < 1.0)\r
+ primaryPriority = 0.0;\r
+ else if(selectivity == 1.0)\r
+ primaryPriority = 1.0;\r
+ else\r
+ primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;\r
+ }\r
+ else\r
+ primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void initializeListeners(QueryPlanningContext context) {\r
+ context.listen(allVars, this);\r
+ }\r
+\r
+ @Override\r
+ public void variableSolved(QueryPlanningContext context, int variableId) {\r
+ for(TIntHashSet variableSet : variableSets)\r
+ variableSet.remove(variableId);\r
+ allVars.remove(variableId);\r
+ updatePrimaryPriority();\r
+ context.priorityQueue.adjust(this);\r
+ }\r
+ \r
+ @Override\r
+ public void generate(QueryPlanningContext context) {\r
+ int boundMask = 0;\r
+ Expression[] boundExpressions = new Expression[expressions.length];\r
+ Variable[] freeVariables = new Variable[expressions.length];\r
+ int freeVariableCount = 0;\r
+ for(int i=0;i<expressions.length;++i)\r
+ if(variableSets[i].isEmpty()) {\r
+ boundExpressions[i] = expressions[i];\r
+ boundMask |= 1 << i;\r
+ }\r
+ else {\r
+ freeVariables[i] = ((EVariable)expressions[i]).getVariable();\r
+ ++freeVariableCount;\r
+ }\r
+ if(relation instanceof CHRConstraint)\r
+ context.addPlanOp(new IterateConstraintOp(location, (CHRConstraint)relation, freeVariables, boundExpressions, boundMask,\r
+ killAfterMatch(), literal.passive));\r
+ else if(relation instanceof ExternalCHRRelation)\r
+ context.addPlanOp(new IterateRelationOp(location, ((ExternalCHRRelation)relation).relation,\r
+ freeVariables, boundExpressions, boundMask));\r
+ else\r
+ throw new InternalCompilerError();\r
+ if(freeVariableCount > 1) {\r
+ THashSet<Variable> usedVariables = new THashSet<Variable>(freeVariableCount);\r
+ for(int i=0;i<freeVariables.length;++i) {\r
+ Variable variable = freeVariables[i];\r
+ if(variable == null)\r
+ continue;\r
+ if(!usedVariables.add(variable)) {\r
+ Variable auxiliary = new Variable(variable.getName(), variable.getType());\r
+ freeVariables[i] = auxiliary;\r
+ context.addPlanOp(new CheckOp(location, new EApply(location, new EConstant(Builtins.EQUALS, variable.getType()), new EVariable(auxiliary), new EVariable(variable))));\r
+ }\r
+ }\r
+ }\r
+ context.bind(allVars);\r
+ }\r
+\r
+ private boolean killAfterMatch() {\r
+ return literal.killAfterMatch && relation instanceof CHRConstraint;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning.items;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.common.names.Names;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.IterateListOp;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class MemberPrePlanItem extends PrePlanItem {\r
+ public Expression expression1, expression2;\r
+ public TIntHashSet variableSet1, variableSet2;\r
+\r
+ public MemberPrePlanItem(Expression expression1, Expression expression2, TIntHashSet variableSet1, TIntHashSet variableSet2, int secondaryPriority) {\r
+ super(secondaryPriority);\r
+ this.expression1 = expression1;\r
+ this.expression2 = expression2;\r
+ this.variableSet1 = variableSet1;\r
+ this.variableSet2 = variableSet2;\r
+ updatePrimaryPriority();\r
+ }\r
+\r
+ private void updatePrimaryPriority() {\r
+ if(variableSet2.isEmpty()) {\r
+ if(variableSet1.isEmpty())\r
+ primaryPriority = 0;\r
+ else \r
+ primaryPriority = 2.0;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void initializeListeners(QueryPlanningContext context) {\r
+ context.listen(variableSet1, this);\r
+ context.listen(variableSet2, this);\r
+ }\r
+\r
+ @Override\r
+ public void variableSolved(QueryPlanningContext context, int variableId) {\r
+ variableSet1.remove(variableId);\r
+ variableSet2.remove(variableId);\r
+ updatePrimaryPriority();\r
+ context.priorityQueue.adjust(this);\r
+ }\r
+\r
+ @Override\r
+ public void generate(QueryPlanningContext context) {\r
+ if(!variableSet2.isEmpty())\r
+ throw new InternalCompilerError("Unsolvable query.");\r
+ if(variableSet1.isEmpty())\r
+ context.addPlanOp(new CheckOp(location,\r
+ new EApply(location,\r
+ new EConstant(context.getCompilationContext().getValue(Names.Prelude_elem)),\r
+ expression1,\r
+ expression2)));\r
+ else\r
+ context.addPlanOp(new IterateListOp(location, ((EVariable)expression1).getVariable(), expression2));\r
+ context.bind(variableSet1);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.relations;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.constants.JavaConstructor;\r
+import org.simantics.scl.compiler.constants.JavaMethod;\r
+import org.simantics.scl.compiler.constants.generic.CallJava;\r
+import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;\r
+import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef;\r
+import org.simantics.scl.compiler.constants.generic.ParameterStackItem;\r
+import org.simantics.scl.compiler.constants.generic.StackItem;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;\r
+import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;\r
+import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;\r
+import org.simantics.scl.compiler.internal.parsing.Symbol;\r
+import org.simantics.scl.compiler.types.TCon;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+import gnu.trove.map.hash.TIntObjectHashMap;\r
+\r
+public class CHRConstraint extends Symbol implements CHRRelation {\r
+ public final String name;\r
+ public final Type[] parameterTypes;\r
+ \r
+ public boolean implicitlyDeclared;\r
+\r
+ // Analysis\r
+ public int firstPriorityAdded;\r
+ public int lastPriorityAdded;\r
+ public int firstPriorityRemoved;\r
+ public int lastPriorityRemoved;\r
+ \r
+ // Transient info\r
+ public CHRRuleset parentRuleset;\r
+ public String factClassName;\r
+ public Type factType;\r
+ public TypeDesc factTypeDesc;\r
+ \r
+ public TCon typeConstructor;\r
+ public Constant constructor;\r
+ public Constant accessId;\r
+ public Constant[] accessors;\r
+ public Constant addProcedure;\r
+ public Constant removeProcedure;\r
+ public Constant isAlive;\r
+ \r
+ public TIntObjectHashMap<IndexInfo> indices;\r
+ \r
+ // Query plans\r
+ public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();\r
+ \r
+ public static class IndexInfo {\r
+ public final int indexMask;\r
+ public final String indexName;\r
+ public final Constant firstFact;\r
+ public final Constant nextFact;\r
+ \r
+ public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {\r
+ this.indexMask = indexMask;\r
+ this.indexName = indexName;\r
+ this.firstFact = firstFact;\r
+ this.nextFact = nextFact;\r
+ }\r
+ }\r
+ \r
+ public CHRConstraint(long location, String name, Type[] parameterTypes) {\r
+ this.location = location;\r
+ this.name = name;\r
+ this.parameterTypes = parameterTypes;\r
+ }\r
+\r
+ public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {\r
+ JavaTypeTranslator jtt = context.javaTypeTranslator;\r
+ \r
+ this.parentRuleset = parentRuleset;\r
+ this.factClassName = parentRuleset.storeClassName + "$" + name;\r
+ TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + name); \r
+ this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);\r
+ this.factTypeDesc = TypeDesc.forClass(factClassName);\r
+ \r
+ Type[] constructorTypes = new Type[parameterTypes.length+1];\r
+ constructorTypes[0] = Types.INTEGER;\r
+ for(int i=0;i<parameterTypes.length;++i)\r
+ constructorTypes[i+1] = parameterTypes[i];\r
+ this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);\r
+ this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},\r
+ null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null);\r
+ this.accessors = new Constant[parameterTypes.length];\r
+ for(int i=0;i<parameterTypes.length;++i)\r
+ this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},\r
+ null, new FieldRef(factClassName, "c" + i, jtt.toTypeDesc(parameterTypes[i])), null);\r
+ this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},\r
+ new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},\r
+ new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),\r
+ null);\r
+ \r
+ this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));\r
+ \r
+ if(context.module != null) // for unit testing\r
+ context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));\r
+ }\r
+\r
+ @Override\r
+ public TVar[] getTypeVariables() {\r
+ return TVar.EMPTY_ARRAY;\r
+ }\r
+\r
+ @Override\r
+ public Type[] getParameterTypes() {\r
+ return parameterTypes;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return name;\r
+ }\r
+ \r
+ public Collection<IndexInfo> getIndices() {\r
+ return indices.valueCollection();\r
+ }\r
+ \r
+ public boolean mayBeRemoved() {\r
+ return removeProcedure != null;\r
+ }\r
+\r
+ private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {\r
+ ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);\r
+ keyTypeList.add(parentRuleset.storeType);\r
+ for(int i=0;i<parameterTypes.length;++i)\r
+ if(((indexMask>>i)&1)==1)\r
+ keyTypeList.add(parameterTypes[i]);\r
+ String indexName = nameOfIndex(indexMask, parameterTypes.length);\r
+ Constant accessIndex;\r
+ if(indexMask == 0) {\r
+ accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType},\r
+ null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null);\r
+ }\r
+ else {\r
+ Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);\r
+ accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);\r
+ }\r
+ return new IndexInfo(\r
+ indexMask,\r
+ indexName,\r
+ accessIndex,\r
+ new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},\r
+ null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)\r
+ );\r
+ }\r
+\r
+ public Constant accessComponent(int i) {\r
+ return accessors[i];\r
+ }\r
+ \r
+ public IVal fetchFromIndex(CompilationContext context, int boundMask) {\r
+ IndexInfo indexInfo = indices.get(boundMask);\r
+ if(indexInfo == null) {\r
+ indexInfo = createIndexInfo(context, boundMask);\r
+ indices.put(boundMask, indexInfo);\r
+ }\r
+ return indexInfo.firstFact;\r
+ }\r
+\r
+ public Constant nextElement(CompilationContext context, int boundMask) {\r
+ IndexInfo indexInfo = indices.get(boundMask);\r
+ if(indexInfo == null) {\r
+ indexInfo = createIndexInfo(context, boundMask);\r
+ indices.put(boundMask, indexInfo);\r
+ }\r
+ return indexInfo.nextFact;\r
+ }\r
+\r
+ \r
+ public static String nameOfIndex(int indexMask, int length) {\r
+ char[] chars = new char[length];\r
+ for(int i=0;i<length;++i)\r
+ chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';\r
+ return new String(chars);\r
+ }\r
+\r
+ public void setMayBeRemoved() {\r
+ if(removeProcedure == null) {\r
+ removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},\r
+ new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},\r
+ new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),\r
+ null);\r
+ isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType);\r
+ }\r
+ }\r
+\r
+ public int getMinimumPriority() {\r
+ return plans.get(0).priority;\r
+ }\r
+ \r
+ public boolean isPassive() {\r
+ return plans.isEmpty();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.relations;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRelation;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+public class ExternalCHRRelation implements CHRRelation {\r
+ public final SCLRelation relation;\r
+\r
+ public ExternalCHRRelation(SCLRelation relation) {\r
+ this.relation = relation;\r
+ }\r
+\r
+ @Override\r
+ public TVar[] getTypeVariables() {\r
+ return relation.getTypeVariables();\r
+ }\r
+\r
+ @Override\r
+ public Type[] getParameterTypes() {\r
+ return relation.getParameterTypes();\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return relation.toString();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.relations;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRelation;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public enum SpecialCHRRelation implements CHRRelation { \r
+ EQUALS(A, A),\r
+ MEMBER(A, Types.list(A)),\r
+ CHECK(Types.BOOLEAN),\r
+ EXECUTE(Types.UNIT);\r
+ \r
+ private final TVar[] typeVariables;\r
+ private final Type[] parameterTypes;\r
+ \r
+ private SpecialCHRRelation(Type ... parameterTypes) {\r
+ this.typeVariables = Types.freeVarsArray(parameterTypes);\r
+ this.parameterTypes = parameterTypes;\r
+ }\r
+\r
+ @Override\r
+ public TVar[] getTypeVariables() {\r
+ return typeVariables;\r
+ }\r
+ \r
+ @Override\r
+ public Type[] getParameterTypes() {\r
+ return parameterTypes;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.relations;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRelation;\r
+import org.simantics.scl.compiler.internal.parsing.Symbol;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+public class UnresolvedCHRRelation extends Symbol implements CHRRelation {\r
+ public String name;\r
+\r
+ public UnresolvedCHRRelation(long location, String name) {\r
+ this.location = location;\r
+ this.name = name;\r
+ }\r
+\r
+ @Override\r
+ public Type[] getParameterTypes() {\r
+ throw new InternalCompilerError("Encountered unresolved CHRRelation during type checking.");\r
+ }\r
+\r
+ @Override\r
+ public TVar[] getTypeVariables() {\r
+ throw new InternalCompilerError("Encountered unresolved CHRRelation during type checking.");\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.translation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRQuery;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EBinary;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVar;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;\r
+import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;\r
+import org.simantics.scl.compiler.environment.AmbiguousNameException;\r
+import org.simantics.scl.compiler.environment.Environments;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.parsing.types.TypeAst;\r
+\r
+public class CHRTranslation {\r
+\r
+ private static CHRLiteral convertExpression(boolean isHead, Expression expression) {\r
+ if(isHead)\r
+ return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);\r
+ else\r
+ return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);\r
+ }\r
+\r
+ private static CHRLiteral convertConstraint(boolean remove, boolean negated, Expression expression) {\r
+ ArrayList<Expression> parameters = new ArrayList<Expression>(4);\r
+ while(expression instanceof EApply) {\r
+ EApply apply = (EApply)expression;\r
+ for(int i=apply.parameters.length-1;i>=0;--i)\r
+ parameters.add(apply.parameters[i]);\r
+ expression = apply.function;\r
+ }\r
+ EVar var = (EVar)expression;\r
+ Expression[] parametersArray = new Expression[parameters.size()];\r
+ for(int i=0,j=parametersArray.length-1;i<parametersArray.length;++i,--j)\r
+ parametersArray[i] = parameters.get(j);\r
+ return new CHRLiteral(expression.location, new UnresolvedCHRRelation(var.location, var.name), parametersArray, remove, negated);\r
+ }\r
+ \r
+ private static CHRLiteral convertListQualifier(TranslationContext context, boolean isHead, ListQualifier qualifier) {\r
+ if(qualifier instanceof ListGuard) {\r
+ Expression originalExpression = ((ListGuard)qualifier).condition;\r
+ if(originalExpression instanceof EVar && ((EVar)originalExpression).name.equals("True"))\r
+ return null;\r
+ Expression currentExpression = originalExpression;\r
+ boolean remove = false;\r
+ boolean negated = false;\r
+ if(currentExpression instanceof EBinary) {\r
+ EBinary binary = (EBinary)currentExpression;\r
+ if(binary.negation==null || !binary.rights.isEmpty())\r
+ return convertExpression(isHead, originalExpression);\r
+ currentExpression = binary.left;\r
+ remove = true;\r
+ }\r
+ else if(currentExpression instanceof EApply) {\r
+ EApply apply = (EApply)currentExpression;\r
+ if(apply.function instanceof EVar && ((EVar)apply.function).name.equals("not")) {\r
+ negated = true;\r
+ if(apply.parameters.length == 1)\r
+ currentExpression = apply.parameters[0];\r
+ else {\r
+ currentExpression = new EApply(\r
+ Locations.combine(apply.parameters[0].location, apply.parameters[apply.parameters.length-1].location),\r
+ apply.parameters[0],\r
+ Arrays.copyOfRange(apply.parameters, 1, apply.parameters.length));\r
+ }\r
+ }\r
+ }\r
+ if(isConstraint(context, currentExpression))\r
+ return convertConstraint(remove, negated, currentExpression);\r
+ else\r
+ return convertExpression(isHead, originalExpression);\r
+ }\r
+ else if(qualifier instanceof ListAssignment) {\r
+ ListAssignment assignment = (ListAssignment)qualifier;\r
+ return new CHRLiteral(assignment.location, SpecialCHRRelation.EQUALS, new Expression[] {\r
+ assignment.pattern, assignment.value \r
+ }, false, false);\r
+ }\r
+ else if(qualifier instanceof ListGenerator) {\r
+ ListGenerator generator = (ListGenerator)qualifier;\r
+ return new CHRLiteral(generator.location, SpecialCHRRelation.MEMBER, new Expression[] {\r
+ generator.pattern, generator.value\r
+ }, false, false);\r
+ }\r
+ else {\r
+ context.getErrorLog().log(qualifier.location, "Invalid CHR literal.");\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ private static boolean isConstraint(TranslationContext context, Expression expression) {\r
+ while(expression instanceof EApply)\r
+ expression = ((EApply)expression).function;\r
+ if(!(expression instanceof EVar))\r
+ return false;\r
+ String name = ((EVar)expression).name;\r
+ if(TranslationContext.isConstructorName(name))\r
+ return true;\r
+ try {\r
+ return Environments.getRelation(context.getEnvironment(), name) != null;\r
+ } catch (AmbiguousNameException e) {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) {\r
+ ArrayList<CHRLiteral> head = new ArrayList<CHRLiteral>(statement.head.length);\r
+ for(ListQualifier qualifier : statement.head) {\r
+ CHRLiteral literal = convertListQualifier(context, true, qualifier);\r
+ if(literal != null)\r
+ head.add(literal);\r
+ }\r
+ ArrayList<CHRLiteral> body = new ArrayList<CHRLiteral>(statement.body.length);\r
+ for(ListQualifier qualifier : statement.body) {\r
+ CHRLiteral literal = convertListQualifier(context, false, qualifier);\r
+ if(literal != null)\r
+ body.add(literal);\r
+ }\r
+ return new CHRRule(statement.location,\r
+ new CHRQuery(head.toArray(new CHRLiteral[head.size()])),\r
+ new CHRQuery(body.toArray(new CHRLiteral[body.size()])),\r
+ null);\r
+ }\r
+\r
+ public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) {\r
+ return new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));\r
+ }\r
+ \r
+}\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.elaboration.expressions.Case;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import gnu.trove.map.hash.THashMap;
public class SimplificationContext implements EnvironmentalContext {
+ CompilationContext compilationContext;
Environment environment;
ErrorLog errorLog;
- public static final Name MAP_LIST = Name.create("Prelude", "mapList");
- public static final Name GUARD_LIST = Name.create("Prelude", "guardList");
- public static final Name CONCAT_MAP = Name.create("Prelude", "concatMap");
- public static final Name EMPTY_LIST = Name.create("Prelude", "emptyList");
- public static final Name SINGLETON_LIST = Name.create("Prelude", "singletonList");
- public static final Name APPEND_LIST = Name.create("Prelude", "appendList");
- public static final Name ADD_LIST = Name.create("Prelude", "addList");
- public static final Name FROM_INTEGER = Name.create("Prelude", "fromInteger");
- public static final Name FROM_DOUBLE = Name.create("Prelude", "fromDouble");
-
THashMap<Name, SCLValue> constants = new THashMap<Name, SCLValue>();
THashMap<Variable, Expression> inlinedVariables = new THashMap<Variable, Expression>();
JavaTypeTranslator javaTypeTranslator;
JavaReferenceValidator<?, ?, ?, ?> validator;
- public SimplificationContext(Environment environment, ErrorLog errorLog,
- JavaTypeTranslator javaTypeTranslator, JavaReferenceValidator<?, ?, ?, ?> validator) {
- this.environment = environment;
- this.errorLog = errorLog;
- this.javaTypeTranslator = javaTypeTranslator;
+ public SimplificationContext(CompilationContext compilationContext, JavaReferenceValidator<?, ?, ?, ?> validator) {
+ this.compilationContext = compilationContext;
+ this.environment = compilationContext.environment;
+ this.errorLog = compilationContext.errorLog;
+ this.javaTypeTranslator = compilationContext.javaTypeTranslator;
this.validator = validator;
}
public Expression mapList(Expression f, Expression l) {
try {
MultiFunction mfun = Types.matchFunction(f.getType(), 1);
- return apply(getConstant(MAP_LIST, new Type[] {mfun.parameterTypes[0], mfun.returnType}), f, l);
+ return apply(getConstant(Names.Prelude_mapList, new Type[] {mfun.parameterTypes[0], mfun.returnType}), f, l);
} catch (MatchException e) {
throw new InternalCompilerError(e);
}
}
public Expression guardList(Expression cond) {
- return apply(getConstant(GUARD_LIST), cond);
+ return apply(getConstant(Names.Prelude_guardList), cond);
}
public Expression concatMap(Expression f, Expression l) {
try {
MultiFunction mfun = Types.matchFunction(f.getType(), 1);
- return apply(getConstant(CONCAT_MAP, new Type[] {
+ return apply(getConstant(Names.Prelude_concatMap, new Type[] {
mfun.parameterTypes[0], mfun.effect,
Types.matchApply(Types.LIST, mfun.returnType)}
), f, l);
}
public Expression emptyList(Type type) {
- return getConstant(EMPTY_LIST, type);
+ return getConstant(Names.Prelude_emptyList, type);
}
public Expression singletonList(Expression e) {
- return apply(getConstant(SINGLETON_LIST, e.getType()), e);
+ return apply(getConstant(Names.Prelude_singletonList, e.getType()), e);
}
public Expression match(Expression scrutinee, Expression pattern, Expression value) {
return new EApply(
Locations.NO_LOCATION,
Types.PROC,
- getConstant(Name.create("Prelude", "iterList"), variable.getType(), Types.PROC, Types.tupleConstructor(0)),
+ getConstant(Names.Prelude_iterList, variable.getType(), Types.PROC, Types.tupleConstructor(0)),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
list
return new EApply(
Locations.NO_LOCATION,
Types.PROC,
- getConstant(Name.create("Vector", "iterVector"), variable.getType(), Types.PROC, Types.tupleConstructor(0)),
+ getConstant(Names.Vector_iterVector, variable.getType(), Types.PROC, Types.tupleConstructor(0)),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
vector
result[i] = new EVariable(parameters[i]);
return result;
}
+
+ public CompilationContext getCompilationContext() {
+ return compilationContext;
+ }
}
\ No newline at end of file
import java.util.Arrays;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.common.precedence.Associativity;
import org.simantics.scl.compiler.common.precedence.Precedence;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
import org.simantics.scl.compiler.elaboration.expressions.Case;
import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
import org.simantics.scl.compiler.elaboration.expressions.EConstant;
import org.simantics.scl.compiler.elaboration.query.pre.PreQuery;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.environment.AmbiguousNameException;
-import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.environment.Environments;
import org.simantics.scl.compiler.environment.LocalEnvironment;
import org.simantics.scl.compiler.environment.Namespace;
import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;
-import org.simantics.scl.compiler.errors.ErrorLog;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
TIntArrayList relationFrames = new TIntArrayList();
ArrayList<RelationEntry> relationEntries = new ArrayList<RelationEntry>();
+ THashMap<String, CHRConstraint> chrConstraints = new THashMap<String, CHRConstraint>();
+ TIntArrayList chrConstraintFrames = new TIntArrayList();
+ ArrayList<CHRConstraintEntry> chrConstraintEntries = new ArrayList<CHRConstraintEntry>();
+
static class Entry {
String name;
Variable variable;
}
}
- public TranslationContext(ErrorLog errorLog,
- Environment environment, LocalEnvironment localEnvironment) {
- super(errorLog, environment);
+ static class CHRConstraintEntry {
+ String name;
+ CHRConstraint constraint;
+ public CHRConstraintEntry(String name, CHRConstraint constraint) {
+ this.name = name;
+ this.constraint = constraint;
+ }
+ }
+
+ public TranslationContext(CompilationContext compilationContext, LocalEnvironment localEnvironment) {
+ super(compilationContext);
this.localEnvironment = localEnvironment;
}
public static boolean isConstructorName(String name) {
- char firstChar = name.charAt(0);
+ int p = name.lastIndexOf('.');
+ char firstChar = name.charAt(p<0 ? 0 : p+1);
return Character.isUpperCase(firstChar);
}
}
}
+ public void pushCHRConstraintFrame() {
+ chrConstraintFrames.add(chrConstraintEntries.size());
+ }
+
+ public void popCHRConstraintFrame(ArrayList<CHRConstraint> constraints) {
+ int frame = chrConstraintFrames.removeAt(chrConstraintFrames.size()-1);
+ int i = chrConstraintEntries.size();
+ while(i > frame) {
+ --i;
+ CHRConstraintEntry entry = chrConstraintEntries.remove(i);
+ CHRConstraint newConstraint;
+ if(entry.constraint == null)
+ newConstraint = chrConstraints.remove(entry.name);
+ else
+ newConstraint = chrConstraints.put(entry.name, entry.constraint);
+ if(newConstraint.implicitlyDeclared)
+ constraints.add(newConstraint);
+ }
+ }
+
public void pushExistentialFrame() {
pushFrame();
existentialFrames.add(new THashSet<String>());
SCLRelation oldRelation = relations.put(name, relation);
relationEntries.add(new RelationEntry(name, oldRelation));
}
+
+ public void newCHRConstraint(String name, CHRConstraint constraint) {
+ CHRConstraint oldConstraint = chrConstraints.put(name, constraint);
+ chrConstraintEntries.add(new CHRConstraintEntry(name, oldConstraint));
+ }
public Precedence getPrecedence(Name op) {
Precedence prec = environment.getValue(op).getPrecedence();
}
private SCLValue resolveValueIn(long location, Namespace namespace, final String name) throws AmbiguousNameException {
- SCLValue value = namespace.getValue(name);
- if(value == null) {
- StringBuilder message = new StringBuilder();
- message.append("Couldn't resolve variable ").append(name).append(".");
-
- final THashSet<String> candidateNames = new THashSet<String>(4);
- namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE,
- new TObjectProcedure<SCLValue>() {
- @Override
- public boolean execute(SCLValue value) {
- if(value == null) {
- new Exception().printStackTrace();
- return true;
- }
- String valueName = value.getName().name;
- if(name.equalsIgnoreCase(valueName))
- candidateNames.add(valueName);
- return true;
- }
- });
- if(localEnvironment != null)
- localEnvironment.forNames(new TObjectProcedure<String>() {
- @Override
- public boolean execute(String valueName) {
- if(name.equalsIgnoreCase(valueName))
- candidateNames.add(valueName);
- return true;
- }
- });
-
- if(candidateNames.size() > 0) {
- message.append(" Did you mean ");
- String[] ns = candidateNames.toArray(new String[candidateNames.size()]);
- Arrays.sort(ns);
- for(int i=0;i<ns.length;++i) {
- if(i > 0) {
- message.append(", ");
- if(i == ns.length-1)
- message.append("or ");
- }
- message.append(ns[i]);
+ SCLValue value = namespace.getValue(name);
+ if(value == null) {
+ StringBuilder message = new StringBuilder();
+ message.append("Couldn't resolve variable ").append(name).append(".");
+
+ final THashSet<String> candidateNames = new THashSet<String>(4);
+ namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE,
+ new TObjectProcedure<SCLValue>() {
+ @Override
+ public boolean execute(SCLValue value) {
+ if(value == null) {
+ new Exception().printStackTrace();
+ return true;
}
- message.append('?');
+ String valueName = value.getName().name;
+ if(name.equalsIgnoreCase(valueName))
+ candidateNames.add(valueName);
+ return true;
}
-
- errorLog.log(location, message.toString());
- return null;
+ });
+ if(localEnvironment != null)
+ localEnvironment.forNames(new TObjectProcedure<String>() {
+ @Override
+ public boolean execute(String valueName) {
+ if(name.equalsIgnoreCase(valueName))
+ candidateNames.add(valueName);
+ return true;
+ }
+ });
+
+ if(candidateNames.size() > 0) {
+ message.append(" Did you mean ");
+ String[] ns = candidateNames.toArray(new String[candidateNames.size()]);
+ Arrays.sort(ns);
+ for(int i=0;i<ns.length;++i) {
+ if(i > 0) {
+ message.append(", ");
+ if(i == ns.length-1)
+ message.append("or ");
+ }
+ message.append(ns[i]);
+ }
+ message.append('?');
}
- return value;
+
+ errorLog.log(location, message.toString());
+ return null;
+ }
+ return value;
}
public Case translateCase(Expression lhs, Expression rhs) {
cases);
}
- private static final Name BIND = Name.create("Prelude", ">>=");
-
public SCLValue getBindFunction() {
if(bindFunction == null) {
- bindFunction = getEnvironment().getValue(BIND);
+ bindFunction = getEnvironment().getValue(Names.Prelude_bind);
}
return bindFunction;
}
return null;
}
}
+
+ public CHRConstraint resolveCHRConstraint(String name) {
+ return chrConstraints.get(name);
+ }
@Override
public SCLValue getValue(Name name) {
package org.simantics.scl.compiler.elaboration.contexts;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.errors.ErrorLog;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
public class TypeTranslationContext {
+ CompilationContext compilationContext;
+
Environment environment;
ErrorLog errorLog;
THashMap<String, TVar> typeVariables = new THashMap<String, TVar>();
- public TypeTranslationContext(ErrorLog errorLog, Environment environment) {
- this.errorLog = errorLog;
- this.environment = environment;
+ public TypeTranslationContext(CompilationContext compilationContext) {
+ this.compilationContext = compilationContext;
+ this.errorLog = compilationContext.errorLog;
+ this.environment = compilationContext.environment;
}
/**
}
public Kind getKind(TCon con) {
- return environment.getTypeConstructor(con).kind;
+ return environment.getTypeDescriptor(con).getKind();
}
/**
import java.util.ArrayList;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.constants.NoRepConstant;
import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
-import org.simantics.scl.compiler.elaboration.expressions.EConstant;
-import org.simantics.scl.compiler.elaboration.expressions.EError;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.errors.ErrorLog;
-import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint;
import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintEnvironment;
import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintSolver;
import gnu.trove.map.hash.THashMap;
import gnu.trove.set.hash.THashSet;
-public class TypingContext implements EnvironmentalContext {
+public class TypingContext {
- private ErrorLog errorLog;
+ private CompilationContext compilationContext;
// Subsumption
private ArrayList<Subsumption> effectSubsumptions = new ArrayList<Subsumption>();
//TypeUnparsingContext tuc = new TypeUnparsingContext();
Environment environment;
- THashMap<Name, SCLValue> constants = new THashMap<Name, SCLValue>();
- public TypingContext(ErrorLog errorLog, Environment environment) {
- this.errorLog = errorLog;
- this.environment = environment;
+ public TypingContext(CompilationContext compilationContext) {
+ this.compilationContext = compilationContext;
+ this.environment = compilationContext.environment;
}
/**
try {
Types.unify(a, Types.NO_EFFECTS);
} catch(UnificationException e) {
- errorLog.log(loc, "No side-effects allowed here.");
+ compilationContext.errorLog.log(loc, "No side-effects allowed here.");
return;
}
}
try {
subsume(sub.loc, a, b);
} catch (UnificationException e) {
- errorLog.log(sub.loc, "Type " + a + " is not a subtype of " + b + ".");
+ compilationContext.errorLog.log(sub.loc, "Type " + a + " is not a subtype of " + b + ".");
}
nontrivialSubs = true;
}
try {
Types.unify(sub.a, sub.b);
} catch (UnificationException e) {
- errorLog.log(sub.loc, "Unification of types failed.");
+ compilationContext.errorLog.log(sub.loc, "Unification of types failed.");
return false;
}
if(type instanceof TMetaVar)
return ((TMetaVar)type).getKind() == Kinds.EFFECT;
else if(type instanceof TCon)
- return environment.getTypeConstructor((TCon)type).kind == Kinds.EFFECT;
+ return environment.getTypeDescriptor((TCon)type).getKind() == Kinds.EFFECT;
else if(type instanceof TVar)
return ((TVar)type).getKind() == Kinds.EFFECT;
else if(type instanceof TUnion)
public void solveSubsumptions(long globalLoc) {
if(expandSubsumptions())
- new SubSolver(errorLog, effectSubsumptions, potentialSingletonEffects, globalLoc).solve();
+ new SubSolver(compilationContext.errorLog, effectSubsumptions, potentialSingletonEffects, globalLoc).solve();
}
public void declareEffect(long loc, Type effect) {
}
public ErrorLog getErrorLog() {
- return errorLog;
+ return compilationContext.errorLog;
}
public boolean isInPattern() {
public void typeError(long loc, Type requiredType, Type givenType) {
TypeUnparsingContext tuc = new TypeUnparsingContext();
- errorLog.log(loc, "Expected <" + requiredType.toString(tuc) + "> got <" + givenType.toString(tuc) + ">.");
+ compilationContext.errorLog.log(loc, "Expected <" + requiredType.toString(tuc) + "> got <" + givenType.toString(tuc) + ">.");
}
public Expression solveConstraints(Environment environment, Expression expression) {
expression);
for(Constraint c : red.unsolvedConstraints)
- errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">.");
+ compilationContext.errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">.");
}
else
expression = expression.decomposeMatching();
return expression;
}
-
- public SCLValue getValue(Name name) {
- if(constants.containsKey(name))
- return constants.get(name);
- SCLValue value = environment.getValue(name);
- if(value == null)
- errorLog.log(Locations.NO_LOCATION, "Couldn't find " + name + ".");
- constants.put(name, value);
- return value;
- }
-
- public Expression getConstant(Name name, Type ... typeParameters) {
- SCLValue value = getValue(name);
- if(value == null)
- return new EError(Locations.NO_LOCATION);
- return new EConstant(value, typeParameters);
- }
public Environment getEnvironment() {
- return environment;
+ return compilationContext.environment;
+ }
+
+ public CompilationContext getCompilationContext() {
+ return compilationContext;
}
}
import gnu.trove.set.hash.TIntHashSet;\r
\r
public class EApply extends Expression {\r
- Expression function;\r
- Expression[] parameters;\r
+ public Expression function;\r
+ public Expression[] parameters;\r
Type effect = Types.NO_EFFECTS;\r
\r
public EApply(Expression function, Expression ... parameters) {\r
public Expression accept(ExpressionTransformer transformer) {\r
return transformer.transform(this);\r
}\r
+ \r
+ @Override\r
+ public boolean equalsExpression(Expression expression) {\r
+ if(expression.getClass() != getClass())\r
+ return false;\r
+ EApply other = (EApply)expression;\r
+ if(parameters.length != other.parameters.length)\r
+ return false;\r
+ if(!function.equalsExpression(other.function))\r
+ return false;\r
+ for(int i=0;i<parameters.length;++i)\r
+ if(!parameters[i].equalsExpression(other.parameters[i]))\r
+ return false;\r
+ return true;\r
+ }\r
}\r
\r
@Override\r
public void collectFreeVariables(THashSet<Variable> vars) {\r
- vars.add(var);\r
- pattern.collectFreeVariables(vars);\r
+ throw new InternalCompilerError(location, "Cannot collect free variables for a pattern.");\r
+ }\r
+ \r
+ @Override\r
+ public void removeFreeVariables(THashSet<Variable> vars) {\r
+ vars.remove(var);\r
+ pattern.removeFreeVariables(vars);\r
}\r
\r
@Override\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.common.precedence.Associativity;\r
import org.simantics.scl.compiler.common.precedence.Precedence;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
public Expression resolve(TranslationContext context) {\r
return parseOperators(context).resolve(context);\r
}\r
-\r
- private static final Name NEG = Name.create("Prelude", "neg");\r
\r
public Expression parseOperators(TranslationContext context) {\r
ArrayList<Expression> output = new ArrayList<Expression>();\r
}\r
if(negation != null && ops.isEmpty()) {\r
if(opPrec.level <= NEGATION_LEVEL) { \r
- SCLValue neg = context.getEnvironment().getValue(NEG);\r
+ SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);\r
if(neg == null) {\r
context.getErrorLog().log(location, \r
"Couldn't resolve variable neg.");\r
output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));\r
}\r
if(negation != null) {\r
- SCLValue neg = context.getEnvironment().getValue(NEG);\r
+ SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);\r
if(neg == null) {\r
context.getErrorLog().log(location, \r
"Couldn't resolve variable neg.");\r
import java.util.List;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
+import org.simantics.scl.compiler.elaboration.expressions.block.StatementGroup;
import org.simantics.scl.compiler.errors.Locations;
public class EBlock extends ASTExpression {
@Override
public Expression resolve(TranslationContext context) {
- if(statements.isEmpty()) {
- context.getErrorLog().log(location, "Block must contain at least one statement.");
- return new EError(location);
- }
+ if(statements.isEmpty())
+ throw new InternalCompilerError();
int i = statements.size()-1;
Statement last = statements.get(i);
if(!(last instanceof GuardStatement)) {
Expression in = ((GuardStatement)last).value;
while(--i >= 0) {
Statement cur = statements.get(i);
- if(cur instanceof RuleStatement) {
- int endId = i+1;
- while(i>0 && statements.get(i-1) instanceof RuleStatement)
- --i;
- in = extractRules(i, endId, in);
- }
- else if(cur instanceof LetStatement && ((LetStatement)cur).pattern.isFunctionPattern()) {
+ StatementGroup group = cur.getStatementGroup();
+ if(group == null)
+ in = cur.toExpression(context, monadic, in);
+ else {
int endId = i+1;
- while(i>0 && (cur = statements.get(i-1)) instanceof LetStatement &&
- ((LetStatement)cur).pattern.isFunctionPattern())
+ while(i>0 && statements.get(i-1).getStatementGroup() == group)
--i;
- in = extractLet(i, endId, in);
+ switch(group) {
+ case LetFunction:
+ in = extractLet(i, endId, in);
+ break;
+ case Rule:
+ in = extractRules(i, endId, in);
+ break;
+ case CHR:
+ in = extractCHRRules(context, i, endId, in);
+ break;
+ }
}
- else
- in = cur.toExpression(context, monadic, in);
}
return in.resolve(context);
}
private Expression extractRules(int begin, int end, Expression in) {
return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in);
}
+
+ private Expression extractCHRRules(TranslationContext context, int begin, int end, Expression in) {
+ CHRRuleset ruleset = new CHRRuleset();
+ ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location);
+ for(int i=begin;i<end;++i) {
+ Statement statement = statements.get(i);
+ if(statement instanceof CHRStatement)
+ ruleset.rules.add(CHRTranslation.convertCHRStatement(context, (CHRStatement)statement));
+ else if(statement instanceof ConstraintStatement)
+ ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
+ else
+ throw new InternalCompilerError("Invalid CHR statement.");
+ }
+ return new ECHRRuleset(ruleset, in);
+ }
@SuppressWarnings("unchecked")
private Expression extractLet(int begin, int end, Expression in) {
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
+import org.simantics.scl.compiler.environment.Environment;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
+import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.exceptions.MatchException;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class ECHRRuleset extends Expression {\r
+ CHRRuleset ruleset;\r
+ Expression in;\r
+ \r
+ public ECHRRuleset(CHRRuleset ruleset, Expression in) {\r
+ this.ruleset = ruleset;\r
+ this.in = in;\r
+ }\r
+ \r
+ @Override\r
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
+ ruleset.collectRefs(allRefs, refs);\r
+ in.collectRefs(allRefs, refs);\r
+ }\r
+ @Override\r
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
+ ruleset.collectVars(allVars, vars);\r
+ in.collectVars(allVars, vars);\r
+ }\r
+ @Override\r
+ public void forVariables(VariableProcedure procedure) {\r
+ ruleset.forVariables(procedure);\r
+ in.forVariables(procedure);\r
+ }\r
+ @Override\r
+ protected void updateType() throws MatchException {\r
+ setType(in.getType());\r
+ }\r
+ @Override\r
+ public IVal toVal(Environment env, CodeWriter w) {\r
+ ruleset.generateCode(w);\r
+ return in.toVal(env, w);\r
+ }\r
+ @Override\r
+ public void collectFreeVariables(THashSet<Variable> vars) {\r
+ ruleset.collectFreeVariables(vars);\r
+ in.collectFreeVariables(vars);\r
+ }\r
+ @Override\r
+ public Expression resolve(TranslationContext context) {\r
+ context.pushFrame();\r
+ context.pushCHRConstraintFrame();\r
+ ruleset.resolve(context);\r
+ in = in.resolve(context);\r
+ context.popCHRConstraintFrame(ruleset.constraints);\r
+ context.popFrame();\r
+ return this;\r
+ }\r
+ @Override\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ this.location = loc;\r
+ ruleset.setLocationDeep(loc);\r
+ in.setLocationDeep(loc);\r
+ }\r
+ }\r
+ @Override\r
+ public Expression decorate(ExpressionDecorator decorator) {\r
+ in = in.decorate(decorator);\r
+ return this;\r
+ }\r
+ @Override\r
+ public void collectEffects(THashSet<Type> effects) {\r
+ ruleset.collectEffects(effects);\r
+ in.collectEffects(effects);\r
+ }\r
+ @Override\r
+ public void accept(ExpressionVisitor visitor) {\r
+ visitor.visit(this);\r
+ }\r
+ \r
+ @Override\r
+ public Expression inferType(TypingContext context) {\r
+ ruleset.checkType(context);\r
+ in = in.inferType(context);\r
+ return this;\r
+ }\r
+ \r
+ @Override\r
+ public Expression simplify(SimplificationContext context) {\r
+ ruleset.simplify(context);\r
+ ruleset.compile(context);\r
+ in = in.simplify(context);\r
+ return this;\r
+ }\r
+ \r
+ @Override\r
+ public Expression accept(ExpressionTransformer transformer) {\r
+ return transformer.transform(this);\r
+ }\r
+ \r
+ @Override\r
+ public IExpression toIExpression(ExpressionInterpretationContext context) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+}\r
return this;\r
}\r
else\r
- return applyPUnit(context);\r
+ return applyPUnit(context.getCompilationContext());\r
}\r
\r
@Override\r
return transformer.transform(this);\r
}\r
\r
+ @Override\r
+ public boolean equalsExpression(Expression expression) {\r
+ if(expression.getClass() != getClass())\r
+ return false;\r
+ EConstant other = (EConstant)expression;\r
+ return value == other.value && Types.equals(typeParameters, other.typeParameters);\r
+ }\r
}\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
accessor.collectFreeVariables(vars);\r
}\r
\r
- private static final Name CHILD = Name.create("Simantics/Variables", "child_");\r
- private static final Name PROPERTY = Name.create("Simantics/Variables", "property");\r
- private static final Name PROPERTY_VALUE = Name.create("Simantics/Variables", "untypedPropertyValue");\r
-\r
@Override\r
public Expression simplify(SimplificationContext context) {\r
// Simplify subexpressions\r
result = new EApply(\r
getLocation(),\r
Types.READ_GRAPH,\r
- context.getConstant(CHILD),\r
+ context.getConstant(Names.Simantics_Variables_child_),\r
result,\r
accessor.asExpression()\r
);\r
result = new EApply(\r
getLocation(),\r
Types.READ_GRAPH,\r
- context.getConstant(PROPERTY),\r
+ context.getConstant(Names.Simantics_Variables_property),\r
result,\r
accessor.asExpression()\r
);\r
result = new EApply(\r
getLocation(),\r
Types.READ_GRAPH,\r
- context.getConstant(PROPERTY_VALUE, getType()),\r
+ context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),\r
result,\r
accessor.asExpression()\r
);\r
import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
+import org.simantics.scl.compiler.internal.interpreted.IConstant;\r
import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
import org.simantics.scl.compiler.internal.interpreted.IIf;\r
import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.Types;\r
import org.simantics.scl.compiler.types.exceptions.MatchException;\r
+import org.simantics.scl.runtime.tuple.Tuple0;\r
\r
import gnu.trove.map.hash.TObjectIntHashMap;\r
import gnu.trove.set.hash.THashSet;\r
public class EIf extends Expression {\r
public Expression condition;\r
public Expression then_;\r
- public Expression else_;\r
+ public Expression else_; // may be null\r
\r
public EIf(Expression condition, Expression then_, Expression else_) {\r
this.condition = condition;\r
public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
condition.collectRefs(allRefs, refs);\r
then_.collectRefs(allRefs, refs);\r
- else_.collectRefs(allRefs, refs);\r
+ if(else_ != null)\r
+ else_.collectRefs(allRefs, refs);\r
}\r
\r
@Override\r
TIntHashSet vars) {\r
condition.collectVars(allVars, vars);\r
then_.collectVars(allVars, vars);\r
- else_.collectVars(allVars, vars);\r
+ if(else_ != null)\r
+ else_.collectVars(allVars, vars);\r
}\r
\r
@Override\r
@Override\r
public IVal toVal(Environment env, CodeWriter w) {\r
IVal conditionVal = condition.toVal(env, w); \r
- \r
- CodeWriter thenBlock = w.createBlock();\r
- CodeWriter elseBlock = w.createBlock();\r
- \r
CodeWriter joinPoint = w.createBlock(getType());\r
- \r
- w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());\r
- \r
+ CodeWriter thenBlock = w.createBlock();\r
+ if(else_ != null) {\r
+ CodeWriter elseBlock = w.createBlock(); \r
+ w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());\r
+ \r
+ IVal elseVal = else_.toVal(env, elseBlock);\r
+ elseBlock.jump(joinPoint.getContinuation(), elseVal);\r
+ }\r
+ else {\r
+ w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());\r
+ }\r
IVal thenVal = then_.toVal(env, thenBlock);\r
thenBlock.jump(joinPoint.getContinuation(), thenVal);\r
- \r
- IVal elseVal = else_.toVal(env, elseBlock);\r
- elseBlock.jump(joinPoint.getContinuation(), elseVal);\r
- \r
w.continueAs(joinPoint);\r
\r
return w.getParameters()[0];\r
public void collectFreeVariables(THashSet<Variable> vars) {\r
condition.collectFreeVariables(vars);\r
then_.collectFreeVariables(vars);\r
- else_.collectFreeVariables(vars);\r
+ if(else_ != null)\r
+ else_.collectFreeVariables(vars);\r
}\r
\r
@Override\r
public Expression simplify(SimplificationContext context) {\r
condition = condition.simplify(context);\r
then_ = then_.simplify(context);\r
- else_ = else_.simplify(context);\r
+ if(else_ != null)\r
+ else_ = else_.simplify(context);\r
return this;\r
}\r
\r
public Expression resolve(TranslationContext context) {\r
condition = condition.resolve(context);\r
then_ = then_.resolve(context);\r
- else_ = else_.resolve(context);\r
+ if(else_ != null)\r
+ else_ = else_.resolve(context);\r
return this;\r
}\r
\r
public Expression replace(ReplaceContext context) {\r
return new EIf(condition.replace(context), \r
then_.replace(context), \r
- else_.replace(context));\r
+ else_ == null ? null : else_.replace(context));\r
}\r
\r
@Override\r
public Expression checkBasicType(TypingContext context, Type requiredType) {\r
condition = condition.checkType(context, Types.BOOLEAN);\r
then_ = then_.checkType(context, requiredType);\r
- else_ = else_.checkType(context, requiredType);\r
+ if(else_ != null)\r
+ else_ = else_.checkType(context, requiredType);\r
+ else\r
+ context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");\r
return this;\r
}\r
\r
public Expression checkIgnoredType(TypingContext context) {\r
condition = condition.checkType(context, Types.BOOLEAN);\r
then_ = then_.checkIgnoredType(context);\r
- else_ = else_.checkIgnoredType(context);\r
+ if(else_ != null)\r
+ else_ = else_.checkIgnoredType(context);\r
return this;\r
}\r
\r
public Expression decorate(ExpressionDecorator decorator) {\r
condition = condition.decorate(decorator);\r
then_ = then_.decorate(decorator);\r
- else_ = else_.decorate(decorator); \r
+ if(else_ != null)\r
+ else_ = else_.decorate(decorator); \r
return decorator.decorate(this);\r
}\r
\r
@Override\r
public boolean isEffectful() {\r
- return condition.isEffectful() || then_.isEffectful() || else_.isEffectful();\r
+ return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());\r
}\r
\r
@Override\r
public void collectEffects(THashSet<Type> effects) {\r
condition.collectEffects(effects);\r
then_.collectEffects(effects);\r
- else_.collectEffects(effects);\r
+ if(else_ != null)\r
+ else_.collectEffects(effects);\r
}\r
\r
@Override\r
location = loc;\r
condition.setLocationDeep(loc);\r
then_.setLocationDeep(loc);\r
- else_.setLocationDeep(loc);\r
+ if(else_ != null)\r
+ else_.setLocationDeep(loc);\r
}\r
}\r
\r
\r
@Override\r
public IExpression toIExpression(ExpressionInterpretationContext target) {\r
- return new IIf(condition.toIExpression(target), then_.toIExpression(target), else_.toIExpression(target));\r
- }\r
- \r
- public Expression getCondition() {\r
- return condition;\r
- }\r
- \r
- public Expression getThen() {\r
- return then_;\r
- }\r
- \r
- public Expression getElse() {\r
- return else_;\r
+ return new IIf(condition.toIExpression(target), then_.toIExpression(target), \r
+ else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));\r
}\r
\r
@Override\r
public void forVariables(VariableProcedure procedure) {\r
condition.forVariables(procedure);\r
then_.forVariables(procedure);\r
- else_.forVariables(procedure);\r
+ if(else_ != null)\r
+ else_.forVariables(procedure);\r
}\r
@Override\r
public Expression accept(ExpressionTransformer transformer) {\r
\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.constants.DoubleConstant;\r
import org.simantics.scl.compiler.constants.FloatConstant;\r
import org.simantics.scl.compiler.constants.IntegerConstant;\r
if(primitive != null)\r
return primitive;\r
return context.apply(\r
- context.getConstant(SimplificationContext.FROM_INTEGER, getType()),\r
+ context.getConstant(Names.Prelude_fromInteger, getType()),\r
constraint.simplify(context),\r
context.literal(new IntegerConstant(Integer.parseInt(value)))\r
);\r
return transformer.transform(this);\r
}\r
\r
+ @Override\r
+ public boolean equalsExpression(Expression expression) {\r
+ if(expression.getClass() != getClass())\r
+ return false;\r
+ ELiteral other = (ELiteral)expression;\r
+ return value.equals(other.value);\r
+ }\r
+\r
}\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
import org.simantics.scl.compiler.errors.Locations;\r
this.from = from;\r
this.to = to;\r
}\r
-\r
- private static final Name RANGE = Name.create("Prelude", "range");\r
\r
@Override\r
public Expression resolve(TranslationContext context) {\r
from = from.resolve(context);\r
to = to.resolve(context);\r
- SCLValue rangeFunction = context.getEnvironment().getValue(RANGE);\r
+ SCLValue rangeFunction = context.getEnvironment().getValue(Names.Prelude_range);\r
return new EApply(location, new EConstant(rangeFunction), from, to);\r
} \r
\r
\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.constants.DoubleConstant;\r
import org.simantics.scl.compiler.constants.FloatConstant;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
if(primitive != null)\r
return primitive;\r
return context.apply(\r
- context.getConstant(SimplificationContext.FROM_DOUBLE, getType()),\r
+ context.getConstant(Names.Prelude_fromDouble, getType()),\r
constraint.simplify(context),\r
context.literal(new DoubleConstant(Double.parseDouble(value)))\r
);\r
import java.util.Set;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
import org.simantics.scl.compiler.internal.elaboration.utils.ForcedClosure;\r
import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;\r
import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
-import org.simantics.scl.compiler.types.TCon;\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.Types;\r
import org.simantics.scl.compiler.types.exceptions.MatchException;\r
Variable handleFunc;\r
}\r
\r
- public static final TCon MSet = Types.con("MSet", "T");\r
- private static final Name MSet_add = Name.create("MSet", "add");\r
- private static final Name MSet_create = Name.create("MSet", "create");\r
-\r
- private static final TCon MList = Types.con("MList", "T");\r
- private static final Name MList_add = Name.create("MList", "add");\r
- private static final Name MList_create = Name.create("MList", "create");\r
- private static final Name MList_removeLast = Name.create("MList", "removeLast");\r
- \r
public Expression compile(TypingContext context) {\r
// Create a map from relations to their ids\r
TObjectIntHashMap<SCLRelation> relationsToIds = new TObjectIntHashMap<SCLRelation>(relations.length,\r
LocalRelation relation = relations[i];\r
Type[] parameterTypes = relation.getParameterTypes();\r
stacks[i] = newVar("stack" + relation.getName(),\r
- Types.apply(MList, Types.tuple(parameterTypes))\r
+ Types.apply(Names.MList_T, Types.tuple(parameterTypes))\r
);\r
}\r
\r
ArrayList<Expression> seedExpressions = new ArrayList<Expression>(); \r
for(DatalogRule rule : rules) {\r
int id = diffables.get(rule.headRelation).id;\r
- Expression appendExp = apply(context, Types.PROC, MList_add, Types.tuple(rule.headRelation.getParameterTypes()),\r
+ Expression appendExp = apply(context.getCompilationContext(), Types.PROC, Names.MList_add, Types.tuple(rule.headRelation.getParameterTypes()),\r
var(stacks[id]),\r
tuple(rule.headParameters)\r
);\r
for(Expression updateExpression : updateExpressions[i])\r
handleRow = seq(updateExpression, handleRow);\r
handleRow = if_(\r
- apply(context, Types.PROC, MSet_add, rowType,\r
+ apply(context.getCompilationContext(), Types.PROC, Names.MSet_add, rowType,\r
var(relation.table), var(row)),\r
handleRow,\r
tuple()\r
apply(Types.PROC, var(loops[(i+1)%relations.length]), addInteger(var(counter), integer(-1)))\r
);\r
Expression body = matchWithDefault(\r
- apply(context, Types.PROC, MList_removeLast, rowType, var(stacks[i])),\r
+ apply(context.getCompilationContext(), Types.PROC, Names.MList_removeLast, rowType, var(stacks[i])),\r
Just(as(row, tuple(vars(parameters)))), handleRow,\r
failure);\r
\r
// Create stacks\r
for(int i=0;i<stacks.length;++i)\r
continuation = let(stacks[i],\r
- apply(context, Types.PROC, MList_create, Types.tuple(relations[i].getParameterTypes()), tuple()),\r
+ apply(context.getCompilationContext(), Types.PROC, Names.MList_create, Types.tuple(relations[i].getParameterTypes()), tuple()),\r
continuation);\r
\r
continuation = ForcedClosure.forceClosure(continuation, SCLCompilerConfiguration.EVERY_DATALOG_STRATUM_IN_SEPARATE_METHOD);\r
// Create relations\r
for(LocalRelation relation : relations)\r
continuation = let(relation.table,\r
- apply(context, Types.PROC, MSet_create, Types.tuple(relation.getParameterTypes()), tuple()),\r
+ apply(context.getCompilationContext(), Types.PROC, Names.MSet_create, Types.tuple(relation.getParameterTypes()), tuple()),\r
continuation);\r
\r
return seq(continuation, in);\r
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
else {\r
Variable accumulator = newVar("accum", Types.apply(ARRAY_LIST, elType));\r
result =\r
- apply(context, Types.PROC, Name.create("ArrayList", "freeze"), elType,\r
+ apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_freeze, elType,\r
var(accumulator));\r
Expression innerExpression = \r
- apply(context, Types.PROC, Name.create("ArrayList", "add"), elType,\r
+ apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_add, elType,\r
var(accumulator), expression);\r
try {\r
QueryCompilationContext queryCompilationContext =\r
return new EError(getLocation());\r
}\r
result = let(accumulator,\r
- apply(context, Types.PROC, Name.create("ArrayList", "new"), elType, tuple()),\r
+ apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_new, elType, tuple()),\r
result\r
);\r
}\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.constants.StringInterpolation;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
@Override\r
public Expression resolve(TranslationContext context) {\r
Expression[] components = new Expression[expressions.length];\r
- SCLValue showForPrinting = context.getEnvironment().getValue(Name.create("Prelude", "showForPrinting"));\r
+ SCLValue showForPrinting = context.getEnvironment().getValue(Names.Prelude_showForPrinting);\r
for(int i=0;i<expressions.length;++i)\r
components[i] = new EApply(new EConstant(showForPrinting), expressions[i]);\r
return new EApply(new ELiteral(new StringInterpolation(strings)), components).resolve(context);\r
public Expression accept(ExpressionTransformer transformer) {\r
return transformer.transform(this);\r
}\r
+ \r
+ @Override\r
+ public Expression resolveAsPattern(TranslationContext context) {\r
+ for(int i=0;i<expressions.length;++i)\r
+ expressions[i] = expressions[i].resolveAsPattern(context);\r
+ if(expressions.length > 1) {\r
+ context.getErrorLog().log(location, "String interpolation can be a pattern only if has one hole.");\r
+ return new EError();\r
+ }\r
+ return new EApply(new ELiteral(new StringInterpolation(strings)), expressions);\r
+ }\r
\r
\r
}\r
return this;\r
}\r
else\r
- return applyPUnit(context);\r
+ return applyPUnit(context.getCompilationContext());\r
}\r
\r
@Override\r
public Expression accept(ExpressionTransformer transformer) {\r
return transformer.transform(this);\r
}\r
+ \r
+ @Override\r
+ public boolean equalsExpression(Expression expression) {\r
+ if(expression.getClass() != getClass())\r
+ return false;\r
+ EVariable other = (EVariable)expression;\r
+ return variable == other.variable;\r
+ }\r
\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
+import org.simantics.scl.compiler.environment.Environment;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.exceptions.MatchException;\r
+import org.simantics.scl.compiler.types.util.MultiFunction;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class EViewPattern extends Expression {\r
+ public Expression expression;\r
+ public Expression pattern;\r
+ \r
+ public EViewPattern(Expression expression, Expression pattern) {\r
+ this.expression = expression;\r
+ this.pattern = pattern;\r
+ }\r
+\r
+ @Override\r
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
+ expression.collectRefs(allRefs, refs);\r
+ pattern.collectRefs(allRefs, refs);\r
+ }\r
+\r
+ @Override\r
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
+ expression.collectVars(allVars, vars);\r
+ pattern.collectVars(allVars, vars);\r
+ }\r
+\r
+ @Override\r
+ public void forVariables(VariableProcedure procedure) {\r
+ expression.forVariables(procedure);\r
+ pattern.forVariables(procedure);\r
+ }\r
+ \r
+ @Override\r
+ public Expression inferType(TypingContext context) {\r
+ context.setInPattern(false);\r
+ expression = expression.inferType(context);\r
+ context.setInPattern(true);\r
+ MultiFunction mfun;\r
+ try {\r
+ mfun = Types.matchFunction(expression.getType(), 1);\r
+ } catch (MatchException e) {\r
+ context.getErrorLog().log(expression.location, "Expected a function as a transformation expression.");\r
+ return new EError(location);\r
+ }\r
+ setType(mfun.parameterTypes[0]);\r
+ pattern.checkType(context, mfun.returnType);\r
+ return this;\r
+ }\r
+\r
+ @Override\r
+ protected void updateType() throws MatchException {\r
+ MultiFunction mfun = Types.matchFunction(expression.getType(), 1);\r
+ setType(mfun.parameterTypes[0]);\r
+ }\r
+\r
+ @Override\r
+ public IVal toVal(Environment env, CodeWriter w) {\r
+ throw new InternalCompilerError(location, "EViewPattern.toVal should not be invoked.");\r
+ }\r
+\r
+ @Override\r
+ public void collectFreeVariables(THashSet<Variable> vars) {\r
+ throw new InternalCompilerError(location, "Cannot collect free variables for a pattern.");\r
+ }\r
+ \r
+ @Override\r
+ public void removeFreeVariables(THashSet<Variable> vars) {\r
+ expression.collectFreeVariables(vars);\r
+ pattern.removeFreeVariables(vars);\r
+ }\r
+\r
+ @Override\r
+ public Expression resolve(TranslationContext context) {\r
+ context.getErrorLog().log("View pattern cannot occur only in patterns. Maybe you are missing '\\' in front of a lambda experssion?");\r
+ return new EError(location);\r
+ }\r
+\r
+ @Override\r
+ public Expression resolveAsPattern(TranslationContext context) {\r
+ expression = expression.resolve(context);\r
+ pattern = pattern.resolveAsPattern(context);\r
+ return this;\r
+ }\r
+ \r
+ @Override\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ location = loc; \r
+ expression.setLocationDeep(loc);\r
+ pattern.setLocationDeep(loc);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Expression decorate(ExpressionDecorator decorator) {\r
+ expression = expression.decorate(decorator);\r
+ return this;\r
+ }\r
+\r
+ @Override\r
+ public void collectEffects(THashSet<Type> effects) {\r
+ expression.collectEffects(effects);\r
+ }\r
+\r
+ @Override\r
+ public void accept(ExpressionVisitor visitor) {\r
+ visitor.visit(this);\r
+ }\r
+\r
+ @Override\r
+ public Expression accept(ExpressionTransformer transformer) {\r
+ return transformer.transform(this);\r
+ }\r
+ \r
+ @Override\r
+ public Expression simplify(SimplificationContext context) {\r
+ expression = expression.simplify(context);\r
+ pattern = pattern.simplify(context);\r
+ return this;\r
+ }\r
+\r
+}\r
public abstract void collectFreeVariables(THashSet<Variable> vars);\r
\r
public Expression simplify(SimplificationContext context) {\r
+ System.out.println("#############################");\r
+ System.out.println(this);\r
throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method.");\r
}\r
\r
}\r
\r
public abstract Expression accept(ExpressionTransformer transformer);\r
+\r
+ // TODO implement for all expressions\r
+ public boolean equalsExpression(Expression expression) {\r
+ return false;\r
+ }\r
}\r
Expression transform(EBinary expression);
Expression transform(EBind expression);
Expression transform(EBlock expression);
+ Expression transform(ECHRRuleset expression);
Expression transform(EConstant expression);
+ Expression transform(ECoveringBranchPoint expression);
Expression transform(EEnforce expression);
Expression transform(EEntityTypeAnnotation expression);
Expression transform(EEquations expression);
Expression transform(EPlaceholder expression);
Expression transform(EPreLet expression);
Expression transform(EPreRuleset expression);
- Expression transform(ECoveringBranchPoint expression);
Expression transform(ERange expression);
Expression transform(ERealLiteral expression);
Expression transform(ERecord expression);
Expression transform(ETypeAnnotation expression);
Expression transform(EVar expression);
Expression transform(EVariable expression);
+ Expression transform(EViewPattern expression);
Expression transform(EWhen expression);
Expression transform(GuardedExpressionGroup expression);
void visit(EApplyType expression);\r
void visit(EAsPattern expression);\r
void visit(EBind expression);\r
+ void visit(ECHRRuleset echrRuleset);\r
void visit(EConstant expression);\r
void visit(ECoveringBranchPoint expression);\r
void visit(EEnforce expression);\r
void visit(ETransformation expression);\r
void visit(ETypeAnnotation expression);\r
void visit(EVariable expression);\r
+ void visit(EViewPattern expression);\r
void visit(EWhen expression);\r
void visit(GuardedExpressionGroup expression);\r
}\r
}\r
\r
public static Expression isZeroInteger(Expression value) {\r
- return apply(Types.NO_EFFECTS, new ELiteral(new JavaComparisonToZeroOperation("==")), value);\r
+ return apply(Types.NO_EFFECTS, new ELiteral(JavaComparisonToZeroOperation.IEQUAL), value);\r
}\r
\r
public static Expression addInteger(Expression a, Expression b) {\r
package org.simantics.scl.compiler.elaboration.expressions;
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;
import org.simantics.scl.compiler.elaboration.equation.EqBasic;
import org.simantics.scl.compiler.elaboration.equation.EqGuard;
import org.simantics.scl.compiler.elaboration.equation.Equation;
return expression;
}
+ @Override
+ public Expression transform(EViewPattern expression) {
+ expression.expression = expression.expression.accept(this);
+ expression.pattern = expression.pattern.accept(this);
+ return expression;
+ }
+
@Override
public Expression transform(EBlock expression) {
for(Statement statement : expression.statements)
statement.body = statement.body.accept(this);
}
+ @Override
+ public Expression transform(ECHRRuleset expression) {
+ expression.in = expression.in.accept(this);
+ for(CHRRule rule : expression.ruleset.rules) {
+ for(CHRLiteral lit : rule.head.literals)
+ for(int i=0;i<lit.parameters.length;++i)
+ lit.parameters[i] = lit.parameters[i].accept(this);
+ for(CHRLiteral lit : rule.body.literals)
+ for(int i=0;i<lit.parameters.length;++i)
+ lit.parameters[i] = lit.parameters[i].accept(this);
+ }
+ return expression;
+ }
+
@Override
public Expression transform(EConstant expression) {
return expression;
public Expression transform(EIf expression) {
expression.condition = expression.condition.accept(this);
expression.then_ = expression.then_.accept(this);
- expression.else_ = expression.else_.accept(this);
+ if(expression.else_ != null)
+ expression.else_ = expression.else_.accept(this);
return expression;
}
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;\r
import org.simantics.scl.compiler.elaboration.equation.EqBasic;\r
import org.simantics.scl.compiler.elaboration.equation.EqGuard;\r
import org.simantics.scl.compiler.elaboration.equation.Equation;\r
public void visit(EIf expression) {\r
expression.condition.accept(this);\r
expression.then_.accept(this);\r
- expression.else_.accept(this);\r
+ if(expression.else_ != null)\r
+ expression.else_.accept(this);\r
}\r
\r
@Override\r
for(Case case_ : expression.cases)\r
visit(case_);\r
}\r
+ \r
+ @Override\r
+ public void visit(EViewPattern expression) {\r
+ expression.expression.accept(this);\r
+ expression.pattern.accept(this);\r
+ }\r
\r
public void visit(Case case_) {\r
for(Expression pattern : case_.patterns)\r
equation.accept(this);\r
}\r
\r
+ @Override\r
+ public void visit(ECHRRuleset ruleset) {\r
+ for(CHRRule rule : ruleset.ruleset.rules) {\r
+ for(CHRLiteral literal : rule.head.literals)\r
+ for(Expression parameter : literal.parameters)\r
+ parameter.accept(this);\r
+ for(CHRLiteral literal : rule.body.literals)\r
+ for(Expression parameter : literal.parameters)\r
+ parameter.accept(this);\r
+ }\r
+ ruleset.in.accept(this);\r
+ }\r
+\r
}\r
public void accept(StatementVisitor visitor) {\r
visitor.visit(this);\r
}\r
+\r
+ @Override\r
+ public StatementGroup getStatementGroup() {\r
+ return null;\r
+ }\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions.block;\r
+\r
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+\r
+public class CHRStatement extends Statement {\r
+\r
+ public ListQualifier[] head;\r
+ public ListQualifier[] body;\r
+\r
+ public CHRStatement(ListQualifier[] head, ListQualifier[] body) {\r
+ this.head = head;\r
+ this.body = body;\r
+ }\r
+\r
+ @Override\r
+ public Expression toExpression(EnvironmentalContext context, boolean monadic, Expression in) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ location = loc;\r
+ for(ListQualifier lq : head)\r
+ lq.setLocationDeep(loc);\r
+ for(ListQualifier lq : body)\r
+ lq.setLocationDeep(loc);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void resolvePattern(TranslationContext context) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public boolean mayBeRecursive() {\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public void accept(StatementVisitor visitor) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+ \r
+ @Override\r
+ public StatementGroup getStatementGroup() {\r
+ return StatementGroup.CHR;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions.block;\r
+\r
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.parsing.Token;\r
+import org.simantics.scl.compiler.internal.parsing.types.TypeAst;\r
+\r
+public class ConstraintStatement extends Statement {\r
+\r
+ public Token name;\r
+ public TypeAst[] parameterTypes;\r
+ \r
+ public ConstraintStatement(Token name, TypeAst[] parameterTypes) {\r
+ this.name = name;\r
+ this.parameterTypes = parameterTypes;\r
+ }\r
+ \r
+ @Override\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ location = loc;\r
+ for(TypeAst parameterType : parameterTypes)\r
+ if(parameterType.location == Locations.NO_LOCATION)\r
+ parameterType.location = location;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Expression toExpression(EnvironmentalContext context, boolean monadic, Expression in) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public void resolvePattern(TranslationContext context) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public boolean mayBeRecursive() {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public void accept(StatementVisitor visitor) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public StatementGroup getStatementGroup() {\r
+ return StatementGroup.CHR;\r
+ }\r
+}\r
public void accept(StatementVisitor visitor) {\r
visitor.visit(this);\r
}\r
+\r
+ @Override\r
+ public StatementGroup getStatementGroup() {\r
+ return null;\r
+ }\r
}\r
public void accept(StatementVisitor visitor) {\r
visitor.visit(this);\r
}\r
+\r
+ @Override\r
+ public StatementGroup getStatementGroup() {\r
+ if(pattern.isFunctionPattern())\r
+ return StatementGroup.LetFunction;\r
+ else\r
+ return null;\r
+ }\r
}
\ No newline at end of file
public void accept(StatementVisitor visitor) {\r
visitor.visit(this);\r
}\r
+\r
+ @Override\r
+ public StatementGroup getStatementGroup() {\r
+ return StatementGroup.Rule;\r
+ }\r
}\r
}\r
\r
public abstract void accept(StatementVisitor visitor);\r
+ public abstract StatementGroup getStatementGroup();\r
\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions.block;\r
+\r
+public enum StatementGroup {\r
+ Rule,\r
+ CHR,\r
+ LetFunction\r
+}\r
\r
import java.util.Map.Entry;\r
\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRQuery;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
import org.simantics.scl.compiler.elaboration.expressions.Assignment;\r
import org.simantics.scl.compiler.elaboration.expressions.Case;\r
import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
import org.simantics.scl.compiler.elaboration.expressions.EApplyType;\r
import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;\r
import org.simantics.scl.compiler.elaboration.expressions.EBind;\r
+import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset;\r
import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;\r
import org.simantics.scl.compiler.elaboration.expressions.EEnforce;\r
import org.simantics.scl.compiler.elaboration.expressions.ETransformation;\r
import org.simantics.scl.compiler.elaboration.expressions.ETypeAnnotation;\r
import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;\r
import org.simantics.scl.compiler.elaboration.expressions.EWhen;\r
import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
import org.simantics.scl.compiler.elaboration.expressions.ExpressionVisitor;\r
@Override\r
public void visit(EIf expression) {\r
b.append("if ");\r
- expression.getCondition().accept(this);\r
+ expression.condition.accept(this);\r
++indentation;\r
newLine();\r
b.append("then ");\r
- expression.getThen().accept(this);\r
- newLine();\r
- b.append("else ");\r
- expression.getElse().accept(this);\r
+ expression.then_.accept(this);\r
+ if(expression.else_ != null) {\r
+ newLine();\r
+ b.append("else ");\r
+ expression.else_.accept(this);\r
+ }\r
--indentation;\r
}\r
\r
}\r
--indentation;\r
}\r
+ \r
+ @Override\r
+ public void visit(EViewPattern expression) {\r
+ b.append('(');\r
+ expression.expression.accept(this);\r
+ b.append(" -> ");\r
+ expression.pattern.accept(this);\r
+ b.append(')');\r
+ }\r
\r
@Override\r
public void visit(ELambdaType expression) {\r
public void visit(EEquations eEquations) {\r
b.append("eq");\r
}\r
+\r
+ @Override\r
+ public void visit(ECHRRuleset echrRuleset) {\r
+ b.append("CHRRuleset");\r
+ }\r
+\r
+ public void visit(CHRRule rule) {\r
+ visit(rule.head);\r
+ b.append(" => ");\r
+ visit(rule.body);\r
+ }\r
+\r
+ public void visit(CHRQuery query) {\r
+ boolean first = true;\r
+ for(CHRLiteral literal : query.literals) {\r
+ if(first)\r
+ first = false;\r
+ else\r
+ b.append(", ");\r
+ visit(literal);\r
+ }\r
+ }\r
+\r
+ public void visit(CHRLiteral literal) {\r
+ if(literal.passive && literal.relation instanceof CHRConstraint)\r
+ b.append("@passive ");\r
+ if(literal.killAfterMatch)\r
+ b.append('-');\r
+ b.append(literal.relation);\r
+ for(Expression parameter : literal.parameters) {\r
+ b.append(' ');\r
+ showPar(parameter);\r
+ }\r
+ }\r
}\r
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.scl.compiler.common.datatypes.Constructor;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.common.precedence.Associativity;
+import org.simantics.scl.compiler.common.precedence.Precedence;
import org.simantics.scl.compiler.constants.BooleanConstant;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.constants.JavaStaticField;
public static SCLValue Nothing;
public static SCLValue Just;
+ public static SCLValue EQUALS;
+
private Builtins() {
super(Types.BUILTIN);
StandardTypeConstructor Boolean = new StandardTypeConstructor(Types.BOOLEAN, Kinds.STAR, TypeDesc.BOOLEAN);
Boolean.documentation = "Data type representing truth values `True` and `False`.";
- addTypeConstructor("Boolean", Boolean);
- addTypeConstructor("Byte", new StandardTypeConstructor(Types.BYTE, Kinds.STAR, TypeDesc.BYTE,
+ addTypeDescriptor("Boolean", Boolean);
+ addTypeDescriptor("Byte", new StandardTypeConstructor(Types.BYTE, Kinds.STAR, TypeDesc.BYTE,
"8-bit signed integer"));
- addTypeConstructor("Character", new StandardTypeConstructor(Types.CHARACTER, Kinds.STAR, TypeDesc.CHAR,
+ addTypeDescriptor("Character", new StandardTypeConstructor(Types.CHARACTER, Kinds.STAR, TypeDesc.CHAR,
"16-bit Unicode character."));
- addTypeConstructor("Short", new StandardTypeConstructor(Types.SHORT, Kinds.STAR, TypeDesc.SHORT,
+ addTypeDescriptor("Short", new StandardTypeConstructor(Types.SHORT, Kinds.STAR, TypeDesc.SHORT,
"16-bit signed integer"));
- addTypeConstructor("Integer", new StandardTypeConstructor(Types.INTEGER, Kinds.STAR, TypeDesc.INT,
+ addTypeDescriptor("Integer", new StandardTypeConstructor(Types.INTEGER, Kinds.STAR, TypeDesc.INT,
"32-bit signed integer"));
- addTypeConstructor("Long", new StandardTypeConstructor(Types.LONG, Kinds.STAR, TypeDesc.LONG,
+ addTypeDescriptor("Long", new StandardTypeConstructor(Types.LONG, Kinds.STAR, TypeDesc.LONG,
"64-bit signed integer"));
- addTypeConstructor("Float", new StandardTypeConstructor(Types.FLOAT, Kinds.STAR, TypeDesc.FLOAT,
+ addTypeDescriptor("Float", new StandardTypeConstructor(Types.FLOAT, Kinds.STAR, TypeDesc.FLOAT,
"32-bit floating point number"));
- addTypeConstructor("Double", new StandardTypeConstructor(Types.DOUBLE, Kinds.STAR, TypeDesc.DOUBLE,
+ addTypeDescriptor("Double", new StandardTypeConstructor(Types.DOUBLE, Kinds.STAR, TypeDesc.DOUBLE,
"64-bit floating point number"));
- addTypeConstructor("String", new StandardTypeConstructor(Types.STRING, Kinds.STAR, TypeDesc.STRING,
+ addTypeDescriptor("String", new StandardTypeConstructor(Types.STRING, Kinds.STAR, TypeDesc.STRING,
"Unicode string"));
- addTypeConstructor("BooleanArray", new StandardTypeConstructor(Types.BOOLEAN_ARRAY, Kinds.STAR, TypeDesc.forClass(boolean[].class)));
- addTypeConstructor("ByteArray", new StandardTypeConstructor(Types.BYTE_ARRAY, Kinds.STAR, TypeDesc.forClass(byte[].class)));
- addTypeConstructor("CharacterArray", new StandardTypeConstructor(Types.CHARACTER_ARRAY, Kinds.STAR, TypeDesc.forClass(char[].class)));
- addTypeConstructor("ShortArray", new StandardTypeConstructor(Types.SHORT_ARRAY, Kinds.STAR, TypeDesc.forClass(short[].class)));
- addTypeConstructor("IntegerArray", new StandardTypeConstructor(Types.INTEGER_ARRAY, Kinds.STAR, TypeDesc.forClass(int[].class)));
- addTypeConstructor("LongArray", new StandardTypeConstructor(Types.LONG_ARRAY, Kinds.STAR, TypeDesc.forClass(long[].class)));
- addTypeConstructor("FloatArray", new StandardTypeConstructor(Types.FLOAT_ARRAY, Kinds.STAR, TypeDesc.forClass(float[].class)));
- addTypeConstructor("DoubleArray", new StandardTypeConstructor(Types.DOUBLE_ARRAY, Kinds.STAR, TypeDesc.forClass(double[].class)));
+ addTypeDescriptor("BooleanArray", new StandardTypeConstructor(Types.BOOLEAN_ARRAY, Kinds.STAR, TypeDesc.forClass(boolean[].class)));
+ addTypeDescriptor("ByteArray", new StandardTypeConstructor(Types.BYTE_ARRAY, Kinds.STAR, TypeDesc.forClass(byte[].class)));
+ addTypeDescriptor("CharacterArray", new StandardTypeConstructor(Types.CHARACTER_ARRAY, Kinds.STAR, TypeDesc.forClass(char[].class)));
+ addTypeDescriptor("ShortArray", new StandardTypeConstructor(Types.SHORT_ARRAY, Kinds.STAR, TypeDesc.forClass(short[].class)));
+ addTypeDescriptor("IntegerArray", new StandardTypeConstructor(Types.INTEGER_ARRAY, Kinds.STAR, TypeDesc.forClass(int[].class)));
+ addTypeDescriptor("LongArray", new StandardTypeConstructor(Types.LONG_ARRAY, Kinds.STAR, TypeDesc.forClass(long[].class)));
+ addTypeDescriptor("FloatArray", new StandardTypeConstructor(Types.FLOAT_ARRAY, Kinds.STAR, TypeDesc.forClass(float[].class)));
+ addTypeDescriptor("DoubleArray", new StandardTypeConstructor(Types.DOUBLE_ARRAY, Kinds.STAR, TypeDesc.forClass(double[].class)));
- addTypeConstructor("Array", new StandardTypeConstructor(Types.con(Types.BUILTIN, "Array"), Kinds.STAR_TO_STAR, TypeDesc.forClass(Object[].class)));
+ addTypeDescriptor("Array", new StandardTypeConstructor(Types.con(Types.BUILTIN, "Array"), Kinds.STAR_TO_STAR, TypeDesc.forClass(Object[].class)));
- addTypeConstructor("Maybe", MaybeType.INSTANCE);
+ addTypeDescriptor("Maybe", MaybeType.INSTANCE);
- addTypeConstructor("Variant", new StandardTypeConstructor(Types.VARIANT, Kinds.STAR, TypeDesc.forClass(Variant.class)));
+ addTypeDescriptor("Variant", new StandardTypeConstructor(Types.VARIANT, Kinds.STAR, TypeDesc.forClass(Variant.class)));
addEffectConstructor("Proc", new EffectConstructor(Types.PROC));
- //addTypeConstructor("->", new StandardTypeConstructor(Kinds.STAR_TO_STAR_TO_STAR, Constants.FUNCTION));
- addTypeConstructor("[]", new StandardTypeConstructor(Types.LIST, Kinds.STAR_TO_STAR, Constants.LIST));
- addTypeConstructor("@", new StandardTypeConstructor(Types.PUNIT, Kinds.STAR, Constants.TUPLE[0]));
- addTypeConstructor("TypeProxy", new StandardTypeConstructor(Types.TYPE_PROXY, Kinds.STAR_TO_STAR, Constants.TUPLE[0]));
+ //addTypeDescriptor("->", new StandardTypeConstructor(Kinds.STAR_TO_STAR_TO_STAR, Constants.FUNCTION));
+ addTypeDescriptor("[]", new StandardTypeConstructor(Types.LIST, Kinds.STAR_TO_STAR, Constants.LIST));
+ addTypeDescriptor("@", new StandardTypeConstructor(Types.PUNIT, Kinds.STAR, Constants.TUPLE[0]));
+ addTypeDescriptor("TypeProxy", new StandardTypeConstructor(Types.TYPE_PROXY, Kinds.STAR_TO_STAR, Constants.TUPLE[0]));
// *** Tuples ***
TCon constructor = Types.tupleConstructor(arity);
StandardTypeConstructor typeConstructor =
new StandardTypeConstructor(constructor, tupleKind, Constants.TUPLE[arity]);
- addTypeConstructor(constructor.name, typeConstructor);
+ addTypeDescriptor(constructor.name, typeConstructor);
Type returnType = Types.apply(constructor, vars);
typeConstructor.setType(constructor, vars);
Constant cons;
Fundep.EMPTY_ARRAY);
addTypeClass("VecComp", VecCompC);
- addTypeConstructor("Vector", new VectorType(Types.VECTOR));
+ addTypeDescriptor("Vector", new VectorType(Types.VECTOR));
addValue("getVector", new GetVector(Types.NO_EFFECTS, Types.VECTOR));
addValue("lengthVector", new LengthVector(Types.VECTOR));
//addValue("createVectorFromList", CreateVectorFromList.INSTANCE);
- addTypeConstructor("MVector", new VectorType(Types.MVECTOR));
+ addTypeDescriptor("MVector", new VectorType(Types.MVECTOR));
addValue("createMVector", CreateMVector.INSTANCE);
addValue("createMVectorProto", CreateMVectorProto.INSTANCE);
addValue("getMVector", new GetVector(Types.PROC, Types.MVECTOR));
x.createOccurrence()));
runProcFunction.addBlock(block);
- SCLConstant runProc = new SCLConstant(Name.create(Types.BUILTIN, "runProc"), runProcFunction.getType());
+ SCLConstant runProc = new SCLConstant(Names.Builtin_runProc, runProcFunction.getType());
runProc.setDefinition(runProcFunction);
runProc.setInlineArity(1, 0xffffffff);
runProc.setBase(new JavaStaticMethod("org/simantics/scl/runtime/procedure/Procedures",
Types.NO_EFFECTS,
TypeDesc.forClass(TUnion.class),
Type, -1));
- /*addValue("TUnion", new JavaStaticMethod(
+ addValue("TUnion2", new JavaStaticMethod(
"org/simantics/scl/compiler/types/Types",
"union",
Types.NO_EFFECTS,
- Type, Types.list(Type)));*/
+ Type, Type, Type));
StandardTypeConstructor TypeC = new StandardTypeConstructor(Type, Kinds.STAR,
TypeDesc.forClass("org/simantics/scl/compiler/types/Type"));
TypeC.setType(Type);
TypeC.isOpen = true;
TypeC.documentation = "Represents an SCL data type.";
- addTypeConstructor("Type", TypeC);
+ addTypeDescriptor("Type", TypeC);
// typeOf :: Typeable a => a -> Type
addValue("typeOf", TypeOfConstant.INSTANCE)
BindingC.setType(Types.BINDING, A);
BindingC.documentation = "`Binding` represents a data type in the form supported by Databoard library. " +
"It is used to serialize and deserialize values.";
- addTypeConstructor("Binding", BindingC);
+ addTypeDescriptor("Binding", BindingC);
// typeOf :: Typeable a => a -> TypeReps
addValue("binding", BindingConstant.INSTANCE)
addRelation("Execute10", new ExecuteRelation(10));
}
- addValue("newEq", EqualsFunction.INSTANCE);
- addValue("newHash", HashCodeFunction.INSTANCE);
+ {
+ EQUALS = new SCLValue(Names.Builtin_equals, EqualsFunction.INSTANCE);
+ EQUALS.setPrecedence(new Precedence(4, Associativity.NONASSOC));
+ addValue(EQUALS);
+ addValue("hashCode", HashCodeFunction.INSTANCE);
+ }
+
// Coverage
{
StandardTypeConstructor branchPoint = new StandardTypeConstructor(Types.BRANCH_POINT, Kinds.STAR,
TypeDesc.forClass(BranchPoint.class));
- addTypeConstructor("BranchPoint", branchPoint);
+ addTypeDescriptor("BranchPoint", branchPoint);
addValue("visitBranchPoint", VisitBranchPoint.INSTANCE);
}
\r
import org.cojen.classfile.TypeDesc;\r
import org.objectweb.asm.Label;\r
+import org.simantics.scl.compiler.constants.ComparisonFunction;\r
import org.simantics.scl.compiler.constants.FunctionValue;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;\r
import org.simantics.scl.compiler.internal.codegen.references.Val;\r
import org.simantics.scl.compiler.internal.codegen.utils.Constants;\r
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
import org.simantics.scl.compiler.types.Types;\r
import org.simantics.scl.compiler.types.kinds.Kinds;\r
\r
-public class EqualsFunction extends FunctionValue {\r
+public class EqualsFunction extends FunctionValue implements ComparisonFunction {\r
private static final TVar A = Types.var(Kinds.STAR);\r
public static final EqualsFunction INSTANCE = new EqualsFunction();\r
\r
mb.invokeStatic("java/util/Objects", "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);\r
return Types.BOOLEAN;\r
}\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return "==";\r
+ }\r
+\r
+ @Override\r
+ public void generateCondition(MethodBuilder mb, Val[] parameters, Cont then_, Cont else_) {\r
+ parameters[0].push(mb);\r
+ parameters[1].push(mb);\r
+ TypeDesc parameterType = mb.getJavaTypeTranslator().getTypeDesc(parameters[0]);\r
+ if(parameterType.isPrimitive()) {\r
+ if(parameterType.equals(TypeDesc.VOID)) {\r
+ mb.jump(then_);\r
+ }\r
+ else {\r
+ mb.ifComparisonBranch(mb.getLabel(then_), "==", parameterType);\r
+ mb.jump(else_);\r
+ mb.ensureExists(then_);\r
+ }\r
+ }\r
+ else {\r
+ mb.invokeStatic("java/util/Objects", "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);\r
+ mb.ifZeroComparisonBranch(mb.getLabel(else_), "==");\r
+ mb.jump(then_);\r
+ mb.ensureExists(else_);\r
+ }\r
+ }\r
}\r
@Override
public String toString() {
- return "[...]";
+ return "[.." + arity + "..]";
}
}
package org.simantics.scl.compiler.elaboration.java;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
case BB:
context.condition(
new EApply(
- context.getConstant(Name.create("Prelude", "elem"), typeParameters),
+ context.getConstant(Names.Prelude_elem, typeParameters),
new Expression[] {
- context.getEvidence(location, Types.pred(Types.EQ, typeParameters[0])),
new EVariable(parameters[0]),
new EVariable(parameters[1])
}
package org.simantics.scl.compiler.elaboration.java;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
case BB:
context.condition(
new EApply(
- context.getConstant(Name.create("Prelude", "elemMaybe"), typeParameters),
+ context.getConstant(Names.Prelude_elemMaybe, typeParameters),
new Expression[] {
- context.getEvidence(location, Types.pred(Types.EQ, typeParameters[0])),
new EVariable(parameters[0]),
new EVariable(parameters[1])
}
package org.simantics.scl.compiler.elaboration.modules;\r
\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.types.TCon;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.kinds.Kind;\r
\r
-public class TypeAlias {\r
- TCon con;\r
- \r
+public class TypeAlias extends TypeDescriptor { \r
public TVar[] parameters;\r
public Type body;\r
+ public String documentation;\r
\r
- public TypeAlias(TCon con, int arity) {\r
- this.con = con;\r
+ public TypeAlias(TCon name, int arity) {\r
+ super(name);\r
this.parameters = new TVar[arity];\r
}\r
\r
- public TCon getCon() {\r
- return con;\r
- }\r
-\r
public int getArity() {\r
return parameters.length;\r
}\r
+\r
+ @Override\r
+ public Kind getKind() {\r
+ throw new InternalCompilerError("Unsupported method TypeAlias.getKind invoked.");\r
+ }\r
+ \r
+ @Override\r
+ public void setDocumentation(String documentation) {\r
+ this.documentation = documentation;\r
+ }\r
+ \r
+ @Override\r
+ public String getDocumentation() {\r
+ return documentation;\r
+ }\r
}\r
import org.simantics.scl.compiler.types.kinds.Kind;\r
import org.simantics.scl.compiler.types.kinds.Kinds;\r
\r
-public abstract class TypeConstructor {\r
+public abstract class TypeConstructor extends TypeDescriptor {\r
public Kind kind;\r
\r
- public TCon name;\r
public TVar[] parameters;\r
public Type type;\r
\r
public boolean isOpen = true;\r
\r
public TypeConstructor(Kind kind) {\r
+ super(null);\r
this.kind = kind;\r
}\r
\r
public TypeConstructor(TCon name, Kind kind) {\r
- this.name = name;\r
+ super(name);\r
this.kind = kind;\r
\r
ArrayList<TVar> vars = new ArrayList<TVar>(2);\r
}\r
\r
public TypeConstructor(TCon name, TVar ... parameters) {\r
+ super(name);\r
setType(name, parameters);\r
Kind kind = Kinds.STAR;\r
for(int i = parameters.length-1;i>=0;--i)\r
this.parameters = parameters;\r
this.type = Types.apply(name, parameters);\r
}\r
- \r
+ \r
public void setConstructors(Constructor ... constructors) {\r
this.constructors = constructors;\r
}\r
\r
public abstract TypeDesc construct(JavaTypeTranslator translator, Type[] parameters);\r
\r
+ @Override\r
public void setDocumentation(String documentation) {\r
this.documentation = documentation;\r
}\r
+ \r
+ @Override\r
+ public Kind getKind() {\r
+ return kind;\r
+ }\r
+ \r
+ @Override\r
+ public String getDocumentation() {\r
+ return documentation;\r
+ }\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.elaboration.modules;\r
+\r
+import org.simantics.scl.compiler.types.TCon;\r
+import org.simantics.scl.compiler.types.kinds.Kind;\r
+\r
+public abstract class TypeDescriptor {\r
+ public TCon name;\r
+ public TypeDescriptor(TCon name) {\r
+ this.name = name;\r
+ }\r
+ public abstract Kind getKind();\r
+ public abstract void setDocumentation(String documentation);\r
+ public abstract String getDocumentation();\r
+}\r
package org.simantics.scl.compiler.elaboration.query;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.QueryTransformer;
@Override
public void generate(QueryCompilationContext context) {
context.condition(new EApply(
- context.getConstant(Name.create("Prelude", "not"), Type.EMPTY_ARRAY),
+ context.getConstant(Names.Prelude_not, Type.EMPTY_ARRAY),
innerContext.getContinuation()));
}
});
package org.simantics.scl.compiler.elaboration.query.compilation;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.errors.ErrorLog;
context.addConstraintDemand(evidence);
return evidence;
}
+
+ public CompilationContext getCompilationContext() {
+ return context.getCompilationContext();
+ }
}
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.constants.BooleanConstant;
-import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.elaboration.expressions.Case;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.java.Builtins;
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.exceptions.MatchException;
-public class QueryCompilationContext implements EnvironmentalContext {
- private static final Name EQUALS = Name.create("Prelude", "==");
-
+public class QueryCompilationContext {
TypingContext context;
QueryCompilationMode mode;
Type resultType;
}
case GET_ALL: {
try {
- return new EApply(context.getConstant(Name.create("Prelude", "appendList"),
+ return new EApply(context.getCompilationContext().getConstant(Names.Prelude_appendList,
Types.matchApply(Types.LIST, a.getType())), a, b);
} catch (MatchException e) {
throw new InternalCompilerError();
condition(new EApply(
location,
Types.PROC,
- context.getConstant(EQUALS, type),
+ context.getCompilationContext().getConstant(Names.Builtin_equals, type),
new Expression[] {
- getEvidence(location, Types.pred(Types.EQ, type)),
a,
b
}
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Prelude", "iterList"), variable.getType(), Types.PROC, Types.tupleConstructor(0)),
+ context.getCompilationContext().getConstant(Names.Prelude_iterList, variable.getType(), Types.PROC, Types.tupleConstructor(0)),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
list
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Prelude", "any"), variable.getType(), Types.PROC),
+ context.getCompilationContext().getConstant(Names.Prelude_any, variable.getType(), Types.PROC),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
list
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Prelude", "concatMap"), variable.getType(), Types.PROC,
+ context.getCompilationContext().getConstant(Names.Prelude_concatMap, variable.getType(), Types.PROC,
Types.matchApply(Types.LIST, continuation.getType())),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Prelude", "mapFirst"), variable.getType(), Types.PROC,
+ context.getCompilationContext().getConstant(Names.Prelude_mapFirst, variable.getType(), Types.PROC,
Types.matchApply(Types.MAYBE, continuation.getType())),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Vector", "iterVector"), variable.getType(), Types.PROC, continuation.getType()),
+ context.getCompilationContext().getConstant(Names.Vector_iterVector, variable.getType(), Types.PROC, continuation.getType()),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
vector
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Vector", "anyVector"), variable.getType(), Types.PROC),
+ context.getCompilationContext().getConstant(Names.Vector_anyVector, variable.getType(), Types.PROC),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
vector
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Vector", "concatMapVector"), variable.getType(), Types.PROC,
+ context.getCompilationContext().getConstant(Names.Vector_concatMapVector, variable.getType(), Types.PROC,
Types.matchApply(Types.LIST, continuation.getType())),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
continuation = new EApply(
Locations.NO_LOCATION,
Types.PROC,
- context.getConstant(Name.create("Vector", "mapFirstVector"), variable.getType(), Types.PROC,
+ context.getCompilationContext().getConstant(Names.Vector_mapFirstVector, variable.getType(), Types.PROC,
Types.matchApply(Types.MAYBE, continuation.getType())),
new Expression[] {
new ESimpleLambda(Types.PROC, variable, continuation),
}
}
- private static final Name MSet_iter = Name.create("MSet", "iter");
- private static final Name MSet_mapFirst = Name.create("MSet", "mapFirst");
-
public void iterateMSet(Variable variable, Expression set) {
try {
switch(mode) {
case ITERATE:
- continuation = apply(context, Types.PROC, MSet_iter, variable.getType(), Types.PROC, continuation.getType(),
+ continuation = apply(context.getCompilationContext(), Types.PROC, Names.MSet_iter, variable.getType(), Types.PROC, continuation.getType(),
lambda(Types.PROC, variable, continuation),
set
);
break;
case GET_FIRST:
- continuation = apply(context, Types.PROC, MSet_mapFirst, variable.getType(), Types.PROC,
+ continuation = apply(context.getCompilationContext(), Types.PROC, Names.MSet_mapFirst, variable.getType(), Types.PROC,
Types.matchApply(Types.MAYBE, continuation.getType()),
lambda(Types.PROC, variable, continuation),
set
}
public Expression getConstant(Name name, Type[] typeParameters) {
- return context.getConstant(name, typeParameters);
+ return context.getCompilationContext().getConstant(name, typeParameters);
}
public QueryCompilationContext createCheckContext() {
return evidence;
}
- @Override
- public SCLValue getValue(Name name) {
- return context.getValue(name);
+ public CompilationContext getCompilationContext() {
+ return context.getCompilationContext();
}
}
package org.simantics.scl.compiler.elaboration.relations;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
import org.simantics.scl.compiler.types.Type;
public abstract class AbstractRelation implements SCLRelation {
public Expression generateEnforce(long location, EnforcingContext context, Type[] typeParameters, Variable[] parameters) {
throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce.");
}
+
+ @Override
+ public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) {
+ throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce.");
+ }
+
+ @Override
+ public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,
+ Expression[] expressions) {
+ throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate.");
+ }
}
import java.util.ArrayList;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
import org.simantics.scl.compiler.internal.parsing.Symbol;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
return name;
}
+ @Override
+ public void generateEnforce(PlanContext context, CodeWriter w, long location, Expression[] parameters) {
+ throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support enforce.");
+ }
+
+ @Override
+ public void generateIterate(PlanContext context, CodeWriter w, long location, int boundMask, Variable[] variables,
+ Expression[] expressions) {
+ throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support iterate.");
+ }
}
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.vars;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
-import org.simantics.scl.compiler.common.names.Name;
-import org.simantics.scl.compiler.elaboration.expressions.ERuleset;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.elaboration.expressions.Expressions;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
private void createTable() {
this.table = newVar("table" + name,
- Types.apply(ERuleset.MSet, Types.tuple(parameterTypes)));
+ Types.apply(Names.MSet_T, Types.tuple(parameterTypes)));
}
public int getArity() {
return 0;
}
- private static final Name MSet_contains = Name.create("MSet", "contains");
- private static final Name EQ = Name.create("Prelude", "==");
@Override
public void generate(long location,
QueryCompilationContext context,
if(table == null)
throw new InternalCompilerError(location, "Variable table is undefined.");
if(boundVariables + 1 == 1 << parameters.length)
- context.condition(apply(context, Types.PROC,
- MSet_contains, Types.tuple(parameterTypes),
+ context.condition(apply(context.getCompilationContext(), Types.PROC,
+ Names.MSet_contains, Types.tuple(parameterTypes),
var(table),
tuple(vars(parameters))
));
Variable row = new Variable("row", Types.tuple(parameterTypes));
for(int i=0;i<parameters.length;++i)
if(((boundVariables>>i)&1) == 1)
- context.condition(apply(context, Types.NO_EFFECTS,
- EQ, parameterTypes[i],
- context.getEvidence(location, Types.pred(Types.EQ, parameterTypes[i])),
+ context.condition(apply(context.getCompilationContext(), Types.NO_EFFECTS,
+ Names.Builtin_equals, parameterTypes[i],
var(aux[i]),
var(parameters[i])
));
package org.simantics.scl.compiler.elaboration.relations;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
Type[] typeParameters,
Variable[] parameters);
+ void generateIterate(
+ PlanContext context,
+ CodeWriter w,
+ long location,
+ int boundMask,
+ Variable[] variables,
+ Expression[] expressions);
+ void generateEnforce(
+ PlanContext context,
+ CodeWriter w,
+ long location,
+ Expression[] parameters);
}
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
type = type.replace(getTypeVariables(), typeParameters);
Expression continuation = context.getContinuation();
+ System.out.println("continuation = " + continuation + " :: " + continuation.getType());
Variable set = new Variable("set", Types.apply(Types.con("MSet", "T"), type));
Variable f = new Variable("f", Types.functionE(type, Types.PROC, continuation.getType()));
Variable innerSolved = new Variable("tcTemp", solved.getType());
+ System.out.println("set :: " + set.getType());
+ System.out.println("f :: " + f.getType());
+ System.out.println("tcTemp :: " + innerSolved.getType());
QueryCompilationContext newContext = context.createSubcontext(new EApply(
new EVariable(f), new EVariable(innerSolved)
innerParameters, boundVariables);
continuation = context.disjunction(continuation, newContext.getContinuation());
- continuation = if_(apply(context, Types.PROC, Name.create("MSet", "add"), type,
+ continuation = if_(apply(context.getCompilationContext(), Types.PROC, Names.MSet_add, type,
var(set), var(solved)),
continuation,
context.failure());
continuation = lambda(Types.PROC, solved, continuation);
continuation = letRec(f, continuation, apply(var(f), var(bound)));
continuation = let(set,
- apply(context, Types.PROC, Name.create("MSet", "create"), type, tuple()),
+ apply(context.getCompilationContext(), Types.PROC, Names.MSet_create, type, tuple()),
continuation);
context.setContinuation(continuation);
\r
import org.simantics.scl.compiler.common.names.Name;\r
import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;\r
import org.simantics.scl.compiler.elaboration.modules.TypeClass;\r
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;\r
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;\r
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;\r
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;\r
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;\r
}\r
\r
@Override\r
- public TypeConstructor getTypeConstructor(TCon type) {\r
+ public TypeDescriptor getTypeDescriptor(TCon type) {\r
Module module = getModule(type.module);\r
if(module == null)\r
return null;\r
- return module.getTypeConstructor(type.name);\r
+ return module.getTypeDescriptor(type.name);\r
}\r
\r
@Override\r
return module.getEffectConstructor(type.name);\r
}\r
\r
- @Override\r
- public TypeAlias getTypeAlias(TCon type) {\r
- Module module = getModule(type.module);\r
- if(module == null)\r
- return null;\r
- return module.getTypeAlias(type.name);\r
- }\r
-\r
@Override\r
public TypeClass getTypeClass(TCon type) {\r
Module module = getModule(type.module);\r
import java.util.function.Consumer;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
throws AmbiguousNameException {
return null;
}
-
+
@Override
- public TypeConstructor getTypeConstructor(String name)
- throws AmbiguousNameException {
+ public TypeConstructor getTypeDescriptor(String name) throws AmbiguousNameException {
return null;
}
return null;
}
- @Override
- public TypeAlias getTypeAlias(String name) throws AmbiguousNameException {
- return null;
- }
-
@Override
public MappingRelation getMappingRelation(String name)
throws AmbiguousNameException {
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
SCLValue getValue(Name name);
SCLRelation getRelation(Name name);
SCLEntityType getEntityType(Name name);
- TypeConstructor getTypeConstructor(TCon type);
+ TypeDescriptor getTypeDescriptor(TCon type);
EffectConstructor getEffectConstructor(TCon type);
- TypeAlias getTypeAlias(TCon type);
TypeClass getTypeClass(TCon type);
Collection<TypeClassInstance> getInstances(TCon typeClass);
void collectRules(Collection<TransformationRule> rules);
import java.util.function.Consumer;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;
-import org.simantics.scl.compiler.errors.ErrorLog;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
* @return A TypeConstructor instance, or null if not found.
* @throws AmbiguousNameException if the same name is found in multiple imported modules.
*/
- public static TypeConstructor getTypeConstructor(Environment environment, String localName) throws AmbiguousNameException {
- return getEnvironmentEntry(environment, localName, getTypeConstructor);
+ public static TypeDescriptor getTypeDescriptor(Environment environment, String localName) throws AmbiguousNameException {
+ return getEnvironmentEntry(environment, localName, getTypeDescriptor);
}
/**
public static TypeClass getTypeClass(Environment environment, String localName) throws AmbiguousNameException {
return getEnvironmentEntry(environment, localName, getTypeClass);
}
-
- /**
- * Get the TypeAlias object representing a type alias defined in a given environment.
- * The name can be a local name or a fully scoped name with modules separated by periods.
- * @param environment the environment
- * @param localName the name to be searched for
- * @return A TypeAlias instance, or null if not found.
- * @throws AmbiguousNameException if the same name is found in multiple imported modules.
- */
- public static TypeAlias getTypeAlias(Environment environment, String localName) throws AmbiguousNameException {
- return getEnvironmentEntry(environment, localName, getTypeAlias);
- }
/**
* Get the Name object representing an SCL value defined in a given environment.
* @return A TCon instance, or null if not found.
* @throws AmbiguousNameException if the same name is used in multiple imported modules.
*/
- public static TCon getTypeConstructorName(Environment environment, String localName) throws AmbiguousNameException {
- TypeConstructor typeConstructor = getTypeConstructor(environment, localName);
- if(typeConstructor == null)
+ public static TCon getTypeDescriptorName(Environment environment, String localName) throws AmbiguousNameException {
+ TypeDescriptor typeDescriptor = getTypeDescriptor(environment, localName);
+ if(typeDescriptor == null)
return null;
else
- return typeConstructor.name;
+ return typeDescriptor.name;
}
/**
*/
public static Type getType(Environment environment, String typeText) throws SCLExpressionCompilationException {
SCLParserImpl parser = new SCLParserImpl(new StringReader(typeText));
- ErrorLog errorLog = new ErrorLog();
+ CompilationContext compilationContext = new CompilationContext();
+ compilationContext.environment = environment;
try {
TypeAst typeAst = (TypeAst)parser.parseType();
- TypeTranslationContext context = new TypeTranslationContext(errorLog, environment);
+ TypeTranslationContext context = new TypeTranslationContext(compilationContext);
Type type = context.toType(typeAst);
- if(errorLog.isEmpty())
+ if(compilationContext.errorLog.isEmpty())
return type;
} catch(SCLSyntaxErrorException e) {
- errorLog.log(e.location, e.getMessage());
+ compilationContext.errorLog.log(e.location, e.getMessage());
} catch(Exception e) {
- errorLog.log(e);
+ compilationContext.errorLog.log(e);
}
- throw new SCLExpressionCompilationException(errorLog.getErrors());
+ throw new SCLExpressionCompilationException(compilationContext.errorLog.getErrors());
}
/**
}
};
- private static final NamespaceValueAccessor<TypeConstructor> getTypeConstructor = new NamespaceValueAccessor<TypeConstructor>() {
+ private static final NamespaceValueAccessor<TypeDescriptor> getTypeDescriptor = new NamespaceValueAccessor<TypeDescriptor>() {
@Override
- public TypeConstructor get(Namespace ns, String name) throws AmbiguousNameException {
- return ns.getTypeConstructor(name);
+ public TypeDescriptor get(Namespace ns, String name) throws AmbiguousNameException {
+ return ns.getTypeDescriptor(name);
}
};
}
};
- private static final NamespaceValueAccessor<TypeAlias> getTypeAlias = new NamespaceValueAccessor<TypeAlias>() {
- @Override
- public TypeAlias get(Namespace ns, String name) throws AmbiguousNameException {
- return ns.getTypeAlias(name);
- }
- };
-
private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
Namespace namespace = environment.getLocalNamespace();
int curPos = 0;
int pos = localName.indexOf('.', curPos);
if(pos < 0)
return accessor.get(namespace, localName.substring(curPos));
- namespace = namespace.getNamespace(localName.substring(curPos, pos));
- if(namespace == null)
- return null;
+ Namespace newNamespace = namespace.getNamespace(localName.substring(curPos, pos));
+ if(newNamespace == null)
+ return accessor.get(namespace, localName.substring(curPos));
+ namespace = newNamespace;
curPos = pos + 1;
}
}
import java.util.function.Consumer;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
SCLEntityType getEntityType(String name) throws AmbiguousNameException;
/**
- * Get a TypeConstructor for a given name. The same instance is returned on each call.
+ * Get a TypeDescriptor for a given name. The same instance is returned on each call.
* @param name the name of a defined entity type
- * @return The return value is a TypeConstructor provided by any source included in the namespace,
+ * @return The return value is a TypeDescriptor provided by any source included in the namespace,
* or null if the name is not found.
* @exception AmbiguousNameException if the name matches with multiple imported modules.
*/
- TypeConstructor getTypeConstructor(String name) throws AmbiguousNameException;
+ TypeDescriptor getTypeDescriptor(String name) throws AmbiguousNameException;
/**
* Get an EffectConstructor for a given name. The same instance is returned on each call.
*/
TypeClass getTypeClass(String name) throws AmbiguousNameException;
- /**
- * Get a TypeAlias for a given name. The same instance is returned on each call.
- * @param name the name of a defined entity type
- * @return The return value is a TypeAlias provided by any source included in the namespace,
- * or null if the name is not found.
- * @exception AmbiguousNameException if the name matches with multiple imported modules.
- */
- TypeAlias getTypeAlias(String name) throws AmbiguousNameException;
-
TransformationRule getRule(String name) throws AmbiguousNameException;
MappingRelation getMappingRelation(String name) throws AmbiguousNameException;
import java.util.function.Consumer;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
this.module = module;
this.filter = filter;
}
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("ModuleImport \"").append(module).append("\"").append(" with filter ").append(filter);
- return sb.toString();
- }
}
public NamespaceImpl(THashMap<String, Namespace> namespaceMap,
}
@Override
- public TypeConstructor getTypeConstructor(String name)
+ public TypeDescriptor getTypeDescriptor(String name)
throws AmbiguousNameException {
- TypeConstructor result = null, temp;
+ TypeDescriptor result = null, temp;
Module resultModule = null;
ArrayList<String> conflictingModules = null;
for(ModuleImport moduleImport : moduleImports) {
Module module = moduleImport.module;
- temp = module.getTypeConstructor(name);
+ temp = module.getTypeDescriptor(name);
if(temp != null) {
if(result != null) {
if(conflictingModules == null) {
return result;
}
- @Override
- public TypeAlias getTypeAlias(String name) throws AmbiguousNameException {
- TypeAlias result = null, temp;
- Module resultModule = null;
- ArrayList<String> conflictingModules = null;
- for(ModuleImport moduleImport : moduleImports) {
- Module module = moduleImport.module;
- temp = module.getTypeAlias(name);
- if(temp != null) {
- if(result != null) {
- if(conflictingModules == null) {
- conflictingModules = new ArrayList<String>(2);
- conflictingModules.add(resultModule.getName());
- }
- conflictingModules.add(module.getName());
- }
- else {
- result = temp;
- resultModule = module;
- }
- }
- }
- if(conflictingModules != null)
- throw new AmbiguousNameException(conflictingModules, name);
- return result;
- }
-
@Override
public MappingRelation getMappingRelation(String name) throws AmbiguousNameException {
MappingRelation result = null, temp;
package org.simantics.scl.compiler.internal.codegen.analysis;\r
\r
import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.constants.SCLConstant;\r
import org.simantics.scl.compiler.internal.codegen.references.Val;\r
import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
return isLoopingBlockWithBreaker(apply.getParent(), breaker);\r
}\r
} \r
-\r
- private static final Name BUILD = Name.create("Prelude", "build");\r
\r
private static boolean isAppliedAtMostOnce(LetApply apply, ValRef funRef, SSAFunction function) {\r
ValRef applyFunctionRef = apply.getFunction();\r
if(!(applyFunction instanceof SCLConstant))\r
return false; // Not necessarily the right answer\r
Name name = ((SCLConstant)applyFunction).getName();\r
- if(name == BUILD)\r
+ if(name == Names.Prelude_build)\r
return true;\r
return false;\r
}\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.constants.SCLConstant;\r
import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;\r
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
}\r
}\r
\r
- private static final Name BUILD = Name.create("Prelude", "build");\r
- \r
private static boolean callsOnlyOnce(Name name, int arity) {\r
- if(name == BUILD)\r
+ if(name == Names.Prelude_build)\r
return arity == 1;\r
else\r
return false;\r
--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.chr;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.objectweb.asm.Label;\r
+import org.objectweb.asm.Opcodes;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo;\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;\r
+import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;\r
+import org.simantics.scl.compiler.internal.codegen.utils.Constants;\r
+import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;\r
+\r
+import gnu.trove.list.array.TIntArrayList;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+public class CHRCodeGenerator {\r
+ \r
+ public static final TypeDesc FACT_ID_TYPE = TypeDesc.INT;\r
+ public static final String CHRHashIndex_name = "org/simantics/scl/runtime/chr/CHRHashIndex";\r
+ public static final TypeDesc CHRHashIndex = TypeDesc.forClass(CHRHashIndex_name);\r
+ public static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue";\r
+ public static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name);\r
+ public static final String Fact_name = "org/simantics/scl/runtime/chr/Fact";\r
+ public static final TypeDesc Fact = TypeDesc.forClass(Fact_name);\r
+ public static final String QUEUE = "queue";\r
+ \r
+ private static class StoreInitialization {\r
+ final int access;\r
+ final String fieldName;\r
+ final TypeDesc fieldType;\r
+ final String className;\r
+ public StoreInitialization(int access, String fieldName, TypeDesc fieldType, String className) {\r
+ this.access = access;\r
+ this.fieldName = fieldName;\r
+ this.fieldType = fieldType;\r
+ this.className = className;\r
+ }\r
+ }\r
+ \r
+ public static void generateStore(ModuleBuilder moduleBuilder, CHRRuleset ruleset) {\r
+ ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.storeClassName, "java/lang/Object");\r
+ if(ruleset.parameters == null)\r
+ ruleset.parameters = new BoundVar[0];\r
+ ruleset.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.parameters); \r
+ \r
+ ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<>();\r
+ for(CHRConstraint constraint : ruleset.constraints)\r
+ generateFact(storeClassBuilder, constraint, hashIndexInitializations);\r
+ \r
+ // Fields\r
+ for(int i=0;i<ruleset.parameterTypeDescs.length;++i)\r
+ storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "p" + i, ruleset.parameterTypeDescs[i]);\r
+ storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);\r
+ for(StoreInitialization ini : hashIndexInitializations)\r
+ storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);\r
+ storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, QUEUE, FactActivationQueue);\r
+ \r
+ // Constructors\r
+ \r
+ {\r
+ MethodBuilderBase mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, ruleset.parameterTypeDescs);\r
+ mb.loadThis();\r
+ mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);\r
+ for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {\r
+ mb.loadThis();\r
+ mb.loadLocal(mb.getParameter(i));\r
+ mb.storeField(ruleset.storeClassName, "p" + i, ruleset.parameterTypeDescs[i]);\r
+ }\r
+ mb.loadThis();\r
+ mb.loadConstant(1);\r
+ mb.storeField(storeClassBuilder.getClassName(), "currentId", TypeDesc.INT);\r
+ for(StoreInitialization ini : hashIndexInitializations) {\r
+ mb.loadThis();\r
+ mb.newObject(ini.className);\r
+ mb.dup();\r
+ mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);\r
+ mb.storeField(ruleset.storeClassName, ini.fieldName, ini.fieldType);\r
+ }\r
+ {\r
+ mb.loadThis();\r
+ mb.newObject(FactActivationQueue_name);\r
+ mb.dup();\r
+ mb.loadConstant(ruleset.priorityCount);\r
+ mb.invokeConstructor(FactActivationQueue_name, new TypeDesc[] {TypeDesc.INT});\r
+ mb.storeField(ruleset.storeClassName, QUEUE, FactActivationQueue);\r
+ }\r
+ mb.returnVoid();\r
+ mb.finish();\r
+ }\r
+ \r
+ // Activate\r
+ \r
+ {\r
+ MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT});\r
+ mb.loadThis();\r
+ mb.loadField(ruleset.storeClassName, QUEUE, FactActivationQueue);\r
+ mb.loadThis();\r
+ mb.loadLocal(mb.getParameter(0));\r
+ mb.invokeVirtual(FactActivationQueue_name, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.INT});\r
+ mb.returnVoid();\r
+ mb.finish();\r
+ }\r
+ \r
+ moduleBuilder.addClass(storeClassBuilder);\r
+ }\r
+ \r
+ private static void generateFact(ClassBuilder storeClassBuilder, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {\r
+ CHRRuleset ruleset = constraint.parentRuleset;\r
+ boolean supportsRemoval = constraint.mayBeRemoved();\r
+ \r
+ ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder();\r
+ JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator();\r
+ TypeDesc storeTypeDesc = storeClassBuilder.getType();\r
+ TypeDesc[] storeTypeDescArray = new TypeDesc[] { storeTypeDesc };\r
+ \r
+ String factClassName = storeClassBuilder.getClassName() + "$" + constraint.name;\r
+ TypeDesc factTypeDesc = TypeDesc.forClass(factClassName);\r
+ ClassBuilder factClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, factClassName, "java/lang/Object", Fact_name);\r
+ \r
+ // Fields\r
+ \r
+ /* public int id;\r
+ public int c0; // key\r
+ public int c1;\r
+ public ExampleFact bfPrev;\r
+ public ExampleFact bfNext;\r
+ */\r
+ TypeDesc[] parameterTypeDescs = jtt.toTypeDescs(constraint.parameterTypes);\r
+ factClassBuilder.addField(Opcodes.ACC_PUBLIC, "id", FACT_ID_TYPE);\r
+ for(int i=0;i<constraint.parameterTypes.length;++i)\r
+ factClassBuilder.addField(Opcodes.ACC_PUBLIC, "c" + i, parameterTypeDescs[i]);\r
+ \r
+ for(IndexInfo indexInfo : constraint.getIndices()) {\r
+ if(supportsRemoval)\r
+ factClassBuilder.addField(Opcodes.ACC_PUBLIC, indexInfo.indexName + "Prev", factTypeDesc);\r
+ factClassBuilder.addField(Opcodes.ACC_PUBLIC, indexInfo.indexName + "Next", factTypeDesc);\r
+ \r
+ String hashIndexField = constraint.name + "$" + indexInfo.indexName;\r
+ if(indexInfo.indexMask == 0) {\r
+ // If there are now bound parameters, use just a direct reference to a fact\r
+ storeClassBuilder.addField(Opcodes.ACC_PUBLIC, hashIndexField, factTypeDesc);\r
+ }\r
+ else {\r
+ ClassBuilder hashClass = generateSpecializedHashIndex(storeClassBuilder, constraint, indexInfo, factTypeDesc, factClassName);\r
+ moduleBuilder.addClass(hashClass);\r
+ hashIndexInitializations.add(new StoreInitialization(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, hashIndexField, CHRHashIndex, hashClass.getClassName()));\r
+ }\r
+ }\r
+ \r
+ // Method: get\r
+ \r
+ hashIndexInitializations.add(new StoreInitialization(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, constraint.name + "$temp", factTypeDesc, factClassName));\r
+\r
+ \r
+ {\r
+ /*\r
+ public ExampleFact ExampleFact$bf(int c0) {\r
+ ExampleFact$temp.c0 = c0;\r
+ return (ExampleFact)ExampleFact_bfIndex.getEqual(ExampleFact$temp);\r
+ }\r
+ */\r
+ for(IndexInfo indexInfo : constraint.getIndices()) {\r
+ /*if(indexInfo.indexMask == 0) {\r
+ MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, constraint.name + "$" + indexInfo.indexName,\r
+ factTypeDesc, Constants.EMPTY_TYPEDESC_ARRAY);\r
+ mb.loadThis();\r
+ mb.loadField(storeClassBuilder.getClassName(), constraint.name + "$" + indexInfo.indexName, factTypeDesc);\r
+ mb.returnValue(factTypeDesc);\r
+ mb.finish();\r
+ }*/\r
+ if(indexInfo.indexMask != 0) {\r
+ ArrayList<TypeDesc> getParameterTypeDescs = new ArrayList<TypeDesc>(constraint.parameterTypes.length);\r
+ for(int i=0;i<constraint.parameterTypes.length;++i)\r
+ if(((indexInfo.indexMask>>i)&1)==1)\r
+ getParameterTypeDescs.add(parameterTypeDescs[i]);\r
+ MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, constraint.name + "$" + indexInfo.indexName, factTypeDesc,\r
+ getParameterTypeDescs.toArray(new TypeDesc[getParameterTypeDescs.size()]));\r
+ mb.loadThis();\r
+ mb.loadField(storeClassBuilder.getClassName(), constraint.name + "$temp", factTypeDesc);\r
+ LocalVariable tempFactVar = mb.createLocalVariable("temp", factTypeDesc);\r
+ mb.storeLocal(tempFactVar);\r
+ int parameterId=0;\r
+ for(int i=0;i<constraint.parameterTypes.length;++i)\r
+ if(((indexInfo.indexMask>>i)&1)==1) {\r
+ mb.loadLocal(tempFactVar);\r
+ mb.loadLocal(mb.getParameter(parameterId++));\r
+ mb.storeField(factClassName, "c"+i, parameterTypeDescs[i]);\r
+ }\r
+\r
+ mb.loadThis();\r
+ mb.loadField(storeClassBuilder.getClassName(), constraint.name + "$" + indexInfo.indexName, CHRHashIndex);\r
+ mb.loadLocal(tempFactVar);\r
+ mb.invokeVirtual(CHRHashIndex_name, supportsRemoval ? "getEqual" : "getEqualNoRemovals", TypeDesc.OBJECT, Constants.OBJECTS[1]);\r
+ mb.checkCast(factTypeDesc);\r
+ \r
+ mb.returnValue(factTypeDesc);\r
+ mb.finish();\r
+ }\r
+ } \r
+ }\r
+ \r
+ // Method: add\r
+ \r
+ {\r
+ MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "add", TypeDesc.VOID, storeTypeDescArray);\r
+ LocalVariable storeParameter = mb.getParameter(0);\r
+ for(IndexInfo indexInfo : constraint.getIndices()) {\r
+ String linkedListPrev = indexInfo.indexName + "Prev";\r
+ String linkedListNext = indexInfo.indexName + "Next";\r
+ String storeHashIndexName = constraint.name + "$" + indexInfo.indexName;\r
+ \r
+ // public void add(ExampleStore store) {\r
+ // bfNext = (ExampleFact)store.ExampleFact_bfIndex.addFreshAndReturnOld(this);\r
+ // if(bfNext != null)\r
+ // bfNext.bfPrev = this;\r
+ // }\r
+ \r
+ if(indexInfo.indexMask == 0) {\r
+ mb.loadThis();\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc);\r
+ if(supportsRemoval)\r
+ mb.dupX1();\r
+ mb.storeField(factClassName, linkedListNext, factTypeDesc);\r
+ if(supportsRemoval) {\r
+ Label cont = new Label();\r
+ mb.ifNullBranch(cont, true);\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ mb.loadThis();\r
+ mb.storeField(factClassName, linkedListPrev, factTypeDesc);\r
+ mb.setLocation(cont);\r
+ }\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadThis();\r
+ mb.storeField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc);\r
+ }\r
+ else {\r
+ // bfNext = (ExampleFact)store.ExampleFact_bfIndex.addFreshAndReturnOld(this);\r
+ mb.loadThis();\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, CHRHashIndex);\r
+ mb.loadThis();\r
+ mb.invokeVirtual(CHRHashIndex_name, supportsRemoval ? "addFreshAndReturnOld" : "addFreshAndReturnOld", TypeDesc.OBJECT, Constants.OBJECTS[1]);\r
+ mb.checkCast(factTypeDesc);\r
+ if(supportsRemoval)\r
+ mb.dupX1();\r
+ mb.storeField(factClassName, linkedListNext, factTypeDesc);\r
+ // leaves bfNext on the stack\r
+\r
+ //if(bfNext != null)\r
+ // bfNext.bfPrev = this;\r
+ if(supportsRemoval) {\r
+ Label cont = new Label();\r
+ mb.ifNullBranch(cont, true);\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ mb.loadThis();\r
+ mb.storeField(factClassName, linkedListPrev, factTypeDesc);\r
+ mb.setLocation(cont);\r
+ }\r
+ }\r
+ } \r
+ if(!constraint.isPassive()) {\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadField(storeClassBuilder.getClassName(), QUEUE, FactActivationQueue);\r
+ mb.loadConstant(constraint.getMinimumPriority());\r
+ mb.loadThis();\r
+ mb.invokeVirtual(FactActivationQueue_name, "add", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT, Fact});\r
+ }\r
+ mb.returnVoid();\r
+ mb.finish();\r
+ }\r
+ \r
+ // Method: remove\r
+\r
+ if(supportsRemoval) {\r
+ // public void remove(ExampleStore store) {\r
+ // if(bfPrev == null) {\r
+ // if(bfNext == null)\r
+ // store.ExampleFact_bfIndex.removeKnownToExistKey(this);\r
+ // else {\r
+ // bfNext.bfPrev = null;\r
+ // store.ExampleFact_bfIndex.replaceKnownToExistKey(this, bfNext);\r
+ // }\r
+ // }\r
+ // else {\r
+ // bfPrev.bfNext = bfNext;\r
+ // if(bfNext != null)\r
+ // bfNext.bfPrev = bfPrev;\r
+ // }\r
+ // }\r
+ \r
+ MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "remove", TypeDesc.VOID, storeTypeDescArray);\r
+ LocalVariable storeParameter = mb.getParameter(0);\r
+ for(IndexInfo indexInfo : constraint.getIndices()) {\r
+ String linkedListPrev = indexInfo.indexName + "Prev";\r
+ String linkedListNext = indexInfo.indexName + "Next";\r
+ String storeHashIndexName = constraint.name + "$" + indexInfo.indexName;\r
+ \r
+ Label nextIndex = mb.createLabel();\r
+ \r
+ // if(bfPrev == null) {\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListPrev, factTypeDesc);\r
+ Label else1 = new Label();\r
+ mb.ifNullBranch(else1, false);\r
+ \r
+ // if(bfNext == null)\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ Label else2 = new Label();\r
+ mb.ifNullBranch(else2, false);\r
+ \r
+ // store.ExampleFact_bfIndex.removeKnownToExistKey(this);\r
+ if(indexInfo.indexMask == 0) {\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadNull();\r
+ mb.storeField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc);\r
+ }\r
+ else {\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, CHRHashIndex);\r
+ mb.loadThis();\r
+ mb.invokeVirtual(CHRHashIndex_name, "removeKnownToExistKey", TypeDesc.VOID, Constants.OBJECTS[1]);\r
+ }\r
+ mb.branch(nextIndex);\r
+ \r
+ // else {\r
+ mb.setLocation(else2);\r
+ // bfNext.bfPrev = null;\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ mb.loadNull();\r
+ mb.storeField(factClassName, linkedListPrev, factTypeDesc);\r
+ // store.ExampleFact_bfIndex.replaceKnownToExistKey(this, bfNext);\r
+ if(indexInfo.indexMask == 0) {\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ mb.storeField(storeClassBuilder.getClassName(), storeHashIndexName, factTypeDesc);\r
+ }\r
+ else {\r
+ mb.loadLocal(storeParameter);\r
+ mb.loadField(storeClassBuilder.getClassName(), storeHashIndexName, CHRHashIndex);\r
+ mb.loadThis();\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ mb.invokeVirtual(CHRHashIndex_name, "replaceKnownToExistKey", TypeDesc.VOID, Constants.OBJECTS[2]);\r
+ }\r
+ mb.branch(nextIndex);\r
+ // }\r
+ \r
+ // else {\r
+ mb.setLocation(else1);\r
+ // bfPrev.bfNext = bfNext;\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListPrev, factTypeDesc);\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ mb.storeField(factClassName, linkedListNext, factTypeDesc);\r
+ // if(bfNext != null)\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ Label else3 = new Label();\r
+ mb.ifNullBranch(else3, true);\r
+ // bfNext.bfPrev = bfPrev;\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListNext, factTypeDesc);\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, linkedListPrev, factTypeDesc);\r
+ mb.storeField(factClassName, linkedListPrev, factTypeDesc);\r
+ mb.setLocation(else3);\r
+ mb.branch(nextIndex);\r
+ // }\r
+ \r
+ mb.setLocation(nextIndex);\r
+ }\r
+ mb.loadThis();\r
+ mb.loadConstant(-1);\r
+ mb.storeField(factClassName, "id", FACT_ID_TYPE);\r
+ mb.returnVoid();\r
+ mb.finish();\r
+ }\r
+ \r
+ // Method: isAlive\r
+\r
+ {\r
+ // @Override\r
+ // public boolean isAlive() {\r
+ // return id >= 0;\r
+ // }\r
+ \r
+ MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "isAlive", TypeDesc.BOOLEAN, Constants.EMPTY_TYPEDESC_ARRAY);\r
+ if(supportsRemoval) {\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, "id", FACT_ID_TYPE);\r
+\r
+ Label thenBranch = mb.createLabel();\r
+ mb.ifZeroComparisonBranch(thenBranch, "<");\r
+ mb.loadConstant(true);\r
+ mb.returnValue(TypeDesc.BOOLEAN);\r
+\r
+ mb.setLocation(thenBranch);\r
+ mb.loadConstant(false);\r
+ mb.returnValue(TypeDesc.BOOLEAN);\r
+ }\r
+ else {\r
+ mb.loadConstant(true);\r
+ mb.returnValue(TypeDesc.BOOLEAN);\r
+ }\r
+ mb.finish();\r
+ }\r
+ \r
+ // activate parts\r
+ \r
+ THashSet<BoundVar> usedParameters = new THashSet<BoundVar>();\r
+ for(int i=0;i<constraint.plans.size();++i) {\r
+ PrioritizedPlan plan = constraint.plans.get(i);\r
+ MethodBuilder mb = factClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "activate" + i, TypeDesc.BOOLEAN, new TypeDesc[] {storeTypeDesc});\r
+ LocalVariable storeVar = mb.getParameter(0);\r
+ LocalVariable factVar = new LocalVariable(0, factTypeDesc);\r
+ mb.setLocalVariable(ruleset.this_, storeVar);\r
+ mb.setLocalVariable(plan.implementation.getParameters()[0], factVar);\r
+ \r
+ // Set closure parameters\r
+ usedParameters.clear();\r
+ plan.implementation.forValRefs(valRef -> {\r
+ if(valRef.getBinding() instanceof BoundVar)\r
+ usedParameters.add((BoundVar)valRef.getBinding());\r
+ });\r
+ for(int j=0;j<ruleset.parameters.length;++j) {\r
+ BoundVar parameter = ruleset.parameters[j];\r
+ if(!usedParameters.contains(parameter))\r
+ continue;\r
+ mb.loadLocal(storeVar);\r
+ mb.loadField(storeClassBuilder.getClassName(), "p"+j, ruleset.parameterTypeDescs[j]);\r
+ mb.store(parameter);\r
+ }\r
+ \r
+ // Generate code\r
+ //System.out.println("=== activate" + i + " ==========================================================");\r
+ //System.out.println(plan.implementation);\r
+ plan.implementation.markGenerateOnFly();\r
+ plan.implementation.generateCodeWithAlreadyPreparedParameters(mb);\r
+ mb.finish();\r
+ }\r
+ \r
+ // Method: activate\r
+\r
+ {\r
+ // @Override\r
+ // public int activate(Object context, int priority) {\r
+ // return -1;\r
+ // }\r
+ \r
+ MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.INT, new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.INT});\r
+ Label defaultLabel = mb.createLabel();\r
+ \r
+ if(!constraint.isPassive()) {\r
+ // Check if the fact is alive\r
+ mb.loadThis();\r
+ mb.loadField(factClassName, "id", TypeDesc.INT);\r
+ mb.ifZeroComparisonBranch(defaultLabel, "<");\r
+\r
+ mb.loadLocal(mb.getParameter(0));\r
+ mb.checkCast(storeTypeDesc);\r
+ LocalVariable storeVariable = new LocalVariable(1, storeTypeDesc);\r
+ mb.storeLocal(storeVariable);\r
+\r
+ TIntArrayList priorities = new TIntArrayList(constraint.plans.size());\r
+ ArrayList<Label> labels = new ArrayList<Label>();\r
+ int lastPriority = -1;\r
+ for(PrioritizedPlan plan : constraint.plans)\r
+ if(plan.priority != lastPriority) {\r
+ priorities.add(plan.priority);\r
+ labels.add(mb.createLabel());\r
+ lastPriority = plan.priority;\r
+ }\r
+\r
+ mb.loadLocal(mb.getParameter(1));\r
+ mb.switch_(priorities.toArray(), labels.toArray(new Label[labels.size()]), defaultLabel);\r
+ int labelId = -1;\r
+ for(int i=0;i<constraint.plans.size();++i) {\r
+ PrioritizedPlan plan = constraint.plans.get(i);\r
+ if(labelId == -1 || plan.priority != priorities.get(labelId)) {\r
+ if(labelId >= 0) {\r
+ mb.loadConstant(plan.priority);\r
+ mb.returnValue(TypeDesc.INT);\r
+ }\r
+ ++labelId;\r
+ mb.setLocation(labels.get(labelId));\r
+ }\r
+ mb.loadThis();\r
+ mb.loadLocal(storeVariable);\r
+ mb.invokeVirtual(factClassName, "activate" + i, TypeDesc.BOOLEAN, new TypeDesc[] {storeTypeDesc});\r
+ mb.ifZeroComparisonBranch(defaultLabel, "==");\r
+ }\r
+ mb.setLocation(defaultLabel);\r
+ }\r
+ mb.loadConstant(-1);\r
+ mb.returnValue(TypeDesc.INT);\r
+ mb.finish();\r
+ }\r
+ \r
+ // Constructors\r
+ \r
+ {\r
+ // public ExampleFact(int id, int c0, int c1) {\r
+ // this.id = id; \r
+ // this.c0 = c0;\r
+ // this.c1 = c1;\r
+ // }\r
+ \r
+ TypeDesc[] constructorParameters = new TypeDesc[parameterTypeDescs.length+1];\r
+ constructorParameters[0] = FACT_ID_TYPE;\r
+ for(int i=0;i<parameterTypeDescs.length;++i)\r
+ constructorParameters[i+1] = parameterTypeDescs[i];\r
+ MethodBuilderBase mb = factClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, constructorParameters);\r
+ mb.loadThis();\r
+ mb.invokeConstructor(factClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);\r
+ mb.loadThis();\r
+ mb.loadLocal(mb.getParameter(0));\r
+ mb.storeField(factClassName, "id", FACT_ID_TYPE);\r
+ for(int i=0;i<constraint.parameterTypes.length;++i) {\r
+ mb.loadThis();\r
+ mb.loadLocal(mb.getParameter(i+1));\r
+ mb.storeField(factClassName, "c" + i, parameterTypeDescs[i]);\r
+ }\r
+ mb.returnVoid();\r
+ mb.finish();\r
+ }\r
+ factClassBuilder.addDefaultConstructor();\r
+ \r
+ moduleBuilder.addClass(factClassBuilder);\r
+ }\r
+\r
+ private static ClassBuilder generateSpecializedHashIndex(ClassBuilder storeClassBuilder, CHRConstraint constraint, IndexInfo indexInfo, TypeDesc factClassTypeDesc, String factClassName) {\r
+ // new CHRHashIndex() {\r
+ // @Override\r
+ // protected boolean keyEquals(Object a, Object b) {\r
+ // return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;\r
+ // }\r
+ // @Override\r
+ // protected int keyHashCode(Object key) {\r
+ // return ((ExampleFact)key).c0;\r
+ // }\r
+ // }\r
+\r
+ ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder();\r
+ JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator();\r
+ \r
+ String hashIndexClassName = factClassName + "$" + indexInfo.indexName; \r
+ ClassBuilder hashIndexClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, hashIndexClassName, "org/simantics/scl/runtime/chr/CHRHashIndex");\r
+ \r
+ // Method: keyEquals\r
+\r
+ {\r
+\r
+ // @Override\r
+ // protected boolean keyEquals(Object a, Object b) {\r
+ // return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;\r
+ // }\r
+ \r
+ MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyEquals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);\r
+ mb.loadLocal(mb.getParameter(0));\r
+ mb.checkCast(factClassTypeDesc);\r
+ LocalVariable aVar = mb.createLocalVariable("a", factClassTypeDesc);\r
+ mb.storeLocal(aVar);\r
+ \r
+ mb.loadLocal(mb.getParameter(1));\r
+ mb.checkCast(factClassTypeDesc);\r
+ LocalVariable bVar = mb.createLocalVariable("b", factClassTypeDesc);\r
+ mb.storeLocal(bVar);\r
+\r
+ Label failure = mb.createLabel();\r
+ \r
+ int curMask = indexInfo.indexMask;\r
+ for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)\r
+ if((curMask&1) == 1) {\r
+ TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);\r
+ if(fieldTypeDesc.equals(TypeDesc.VOID))\r
+ continue;\r
+ mb.loadLocal(aVar);\r
+ mb.loadField(factClassName, "c"+i, fieldTypeDesc);\r
+ \r
+ mb.loadLocal(bVar);\r
+ mb.loadField(factClassName, "c"+i, fieldTypeDesc);\r
+\r
+ CodeBuilderUtils.equals(mb, fieldTypeDesc, failure);\r
+ }\r
+ mb.loadConstant(true);\r
+ mb.returnValue(TypeDesc.BOOLEAN);\r
+ \r
+ mb.setLocation(failure);\r
+ mb.loadConstant(false);\r
+ mb.returnValue(TypeDesc.BOOLEAN);\r
+ mb.finish();\r
+ }\r
+ \r
+ // Method: keyHashCode\r
+\r
+ {\r
+ // @Override\r
+ // protected int keyHashCode(Object key) {\r
+ // return (0x811C9DC5^((ExampleFact)key).c0)*16777619;\r
+ // }\r
+ \r
+ MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyHashCode", TypeDesc.INT, Constants.OBJECTS[1]);\r
+ mb.loadLocal(mb.getParameter(0));\r
+ mb.checkCast(factClassTypeDesc);\r
+ LocalVariable factVar = mb.createLocalVariable("fact", factClassTypeDesc);\r
+ mb.storeLocal(factVar);\r
+\r
+ mb.loadConstant(0x811C9DC5);\r
+\r
+ int curMask = indexInfo.indexMask;\r
+ for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)\r
+ if((curMask&1) == 1) {\r
+ TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);\r
+ if(fieldTypeDesc.equals(TypeDesc.VOID))\r
+ continue;\r
+ mb.loadLocal(factVar);\r
+ mb.loadField(factClassName, "c"+i, fieldTypeDesc);\r
+ CodeBuilderUtils.hashCode(mb, fieldTypeDesc);\r
+ mb.math(Opcodes.IXOR);\r
+ mb.loadConstant(16777619);\r
+ mb.math(Opcodes.IMUL);\r
+\r
+ }\r
+ mb.returnValue(TypeDesc.INT);\r
+ mb.finish();\r
+ }\r
+\r
+ hashIndexClassBuilder.addDefaultConstructor();\r
+ \r
+ return hashIndexClassBuilder;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.chr;\r
+\r
+import org.simantics.scl.runtime.chr.CHRHashIndex;\r
+import org.simantics.scl.runtime.chr.Fact;\r
+import org.simantics.scl.runtime.chr.FactActivationQueue;\r
+\r
+public class ExampleStore {\r
+ /*\r
+ * constraint ExampleFact Integer Integer where\r
+ * index(bf)\r
+ * \r
+ * =>\r
+ * \r
+ * data Store // class Module$123\r
+ * data ExampleFact // class Module$123/ExampleFact\r
+ * \r
+ * add :: Store -> ExampleFact -> <Proc> ()\r
+ * remove :: Store -> ExampleFact -> <Proc> ()\r
+ * get_bf :: Store -> Integer -> <Proc> ExampleFact\r
+ * next_bf :: ExampleFact -> <Proc> Maybe ExampleFact\r
+ * idOf :: ExampleFact -> <Proc> Integer\r
+ * isAlive :: ExampleFact -> <Proc> Boolean\r
+ */\r
+ \r
+ CHRHashIndex ExampleFact_bfIndex = new CHRHashIndex() {\r
+ @Override\r
+ protected boolean keyEquals(Object a, Object b) {\r
+ return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;\r
+ }\r
+ @Override\r
+ protected int keyHashCode(Object key) {\r
+ return ((ExampleFact)key).c0;\r
+ }\r
+ };\r
+ \r
+ public FactActivationQueue queue = new FactActivationQueue(2);\r
+ \r
+ private ExampleFact ExampleFact_temp = new ExampleFact();\r
+ \r
+ public ExampleFact getExampleFact_bf(int c0) {\r
+ ExampleFact_temp.c0 = c0;\r
+ return (ExampleFact)ExampleFact_bfIndex.getEqual(ExampleFact_temp);\r
+ }\r
+ \r
+ public static class ExampleFact implements Fact {\r
+ public int id;\r
+ public int c0; // key\r
+ public int c1;\r
+ public ExampleFact bfPrev;\r
+ public ExampleFact bfNext;\r
+ \r
+ public ExampleFact() {\r
+ }\r
+ \r
+ public ExampleFact(int c0, int c1) {\r
+ this.c0 = c0;\r
+ this.c1 = c1;\r
+ }\r
+ \r
+ public void add(ExampleStore store) {\r
+ bfNext = (ExampleFact)store.ExampleFact_bfIndex.addFreshAndReturnOld(this);\r
+ if(bfNext != null)\r
+ bfNext.bfPrev = this;\r
+ }\r
+ \r
+ public void remove(ExampleStore store) {\r
+ if(bfPrev == null) {\r
+ if(bfNext == null)\r
+ store.ExampleFact_bfIndex.removeKnownToExistKey(this);\r
+ else {\r
+ bfNext.bfPrev = null;\r
+ store.ExampleFact_bfIndex.replaceKnownToExistKey(this, bfNext);\r
+ }\r
+ }\r
+ else {\r
+ bfPrev.bfNext = bfNext;\r
+ if(bfNext != null)\r
+ bfNext.bfPrev = bfPrev;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public int activate(Object context, int priority) {\r
+ return -1;\r
+ }\r
+\r
+ @Override\r
+ public boolean isAlive() {\r
+ return id >= 0;\r
+ }\r
+ }\r
+\r
+}\r
package org.simantics.scl.compiler.internal.codegen.optimization;\r
\r
import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
import org.simantics.scl.compiler.constants.SCLConstant;\r
import org.simantics.scl.compiler.internal.codegen.analysis.StatementBrowser;\r
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
\r
public enum FoldlBuildFusion implements Optimization {\r
INSTANCE;\r
-\r
- private static final Name BUILD = Name.create("Prelude", "build");\r
\r
private static class Analysis extends StatementBrowser {\r
\r
Val buildFunction = buildApplication.getFunction().getBinding();\r
if(!(buildFunction instanceof SCLConstant))\r
return;\r
- if(((SCLConstant)buildFunction).getName() != BUILD)\r
+ if(((SCLConstant)buildFunction).getName() != Names.Prelude_build)\r
return;\r
}\r
\r
package org.simantics.scl.compiler.internal.codegen.optimization;\r
\r
import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.common.names.Names;\r
\r
import gnu.trove.map.hash.THashMap;\r
\r
public static final THashMap<Name, Optimization> OPTIMIZATIONS = new THashMap<Name, Optimization>();\r
\r
static {\r
- OPTIMIZATIONS.put(Name.create("Prelude", "foldl"), FoldlBuildFusion.INSTANCE);\r
+ OPTIMIZATIONS.put(Names.Prelude_foldl, FoldlBuildFusion.INSTANCE);\r
}\r
\r
}\r
return occurrence;\r
}\r
\r
- private void replaceBy(Val other) {\r
+ public void replaceBy(Val other) {\r
ValRef cur = occurrence;\r
if(cur != null) {\r
while(true) {\r
import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
stat.prepare(mb);\r
exit.prepare(mb);\r
}\r
+\r
+ public void forValRefs(ValRefVisitor visitor) {\r
+ for(SSAStatement statement = firstStatement;\r
+ statement != null; statement = statement.next)\r
+ statement.forValRefs(visitor);\r
+ exit.forValRefs(visitor);\r
+ }\r
\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.ssa;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.BoundVarBinder;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ClosureBinder;\r
+import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;\r
+import org.simantics.scl.compiler.internal.codegen.utils.Printable;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+public abstract class SSAClosure implements Printable, BoundVarBinder{ \r
+ Val target;\r
+ \r
+ ClosureBinder parent;\r
+ SSAClosure prev;\r
+ SSAClosure next;\r
+ \r
+ public void setParent(ClosureBinder parent) {\r
+ this.parent = parent;\r
+ }\r
+\r
+ public SSAClosure getNext() {\r
+ return next;\r
+ }\r
+\r
+ public void setPrev(SSAClosure function) {\r
+ this.prev = function;\r
+ }\r
+\r
+ public void setNext(SSAClosure function) {\r
+ this.next = function;\r
+ }\r
+\r
+ public SSAFunction getParentFunction() {\r
+ return parent.getParentFunction();\r
+ }\r
+ \r
+ public ClosureBinder getParent() {\r
+ return parent;\r
+ }\r
+\r
+ public Val getTarget() {\r
+ return target;\r
+ }\r
+ \r
+ public void setTarget(Val target) {\r
+ this.target = target;\r
+ if(target instanceof BoundVar)\r
+ ((BoundVar) target).parent = this; \r
+ }\r
+ \r
+ public void setTarget(BoundVar target) {\r
+ this.target = target;\r
+ target.parent = this; \r
+ }\r
+ \r
+ public void detach() {\r
+ if(prev == null)\r
+ parent.setFirstClosure(next);\r
+ else\r
+ prev.next = next;\r
+ if(next != null)\r
+ next.prev = prev;\r
+ }\r
+ \r
+ public void remove() {\r
+ destroy();\r
+ detach();\r
+ }\r
+\r
+ public SSAClosure copy() {\r
+ return copy(new CopyContext());\r
+ }\r
+ \r
+ public abstract void destroy();\r
+ public abstract SSAClosure copy(CopyContext context);\r
+ public abstract void markGenerateOnFly();\r
+ public abstract void replace(TVar[] vars, Type[] replacements);\r
+ public abstract void collectFreeVariables(ArrayList<ValRef> freeVars);\r
+ public abstract void simplify(SSASimplificationContext context);\r
+ public abstract void validate(SSAValidationContext context);\r
+ public abstract void lambdaLift(SSALambdaLiftingContext context);\r
+ public abstract boolean isValue();\r
+ public abstract Type getType();\r
+ public abstract void parametrize(BoundVar[] parameters);\r
+\r
+ public Constant liftClosure(BoundVar newTarget, BoundVar[] newVarsList) {\r
+ throw new InternalCompilerError("Unsupported method liftClosure");\r
+ }\r
+\r
+ public void generateCode(ModuleBuilder moduleBuilder) {\r
+ throw new InternalCompilerError("Unsupported method generateCode");\r
+ }\r
+\r
+ public abstract void forValRefs(ValRefVisitor visitor);\r
+ \r
+}\r
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.Types;\r
\r
public void prepare(MethodBuilder mb) {\r
}\r
+\r
+ public abstract void forValRefs(ValRefVisitor visitor);\r
}
\ No newline at end of file
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
import org.simantics.scl.compiler.internal.codegen.references.Val;
import org.simantics.scl.compiler.internal.codegen.references.ValRef;
-import org.simantics.scl.compiler.internal.codegen.ssa.binders.BoundVarBinder;
-import org.simantics.scl.compiler.internal.codegen.ssa.binders.FunctionBinder;
import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;
import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions;
import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
-import org.simantics.scl.compiler.internal.codegen.utils.Printable;
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
-public final class SSAFunction implements Printable, BoundVarBinder {
- Val target;
-
+public final class SSAFunction extends SSAClosure {
TVar[] typeParameters;
Type effect;
SSABlock firstBlock;
SSABlock lastBlock;
- ReturnCont returnCont;
-
- FunctionBinder parent;
- SSAFunction prev;
- SSAFunction next;
+ ReturnCont returnCont;
public SSAFunction(TVar[] typeParameters, Type effect, Type returnType) {
this(typeParameters, effect, new ReturnCont(returnType));
this.effect = Types.canonical(effect);
returnCont.setParent(this);
}
-
- public Val getTarget() {
- return target;
- }
-
- public void setTarget(Val target) {
- this.target = target;
- if(target instanceof BoundVar)
- ((BoundVar) target).parent = this;
- }
-
- public void setTarget(BoundVar target) {
- this.target = target;
- target.parent = this;
- }
public boolean hasEffect() {
return effect != Types.NO_EFFECTS;
for(int i=0,j=0;i<firstBlock.parameters.length;++i)
if(!tt.toTypeDesc(firstBlock.parameters[i].getType()).equals(TypeDesc.VOID))
mb.setLocalVariable(firstBlock.parameters[i], mb.getParameter(j++));
+ generateCodeWithAlreadyPreparedParameters(mb);
+ }
+
+ public void generateCodeWithAlreadyPreparedParameters(MethodBuilder mb) {
for(SSABlock block = firstBlock; block != null; block = block.next)
block.prepare(mb);
firstBlock.generateCode(mb);
//context.reset(); // FIXME not good when there are nested functions
}
- public void simplify(SSASimplificationContext context) {
- /*if(target instanceof BoundVar) {
- tryToMakeMonadic(context);
- }*/
+ @Override
+ public void simplify(SSASimplificationContext context) {
for(SSABlock block = firstBlock; block != null; block = block.next)
block.simplify(context);
if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement &&
private void simplifySingleLambda(SSASimplificationContext context) {
LetFunctions letF = (LetFunctions)firstBlock.firstStatement;
- SSAFunction f = letF.getFirstFunction();
+ if(!(letF.getFirstClosure() instanceof SSAFunction))
+ return;
+ SSAFunction f = (SSAFunction)letF.getFirstClosure();
if(f.getNext() != null)
return;
Val fVal = f.getTarget();
this.returnCont = returnCont;
returnCont.setParent(this);
}
-
- /*public void tryToMakeMonadic(SSASimplificationContext context) {
- if(monadic)
- return;
- if(!Types.isApply(BTypes.PROC, 1, getReturnType()))
- return;
- for(ValRef ref = target.getOccurrence(); ref != null; ref = ref.getNext()) {
- ValRefBinder parent = ref.getParent();
- if(!(parent instanceof LetApply))
- return;
- LetApply apply = (LetApply)parent;
- if(apply.getFunction() != ref)
- return;
- if(apply.getParameters().length != getParameters().length)
- return;
- if(!apply.hasEffect())
- return;
- }
- makeMonadic(context);
- }*/
-
- /*private void makeMonadic(SSASimplificationContext context) {
- Type oldReturnType = returnCont.getType();
- Type newReturnType;
- try {
- newReturnType = Types.matchApply(BTypes.PROC, oldReturnType);
- } catch (MatchException e) {
- throw new InternalCompilerError();
- }
-
- //
- returnCont.setType(newReturnType);
- monadic = true;
-
- //
- SSABlock block = new SSABlock(oldReturnType);
- addBlock(block);
-
- returnCont.replaceWith(block);
-
- BoundVar x = new BoundVar(newReturnType);
- LetApply apply = new LetApply(x, block.parameters[0].createOccurrence());
- apply.setMonadic(true);
- block.addStatement(apply);
-
- block.setExit(new Jump(returnCont.createOccurrence(), x.createOccurrence()));
- context.markModified("SSAFunction.make-monadic");
- }*/
public ValRef isEqualToConstant() {
if(firstBlock.parameters.length > 0)
return firstBlock.parameters.length;
}
+ @Override
public void markGenerateOnFly() {
for(SSABlock block = firstBlock; block != null; block = block.next)
block.markGenerateOnFly();
}
- public SSAFunction copy(CopyContext context) {
+ @Override
+ public SSAClosure copy(CopyContext context) {
TVar[] newTypeParameters = context.copyParameters(typeParameters);
SSAFunction newFunction = new SSAFunction(newTypeParameters, effect, context.copy(returnCont));
for(SSABlock block = firstBlock;
newFunction.addBlock(context.copy(block));
return newFunction;
}
-
- public SSAFunction copy() {
- return copy(new CopyContext());
- }
-
+
+ @Override
public void replace(TVar[] vars, Type[] replacements) {
returnCont.replace(vars, replacements);
for(SSABlock block = firstBlock;
this.typeParameters = typeParameters;
}
+ @Override
public Type getType() {
Type type = returnCont.getType();
type = Types.functionE(
return returnCont.getType();
}
+ @Override
public void destroy() {
for(SSABlock block = firstBlock;
block != null; block = block.next)
block.destroy();
}
- public void detach() {
- if(prev == null)
- parent.setFirstFunction(next);
- else
- prev.next = next;
- if(next != null)
- next.prev = prev;
- }
-
- public void remove() {
- destroy();
- detach();
- }
-
- public void addSibling(SSAFunction function) {
- function.parent = parent;
- function.next = next;
- function.prev = this;
-
- next.prev = function;
- next = function;
- }
-
- public SSAFunction getNext() {
- return next;
- }
-
- public void setParent(FunctionBinder parent) {
- this.parent = parent;
- }
-
- public void setPrev(SSAFunction function) {
- this.prev = function;
- }
-
- public void setNext(SSAFunction function) {
- this.next = function;
- }
-
+ @Override
public void collectFreeVariables(ArrayList<ValRef> vars) {
for(SSABlock block = firstBlock;
block != null; block = block.next)
block.collectFreeVariables(this, vars);
}
-
- @Override
- public SSAFunction getParentFunction() {
- return parent.getParentFunction();
- }
-
- public FunctionBinder getParent() {
- return parent;
- }
+ @Override
public void lambdaLift(SSALambdaLiftingContext context) {
for(SSABlock block = firstBlock;
block != null; block = block.next)
block.lambdaLift(context);
}
- public void addParametersInFront(BoundVar[] parameters) {
+ @Override
+ public void parametrize(BoundVar[] parameters) {
Cont proxy = null;
for(ContRef ref = firstBlock.getOccurrence(); ref != null; ref = ref.getNext())
proxy = ref.addParametersInFront(parameters, firstBlock.parameters, proxy);
return effect;
}
- public int getBlockCount() {
- int count = 0;
- for(SSABlock block = firstBlock;block != null;block = block.next)
- ++count;
- return count;
+ @Override
+ public boolean isValue() {
+ return getArity() == 0;
+ }
+
+ @Override
+ public void forValRefs(ValRefVisitor visitor) {
+ for(SSABlock block = firstBlock;
+ block != null; block = block.next)
+ block.forValRefs(visitor);
}
}
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
-import org.simantics.scl.compiler.types.Type;
-import org.simantics.scl.runtime.tuple.Tuple2;
import gnu.trove.map.hash.THashMap;
import gnu.trove.procedure.TObjectObjectProcedure;
public class SSAModule {
THashMap<Name, SCLConstant> functions = new THashMap<Name, SCLConstant>();
- ArrayList<Tuple2> staticFields = new ArrayList<Tuple2>();
+ ArrayList<StaticField> staticFields = new ArrayList<StaticField>();
+ public ArrayList<SSAClosure> closuresToGenerate = new ArrayList<SSAClosure>();
public void put(Name name, SCLConstant function) {
functions.put(name, function);
});
JavaTypeTranslator javaTypeTranslator = moduleBuilder.getJavaTypeTranslator();
- for(Tuple2 tuple : staticFields) {
- classFile.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, (String)tuple.c0,
- javaTypeTranslator.toTypeDesc((Type)tuple.c1));
+ for(StaticField tuple : staticFields) {
+ classFile.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, tuple.name,
+ javaTypeTranslator.toTypeDesc(tuple.type));
}
classFile.addDefaultConstructor();
moduleBuilder.addClass(classFile);
+
+ for(SSAClosure closure : closuresToGenerate)
+ closure.generateCode(moduleBuilder);
}
/**
});
}
- public void addStaticField(Tuple2 tuple) {
+ public void addStaticField(StaticField tuple) {
staticFields.add(tuple);
}
--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.ssa;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ClosureBinder;\r
+import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.internal.codegen.writer.ModuleWriter;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+public class SSAObject extends SSAClosure implements ClosureBinder {\r
+ Type type;\r
+ SSAClosure firstClosure;\r
+ \r
+ public SSAObject(Type type) {\r
+ this.type = type;\r
+ }\r
+\r
+ @Override\r
+ public void toString(PrintingContext context) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ context.indentation();\r
+ context.append(closure.getTarget());\r
+ context.append("(" + closure.getTarget().occurrenceCount() + ")");\r
+ context.append(" :: ");\r
+ context.append(closure.getTarget().getType());\r
+ context.append(" = \n");\r
+ context.indent();\r
+ closure.toString(context);\r
+ context.dedent();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public SSAClosure getFirstClosure() {\r
+ return firstClosure;\r
+ }\r
+ \r
+ @Override\r
+ public void setFirstClosure(SSAClosure function) {\r
+ this.firstClosure = function; \r
+ if(function == null)\r
+ detach();\r
+ }\r
+ \r
+ @Override\r
+ public void destroy() {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.destroy();\r
+ }\r
+\r
+ @Override\r
+ public SSAClosure copy(CopyContext context) {\r
+ SSAObject result = new SSAObject(context.copyType(type));\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ SSAClosure newFunction = closure.copy(context);\r
+ newFunction.setTarget(context.copy(closure.getTarget()));\r
+ result.addClosure(newFunction);\r
+ }\r
+ return result; \r
+ }\r
+\r
+ public void addClosure(SSAClosure closure) {\r
+ closure.setParent(this); \r
+ closure.setNext(firstClosure);\r
+ if(firstClosure != null)\r
+ firstClosure.setPrev(closure);\r
+ firstClosure = closure;\r
+ }\r
+ \r
+ @Override\r
+ public void markGenerateOnFly() {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.markGenerateOnFly();\r
+ }\r
+\r
+ @Override\r
+ public void replace(TVar[] vars, Type[] replacements) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.replace(vars, replacements);\r
+ }\r
+\r
+ @Override\r
+ public void collectFreeVariables(ArrayList<ValRef> freeVars) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.collectFreeVariables(freeVars);\r
+ }\r
+\r
+ @Override\r
+ public void simplify(SSASimplificationContext context) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.simplify(context);\r
+ }\r
+\r
+ @Override\r
+ public void validate(SSAValidationContext context) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.validate(context);\r
+ }\r
+\r
+ @Override\r
+ public void lambdaLift(SSALambdaLiftingContext context) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.lambdaLift(context);\r
+ }\r
+\r
+ @Override\r
+ public boolean isValue() {\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public void parametrize(BoundVar[] parameters) {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ @Override\r
+ public Type getType() {\r
+ return type;\r
+ }\r
+ \r
+ public CodeWriter createMethod(ModuleWriter moduleWriter, TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {\r
+ SSAFunction function = new SSAFunction(typeParameters, effect, returnType);\r
+ SSABlock block = new SSABlock(parameterTypes);\r
+ function.addBlock(block);\r
+ BoundVar target = new BoundVar(function.getType());\r
+ function.setTarget(target);\r
+ addClosure(function);\r
+ return new CodeWriter(moduleWriter, block);\r
+ }\r
+\r
+ @Override\r
+ public void forValRefs(ValRefVisitor visitor) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.forValRefs(visitor);\r
+ }\r
+\r
+}\r
import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.Types;\r
\r
public void prepare(MethodBuilder mb) { \r
}\r
+\r
+ public abstract void forValRefs(ValRefVisitor visitor);\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.ssa;\r
+\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+public class StaticField {\r
+ public final String name;\r
+ public final Type type;\r
+ \r
+ public StaticField(String name, Type type) {\r
+ this.name = name;\r
+ this.type = type;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.ssa.binders;\r
+\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAClosure;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
+\r
+public interface ClosureBinder {\r
+ SSAClosure getFirstClosure();\r
+ void setFirstClosure(SSAClosure function);\r
+ SSAFunction getParentFunction();\r
+}\r
+++ /dev/null
-package org.simantics.scl.compiler.internal.codegen.ssa.binders;\r
-\r
-import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
-\r
-public interface FunctionBinder {\r
- SSAFunction getFirstFunction();\r
- void setFirstFunction(SSAFunction function);\r
- SSAFunction getParentFunction();\r
-}\r
import org.objectweb.asm.Label;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.BooleanConstant;
+import org.simantics.scl.compiler.constants.ComparisonFunction;
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.references.BoundVar;
import org.simantics.scl.compiler.internal.codegen.references.Val;
import org.simantics.scl.compiler.internal.codegen.references.ValRef;
import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAExit;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
@Override
public void generateCode(MethodBuilder mb) {
+ Val binding = condition.getBinding();
+ simplifyTestCode: if(binding instanceof BoundVar) {
+ BoundVar boundVar = (BoundVar)binding;
+ if(!boundVar.generateOnFly)
+ break simplifyTestCode;
+ LetApply apply = (LetApply)boundVar.getParent();
+ Val function = apply.getFunction().getBinding();
+ if(!(function instanceof ComparisonFunction))
+ break simplifyTestCode;
+
+ Val[] ps = ValRef.getBindings(apply.getParameters());
+ ((ComparisonFunction)function).generateCondition(mb, ps, thenTarget.getBinding(), elseTarget.getBinding());
+ return;
+ }
mb.push(condition.getBinding(), Types.BOOLEAN);
Label elseLabel = mb.getLabel(elseTarget.getBinding());
mb.ifZeroComparisonBranch(elseLabel, "==");
return SSABlock.EMPTY_ARRAY;
}
}
+
+ @Override
+ public void forValRefs(ValRefVisitor visitor) {
+ visitor.visit(condition);
+ }
}
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
\r
else\r
return SSABlock.EMPTY_ARRAY;\r
}\r
+\r
+ @Override\r
+ public void forValRefs(ValRefVisitor visitor) {\r
+ for(ValRef parameter : parameters)\r
+ visitor.visit(parameter);\r
+ }\r
}\r
import org.objectweb.asm.Label;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.BooleanConstant;
+import org.simantics.scl.compiler.constants.IntegerConstant;
import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
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.utils.PrintingContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
public BranchRef[] getBranches() {
return branches;
}
+
+ private boolean isIntegerSwitch() {
+ if(scrutinee.getType() != Types.INTEGER)
+ return false;
+ for(BranchRef branch : branches)
+ if(branch.constructor != null && !(branch.constructor instanceof IntegerConstant))
+ return false;
+ return true;
+ }
+
+ private void generateIntegerSwitch(MethodBuilder mb) {
+ int defaultId;
+ for(defaultId=0;defaultId<branches.length-1&&branches[defaultId].constructor!=null;++defaultId);
+ int[] values = new int[defaultId];
+ Label[] labels = new Label[defaultId];
+ Cont[] continuations = new Cont[defaultId+1];
+ for(int i=0;i<defaultId;++i) {
+ values[i] = ((IntegerConstant)branches[i].constructor).getValue();
+ Cont cont = branches[i].cont.getBinding();
+ labels[i] = mb.getLabel(cont);
+ continuations[i] = cont;
+ }
+ Label defaultLabel;
+ {
+ Cont cont = branches[defaultId].cont.getBinding();
+ defaultLabel = mb.getLabel(cont);
+ continuations[defaultId] = cont;
+ }
+ mb.push(scrutinee, Types.INTEGER);
+ mb.switch_(values, labels, defaultLabel);
+ for(Cont cont : continuations)
+ mb.ensureExists(cont);
+ }
@Override
public void generateCode(MethodBuilder mb) {
+ if(isIntegerSwitch()) {
+ generateIntegerSwitch(mb);
+ return;
+ }
for(int i=0;i<branches.length;++i) {
BranchRef branch = branches[i];
- if(branch.constructor == null) {
+ if(branch.constructor == null)
mb.jump(branch.cont);
- }
else if(i < branches.length-1) {
Label failure = mb.createLabel();
branch.constructor.deconstruct(mb, scrutinee,
branch.cont.getBinding(), failure);
mb.setLocation(failure);
}
- else {
+ else
branch.constructor.deconstruct(mb, scrutinee,
branch.cont.getBinding(), null);
- }
}
}
Cont cont = branch.cont.getBinding();
if(cont instanceof SSABlock) {
SSABlock block = (SSABlock)cont;
- if(cont.hasMoreThanOneOccurences()) {
+ //if(cont.hasMoreThanOneOccurences()) {
context.append(cont);
context.append('\n');
context.addBlock(block);
- }
+ /*}
else {
block.parametersToString(context);
context.append('\n');
block.bodyToString(context);
- }
+ }*/
}
else {
context.append(cont);
}
return result.toArray(new SSABlock[result.size()]);
}
+
+ @Override
+ public void forValRefs(ValRefVisitor visitor) {
+ visitor.visit(scrutinee);
+ }
}
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.runtime.exceptions.MatchingException;
public SSABlock[] getSuccessors() {
return SSABlock.EMPTY_ARRAY;
}
+
+ @Override
+ public void forValRefs(ValRefVisitor visitor) {
+ }
}
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.constants.SCLConstant;\r
import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;\r
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
import org.simantics.scl.compiler.internal.codegen.references.Val;\r
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
context.markModified("LetApply.dead-let-statement");\r
return;\r
}\r
+ // TODO this is quite heavy way for inlining constants\r
+ for(int i=0;i<parameters.length;++i) {\r
+ ValRef parameter = parameters[i];\r
+ Val value = parameter.getBinding();\r
+ if(!(value instanceof SCLConstant))\r
+ continue;\r
+ SCLConstant constant = (SCLConstant)value;\r
+ if(constant.inlineArity != 0)\r
+ continue;\r
+ SSAFunction definition = constant.definition;\r
+ SSABlock block = definition.getFirstBlock();\r
+ if(block.getFirstStatement() != null || !(block.getExit() instanceof Jump))\r
+ continue;\r
+ Jump jump = (Jump)block.getExit();\r
+ if(jump.getTarget().getBinding() != definition.getReturnCont())\r
+ continue;\r
+ if(jump.getParameter(0).getTypeParameters().length > 0)\r
+ continue;\r
+ parameter.replaceBy(jump.getParameter(0).getBinding());\r
+ }\r
Val functionVal = getFunction().getBinding();\r
if(functionVal instanceof BoundVar) {\r
BoundVarBinder parent_ = ((BoundVar)functionVal).parent;\r
public void prepare(MethodBuilder mb) {\r
function.getBinding().prepare(mb);\r
}\r
+\r
+ @Override\r
+ public void forValRefs(ValRefVisitor visitor) {\r
+ visitor.visit(function);\r
+ for(ValRef parameter : parameters)\r
+ visitor.visit(parameter);\r
+ }\r
}\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.constants.Constant;\r
import org.simantics.scl.compiler.constants.SCLConstant;\r
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAClosure;\r
import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
import org.simantics.scl.compiler.internal.codegen.ssa.SSAStatement;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.binders.FunctionBinder;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ClosureBinder;\r
import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
\r
import gnu.trove.map.hash.THashMap;\r
import gnu.trove.set.hash.THashSet;\r
\r
-public class LetFunctions extends SSAStatement implements FunctionBinder {\r
+public class LetFunctions extends SSAStatement implements ClosureBinder {\r
long recursiveGroupLocation;\r
- SSAFunction firstFunction;\r
+ SSAClosure firstClosure;\r
\r
public LetFunctions() {\r
}\r
\r
- public LetFunctions(SSAFunction function) {\r
- firstFunction = function;\r
- function.setParent(this);\r
+ public LetFunctions(SSAClosure closure) {\r
+ firstClosure = closure;\r
+ closure.setParent(this);\r
}\r
\r
@Override\r
public void toString(PrintingContext context) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
context.indentation();\r
- context.append(function.getTarget());\r
- context.append("(" + function.getTarget().occurrenceCount() + ")");\r
+ context.append(closure.getTarget());\r
+ context.append("(" + closure.getTarget().occurrenceCount() + ")");\r
context.append(" :: ");\r
- context.append(function.getTarget().getType());\r
+ context.append(closure.getTarget().getType());\r
context.append(" = \n");\r
context.indent();\r
- function.toString(context);\r
+ closure.toString(context);\r
context.dedent();\r
}\r
}\r
\r
- public void addFunction(SSAFunction function) {\r
- function.setParent(this); \r
- function.setNext(firstFunction);\r
- if(firstFunction != null)\r
- firstFunction.setPrev(function);\r
- firstFunction = function;\r
+ public void addClosure(SSAClosure closure) {\r
+ closure.setParent(this); \r
+ closure.setNext(firstClosure);\r
+ if(firstClosure != null)\r
+ firstClosure.setPrev(closure);\r
+ firstClosure = closure;\r
}\r
\r
@Override\r
\r
@Override\r
public void validate(SSAValidationContext context) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
- if(!(function.getTarget() instanceof BoundVar))\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ if(!(closure.getTarget() instanceof BoundVar))\r
throw new InternalCompilerError();\r
- function.validate(context);\r
+ closure.validate(context);\r
}\r
}\r
\r
@Override\r
public void destroy() {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext())\r
- function.destroy();\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.destroy();\r
}\r
\r
@Override\r
public SSAStatement copy(CopyContext context) {\r
LetFunctions result = new LetFunctions();\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
- SSAFunction newFunction = function.copy(context);\r
- newFunction.setTarget(context.copy(function.getTarget()));\r
- result.addFunction(newFunction);\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ SSAClosure newFunction = closure.copy(context);\r
+ newFunction.setTarget(context.copy(closure.getTarget()));\r
+ result.addClosure(newFunction);\r
}\r
return result; \r
}\r
\r
@Override\r
public void replace(TVar[] vars, Type[] replacements) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
- ((BoundVar)function.getTarget()).replace(vars, replacements);\r
- function.replace(vars, replacements);\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ ((BoundVar)closure.getTarget()).replace(vars, replacements);\r
+ closure.replace(vars, replacements);\r
}\r
}\r
\r
@Override\r
public void addBoundVariablesTo(SSAValidationContext context) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext())\r
- context.validBoundVariables.add((BoundVar)function.getTarget()); \r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ context.validBoundVariables.add((BoundVar)closure.getTarget()); \r
}\r
\r
@Override\r
- public SSAFunction getFirstFunction() {\r
- return firstFunction;\r
+ public SSAClosure getFirstClosure() {\r
+ return firstClosure;\r
}\r
\r
@Override\r
- public void setFirstFunction(SSAFunction function) {\r
- this.firstFunction = function; \r
+ public void setFirstClosure(SSAClosure function) {\r
+ this.firstClosure = function; \r
if(function == null)\r
detach();\r
}\r
boolean hasValues = false;\r
boolean isRecursive = false;\r
\r
- // Lambda lift functions and collect free variables\r
+ // Lambda lift substructure and collect free variables\r
THashSet<BoundVar> targets = new THashSet<BoundVar>();\r
ArrayList<ValRef> freeVars = new ArrayList<ValRef>(); \r
- for(SSAFunction function = firstFunction; \r
- function != null; \r
- function = function.getNext()) {\r
- hasValues |= function.getArity() == 0;\r
- function.lambdaLift(context);\r
- targets.add((BoundVar)function.getTarget());\r
- function.collectFreeVariables(freeVars);\r
+ for(SSAClosure closure = firstClosure; \r
+ closure != null; \r
+ closure = closure.getNext()) {\r
+ hasValues |= closure.isValue();\r
+ closure.lambdaLift(context);\r
+ targets.add((BoundVar)closure.getTarget());\r
+ closure.collectFreeVariables(freeVars);\r
+ }\r
+ \r
+ if(!(firstClosure instanceof SSAFunction) && firstClosure.getNext() == null) {\r
+ THashMap<BoundVar, BoundVar> varMap = new THashMap<BoundVar, BoundVar>(); \r
+ ArrayList<BoundVar> oldVarsList = new ArrayList<BoundVar>(4);\r
+ ArrayList<BoundVar> newVarsList = new ArrayList<BoundVar>(4);\r
+ BoundVar newTarget = null;\r
+ for(ValRef ref : freeVars) {\r
+ BoundVar var = (BoundVar)ref.getBinding();\r
+ if(targets.contains(var)) {\r
+ if(newTarget == null)\r
+ newTarget = new BoundVar(var.getType());\r
+ ref.replaceBy(newTarget);\r
+ continue;\r
+ }\r
+ BoundVar newVar = varMap.get(var);\r
+ if(newVar == null) {\r
+ newVar = new BoundVar(var.getType());\r
+ oldVarsList.add(var);\r
+ newVarsList.add(newVar);\r
+ varMap.put(var, newVar);\r
+ }\r
+ ref.replaceBy(newVar);\r
+ }\r
+ Constant constant = firstClosure.liftClosure(newTarget, newVarsList.toArray(new BoundVar[newVarsList.size()]));\r
+ new LetApply(targets.iterator().next(), Types.PROC, constant.createOccurrence(), ValRef.createOccurrences(oldVarsList))\r
+ .insertBefore(this);\r
+ detach();\r
+ context.addClosure(firstClosure);\r
+ return;\r
}\r
\r
// Classify by BoundVars\r
if(boundVars.add(var))\r
boundVarsList.add(var);\r
newFreeVars.add(ref);\r
- /*BoundVar inVar = map.get(outVar);\r
- if(inVar == null) {\r
- inVar = new BoundVar(outVar.getType());\r
- map.put(outVar, inVar);\r
- outParameters.add(outVar);\r
- inParameters.add(inVar);\r
- }\r
- ref.replaceBy(inVar);*/\r
}\r
BoundVar[] outVars = boundVarsList.toArray(new BoundVar[boundVarsList.size()]);\r
freeVars = newFreeVars;\r
\r
// Modify functions\r
- THashMap<SSAFunction, THashMap<BoundVar, BoundVar>> varMap = new THashMap<SSAFunction, THashMap<BoundVar, BoundVar>>();\r
- THashMap<SSAFunction, BoundVar[]> inVarsMap = new THashMap<SSAFunction, BoundVar[]>();\r
- THashMap<SSAFunction, BoundVar> oldTargets = new THashMap<SSAFunction, BoundVar>();\r
- for(SSAFunction function = firstFunction; \r
- function != null; \r
- function = function.getNext()) {\r
- THashMap<BoundVar, BoundVar> map = new THashMap<BoundVar, BoundVar>(2*outVars.length);\r
+ THashMap<SSAClosure, THashMap<BoundVar, BoundVar>> varMap = new THashMap<SSAClosure, THashMap<BoundVar, BoundVar>>();\r
+ THashMap<SSAClosure, BoundVar[]> inVarsMap = new THashMap<SSAClosure, BoundVar[]>();\r
+ THashMap<SSAClosure, BoundVar> oldTargets = new THashMap<SSAClosure, BoundVar>();\r
+ for(SSAClosure closure = firstClosure; \r
+ closure != null; \r
+ closure = closure.getNext()) {\r
+ THashMap<BoundVar, BoundVar> map = new THashMap<BoundVar, BoundVar>(outVars.length);\r
BoundVar[] inVars = new BoundVar[outVars.length]; \r
for(int i=0;i<inVars.length;++i) {\r
inVars[i] = new BoundVar(outVars[i].getType());\r
map.put(outVars[i], inVars[i]);\r
}\r
- inVarsMap.put(function, inVars);\r
- varMap.put(function, map);\r
+ inVarsMap.put(closure, inVars);\r
+ varMap.put(closure, map);\r
\r
- function.addParametersInFront(inVars); \r
- SCLConstant functionConstant = new SCLConstant(context.createName(), function.getType());\r
+ closure.parametrize(inVars); \r
+ SCLConstant functionConstant = new SCLConstant(context.createName(), closure.getType());\r
context.addConstant(functionConstant); \r
- oldTargets.put(function, (BoundVar)function.getTarget());\r
- function.setTarget(functionConstant);\r
- functionConstant.setDefinition(function); \r
+ oldTargets.put(closure, (BoundVar)closure.getTarget());\r
+ closure.setTarget(functionConstant);\r
+ functionConstant.setDefinition((SSAFunction)closure); \r
functionConstant.setPrivate(true);\r
// TODO handle type parameters\r
\r
ValRef.createOccurrences(outVars)).insertBefore(this);*/\r
}\r
\r
- for(SSAFunction function = firstFunction; \r
- function != null; \r
- function = function.getNext()) {\r
- BoundVar oldTarget = oldTargets.get(function);\r
+ for(SSAClosure closure = firstClosure; \r
+ closure != null; \r
+ closure = closure.getNext()) {\r
+ BoundVar oldTarget = oldTargets.get(closure);\r
for(ValRef ref : oldTarget.getOccurences()) {\r
SSAFunction parent = ref.getParentFunction();\r
BoundVar[] vars = inVarsMap.get(parent);\r
if(vars == null)\r
vars = outVars;\r
if(vars.length > 0)\r
- ref.replaceByApply(function.getTarget(), vars);\r
+ ref.replaceByApply(closure.getTarget(), vars);\r
else\r
- ref.replaceBy(function.getTarget());\r
+ ref.replaceBy(closure.getTarget());\r
}\r
}\r
\r
\r
@Override\r
public void simplify(SSASimplificationContext context) {\r
- for(SSAFunction function = firstFunction; \r
+ for(SSAClosure function = firstClosure; \r
function != null; \r
function = function.getNext())\r
function.simplify(context);\r
public void setRecursiveGroupLocation(long recursiveGroupLocation) {\r
this.recursiveGroupLocation = recursiveGroupLocation;\r
}\r
+ \r
+ @Override\r
+ public void forValRefs(ValRefVisitor visitor) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.forValRefs(visitor); \r
+ }\r
}\r
import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.internal.codegen.utils.Constants;
import org.simantics.scl.compiler.types.TApply;
parameters[len-i-1] = temp;
}
}
+
+ private TypeConstructor getTypeConstructor(TCon con) {
+ TypeDescriptor typeDescriptor = environment.getTypeDescriptor(con);
+ if(typeDescriptor == null)
+ throw new InternalCompilerError("Didn't find type constructor " + con.module + "/" + con.name + ".");
+ if(typeDescriptor instanceof TypeAlias)
+ throw new InternalCompilerError("Type " + con.module + "/" + con.name + " is a type alias.");
+ return (TypeConstructor)typeDescriptor;
+ }
public TypeDesc toTypeDesc(Type type) {
while(true) {
- if(type instanceof TCon) {
- TCon con = (TCon)type;
- TypeConstructor typeConstructor = environment.getTypeConstructor(con);
- if(typeConstructor == null)
- throw new InternalCompilerError("Didn't find type constructor " + con.module + "/" + con.name + ".");
- return typeConstructor.construct(this, Type.EMPTY_ARRAY);
- }
+ if(type instanceof TCon)
+ return getTypeConstructor((TCon)type).construct(this, Type.EMPTY_ARRAY);
else if(type instanceof TApply) {
int i=0;
while(true) {
type = Types.canonical(apply.function);
if(type instanceof TCon) {
reverseParameters(i);
- return environment.getTypeConstructor((TCon)type).construct(this, parameters);
+ return getTypeConstructor((TCon)type).construct(this, parameters);
}
else if(type instanceof TApply)
;
import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.kinds.Kind;
this.typeDesc = typeDesc;
this.documentation = documentation;
}
+
+ public StandardTypeConstructor(TCon name, TVar[] parameters, TypeDesc typeDesc) {
+ super(name, parameters);
+ this.typeDesc = typeDesc;
+ }
public void setTypeDesc(TypeDesc typeDesc) {
this.typeDesc = typeDesc;
System.out.println();
}*/
}
+
+ public ModuleBuilder getModuleBuilder() {
+ return moduleBuilder;
+ }
}
tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
tsmb.loadLocal(other);
tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
- if(type.isPrimitive())
- tsmb.ifComparisonBranch(failure, "!=", type);
- else {
- Label isNull = tsmb.createLabel();
- Label finished = tsmb.createLabel();
- tsmb.swap();
- tsmb.dup();
- tsmb.ifNullBranch(isNull, true);
- tsmb.swap();
- tsmb.invokeVirtual("java/lang/Object", "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[1]);
- tsmb.ifZeroComparisonBranch(failure, "==");
- tsmb.branch(finished);
- tsmb.setLocation(isNull);
- tsmb.pop();
- tsmb.ifNullBranch(failure, false);
- tsmb.setLocation(finished);
- }
+ equals(tsmb, type, failure);
}
// Return
tsmb.math(Opcodes.IMUL);
tsmb.loadThis();
tsmb.loadField(classBuilder.getClassName(), fieldNamePrefix+i, type);
- switch(type.getTypeCode()) {
- case TypeDesc.INT_CODE:
- break;
- case TypeDesc.OBJECT_CODE: {
- Label isNull = tsmb.createLabel();
- Label finished = tsmb.createLabel();
- tsmb.dup();
- tsmb.ifNullBranch(isNull, true);
- tsmb.invokeVirtual("java/lang/Object", "hashCode", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);
- tsmb.branch(finished);
- tsmb.setLocation(isNull);
- tsmb.pop();
- tsmb.loadConstant(0);
- tsmb.setLocation(finished);
- } break;
- case TypeDesc.DOUBLE_CODE:
- tsmb.invokeStatic("java/lang/Double", "doubleToLongBits", TypeDesc.LONG, new TypeDesc[] { TypeDesc.DOUBLE });
- case TypeDesc.LONG_CODE:
- tsmb.dup2();
- tsmb.loadConstant(32);
- tsmb.math(Opcodes.LSHR);
- tsmb.math(Opcodes.LXOR);
- tsmb.convert(TypeDesc.LONG, TypeDesc.INT);
- break;
- case TypeDesc.FLOAT_CODE:
- tsmb.invokeStatic("java/lang/Float", "floatToIntBits", TypeDesc.INT, new TypeDesc[] { TypeDesc.FLOAT });
- break;
- default:
- tsmb.convert(type, TypeDesc.INT);
- }
+ hashCode(tsmb, type);
tsmb.math(Opcodes.IADD);
}
tsmb.returnValue(TypeDesc.INT);
}
}
+ public static void equals(MethodBuilderBase mb, TypeDesc typeDesc, Label failure) {
+ if(typeDesc.isPrimitive())
+ mb.ifComparisonBranch(failure, "!=", typeDesc);
+ else {
+ Label isNull = mb.createLabel();
+ Label finished = mb.createLabel();
+ mb.swap();
+ mb.dup();
+ mb.ifNullBranch(isNull, true);
+ mb.swap();
+ mb.invokeVirtual("java/lang/Object", "equals", TypeDesc.BOOLEAN, Constants.OBJECTS[1]);
+ mb.ifZeroComparisonBranch(failure, "==");
+ mb.branch(finished);
+ mb.setLocation(isNull);
+ mb.pop();
+ mb.ifNullBranch(failure, false);
+ mb.setLocation(finished);
+ }
+ }
+
+ /**
+ * Calculates the hash code of a value in stack.
+ */
+ public static void hashCode(MethodBuilderBase mb, TypeDesc typeDesc) {
+ switch(typeDesc.getTypeCode()) {
+ case TypeDesc.INT_CODE:
+ break;
+ case TypeDesc.OBJECT_CODE: {
+ Label isNull = mb.createLabel();
+ Label finished = mb.createLabel();
+ mb.dup();
+ mb.ifNullBranch(isNull, true);
+ mb.invokeVirtual("java/lang/Object", "hashCode", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);
+ mb.branch(finished);
+ mb.setLocation(isNull);
+ mb.pop();
+ mb.loadConstant(0);
+ mb.setLocation(finished);
+ } break;
+ case TypeDesc.DOUBLE_CODE:
+ mb.invokeStatic("java/lang/Double", "doubleToLongBits", TypeDesc.LONG, new TypeDesc[] { TypeDesc.DOUBLE });
+ case TypeDesc.LONG_CODE:
+ mb.dup2();
+ mb.loadConstant(32);
+ mb.math(Opcodes.LSHR);
+ mb.math(Opcodes.LXOR);
+ mb.convert(TypeDesc.LONG, TypeDesc.INT);
+ break;
+ case TypeDesc.FLOAT_CODE:
+ mb.invokeStatic("java/lang/Float", "floatToIntBits", TypeDesc.INT, new TypeDesc[] { TypeDesc.FLOAT });
+ break;
+ default:
+ mb.convert(typeDesc, TypeDesc.INT);
+ }
+ }
+
public static void constructRecord(TypeDesc clazz, MethodBuilder mb,
Type[] parameterTypes, Val... parameters) {
if(parameters.length == 0) {
return NameMangling.mangle(name);
}
+ public String getFreshClosureClassNameSuffix() {
+ return "$" + (++closureCount);
+ }
+
public String getFreshClosureClassName() {
return moduleClassName + "$" + (++closureCount);
}
storeLocal(lv);
}
+ /**
+ * Generates the continuation code if it does not already exist.
+ */
public void ensureExists(Cont continuation) {
if(!generatedConts.contains(continuation))
((SSABlock)continuation).generateCode(this);
public <T> void addPreparation(PreparationStep<T> step, T result) {
preparationSteps.put(step, result);
}
+
+ public LocalVariable cacheValue(IVal val, Type type) {
+ if(val instanceof BoundVar) {
+ BoundVar boundVar = (BoundVar)val;
+ if(!boundVar.generateOnFly)
+ return getLocalVariable(boundVar);
+ }
+ push(val, type);
+ LocalVariable temp = createLocalVariable(null, getJavaTypeTranslator().toTypeDesc(type));
+ storeLocal(temp);
+ return temp;
+ }
}
public void newObject(TypeDesc type) {
methodVisitor.visitTypeInsn(Opcodes.NEW, getClassName(type));
}
+
+ public void newObject(String type) {
+ methodVisitor.visitTypeInsn(Opcodes.NEW, type);
+ }
public void newObject(TypeDesc type, int dimensions) {
methodVisitor.visitMultiANewArrayInsn(type.getDescriptor(), dimensions);
public static String getClassName(Class<?> clazz) {
return clazz.getName().replace('.', '/');
}
+
+ public void switch_(int[] values, Label[] labels, Label defaultLabel) {
+ int lo = values[0];
+ int hi = values[values.length-1];
+ long table_space_cost = 4 + ((long) hi - lo + 1); // words
+ long table_time_cost = 3; // comparisons
+ long lookup_space_cost = 3 + 2 * (long) values.length;
+ long lookup_time_cost = values.length;
+ if(values.length > 0 &&
+ table_space_cost + 3 * table_time_cost <=
+ lookup_space_cost + 3 * lookup_time_cost) {
+ Label[] table = new Label[hi - lo + 1];
+ for(int i=0,j=0;i<table.length;++i) {
+ int id = lo+i;
+ if(values[j] == id) {
+ table[i] = labels[j];
+ ++j;
+ }
+ else
+ table[i] = defaultLabel;
+ }
+ methodVisitor.visitTableSwitchInsn(lo, hi, defaultLabel, table);
+ }
+ else
+ methodVisitor.visitLookupSwitchInsn(defaultLabel, values, labels);
+ }
}
import org.simantics.scl.compiler.common.names.Name;\r
import org.simantics.scl.compiler.constants.SCLConstant;\r
import org.simantics.scl.compiler.errors.ErrorLog;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAClosure;\r
import org.simantics.scl.compiler.internal.codegen.ssa.SSAModule;\r
\r
public class SSALambdaLiftingContext {\r
public ErrorLog getErrorLog() {\r
return errorLog;\r
}\r
+ \r
+ public void addClosure(SSAClosure closure) {\r
+ module.closuresToGenerate.add(closure);\r
+ }\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.utils;\r
+\r
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+\r
+@FunctionalInterface\r
+public interface ValRefVisitor {\r
+ public void visit(ValRef valRef);\r
+}\r
import org.simantics.scl.compiler.internal.codegen.references.ValRef;
import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject;
import org.simantics.scl.compiler.internal.codegen.ssa.exits.If;
import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;
import org.simantics.scl.compiler.internal.codegen.ssa.exits.Switch;
ModuleWriter moduleWriter;
SSABlock block;
- CodeWriter(ModuleWriter moduleWriter, SSABlock block) {
+ public CodeWriter(ModuleWriter moduleWriter, SSABlock block) {
this.moduleWriter = moduleWriter;
this.block = block;
}
- public IVal apply(int lineNumber, IVal function, IVal ... parameters) {
+ public IVal apply(long lineNumber, IVal function, IVal ... parameters) {
try {
MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
return applyWithEffect(lineNumber,
}
}
- public IVal applyWithEffectChecked(int lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {
+ public IVal applyWithEffectChecked(long lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {
try {
MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
if(!Types.equals(effect, mfun.effect))
return var;
}
+ public CodeWriter createBlock() {
+ SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
+ block.getParent().addBlock(newBlock);
+ return new CodeWriter(moduleWriter, newBlock);
+ }
+
public CodeWriter createBlock(Type ... parameterTypes) {
SSABlock newBlock = new SSABlock(parameterTypes);
block.getParent().addBlock(newBlock);
elseTarget.createOccurrence()));
block = null;
}
+
+ public void branchAwayIf(IVal condition, ICont target) {
+ SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
+ block.getParent().addBlock(newBlock);
+ block.setExit(new If(condition.createOccurrence(),
+ target.createOccurrence(),
+ newBlock.createOccurrence()));
+ this.block = newBlock;
+ }
+
+ public void branchAwayUnless(IVal condition, ICont target) {
+ SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
+ block.getParent().addBlock(newBlock);
+ block.setExit(new If(condition.createOccurrence(),
+ newBlock.createOccurrence(),
+ target.createOccurrence()));
+ this.block = newBlock;
+ }
public void return_(IVal val) {
jump(block.getParent().getReturnCont(), val);
public SSAFunction getFunction() {
return block.getParent();
- }
+ }
+
+ public boolean isUnfinished() {
+ return block != null;
+ }
+
+ public void defineObject(SSAObject object) {
+ this.block.addStatement(new LetFunctions(object));
+ }
}
import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAModule;
+import org.simantics.scl.compiler.internal.codegen.ssa.StaticField;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.runtime.tuple.Tuple2;
String name = "externalConstant" + externalConstantId;
JavaStaticField constant = new JavaStaticField(moduleClassName, name, type, -1);
externalConstantMap.put(tuple, constant);
- module.addStaticField(new Tuple2(name, type));
+ module.addStaticField(new StaticField(name, type));
return constant;
}
}
function.addBlock(block);\r
function.setTarget(target);\r
\r
- let.addFunction(function);\r
+ let.addClosure(function);\r
\r
return new CodeWriter(moduleWriter, block);\r
}\r
+++ /dev/null
-package org.simantics.scl.compiler.internal.deriving;
-
-import java.util.ArrayList;
-
-import org.simantics.scl.compiler.common.datatypes.Constructor;
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
-import org.simantics.scl.compiler.elaboration.expressions.EApply;
-import org.simantics.scl.compiler.elaboration.expressions.EVar;
-import org.simantics.scl.compiler.elaboration.expressions.EVariable;
-import org.simantics.scl.compiler.elaboration.expressions.Expression;
-import org.simantics.scl.compiler.elaboration.expressions.Variable;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
-import org.simantics.scl.compiler.environment.AmbiguousNameException;
-import org.simantics.scl.compiler.environment.Environment;
-import org.simantics.scl.compiler.environment.Environments;
-import org.simantics.scl.compiler.errors.ErrorLog;
-import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
-import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
-import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
-import org.simantics.scl.compiler.internal.parsing.expressions.Expressions;
-import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
-import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
-import org.simantics.scl.compiler.internal.parsing.types.TVarAst;
-import org.simantics.scl.compiler.types.TCon;
-
-class EqDeriver implements InstanceDeriver {
-
- @Override
- public void derive(
- ErrorLog errorLog,
- Environment environment,
- ArrayList<ProcessedDInstanceAst> instancesAst,
- DDerivingInstanceAst der) {
- // Analyze
- if(der.types.length != 1) {
- errorLog.log(der.location, "Invalid number of parameters to " + der.name);
- return;
- }
- TVarAst headType = DerivingUtils.getHeadType(der.types[0]);
- if(headType == null) {
- errorLog.log(der.types[0].location, "Cannot derive Eq instance for the type " + headType + ".");
- return;
- }
- TCon con;
- try {
- con = Environments.getTypeConstructorName(environment, headType.name);
- } catch (AmbiguousNameException e1) {
- errorLog.log(headType.location, e1.getMessage());
- return;
- }
- if(con == null) {
- errorLog.log(headType.location, "Couldn't resolve " + headType.name);
- return;
- }
- TypeConstructor tcon = environment.getTypeConstructor(con);
- if(tcon == null) {
- errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
- return;
- }
- if(tcon.isOpen) {
- errorLog.log(headType.location, "Cannot derive instance for open data types.");
- return;
- }
-
- // Generate
- DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types);
- ValueRepository valueDefs = new ValueRepository();
- for(Constructor constructor : tcon.constructors) {
- int l = constructor.parameterTypes.length;
- String[] par1 = new String[l];
- String[] par2 = new String[l];
- for(int i=0;i<l;++i) {
- par1[i] = "a" + i;
- par2[i] = "b" + i;
- }
- Expression lhs = new EApply(
- new EVar("=="),
- new EApply(new EVar(constructor.name.name), Expressions.vars(par1)),
- new EApply(new EVar(constructor.name.name), Expressions.vars(par2))
- );
- Expression value = new EVar("True");
- for(int i=l-1;i>=0;--i)
- value = new EApply(
- new EVar("&&"),
- new EApply(
- new EVar("=="),
- new EVar(par1[i]),
- new EVar(par2[i])),
- value);
- try {
- DValueAst valueAst = new DValueAst(lhs, value);
- valueAst.setLocationDeep(der.location);
- valueDefs.add(valueAst);
- } catch (NotPatternException e) {
- errorLog.log(e.getExpression().location, "Not a pattern.");
- }
- }
- {
- Expression lhs = new EApply(
- new EVar("=="),
- new EVariable(new Variable("_")),
- new EVariable(new Variable("_")));
- Expression value = new EVar("False");
- try {
- DValueAst valueAst = new DValueAst(lhs, value);
- valueAst.setLocationDeep(der.location);
- valueDefs.add(valueAst);
- /*valueDefs.addAnnotation("==", new DAnnotationAst(new EVar("@private"),
- Collections.<Expression>emptyList()));*/
- } catch (NotPatternException e) {
- errorLog.log(e.getExpression().location, "Not a pattern.");
- }
- }
- instancesAst.add(new ProcessedDInstanceAst(instanceAst, valueDefs));
- }
-
-}
+++ /dev/null
-package org.simantics.scl.compiler.internal.deriving;
-
-import java.util.ArrayList;
-
-import org.simantics.scl.compiler.common.datatypes.Constructor;
-import org.simantics.scl.compiler.constants.IntegerConstant;
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
-import org.simantics.scl.compiler.elaboration.expressions.EApply;
-import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
-import org.simantics.scl.compiler.elaboration.expressions.EVar;
-import org.simantics.scl.compiler.elaboration.expressions.Expression;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
-import org.simantics.scl.compiler.environment.AmbiguousNameException;
-import org.simantics.scl.compiler.environment.Environment;
-import org.simantics.scl.compiler.environment.Environments;
-import org.simantics.scl.compiler.errors.ErrorLog;
-import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
-import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
-import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
-import org.simantics.scl.compiler.internal.parsing.expressions.Expressions;
-import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
-import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
-import org.simantics.scl.compiler.internal.parsing.types.TVarAst;
-import org.simantics.scl.compiler.types.TCon;
-
-class HashableDeriver implements InstanceDeriver {
-
- @Override
- public void derive(
- ErrorLog errorLog,
- Environment environment,
- ArrayList<ProcessedDInstanceAst> instancesAst,
- DDerivingInstanceAst der) {
- // Analyze
- if(der.types.length != 1) {
- errorLog.log(der.location, "Invalid number of parameters to " + der.name);
- return;
- }
- TVarAst headType = DerivingUtils.getHeadType(der.types[0]);
- if(headType == null) {
- errorLog.log(der.types[0].location, "Cannot derive Hashable instance for the type " + headType + ".");
- return;
- }
- TCon con;
- try {
- con = Environments.getTypeConstructorName(environment, headType.name);
- } catch (AmbiguousNameException e1) {
- errorLog.log(headType.location, e1.getMessage());
- return;
- }
- if(con == null) {
- errorLog.log(headType.location, "Couldn't resolve " + headType.name);
- return;
- }
- TypeConstructor tcon = environment.getTypeConstructor(con);
- if(tcon == null) {
- errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
- return;
- }
- if(tcon.isOpen) {
- errorLog.log(headType.location, "Cannot derive instance for open data types.");
- return;
- }
-
- // Generate
- DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types);
- ValueRepository valueDefs = new ValueRepository();
- int cId = 0;
- for(Constructor constructor : tcon.constructors) {
- int l = constructor.parameterTypes.length;
- String[] par = new String[l];
- for(int i=0;i<l;++i) {
- par[i] = "v" + i;
- }
- Expression lhs = new EApply(
- new EVar("hashP"),
- new EApply(new EVar(constructor.name.name), Expressions.vars(par)),
- new EVar("accum")
- );
- Expression value = new EVar("accum");
- for(int i=0;i<l;++i) {
- value = new EApply(new EVar("hashP"),
- new EVar(par[i]),
- value
- );
- }
- if(tcon.constructors.length > 1)
- value = new EApply(new EVar("hashP"),
- new ELiteral(new IntegerConstant(cId)),
- value
- );
-
- try {
- DValueAst valueAst = new DValueAst(lhs, value);
- valueAst.setLocationDeep(der.location);
- valueDefs.add(valueAst);
- } catch (NotPatternException e) {
- errorLog.log(e.getExpression().location, "Not a pattern.");
- }
- ++ cId;
- }
- instancesAst.add(new ProcessedDInstanceAst(instanceAst, valueDefs));
- }
-
-}
import java.util.ArrayList;
import org.simantics.scl.compiler.common.datatypes.Constructor;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.constants.ByteConstant;
import org.simantics.scl.compiler.constants.IntegerConstant;
import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.environment.AmbiguousNameException;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.environment.Environments;
import org.simantics.scl.compiler.types.TCon;
class IODeriver implements InstanceDeriver {
-
- private static final Name WRITE = Name.create("Serialization", "write");
- private static final Name READ = Name.create("Serialization", "read");
- private static final Name IO_SIZE = Name.create("Serialization", "ioSize");
@Override
public void derive(
}
TCon con;
try {
- con = Environments.getTypeConstructorName(environment, headType.name);
+ con = Environments.getTypeDescriptorName(environment, headType.name);
} catch (AmbiguousNameException e1) {
errorLog.log(headType.location, e1.getMessage());
return;
errorLog.log(headType.location, "Couldn't resolve " + headType.name);
return;
}
- TypeConstructor tcon = environment.getTypeConstructor(con);
- if(tcon == null) {
+ TypeDescriptor tdesc = environment.getTypeDescriptor(con);
+ if(tdesc == null) {
errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
return;
}
+ if(tdesc instanceof TypeAlias) {
+ errorLog.log(headType.location, "Cannot derive instance for a type alias.");
+ return;
+ }
+ TypeConstructor tcon = (TypeConstructor)tdesc;
if(tcon.isOpen) {
errorLog.log(headType.location, "Cannot derive instance for open data types.");
return;
DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types);
ValueRepository valueDefs = new ValueRepository();
- SCLValue write = environment.getValue(WRITE);
- SCLValue read = environment.getValue(READ);
- SCLValue ioSize = environment.getValue(IO_SIZE);
+ SCLValue write = environment.getValue(Names.Serialization_write);
+ SCLValue read = environment.getValue(Names.Serialization_read);
+ SCLValue ioSize = environment.getValue(Names.Serialization_ioSize);
// Generate write
for(int id=0;id<tcon.constructors.length;++id) {
new THashMap<TCon, InstanceDeriver>();\r
\r
static {\r
- MAP.put(Types.EQ, new EqDeriver());\r
- MAP.put(Types.HASHABLE, new HashableDeriver());\r
MAP.put(Types.IO, new IODeriver());\r
MAP.put(Types.ORD, new OrdDeriver());\r
MAP.put(Types.SHOW, new ShowDeriver());\r
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
import org.simantics.scl.compiler.elaboration.expressions.EVar;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.environment.AmbiguousNameException;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.environment.Environments;
}
TCon con;
try {
- con = Environments.getTypeConstructorName(environment, headType.name);
+ con = Environments.getTypeDescriptorName(environment, headType.name);
} catch (AmbiguousNameException e1) {
errorLog.log(headType.location, e1.getMessage());
return;
errorLog.log(headType.location, "Couldn't resolve " + headType.name);
return;
}
- TypeConstructor tcon = environment.getTypeConstructor(con);
- if(tcon == null) {
+ TypeDescriptor tdesc = environment.getTypeDescriptor(con);
+ if(tdesc == null) {
errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
return;
}
+ if(tdesc instanceof TypeAlias) {
+ errorLog.log(headType.location, "Cannot derive instance for a type alias.");
+ return;
+ }
+ TypeConstructor tcon = (TypeConstructor)tdesc;
if(tcon.isOpen) {
errorLog.log(headType.location, "Cannot derive instance for open data types.");
return;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
import org.simantics.scl.compiler.elaboration.expressions.EVar;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.environment.AmbiguousNameException;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.environment.Environments;
}
TCon con;
try {
- con = Environments.getTypeConstructorName(environment, headType.name);
+ con = Environments.getTypeDescriptorName(environment, headType.name);
} catch (AmbiguousNameException e1) {
errorLog.log(headType.location, e1.getMessage());
return;
errorLog.log(headType.location, "Couldn't resolve " + headType.name);
return;
}
- TypeConstructor tcon = environment.getTypeConstructor(con);
- if(tcon == null) {
+ TypeDescriptor tdesc = environment.getTypeDescriptor(con);
+ if(tdesc == null) {
errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
return;
}
+ if(tdesc instanceof TypeAlias) {
+ errorLog.log(headType.location, "Cannot derive instance for a type alias.");
+ return;
+ }
+ TypeConstructor tcon = (TypeConstructor)tdesc;
if(tcon.isOpen) {
errorLog.log(headType.location, "Cannot derive instance for open data types.");
return;
package org.simantics.scl.compiler.internal.elaboration.constraints;
+import java.util.ArrayList;
+
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.ClassConstant;
import org.simantics.scl.compiler.constants.StringConstant;
else if(parameter instanceof TUnion) {
TUnion union = (TUnion)parameter;
- /*TPred[] demands = new TPred[union.effects.length];
- for(int i=0;i<union.effects.length;++i)
- demands[i] = Types.pred(Types.TYPEABLE, union.effects[i]);*/
if(union.effects.length == 0)
- return new Reduction(
+ return new Reduction(
new EConstant(Builtins.INSTANCE.getValue("TPure")),
Type.EMPTY_ARRAY,
TPred.EMPTY_ARRAY);
+ else if(union.effects.length == 2) {
+ return new Reduction(
+ new EConstant(Builtins.INSTANCE.getValue("TUnion2")),
+ Type.EMPTY_ARRAY, new TPred[] {
+ Types.pred(Types.TYPEABLE, union.effects[0]),
+ Types.pred(Types.TYPEABLE, union.effects[1])
+ });
+ }
}
}
// Standard case
- THashMap<TVar, Type> substitution = new THashMap<TVar, Type>();
+ THashMap<TVar, Type> substitution = new THashMap<TVar, Type>();
+ ArrayList<Reduction> reductions = new ArrayList<Reduction>(1);
for(TypeClassInstance inst : environment.getInstances(constraint.typeClass)) {
if(Types.match(inst.instance, constraint, substitution)) {
TPred[] demands = new TPred[inst.context.length];
parameter = inst.generatorParameters[i]; // TODO Is this correct?
parameters[i] = parameter;
}
- return new Reduction(new ELiteral(inst.generator), parameters, demands);
+ reductions.add(new Reduction(new ELiteral(inst.generator), parameters, demands));
}
- else
- substitution.clear();
+ substitution.clear();
+ }
+ //System.out.println(constraint.typeClass + " -> " + reductions.size());
+ if(reductions.size() == 1)
+ return reductions.get(0);
+ else if(reductions.size() > 1) {
+ throw new InternalCompilerError("Found more than one matching instances for " + constraint.typeClass + ".");
}
return null;
}
DEFAULTS_IGNORE.add(Types.SHOW);\r
DEFAULTS_IGNORE.add(Types.con("Json2", "JSON"));\r
DEFAULTS_IGNORE.add(Types.VEC_COMP);\r
- DEFAULTS_IGNORE.add(Types.EQ);\r
DEFAULTS_IGNORE.add(Types.ORD);\r
DEFAULTS_IGNORE.add(Types.TYPEABLE);\r
DEFAULTS_IGNORE.add(Types.SERIALIZABLE);\r
package org.simantics.scl.compiler.internal.elaboration.matching;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
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.expressions.GuardedExpressionGroup;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
return newVals;
}
- private static void split(CodeWriter w, final Environment env, IVal[] scrutinee, final ICont success, ICont failure, List<Row> rows, int columnId) {
+ private static void splitByConstructors(CodeWriter w, final Environment env, IVal[] scrutinee, final ICont success, ICont failure, List<Row> rows, int columnId) {
THashMap<Object, ExpressionMatrix> matrixMap = new THashMap<Object, ExpressionMatrix>();
ArrayList<Branch> branches = new ArrayList<Branch>();
ArrayList<ExpressionMatrix> matrices = new ArrayList<ExpressionMatrix>();
Expression constructor_ = applyConstructor.getFunction();
while(constructor_ instanceof EApplyType)
constructor_ = ((EApplyType)constructor_).getExpression();
- SCLValue constructor = ((EConstant)constructor_).getValue();
- // TODO How type parameters are handled???
Expression[] parameters = applyConstructor.getParameters();
-
- ExpressionMatrix matrix = matrixMap.get(constructor.getName());
- if(matrix == null) {
- CodeWriter newW = w.createBlock(Types.getTypes(parameters));
- branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));
- matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));
- matrices.add(matrix);
- matrixMap.put(constructor.getName(), matrix);
+ // TODO How type parameters are handled???
+ if(constructor_ instanceof EConstant) {
+ SCLValue constructor = ((EConstant)constructor_).getValue();
+
+ ExpressionMatrix matrix = matrixMap.get(constructor.getName());
+ if(matrix == null) {
+ CodeWriter newW = w.createBlock(Types.getTypes(parameters));
+ branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));
+ matrices.add(matrix);
+ matrixMap.put(constructor.getName(), matrix);
+ }
+ matrix.rows.add(row.replace(columnId, parameters));
+ }
+ else if(constructor_ instanceof ELiteral) {
+ Constant constructor = ((ELiteral)constructor_).getValue();
+
+ ExpressionMatrix matrix = matrixMap.get(constructor);
+ if(matrix == null) {
+ CodeWriter newW = w.createBlock(Types.getTypes(parameters));
+ branches.add(new Branch(constructor, newW.getContinuation()));
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));
+ matrices.add(matrix);
+ matrixMap.put(constructor, matrix);
+ }
+ matrix.rows.add(row.replace(columnId, parameters));
}
- matrix.rows.add(row.replace(columnId, parameters));
}
else if(pattern instanceof EConstant) {
EConstant applyConstructor = (EConstant)pattern;
} catch (MatchException e) {
throw new InternalCompilerError();
}
- TypeConstructor cons = env.getTypeConstructor(con);
+ TypeConstructor cons = (TypeConstructor)env.getTypeDescriptor(con);
int maxBranchCount = cons.isOpen ? Integer.MAX_VALUE
: cons.constructors.length;
if(branches.size() < maxBranchCount)
w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()]));
}
+ private static void splitByViewPattern(CodeWriter w, Environment env, IVal[] scrutinee, ICont success,
+ ICont failure, List<Row> rows, int viewPatternColumn) {
+ Row firstRow = rows.get(0);
+ EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn];
+ firstRow.patterns[viewPatternColumn] = firstViewPattern.pattern;
+ int i;
+ for(i=1;i<rows.size();++i) {
+ Row row = rows.get(i);
+ Expression pattern = row.patterns[viewPatternColumn];
+ while(true) {
+ if(pattern instanceof EApplyType)
+ pattern = ((EApplyType)pattern).getExpression();
+ else if(pattern instanceof EAsPattern) {
+ EAsPattern asPattern = (EAsPattern)pattern;
+ pattern = asPattern.getPattern();
+ asPattern.getVariable().setVal(scrutinee[viewPatternColumn]);
+ }
+ else
+ break;
+ row.patterns[viewPatternColumn] = pattern;
+ }
+ if(!(pattern instanceof EViewPattern))
+ break;
+ EViewPattern otherViewPattern = (EViewPattern)pattern;
+ if(!otherViewPattern.expression.equalsExpression(firstViewPattern.expression))
+ break;
+ row.patterns[viewPatternColumn] = otherViewPattern.pattern;
+ }
+
+ IVal[] newScrutinee = Arrays.copyOf(scrutinee, scrutinee.length);
+ newScrutinee[viewPatternColumn] =
+ w.apply(firstViewPattern.location,
+ firstViewPattern.expression.toVal(env, w),
+ scrutinee[viewPatternColumn]);
+ if(i == rows.size()) {
+ split(w, env, newScrutinee, success, failure, rows);
+ }
+ else {
+ CodeWriter cont = w.createBlock();
+ split(w, env, newScrutinee, success, cont.getContinuation(), rows.subList(0, i));
+ split(cont, env, scrutinee, success, failure, rows.subList(i, rows.size()));
+ }
+ }
+
public static void split(CodeWriter w, Environment env, IVal[] scrutinee, ICont success, ICont failure, List<Row> rows) {
Row firstRow = rows.get(0);
Expression[] patterns = firstRow.patterns;
if(scrutinee.length != patterns.length)
- throw new InternalCompilerError();
+ throw new InternalCompilerError("Scrutinee and patterns have a different length");
// Find a non-variable pattern and split by it
+ int viewPatternColumn = -1;
for(int i=0;i<patterns.length;++i) {
- if(!(patterns[i] instanceof EVariable)) {
- split(w, env, scrutinee, success, failure, rows, i);
+ Expression pattern = patterns[i];
+ if(pattern instanceof EViewPattern) {
+ if(viewPatternColumn == -1)
+ viewPatternColumn = i;
+ }
+ else if(!(pattern instanceof EVariable)) {
+ splitByConstructors(w, env, scrutinee, success, failure, rows, i);
return;
}
}
+
+ if(viewPatternColumn >= 0) {
+ splitByViewPattern(w, env, scrutinee, success, failure, rows, viewPatternColumn);
+ return;
+ }
- // No matching needed
+ // The first row has only variable patterns: no matching needed
for(int i=0;i<patterns.length;++i)
((EVariable)patterns[i]).getVariable().setVal(scrutinee[i]);
if(firstRow.value instanceof GuardedExpressionGroup) {
package org.simantics.scl.compiler.internal.elaboration.matching;\r
\r
\r
+import java.util.Arrays;\r
+\r
import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
\r
public class Row {\r
newPatterns[j++] = patterns[i];\r
return new Row(newPatterns, value);\r
}\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return Arrays.toString(patterns) + " -> " + value;\r
+ }\r
}\r
--- /dev/null
+package org.simantics.scl.compiler.internal.elaboration.matching2;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApplyType;\r
+import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
+import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;\r
+import org.simantics.scl.compiler.environment.Environment;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.Branch;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.types.TCon;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.exceptions.MatchException;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+public class PatternMatchingCompiler2 {\r
+\r
+ private static class ExpressionMatrix {\r
+ final CodeWriter w;\r
+ final IVal[] scrutinee;\r
+ final List<Row2> rows = new ArrayList<Row2>();\r
+\r
+ public ExpressionMatrix(CodeWriter w, IVal[] scrutinee) {\r
+ this.w = w;\r
+ this.scrutinee = scrutinee;\r
+ }\r
+ }\r
+\r
+ public static IVal[] replace(IVal[] vals, int columnToReplace, IVal ... substitution) {\r
+ IVal[] newVals = new IVal[vals.length-1+substitution.length];\r
+ int j=0;\r
+ for(int i=0;i<columnToReplace;++i)\r
+ newVals[j++] = vals[i];\r
+ for(int i=0;i<substitution.length;++i)\r
+ newVals[j++] = substitution[i];\r
+ for(int i=columnToReplace+1;i<vals.length;++i)\r
+ newVals[j++] = vals[i];\r
+ return newVals;\r
+ }\r
+\r
+ private static void splitByConstructors(CodeWriter w, final Environment env, IVal[] scrutinee, ICont failure, List<Row2> rows, int columnId) {\r
+ THashMap<Object, ExpressionMatrix> matrixMap = new THashMap<Object, ExpressionMatrix>();\r
+ ArrayList<Branch> branches = new ArrayList<Branch>();\r
+ ArrayList<ExpressionMatrix> matrices = new ArrayList<ExpressionMatrix>();\r
+ \r
+ /*System.out.println("---");\r
+ for(Row row : rows) {\r
+ for(Expression e : row.patterns)\r
+ System.out.print(e + " ");\r
+ System.out.println();\r
+ }*/\r
+\r
+ int i;\r
+ for(i=0;i<rows.size();++i) {\r
+ Row2 row = rows.get(i);\r
+ Expression pattern = row.patterns[columnId];\r
+ while(true) {\r
+ if(pattern instanceof EApplyType)\r
+ pattern = ((EApplyType)pattern).getExpression();\r
+ else if(pattern instanceof EAsPattern) {\r
+ EAsPattern asPattern = (EAsPattern)pattern;\r
+ pattern = asPattern.getPattern();\r
+ asPattern.getVariable().setVal(scrutinee[columnId]);\r
+ }\r
+ else\r
+ break;\r
+ row.patterns[columnId] = pattern;\r
+ }\r
+ if(pattern instanceof EVariable)\r
+ break;\r
+ else if(pattern instanceof EApply) {\r
+ EApply applyConstructor = (EApply)pattern;\r
+ Expression constructor_ = applyConstructor.getFunction();\r
+ while(constructor_ instanceof EApplyType)\r
+ constructor_ = ((EApplyType)constructor_).getExpression();\r
+ Expression[] parameters = applyConstructor.getParameters();\r
+ // TODO How type parameters are handled???\r
+ if(constructor_ instanceof EConstant) {\r
+ SCLValue constructor = ((EConstant)constructor_).getValue();\r
+ \r
+ ExpressionMatrix matrix = matrixMap.get(constructor.getName());\r
+ if(matrix == null) {\r
+ CodeWriter newW = w.createBlock(Types.getTypes(parameters));\r
+ branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));\r
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
+ matrices.add(matrix);\r
+ matrixMap.put(constructor.getName(), matrix);\r
+ }\r
+ matrix.rows.add(row.replace(columnId, parameters));\r
+ }\r
+ else if(constructor_ instanceof ELiteral) {\r
+ Constant constructor = ((ELiteral)constructor_).getValue();\r
+ \r
+ ExpressionMatrix matrix = matrixMap.get(constructor);\r
+ if(matrix == null) {\r
+ CodeWriter newW = w.createBlock(Types.getTypes(parameters));\r
+ branches.add(new Branch(constructor, newW.getContinuation()));\r
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
+ matrices.add(matrix);\r
+ matrixMap.put(constructor, matrix);\r
+ }\r
+ matrix.rows.add(row.replace(columnId, parameters));\r
+ }\r
+ }\r
+ else if(pattern instanceof EConstant) {\r
+ EConstant applyConstructor = (EConstant)pattern;\r
+ SCLValue constructor = applyConstructor.getValue();\r
+\r
+ ExpressionMatrix matrix = matrixMap.get(constructor.getName());\r
+ if(matrix == null) {\r
+ CodeWriter newW = w.createBlock();\r
+ branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));\r
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
+ matrices.add(matrix);\r
+ matrixMap.put(constructor.getName(), matrix);\r
+ }\r
+ matrix.rows.add(row.replace(columnId, Expression.EMPTY_ARRAY));\r
+ }\r
+ else if(pattern instanceof ELiteral) {\r
+ ELiteral literal = (ELiteral)pattern;\r
+ Constant constructor = literal.getValue();\r
+\r
+ ExpressionMatrix matrix = matrixMap.get(constructor);\r
+ if(matrix == null) {\r
+ CodeWriter newW = w.createBlock();\r
+ branches.add(new Branch(constructor, newW.getContinuation()));\r
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
+ matrices.add(matrix);\r
+ matrixMap.put(constructor, matrix);\r
+ }\r
+ matrix.rows.add(row.replace(columnId, Expression.EMPTY_ARRAY));\r
+ }\r
+ else if(pattern instanceof EExternalConstant) {\r
+ EExternalConstant constant = (EExternalConstant)pattern;\r
+ Constant constructor = w.getModuleWriter().getExternalConstant(constant.getValue(), constant.getType());\r
+\r
+ ExpressionMatrix matrix = matrixMap.get(constructor);\r
+ if(matrix == null) {\r
+ CodeWriter newW = w.createBlock();\r
+ branches.add(new Branch(constructor, newW.getContinuation()));\r
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
+ matrices.add(matrix);\r
+ matrixMap.put(constructor, matrix);\r
+ }\r
+ matrix.rows.add(row.replace(columnId, Expression.EMPTY_ARRAY));\r
+ }\r
+ else\r
+ throw new InternalCompilerError("Cannot handle an instance of " + pattern.getClass().getSimpleName() + " in a pattern.");\r
+ }\r
+ if(i < rows.size()) {\r
+ CodeWriter newW = w.createBlock();\r
+ ICont cont = newW.getContinuation();\r
+ branches.add(new Branch(null, cont));\r
+ split(newW, env, scrutinee, failure, rows.subList(i, rows.size()));\r
+ failure = cont;\r
+ }\r
+ else {\r
+ TCon con;\r
+ try {\r
+ con = Types.getConstructor(scrutinee[columnId].getType());\r
+ } catch (MatchException e) {\r
+ throw new InternalCompilerError(e);\r
+ }\r
+ TypeConstructor cons = (TypeConstructor)env.getTypeDescriptor(con);\r
+ int maxBranchCount = cons.isOpen ? Integer.MAX_VALUE \r
+ : cons.constructors.length;\r
+ if(branches.size() < maxBranchCount)\r
+ branches.add(new Branch(null, failure));\r
+ }\r
+\r
+ for(ExpressionMatrix mx : matrices)\r
+ split(mx.w, env, mx.scrutinee, failure, mx.rows);\r
+ w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()]));\r
+ }\r
+\r
+ private static void splitByViewPattern(CodeWriter w, Environment env, IVal[] scrutinee, ICont failure, List<Row2> rows, int viewPatternColumn) {\r
+ Row2 firstRow = rows.get(0);\r
+ EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn];\r
+ firstRow.patterns[viewPatternColumn] = firstViewPattern.pattern;\r
+ int i;\r
+ for(i=1;i<rows.size();++i) {\r
+ Row2 row = rows.get(i);\r
+ Expression pattern = row.patterns[viewPatternColumn];\r
+ while(true) {\r
+ if(pattern instanceof EApplyType)\r
+ pattern = ((EApplyType)pattern).getExpression();\r
+ else if(pattern instanceof EAsPattern) {\r
+ EAsPattern asPattern = (EAsPattern)pattern;\r
+ pattern = asPattern.getPattern();\r
+ asPattern.getVariable().setVal(scrutinee[viewPatternColumn]);\r
+ }\r
+ else\r
+ break;\r
+ row.patterns[viewPatternColumn] = pattern;\r
+ }\r
+ if(!(pattern instanceof EViewPattern))\r
+ break;\r
+ EViewPattern otherViewPattern = (EViewPattern)pattern;\r
+ if(!otherViewPattern.expression.equalsExpression(firstViewPattern.expression))\r
+ break;\r
+ row.patterns[viewPatternColumn] = otherViewPattern.pattern;\r
+ }\r
+ \r
+ IVal[] newScrutinee = Arrays.copyOf(scrutinee, scrutinee.length);\r
+ newScrutinee[viewPatternColumn] =\r
+ w.apply(firstViewPattern.location,\r
+ firstViewPattern.expression.toVal(env, w),\r
+ scrutinee[viewPatternColumn]);\r
+ if(i == rows.size()) {\r
+ split(w, env, newScrutinee, failure, rows);\r
+ }\r
+ else {\r
+ CodeWriter cont = w.createBlock();\r
+ split(w, env, newScrutinee, cont.getContinuation(), rows.subList(0, i));\r
+ split(cont, env, scrutinee, failure, rows.subList(i, rows.size()));\r
+ }\r
+ }\r
+\r
+ public static void split(CodeWriter w, Environment env, IVal[] scrutinee, ICont failure, List<Row2> rows) {\r
+ Row2 firstRow = rows.get(0);\r
+ Expression[] patterns = firstRow.patterns;\r
+ if(scrutinee.length != patterns.length)\r
+ throw new InternalCompilerError("Scrutinee and patterns have a different length");\r
+ \r
+ // Find a non-variable pattern and split by it\r
+ int viewPatternColumn = -1;\r
+ for(int i=0;i<patterns.length;++i) {\r
+ Expression pattern = patterns[i];\r
+ if(pattern instanceof EViewPattern) {\r
+ if(viewPatternColumn == -1)\r
+ viewPatternColumn = i;\r
+ }\r
+ else if(!(pattern instanceof EVariable)) {\r
+ splitByConstructors(w, env, scrutinee, failure, rows, i);\r
+ return;\r
+ }\r
+ }\r
+ \r
+ if(viewPatternColumn >= 0) {\r
+ splitByViewPattern(w, env, scrutinee, failure, rows, viewPatternColumn);\r
+ return;\r
+ }\r
+\r
+ // The first row has only variable patterns: no matching needed\r
+ for(int i=0;i<patterns.length;++i)\r
+ ((EVariable)patterns[i]).getVariable().setVal(scrutinee[i]);\r
+ w.jump(firstRow.continuation);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.compiler.internal.elaboration.matching2;\r
+\r
+\r
+import java.util.Arrays;\r
+\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
+\r
+public class Row2 {\r
+ Expression[] patterns;\r
+ ICont continuation;\r
+ \r
+ public Row2(Expression[] patterns,ICont continuation) {\r
+ this.patterns = patterns;\r
+ this.continuation = continuation;\r
+ }\r
+ \r
+ public Row2 replace(int columnToReplace, Expression[] substitution) {\r
+ Expression[] newPatterns = new Expression[patterns.length-1+substitution.length];\r
+ int j=0;\r
+ for(int i=0;i<columnToReplace;++i)\r
+ newPatterns[j++] = patterns[i];\r
+ for(int i=0;i<substitution.length;++i)\r
+ newPatterns[j++] = substitution[i];\r
+ for(int i=columnToReplace+1;i<patterns.length;++i)\r
+ newPatterns[j++] = patterns[i];\r
+ return new Row2(newPatterns, continuation);\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return Arrays.toString(patterns);\r
+ }\r
+}\r
import org.simantics.scl.compiler.elaboration.expressions.EBinary;
import org.simantics.scl.compiler.elaboration.expressions.EBind;
import org.simantics.scl.compiler.elaboration.expressions.EBlock;
+import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset;
import org.simantics.scl.compiler.elaboration.expressions.EConstant;
import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;
import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
++codeCounter;
expression.condition = expression.condition.accept(this);
expression.then_ = injectBranchPoint(expression.then_);
- expression.else_ = injectBranchPoint(expression.else_);
+ if(expression.else_ != null)
+ expression.else_ = injectBranchPoint(expression.else_);
return expression;
}
return super.transform(expression);
}
+ @Override
+ public Expression transform(ECHRRuleset expression) {
+ ++codeCounter;
+ return super.transform(expression);
+ }
+
@Override
public Expression transform(EConstant expression) {
++codeCounter;
import java.util.Arrays;
import java.util.List;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.internal.codegen.references.IVal;
import org.simantics.scl.compiler.internal.elaboration.utils.ForcedClosure;
import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
-import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
import gnu.trove.set.hash.THashSet;
public class TransformationBuilder {
- private static final TCon UMap = Types.con("Unification", "UMap");
- private static final Name createUMap = Name.create("Unification", "createUMap");
-
- private static final TCon Unifiable = Types.con("Unification", "Unifiable");
- private static final Name uVar = Name.create("Unification", "uVar");
-
private final ErrorLog errorLog;
private final TypingContext context;
private final UnifiableFactory unifiableFactory;
mappingRelation.parameterTypes[0]
});
mapping.umap = new Variable("map_" + mappingRelation.name.name,
- Types.apply(UMap, mappingRelation.parameterTypes)
+ Types.apply(Names.Unifiable_UMap, mappingRelation.parameterTypes)
);
mappings.put(mappingRelation, mapping);
mappingStatements.add(new LetStatement(new EVariable(mapping.umap),
- Expressions.apply(context, Types.PROC, createUMap,
+ Expressions.apply(context.getCompilationContext(), Types.PROC, Names.Unifiable_createUMap,
mappingRelation.parameterTypes[0],
mappingRelation.parameterTypes[1],
Expressions.punit())));
int count = mappedVariableUseCount.get(variable);
if(count > 1) {
Variable uniVariable = new Variable("uvar_" + variable.getName(),
- Types.apply(Unifiable, variable.getType()));
+ Types.apply(Names.Unifiable_Unifiable, variable.getType()));
phase2Actions.add(new LetStatement(new EVariable(uniVariable),
- Expressions.apply(context, Types.PROC,
- uVar,
+ Expressions.apply(context.getCompilationContext(), Types.PROC,
+ Names.Unifiable_uVar,
variable.getType(),
Expressions.tuple())));
uniVariableMap.put(variable, uniVariable);
new QAtom(decomposed.ruleMatchingRelation,
Type.EMPTY_ARRAY,
Expressions.vars(sourceVariables)),
- statementsToExpression(context, phase2Actions),
+ statementsToExpression(context.getCompilationContext(), phase2Actions),
sourceVariables).compile(context)));
// Enforcing statement
for(int phase : phases.keys()) {
ArrayList<Query> targetQuery = phases.get(phase);
Expression enforcing = new EEnforce(new QConjunction(targetQuery.toArray(new Query[targetQuery.size()]))).compile(context);
- enforcing = statementsToExpression(context, phase3Actions, enforcing);
+ enforcing = statementsToExpression(context.getCompilationContext(), phase3Actions, enforcing);
enforcing = new EWhen(
rule.location,
new QAtom(decomposed.ruleMatchingRelation,
for(int phase : phases)
allEnforcingStatements.addAll(enforcingStatements.get(phase));
}
- Expression expression = statementsToExpression(context, allEnforcingStatements);
- expression = statementsToExpression(context, mappingStatements, expression);
+ Expression expression = statementsToExpression(context.getCompilationContext(), allEnforcingStatements);
+ expression = statementsToExpression(context.getCompilationContext(), mappingStatements, expression);
// Matching
Expression result = new ERuleset(
import java.util.ArrayList;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
-import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.constants.StringConstant;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import gnu.trove.set.hash.THashSet;
public class UnifiableFactory {
- private static final TCon Unifiable = Types.con("Unification", "Unifiable");
- private static final Name uVar = Name.create("Unification", "uVar");
- private static final Name uCons = Name.create("Unification", "uCons");
- private static final Name uId = Name.create("Unification", "uId");
- private static final Name uPending = Name.create("Unification", "uPending");
- private static final TCon UTag = Types.con("Unification", "UTag");
- private static final Name uTag = Name.create("Unification", "uTag");
- private static final Name extractWithDefault = Name.create("Unification", "extractWithDefault");
-
- private static final Name putUMap = Name.create("Unification", "putUMap");
- private static final Name putUMapC = Name.create("Unification", "putUMapC");
- private static final Name getUMapWithDefault = Name.create("Unification", "getUMapWithDefault");
-
- private static final Name fail = Name.create("Builtin", "fail");
- private static final Name unsafeCoerce = Name.create("JavaBuiltin", "unsafeCoerce");
- private static final Name newResource = Name.create("Simantics/DB", "newResource");
- private static final Name createElement = Name.create("Data/XML", "createElement");
-
- private static final Type XML_ELEMENT = Types.con("Data/XML", "Element");
-
private final TypingContext context;
/**
* The factory generates here the statements initializing the variables needed in unification.
}
@Override
public Expression toExpression() {
- return Expressions.apply(context, Types.NO_EFFECTS, uId,
+ return Expressions.apply(context.getCompilationContext(), Types.NO_EFFECTS, Names.Unifiable_uId,
constant.getType(), constant);
}
}
variable,
extract(variable.getType(), Expressions.var(uniVariableMap.get(variable))),
expression);
- return Expressions.apply(context, Types.NO_EFFECTS, uPending,
+ return Expressions.apply(context.getCompilationContext(), Types.NO_EFFECTS, Names.Unifiable_uPending,
value.getType(), Expressions.computation(Types.PROC, expression));
}
}
if(uniVariable != null)
return new UniRep(new EVariable(uniVariable));
else
- return new UniRep(Expressions.apply(context, Types.PROC, uVar, variable.getType(), Expressions.punit()));
+ return new UniRep(Expressions.apply(context.getCompilationContext(), Types.PROC, Names.Unifiable_uVar, variable.getType(), Expressions.punit()));
}
apply:
if(expression instanceof EApply) {
for(int i=0;i<arity;++i)
tupleParameters[i] = uniParameters[i].toExpression();
Expression tuple = Expressions.tuple(tupleParameters);
- return new UniRep(Expressions.apply(context, Types.NO_EFFECTS, uCons,
+ return new UniRep(Expressions.apply(context.getCompilationContext(), Types.NO_EFFECTS, Names.Unifiable_uCons,
expression.getType(), tuple.getType(),
getTag(function), tuple));
}
Type[] uniParameterTypes = new Type[arity];
for(int i=0;i<arity;++i)
- uniParameterTypes[i] = Types.apply(Unifiable, mfun.parameterTypes[i]);
+ uniParameterTypes[i] = Types.apply(Names.Unifiable_Unifiable, mfun.parameterTypes[i]);
Type tupleType = Types.tuple(uniParameterTypes);
// Destructor
Expression destructor;
if(sclValue.getName().module.equals("Builtin") && sclValue.getName().name.charAt(0)=='(') {
// Tuple constructor is a special case, where we can just cast the value
- destructor = Expressions.constant(context, unsafeCoerce, mfun.returnType, tupleType);
+ destructor = Expressions.constant(context.getCompilationContext(), Names.JavaBuiltin_unsafeCoerce, mfun.returnType, tupleType);
}
else {
Variable[] parameters = new Variable[arity];
Expression pattern = new EApply(constructorExpr.copy(context), Expressions.vars(parameters));
Expression[] tupleParameters = new Expression[arity];
for(int i=0;i<arity;++i)
- tupleParameters[i] = Expressions.apply(context, Types.NO_EFFECTS, uId,
+ tupleParameters[i] = Expressions.apply(context.getCompilationContext(), Types.NO_EFFECTS, Names.Unifiable_uId,
parameters[i].getType(), Expressions.var(parameters[i]));
Expression value = Expressions.tuple(tupleParameters);
destructor = new ELambda(Locations.NO_LOCATION, pattern, value);
constructor = new ELambda(Locations.NO_LOCATION, pattern, value);
}
- tag = new Variable("tag", Types.apply(UTag, mfun.returnType, tupleType));
+ tag = new Variable("tag", Types.apply(Names.Unifiable_UTag, mfun.returnType, tupleType));
mappingStatements.add(new LetStatement(new EVariable(tag),
- Expressions.apply(context, Types.NO_EFFECTS, uTag, tupleType, mfun.returnType,
+ Expressions.apply(context.getCompilationContext(), Types.NO_EFFECTS, Names.Unifiable_uTag, tupleType, mfun.returnType,
Expressions.integer(constructorTag), constructor, destructor)));
constructorTags.put(key, tag);
}
}
private Expression extract(Type type, Expression uni) {
- return Expressions.apply(context, Types.PROC, extractWithDefault,
+ return Expressions.apply(context.getCompilationContext(), Types.PROC, Names.Unifiable_extractWithDefault,
type, getDefaultGenerator(type), uni);
}
//System.out.println("createGenerationExpression(" + type.toString(tuc) + ")");
if(apply.constructor instanceof TCon) {
if(apply.constructor.equals(Types.RESOURCE))
- return Expressions.apply(context, Types.PROC, newResource, Expressions.tuple());
+ return Expressions.apply(context.getCompilationContext(), Types.PROC, Names.Simantics_DB_newResource, Expressions.tuple());
if(apply.constructor.equals(Types.STRING))
return new ELiteral(new StringConstant("")); // FIXME
- if(apply.constructor.equals(XML_ELEMENT))
- return Expressions.apply(context, Types.PROC, createElement, Expressions.string("NO-NAME"));
+ if(apply.constructor.equals(Names.Data_XML_Element))
+ return Expressions.apply(context.getCompilationContext(), Types.PROC, Names.Data_XML_createElement, Expressions.string("NO-NAME"));
TCon con = (TCon)apply.constructor;
if(con.name.charAt(0) == '(') { // (), (,), (,,),...
return Expressions.tuple(parameters);
}
}
- return Expressions.apply(context, Types.NO_EFFECTS, fail,
+ return Expressions.apply(context.getCompilationContext(), Types.NO_EFFECTS, Names.Builtin_fail,
new ELiteral(new StringConstant("Cannot generated default instance for type " + type + ".")));
}
}
public Expression getFromUMap(Expression umap, Expression key, Type valueType) {
- return Expressions.apply(context, Types.PROC,
- getUMapWithDefault,
+ return Expressions.apply(context.getCompilationContext(), Types.PROC,
+ Names.Unifiable_getUMapWithDefault,
valueType,
key.getType(),
getDefaultGenerator(valueType),
public Expression putToUMapUnifiable(
THashSet<Variable> variableSet, THashMap<Variable, Variable> uniVariableMap,
Expression umap, Expression key, Expression value) {
- return Expressions.apply(context, Types.PROC,
- putUMap,
+ return Expressions.apply(context.getCompilationContext(), Types.PROC,
+ Names.Unifiable_putUMap,
key.getType(),
value.getType(),
umap,
}
public Expression putToUMapConstant(Variable umap, Expression key, Expression value) {
- return Expressions.apply(context, Types.PROC,
- putUMapC,
+ return Expressions.apply(context.getCompilationContext(), Types.PROC,
+ Names.Unifiable_putUMapC,
key.getType(), value.getType(),
Expressions.var(umap),
key, value);
;
lexp
- = faexp+ # Apply, shift ID, shift LAMBDA,
+ = faexp+ # Apply, shift ID, shift LAMBDA, shift LAMBDA_MATCH,
shift LET, shift INTEGER, shift BEGIN_STRING,
shift IF, shift MATCH, shift DO,
shift MDO, shift ENFORCE, shift BLANK,
aexp
= LAMBDA aexp+ ARROW exp # Lambda, shift HASTYPE
+ | LAMBDA_MATCH LBRACE case (SEMICOLON case)* RBRACE # LambdaMatch, shift HASTYPE
| LET statements IN exp # Let, shift HASTYPE
- | IF exp THEN exp ELSE exp # If, shift HASTYPE
+ | IF exp THEN exp (ELSE exp)? # If, shift HASTYPE, shift ELSE
| MATCH exp WITH
LBRACE case (SEMICOLON case)* RBRACE # Match
| (DO | MDO) statements # Do
| (SELECT | SELECT_FIRST | SELECT_DISTINCT)
exp WHERE queryBlock # Select
| ENFORCE queryBlock # Enforce
- | WHEN queryBlock SEMICOLON exp # When
+ //| WHEN queryBlock SEMICOLON exp # When
| var # Var
| ATTACHED_HASH ID # HashedId
| BLANK # Blank
| stringLiteral # String
| CHAR # Char
| LPAREN (exp (COMMA exp)*)? RPAREN # Tuple
+ | LPAREN exp ARROW exp RPAREN # ViewPattern
| LPAREN symbolWithoutMinus lexp RPAREN # RightSection
| LPAREN lexp symbol RPAREN # LeftSection
| LBRACKET (exp (COMMA exp)*)? RBRACKET # ListLiteral
| exp rhs # LetStatement
| exp BINDS exp # BindStatement
| exp FOLLOWS queryBlock # RuleStatement
+ | chrQuery IMPLIES chrQuery # CHRStatement
+ | WHEN verboseChrQuery THEN_AFTER_WHEN verboseChrQuery # VerboseCHRStatement
+ | CONSTRAINT ID atype* # ConstraintStatement
+ ;
+
+chrQuery
+ = listQualifier (COMMA listQualifier)* # CHRQuery
+ ;
+
+verboseChrQuery
+ = LBRACE listQualifier (SEMICOLON listQualifier)* RBRACE # VerboseCHRQuery
;
listQualifier
digit = [0-9]
hexDigit = [0-9a-fA-F]
id_char = {letter} | {digit} | "'"
-ord_symbol_char = [!$%&*+\/<=>?@\\\^|\-:~]
+ord_symbol_char = [!$%&*+\/<=>@\\\^|\-:~]
symbol_char = {ord_symbol_char} | "#"
prefix = {letter} {id_char}* "."
// relation { return sym(SCLTerminals.RELATION); }
as { return sym(SCLTerminals.AS); }
by { return sym(SCLTerminals.BY); }
+ constraint { return sym(SCLTerminals.CONSTRAINT); }
{queryOp} { return sym(SCLTerminals.QUERY_OP); }
"@" { return sym(SCLTerminals.AT); }
"{" { return sym(SCLTerminals.LBRACE); }
{separatedDot} { return sym(SCLTerminals.SEPARATED_DOT, "."); }
"." { return sym(SCLTerminals.ATTACHED_DOT, "."); }
"-" { return sym(SCLTerminals.MINUS, "-"); }
-// "<" existentialVar ">" { yybegin(XML); return sym(SCLTerminals.XML_BEGIN); }
+// "<" {existentialVar} ">" { yybegin(XML); return sym(SCLTerminals.XML_BEGIN); }
"<" { return sym(SCLTerminals.LESS, "<"); }
">" { return sym(SCLTerminals.GREATER, ">"); }
";" { return sym(SCLTerminals.SEMICOLON); }
"=" { return sym(SCLTerminals.EQUALS); }
"::" { return sym(SCLTerminals.HASTYPE); }
":" { return sym(SCLTerminals.COLON); }
+ "\\" " "* match { return sym(SCLTerminals.LAMBDA_MATCH); }
"\\" { return sym(SCLTerminals.LAMBDA); }
"\"\"\"" { string.setLength(0); stringStart=yychar; yybegin(LONG_STRING); return sym(SCLTerminals.BEGIN_STRING); }
"\"" { string.setLength(0); stringStart=yychar; yybegin(STRING); return sym(SCLTerminals.BEGIN_STRING); }
/* The following code was generated by JFlex 1.6.1 */\r
\r
-package org.simantics.scl.compiler.internal.parsing.parser;\r
-\r
-import org.simantics.scl.compiler.internal.parsing.Token;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;\r
-import gnu.trove.list.array.TIntArrayList;\r
-\r
+package org.simantics.scl.compiler.internal.parsing.parser;
+
+import org.simantics.scl.compiler.internal.parsing.Token;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
+import gnu.trove.list.array.TIntArrayList;
+
\r
/**\r
* This class is a scanner generated by \r
\r
private static final String ZZ_ACTION_PACKED_0 =\r
"\4\0\1\1\1\2\1\3\1\1\1\4\1\5\1\6"+\r
- "\1\7\1\10\1\11\1\12\1\4\1\13\1\1\1\14"+\r
+ "\1\7\1\10\1\11\1\12\1\1\1\13\1\1\1\14"+\r
"\1\15\1\16\1\17\1\4\1\20\1\21\16\2\1\22"+\r
"\1\23\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+\r
"\1\33\1\13\1\34\1\35\1\36\1\0\1\37\1\36"+\r
"\1\40\2\35\2\40\5\0\1\4\1\41\1\42\1\43"+\r
- "\3\0\1\2\3\0\1\4\1\44\1\45\1\46\1\4"+\r
- "\2\2\1\47\2\2\1\50\1\51\11\2\1\52\3\2"+\r
- "\1\53\1\2\1\54\4\2\1\55\1\56\1\57\1\0"+\r
- "\1\60\1\61\1\62\1\63\1\64\1\60\1\65\2\0"+\r
- "\2\66\1\0\1\67\1\70\1\2\1\0\1\71\2\0"+\r
- "\1\72\1\0\1\4\3\2\1\73\24\2\1\74\1\75"+\r
- "\1\0\1\76\2\0\1\46\1\2\1\77\6\2\1\100"+\r
- "\1\101\2\2\1\102\3\2\1\103\1\2\1\104\1\2"+\r
- "\1\105\3\2\1\0\1\46\2\2\1\106\11\2\1\107"+\r
- "\1\110\1\2\1\111\1\2\1\0\1\112\1\2\1\113"+\r
- "\1\114\2\2\1\115\1\2\1\116\1\117\2\2\1\120"+\r
- "\2\2\1\121\2\2\1\122\2\2\1\123\1\124\1\0"+\r
- "\3\2\1\125\2\2\2\0\1\126\2\0\2\2\4\0"+\r
- "\1\127\1\2\4\0\1\2\4\0\1\2\1\130\2\0"+\r
- "\1\131\1\2\2\0\1\132\2\0\1\133\1\0\1\134";\r
+ "\3\0\1\2\4\0\1\4\1\44\1\45\1\46\1\4"+\r
+ "\2\0\2\2\1\47\2\2\1\50\1\51\11\2\1\52"+\r
+ "\3\2\1\53\2\2\1\54\4\2\1\55\1\56\1\57"+\r
+ "\1\0\1\60\1\61\1\62\1\63\1\64\1\60\1\65"+\r
+ "\2\0\2\66\1\0\1\67\1\70\1\2\1\0\1\71"+\r
+ "\2\0\2\72\1\0\1\4\1\0\3\2\1\73\25\2"+\r
+ "\1\74\1\75\1\0\1\76\2\0\1\46\1\0\1\2"+\r
+ "\1\77\6\2\1\100\1\101\2\2\1\102\3\2\1\103"+\r
+ "\1\2\1\104\2\2\1\105\3\2\1\0\1\46\1\0"+\r
+ "\2\2\1\106\11\2\1\107\1\2\1\110\1\2\1\111"+\r
+ "\1\2\1\0\1\112\1\113\1\2\1\114\1\115\2\2"+\r
+ "\1\116\1\2\1\117\1\120\2\2\1\121\3\2\1\122"+\r
+ "\2\2\1\123\2\2\1\124\1\125\1\0\4\2\1\126"+\r
+ "\2\2\2\0\1\2\1\127\2\0\2\2\2\0\1\2"+\r
+ "\2\0\1\130\1\2\2\0\1\131\2\0\1\2\4\0"+\r
+ "\1\2\1\132\2\0\1\133\1\2\2\0\1\134\2\0"+\r
+ "\1\135\1\0\1\136";\r
\r
private static int [] zzUnpackAction() {\r
- int [] result = new int[276];\r
+ int [] result = new int[293];\r
int offset = 0;\r
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);\r
return result;\r
"\0\0\0\76\0\174\0\272\0\272\0\370\0\u0136\0\u0174"+\r
"\0\u01b2\0\u01f0\0\u022e\0\u026c\0\u02aa\0\272\0\272\0\u02e8"+\r
"\0\u0326\0\u0364\0\u03a2\0\u01b2\0\u03e0\0\u041e\0\u045c\0\272"+\r
- "\0\u01b2\0\u049a\0\u04d8\0\u0516\0\u0554\0\u0592\0\u05d0\0\u060e"+\r
- "\0\u064c\0\u068a\0\u06c8\0\u0706\0\u0744\0\u0782\0\u07c0\0\272"+\r
- "\0\272\0\272\0\272\0\u07fe\0\u083c\0\272\0\u01b2\0\u087a"+\r
- "\0\370\0\272\0\272\0\u08b8\0\u08f6\0\u0934\0\272\0\272"+\r
- "\0\u0972\0\u09b0\0\u09ee\0\u08b8\0\272\0\u0a2c\0\u0a6a\0\u0aa8"+\r
- "\0\u0ae6\0\u0b24\0\u0b62\0\272\0\u0ba0\0\u0bde\0\u0c1c\0\u0c5a"+\r
- "\0\u0c98\0\u0cd6\0\u0d14\0\u0d52\0\u0d90\0\u0dce\0\u01b2\0\u01b2"+\r
- "\0\u0e0c\0\u0e4a\0\u0e88\0\u0ec6\0\370\0\u0f04\0\u0f42\0\370"+\r
- "\0\u0f80\0\u0fbe\0\u0ffc\0\u103a\0\u1078\0\u10b6\0\u10f4\0\u1132"+\r
- "\0\u1170\0\u11ae\0\370\0\u11ec\0\u122a\0\u1268\0\370\0\u12a6"+\r
- "\0\370\0\u12e4\0\u1322\0\u1360\0\u139e\0\u01b2\0\u01b2\0\u01b2"+\r
- "\0\u13dc\0\272\0\272\0\272\0\272\0\272\0\u141a\0\272"+\r
- "\0\u1458\0\u1496\0\u14d4\0\u1512\0\u1512\0\272\0\272\0\272"+\r
- "\0\u1550\0\272\0\u158e\0\u15cc\0\u01b2\0\u160a\0\u1648\0\u1686"+\r
- "\0\u16c4\0\u1702\0\370\0\u1740\0\u177e\0\u17bc\0\u17fa\0\u1838"+\r
- "\0\u1876\0\u18b4\0\u18f2\0\u1930\0\u196e\0\u19ac\0\u19ea\0\u1a28"+\r
- "\0\u1a66\0\u1aa4\0\u1ae2\0\u1b20\0\u1b5e\0\u1b9c\0\u1bda\0\370"+\r
- "\0\272\0\u1c18\0\272\0\u1c56\0\u1c94\0\u01b2\0\u1cd2\0\370"+\r
- "\0\u1d10\0\u1d4e\0\u1d8c\0\u1dca\0\u1e08\0\u1e46\0\370\0\370"+\r
- "\0\u1e84\0\u1ec2\0\370\0\u1f00\0\u1f3e\0\u1f7c\0\370\0\u1fba"+\r
- "\0\370\0\u1ff8\0\370\0\u2036\0\u2074\0\u20b2\0\u20f0\0\272"+\r
- "\0\u212e\0\u216c\0\u21aa\0\u21e8\0\u2226\0\u2264\0\u22a2\0\u22e0"+\r
- "\0\u231e\0\u235c\0\u239a\0\u23d8\0\370\0\370\0\u2416\0\370"+\r
- "\0\u2454\0\u2492\0\370\0\u24d0\0\370\0\370\0\u250e\0\u254c"+\r
- "\0\u258a\0\u25c8\0\370\0\370\0\u2606\0\u2644\0\u2682\0\u26c0"+\r
- "\0\u26fe\0\272\0\u273c\0\u277a\0\370\0\u27b8\0\u27f6\0\370"+\r
- "\0\370\0\u2834\0\u2872\0\u28b0\0\u28ee\0\370\0\u292c\0\u296a"+\r
- "\0\u29a8\0\u29e6\0\370\0\u2a24\0\u2a62\0\u2aa0\0\u2ade\0\u2b1c"+\r
+ "\0\u049a\0\u04d8\0\u0516\0\u0554\0\u0592\0\u05d0\0\u060e\0\u064c"+\r
+ "\0\u068a\0\u06c8\0\u0706\0\u0744\0\u0782\0\u07c0\0\u07fe\0\272"+\r
+ "\0\272\0\272\0\272\0\u083c\0\u087a\0\272\0\u01b2\0\u08b8"+\r
+ "\0\370\0\272\0\272\0\u08f6\0\u0934\0\u0972\0\272\0\272"+\r
+ "\0\u09b0\0\u09ee\0\u0a2c\0\u08f6\0\272\0\u0a6a\0\u0aa8\0\u0ae6"+\r
+ "\0\u0b24\0\u0b62\0\u0ba0\0\272\0\u0bde\0\u0c1c\0\u0c5a\0\u0c98"+\r
+ "\0\u0cd6\0\u0d14\0\u0d52\0\u0d90\0\u0dce\0\u0e0c\0\u0e4a\0\u01b2"+\r
+ "\0\u01b2\0\u0e88\0\u0ec6\0\u0f04\0\u0f42\0\u0f80\0\u0fbe\0\370"+\r
+ "\0\u0ffc\0\u103a\0\370\0\u1078\0\u10b6\0\u10f4\0\u1132\0\u1170"+\r
+ "\0\u11ae\0\u11ec\0\u122a\0\u1268\0\u12a6\0\370\0\u12e4\0\u1322"+\r
+ "\0\u1360\0\370\0\u139e\0\u13dc\0\370\0\u141a\0\u1458\0\u1496"+\r
+ "\0\u14d4\0\u01b2\0\u01b2\0\u01b2\0\u1512\0\272\0\272\0\272"+\r
+ "\0\272\0\272\0\u1550\0\272\0\u158e\0\u02e8\0\u15cc\0\u160a"+\r
+ "\0\u160a\0\272\0\272\0\272\0\u1648\0\272\0\u1686\0\u16c4"+\r
+ "\0\272\0\u01b2\0\u1702\0\u1740\0\u177e\0\u17bc\0\u17fa\0\u1838"+\r
+ "\0\370\0\u1876\0\u18b4\0\u18f2\0\u1930\0\u196e\0\u19ac\0\u19ea"+\r
+ "\0\u1a28\0\u1a66\0\u1aa4\0\u1ae2\0\u1b20\0\u1b5e\0\u1b9c\0\u1bda"+\r
+ "\0\u1c18\0\u1c56\0\u1c94\0\u1cd2\0\u1d10\0\u1d4e\0\370\0\272"+\r
+ "\0\u1d8c\0\272\0\u1dca\0\u1e08\0\u01b2\0\u1e46\0\u1e84\0\370"+\r
+ "\0\u1ec2\0\u1f00\0\u1f3e\0\u1f7c\0\u1fba\0\u1ff8\0\370\0\370"+\r
+ "\0\u2036\0\u2074\0\370\0\u20b2\0\u20f0\0\u212e\0\370\0\u216c"+\r
+ "\0\370\0\u21aa\0\u21e8\0\370\0\u2226\0\u2264\0\u22a2\0\u22e0"+\r
+ "\0\272\0\u231e\0\u235c\0\u239a\0\u23d8\0\u2416\0\u2454\0\u2492"+\r
+ "\0\u24d0\0\u250e\0\u254c\0\u258a\0\u25c8\0\u2606\0\370\0\u2644"+\r
+ "\0\370\0\u2682\0\370\0\u26c0\0\u26fe\0\272\0\370\0\u273c"+\r
+ "\0\370\0\370\0\u277a\0\u27b8\0\u27f6\0\u2834\0\370\0\370"+\r
+ "\0\u2872\0\u28b0\0\u28ee\0\u292c\0\u296a\0\u29a8\0\272\0\u29e6"+\r
+ "\0\u2a24\0\370\0\u2a62\0\u2aa0\0\370\0\370\0\u2ade\0\u2b1c"+\r
"\0\u2b5a\0\u2b98\0\u2bd6\0\370\0\u2c14\0\u2c52\0\u2c90\0\u2cce"+\r
- "\0\u2d0c\0\u2d4a\0\u2d88\0\u2dc6\0\u2e04\0\u2e42\0\u2e80\0\272"+\r
- "\0\u2ebe\0\u2efc\0\272\0\u2f3a\0\u2f78\0\u2fb6\0\370\0\u2ff4"+\r
- "\0\u3032\0\272\0\u3070\0\272";\r
+ "\0\u2d0c\0\370\0\u2d4a\0\u2d88\0\u2dc6\0\u2e04\0\u2e42\0\u2e80"+\r
+ "\0\u2ebe\0\u2efc\0\u2f3a\0\370\0\u2f78\0\u2fb6\0\u2ff4\0\370"+\r
+ "\0\u3032\0\u3070\0\u30ae\0\u30ec\0\u312a\0\u3168\0\u31a6\0\u31e4"+\r
+ "\0\272\0\u3222\0\u3260\0\272\0\u329e\0\u32dc\0\u331a\0\370"+\r
+ "\0\u3358\0\u3396\0\272\0\u33d4\0\272";\r
\r
private static int [] zzUnpackRowMap() {\r
- int [] result = new int[276];\r
+ int [] result = new int[293];\r
int offset = 0;\r
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);\r
return result;\r
"\12\0\1\6\6\0\30\6\11\0\1\6\5\0\1\7"+\r
"\4\0\1\77\12\0\1\100\16\0\1\100\34\0\4\101"+\r
"\1\0\22\101\1\0\1\102\45\101\5\0\2\11\1\0"+\r
- "\1\11\3\0\1\11\2\0\3\11\1\0\1\11\1\0"+\r
- "\2\11\1\0\1\11\34\0\2\11\1\0\1\11\12\0"+\r
- "\2\11\1\0\1\11\3\0\1\11\1\103\1\0\3\11"+\r
- "\1\0\1\11\1\103\2\11\1\0\1\11\34\0\2\11"+\r
- "\1\0\1\11\3\0\1\103\10\0\1\104\5\0\1\105"+\r
- "\6\0\1\105\47\0\1\105\2\0\1\106\1\0\1\106"+\r
- "\1\0\2\11\1\0\1\11\3\0\1\11\2\0\3\11"+\r
- "\1\106\1\11\1\0\2\11\1\0\1\11\30\106\4\0"+\r
- "\2\11\1\0\1\11\1\0\1\106\10\0\2\107\1\110"+\r
- "\1\107\1\0\1\111\1\0\1\107\2\0\3\107\1\0"+\r
- "\1\107\1\0\2\107\1\0\1\107\34\0\2\107\1\0"+\r
- "\1\107\6\0\1\112\1\0\1\112\1\0\2\11\1\0"+\r
- "\1\11\3\0\1\11\2\0\3\11\1\112\1\11\1\0"+\r
- "\2\11\1\0\1\11\30\112\4\0\2\11\1\0\1\11"+\r
- "\1\0\1\112\77\0\1\62\2\0\1\113\1\0\1\113"+\r
- "\5\0\1\114\2\0\1\115\5\0\1\113\6\0\30\113"+\r
- "\11\0\1\113\10\0\2\11\1\0\1\11\3\0\1\116"+\r
- "\2\0\1\11\1\116\1\11\1\0\1\117\1\0\2\11"+\r
- "\1\0\1\11\34\0\2\11\1\0\1\116\12\0\2\11"+\r
- "\1\0\1\11\3\0\1\11\2\0\2\11\1\120\1\0"+\r
+ "\1\11\6\0\3\11\1\0\1\11\1\0\2\11\1\0"+\r
+ "\1\11\34\0\2\11\1\0\1\11\12\0\2\11\1\0"+\r
+ "\1\11\4\0\1\103\1\0\3\11\1\0\1\11\1\103"+\r
+ "\2\11\1\0\1\11\34\0\2\11\1\0\1\11\3\0"+\r
+ "\1\103\10\0\1\104\5\0\1\105\6\0\1\105\47\0"+\r
+ "\1\105\2\0\1\106\1\0\1\106\1\0\2\11\1\0"+\r
+ "\1\11\6\0\3\11\1\106\1\11\1\0\2\11\1\0"+\r
+ "\1\11\30\106\4\0\2\11\1\0\1\11\1\0\1\106"+\r
+ "\10\0\2\107\1\110\1\107\1\0\1\111\4\0\3\107"+\r
+ "\1\0\1\107\1\0\2\107\1\0\1\107\34\0\2\107"+\r
+ "\1\0\1\107\6\0\1\112\1\0\1\112\16\0\1\112"+\r
+ "\6\0\30\112\11\0\1\112\77\0\1\62\2\0\1\113"+\r
+ "\1\0\1\113\5\0\1\114\2\0\1\115\5\0\1\113"+\r
+ "\6\0\30\113\11\0\1\113\10\0\2\11\1\0\1\11"+\r
+ "\3\0\1\116\2\0\1\11\1\117\1\11\1\0\1\120"+\r
+ "\1\0\2\11\1\0\1\11\34\0\2\11\1\0\1\117"+\r
+ "\12\0\2\11\1\0\1\11\6\0\2\11\1\121\1\0"+\r
"\1\11\1\0\2\11\1\0\1\11\34\0\2\11\1\0"+\r
- "\1\11\31\0\1\26\56\0\2\11\1\0\1\11\3\0"+\r
- "\1\11\2\0\3\11\1\0\1\11\1\0\1\121\1\122"+\r
- "\1\0\1\11\34\0\2\11\1\0\1\11\6\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\1\6\1\123\26\6"+\r
+ "\1\11\31\0\1\26\56\0\2\11\1\0\1\11\6\0"+\r
+ "\3\11\1\0\1\11\1\0\1\122\1\123\1\0\1\11"+\r
+ "\34\0\2\11\1\0\1\11\12\0\2\11\1\0\1\11"+\r
+ "\6\0\3\11\1\0\1\11\1\124\2\11\1\0\1\11"+\r
+ "\21\0\1\125\12\0\2\11\1\0\1\11\6\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\1\6\1\126\26\6"+\r
"\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\14\6\1\124\13\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\12\6\1\125\2\6"+\r
- "\1\126\12\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\10\6\1\127\17\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\1\130"+\r
- "\10\6\1\131\7\6\1\132\6\6\11\0\1\6\4\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\2\6\1\133"+\r
- "\4\6\1\134\16\6\1\135\1\6\11\0\1\6\4\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\5\6\1\136"+\r
+ "\6\0\14\6\1\127\13\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\12\6\1\130\2\6"+\r
+ "\1\131\12\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\10\6\1\132\17\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\1\133"+\r
+ "\10\6\1\134\7\6\1\135\6\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\2\6\1\136"+\r
+ "\4\6\1\137\16\6\1\140\1\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\5\6\1\141"+\r
"\22\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\1\137\3\6\1\140\4\6\1\141\5\6"+\r
- "\1\142\4\6\1\143\3\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\10\6\1\144\17\6"+\r
+ "\1\6\6\0\1\142\3\6\1\143\4\6\1\144\5\6"+\r
+ "\1\145\4\6\1\146\3\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\10\6\1\147\17\6"+\r
"\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\5\6\1\145\1\6\1\146\20\6\11\0\1\6"+\r
+ "\6\0\5\6\1\150\1\6\1\151\20\6\11\0\1\6"+\r
"\4\0\4\6\2\0\1\76\12\0\1\6\6\0\26\6"+\r
- "\1\147\1\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\4\6\1\150\23\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\1\6"+\r
- "\1\151\1\6\1\152\4\6\1\153\17\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\3\6"+\r
- "\1\154\14\6\1\155\7\6\11\0\1\6\10\0\2\11"+\r
- "\1\0\1\11\3\0\1\11\2\0\2\11\1\156\1\0"+\r
- "\1\11\1\0\2\11\1\0\1\11\34\0\2\11\1\0"+\r
- "\1\11\12\0\2\11\1\0\1\11\3\0\1\11\2\0"+\r
- "\3\11\1\0\1\157\1\0\2\11\1\0\1\11\34\0"+\r
- "\1\11\1\160\1\0\1\11\76\0\1\161\4\0\15\64"+\r
- "\1\0\11\64\2\0\40\64\1\0\2\64\1\0\1\64"+\r
- "\74\0\1\70\1\0\4\162\1\163\4\162\1\164\3\162"+\r
- "\1\0\12\162\1\163\2\162\1\165\3\162\1\166\2\162"+\r
- "\1\75\2\162\1\167\23\162\1\163\1\162\2\0\1\162"+\r
- "\74\0\1\75\12\0\1\170\155\0\1\171\5\0\1\6"+\r
- "\1\0\1\6\10\0\1\172\5\0\1\6\6\0\30\6"+\r
- "\11\0\1\6\5\0\1\173\75\0\1\174\20\0\1\175"+\r
- "\56\0\1\176\71\0\27\101\1\0\46\101\15\0\1\103"+\r
- "\6\0\1\103\47\0\1\103\16\0\1\105\6\0\1\105"+\r
- "\47\0\1\105\2\0\4\106\15\0\1\106\6\0\30\106"+\r
- "\11\0\1\106\10\0\2\107\1\0\1\107\2\0\1\177"+\r
- "\1\107\2\0\3\107\1\0\1\107\1\0\2\107\1\0"+\r
- "\1\107\34\0\2\107\1\0\1\107\20\0\1\177\74\0"+\r
- "\1\111\1\200\63\0\4\112\15\0\1\112\6\0\30\112"+\r
- "\11\0\1\112\4\0\4\113\2\0\1\201\6\0\1\202"+\r
- "\3\0\1\113\6\0\30\113\11\0\1\113\15\0\1\203"+\r
- "\64\0\1\204\1\0\1\204\16\0\1\204\6\0\30\204"+\r
- "\11\0\1\204\10\0\2\11\1\0\1\11\3\0\1\11"+\r
- "\2\0\2\11\1\205\1\0\1\11\1\0\2\11\1\0"+\r
- "\1\11\34\0\2\11\1\0\1\11\5\0\15\121\1\0"+\r
- "\56\121\1\0\1\121\5\206\2\122\1\206\1\122\3\206"+\r
- "\1\122\2\206\3\122\1\206\1\122\1\206\1\122\1\207"+\r
- "\1\206\1\122\34\206\2\122\1\206\1\122\5\206\1\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\2\6\1\210"+\r
- "\25\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\4\6\1\211\23\6\11\0\1\6\4\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\12\6\1\212"+\r
- "\15\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\6\6\1\213\21\6\11\0\1\6\4\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\1\214\11\6"+\r
- "\1\215\3\6\1\216\11\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\22\6\1\217\5\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\3\6\1\220\24\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\10\6\1\221\17\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\22\6\1\222\5\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\20\6\1\223\7\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\1\224\27\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\12\6\1\225\15\6\11\0"+\r
- "\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\1\226\27\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\6\6\1\227\21\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\4\6"+\r
- "\1\230\23\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\6\6\1\231\21\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\10\6"+\r
- "\1\232\17\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\3\6\1\233\24\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\6\6"+\r
- "\1\234\21\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\2\6\1\235\25\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\6\6"+\r
- "\1\236\13\6\1\237\5\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\1\6\1\240\26\6"+\r
- "\11\0\1\6\74\0\1\241\6\0\2\242\16\0\1\242"+\r
- "\6\0\1\242\2\0\1\242\4\0\1\242\4\0\2\242"+\r
- "\1\0\1\242\115\0\1\243\5\0\1\112\1\0\1\112"+\r
- "\16\0\1\112\6\0\30\112\11\0\1\112\5\0\1\173"+\r
- "\17\0\1\100\16\0\1\100\36\0\1\174\74\0\1\113"+\r
- "\1\0\1\113\10\0\1\115\5\0\1\113\6\0\30\113"+\r
- "\11\0\1\113\15\0\1\203\1\244\63\0\4\204\11\0"+\r
- "\1\202\3\0\1\204\6\0\30\204\11\0\1\204\3\0"+\r
- "\26\206\1\245\54\206\2\122\1\206\1\122\3\206\1\122"+\r
- "\2\206\3\122\1\206\1\122\1\206\1\246\1\207\1\206"+\r
- "\1\122\34\206\2\122\1\206\1\122\5\206\1\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\3\6\1\247\24\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\10\6\1\250\17\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\6\6\1\251\21\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\5\6\1\252\22\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\6\6\1\253\21\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\4\6\1\254\23\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\1\6\1\255\26\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\11\6\1\256\16\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\11\6\1\257\16\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\10\6\1\260\17\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\5\6\1\261\22\6"+\r
+ "\1\152\1\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\1\6\1\153\2\6\1\154\23\6"+\r
"\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\10\6\1\262\17\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\10\6\1\263\17\6"+\r
+ "\6\0\1\6\1\155\1\6\1\156\4\6\1\157\17\6"+\r
"\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\1\6\1\264\26\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\10\6\1\265\17\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\10\6\1\266\17\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\7\6\1\267\20\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\2\6\1\270\6\6\1\271\16\6\11\0\1\6"+\r
+ "\6\0\3\6\1\160\14\6\1\161\7\6\11\0\1\6"+\r
+ "\10\0\2\11\1\0\1\11\6\0\2\11\1\162\1\0"+\r
+ "\1\11\1\0\2\11\1\0\1\11\34\0\2\11\1\0"+\r
+ "\1\11\12\0\2\11\1\0\1\11\6\0\3\11\1\0"+\r
+ "\1\163\1\0\2\11\1\0\1\11\34\0\1\11\1\164"+\r
+ "\1\0\1\11\76\0\1\165\4\0\15\64\1\0\11\64"+\r
+ "\2\0\40\64\1\0\2\64\1\0\1\64\74\0\1\70"+\r
+ "\1\0\4\166\1\167\4\166\1\170\3\166\1\0\12\166"+\r
+ "\1\167\2\166\1\171\3\166\1\172\2\166\1\75\2\166"+\r
+ "\1\173\23\166\1\167\1\166\2\0\1\166\74\0\1\75"+\r
+ "\12\0\1\174\155\0\1\175\5\0\1\6\1\0\1\6"+\r
+ "\10\0\1\176\5\0\1\6\6\0\30\6\11\0\1\6"+\r
+ "\5\0\1\177\75\0\1\200\20\0\1\201\56\0\1\202"+\r
+ "\71\0\27\101\1\0\46\101\15\0\1\103\6\0\1\103"+\r
+ "\47\0\1\103\16\0\1\105\6\0\1\105\47\0\1\105"+\r
+ "\2\0\4\106\15\0\1\106\6\0\30\106\11\0\1\106"+\r
+ "\10\0\2\107\1\0\1\107\2\0\1\203\3\0\3\107"+\r
+ "\1\0\1\107\1\0\2\107\1\0\1\107\34\0\2\107"+\r
+ "\1\0\1\107\20\0\1\203\74\0\1\111\1\204\63\0"+\r
+ "\4\112\15\0\1\112\6\0\30\112\11\0\1\112\4\0"+\r
+ "\4\113\2\0\1\205\6\0\1\206\3\0\1\113\6\0"+\r
+ "\30\113\11\0\1\113\15\0\1\207\64\0\1\210\1\0"+\r
+ "\1\210\16\0\1\210\6\0\30\210\11\0\1\210\24\0"+\r
+ "\1\211\61\0\2\11\1\0\1\11\6\0\2\11\1\212"+\r
+ "\1\0\1\11\1\0\2\11\1\0\1\11\34\0\2\11"+\r
+ "\1\0\1\11\5\0\15\122\1\0\56\122\1\0\1\122"+\r
+ "\5\213\2\123\1\213\1\123\6\213\3\123\1\213\1\123"+\r
+ "\1\213\1\123\1\214\1\213\1\123\34\213\2\123\1\213"+\r
+ "\1\123\5\213\24\0\1\124\25\0\1\125\57\0\1\215"+\r
+ "\42\0\4\6\2\0\1\76\12\0\1\6\6\0\2\6"+\r
+ "\1\216\25\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\4\6\1\217\23\6\11\0\1\6"+\r
"\4\0\4\6\2\0\1\76\12\0\1\6\6\0\12\6"+\r
- "\1\272\15\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\3\6\1\273\24\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\5\6"+\r
- "\1\274\22\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\16\6\1\275\11\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\22\6"+\r
- "\1\276\5\6\11\0\1\6\5\0\2\277\16\0\1\277"+\r
- "\6\0\1\277\2\0\1\277\4\0\1\277\4\0\2\277"+\r
- "\1\0\1\277\42\0\1\202\57\0\25\206\1\300\1\245"+\r
- "\47\206\1\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\4\6\1\301\23\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\2\6\1\302\25\6\11\0"+\r
+ "\1\220\15\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\6\6\1\221\21\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\1\222"+\r
+ "\11\6\1\223\3\6\1\224\11\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\22\6\1\225"+\r
+ "\5\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\3\6\1\226\24\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\10\6\1\227"+\r
+ "\17\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\22\6\1\230\5\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\20\6\1\231"+\r
+ "\7\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\1\232\27\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\12\6\1\233\15\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\1\234\27\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\6\6\1\235\21\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\17\6\1\303\10\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\3\6\1\304\24\6\11\0"+\r
+ "\4\6\1\236\23\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\6\6\1\237\21\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\14\6\1\305\13\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\2\6\1\306\25\6\11\0"+\r
+ "\10\6\1\240\17\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\11\6\1\241\16\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\12\6\1\307\15\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\11\6\1\310\16\6\11\0"+\r
+ "\3\6\1\242\24\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\6\6\1\243\21\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\16\6\1\311\11\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\2\6\1\312\25\6\11\0"+\r
+ "\2\6\1\244\25\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\6\6\1\245\13\6\1\246"+\r
+ "\5\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\1\6\1\247\26\6\11\0\1\6\74\0"+\r
+ "\1\250\6\0\2\251\16\0\1\251\6\0\1\251\2\0"+\r
+ "\1\251\4\0\1\251\4\0\2\251\1\0\1\251\115\0"+\r
+ "\1\252\6\0\1\177\17\0\1\100\16\0\1\100\36\0"+\r
+ "\1\200\74\0\1\113\1\0\1\113\10\0\1\115\5\0"+\r
+ "\1\113\6\0\30\113\11\0\1\113\15\0\1\207\1\253"+\r
+ "\63\0\4\210\11\0\1\206\3\0\1\210\6\0\30\210"+\r
+ "\11\0\1\210\3\0\26\213\1\254\54\213\2\123\1\213"+\r
+ "\1\123\6\213\3\123\1\213\1\123\1\213\1\255\1\214"+\r
+ "\1\213\1\123\34\213\2\123\1\213\1\123\5\213\37\0"+\r
+ "\1\256\37\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
+ "\3\6\1\257\24\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\10\6\1\260\17\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\11\6\1\313\16\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\16\6\1\314\11\6\11\0"+\r
+ "\6\6\1\261\21\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\5\6\1\262\22\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\10\6\1\315\17\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\12\6\1\316\15\6\11\0"+\r
+ "\6\6\1\263\21\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\4\6\1\264\23\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\25\6\1\317\2\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\7\6\1\320\20\6\11\0"+\r
+ "\1\6\1\265\26\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\11\6\1\266\16\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\5\6\1\321\22\6\11\0\1\6\5\0\2\322\16\0"+\r
- "\1\322\6\0\1\322\2\0\1\322\4\0\1\322\4\0"+\r
- "\2\322\1\0\1\322\25\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\4\6\1\323\23\6\11\0\1\6\4\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\3\6\1\324"+\r
- "\24\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\2\6\1\325\1\6\1\326\23\6\11\0"+\r
+ "\11\6\1\267\16\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\10\6\1\270\17\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\11\6\1\327\16\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\20\6\1\330\7\6\11\0"+\r
+ "\5\6\1\271\22\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\10\6\1\272\17\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\6\6\1\331\21\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\1\332\27\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\23\6"+\r
- "\1\333\4\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\6\6\1\334\21\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\16\6"+\r
- "\1\335\11\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\20\6\1\336\7\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\6\6"+\r
- "\1\337\21\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
- "\12\0\1\6\6\0\5\6\1\340\22\6\11\0\1\6"+\r
- "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\11\6"+\r
- "\1\341\16\6\11\0\1\6\5\0\2\342\16\0\1\342"+\r
- "\6\0\1\342\2\0\1\342\4\0\1\342\4\0\2\342"+\r
- "\1\0\1\342\25\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\16\6\1\343\11\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\16\6\1\344\11\6"+\r
- "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
- "\6\0\10\6\1\345\17\6\11\0\1\6\4\0\4\6"+\r
- "\2\0\1\76\12\0\1\6\6\0\27\6\1\346\11\0"+\r
+ "\10\6\1\273\17\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\1\6\1\274\26\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\1\6\1\347\26\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\10\6\1\350\17\6\11\0"+\r
+ "\10\6\1\275\17\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\10\6\1\276\17\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\12\6\1\351\15\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\1\0\1\352\4\0\30\6\11\0"+\r
- "\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\11\6\1\353\16\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\23\6\1\354\4\6\11\0"+\r
+ "\7\6\1\277\20\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\2\6\1\300\6\6\1\301"+\r
+ "\16\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\12\6\1\302\15\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\12\6\1\303"+\r
+ "\15\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\3\6\1\304\24\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\5\6\1\305"+\r
+ "\22\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\16\6\1\306\11\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\22\6\1\307"+\r
+ "\5\6\11\0\1\6\5\0\2\310\16\0\1\310\6\0"+\r
+ "\1\310\2\0\1\310\4\0\1\310\4\0\2\310\1\0"+\r
+ "\1\310\42\0\1\206\57\0\25\213\1\311\1\254\47\213"+\r
+ "\47\0\1\312\27\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\4\6\1\313\23\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\2\6\1\314\25\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\17\6\1\315\10\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\3\6\1\316\24\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\14\6\1\317\13\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\2\6\1\320\25\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\12\6\1\321\15\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\11\6\1\322\16\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\16\6\1\323\11\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\2\6\1\324\25\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\11\6\1\325\16\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\16\6\1\326\11\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\10\6\1\327\17\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\6\6\1\330\21\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\12\6\1\331\15\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\25\6\1\332\2\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\7\6\1\333\20\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\5\6\1\334\22\6"+\r
+ "\11\0\1\6\5\0\2\335\16\0\1\335\6\0\1\335"+\r
+ "\2\0\1\335\4\0\1\335\4\0\2\335\1\0\1\335"+\r
+ "\64\0\1\336\36\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\4\6\1\337\23\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\3\6\1\340\24\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\2\6\1\341\1\6\1\342\23\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\11\6"+\r
+ "\1\343\16\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\20\6\1\344\7\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\6\6"+\r
+ "\1\345\21\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\1\346\27\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\23\6\1\347"+\r
+ "\4\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\6\6\1\350\21\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\16\6\1\351"+\r
+ "\11\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\20\6\1\352\7\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\6\6\1\353"+\r
+ "\21\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\2\6\1\354\25\6\11\0\1\6\4\0"+\r
+ "\4\6\2\0\1\76\12\0\1\6\6\0\5\6\1\355"+\r
+ "\22\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
+ "\1\6\6\0\11\6\1\356\16\6\11\0\1\6\5\0"+\r
+ "\2\357\16\0\1\357\6\0\1\357\2\0\1\357\4\0"+\r
+ "\1\357\4\0\2\357\1\0\1\357\25\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\16\6\1\360\11\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\6\6\1\355\21\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\10\6\1\356\17\6\11\0"+\r
+ "\16\6\1\361\11\6\11\0\1\6\4\0\4\6\2\0"+\r
+ "\1\76\12\0\1\6\6\0\10\6\1\362\17\6\11\0"+\r
"\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+\r
- "\3\6\1\357\24\6\11\0\1\6\4\0\4\6\2\0"+\r
- "\1\76\12\0\1\6\6\0\2\6\1\360\25\6\11\0"+\r
- "\1\6\27\0\1\352\4\0\1\361\17\0\1\362\25\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\23\6\1\363"+\r
- "\4\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\1\0\1\364\4\0\30\6\11\0\1\6\4\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\1\0\1\365\4\0"+\r
- "\30\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\25\6\1\366\2\6\11\0\1\6\4\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\21\6\1\367"+\r
- "\6\6\11\0\1\6\41\0\1\370\75\0\1\371\63\0"+\r
- "\1\364\6\0\1\372\66\0\1\365\6\0\1\373\43\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\3\6\1\374"+\r
- "\24\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\3\6\1\375\24\6\11\0\1\6\36\0"+\r
- "\1\376\105\0\1\377\73\0\1\u0100\101\0\1\u0101\31\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\6\6\1\u0102"+\r
- "\21\6\11\0\1\6\46\0\1\u0103\71\0\1\u0104\73\0"+\r
- "\1\u0105\75\0\1\u0106\41\0\4\6\2\0\1\76\12\0"+\r
- "\1\6\6\0\5\6\1\u0107\22\6\11\0\1\6\42\0"+\r
- "\1\u0108\74\0\1\u0109\73\0\1\u010a\102\0\1\u010b\35\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\1\6\1\u010c"+\r
- "\26\6\11\0\1\6\45\0\1\u010d\72\0\1\u010e\37\0"+\r
- "\4\6\2\0\1\76\12\0\1\6\6\0\11\6\1\u010f"+\r
- "\16\6\11\0\1\6\52\0\1\u0110\64\0\1\u0111\76\0"+\r
- "\1\u0112\70\0\1\u0113\105\0\1\u0114\33\0";\r
+ "\27\6\1\363\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\1\6\1\364\26\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\10\6"+\r
+ "\1\365\17\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\12\6\1\366\15\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\1\0\1\367"+\r
+ "\4\0\30\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\3\6\1\370\24\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\11\6"+\r
+ "\1\371\16\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\23\6\1\372\4\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\6\6"+\r
+ "\1\373\21\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\10\6\1\374\17\6\11\0\1\6"+\r
+ "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\3\6"+\r
+ "\1\375\24\6\11\0\1\6\4\0\4\6\2\0\1\76"+\r
+ "\12\0\1\6\6\0\2\6\1\376\25\6\11\0\1\6"+\r
+ "\27\0\1\367\4\0\1\377\17\0\1\u0100\25\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\5\6\1\u0101\22\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\23\6\1\u0102\4\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\1\0\1\u0103\4\0\30\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\1\0\1\u0104\4\0\30\6\11\0\1\6\4\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\25\6\1\u0105\2\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\21\6\1\u0106\6\6\11\0\1\6\41\0\1\u0107"+\r
+ "\75\0\1\u0108\40\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\11\6\1\u0109\16\6\11\0\1\6\27\0\1\u0103"+\r
+ "\6\0\1\u010a\66\0\1\u0104\6\0\1\u010b\43\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\3\6\1\u010c\24\6"+\r
+ "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\3\6\1\u010d\24\6\11\0\1\6\36\0\1\u010e"+\r
+ "\105\0\1\u010f\33\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\6\6\1\u0110\21\6\11\0\1\6\44\0\1\u0111"+\r
+ "\101\0\1\u0112\31\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\6\6\1\u0113\21\6\11\0\1\6\46\0\1\u0114"+\r
+ "\71\0\1\u0115\73\0\1\u0116\75\0\1\u0117\41\0\4\6"+\r
+ "\2\0\1\76\12\0\1\6\6\0\5\6\1\u0118\22\6"+\r
+ "\11\0\1\6\42\0\1\u0119\74\0\1\u011a\73\0\1\u011b"+\r
+ "\102\0\1\u011c\35\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\1\6\1\u011d\26\6\11\0\1\6\45\0\1\u011e"+\r
+ "\72\0\1\u011f\37\0\4\6\2\0\1\76\12\0\1\6"+\r
+ "\6\0\11\6\1\u0120\16\6\11\0\1\6\52\0\1\u0121"+\r
+ "\64\0\1\u0122\76\0\1\u0123\70\0\1\u0124\105\0\1\u0125"+\r
+ "\33\0";\r
\r
private static int [] zzUnpackTrans() {\r
- int [] result = new int[12462];\r
+ int [] result = new int[13330];\r
int offset = 0;\r
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);\r
return result;\r
"\3\0\1\10\1\11\10\1\2\11\10\1\1\11\17\1"+\r
"\4\11\2\1\1\11\3\1\2\11\2\1\1\0\2\11"+\r
"\4\1\1\11\5\0\1\1\1\11\2\1\3\0\1\1"+\r
- "\3\0\43\1\1\0\5\11\1\1\1\11\2\0\2\1"+\r
- "\1\0\3\11\1\0\1\11\2\0\1\1\1\0\32\1"+\r
- "\1\11\1\0\1\11\2\0\31\1\1\0\1\11\21\1"+\r
- "\1\0\17\1\1\11\7\1\1\0\6\1\2\0\1\1"+\r
- "\2\0\2\1\4\0\2\1\4\0\1\1\4\0\1\1"+\r
- "\1\11\2\0\1\11\1\1\2\0\1\1\2\0\1\11"+\r
- "\1\0\1\11";\r
+ "\4\0\5\1\2\0\37\1\1\0\5\11\1\1\1\11"+\r
+ "\2\0\2\1\1\0\3\11\1\0\1\11\2\0\1\11"+\r
+ "\1\1\1\0\1\1\1\0\32\1\1\11\1\0\1\11"+\r
+ "\2\0\1\1\1\0\31\1\1\0\1\11\1\0\22\1"+\r
+ "\1\0\1\11\20\1\1\11\7\1\1\0\7\1\2\0"+\r
+ "\2\1\2\0\2\1\2\0\1\1\2\0\2\1\2\0"+\r
+ "\1\1\2\0\1\1\4\0\1\1\1\11\2\0\1\11"+\r
+ "\1\1\2\0\1\1\2\0\1\11\1\0\1\11";\r
\r
private static int [] zzUnpackAttribute() {\r
- int [] result = new int[276];\r
+ int [] result = new int[293];\r
int offset = 0;\r
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);\r
return result;\r
private int zzFinalHighSurrogate = 0;\r
\r
/* user code: */\r
- public SCLParserOptions options = SCLParserOptions.DEFAULT;\r
- int stringStart;\r
- TIntArrayList parenCountStack = new TIntArrayList(2);\r
- int parenCount = 0;\r
- TIntArrayList stateStack = new TIntArrayList(2);\r
-\r
- StringBuffer string = new StringBuffer();\r
- \r
- private Token sym(int id) {\r
- return new Token(id, yychar, yychar+yylength(), yytext());\r
- }\r
- private Token sym(int id, String text) {\r
- return new Token(id, yychar, yychar+yylength(), text);\r
- }\r
+ public SCLParserOptions options = SCLParserOptions.DEFAULT;
+ int stringStart;
+ TIntArrayList parenCountStack = new TIntArrayList(2);
+ int parenCount = 0;
+ TIntArrayList stateStack = new TIntArrayList(2);
+
+ StringBuffer string = new StringBuffer();
+
+ private Token sym(int id) {
+ return new Token(id, yychar, yychar+yylength(), yytext());
+ }
+ private Token sym(int id, String text) {
+ return new Token(id, yychar, yychar+yylength(), text);
+ }
\r
\r
/**\r
case STRING: {\r
throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Unclosed string literal.");\r
}\r
- case 277: break;\r
+ case 294: break;\r
case LONG_STRING: {\r
throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Unclosed string literal.");\r
}\r
- case 278: break;\r
+ case 295: break;\r
default:\r
- { return sym(SCLTerminals.EOF);\r
+ { return sym(SCLTerminals.EOF);
}\r
}\r
}\r
case 1: \r
{ throw new SCLSyntaxErrorException(Locations.location(yychar, yychar+1), "Illegal character '" + yytext() + "'.");\r
}\r
- case 93: break;\r
+ case 95: break;\r
case 2: \r
{ return sym(SCLTerminals.ID);\r
}\r
- case 94: break;\r
+ case 96: break;\r
case 3: \r
{ return sym(SCLTerminals.INTEGER);\r
}\r
- case 95: break;\r
+ case 97: break;\r
case 4: \r
{ return sym(SCLTerminals.SYMBOL, yytext().trim());\r
}\r
- case 96: break;\r
+ case 98: break;\r
case 5: \r
{ return sym(SCLTerminals.ATTACHED_HASH, "#");\r
}\r
- case 97: break;\r
+ case 99: break;\r
case 6: \r
{ return sym(SCLTerminals.ATTACHED_DOT, ".");\r
}\r
- case 98: break;\r
+ case 100: break;\r
case 7: \r
{ return sym(SCLTerminals.AT);\r
}\r
- case 99: break;\r
+ case 101: break;\r
case 8: \r
{ ++parenCount; return sym(SCLTerminals.LPAREN);\r
}\r
- case 100: break;\r
+ case 102: break;\r
case 9: \r
{ return sym(SCLTerminals.COMMA);\r
}\r
- case 101: break;\r
+ case 103: break;\r
case 10: \r
- { --parenCount;\r
- if(parenCount == 0 && !parenCountStack.isEmpty()) { \r
- parenCount = parenCountStack.removeAt(parenCountStack.size()-1);\r
- string.setLength(0);\r
- stringStart=yychar;\r
- yybegin(stateStack.removeAt(stateStack.size()-1));\r
- return sym(SCLTerminals.CONTINUE_STRING);\r
- }\r
- else\r
+ { --parenCount;
+ if(parenCount == 0 && !parenCountStack.isEmpty()) {
+ parenCount = parenCountStack.removeAt(parenCountStack.size()-1);
+ string.setLength(0);
+ stringStart=yychar;
+ yybegin(stateStack.removeAt(stateStack.size()-1));
+ return sym(SCLTerminals.CONTINUE_STRING);
+ }
+ else
return sym(SCLTerminals.RPAREN);\r
}\r
- case 102: break;\r
+ case 104: break;\r
case 11: \r
{ return new Token(SCLTerminals.EOL, yychar, yychar+yylength(), "");\r
}\r
- case 103: break;\r
+ case 105: break;\r
case 12: \r
{ return sym(SCLTerminals.LESS, "<");\r
}\r
- case 104: break;\r
+ case 106: break;\r
case 13: \r
{ return sym(SCLTerminals.GREATER, ">");\r
}\r
- case 105: break;\r
+ case 107: break;\r
case 14: \r
{ return sym(SCLTerminals.MINUS, "-");\r
}\r
- case 106: break;\r
+ case 108: break;\r
case 15: \r
{ \r
}\r
- case 107: break;\r
+ case 109: break;\r
case 16: \r
{ throw new SCLSyntaxErrorException(Locations.location(yychar, yychar+1), "Character does not conform to UTF-8 encoding.");\r
}\r
- case 108: break;\r
+ case 110: break;\r
case 17: \r
{ return sym(SCLTerminals.LAMBDA);\r
}\r
- case 109: break;\r
+ case 111: break;\r
case 18: \r
{ return sym(SCLTerminals.LBRACE);\r
}\r
- case 110: break;\r
+ case 112: break;\r
case 19: \r
{ return sym(SCLTerminals.RBRACE);\r
}\r
- case 111: break;\r
+ case 113: break;\r
case 20: \r
{ return sym(SCLTerminals.LBRACKET);\r
}\r
- case 112: break;\r
+ case 114: break;\r
case 21: \r
{ return sym(SCLTerminals.RBRACKET);\r
}\r
- case 113: break;\r
+ case 115: break;\r
case 22: \r
{ return sym(SCLTerminals.EQUALS);\r
}\r
- case 114: break;\r
+ case 116: break;\r
case 23: \r
{ return sym(SCLTerminals.COLON);\r
}\r
- case 115: break;\r
+ case 117: break;\r
case 24: \r
{ return sym(SCLTerminals.SEMICOLON);\r
}\r
- case 116: break;\r
+ case 118: break;\r
case 25: \r
{ return sym(SCLTerminals.BAR);\r
}\r
- case 117: break;\r
+ case 119: break;\r
case 26: \r
{ string.setLength(0); stringStart=yychar; yybegin(STRING); return sym(SCLTerminals.BEGIN_STRING);\r
}\r
- case 118: break;\r
+ case 120: break;\r
case 27: \r
{ return sym(SCLTerminals.BLANK);\r
}\r
- case 119: break;\r
+ case 121: break;\r
case 28: \r
{ throw new SCLSyntaxErrorException(Locations.location(yychar, yychar+1), "Tabulator is not allowed except inside string literals.");\r
}\r
- case 120: break;\r
+ case 122: break;\r
case 29: \r
{ string.append( yytext() );\r
}\r
- case 121: break;\r
+ case 123: break;\r
case 30: \r
{ throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Unclosed string literal.");\r
}\r
- case 122: break;\r
+ case 124: break;\r
case 31: \r
- { yybegin(YYINITIAL); \r
+ { yybegin(YYINITIAL);
return new Token(SCLTerminals.END_STRING, stringStart, yychar+1, string.toString());\r
}\r
- case 123: break;\r
+ case 125: break;\r
case 32: \r
{ string.append('\n');\r
}\r
- case 124: break;\r
+ case 126: break;\r
case 33: \r
{ return sym(SCLTerminals.DOTDOT, ".");\r
}\r
- case 125: break;\r
+ case 127: break;\r
case 34: \r
{ return sym(SCLTerminals.SEPARATED_DOT, ".");\r
}\r
- case 126: break;\r
+ case 128: break;\r
case 35: \r
{ return sym(SCLTerminals.ANNOTATION_ID);\r
}\r
- case 127: break;\r
+ case 129: break;\r
case 36: \r
{ return sym(SCLTerminals.BINDS);\r
}\r
- case 128: break;\r
+ case 130: break;\r
case 37: \r
{ return sym(SCLTerminals.ARROW);\r
}\r
- case 129: break;\r
+ case 131: break;\r
case 38: \r
{ return sym(SCLTerminals.COMMENT);\r
}\r
- case 130: break;\r
+ case 132: break;\r
case 39: \r
{ return sym(SCLTerminals.AS);\r
}\r
- case 131: break;\r
+ case 133: break;\r
case 40: \r
{ return sym(SCLTerminals.IF);\r
}\r
- case 132: break;\r
+ case 134: break;\r
case 41: \r
{ return sym(SCLTerminals.IN);\r
}\r
- case 133: break;\r
+ case 135: break;\r
case 42: \r
{ return sym(options.supportEq ? SCLTerminals.EQ : SCLTerminals.ID);\r
}\r
- case 134: break;\r
+ case 136: break;\r
case 43: \r
{ return sym(SCLTerminals.BY);\r
}\r
- case 135: break;\r
+ case 137: break;\r
case 44: \r
{ return sym(SCLTerminals.DO);\r
}\r
- case 136: break;\r
+ case 138: break;\r
case 45: \r
{ return sym(SCLTerminals.IMPLIES);\r
}\r
- case 137: break;\r
+ case 139: break;\r
case 46: \r
{ return sym(SCLTerminals.FOLLOWS);\r
}\r
- case 138: break;\r
+ case 140: break;\r
case 47: \r
{ return sym(SCLTerminals.HASTYPE);\r
}\r
- case 139: break;\r
+ case 141: break;\r
case 48: \r
{ throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Illegal string escape character.");\r
}\r
- case 140: break;\r
+ case 142: break;\r
case 49: \r
{ string.append(yytext().substring(1));\r
}\r
- case 141: break;\r
+ case 143: break;\r
case 50: \r
- { parenCountStack.add(parenCount);\r
- parenCount = 1;\r
- stateStack.add(STRING);\r
- yybegin(YYINITIAL); \r
+ { parenCountStack.add(parenCount);
+ parenCount = 1;
+ stateStack.add(STRING);
+ yybegin(YYINITIAL);
return new Token(SCLTerminals.SUSPEND_STRING, stringStart, yychar+1, string.toString());\r
}\r
- case 142: break;\r
+ case 144: break;\r
case 51: \r
{ string.append('\r');\r
}\r
- case 143: break;\r
+ case 145: break;\r
case 52: \r
{ string.append('\t');\r
}\r
- case 144: break;\r
+ case 146: break;\r
case 53: \r
- { parenCountStack.add(parenCount);\r
- parenCount = 1;\r
- stateStack.add(LONG_STRING);\r
- yybegin(YYINITIAL); \r
+ { parenCountStack.add(parenCount);
+ parenCount = 1;
+ stateStack.add(LONG_STRING);
+ yybegin(YYINITIAL);
return new Token(SCLTerminals.SUSPEND_STRING, stringStart, yychar+1, string.toString());\r
}\r
- case 145: break;\r
+ case 147: break;\r
case 54: \r
{ return sym(SCLTerminals.FLOAT);\r
}\r
- case 146: break;\r
+ case 148: break;\r
case 55: \r
{ return sym(SCLTerminals.CHAR);\r
}\r
- case 147: break;\r
+ case 149: break;\r
case 56: \r
- { String text = yytext();\r
+ { String text = yytext();
return sym(SCLTerminals.ID, text.substring(1, text.length()-1));\r
}\r
- case 148: break;\r
+ case 150: break;\r
case 57: \r
- { String text = yytext();\r
+ { String text = yytext();
return sym(SCLTerminals.SYMBOL, text.substring(1, text.length()-1));\r
}\r
- case 149: break;\r
+ case 151: break;\r
case 58: \r
{ return sym(SCLTerminals.QUERY_OP);\r
}\r
- case 150: break;\r
+ case 152: break;\r
case 59: \r
{ return sym(SCLTerminals.LET);\r
}\r
- case 151: break;\r
+ case 153: break;\r
case 60: \r
{ return sym(SCLTerminals.MDO);\r
}\r
- case 152: break;\r
+ case 154: break;\r
case 61: \r
{ string.setLength(0); stringStart=yychar; yybegin(LONG_STRING); return sym(SCLTerminals.BEGIN_STRING);\r
}\r
- case 153: break;\r
+ case 155: break;\r
case 62: \r
- { yybegin(YYINITIAL); \r
+ { yybegin(YYINITIAL);
return new Token(SCLTerminals.END_STRING, stringStart, yychar+3, string.toString());\r
}\r
- case 154: break;\r
+ case 156: break;\r
case 63: \r
{ return sym(SCLTerminals.RULE);\r
}\r
- case 155: break;\r
+ case 157: break;\r
case 64: \r
{ return sym(SCLTerminals.THEN);\r
}\r
- case 156: break;\r
+ case 158: break;\r
case 65: \r
{ return sym(SCLTerminals.TYPE);\r
}\r
- case 157: break;\r
+ case 159: break;\r
case 66: \r
{ return sym(SCLTerminals.ELSE);\r
}\r
- case 158: break;\r
+ case 160: break;\r
case 67: \r
{ return sym(SCLTerminals.WITH);\r
}\r
- case 159: break;\r
+ case 161: break;\r
case 68: \r
{ return sym(SCLTerminals.WHEN);\r
}\r
- case 160: break;\r
+ case 162: break;\r
case 69: \r
{ return sym(SCLTerminals.DATA);\r
}\r
- case 161: break;\r
+ case 163: break;\r
case 70: \r
{ return sym(SCLTerminals.INFIX);\r
}\r
- case 162: break;\r
+ case 164: break;\r
case 71: \r
{ return sym(SCLTerminals.WHERE);\r
}\r
- case 163: break;\r
+ case 165: break;\r
case 72: \r
{ return sym(SCLTerminals.CLASS);\r
}\r
- case 164: break;\r
+ case 166: break;\r
case 73: \r
{ return sym(SCLTerminals.MATCH);\r
}\r
- case 165: break;\r
+ case 167: break;\r
case 74: \r
- { return sym(SCLTerminals.FORALL);\r
+ { return sym(SCLTerminals.LAMBDA_MATCH);\r
}\r
- case 166: break;\r
+ case 168: break;\r
case 75: \r
- { return sym(SCLTerminals.INFIXR);\r
+ { return sym(SCLTerminals.FORALL);\r
}\r
- case 167: break;\r
+ case 169: break;\r
case 76: \r
- { return sym(SCLTerminals.INFIXL);\r
+ { return sym(SCLTerminals.INFIXR);\r
}\r
- case 168: break;\r
+ case 170: break;\r
case 77: \r
- { return sym(SCLTerminals.IMPORT);\r
+ { return sym(SCLTerminals.INFIXL);\r
}\r
- case 169: break;\r
+ case 171: break;\r
case 78: \r
- { return sym(SCLTerminals.HIDING);\r
+ { return sym(SCLTerminals.IMPORT);\r
}\r
- case 170: break;\r
+ case 172: break;\r
case 79: \r
- { return sym(SCLTerminals.EFFECT);\r
+ { return sym(SCLTerminals.HIDING);\r
}\r
- case 171: break;\r
+ case 173: break;\r
case 80: \r
- { return sym(SCLTerminals.SELECT);\r
+ { return sym(SCLTerminals.EFFECT);\r
}\r
- case 172: break;\r
+ case 174: break;\r
case 81: \r
- { string.append((char)Integer.parseInt(yytext().substring(2), 16));\r
+ { return sym(SCLTerminals.SELECT);\r
}\r
- case 173: break;\r
+ case 175: break;\r
case 82: \r
- { return sym(SCLTerminals.INCLUDE);\r
+ { string.append((char)Integer.parseInt(yytext().substring(2), 16));\r
}\r
- case 174: break;\r
+ case 176: break;\r
case 83: \r
- { return sym(SCLTerminals.ENFORCE);\r
+ { return sym(SCLTerminals.INCLUDE);\r
}\r
- case 175: break;\r
+ case 177: break;\r
case 84: \r
- { return sym(SCLTerminals.EXTENDS);\r
+ { return sym(SCLTerminals.ENFORCE);\r
}\r
- case 176: break;\r
+ case 178: break;\r
case 85: \r
- { return sym(SCLTerminals.INSTANCE);\r
+ { return sym(SCLTerminals.EXTENDS);\r
}\r
- case 177: break;\r
+ case 179: break;\r
case 86: \r
- { return sym(SCLTerminals.DERIVING);\r
+ { return sym(SCLTerminals.INSTANCE);\r
}\r
- case 178: break;\r
+ case 180: break;\r
case 87: \r
- { return sym(SCLTerminals.IMPORTJAVA);\r
+ { return sym(SCLTerminals.DERIVING);\r
}\r
- case 179: break;\r
+ case 181: break;\r
case 88: \r
- { return sym(SCLTerminals.SELECT_FIRST);\r
+ { return sym(SCLTerminals.IMPORTJAVA);\r
}\r
- case 180: break;\r
+ case 182: break;\r
case 89: \r
- { return sym(SCLTerminals.ABSTRACT_RULE);\r
+ { return sym(SCLTerminals.CONSTRAINT);\r
}\r
- case 181: break;\r
+ case 183: break;\r
case 90: \r
- { return sym(SCLTerminals.TRANSFORMATION);\r
+ { return sym(SCLTerminals.SELECT_FIRST);\r
}\r
- case 182: break;\r
+ case 184: break;\r
case 91: \r
- { return sym(SCLTerminals.SELECT_DISTINCT);\r
+ { return sym(SCLTerminals.ABSTRACT_RULE);\r
}\r
- case 183: break;\r
+ case 185: break;\r
case 92: \r
+ { return sym(SCLTerminals.TRANSFORMATION);\r
+ }\r
+ case 186: break;\r
+ case 93: \r
+ { return sym(SCLTerminals.SELECT_DISTINCT);\r
+ }\r
+ case 187: break;\r
+ case 94: \r
{ return sym(SCLTerminals.MAPPING_RELATION);\r
}\r
- case 184: break;\r
+ case 188: break;\r
default:\r
zzScanError(ZZ_NO_MATCH);\r
}\r
public static final boolean TRACE = false;\r
\r
private static final int INITIAL_CAPACITY = 16;\r
- private static final int STATE_COUNT = 324;\r
- private static final int TERMINAL_COUNT = 79;\r
- private static final int NONTERMINAL_COUNT = 49;\r
- private static final int PRODUCT_COUNT = 126;\r
+ private static final int STATE_COUNT = 344;\r
+ private static final int TERMINAL_COUNT = 82;\r
+ private static final int NONTERMINAL_COUNT = 51;\r
+ private static final int PRODUCT_COUNT = 132;\r
\r
private static final int[] ACTION_ROW_ID = new int[STATE_COUNT];\r
private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT];\r
- private static final short[] ACTION_TABLE = new short[5508];\r
- private static final int[] ERROR_TABLE = new int[800];\r
+ private static final short[] ACTION_TABLE = new short[6120];\r
+ private static final int[] ERROR_TABLE = new int[882];\r
private static final int[] GOTO_ROW_ID = new int[STATE_COUNT];\r
private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT];\r
- private static final short[] GOTO_TABLE = new short[1620];\r
+ private static final short[] GOTO_TABLE = new short[1829];\r
private static final int[] PRODUCT_LHS = new int[PRODUCT_COUNT];\r
\r
private static final short STATE_MASK = (short)0x0fff;\r
"SEPARATED_DOT",\r
"ESCAPED_ID",\r
"LAMBDA",\r
+ "LAMBDA_MATCH",\r
"LET",\r
"IF",\r
"MATCH",\r
"SUSPEND_STRING",\r
"CONTINUE_STRING",\r
"BINDS",\r
+ "IMPLIES",\r
+ "THEN_AFTER_WHEN",\r
+ "CONSTRAINT",\r
"BY",\r
"QUERY_OP",\r
- "IMPLIES",\r
"FORALL",\r
"COMMENT",\r
"EOL",\r
"symbolWithoutMinus",\r
"listQualifier",\r
"field",\r
+ "chrQuery",\r
+ "verboseChrQuery",\r
"caseRhs",\r
"guardedExpArrow",\r
"equation",\r
return parse(0);\r
}\r
public Object parseCommands() {\r
- return parse(309);\r
+ return parse(329);\r
}\r
public Object parseImport() {\r
- return parse(316);\r
+ return parse(336);\r
}\r
public Object parseType() {\r
- return parse(318);\r
+ return parse(338);\r
}\r
public Object parseExp() {\r
- return parse(320);\r
+ return parse(340);\r
}\r
public Object parseEquationBlock() {\r
- return parse(322);\r
+ return parse(342);\r
}\r
\r
\r
case 29:\r
return reduceRuleStatement();\r
case 30:\r
- return reduceDeclarations();\r
+ return reduceCHRStatement();\r
case 31:\r
- return reduceVarId();\r
+ return reduceVerboseCHRStatement();\r
case 32:\r
- return reduceEscapedSymbol();\r
+ return reduceConstraintStatement();\r
case 33:\r
- return reduceTupleConstructor();\r
+ return reduceDeclarations();\r
case 34:\r
- return reduceBinary();\r
+ return reduceVarId();\r
case 35:\r
- return reduceSimpleRhs();\r
+ return reduceEscapedSymbol();\r
case 36:\r
- return reduceGuardedRhs();\r
+ return reduceTupleConstructor();\r
case 37:\r
- return reduceConstructor();\r
+ return reduceBinary();\r
case 38:\r
- return reduceRecordConstructor();\r
+ return reduceSimpleRhs();\r
case 39:\r
- return reduceContext();\r
+ return reduceGuardedRhs();\r
case 40:\r
- return reduceFundeps();\r
+ return reduceConstructor();\r
case 41:\r
- return reduceTypeVar();\r
+ return reduceRecordConstructor();\r
case 42:\r
- return reduceTupleType();\r
+ return reduceContext();\r
case 43:\r
- return reduceListType();\r
+ return reduceFundeps();\r
case 44:\r
- return reduceListTypeConstructor();\r
+ return reduceTypeVar();\r
case 45:\r
- return reduceTupleTypeConstructor();\r
+ return reduceTupleType();\r
case 46:\r
- return reduceLambda();\r
+ return reduceListType();\r
case 47:\r
- return reduceLet();\r
+ return reduceListTypeConstructor();\r
case 48:\r
- return reduceIf();\r
+ return reduceTupleTypeConstructor();\r
case 49:\r
- return reduceMatch();\r
+ return reduceLambda();\r
case 50:\r
- return reduceDo();\r
+ return reduceLambdaMatch();\r
case 51:\r
- return reduceSelect();\r
+ return reduceLet();\r
case 52:\r
- return reduceEnforce();\r
+ return reduceIf();\r
case 53:\r
- return reduceWhen();\r
+ return reduceMatch();\r
case 54:\r
- return reduceVar();\r
+ return reduceDo();\r
case 55:\r
- return reduceHashedId();\r
+ return reduceSelect();\r
case 56:\r
- return reduceBlank();\r
+ return reduceEnforce();\r
case 57:\r
- return reduceInteger();\r
+ return reduceVar();\r
case 58:\r
- return reduceFloat();\r
+ return reduceHashedId();\r
case 59:\r
- return reduceString();\r
+ return reduceBlank();\r
case 60:\r
- return reduceChar();\r
+ return reduceInteger();\r
case 61:\r
- return reduceTuple();\r
+ return reduceFloat();\r
case 62:\r
- return reduceRightSection();\r
+ return reduceString();\r
case 63:\r
- return reduceLeftSection();\r
+ return reduceChar();\r
case 64:\r
- return reduceListLiteral();\r
+ return reduceTuple();\r
case 65:\r
- return reduceRange();\r
+ return reduceViewPattern();\r
case 66:\r
- return reduceListComprehension();\r
+ return reduceRightSection();\r
case 67:\r
- return reduceAs();\r
+ return reduceLeftSection();\r
case 68:\r
- return reduceRecord();\r
+ return reduceListLiteral();\r
case 69:\r
- return reduceTransformation();\r
+ return reduceRange();\r
case 70:\r
- return reduceEq();\r
+ return reduceListComprehension();\r
case 71:\r
- return reduceRuleDeclarations();\r
+ return reduceAs();\r
case 72:\r
- return reduceImportShowing();\r
+ return reduceRecord();\r
case 73:\r
- return reduceImportHiding();\r
+ return reduceTransformation();\r
case 74:\r
- return reduceImportValueItem();\r
+ return reduceEq();\r
case 75:\r
- return reduceFieldDescription();\r
+ return reduceRuleDeclarations();\r
case 76:\r
- return reduceStatements();\r
+ return reduceImportShowing();\r
case 77:\r
- return reduceGuardedExpEq();\r
+ return reduceImportHiding();\r
case 78:\r
- return reduceFundep();\r
+ return reduceImportValueItem();\r
case 79:\r
- return reduceQueryRuleDeclaration();\r
+ return reduceFieldDescription();\r
case 80:\r
- return reduceAnnotation();\r
+ return reduceStatements();\r
case 81:\r
- return reduceGuardQuery();\r
+ return reduceGuardedExpEq();\r
case 82:\r
- return reduceEqualsQuery();\r
+ return reduceFundep();\r
case 83:\r
- return reduceBindQuery();\r
+ return reduceQueryRuleDeclaration();\r
case 84:\r
- return reduceCompositeQuery();\r
+ return reduceAnnotation();\r
case 85:\r
- return reduceQueryBlock();\r
+ return reduceGuardQuery();\r
case 86:\r
- return reduceApply();\r
+ return reduceEqualsQuery();\r
case 87:\r
- return reduceSymbol();\r
+ return reduceBindQuery();\r
case 88:\r
- return reduceEscapedId();\r
+ return reduceCompositeQuery();\r
case 89:\r
- return reduceMinus();\r
+ return reduceQueryBlock();\r
case 90:\r
- return reduceLess();\r
+ return reduceApply();\r
case 91:\r
- return reduceGreater();\r
+ return reduceSymbol();\r
case 92:\r
- return reduceDot();\r
+ return reduceEscapedId();\r
case 93:\r
- return reduceFieldAccess();\r
+ return reduceMinus();\r
case 94:\r
- return reduceIdAccessor();\r
+ return reduceLess();\r
case 95:\r
- return reduceStringAccessor();\r
+ return reduceGreater();\r
case 96:\r
- return reduceExpAccessor();\r
+ return reduceDot();\r
case 97:\r
- return reduceCase();\r
+ return reduceFieldAccess();\r
case 98:\r
- return reduceStringLiteral();\r
+ return reduceIdAccessor();\r
case 99:\r
- return reduceSymbol();\r
+ return reduceStringAccessor();\r
case 100:\r
- return reduceEscapedId();\r
+ return reduceExpAccessor();\r
case 101:\r
- return reduceLess();\r
+ return reduceCase();\r
case 102:\r
- return reduceGreater();\r
+ return reduceStringLiteral();\r
case 103:\r
- return reduceDot();\r
+ return reduceSymbol();\r
case 104:\r
- return reduceGuardQualifier();\r
+ return reduceEscapedId();\r
case 105:\r
- return reduceLetQualifier();\r
+ return reduceLess();\r
case 106:\r
- return reduceBindQualifier();\r
+ return reduceGreater();\r
case 107:\r
- return reduceThenQualifier();\r
+ return reduceDot();\r
case 108:\r
- return reduceField();\r
+ return reduceGuardQualifier();\r
case 109:\r
- return reduceFieldShorthand();\r
+ return reduceLetQualifier();\r
case 110:\r
- return reduceSimpleCaseRhs();\r
+ return reduceBindQualifier();\r
case 111:\r
- return reduceGuardedCaseRhs();\r
+ return reduceThenQualifier();\r
case 112:\r
- return reduceGuardedExpArrow();\r
+ return reduceField();\r
case 113:\r
- return reduceGuardEquation();\r
+ return reduceFieldShorthand();\r
case 114:\r
- return reduceBasicEquation();\r
+ return reduceCHRQuery();\r
case 115:\r
- return reduceEffect();\r
+ return reduceVerboseCHRQuery();\r
case 116:\r
- return reduceJustEtype();\r
+ return reduceSimpleCaseRhs();\r
case 117:\r
- return reduceForAll();\r
+ return reduceGuardedCaseRhs();\r
case 118:\r
- return reduceApplyType();\r
+ return reduceGuardedExpArrow();\r
case 119:\r
+ return reduceGuardEquation();\r
+ case 120:\r
+ return reduceBasicEquation();\r
+ case 121:\r
+ return reduceEffect();\r
+ case 122:\r
+ return reduceJustEtype();\r
+ case 123:\r
+ return reduceForAll();\r
+ case 124:\r
+ return reduceApplyType();\r
+ case 125:\r
return reduceDummy1();\r
\r
default:\r
* statement ::= exp FOLLOWS queryBlock\r
*/\r
protected abstract Object reduceRuleStatement();\r
+ /**\r
+ * statement ::= chrQuery IMPLIES chrQuery\r
+ */\r
+ protected abstract Object reduceCHRStatement();\r
+ /**\r
+ * statement ::= WHEN verboseChrQuery THEN_AFTER_WHEN verboseChrQuery\r
+ */\r
+ protected abstract Object reduceVerboseCHRStatement();\r
+ /**\r
+ * statement ::= CONSTRAINT ID atype*\r
+ */\r
+ protected abstract Object reduceConstraintStatement();\r
/**\r
* declarations ::= LBRACE (declaration (SEMICOLON (declaration SEMICOLON)* declaration)?)? RBRACE\r
*/\r
* aexp ::= LAMBDA aexp aexp* ARROW exp\r
*/\r
protected abstract Object reduceLambda();\r
+ /**\r
+ * aexp ::= LAMBDA_MATCH LBRACE case (SEMICOLON case)* RBRACE\r
+ */\r
+ protected abstract Object reduceLambdaMatch();\r
/**\r
* aexp ::= LET statements IN exp\r
*/\r
protected abstract Object reduceLet();\r
/**\r
- * aexp ::= IF exp THEN exp ELSE exp\r
+ * aexp ::= IF exp THEN exp (ELSE exp)?\r
*/\r
protected abstract Object reduceIf();\r
/**\r
* aexp ::= ENFORCE queryBlock\r
*/\r
protected abstract Object reduceEnforce();\r
- /**\r
- * aexp ::= WHEN queryBlock SEMICOLON exp\r
- */\r
- protected abstract Object reduceWhen();\r
/**\r
* aexp ::= var\r
*/\r
* aexp ::= LPAREN (exp (COMMA (exp COMMA)* exp)?)? RPAREN\r
*/\r
protected abstract Object reduceTuple();\r
+ /**\r
+ * aexp ::= LPAREN exp ARROW exp RPAREN\r
+ */\r
+ protected abstract Object reduceViewPattern();\r
/**\r
* aexp ::= LPAREN symbolWithoutMinus lexp RPAREN\r
*/\r
* field ::= ID\r
*/\r
protected abstract Object reduceFieldShorthand();\r
+ /**\r
+ * chrQuery ::= (listQualifier COMMA)* listQualifier\r
+ */\r
+ protected abstract Object reduceCHRQuery();\r
+ /**\r
+ * verboseChrQuery ::= LBRACE listQualifier (SEMICOLON listQualifier)* RBRACE\r
+ */\r
+ protected abstract Object reduceVerboseCHRQuery();\r
/**\r
* caseRhs ::= ARROW exp (WHERE statements)?\r
*/\r
import org.simantics.scl.compiler.elaboration.expressions.ETypeAnnotation;
import org.simantics.scl.compiler.elaboration.expressions.EVar;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
-import org.simantics.scl.compiler.elaboration.expressions.EWhen;
+import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.GuardedExpression;
import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup;
import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor;
import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
);
}
+ @SuppressWarnings("unchecked")
@Override
protected Object reduceClassDefinition() {
int i=1;
return fundeps;
}
+ @SuppressWarnings("unchecked")
@Override
protected Object reduceInstanceDefinition() {
int i=1;
declarations);
}
+ @SuppressWarnings("unchecked")
@Override
protected Object reduceDerivingInstanceDefinition() {
int i=2;
return get(0);
}
+ @SuppressWarnings("unchecked")
@Override
protected Object reduceImportJava() {
return new DImportJavaAst(((Token)get(2)).text, (ArrayList<DeclarationAst>)get(4));
case_.setLhs(Locations.combine(patterns[0].location, patterns[patterns.length-1].location));
return new ELambda(case_);
}
+
+ @Override
+ protected Object reduceLambdaMatch() {
+ Case[] cases = new Case[length()/2-1];
+ for(int i=0;i<cases.length;++i)
+ cases[i] = (Case)get(i*2+2);
+ return new ELambda(cases);
+ }
@Override
protected Object reduceLet() {
return new EIf(
(Expression)get(1),
(Expression)get(3),
- (Expression)get(5));
+ length() == 6 ? (Expression)get(5) : null);
}
@Override
protected Object reduceSelect() {
return new ESelect(((Token)get(0)).id, (Expression)get(1), new QConjunction((Query[])get(3)));
}
-
- @Override
- protected Object reduceWhen() {
- return new EWhen(
- new QConjunction((Query[])get(1)),
- (Expression)get(3));
- }
-
+
@Override
protected Object reduceEnforce() {
return new EEnforce(new QConjunction((Query[])get(1)));
throw new UnsupportedOperationException();
}
+ @SuppressWarnings("unchecked")
@Override
protected void postReduce(Object reduced) {
if(!(reduced instanceof Symbol))
Symbol sym = (Symbol)reduced;
if(sym.location != Locations.NO_LOCATION || length() == 0)
return;
+ Object first = get(0);
+ if(!(first instanceof Symbol)) {
+ if(first instanceof List) {
+ List<Object> ll = (List<Object>)first;
+ first = ll.get(0);
+ }
+ else {
+ Object[] ll = (Object[])first;
+ if(ll.length > 0)
+ first = ll[0];
+ else
+ first = get(1);
+ }
+ }
Object last = get(length()-1);
if(!(last instanceof Symbol)) {
if(last instanceof List) {
last = get(length()-2);
}
}
- sym.location = (((Symbol)get(0)).location & 0xffffffff00000000L)
+ sym.location = (((Symbol)first).location & 0xffffffff00000000L)
| (((Symbol)last).location & 0xffffffffL);
/*for(int i=0;i<length();++i) {
Object obj = get(i);
private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ @SuppressWarnings("unchecked")
@Override
protected Object reduceRuleDefinition() {
String[] extendsNames = EMPTY_STRING_ARRAY;
);
}
+ @SuppressWarnings("unchecked")
@Override
protected Object reduceRelationDefinition() {
return new DRelationAst((Expression)get(0),
protected Object reduceBasicEquation() {
return new EqBasic((Expression)get(0), (Expression)get(2));
}
+
+ @Override
+ protected Object reduceViewPattern() {
+ return new EViewPattern((Expression)get(1), (Expression)get(3));
+ }
+
+ @Override
+ protected Object reduceCHRStatement() {
+ return new CHRStatement((ListQualifier[])get(0), (ListQualifier[])get(2));
+ }
+
+ @Override
+ protected Object reduceConstraintStatement() {
+ TypeAst[] parameterTypes = new TypeAst[length()-2];
+ for(int i=0;i<parameterTypes.length;++i)
+ parameterTypes[i] = (TypeAst)get(2+i);
+ return new ConstraintStatement((Token)get(1), parameterTypes);
+ }
+
+ @Override
+ protected Object reduceCHRQuery() {
+ ListQualifier[] query = new ListQualifier[(length()+1)/2];
+ for(int i=0;i<query.length;++i)
+ query[i] = (ListQualifier)get(i*2);
+ return query;
+ }
+
+ /*
+ @Override
+ protected Object reduceWhen() {
+ return new EWhen(
+ new QConjunction((Query[])get(1)),
+ (Expression)get(3));
+ }*/
+
+ @Override
+ protected Object reduceVerboseCHRQuery() {
+ ListQualifier[] query = new ListQualifier[(length()-1)/2];
+ for(int i=0;i<query.length;++i)
+ query[i] = (ListQualifier)get(i*2+1);
+ return query;
+ }
+
+ @Override
+ protected Object reduceVerboseCHRStatement() {
+ return new CHRStatement((ListQualifier[])get(1), (ListQualifier[])get(3));
+ }
+
}
INDENTABLE.add(SCLTerminals.WHEN);
INDENTABLE.add(SCLTerminals.FOLLOWS);
INDENTABLE.add(SCLTerminals.EQ);
+ INDENTABLE.add(SCLTerminals.LAMBDA_MATCH);
+ INDENTABLE.add(SCLTerminals.THEN_AFTER_WHEN);
NO_SEMICOLON_BEFORE.add(SCLTerminals.EOF);
NO_SEMICOLON_BEFORE.add(SCLTerminals.SYMBOL);
NO_SEMICOLON_BEFORE.add(SCLTerminals.THEN);
- NO_SEMICOLON_BEFORE.add(SCLTerminals.ELSE);
NO_SEMICOLON_BEFORE.add(SCLTerminals.IN);
NO_SEMICOLON_BEFORE.add(SCLTerminals.RBRACE);
NO_SEMICOLON_BEFORE.add(SCLTerminals.RBRACKET);
NO_SEMICOLON_BEFORE.add(SCLTerminals.RPAREN);
+ NO_SEMICOLON_BEFORE.add(SCLTerminals.SEMICOLON);
NO_SEMICOLON_AFTER.add(SCLTerminals.EOF);
NO_SEMICOLON_AFTER.add(SCLTerminals.SYMBOL);
Token[] queue = new Token[16];
int queuePos=0, queueSize=0;
TIntArrayList indentations = new TIntArrayList();
+ TIntArrayList indentationTokens = new TIntArrayList();
Token curToken = null;
int lineStart = 0;
boolean firstTokenOfLine = true;
{
indentations.add(0);
+ indentationTokens.add(SCLTerminals.EOF);
}
public SCLPostLexer(SCLLexer lexer) {
int symbolIndentation = symbolStart-lineStart;
//System.out.println("symbolIndentation = " + symbolIndentation);
indentations.add(symbolIndentation);
+ indentationTokens.add(prevTokenId);
firstTokenOfLine = false;
}
else if(firstTokenOfLine) {
//System.out.println("level = " + level);
if(indentations.get(indentations.size()-1) >= level) {
while(indentations.get(indentations.size()-1) > level) {
+ indentationTokens.removeAt(indentations.size()-1);
indentations.removeAt(indentations.size()-1);
int loc = Locations.endOf(prevToken.location);
push(new Token(SCLTerminals.RBRACE, loc, loc, "implicit }"));
}
- if(indentations.get(indentations.size()-1) == level)
+ if(indentations.get(indentations.size()-1) == level && symbolId != SCLTerminals.ELSE)
push(new Token(SCLTerminals.SEMICOLON, symbolStart, symbolStart, "implicit ;"));
}
}
case SCLTerminals.LPAREN:
case SCLTerminals.LBRACKET:
case SCLTerminals.IF:
+ case SCLTerminals.WHEN:
case SCLTerminals.LET:
indentations.add(-1);
+ indentationTokens.add(symbolId);
push(symbol);
return;
+ case SCLTerminals.THEN:
+ /*for(int tt : indentationTokens.toArray())
+ System.out.print(SCLParser.TERMINAL_NAMES[tt] + " ");
+ System.out.println();*/
+ if(prevTokenId == SCLTerminals.COMMA) {
+ // for list comprehension syntax
+ push(symbol);
+ break;
+ }
case SCLTerminals.RBRACE:
case SCLTerminals.RPAREN:
case SCLTerminals.RBRACKET:
- case SCLTerminals.ELSE:
+ //case SCLTerminals.ELSE:
case SCLTerminals.IN:
- while(!indentations.isEmpty() && indentations.removeAt(indentations.size()-1) >= 0) {
- int loc = Locations.endOf(prevToken.location);
- push(new Token(SCLTerminals.RBRACE, loc, loc, "implicit }"));
+ int removedToken = SCLTerminals.EOF;
+ while(!indentations.isEmpty()) {
+ removedToken = indentationTokens.removeAt(indentations.size()-1);
+ //System.out.println(" removed " + SCLParser.TERMINAL_NAMES[removedToken]);
+ if(indentations.removeAt(indentations.size()-1) < 0)
+ break;
+ long loc = prevToken != null ? Locations.location(Locations.endOf(prevToken.location), Locations.endOf(prevToken.location)) : symbol.location;
+ push(new Token(SCLTerminals.RBRACE, loc, "implicit }"));
}
if(indentations.isEmpty())
throw error(symbolStart, symbolEnd, "No corresponding opening parenthesis for '" + symbol.text + "'.");
+ if(symbolId == SCLTerminals.THEN && removedToken == SCLTerminals.WHEN)
+ curToken = symbol = new Token(SCLTerminals.THEN_AFTER_WHEN, symbol.location, symbol.text);
push(symbol);
- return;
- case SCLTerminals.THEN: // 'then' both closes and opens a block
- while(!indentations.isEmpty() && indentations.removeAt(indentations.size()-1) >= 0) {
- int loc = Locations.endOf(prevToken.location);
- push(new Token(SCLTerminals.RBRACE, loc, loc, "implicit }"));
- }
- if(indentations.isEmpty())
- throw error(symbolStart, symbolEnd, "No corresponding opening parenthesis for '" + symbol.text + "'.");
- push(symbol);
- indentations.add(-1);
+ //if(symbolId == SCLTerminals.THEN)
+ // indentations.add(-1);
return;
case SCLTerminals.EOF:
while(indentations.size() > 1 && indentations.get(indentations.size()-1) >= 0) {
- int loc = Locations.endOf(prevToken.location);
- push(new Token(SCLTerminals.RBRACE, loc, loc, "implicit }"));
+ long loc = prevToken != null ? Locations.location(Locations.endOf(prevToken.location), Locations.endOf(prevToken.location)) : symbol.location;
+ push(new Token(SCLTerminals.RBRACE, loc, "implicit }"));
+ indentationTokens.removeAt(indentations.size()-1);
indentations.removeAt(indentations.size()-1);
}
if(indentations.size() > 1)
public static final int SEPARATED_DOT = 41;\r
public static final int ESCAPED_ID = 42;\r
public static final int LAMBDA = 43;\r
- public static final int LET = 44;\r
- public static final int IF = 45;\r
- public static final int MATCH = 46;\r
- public static final int DO = 47;\r
- public static final int MDO = 48;\r
- public static final int ENFORCE = 49;\r
- public static final int BLANK = 50;\r
- public static final int FLOAT = 51;\r
- public static final int LBRACKET = 52;\r
- public static final int ESCAPED_SYMBOL = 53;\r
- public static final int CHAR = 54;\r
- public static final int WHEN = 55;\r
- public static final int ATTACHED_HASH = 56;\r
- public static final int SELECT = 57;\r
- public static final int SELECT_FIRST = 58;\r
- public static final int SELECT_DISTINCT = 59;\r
- public static final int TRANSFORMATION = 60;\r
- public static final int EQ = 61;\r
- public static final int ATTACHED_DOT = 62;\r
- public static final int IN = 63;\r
- public static final int THEN = 64;\r
- public static final int ELSE = 65;\r
- public static final int RBRACKET = 66;\r
- public static final int DOTDOT = 67;\r
- public static final int AT = 68;\r
- public static final int SUSPEND_STRING = 69;\r
- public static final int CONTINUE_STRING = 70;\r
- public static final int BINDS = 71;\r
- public static final int BY = 72;\r
- public static final int QUERY_OP = 73;\r
- public static final int IMPLIES = 74;\r
- public static final int FORALL = 75;\r
- public static final int COMMENT = 76;\r
- public static final int EOL = 77;\r
- public static final int EOF = 78;\r
+ public static final int LAMBDA_MATCH = 44;\r
+ public static final int LET = 45;\r
+ public static final int IF = 46;\r
+ public static final int MATCH = 47;\r
+ public static final int DO = 48;\r
+ public static final int MDO = 49;\r
+ public static final int ENFORCE = 50;\r
+ public static final int BLANK = 51;\r
+ public static final int FLOAT = 52;\r
+ public static final int LBRACKET = 53;\r
+ public static final int ESCAPED_SYMBOL = 54;\r
+ public static final int CHAR = 55;\r
+ public static final int WHEN = 56;\r
+ public static final int ATTACHED_HASH = 57;\r
+ public static final int SELECT = 58;\r
+ public static final int SELECT_FIRST = 59;\r
+ public static final int SELECT_DISTINCT = 60;\r
+ public static final int TRANSFORMATION = 61;\r
+ public static final int EQ = 62;\r
+ public static final int ATTACHED_DOT = 63;\r
+ public static final int IN = 64;\r
+ public static final int THEN = 65;\r
+ public static final int ELSE = 66;\r
+ public static final int RBRACKET = 67;\r
+ public static final int DOTDOT = 68;\r
+ public static final int AT = 69;\r
+ public static final int SUSPEND_STRING = 70;\r
+ public static final int CONTINUE_STRING = 71;\r
+ public static final int BINDS = 72;\r
+ public static final int IMPLIES = 73;\r
+ public static final int THEN_AFTER_WHEN = 74;\r
+ public static final int CONSTRAINT = 75;\r
+ public static final int BY = 76;\r
+ public static final int QUERY_OP = 77;\r
+ public static final int FORALL = 78;\r
+ public static final int COMMENT = 79;\r
+ public static final int EOL = 80;\r
+ public static final int EOF = 81;\r
}\r
import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.environment.AmbiguousNameException;
import org.simantics.scl.compiler.environment.Environments;
import org.simantics.scl.compiler.internal.types.TypeElaborationContext;
public Type toType(TypeTranslationContext context, Kind expectedKind) {
if(function instanceof TVarAst) {
String name = ((TVarAst)function).name;
- TypeAlias alias;
+ TypeAlias alias = null;
try {
- alias = Environments.getTypeAlias(context.getEnvironment(), name);
+ TypeDescriptor tdesc = Environments.getTypeDescriptor(context.getEnvironment(), name);
+ if(tdesc instanceof TypeAlias)
+ alias = (TypeAlias)tdesc;
} catch (AmbiguousNameException e) {
context.getErrorLog().log(location, e.getMessage());
return Types.metaVar(Kinds.STAR);
import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.environment.AmbiguousNameException;
import org.simantics.scl.compiler.environment.Environments;
import org.simantics.scl.compiler.internal.types.TypeElaborationContext;
for(int i=1;i<name.length()-1;++i)
if(name.charAt(i) != ',') {
try {
- con = Environments.getTypeConstructorName(context.getEnvironment(), name.substring(1, name.length()-1));
+ con = Environments.getTypeDescriptorName(context.getEnvironment(), name.substring(1, name.length()-1));
} catch(AmbiguousNameException e) {
context.getErrorLog().log(location, e.getMessage());
return Types.metaVar(Kinds.STAR);
else if(Character.isLowerCase(c))
return context.resolveTypeVariable(location, name, expectedKind);
else {
- TypeAlias alias;
+ TypeDescriptor tdesc;
try {
- alias = Environments.getTypeAlias(context.getEnvironment(), name);
- } catch (AmbiguousNameException e1) {
- context.getErrorLog().log(location, e1.getMessage());
+ tdesc = Environments.getTypeDescriptor(context.getEnvironment(), name);
+ } catch (AmbiguousNameException e) {
+ context.getErrorLog().log(location, e.getMessage());
+ return Types.metaVar(Kinds.STAR);
+ }
+ if(tdesc == null) {
+ context.getErrorLog().log(location, "Didn't find type constructor " + name + ".");
return Types.metaVar(Kinds.STAR);
}
- if(alias != null) {
+ if(tdesc instanceof TypeAlias) {
+ TypeAlias alias = (TypeAlias)tdesc;
if(alias.getArity() > 0) {
context.getErrorLog().log(location, "The alias expects " +
alias.getArity() + " parameters, but none are given.");
}
return alias.body;
}
- try {
- con = Environments.getTypeConstructorName(context.getEnvironment(), name);
- } catch(AmbiguousNameException e) {
- context.getErrorLog().log(location, e.getMessage());
- return Types.metaVar(Kinds.STAR);
- }
- if(con == null) {
- context.getErrorLog().log(location, "Didn't find type constructor " + name + ".");
- return Types.metaVar(Kinds.STAR);
- }
+ con = tdesc.name;
}
}
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;
import org.simantics.scl.compiler.errors.Failable;
import org.simantics.scl.compiler.markdown.internal.ExtensionNodeHandler;
}
private void generateDataDocumentation(Node container, Module module, String name) {
- TypeConstructor typeConstructor = module.getTypeConstructor(name);
- if(typeConstructor == null) {
+ TypeDescriptor typeDescriptor = module.getTypeDescriptor(name);
+ if(typeDescriptor == null) {
StringBuilder error = new StringBuilder();
- error.append("Didn't find the type constructor '" + name + "'.");
- System.err.println(error);
+ error.append("Didn't find the type " + name + ".");
container.addChild(new CodeBlockNode(error));
return;
}
StringBuilder signature = new StringBuilder();
signature.append("<div class=\"code-doc-box\"><div class=\"code\">");
signature.append("data ");
- signature.append(typeConstructor.name.name);
- for(TVar p : typeConstructor.parameters) {
- signature.append(' ');
- p.toName(tuc, signature);
+ signature.append(typeDescriptor.name.name);
+ if(typeDescriptor instanceof TypeConstructor) {
+ for(TVar p : ((TypeConstructor)typeDescriptor).parameters) {
+ signature.append(' ');
+ p.toName(tuc, signature);
+ }
}
String moduleName = module.getName();
if(!moduleName.equals(documentationName)) {
signature.append("</div><div class=\"doc\">");
container.addChild(new HtmlNode(signature));
- if(typeConstructor.documentation != null) {
+ if(typeDescriptor.getDocumentation() != null) {
MarkdownParser parser = new MarkdownParser();
- container.addChild(parser.parseDocument(typeConstructor.documentation));
+ container.addChild(parser.parseDocument(typeDescriptor.getDocumentation()));
}
else
System.out.println(name);
- for(Constructor constructor : typeConstructor.constructors) {
- if(!documentedValues.add(constructor.name.name))
- System.err.println("Method '" + constructor.name.name + "' has already been documented in " + documentationName + ".");
- generateValueDocumentation(container, module, constructor.name.name, new TypeUnparsingContext(tuc));
+ if(typeDescriptor instanceof TypeConstructor) {
+ for(Constructor constructor : ((TypeConstructor)typeDescriptor).constructors) {
+ if(!documentedValues.add(constructor.name.name))
+ System.err.println("Method '" + constructor.name.name + "' has already been documented in " + documentationName + ".");
+ generateValueDocumentation(container, module, constructor.name.name, new TypeUnparsingContext(tuc));
+ }
}
container.addChild(new HtmlNode("</div></div>"));
}
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.elaboration.modules.Documentation;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
public class ConcreteModule implements Module {
String moduleName;
- THashMap<String, TypeConstructor> typeConstructors = new THashMap<String, TypeConstructor>();
- THashMap<String, TypeAlias> typeAliases = new THashMap<String, TypeAlias>();
+ THashMap<String, TypeDescriptor> typeDescriptors = new THashMap<String, TypeDescriptor>();
THashMap<String, EffectConstructor> effectConstructors = new THashMap<String, EffectConstructor>();
THashMap<String, TypeClass> typeClasses = new THashMap<String, TypeClass>();
THashMap<TCon, ArrayList<TypeClassInstance>> typeClassInstances = new THashMap<TCon, ArrayList<TypeClassInstance>>();
this.moduleName = moduleName;
}
- public boolean addTypeConstructor(String name, TypeConstructor typeConstructor) {
- return typeConstructors.put(name, typeConstructor) != null;
- }
-
- public boolean addTypeAlias(String name, TypeAlias alias) {
- return typeAliases.put(name, alias) != null;
+ public boolean addTypeDescriptor(String name, TypeDescriptor typeConstructor) {
+ return typeDescriptors.put(name, typeConstructor) != null;
}
public boolean addEffectConstructor(String name, EffectConstructor effectConstructor) {
}
@Override
- public TypeConstructor getTypeConstructor(String name) {
- return typeConstructors.get(name);
+ public TypeDescriptor getTypeDescriptor(String name) {
+ return typeDescriptors.get(name);
}
@Override
return documentation;
}
- @Override
- public TypeAlias getTypeAlias(String name) {
- return typeAliases.get(name);
- }
-
public void setClasses(Map<String, byte[]> classes) {
this.classes = classes;
}
@Override
public void findTypesForPrefix(String prefix, NamespaceFilter filter, Consumer<TCon> consumer) {
- typeConstructors.values().forEach(type -> {
+ typeDescriptors.values().forEach(type -> {
TCon tcon = type.name;
if (tcon.name.toLowerCase().startsWith(prefix.toLowerCase()) && filter.isValueIncluded(tcon.name))
consumer.accept(tcon);
});
- typeAliases.values().forEach(type -> {
- TCon tcon = type.getCon();
- if (tcon.name.toLowerCase().startsWith(prefix.toLowerCase()) && filter.isValueIncluded(tcon.name))
- consumer.accept(tcon);
- });
}
public void setBranchPoints(THashMap<String, BranchPoint[]> branchPoints) {
import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
}
@Override
- public TypeConstructor getTypeConstructor(String name) {
+ public TypeDescriptor getTypeDescriptor(String name) {
return null;
}
return null;
}
- @Override
- public TypeAlias getTypeAlias(String name) {
- return null;
- }
-
@Override
public Collection<TransformationRule> getRules() {
return Collections.emptyList();
import org.simantics.scl.compiler.elaboration.modules.Documentation;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
SCLValue getValue(String name);
SCLRelation getRelation(String name);
SCLEntityType getEntityType(String name);
- TypeConstructor getTypeConstructor(String name);
+
+ TypeDescriptor getTypeDescriptor(String name);
+
EffectConstructor getEffectConstructor(String name);
TypeClass getTypeClass(String name);
Collection<TypeClassInstance> getInstances(TCon typeClass);
- TypeAlias getTypeAlias(String name);
MappingRelation getMappingRelation(String name);
TransformationRule getRule(String name);
Collection<TransformationRule> getRules();
-package org.simantics.scl.compiler.module.repository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;
-import org.simantics.scl.compiler.environment.ConcreteEnvironment;
-import org.simantics.scl.compiler.environment.Environment;
-import org.simantics.scl.compiler.environment.NamespaceImpl.ModuleImport;
-import org.simantics.scl.compiler.environment.NamespaceSpec;
-import org.simantics.scl.compiler.environment.filter.NamespaceFilter;
-import org.simantics.scl.compiler.environment.filter.NamespaceFilters;
-import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
-import org.simantics.scl.compiler.errors.CompilationError;
-import org.simantics.scl.compiler.errors.DoesNotExist;
-import org.simantics.scl.compiler.errors.Failable;
-import org.simantics.scl.compiler.errors.Failure;
-import org.simantics.scl.compiler.errors.Success;
-import org.simantics.scl.compiler.module.ImportDeclaration;
-import org.simantics.scl.compiler.module.Module;
-import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;
-import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
-import org.simantics.scl.compiler.runtime.RuntimeEnvironmentImpl;
-import org.simantics.scl.compiler.runtime.RuntimeModule;
-import org.simantics.scl.compiler.runtime.RuntimeModuleMap;
-import org.simantics.scl.compiler.source.ModuleSource;
-import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;
-import org.simantics.scl.compiler.top.ModuleInitializer;
-import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
-import org.simantics.scl.compiler.top.ValueNotFound;
-import org.simantics.scl.compiler.types.Types;
-
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectObjectProcedure;
-import gnu.trove.set.hash.THashSet;
-
-/**
- * Manages compilation and caching of SCL modules.
- *
- * @author Hannu Niemistö
- */
-public class ModuleRepository {
- private final ModuleRepository parentRepository;
- private final ModuleSourceRepository sourceRepository;
- private ConcurrentHashMap<String, ModuleEntry> moduleCache = new ConcurrentHashMap<String, ModuleEntry>();
-
- private static final ThreadLocal<THashSet<String>> PENDING_MODULES = new ThreadLocal<THashSet<String>>();
-
- private ModuleCompilationOptionsAdvisor advisor = null;
-
- private static void beginModuleCompilation(String moduleName) {
- THashSet<String> set = PENDING_MODULES.get();
- if(set == null) {
- set = new THashSet<String>();
- PENDING_MODULES.set(set);
- }
- if(!set.add(moduleName))
- throw new IllegalArgumentException("Cyclic module dependency detected at " + moduleName + ".");
- }
-
- private static void finishModuleCompilation(String moduleName) {
- PENDING_MODULES.get().remove(moduleName);
- }
-
- private class ModuleEntry implements UpdateListener {
- final String moduleName;
- WeakHashMap<UpdateListener,Object> listeners = new WeakHashMap<UpdateListener,Object>();
-
- ModuleSource source;
- Failable<Module> compilationResult;
- Failable<RuntimeModule> runtimeModule; // created lazily
-
- public ModuleEntry(String moduleName) {
- this.moduleName = moduleName;
- }
-
- synchronized void addListener(UpdateListener listener) {
- if(listener != null)
- listeners.put(listener, null);
- }
-
- @Override
- public void notifyAboutUpdate() {
- if (listeners == null)
- return;
- ArrayList<UpdateListener> externalListeners = new ArrayList<UpdateListener>();
- notifyAboutUpdate(externalListeners);
- for(UpdateListener listener : externalListeners)
- listener.notifyAboutUpdate();
- }
-
- synchronized void notifyAboutUpdate(ArrayList<UpdateListener> externalListeners) {
- if(moduleCache.get(moduleName) == this) {
- moduleCache.remove(moduleName);
- if(SCLCompilerConfiguration.TRACE_MODULE_UPDATE) {
- System.out.println("Invalidate " + moduleName);
- for(UpdateListener l : listeners.keySet())
- System.out.println(" " + l);
- }
- for(UpdateListener l : listeners.keySet())
- if(l instanceof ModuleEntry)
- ((ModuleEntry)l).notifyAboutUpdate(externalListeners);
- else
- externalListeners.add(l);
- }
- }
-
- private ModuleEntry initModuleEntryAndAddListener(UpdateListener listener) {
- source = sourceRepository.getModuleSource(moduleName, this);
-
- if(source == null)
- compilationResult = DoesNotExist.getInstance();
- else {
- if(SCLCompilerConfiguration.TRACE_MODULE_UPDATE)
- System.out.println("Compile " + source);
- beginModuleCompilation(moduleName);
- compilationResult = source.compileModule(ModuleRepository.this, this, advisor == null ? null : advisor.getOptions(moduleName));
- finishModuleCompilation(moduleName);
- }
-
- ModuleEntry oldEntry = moduleCache.putIfAbsent(moduleName, this);
- if(oldEntry != null) {
- oldEntry.addListener(listener);
- return oldEntry;
- }
-
- addListener(listener);
- return this;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public synchronized Failable<RuntimeModule> getRuntimeModule() {
- if(runtimeModule == null) {
- if(compilationResult.didSucceed()) {
- Module module = compilationResult.getResult();
- RuntimeModuleMap parentModules = new RuntimeModuleMap();
- if(!moduleName.equals(Types.BUILTIN)) {
- parentModules.add(ModuleRepository.this.getRuntimeModule(Types.BUILTIN)
- .getResult());
- Collection<ImportDeclaration> dependencies = module.getDependencies();
- THashMap<String, ModuleEntry> moduleEntries;
- try {
- moduleEntries = getModuleEntries(dependencies.toArray(new ImportDeclaration[dependencies.size()]), null);
- } catch (ImportFailureException e) {
- throw new InternalCompilerError(e);
- }
- for(RuntimeModule m : mapEntriesToRuntimeModules(moduleEntries).values())
- parentModules.add(m);
- }
- /*for(ImportDeclaration importAst : module.getDependencies()) {
- RuntimeModule parentModule =
- ModuleRepository.this.getRuntimeModule(importAst.moduleName)
- .getResult();
- if(parentModule != null)
- parentModules.add(parentModule);
- }*/
- RuntimeModule rm = new RuntimeModule(module, parentModules, source.getClassLoader());
- ModuleInitializer initializer = module.getModuleInitializer();
- if(initializer != null)
- try {
- initializer.initializeModule(rm.getMutableClassLoader().getClassLoader());
- } catch (Exception e) {
- compilationResult = new Failure(new CompilationError[] {new CompilationError("Initialization of module " + moduleName + " failed: " + e.getMessage())});
- e.printStackTrace();
- }
- runtimeModule = new Success<RuntimeModule>(rm);
- }
- else
- runtimeModule = (Failable<RuntimeModule>)(Failable)compilationResult;
- }
- return runtimeModule;
- }
-
- public void dispose() {
- if (listeners != null)
- listeners.clear();
- listeners = null;
- source = null;
- compilationResult = null;
- if (runtimeModule != null) {
- if (runtimeModule.didSucceed())
- runtimeModule.getResult().dispose();
- }
- runtimeModule = null;
- }
-
- @Override
- public String toString() {
- return "ModuleEntry@" + moduleName + "@" + hashCode();
- }
- }
-
- public ModuleRepository(ModuleRepository parentRepository, ModuleSourceRepository sourceRepository) {
- this.parentRepository = parentRepository;
- this.sourceRepository = sourceRepository;
- }
-
- public ModuleRepository(ModuleSourceRepository sourceRepository) {
- this(null, sourceRepository);
- }
-
- public Failable<Module> getModule(String moduleName, UpdateListener listener) {
- return getModuleEntry(moduleName, listener).compilationResult;
- }
-
- public Failable<Module> getModule(String moduleName) {
- return getModule(moduleName, null);
- }
-
- public Failable<RuntimeModule> getRuntimeModule(String moduleName, UpdateListener listener) {
- return getModuleEntry(moduleName, listener).getRuntimeModule();
- }
-
- public Failable<RuntimeModule> getRuntimeModule(String moduleName) {
- return getRuntimeModule(moduleName, null);
- }
-
- private ModuleEntry getModuleEntry(String moduleName, UpdateListener listener) {
- /* It is deliberate that the following code does not try to prevent
- * simultaneous compilation of the same module. This is because in
- * some situations only certain thread trying compilation can succeed
- * in it.
- */
- ModuleEntry entry = moduleCache.get(moduleName);
- if(entry == null)
- entry = new ModuleEntry(moduleName).initModuleEntryAndAddListener(listener);
- else
- entry.addListener(listener);
-
- if(entry.compilationResult == DoesNotExist.INSTANCE && parentRepository != null)
- return parentRepository.getModuleEntry(moduleName, listener);
- else
- return entry;
- }
-
- private THashMap<String, ModuleEntry> getModuleEntries(
- ImportDeclaration[] imports,
- UpdateListener listener) throws ImportFailureException {
- THashMap<String, ModuleEntry> result = new THashMap<String, ModuleEntry>();
- Collection<ImportFailure> failures = null;
-
- ArrayList<ImportDeclaration> stack = new ArrayList<ImportDeclaration>(imports.length);
- for(ImportDeclaration import_ : imports)
- stack.add(import_);
- while(!stack.isEmpty()) {
- ImportDeclaration import_ = stack.remove(stack.size()-1);
- if(!result.containsKey(import_.moduleName)) {
- ModuleEntry entry = getModuleEntry(import_.moduleName, listener);
- Failable<Module> compilationResult = entry.compilationResult;
- if(compilationResult.didSucceed()) {
- result.put(import_.moduleName, entry);
- stack.addAll(compilationResult.getResult().getDependencies());
- }
- else {
- if(failures == null)
- failures = new ArrayList<ImportFailure>(2);
- failures.add(new ImportFailure(import_.location, import_.moduleName,
- compilationResult == DoesNotExist.INSTANCE
- ? ImportFailure.MODULE_DOES_NOT_EXIST_REASON
- : ((Failure)compilationResult).errors));
- }
- }
- }
-
- if(failures != null)
- throw new ImportFailureException(failures);
-
- return result;
- }
-
- private static THashMap<String, Module> mapEntriesToModules(THashMap<String, ModuleEntry> entries) {
- final THashMap<String, Module> result = new THashMap<String, Module>(entries.size());
- entries.forEachEntry(new TObjectObjectProcedure<String, ModuleEntry>() {
- @Override
- public boolean execute(String a, ModuleEntry b) {
- result.put(a, b.compilationResult.getResult());
- return true;
- }
- });
- return result;
- }
-
- private static THashMap<String, RuntimeModule> mapEntriesToRuntimeModules(THashMap<String, ModuleEntry> entries) {
- final THashMap<String, RuntimeModule> result = new THashMap<String, RuntimeModule>(entries.size());
- entries.forEachEntry(new TObjectObjectProcedure<String, ModuleEntry>() {
- @Override
- public boolean execute(String a, ModuleEntry b) {
- result.put(a, b.getRuntimeModule().getResult());
- return true;
- }
- });
- return result;
- }
-
- public Environment createEnvironment(
- ImportDeclaration[] imports,
- UpdateListener listener) throws ImportFailureException {
- THashMap<String, ModuleEntry> entries = getModuleEntries(imports, listener);
- THashMap<String, Module> moduleMap = mapEntriesToModules(entries);
- return createEnvironment(moduleMap, imports);
- }
-
- public Environment createEnvironment(
- EnvironmentSpecification specification,
- UpdateListener listener) throws ImportFailureException {
- return createEnvironment(specification.imports.toArray(new ImportDeclaration[specification.imports.size()]), listener);
- }
-
- public RuntimeEnvironment createRuntimeEnvironment(
- EnvironmentSpecification environmentSpecification, ClassLoader parentClassLoader) throws ImportFailureException {
- return createRuntimeEnvironment(environmentSpecification, parentClassLoader, null);
- }
-
- public RuntimeEnvironment createRuntimeEnvironment(
- EnvironmentSpecification environmentSpecification,
- ClassLoader parentClassLoader,
- UpdateListener listener) throws ImportFailureException {
- return createRuntimeEnvironment(
- environmentSpecification.imports.toArray(new ImportDeclaration[environmentSpecification.imports.size()]),
- parentClassLoader,
- listener);
- }
-
- public RuntimeEnvironment createRuntimeEnvironment(
- ImportDeclaration[] imports,
- ClassLoader parentClassLoader,
- UpdateListener listener) throws ImportFailureException {
- THashMap<String, ModuleEntry> entries = getModuleEntries(imports, listener);
- THashMap<String, Module> moduleMap = mapEntriesToModules(entries);
- Environment environment = createEnvironment(moduleMap, imports);
- THashMap<String, RuntimeModule> runtimeModuleMap = mapEntriesToRuntimeModules(entries);
- return new RuntimeEnvironmentImpl(environment, parentClassLoader, runtimeModuleMap);
- }
-
- private static Environment createEnvironment(THashMap<String, Module> moduleMap,
- ImportDeclaration[] imports) {
- NamespaceSpec spec = new NamespaceSpec();
- for(ImportDeclaration import_ : imports)
- if(import_.localName != null)
- addToNamespace(moduleMap, spec, import_.moduleName, import_.localName,
- NamespaceFilters.createFromSpec(import_.spec));
-
- return new ConcreteEnvironment(moduleMap, spec.toNamespace());
- }
-
- private static void addToNamespace(THashMap<String, Module> moduleMap,
- NamespaceSpec namespace, String moduleName, String localName,
- NamespaceFilter filter) {
- if(localName.isEmpty())
- addToNamespace(moduleMap, namespace, moduleName, filter);
- else
- addToNamespace(moduleMap, namespace.getNamespace(localName), moduleName, filter);
- }
-
- private static void addToNamespace(THashMap<String, Module> moduleMap,
- NamespaceSpec namespace, String moduleName, NamespaceFilter filter) {
- ModuleImport moduleImport = namespace.moduleMap.get(moduleName);
- if(moduleImport == null) {
- Module module = moduleMap.get(moduleName);
- namespace.moduleMap.put(moduleName, new ModuleImport(module, filter));
- for(ImportDeclaration import_ : module.getDependencies())
- if(import_.localName != null) {
- NamespaceFilter localFilter = NamespaceFilters.createFromSpec(import_.spec);
- if(import_.localName.equals(""))
- localFilter = NamespaceFilters.intersection(filter, localFilter);
- addToNamespace(moduleMap, namespace, import_.moduleName, import_.localName, localFilter);
- }
- }
- else if(!filter.isSubsetOf(moduleImport.filter)) {
- moduleImport.filter = NamespaceFilters.union(moduleImport.filter, filter);
- for(ImportDeclaration import_ : moduleImport.module.getDependencies())
- // We have to recheck only modules imported to this namespace
- if("".equals(import_.localName)) {
- NamespaceFilter localFilter = NamespaceFilters.createFromSpec(import_.spec);
- localFilter = NamespaceFilters.intersection(filter, localFilter);
- addToNamespace(moduleMap, namespace, import_.moduleName, import_.localName, localFilter);
- }
- }
- }
-
- public Object getValue(String moduleName, String valueName) throws ValueNotFound {
- Failable<RuntimeModule> module = getRuntimeModule(moduleName);
- if(module.didSucceed())
- return module.getResult().getValue(valueName);
- else if(module == DoesNotExist.INSTANCE)
- throw new ValueNotFound("Didn't find module " + moduleName);
- else
- throw new ValueNotFound(((Failure)module).toString());
- }
-
- public Object getValue(String fullValueName) throws ValueNotFound {
- int p = fullValueName.lastIndexOf('/');
- if(p < 0)
- throw new ValueNotFound(fullValueName + " is not a valid full value name.");
- return getValue(fullValueName.substring(0, p), fullValueName.substring(p+1));
- }
-
- public SCLValue getValueRef(String moduleName, String valueName) throws ValueNotFound {
- Failable<Module> module = getModule(moduleName);
- if(module.didSucceed()) {
- SCLValue value = module.getResult().getValue(valueName);
- if(value == null)
- throw new ValueNotFound("Module " + moduleName + " does not contain value " + valueName + ".");
- return value;
- }
- else if(module == DoesNotExist.INSTANCE)
- throw new ValueNotFound("Didn't find module " + moduleName);
- else
- throw new ValueNotFound(((Failure)module).toString());
- }
-
- public SCLValue getValueRef(String fullValueName) throws ValueNotFound {
- int p = fullValueName.lastIndexOf('/');
- if(p < 0)
- throw new ValueNotFound(fullValueName + " is not a valid full value name.");
- return getValueRef(fullValueName.substring(0, p), fullValueName.substring(p+1));
- }
-
- public ModuleSourceRepository getSourceRepository() {
- return sourceRepository;
- }
-
- public String getDocumentation(String documentationName) {
- String documentation = sourceRepository.getDocumentation(documentationName);
- if(documentation == null && parentRepository != null)
- return parentRepository.getDocumentation(documentationName);
- return documentation;
- }
-
- public void flush() {
- if (parentRepository != null)
- parentRepository.flush();
- if (moduleCache != null) {
- for (ModuleEntry entry : moduleCache.values()) {
- entry.dispose();
- }
- moduleCache.clear();
- }
- moduleCache = null;
- }
-
- public Map<String, Module> getModules() {
- Map<String, Module> result = new HashMap<>(moduleCache.size());
- for (Map.Entry<String, ModuleEntry> entry : moduleCache.entrySet()) {
- ModuleEntry moduleEntry = entry.getValue();
- if (moduleEntry.compilationResult.didSucceed()) {
- result.put(entry.getKey(), moduleEntry.compilationResult.getResult());
- }
- }
- return result;
- }
-
- public ModuleCompilationOptionsAdvisor getAdvisor() {
- return advisor;
- }
-
- public void setAdvisor(ModuleCompilationOptionsAdvisor advisor) {
- this.advisor = advisor;
- }
+package org.simantics.scl.compiler.module.repository;\r
\r
-}
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.WeakHashMap;\r
+import java.util.concurrent.ConcurrentHashMap;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
+import org.simantics.scl.compiler.environment.ConcreteEnvironment;\r
+import org.simantics.scl.compiler.environment.Environment;\r
+import org.simantics.scl.compiler.environment.NamespaceImpl.ModuleImport;\r
+import org.simantics.scl.compiler.environment.NamespaceSpec;\r
+import org.simantics.scl.compiler.environment.filter.NamespaceFilter;\r
+import org.simantics.scl.compiler.environment.filter.NamespaceFilters;\r
+import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
+import org.simantics.scl.compiler.errors.CompilationError;\r
+import org.simantics.scl.compiler.errors.DoesNotExist;\r
+import org.simantics.scl.compiler.errors.Failable;\r
+import org.simantics.scl.compiler.errors.Failure;\r
+import org.simantics.scl.compiler.errors.Success;\r
+import org.simantics.scl.compiler.module.ImportDeclaration;\r
+import org.simantics.scl.compiler.module.Module;\r
+import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;\r
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
+import org.simantics.scl.compiler.runtime.RuntimeEnvironmentImpl;\r
+import org.simantics.scl.compiler.runtime.RuntimeModule;\r
+import org.simantics.scl.compiler.runtime.RuntimeModuleMap;\r
+import org.simantics.scl.compiler.source.ModuleSource;\r
+import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;\r
+import org.simantics.scl.compiler.top.ModuleInitializer;\r
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
+import org.simantics.scl.compiler.top.ValueNotFound;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectObjectProcedure;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+/**\r
+ * Manages compilation and caching of SCL modules.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public class ModuleRepository {\r
+ private final ModuleRepository parentRepository;\r
+ private final ModuleSourceRepository sourceRepository;\r
+ private ConcurrentHashMap<String, ModuleEntry> moduleCache = new ConcurrentHashMap<String, ModuleEntry>();\r
+ \r
+ private static final ThreadLocal<THashSet<String>> PENDING_MODULES = new ThreadLocal<THashSet<String>>();\r
+ \r
+ private ModuleCompilationOptionsAdvisor advisor = null;\r
+ \r
+ private static void beginModuleCompilation(String moduleName) {\r
+ THashSet<String> set = PENDING_MODULES.get();\r
+ if(set == null) {\r
+ set = new THashSet<String>();\r
+ PENDING_MODULES.set(set);\r
+ }\r
+ if(!set.add(moduleName))\r
+ throw new IllegalArgumentException("Cyclic module dependency detected at " + moduleName + ".");\r
+ }\r
+ \r
+ private static void finishModuleCompilation(String moduleName) {\r
+ PENDING_MODULES.get().remove(moduleName);\r
+ }\r
+ \r
+ private class ModuleEntry implements UpdateListener {\r
+ final String moduleName;\r
+ WeakHashMap<UpdateListener,Object> listeners = new WeakHashMap<UpdateListener,Object>();\r
+ \r
+ ModuleSource source;\r
+ Failable<Module> compilationResult;\r
+ Failable<RuntimeModule> runtimeModule; // created lazily\r
+\r
+ public ModuleEntry(String moduleName) {\r
+ this.moduleName = moduleName;\r
+ }\r
+ \r
+ synchronized void addListener(UpdateListener listener) {\r
+ if(listener != null)\r
+ listeners.put(listener, null);\r
+ }\r
+ \r
+ @Override\r
+ public void notifyAboutUpdate() {\r
+ if (listeners == null)\r
+ return;\r
+ ArrayList<UpdateListener> externalListeners = new ArrayList<UpdateListener>();\r
+ notifyAboutUpdate(externalListeners);\r
+ for(UpdateListener listener : externalListeners)\r
+ listener.notifyAboutUpdate();\r
+ }\r
+\r
+ synchronized void notifyAboutUpdate(ArrayList<UpdateListener> externalListeners) {\r
+ if(moduleCache.get(moduleName) == this) {\r
+ moduleCache.remove(moduleName);\r
+ if(SCLCompilerConfiguration.TRACE_MODULE_UPDATE) {\r
+ System.out.println("Invalidate " + moduleName);\r
+ for(UpdateListener l : listeners.keySet())\r
+ System.out.println(" " + l);\r
+ }\r
+ for(UpdateListener l : listeners.keySet())\r
+ if(l instanceof ModuleEntry)\r
+ ((ModuleEntry)l).notifyAboutUpdate(externalListeners);\r
+ else\r
+ externalListeners.add(l);\r
+ }\r
+ }\r
+\r
+ private ModuleEntry initModuleEntryAndAddListener(UpdateListener listener) {\r
+ source = sourceRepository.getModuleSource(moduleName, this);\r
+ \r
+ if(source == null)\r
+ compilationResult = DoesNotExist.getInstance();\r
+ else {\r
+ if(SCLCompilerConfiguration.TRACE_MODULE_UPDATE)\r
+ System.out.println("Compile " + source);\r
+ beginModuleCompilation(moduleName);\r
+ compilationResult = source.compileModule(ModuleRepository.this, this, advisor == null ? null : advisor.getOptions(moduleName));\r
+ finishModuleCompilation(moduleName);\r
+ }\r
+ \r
+ ModuleEntry oldEntry = moduleCache.putIfAbsent(moduleName, this);\r
+ if(oldEntry != null) {\r
+ oldEntry.addListener(listener);\r
+ return oldEntry;\r
+ }\r
+ \r
+ addListener(listener);\r
+ return this;\r
+ }\r
+ \r
+ @SuppressWarnings({ "rawtypes", "unchecked" })\r
+ public synchronized Failable<RuntimeModule> getRuntimeModule() {\r
+ if(runtimeModule == null) {\r
+ if(compilationResult.didSucceed()) {\r
+ Module module = compilationResult.getResult();\r
+ RuntimeModuleMap parentModules = new RuntimeModuleMap();\r
+ if(!moduleName.equals(Types.BUILTIN)) {\r
+ parentModules.add(ModuleRepository.this.getRuntimeModule(Types.BUILTIN)\r
+ .getResult());\r
+ Collection<ImportDeclaration> dependencies = module.getDependencies();\r
+ THashMap<String, ModuleEntry> moduleEntries;\r
+ try {\r
+ moduleEntries = getModuleEntries(dependencies.toArray(new ImportDeclaration[dependencies.size()]), null);\r
+ } catch (ImportFailureException e) {\r
+ throw new InternalCompilerError(e);\r
+ }\r
+ for(RuntimeModule m : mapEntriesToRuntimeModules(moduleEntries).values())\r
+ parentModules.add(m);\r
+ }\r
+ /*for(ImportDeclaration importAst : module.getDependencies()) {\r
+ RuntimeModule parentModule =\r
+ ModuleRepository.this.getRuntimeModule(importAst.moduleName)\r
+ .getResult();\r
+ if(parentModule != null)\r
+ parentModules.add(parentModule);\r
+ }*/\r
+ RuntimeModule rm = new RuntimeModule(module, parentModules, source.getClassLoader());\r
+ ModuleInitializer initializer = module.getModuleInitializer();\r
+ if(initializer != null)\r
+ try {\r
+ initializer.initializeModule(rm.getMutableClassLoader().getClassLoader());\r
+ } catch (Exception e) {\r
+ compilationResult = new Failure(new CompilationError[] {new CompilationError("Initialization of module " + moduleName + " failed: " + e.getMessage())});\r
+ e.printStackTrace();\r
+ }\r
+ runtimeModule = new Success<RuntimeModule>(rm); \r
+ }\r
+ else\r
+ runtimeModule = (Failable<RuntimeModule>)(Failable)compilationResult;\r
+ }\r
+ return runtimeModule;\r
+ }\r
+\r
+ public void dispose() {\r
+ if (listeners != null)\r
+ listeners.clear();\r
+ listeners = null;\r
+ source = null;\r
+ compilationResult = null;\r
+ if (runtimeModule != null) {\r
+ if (runtimeModule.didSucceed())\r
+ runtimeModule.getResult().dispose();\r
+ }\r
+ runtimeModule = null;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return "ModuleEntry@" + moduleName + "@" + hashCode();\r
+ }\r
+ }\r
+ \r
+ public ModuleRepository(ModuleRepository parentRepository, ModuleSourceRepository sourceRepository) {\r
+ this.parentRepository = parentRepository;\r
+ this.sourceRepository = sourceRepository;\r
+ }\r
+\r
+ public ModuleRepository(ModuleSourceRepository sourceRepository) {\r
+ this(null, sourceRepository);\r
+ }\r
+ \r
+ public Failable<Module> getModule(String moduleName, UpdateListener listener) {\r
+ return getModuleEntry(moduleName, listener).compilationResult;\r
+ }\r
+ \r
+ public Failable<Module> getModule(String moduleName) {\r
+ return getModule(moduleName, null);\r
+ }\r
+ \r
+ public Failable<RuntimeModule> getRuntimeModule(String moduleName, UpdateListener listener) {\r
+ return getModuleEntry(moduleName, listener).getRuntimeModule();\r
+ }\r
+ \r
+ public Failable<RuntimeModule> getRuntimeModule(String moduleName) {\r
+ return getRuntimeModule(moduleName, null);\r
+ }\r
+ \r
+ private ModuleEntry getModuleEntry(String moduleName, UpdateListener listener) {\r
+ /* It is deliberate that the following code does not try to prevent\r
+ * simultaneous compilation of the same module. This is because in\r
+ * some situations only certain thread trying compilation can succeed\r
+ * in it.\r
+ */\r
+ ModuleEntry entry = moduleCache.get(moduleName);\r
+ if(entry == null)\r
+ entry = new ModuleEntry(moduleName).initModuleEntryAndAddListener(listener);\r
+ else\r
+ entry.addListener(listener);\r
+\r
+ if(entry.compilationResult == DoesNotExist.INSTANCE && parentRepository != null)\r
+ return parentRepository.getModuleEntry(moduleName, listener);\r
+ else\r
+ return entry;\r
+ }\r
+ \r
+ private THashMap<String, ModuleEntry> getModuleEntries(\r
+ ImportDeclaration[] imports,\r
+ UpdateListener listener) throws ImportFailureException {\r
+ THashMap<String, ModuleEntry> result = new THashMap<String, ModuleEntry>();\r
+ Collection<ImportFailure> failures = null;\r
+ \r
+ ArrayList<ImportDeclaration> stack = new ArrayList<ImportDeclaration>(imports.length);\r
+ for(ImportDeclaration import_ : imports)\r
+ stack.add(import_);\r
+ while(!stack.isEmpty()) {\r
+ ImportDeclaration import_ = stack.remove(stack.size()-1);\r
+ if(!result.containsKey(import_.moduleName)) {\r
+ ModuleEntry entry = getModuleEntry(import_.moduleName, listener);\r
+ Failable<Module> compilationResult = entry.compilationResult;\r
+ if(compilationResult.didSucceed()) {\r
+ result.put(import_.moduleName, entry);\r
+ stack.addAll(compilationResult.getResult().getDependencies());\r
+ }\r
+ else {\r
+ if(failures == null)\r
+ failures = new ArrayList<ImportFailure>(2);\r
+ failures.add(new ImportFailure(import_.location, import_.moduleName,\r
+ compilationResult == DoesNotExist.INSTANCE\r
+ ? ImportFailure.MODULE_DOES_NOT_EXIST_REASON\r
+ : ((Failure)compilationResult).errors));\r
+ }\r
+ }\r
+ }\r
+ \r
+ if(failures != null)\r
+ throw new ImportFailureException(failures);\r
+ \r
+ return result;\r
+ }\r
+\r
+ private static THashMap<String, Module> mapEntriesToModules(THashMap<String, ModuleEntry> entries) {\r
+ final THashMap<String, Module> result = new THashMap<String, Module>(entries.size());\r
+ entries.forEachEntry(new TObjectObjectProcedure<String, ModuleEntry>() {\r
+ @Override\r
+ public boolean execute(String a, ModuleEntry b) {\r
+ result.put(a, b.compilationResult.getResult());\r
+ return true;\r
+ }\r
+ });\r
+ return result;\r
+ }\r
+ \r
+ private static THashMap<String, RuntimeModule> mapEntriesToRuntimeModules(THashMap<String, ModuleEntry> entries) {\r
+ final THashMap<String, RuntimeModule> result = new THashMap<String, RuntimeModule>(entries.size());\r
+ entries.forEachEntry(new TObjectObjectProcedure<String, ModuleEntry>() {\r
+ @Override\r
+ public boolean execute(String a, ModuleEntry b) {\r
+ result.put(a, b.getRuntimeModule().getResult());\r
+ return true;\r
+ }\r
+ });\r
+ return result;\r
+ }\r
+ \r
+ public Environment createEnvironment(\r
+ ImportDeclaration[] imports,\r
+ UpdateListener listener) throws ImportFailureException {\r
+ THashMap<String, ModuleEntry> entries = getModuleEntries(imports, listener);\r
+ THashMap<String, Module> moduleMap = mapEntriesToModules(entries);\r
+ return createEnvironment(moduleMap, imports);\r
+ }\r
+ \r
+ public Environment createEnvironment(\r
+ EnvironmentSpecification specification,\r
+ UpdateListener listener) throws ImportFailureException {\r
+ return createEnvironment(specification.imports.toArray(new ImportDeclaration[specification.imports.size()]), listener);\r
+ }\r
+ \r
+ public RuntimeEnvironment createRuntimeEnvironment(\r
+ EnvironmentSpecification environmentSpecification, ClassLoader parentClassLoader) throws ImportFailureException {\r
+ return createRuntimeEnvironment(environmentSpecification, parentClassLoader, null);\r
+ }\r
+ \r
+ public RuntimeEnvironment createRuntimeEnvironment(\r
+ EnvironmentSpecification environmentSpecification,\r
+ ClassLoader parentClassLoader,\r
+ UpdateListener listener) throws ImportFailureException {\r
+ return createRuntimeEnvironment(\r
+ environmentSpecification.imports.toArray(new ImportDeclaration[environmentSpecification.imports.size()]),\r
+ parentClassLoader,\r
+ listener);\r
+ }\r
+ \r
+ public RuntimeEnvironment createRuntimeEnvironment(\r
+ ImportDeclaration[] imports,\r
+ ClassLoader parentClassLoader,\r
+ UpdateListener listener) throws ImportFailureException {\r
+ THashMap<String, ModuleEntry> entries = getModuleEntries(imports, listener);\r
+ THashMap<String, Module> moduleMap = mapEntriesToModules(entries);\r
+ Environment environment = createEnvironment(moduleMap, imports);\r
+ THashMap<String, RuntimeModule> runtimeModuleMap = mapEntriesToRuntimeModules(entries);\r
+ return new RuntimeEnvironmentImpl(environment, parentClassLoader, runtimeModuleMap);\r
+ }\r
+ \r
+ private static Environment createEnvironment(THashMap<String, Module> moduleMap, \r
+ ImportDeclaration[] imports) {\r
+ NamespaceSpec spec = new NamespaceSpec();\r
+ for(ImportDeclaration import_ : imports)\r
+ if(import_.localName != null)\r
+ addToNamespace(moduleMap, spec, import_.moduleName, import_.localName,\r
+ NamespaceFilters.createFromSpec(import_.spec));\r
+ \r
+ return new ConcreteEnvironment(moduleMap, spec.toNamespace());\r
+ }\r
+ \r
+ private static void addToNamespace(THashMap<String, Module> moduleMap, \r
+ NamespaceSpec namespace, String moduleName, String localName,\r
+ NamespaceFilter filter) {\r
+ if(localName.isEmpty())\r
+ addToNamespace(moduleMap, namespace, moduleName, filter);\r
+ else\r
+ addToNamespace(moduleMap, namespace.getNamespace(localName), moduleName, filter);\r
+ }\r
+ \r
+ private static void addToNamespace(THashMap<String, Module> moduleMap, \r
+ NamespaceSpec namespace, String moduleName, NamespaceFilter filter) {\r
+ ModuleImport moduleImport = namespace.moduleMap.get(moduleName);\r
+ if(moduleImport == null) {\r
+ Module module = moduleMap.get(moduleName);\r
+ namespace.moduleMap.put(moduleName, new ModuleImport(module, filter));\r
+ for(ImportDeclaration import_ : module.getDependencies())\r
+ if(import_.localName != null) {\r
+ NamespaceFilter localFilter = NamespaceFilters.createFromSpec(import_.spec);\r
+ if(import_.localName.equals(""))\r
+ localFilter = NamespaceFilters.intersection(filter, localFilter);\r
+ addToNamespace(moduleMap, namespace, import_.moduleName, import_.localName, localFilter);\r
+ }\r
+ }\r
+ else if(!filter.isSubsetOf(moduleImport.filter)) {\r
+ moduleImport.filter = NamespaceFilters.union(moduleImport.filter, filter);\r
+ for(ImportDeclaration import_ : moduleImport.module.getDependencies())\r
+ // We have to recheck only modules imported to this namespace\r
+ if("".equals(import_.localName)) {\r
+ NamespaceFilter localFilter = NamespaceFilters.createFromSpec(import_.spec);\r
+ localFilter = NamespaceFilters.intersection(filter, localFilter);\r
+ addToNamespace(moduleMap, namespace, import_.moduleName, import_.localName, localFilter);\r
+ }\r
+ }\r
+ }\r
+\r
+ public Object getValue(String moduleName, String valueName) throws ValueNotFound {\r
+ Failable<RuntimeModule> module = getRuntimeModule(moduleName);\r
+ if(module.didSucceed())\r
+ return module.getResult().getValue(valueName);\r
+ else if(module == DoesNotExist.INSTANCE)\r
+ throw new ValueNotFound("Didn't find module " + moduleName);\r
+ else\r
+ throw new ValueNotFound(((Failure)module).toString());\r
+ }\r
+\r
+ public Object getValue(String fullValueName) throws ValueNotFound {\r
+ int p = fullValueName.lastIndexOf('/');\r
+ if(p < 0)\r
+ throw new ValueNotFound(fullValueName + " is not a valid full value name.");\r
+ return getValue(fullValueName.substring(0, p), fullValueName.substring(p+1));\r
+ }\r
+\r
+ public SCLValue getValueRef(String moduleName, String valueName) throws ValueNotFound {\r
+ Failable<Module> module = getModule(moduleName);\r
+ if(module.didSucceed()) {\r
+ SCLValue value = module.getResult().getValue(valueName);\r
+ if(value == null)\r
+ throw new ValueNotFound("Module " + moduleName + " does not contain value " + valueName + ".");\r
+ return value;\r
+ }\r
+ else if(module == DoesNotExist.INSTANCE)\r
+ throw new ValueNotFound("Didn't find module " + moduleName);\r
+ else\r
+ throw new ValueNotFound(((Failure)module).toString());\r
+ }\r
+ \r
+ public SCLValue getValueRef(String fullValueName) throws ValueNotFound {\r
+ int p = fullValueName.lastIndexOf('/');\r
+ if(p < 0)\r
+ throw new ValueNotFound(fullValueName + " is not a valid full value name.");\r
+ return getValueRef(fullValueName.substring(0, p), fullValueName.substring(p+1));\r
+ }\r
+ \r
+ public ModuleSourceRepository getSourceRepository() {\r
+ return sourceRepository;\r
+ }\r
+ \r
+ public String getDocumentation(String documentationName) {\r
+ String documentation = sourceRepository.getDocumentation(documentationName);\r
+ if(documentation == null && parentRepository != null)\r
+ return parentRepository.getDocumentation(documentationName);\r
+ return documentation;\r
+ }\r
+ \r
+ public void flush() {\r
+ if (parentRepository != null)\r
+ parentRepository.flush();\r
+ if (moduleCache != null) {\r
+ for (ModuleEntry entry : moduleCache.values()) {\r
+ entry.dispose();\r
+ }\r
+ moduleCache.clear();\r
+ }\r
+ moduleCache = null;\r
+ }\r
+\r
+ public Map<String, Module> getModules() {\r
+ Map<String, Module> result = new HashMap<>(moduleCache.size()); \r
+ for (Map.Entry<String, ModuleEntry> entry : moduleCache.entrySet()) {\r
+ ModuleEntry moduleEntry = entry.getValue();\r
+ if (moduleEntry.compilationResult.didSucceed()) {\r
+ result.put(entry.getKey(), moduleEntry.compilationResult.getResult());\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ public ModuleCompilationOptionsAdvisor getAdvisor() {\r
+ return advisor;\r
+ }\r
+\r
+ public void setAdvisor(ModuleCompilationOptionsAdvisor advisor) {\r
+ this.advisor = advisor;\r
+ }\r
+\r
+}\r
\ No newline at end of file
return defineClass(name, bytes, 0, bytes.length);
}
+ public byte[] getBytes(String name) {
+ // Non-SCL classes are not handled here
+ if(!name.startsWith(SCL_PACKAGE_PREFIX))
+ return null;
+
+ // Determine the id of the class loader which is responsible of the class
+ String requestedModuleName = RuntimeModule.extractClassLoaderId(name);
+
+ // Is class defined locally in this class loader?
+ if(requestedModuleName.equals(basePackageName)) {
+ String internalName = name.replace('.', '/');
+ byte[] bytes = localClasses.get(internalName);
+ if(bytes != null)
+ return bytes;
+ return localClasses.get(internalName);
+ }
+
+ // Find suitable class loader that has this class locally
+ {
+ RuntimeModule parentModule = runtimeModuleMap.get(requestedModuleName);
+ if(parentModule == null)
+ return null;
+
+ // Find the class from the ancestor class loader
+ return parentModule.classLoader.getBytes(name);
+ }
+ }
+
private Class<?> getClass(String name) throws ClassNotFoundException {
//System.out.println("getClass " + name);
package org.simantics.scl.compiler.runtime;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
import org.simantics.scl.compiler.module.Module;
-import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
import org.simantics.scl.compiler.top.ValueNotFound;
-import com.strobel.assembler.metadata.Buffer;
-import com.strobel.assembler.metadata.ClasspathTypeLoader;
-import com.strobel.assembler.metadata.CompositeTypeLoader;
-import com.strobel.assembler.metadata.ITypeLoader;
-import com.strobel.decompiler.Decompiler;
-import com.strobel.decompiler.DecompilerSettings;
-import com.strobel.decompiler.PlainTextOutput;
-
import gnu.trove.map.hash.THashMap;
public class RuntimeModule {
bytes = localClasses.get(internalName);
if(bytes == null)
throw new ClassNotFoundException(name);
- }
- if(SCLCompilerConfiguration.SHOW_LOADED_CLASSES_DISASSEMBLED) {
- DecompilerSettings settings = DecompilerSettings.javaDefaults();
- ITypeLoader typeLoader = new ITypeLoader() {
- @Override
- public boolean tryLoadType(String internalName, Buffer buffer) {
- byte[] bytes = getBytes(internalName);
- if(bytes != null) {
- buffer.reset(bytes.length);
- buffer.putByteArray(bytes, 0, bytes.length);
- buffer.position(0);
- return true;
- }
- else
- return false;
- }
- };
- settings.setTypeLoader(new CompositeTypeLoader(typeLoader, new ClasspathTypeLoader()));
- OutputStreamWriter writer = new OutputStreamWriter(System.out);
- PlainTextOutput output = new PlainTextOutput(writer);
- Decompiler.decompile(name, output, settings);
- try {
- writer.flush();
- } catch (IOException e) {
- }
- }
+ }
return defineClass(name, bytes, 0, bytes.length);
}
import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
import org.simantics.scl.compiler.module.repository.ModuleRepository;
import org.simantics.scl.compiler.module.repository.UpdateListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public abstract class TextualModuleSource implements ModuleSource {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TextualModuleSource.class);
+
public static final ImportDeclaration[] DEFAULT_IMPORTS = new ImportDeclaration[] {
new ImportDeclaration("Builtin", ""),
new ImportDeclaration("Prelude", "")
if(compiler.getErrorLog().isEmpty())
return new Success<Module>(compiler.getModule());
else {
- System.err.println("While compiling " + getModuleName() + ":");
- System.err.println(CompilationErrorFormatter.toString(getSourceReader(null), compiler.getErrorLog().getErrors()));
+ LOGGER.error("While compiling " + getModuleName() + ":");
+ LOGGER.error(CompilationErrorFormatter.toString(getSourceReader(null), compiler.getErrorLog().getErrors()));
return new Failure(compiler.getErrorLog().getErrors());
}
} catch (IOException e) {
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.compilation.CodeGeneration;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.constants.JavaStaticMethod;
import org.simantics.scl.compiler.constants.SCLConstant;
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
public Object eval() throws SCLExpressionCompilationException {
fillDefaults();
- final ErrorLog errorLog = new ErrorLog();
+ final CompilationContext compilationContext = new CompilationContext();
+ final ErrorLog errorLog = compilationContext.errorLog;
final Environment environment = runtimeEnvironment.getEnvironment();
+ compilationContext.environment = environment;
// Parse expression
- if(expressionText != null && !expressionText.trim().isEmpty()) {
+ if(expressionText != null) {
try {
switch(parseMode) {
case BLOCK: {
// Elaboration
{
- TranslationContext context = new TranslationContext(errorLog,
- environment, localEnvironment);
+ TranslationContext context = new TranslationContext(compilationContext, localEnvironment);
expression = expression.resolve(context);
if(!errorLog.isEmpty())
throw new SCLExpressionCompilationException(errorLog.getErrors());
// Type checking
{
- TypingContext context = new TypingContext(errorLog, environment);
+ TypingContext context = new TypingContext(compilationContext);
context.pushEffectUpperBound(expression.location, expectedEffect);
expression = expression.checkType(context, expectedType);
MutableClassLoader classLoader = runtimeEnvironment.getMutableClassLoader();
String moduleName = classLoader.getFreshPackageName();
JavaTypeTranslator javaTypeTranslator = new JavaTypeTranslator(environment);
+ compilationContext.javaTypeTranslator = javaTypeTranslator;
JavaNamingPolicy namingPolicy = new JavaNamingPolicy(moduleName);
+ compilationContext.namingPolicy = namingPolicy;
ModuleBuilder moduleBuilder = new ModuleBuilder(namingPolicy, javaTypeTranslator);
// Simplify
SimplificationContext context =
- new SimplificationContext(environment, errorLog,
- javaTypeTranslator, DummyJavaReferenceValidator.INSTANCE);
+ new SimplificationContext(compilationContext, DummyJavaReferenceValidator.INSTANCE);
expression = expression.simplify(context);
if(!errorLog.isEmpty())
public static final boolean SHOW_SSA_BEFORE_LAMBDA_LIFTING = false;
public static final boolean SHOW_FINAL_SSA = false;
public static final boolean SHOW_COMPILED_BYTECODE = false;
- public static final boolean SHOW_LOADED_CLASSES_DISASSEMBLED = false;
public static final boolean SHOW_EXPRESSION_BEFORE_EVALUATION = false;
public static final boolean SHOW_INTERPRETED_EXPRESSION = false;
public static final boolean EVERY_RULE_ENFORCEMENT_IN_SEPARATE_METHOD = true;
public static final boolean EVERY_DATALOG_STRATUM_IN_SEPARATE_METHOD = true;
- public static final boolean ALLOW_OVERLOADING = false;
+ public static final boolean ALLOW_OVERLOADING = true;
}
import java.util.ArrayList;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EConstant;
import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
ArrayList<TCon> concreteEffects = new ArrayList<TCon>();
effect.collectConcreteEffects(concreteEffects);
if(concreteEffects.contains(Types.WRITE_GRAPH)) {
- Name name = Name.create("Simantics/DB", "syncWrite");
+ Name name = Names.Simantics_DB_syncWrite;
SCLValue transactionFunction = environment.getValue(name);
if(transactionFunction == null) {
errorLog.log(expression.location, "Cannot locate " + name);
expression = decorate(transactionFunction, Types.WRITE_GRAPH, expression);
}
else if(concreteEffects.contains(Types.READ_GRAPH)) {
- Name name = Name.create("Simantics/DB", "syncRead");
+ Name name = Names.Simantics_DB_syncRead;
SCLValue transactionFunction = environment.getValue(name);
if(transactionFunction == null) {
errorLog.log(expression.location, "Cannot locate " + name);
expression = decorate(transactionFunction, Types.READ_GRAPH, expression);
}
if(concreteEffects.contains(R)) {
- Name name = Name.create("R/R", "runR");
+ Name name = Names.R_R_runR;
SCLValue transactionFunction = environment.getValue(name);
if(transactionFunction == null) {
errorLog.log(expression.location, "Cannot locate " + name);
expression = decorate(transactionFunction, R, expression);
}
if(concreteEffects.contains(Types.RANDOM)) {
- Name name = Name.create("Random", "runRandom");
+ Name name = Names.Random_runRandom;
SCLValue transactionFunction = environment.getValue(name);
if(transactionFunction == null) {
errorLog.log(expression.location, "Cannot locate " + name);
import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
import org.simantics.scl.compiler.types.exceptions.UnificationException;
+import org.simantics.scl.compiler.types.kinds.Kind;
import org.simantics.scl.compiler.types.kinds.Kinds;
import gnu.trove.map.hash.THashMap;
return Types.metaVar(Kinds.EFFECT);
return first;
}
+
+ public static boolean equalSkeletons(TApply a, TApply b) {
+ return equalSkeletons(a.parameter, b.parameter)
+ && equalSkeletons(a.function , b.function );
+ }
+
+ public static boolean equalSkeletons(TFun a, TFun b) {
+ return equalSkeletons(a.domain, b.domain)
+ && equalSkeletons(a.range, b.range);
+ }
+
+ public static boolean equalSkeletons(TForAll a, TForAll b) {
+ Kind aKind = a.var.getKind();
+ if(!Kinds.equalsCanonical(aKind, b.var.getKind()))
+ return false;
+ TVar newVar = Types.var(aKind);
+ return equalSkeletons(a.type.replace(a.var, newVar), b.type.replace(b.var, newVar));
+ }
+
+ public static boolean equalSkeletons(TPred a, TPred b) {
+ if(a.typeClass != b.typeClass
+ || a.parameters.length != b.parameters.length)
+ return false;
+ Type[] aParameters = a.parameters;
+ Type[] bParameters = b.parameters;
+ for(int i=0;i<aParameters.length;++i)
+ if(!equalSkeletons(aParameters[i], bParameters[i]))
+ return false;
+ return true;
+ }
+
+ /**
+ * Tests equality of two types. Unbound TVars
+ * are equal only if they are the same variable.
+ * Bound TMetaVar is equal to the type it is bound to.
+ * Unbound TMetaVars are equal only if they are the same metavariable.
+ * Order of predicates and forall quantifiers matters.
+ */
+ public static boolean equalSkeletons(Type a, Type b) {
+ a = canonicalSkeleton(a);
+ b = canonicalSkeleton(b);
+ if(a == b)
+ return true;
+ Class<?> ca = a.getClass();
+ Class<?> cb = b.getClass();
+ if(ca != cb)
+ return false;
+ if(ca == TApply.class)
+ return equalSkeletons((TApply)a, (TApply)b);
+ else if(ca == TFun.class)
+ return equalSkeletons((TFun)a, (TFun)b);
+ else if(ca == TForAll.class)
+ return equalSkeletons((TForAll)a, (TForAll)b);
+ else if(ca == TPred.class)
+ return equalSkeletons((TPred)a, (TPred)b);
+ else // ca == TCon.class
+ // || (ca == TMetaVar.class && a.ref == null && b.ref == null)
+ // || ca = TVar.class
+ return false; // Equals only if a == b, that was already tested
+ }
}
return hash;
}
+ @Override
+ public int skeletonHashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
+ hash = function.skeletonHashCode(hash);
+ hash = parameter.skeletonHashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
+ hash = function.skeletonHashCode(hash, boundVars);
+ hash = parameter.skeletonHashCode(hash, boundVars);
+ return hash;
+ }
+
public Type getCanonicalFunction() {
if(function instanceof TMetaVar)
function = function.canonical();
return getCanonicalFunction().equalsCanonical(apply.getCanonicalFunction())
&& getCanonicalParameter().equalsCanonical(apply.getCanonicalParameter());
}
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ return new Type[] {Skeletons.canonicalSkeleton(function), Skeletons.canonicalSkeleton(parameter)};
+ }
}
return this == obj;
}
- @Override
- public int hashCode() {
- return System.identityHashCode(this);
- }
-
@Override
public void updateHashCode(TypeHashCodeContext context) {
context.append(System.identityHashCode(this));
}
public Kind inferKind(Environment context) throws KindUnificationException {
- return context.getTypeConstructor(this).kind;
+ return context.getTypeDescriptor(this).getKind();
}
public Kind getKind(Environment context) {
- return context.getTypeConstructor(this).kind;
+ return context.getTypeDescriptor(this).getKind();
}
@Override
public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
return this;
}
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
@Override
public int hashCode(int hash) {
return HashCodeUtils.update(hash, System.identityHashCode(this));
}
+ @Override
+ public int skeletonHashCode() {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public int skeletonHashCode(int hash) {
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
@Override
public boolean equalsCanonical(Type other) {
return this == other;
}
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ return EMPTY_ARRAY;
+ }
}
return t.type.hashCode(hash, boundVars);
}
+ @Override
+ public int skeletonHashCode(int hash) {
+ int count=1;
+ {
+ Type t = Types.canonical(type);
+ while(t instanceof TForAll) {
+ t = Types.canonical( ((TForAll)t).type );
+ ++count;
+ }
+ }
+ TVar[] boundVars = new TVar[count];
+ boundVars[0] = var;
+ TForAll t = this;
+ {
+ for(int i=1;i<count;++i) {
+ t = (TForAll)Types.canonical(t.type);
+ boundVars[i] = t.var;
+ }
+ }
+
+ for(int i=0;i<count;++i)
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
+ return t.type.skeletonHashCode(hash, boundVars);
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] oldBoundVars) {
+ int count=1;
+ {
+ Type t = Types.canonical(type);
+ while(t instanceof TForAll) {
+ t = Types.canonical( ((TForAll)t).type );
+ ++count;
+ }
+ }
+ TVar[] boundVars = Arrays.copyOf(oldBoundVars, oldBoundVars.length + count);
+ boundVars[oldBoundVars.length] = var;
+ TForAll t = this;
+ {
+ for(int i=1;i<count;++i) {
+ t = (TForAll)Types.canonical(t.type);
+ boundVars[oldBoundVars.length + i] = t.var;
+ }
+ }
+
+ for(int i=0;i<count;++i)
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
+ return t.type.skeletonHashCode(hash, boundVars);
+ }
+
public Type getCanonicalType() {
if(type instanceof TMetaVar)
type = type.canonical();
@Override
public Kind getKind(Environment context) {
return Kinds.STAR;
+ }
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ return new Type[] { Skeletons.canonicalSkeleton(type) };
}
}
return hash;
}
+ @Override
+ public int skeletonHashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.skeletonHashCode(hash);
+ hash = range.skeletonHashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.skeletonHashCode(hash, boundVars);
+ hash = range.skeletonHashCode(hash, boundVars);
+ return hash;
+ }
+
public Type getCanonicalDomain() {
if(domain instanceof TMetaVar)
domain = domain.canonical();
public Kind getKind(Environment context) {
return Kinds.STAR;
}
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ return new Type[] {Skeletons.canonicalSkeleton(domain), Skeletons.canonicalSkeleton(range)};
+ }
}
return ref.toTypeAst(context);
}
- @Override
- public int hashCode() {
- if(ref == null)
- return System.identityHashCode(this);
- else
- return ref.hashCode();
- }
-
@Override
public void updateHashCode(TypeHashCodeContext context) {
if(ref == null)
}
public void setRef(Type type) throws UnificationException {
+ if(type instanceof TMetaVar && ((TMetaVar)type).ref != null)
+ throw new InternalCompilerError("Not canonical!");
+ if(type == this)
+ throw new InternalCompilerError("Illegal setRef");
if(DEBUG)
System.out.println("setRef " + System.identityHashCode(this) + " -> " + type);
if(ref != null)
fireNotifyAboutChange();
}
+ @Override
+ public int hashCode() {
+ if(ref == null)
+ return System.identityHashCode(this);
+ else
+ return ref.hashCode();
+ }
+
@Override
public int hashCode(int hash) {
if(ref == null)
return ref.hashCode(hash, boundVars);
}
+ @Override
+ public int skeletonHashCode() {
+ if(ref != null)
+ return ref.skeletonHashCode();
+ else if(skeletonRef != null)
+ return skeletonRef.skeletonHashCode();
+ else
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public int skeletonHashCode(int hash) {
+ if(ref != null)
+ return ref.skeletonHashCode(hash);
+ else if(skeletonRef != null)
+ return skeletonRef.skeletonHashCode(hash);
+ else
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ if(ref != null)
+ return ref.skeletonHashCode(hash, boundVars);
+ else if(skeletonRef != null)
+ return skeletonRef.skeletonHashCode(hash, boundVars);
+ else
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
@Override
public boolean equalsCanonical(Type other) {
return this == other;
public Kind getKind(Environment context) {
return kind;
}
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ // Assumes that this is already canonical skeleton
+ return EMPTY_ARRAY;
+ }
}
hash = parameter.hashCode(hash, boundVars);
return hash;
}
+
+ @Override
+ public int skeletonHashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, PRED_HASH);
+ hash = typeClass.skeletonHashCode(hash);
+ for(Type parameter : parameters)
+ hash = parameter.skeletonHashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, PRED_HASH);
+ hash = typeClass.skeletonHashCode(hash, boundVars);
+ for(Type parameter : parameters)
+ hash = parameter.skeletonHashCode(hash, boundVars);
+ return hash;
+ }
@Override
public boolean equalsCanonical(Type other) {
public Kind getKind(Environment context) {
return Kinds.STAR;
}
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ Type[] result = new Type[parameters.length];
+ for(int i=0;i<parameters.length;++i)
+ result[i] = Skeletons.canonicalSkeleton(parameters[i]);
+ return result;
+ }
}
return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
}
+ @Override
+ public int skeletonHashCode(int hash) {
+ int sum = UNION_HASH;
+ for(Type effect : effects)
+ sum += effect.skeletonHashCode(HashCodeUtils.SEED);
+ return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ int sum = UNION_HASH;
+ for(Type effect : effects)
+ sum += effect.skeletonHashCode(HashCodeUtils.SEED, boundVars);
+ return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
+ }
+
@Override
public boolean equalsCanonical(Type other) {
if(this == other)
public Kind getKind(Environment context) {
return Kinds.EFFECT;
}
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ return EMPTY_ARRAY;
+ }
}
return this == obj;
}
- @Override
- public int hashCode() {
- return System.identityHashCode(this);
- }
-
@Override
public void updateHashCode(TypeHashCodeContext context) {
TObjectIntHashMap<TVar> varHashCode = context.getVarHashCode();
return this;
}
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
@Override
public int hashCode(int hash) {
return HashCodeUtils.update(hash, System.identityHashCode(this));
return HashCodeUtils.update(hash, System.identityHashCode(this));
}
+ @Override
+ public int skeletonHashCode() {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public int skeletonHashCode(int hash) {
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ for(int i=0;i<boundVars.length;++i)
+ if(boundVars[i] == this) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, BOUND_VAR_HASH);
+ return HashCodeUtils.update(hash, i);
+ }
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
@Override
public boolean equalsCanonical(Type other) {
return this == other;
public Kind getKind(Environment context) {
return kind;
}
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ return EMPTY_ARRAY;
+ }
}
public abstract void updateHashCode(TypeHashCodeContext context);
public abstract int hashCode(int hash);
public abstract int hashCode(int hash, TVar[] boundVars);
+
+ public int skeletonHashCode() {
+ return skeletonHashCode(HashCodeUtils.SEED);
+ }
+
+ public abstract int skeletonHashCode(int hash);
+ public abstract int skeletonHashCode(int hash, TVar[] boundVars);
public abstract void collectFreeVars(ArrayList<TVar> vars);
public abstract Kind getKind(Environment context);
+ public abstract Type[] skeletonCanonicalChildren();
+
}
\ No newline at end of file
public static final TCon ORDERED_RING = con("Prelude", "OrderedRing");
public static final TCon REAL = con("Prelude", "Real");
public static final TCon SHOW = con("Prelude", "Show");
- public static final TCon EQ = con("Prelude", "Eq");
public static final TCon ORD = con("Prelude", "Ord");
- public static final TCon HASHABLE = con("Prelude", "Hashable");
public static final TCon IO = con("Serialization", "IO");
public static final Type REF = con("Prelude", "Ref");
else
return new TUnion(effects);
}
+
+ public static Type union(Type effect1, Type effect2) {
+ return new TUnion(effect1, effect2);
+ }
public static Type union(List<Type> effects) {
if(effects.size() == 0)
--- /dev/null
+package org.simantics.scl.compiler.types.util;\r
+\r
+import org.simantics.scl.compiler.types.Skeletons;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+public class SkeletonKeyMap<T> extends THashMap<Type,T> {\r
+ @Override\r
+ protected int hash(Object notnull) {\r
+ return ((Type)notnull).hashCode();\r
+ }\r
+ \r
+ @Override\r
+ protected boolean equals(Object notnull, Object two) {\r
+ return Skeletons.equalSkeletons((Type)notnull, (Type)two);\r
+ }\r
+}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class ActiveTests extends TestBase {
-
- public ActiveTests() { super("scl"); }
-/*
- @Test public void Equations1() { test(); }
- @Test public void MarketModel2() { test(); }
- @Test public void Overloading2() { test(); }
- @Test public void Overloading3() { test(); }
- //@Ignore
- @Test public void PatternError() { test(); }
- @Test public void Serialization() { test(); }
- @Ignore
- @Test public void TypeClass2() { test(); }
- @Test public void TypeClassBug2() { test(); }
- */
-
- //@Test public void CityoptSetup() { test(); }
- @Test public void EmptyLet() { test(); }
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;\r
-\r
-import java.lang.reflect.Method;\r
-\r
-import org.objectweb.asm.ClassWriter;\r
-import org.objectweb.asm.MethodVisitor;\r
-import org.objectweb.asm.Opcodes;\r
-\r
-public class FindAllowedChars {\r
- public static class MyClassLoader extends ClassLoader {\r
- final String className;\r
- final byte[] classBytes;\r
- \r
- public MyClassLoader(ClassLoader parent, String className, byte[] classBytes) {\r
- super(parent);\r
- this.className = className;\r
- this.classBytes = classBytes;\r
- }\r
- \r
- public MyClassLoader(String className, byte[] classBytes) {\r
- this.className = className;\r
- this.classBytes = classBytes;\r
- }\r
-\r
- @Override\r
- protected Class<?> findClass(String name) throws ClassNotFoundException {\r
- if(name.equals(name))\r
- return defineClass(name, classBytes, 0, classBytes.length);\r
- else\r
- return super.findClass(name);\r
- }\r
- }\r
- \r
- public static void test(String className, String methodName) throws Exception {\r
- ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);\r
- classWriter.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);\r
- \r
- MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, methodName, "()V", null, null);\r
- /*methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");\r
- methodVisitor.visitLdcInsn("Hello world!");\r
- methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);*/\r
- methodVisitor.visitInsn(Opcodes.RETURN);\r
- methodVisitor.visitMaxs(0, 0);\r
- methodVisitor.visitEnd();\r
- classWriter.visitEnd();\r
- \r
- ClassLoader loader = new MyClassLoader(className, classWriter.toByteArray());\r
- Class<?> clazz = loader.loadClass(className);\r
- Method method = clazz.getMethod(methodName);\r
- method.invoke(null);\r
- }\r
- \r
- public static void main(String[] args) throws Exception {\r
- for(int a=Character.MIN_VALUE;a<Character.MAX_VALUE;++a) {\r
- //for(char b=0;b<256;++b) {\r
- String name = new String(new char[] {(char)a});\r
- try {\r
- test(name, "test");\r
- } catch(Throwable e) {\r
- System.out.println(name + " (" + a + ")");\r
- }\r
- //} \r
- }\r
- System.out.println((int)Character.MAX_VALUE);\r
- }\r
-}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.AfterClass;
-import org.junit.Test;
-import org.simantics.scl.compiler.errors.Failable;
-import org.simantics.scl.compiler.module.Module;
-import org.simantics.scl.compiler.module.coverage.CoverageUtils;
-import org.simantics.scl.compiler.module.coverage.ModuleCoverage;
-import org.simantics.scl.compiler.top.ValueNotFound;
-import org.simantics.scl.runtime.profiling.BranchPoint;
-
-public class ModuleRegressionTests extends TestBase {
-
- public ModuleRegressionTests() { super("scl"); }
-
- @Test public void AmbiguousType() { test(); }
- @Test public void ApplicationOfNunfunction() { test(); }
- @Test public void Arity1() { test(); }
- @Test public void AsPattern() { test(); }
- @Test public void BigContext() { test(); }
- @Test public void BigFunction() { test(); }
- @Test public void BinaryOperators1() { test(); }
- @Test public void BooleanId() { test(); }
- @Test public void Bug4450() { test(); }
- @Test public void Character1() { test(); }
- @Test public void ClashingClass() { test(); }
- @Test public void ClashingData() { test(); }
- @Test public void ClashingInstance() { test(); }
- @Test public void ClashingValueType() { test(); }
- @Test public void Collaz() { test(); }
- @Test public void Compose() { test(); }
- @Test public void Composition() { test(); }
- @Test public void ConjunctionMacro() { test(); }
- @Test public void Constant() { test(); }
- @Test public void ConstructorNameClash() { test(); }
- @Test public void DefaultMethods1() { test(); }
- @Test public void Deriving3() { test(); }
- @Test public void Deriving4() { test(); }
- @Test public void DifferentBranchTypes() { test(); }
- @Test public void Div() { test(); }
- @Test public void DoubleConversion() { test(); }
- @Test public void DoubleEffect() { test(); }
- @Test public void Effects1() { test(); }
- @Test public void Effects2() { test(); }
- @Test public void Effects3() { test(); }
- @Test public void Effects4() { test(); }
- @Test public void Effects5() { test(); }
- @Test public void Effects6() { test(); }
- @Test(expected=ValueNotFound.class)
- public void EmptyModule() throws ValueNotFound {
- test(new String[]{"EmptyModule"}, new String[]{""});
- }
- @Test public void Equality() { test(); }
- @Test public void ExistentialData() { test(); }
- @Test public void ExistentialData2() { test(); }
- @Test public void ExpressionParsing() { test(); }
- @Test public void FaultyRecursion() { test(); }
- @Test public void Fibonacci() { test(); }
- @Test public void Fibonacci2() { test(); }
- @Test public void Fibonacci3() { test(); }
- @Test public void FingerTree() { test(); }
- @Test public void FoldMissingInitialValue() { test(); }
- @Test public void FoldlBuild1() { test(); }
- @Test public void FoldlBuild2() { test(); }
- @Test public void Forall1() { test(); }
- @Test public void Forall2() { test(); }
- @Test public void Forall3() { test(); }
- @Test public void Formula() { test(); }
- @Test public void FromDynamic() { test(); }
- @Test public void FromDynamic2() { test(); }
- @Test public void FromDynamic3() { test(); }
- @Test public void FromDynamic4() { test(); }
- @Test public void FromDynamic5() { test(); }
- @Test public void FunctionFunctor() { test(); }
- @Test public void Functor() { test(); }
- @Test public void FunctorM1() { test(); }
- @Test public void Generalization() { test(); }
- @Test public void GenericMutualRecursion() { test(); }
- @Test public void GlobalVariables() { test(); }
- @Test public void GuardedExpressionBug() { test(); }
- @Test public void Guards1() { test(); }
- @Test public void Guards2() { test(); }
- @Test public void IdAsOperator() { test(); }
- @Test public void IllegalChar() { test(); }
- @Test public void ImportJavaConstructor() { test(); }
- @Test public void ImportRef() { test(); }
- @Test public void InconsistentArity() { test(); }
- @Test public void InconsistentIndentation() { test(); }
- @Test public void IndentationAndParenthesis() { test(); }
- @Test public void Index() { test(); }
- @Test public void Inline1() { test(); }
- @Test public void InstanceHierarchy() { test(); }
- @Test public void InstanceIsTypoedAsClass() { test(); }
- @Test public void InvalidClass1() { test(); }
- @Test public void InvalidEncoding() { test(); }
- @Test public void InvalidInstance1() { test(); }
- @Test public void InvalidJavaTypeAnnotation() { test(); }
- @Test public void InvalidKinds() { test(); }
- @Test public void InvalidKinds2() { test(); }
- @Test public void InvalidKinds3() { test(); }
- @Test public void InvalidLambda() { test(); }
- @Test public void InvalidModule() { test(); }
- @Test public void InvalidPattern1() { test(); }
- @Test public void InvalidPattern2() { test(); }
- @Test public void InvalidPattern3() { test(); }
- @Test public void InvalidPattern4() { test(); }
- @Test public void InvalidTypeClassInstance1() { test(); }
- @Test public void JavaAccess1() { test(); }
- @Test public void JavaConstructors() { test(); }
- @Test public void JavaMethods() { test(); }
- @Test public void JavaTypes() { test(); }
- @Test public void Kinds1() { test(); }
- @Test public void Lambda() { test(); }
- @Test public void Layout1() { test(); }
- @Test public void List() { test(); }
- @Test public void ListError1() { test(); }
- @Test public void ListError2() { test(); }
- @Test public void ListSyntax() { test(); }
- @Test public void ListSyntax10() { test(); }
- @Test public void ListSyntax11() { test(); }
- @Test public void ListSyntax12() { test(); }
- @Test public void ListSyntax2() { test(); }
- @Test public void ListSyntax3() { test(); }
- @Test public void ListSyntax4() { test(); }
- @Test public void ListSyntax5() { test(); }
- @Test public void ListSyntax6() { test(); }
- @Test public void ListSyntax7() { test(); }
- @Test public void ListSyntax8() { test(); }
- @Test public void ListSyntax9() { test(); }
- @Test public void ListSyntaxWithoutPrelude() { test(); }
- @Test public void LocalDefinitions() { test(); }
- @Test public void LocalDefinitions2() { test(); }
- @Test public void LocalDefinitions3() { test(); }
- @Test public void LocalDefinitions4() { test(); }
- @Test public void LocalDefinitions5() { test(); }
- @Test public void Macros1() { test(); }
- @Test public void Macros2() { test(); }
- @Test public void Macros4() { test(); }
- @Test public void Map1() { test(); }
- @Test public void MarketModel() { test(); }
- @Test public void Matching() { test(); }
- @Test public void Matching2() { test(); }
- @Test public void Matching4() { test(); }
- @Test public void Matching5() { test(); }
- @Test public void MatchingWithMissingParameter() { test(); }
- @Test public void MatchingWithoutTypeAnnotations() { test(); }
- @Test public void MaximumBy() { test(); }
- @Test public void Maybe1() { test(); }
- @Test public void Maybe2() { test(); }
- @Test public void Maybe3() { test(); }
- @Test public void Maybe4() { test(); }
- @Test public void MissingEffect() { test(); }
- @Test public void MissingMethod() { test(); }
- @Test public void ModuleInitialization() { test(); }
- @Test public void MonadBug1() { test(); }
- @Test public void MonadSyntax1() { test(); }
- @Test public void Monads1() { test(); }
- @Test public void NoDefinitionErrorMessage() { test(); }
- @Test public void NoInstance() { test(); }
- @Test public void NoInstance2() { test(); }
- @Test public void NonassociativeOperator() { test(); }
- @Test public void NonexistentTypeClassInAnnotation() { test(); }
- @Test public void NonexistingEffect() { test(); }
- @Test public void OneLineMatch() { test(); }
- @Test public void OpenString1() { test(); }
- @Test public void OpenString2() { test(); }
- @Test public void OverloadedArithmetic1() { test(); }
- @Test public void OverloadedArithmetic2() { test(); }
- @Test public void OverloadedArithmetic3() { test(); }
- @Test public void OverloadedLiterals2() { test(); }
- @Test public void Overloading1() { test(); }
- @Test public void Parsing() { test(); }
- @Test public void PolymorphicRecursion() { test(); }
- @Test public void PolymorphicRecursion2() { test(); }
- @Test public void Polynomials() { test(); }
- @Test public void PrecedenceOfNonoperators() { test(); }
- @Test public void Primes() { test(); }
- @Test public void Proc1() { test(); }
- @Test public void Proc2() { test(); }
- @Test public void Proc3() { test(); }
- @Test public void Pythagoras() { test(); }
- @Test public void Random1() { test(); }
- @Test public void RangeSyntax() { test(); }
- @Test public void Record1() { test(); }
- @Test public void RecordShorthand() { test(); }
- @Test public void RecursiveContext() { test(); }
- @Test public void RecursiveValues2() { test(); }
- @Test public void RecursiveValues3() { test(); }
- @Test public void RecursiveValues4() { test(); }
- @Test public void RedBlackTrees() { test(); }
- @Test public void Relations1() { test(); }
- @Test public void Relations2() { test(); }
- @Test public void RepeatedVariableInPattern() { test(); }
- @Test public void SSATypingBug() { test(); }
- @Test public void Scanl() { test(); }
- @Test public void Search() { test(); }
- @Test public void Sections() { test(); }
- @Test public void Select1() { test(); }
- @Test public void Select2() { test(); }
- @Test public void Select3() { test(); }
- @Test public void Select4() { test(); }
- @Test public void Select5() { test(); }
- @Test public void Select6() { test(); }
- @Test public void Select7() { test(); }
- @Test public void Select8() { test(); }
- @Test public void Select9() { test(); }
- @Test public void SelfReferringContextInTypeClass() { test(); }
- @Test public void Serialization2() { test(); }
- @Test public void Serialization3() { test(); }
- @Test public void SharedTypeVariable() { test(); }
- @Test public void ShortcutFusion() { test(); }
- @Test public void Show1() { test(); }
- @Test public void SinConst1() { test(); }
- @Test public void Sort() { test(); }
- @Test public void Sort2() { test(); }
- @Test public void StreamFusion() { test(); }
- @Test public void StringEscape() { test(); }
- @Test public void StringInterpolation1() { test(); }
- @Test public void StringMatching1() { test(); }
- @Test public void SumOfInverses2() { test(); }
- @Test public void TooManyParametersToSin() { test(); }
- @Test public void Transformation1() { test(); }
- @Test public void Transformation2() { test(); }
- @Test public void Transformation3() { test(); }
- @Test public void Transformation4() { test(); }
- @Test public void Transformation5() { test(); }
- @Test public void Transformation6() { test(); }
- @Test public void Transformation7() { test(); }
- @Test public void TransformationOrder() { test(); }
- @Test public void Tuples() { test(); }
- @Test public void Tuples2() { test(); }
- @Test public void TypeAlias1() { test(); }
- @Test public void TypeAlias2() { test(); }
- @Test public void TypeAlias3() { test(); }
- @Test public void TypeAliasRefsToTypeAlias() { test(); }
- @Test public void TypeAnnotation1() { test(); }
- @Test public void TypeAnnotation2() { test(); }
- @Test public void TypeClass() { test(); }
- @Test public void TypeClassBug1() { test(); }
- @Test(timeout=1000L) public void TypeInferenceBug2() { test(); }
- @Test public void TypeOf1() { test(); }
- @Test public void TypingBug1() { test(); }
- @Test public void TypingError1() { test(); }
- @Test public void TypingError2() { test(); }
- @Test public void UnaryMinus() { test(); }
- @Test public void UndefinedValue() { test(); }
- @Test public void UnexpectedToken() { test(); }
- @Test public void Unification1() { test(); }
- @Test public void UnknownAnnotation() { test(); }
- @Test public void UnresolvedClass() { test(); }
- @Test public void UnresolvedTypeInAnnotation() { test(); }
- @Test public void UnresolvedTypeInInstance() { test(); }
- @Test public void UnresolvedVariable() { test(); }
- @Test public void UnresolvedVariable2() { test(); }
- @Test public void ValueAsOperator() { test(); }
- @Test public void ValueConversion() { test(); }
- @Test public void Vector1() { test(); }
- @Test public void Vector2() { test(); }
- @Test public void Void1() { test(); }
- @Test public void Void2() { test(); }
- @Test public void Void3() { test(); }
- @Test public void While() { test(); }
- @Test public void While2() { test(); }
- @Test public void While3() { test(); }
- @Test public void WrongDefaultMethod() { test(); }
- @Test public void WrongInstanceMethod() { test(); }
-
- @AfterClass
- public static void checkCoverage() {
- Failable<Module> maybeModule = PRELUDE_MODULE_REPOSITORY.getModule("Prelude");
- if(!maybeModule.didSucceed())
- return;
- Module module = maybeModule.getResult();
- ModuleCoverage coverage = CoverageUtils.getCoverage(module);
- if(coverage == null)
- return;
- coverage.print(System.out);
- printCoverageTree(module.getBranchPoints().get("lookup"), 0);
- }
-
- private static void printCoverageTree(BranchPoint[] branchPoints, int ind) {
- for(BranchPoint bp : branchPoints) {
- for(int i=0;i<ind;++i)
- System.out.print(" ");
- System.out.println(bp.getCodeSize());
- printCoverageTree(bp.getChildren(), ind+1);
- }
- }
-
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-
-@RunWith(Suite.class)
-@SuiteClasses({
- ModuleRegressionTests.class,
- TestExpressionEvaluator.class,
- TestCommandSession.class
-})
-public class RegressionTests {
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.nio.charset.Charset;
-
-import org.junit.Before;
-import org.simantics.scl.compiler.commands.CommandSession;
-import org.simantics.scl.compiler.commands.TestScriptExecutor;
-import org.simantics.scl.compiler.module.repository.ModuleRepository;
-import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
-import org.simantics.scl.compiler.source.repository.SourceRepositories;
-
-public class ScriptTestBase {
-
- private final String path;
-
- ModuleRepository moduleRepository;
-
- public ScriptTestBase(String path) {
- this.path = path;
- }
-
- @Before
- public void initialize() throws Exception {
- moduleRepository = new ModuleRepository(
- new CompositeModuleSourceRepository(
- SourceRepositories.BUILTIN_SOURCE_REPOSITORY,
- SourceRepositories.PRELUDE_SOURCE_REPOSITORY
- ));
- }
-
- protected void test() throws Exception {
- String testScriptName = Thread.currentThread().getStackTrace()[2].getMethodName();
- String testPath = "scripts/" + testScriptName + ".sts";
-
- CommandSession session = new CommandSession(moduleRepository, null);
- new TestScriptExecutor(session,
- new BufferedReader(
- new InputStreamReader(getClass().getResourceAsStream(testPath), Charset.forName("UTF-8"))),
- null)
- .execute();
- }
-
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.Test;
-
-public class ScriptTests extends ScriptTestBase {
-
- public ScriptTests() {
- super("scripts");
- }
-
- @Test public void Arithmetic() throws Exception { test(); }
- @Test public void Functions() throws Exception { test(); }
- @Test public void Functions2() throws Exception { test(); }
- @Test public void Lists() throws Exception { test(); }
-
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-import org.simantics.scl.compiler.tests.unit.TestSubSolver;
-
-@RunWith(Suite.class)
-@SuiteClasses({
- RegressionTests.class,
-
- ActiveTests.class,
- UnimplementedTests.class,
- ScriptTests.class,
-
- TestSubSolver.class
-})
-public class TestAll {
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.regex.Pattern;
-
-import org.junit.Assert;
-import org.simantics.scl.compiler.errors.Failable;
-import org.simantics.scl.compiler.errors.Failure;
-import org.simantics.scl.compiler.module.ImportDeclaration;
-import org.simantics.scl.compiler.module.Module;
-import org.simantics.scl.compiler.module.repository.ModuleRepository;
-import org.simantics.scl.compiler.module.repository.UpdateListener;
-import org.simantics.scl.compiler.source.ModuleSource;
-import org.simantics.scl.compiler.source.StringModuleSource;
-import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
-import org.simantics.scl.compiler.source.repository.MapModuleSourceRepository;
-import org.simantics.scl.compiler.source.repository.SourceRepositories;
-import org.simantics.scl.compiler.top.ValueNotFound;
-
-public class TestBase {
-
- public static final ModuleRepository PRELUDE_MODULE_REPOSITORY = new ModuleRepository(
- new CompositeModuleSourceRepository(
- SourceRepositories.BUILTIN_SOURCE_REPOSITORY,
- SourceRepositories.PRELUDE_SOURCE_REPOSITORY
- ));
- private static final Pattern TEST_SEPARATOR = Pattern.compile("^--+ *$", Pattern.MULTILINE);
- private static final Charset UTF8 = Charset.forName("UTF-8");
-
- String path;
-
- public TestBase(String path) {
- this.path = path;
- }
-
- protected void test() {
- String testModuleName = Thread.currentThread().getStackTrace()[2].getMethodName();
- String testPath = path + "/" + testModuleName + ".scl";
-
- try {
- String[] testParts = readTestParts(testPath);
-
- int j=0;
- ArrayList<String> auxModuleNameList = new ArrayList<String>();
- while(j < testParts.length) {
- String part = testParts[j];
- if(part.startsWith("// module "))
- auxModuleNameList.add(part.substring(10).split("\\n", 2)[0].trim());
- else
- break;
- ++j;
- }
- int mainId = j;
- String[] moduleNames = new String[mainId+1];
- String[] moduleTexts = new String[mainId+1];
- for(int i=0;i<mainId;++i) {
- moduleNames[i] = auxModuleNameList.get(i);
- moduleTexts[i] = testParts[i];
- }
- moduleNames[mainId] = testModuleName;
-
- for(;j<testParts.length;j+=2) {
- moduleTexts[mainId] = testParts[j];
- String expectedOutput = j+1<testParts.length ? testParts[j+1] : "";
- String actualOutput = test(moduleNames, moduleTexts);
- Assert.assertEquals(
- canonicalizeOutput(expectedOutput),
- canonicalizeOutput(actualOutput));
- }
- } catch(IOException e) {
- throw new RuntimeException(e);
- } catch (ValueNotFound e) {
- throw new RuntimeException(e);
- }
- }
-
- private static String canonicalizeOutput(String text) {
- return text.trim().replace("\r\n", "\n");
- }
-
- protected String test(String[] moduleNames, String[] moduleTexts) throws ValueNotFound {
- if(moduleNames.length != moduleTexts.length)
- throw new IllegalArgumentException();
- /*for(int i=0;i<moduleNames.length;++i) {
- System.out.println("-- " + moduleNames[i] + " --");
- System.out.println(moduleTexts[i]);
- }*/
-
- ModuleSource[] moduleSources = new ModuleSource[moduleNames.length];
- for(int i=0;i<moduleNames.length;++i)
- moduleSources[i] = new StringModuleSource(
- moduleNames[i], getClass().getClassLoader(), moduleTexts[i]) {
- @Override
- protected ImportDeclaration[] getBuiltinImports(UpdateListener listener) {
- return ImportDeclaration.ONLY_BUILTINS;
- }
- };
- ModuleRepository testEnvironment = new ModuleRepository(
- PRELUDE_MODULE_REPOSITORY,
- new MapModuleSourceRepository(moduleSources));
- int lastId = moduleNames.length-1;
- Failable<Module> result = testEnvironment.getModule(moduleNames[lastId]);
- if(!result.didSucceed())
- return ((Failure)result).toString(moduleTexts[lastId]);
- else {
- Object main = testEnvironment.getRuntimeModule(moduleNames[lastId]).getResult().getValue("main");
- return String.valueOf(main);
- }
- }
-
- private String[] readTestParts(String testPath) throws IOException {
- InputStream stream = getClass().getResourceAsStream(testPath);
- try {
- byte[] buffer = new byte[1024];
- int pos = 0;
- while(true) {
- int c = stream.read(buffer, pos, buffer.length-pos);
- if(c <= 0)
- break;
- pos += c;
- if(pos < buffer.length)
- break;
- buffer = Arrays.copyOf(buffer, pos*2);
- }
- String text = new String(buffer, 0, pos, UTF8);
- String[] result = TEST_SEPARATOR.split(text);
- for(int i=1;i<result.length;++i) {
- if(result[i].startsWith("\r\n"))
- result[i] = result[i].substring(2);
- if(result[i].startsWith("\n") || result[i].startsWith("\r"))
- result[i] = result[i].substring(1);
- }
- return result;
- } finally {
- stream.close();
- }
- }
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;\r
-\r
-import org.junit.Test;\r
-import org.simantics.scl.compiler.elaboration.java.Builtins;\r
-import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
-import org.simantics.scl.compiler.module.ImportDeclaration;\r
-import org.simantics.scl.compiler.module.repository.ModuleRepository;\r
-import org.simantics.scl.compiler.module.repository.UpdateListener;\r
-import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
-import org.simantics.scl.compiler.source.PrecompiledModuleSource;\r
-import org.simantics.scl.compiler.source.StringModuleSource;\r
-import org.simantics.scl.compiler.source.repository.MapModuleSourceRepository;\r
-import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;\r
-import org.simantics.scl.compiler.top.ExpressionEvaluator;\r
-\r
-import junit.framework.Assert;\r
-\r
-public class TestClassNaming {\r
-\r
- private static class SimpleModuleSource extends StringModuleSource {\r
- public SimpleModuleSource(String moduleName, String moduleText) {\r
- super(moduleName, moduleText);\r
- }\r
- \r
- @Override\r
- protected ImportDeclaration[] getBuiltinImports(UpdateListener listener) {\r
- return new ImportDeclaration[] {new ImportDeclaration("Builtin", "")};\r
- }\r
- }\r
- \r
- @Test\r
- public void testClassNaming() throws Exception {\r
- ModuleSourceRepository sourceRepository = new MapModuleSourceRepository(\r
- new PrecompiledModuleSource(Builtins.INSTANCE),\r
- new SimpleModuleSource("http://ProjectGame@A/SCLConstants",\r
- "locale = \"fi-FI\"")\r
- );\r
- ModuleRepository moduleRepository = new ModuleRepository(sourceRepository);\r
- RuntimeEnvironment runtimeEnvironment = moduleRepository.createRuntimeEnvironment(\r
- EnvironmentSpecification.of(\r
- "http://ProjectGame@A/SCLConstants", ""),\r
- getClass().getClassLoader());\r
- Assert.assertEquals("fi-FI", new ExpressionEvaluator(runtimeEnvironment, "locale").eval());\r
- }\r
- \r
-}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests;\r
-\r
-import java.io.Reader;\r
-import java.io.StringReader;\r
-\r
-import org.junit.Test;\r
-import org.simantics.scl.compiler.internal.parsing.parser.SCLParser;\r
-import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;\r
-\r
-public class TestCommandParsing {\r
- @Test\r
- public void testCommandParsing() throws Exception {\r
- Reader reader = new StringReader("import \"asdasd\";a = 1\nb = 2");\r
- SCLParser parser = new SCLParserImpl(reader) {\r
- @Override\r
- protected Object reduceStatementCommand() {\r
- System.out.println("statement " + get(0));\r
- return null;\r
- }\r
- \r
- @Override\r
- protected Object reduceImport() {\r
- System.out.println("import " + get(0));\r
- return null;\r
- }\r
- };\r
- parser.parseCommands();\r
- }\r
-}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.simantics.scl.compiler.commands.CommandSession;
-import org.simantics.scl.compiler.module.repository.ModuleRepository;
-import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
-import org.simantics.scl.compiler.source.repository.SourceRepositories;
-import org.simantics.scl.runtime.reporting.AbstractSCLReportingHandler;
-import org.simantics.scl.runtime.reporting.SCLReportingHandler;
-
-public class TestCommandSession {
-
- ModuleRepository moduleRepository;
-
- @Before
- public void initialize() throws Exception {
- moduleRepository = new ModuleRepository(
- new CompositeModuleSourceRepository(
- SourceRepositories.BUILTIN_SOURCE_REPOSITORY,
- SourceRepositories.PRELUDE_SOURCE_REPOSITORY
- ));
- }
-
- private static class SCLErrorMessageException extends RuntimeException {
- private static final long serialVersionUID = 418954639267697065L;
- public SCLErrorMessageException(String message) {
- super(message);
- }
- }
-
- private static final SCLReportingHandler TEST_HANDLER = new AbstractSCLReportingHandler() {
- @Override
- public void print(String text) {
- System.out.println(text);
- }
-
- public void printError(String error) {
- System.err.println(error);
- throw new SCLErrorMessageException(error);
- }
- };
-
- @Test
- public void testCommandSession() {
- CommandSession session = new CommandSession(moduleRepository, TEST_HANDLER);
-
- session.execute("a = 1");
- session.execute("b = 2");
- session.execute("a + b");
-
- session.execute("x = 1\ny = 2");
- session.execute("x + y");
- }
-
- @Test
- public void testCommandSession2() {
- CommandSession session = new CommandSession(moduleRepository, TEST_HANDLER);
-
- session.execute("f name coords = print \"\\(name :: String) \\(coords :: (Double, Double))\"");
- session.execute("g name (x,y) = f name (x,y)");
- }
-
- @Test
- public void testTyping1() {
- CommandSession session = new CommandSession(moduleRepository, TEST_HANDLER);
-
- session.execute("apply f = f ()");
- session.execute("printHello () = print \"Hello\"");
- session.execute("apply printHello");
- }
-
- @Test
- public void testTyping2() {
- CommandSession session = new CommandSession(moduleRepository, TEST_HANDLER);
-
- session.execute("iter f (list :: [a]) = loop 0 where { len = length list ; loop i | i == len = 0 | otherwise = do f (list!i) ; loop (i+1) }");
- session.execute("iter (\\i -> print i) [1,2,3]");
- session.execute("iter (\\i -> print i) [(),(),()]");
- }
-
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import java.util.Arrays;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.simantics.scl.compiler.elaboration.expressions.EVariable;
-import org.simantics.scl.compiler.elaboration.expressions.Expression;
-import org.simantics.scl.compiler.elaboration.expressions.Variable;
-import org.simantics.scl.compiler.environment.AbstractLocalEnvironment;
-import org.simantics.scl.compiler.environment.Environment;
-import org.simantics.scl.compiler.environment.LocalEnvironment;
-import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
-import org.simantics.scl.compiler.errors.CompilationErrorFormatter;
-import org.simantics.scl.compiler.module.repository.ImportFailure;
-import org.simantics.scl.compiler.module.repository.ImportFailureException;
-import org.simantics.scl.compiler.module.repository.ModuleRepository;
-import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
-import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
-import org.simantics.scl.compiler.source.repository.SourceRepositories;
-import org.simantics.scl.compiler.top.ExpressionEvaluator;
-import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
-import org.simantics.scl.compiler.types.Type;
-import org.simantics.scl.compiler.types.Types;
-import org.simantics.scl.runtime.function.Function;
-import org.simantics.scl.runtime.tuple.Tuple0;
-
-import junit.framework.Assert;
-
-public class TestExpressionEvaluator {
-
- public static final boolean TIMING = false;
- public static final int COUNT = 10000;
-
- ModuleRepository moduleRepository;
-
- RuntimeEnvironment runtimeEnvironment;
-
- @Before
- public void initialize() throws Exception {
- moduleRepository = new ModuleRepository(
- new CompositeModuleSourceRepository(
- SourceRepositories.BUILTIN_SOURCE_REPOSITORY,
- SourceRepositories.PRELUDE_SOURCE_REPOSITORY
- ));
-
- // Environment for compiling expressions
- EnvironmentSpecification environmentSpecification = new EnvironmentSpecification();
- environmentSpecification.importModule("Builtin", "");
- environmentSpecification.importModule("Prelude", "");
-
- try {
- runtimeEnvironment = moduleRepository.createRuntimeEnvironment(environmentSpecification,
- getClass().getClassLoader());
- } catch(ImportFailureException e) {
- for(ImportFailure failure : e.failures)
- System.err.println("Failed to import " + failure.moduleName);
- throw e;
- }
- }
-
- private void testExpression0(String expressionText,
- Object expectedValue,
- Type expectedType) throws Exception {
- // Compiling and running expression
- try {
- Object result = new ExpressionEvaluator(runtimeEnvironment, expressionText)
- .expectedType(expectedType)
- .eval();
- if(expectedValue != null)
- Assert.assertEquals(expectedValue, result);
- } catch(SCLExpressionCompilationException e) {
- System.out.println(CompilationErrorFormatter.toString(expressionText, e.getErrors()));
- throw e;
- }
- }
-
- private void testExpression(String expressionText,
- Object expectedValue,
- Type expectedType) throws Exception {
- if(TIMING) {
- System.out.println(expressionText);
- long beginTime = System.nanoTime();
- for(int i=0;i<COUNT;++i)
- testExpression0(expressionText, expectedValue, expectedType);
- long endTime = System.nanoTime();
- System.out.println( " " + (endTime-beginTime)*1e-6/COUNT + " ms");
- }
- else
- testExpression0(expressionText, expectedValue, expectedType);
- }
-
- @Test
- public void testExpressionCompiler() throws Exception {
- testExpression("1",
- Integer.valueOf(1),
- Types.INTEGER);
- testExpression("1+2",
- Integer.valueOf(3),
- Types.INTEGER);
- testExpression("map (\\(_,x) -> x) [(1,2),(2,3)]",
- Arrays.asList(2.0, 3.0),
- Types.list(Types.DOUBLE));
- testExpression("map (\\x -> snd x) [(1,2),(2,3)]",
- Arrays.asList(2.0, 3.0),
- Types.list(Types.DOUBLE));
- testExpression("let f x = x+1 in (f . f . f) 3",
- Double.valueOf(6.0),
- Types.DOUBLE);
- if(!TIMING)
- testExpression("print \"Hello world!\"",
- Tuple0.INSTANCE,
- Types.UNIT);
- testExpression("[1,2+3,4+5]",
- Arrays.asList(1,5,9),
- Types.list(Types.INTEGER));
- testExpression("let a = 5.3 in let f x = x+a in f 3",
- Double.valueOf(8.3),
- Types.DOUBLE);
- testExpression("let mm x y = if x < y then x else y in mm 2 (mm 1 3)",
- Double.valueOf(1.0),
- Types.DOUBLE);
- }
-
- @Test
- public void testLocalEnvironment() throws Exception {
- String expressionText = "a + b";
- LocalEnvironment localEnvironment = new AbstractLocalEnvironment() {
- Variable[] localParameters = new Variable[] {
- new Variable("a", Types.DOUBLE),
- new Variable("b", Types.DOUBLE),
- };
-
- @Override
- public Expression resolve(Environment environment, String localName) {
- if(localName.equals("a"))
- return new EVariable(localParameters[0]);
- else if(localName.equals("b"))
- return new EVariable(localParameters[1]);
- else
- return null;
- }
-
- @Override
- protected Variable[] getContextVariables() {
- return localParameters;
- }
- };
- try {
- Object result = new ExpressionEvaluator(runtimeEnvironment, expressionText)
- .localEnvironment(localEnvironment)
- .expectedType(Types.DOUBLE)
- .eval();
- Assert.assertEquals(
- Double.valueOf(15.0),
- ((Function)result).apply(7.0, 8.0));
- } catch(SCLExpressionCompilationException e) {
- System.out.println(CompilationErrorFormatter.toString(expressionText, e.getErrors()));
- throw e;
- }
- }
-
- @Test
- public void testArities() throws Exception {
- for(int arity=1;arity<50;++arity) {
- // Build expressions
- StringBuilder b = new StringBuilder();
- b.append('\\');
- for(int i=0;i<arity;++i)
- b.append("v" + i + " ");
- b.append("-> ");
- for(int i=0;i<arity;++i) {
- if(i > 0)
- b.append(" + ");
- b.append("v" + i);
- }
- //System.out.println(b.toString());
-
- // Compile
- Type expectedType = Types.INTEGER;
- for(int i=0;i<arity;++i)
- expectedType = Types.function(Types.INTEGER, expectedType);
-
- Function function = (Function)new ExpressionEvaluator(runtimeEnvironment, b.toString())
- .expectedType(expectedType)
- .interpretIfPossible(false)
- .eval();
-
- // Evaluate
- Object[] parameters = new Object[arity];
- int sum = 0;
- for(int i=0;i<arity;++i) {
- int value = i+1;
- parameters[i] = value;
- sum += value;
- }
- Object result = function.applyArray(parameters);
- Assert.assertEquals(sum, result);
- }
- }
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.cojen.classfile.TypeDesc;
-
-public class TestTypeDesc {
- public static void main(String[] args) {
- System.out.println(TypeDesc.forClass(String.class).getFullName());
- System.out.println(TypeDesc.forClass(String.class).getDescriptor());
- System.out.println(TypeDesc.forClass(String.class).getRootName());
-
- }
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.Test;
-
-public class UnimplementedTests extends TestBase {
-
- public UnimplementedTests() { super("scl"); }
-
- @Test public void BigInstances() { test(); }
- @Test public void BlankExpression() { test(); }
- @Test public void ClashingValueDefinition() { test(); }
- @Test public void FunctionalDependencies1() { test(); }
- @Test public void FunctionalDependencies2() { test(); }
- @Test public void InlineLoop() { test(); }
- @Test public void InstanceTypeVariables() { test(); }
- @Test public void LP() { test(); }
- @Test public void Macros3() { test(); }
- @Test public void MissingTypeParameter() { test(); }
- @Test(timeout=100L) public void RecursiveValues() { test(); }
-
- @Test public void Set1() { test(); }
- @Test public void Signals() { test(); }
- @Test public void SpecConstr1() { test(); }
- @Test public void StackTrace() { test(); }
- @Test public void StringInterpolation2() { test(); }
- @Test public void Timing() { test(); }
-
-}
-
+++ /dev/null
-package org.simantics.scl.compiler.tests.experimentation;\r
-\r
-import java.io.PrintWriter;\r
-import java.lang.reflect.Method;\r
-import java.util.concurrent.atomic.AtomicReference;\r
-\r
-import org.objectweb.asm.ClassVisitor;\r
-import org.objectweb.asm.ClassWriter;\r
-import org.objectweb.asm.MethodVisitor;\r
-import org.objectweb.asm.Opcodes;\r
-import org.objectweb.asm.util.TraceClassVisitor;\r
-\r
-public class RecursiveInitialization {\r
-\r
- public static void main(String[] args) throws Exception {\r
- ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);\r
- ClassVisitor classVisitor = new TraceClassVisitor(classWriter, new PrintWriter(System.out));\r
- classVisitor.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "test/Test", null, "java/lang/Object", new String[0]);\r
- MethodVisitor methodWriter = classVisitor.visitMethod(\r
- Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,\r
- "main", "()Ljava/lang/Object;", null, null);\r
- \r
- methodWriter.visitCode(); \r
- methodWriter.visitTypeInsn(Opcodes.NEW, "java/util/concurrent/atomic/AtomicReference");\r
- methodWriter.visitVarInsn(Opcodes.ASTORE, 2);\r
-\r
- methodWriter.visitTypeInsn(Opcodes.NEW, "java/util/concurrent/atomic/AtomicReference");\r
- methodWriter.visitVarInsn(Opcodes.ASTORE, 1);\r
- \r
- methodWriter.visitVarInsn(Opcodes.ALOAD, 2);\r
- methodWriter.visitVarInsn(Opcodes.ALOAD, 1);\r
- //methodWriter.visitInsn(Opcodes.ACONST_NULL);\r
- methodWriter.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/concurrent/atomic/AtomicReference", "<init>", "(Ljava/lang/Object;)V", false);\r
- \r
- methodWriter.visitVarInsn(Opcodes.ALOAD, 1);\r
- methodWriter.visitVarInsn(Opcodes.ALOAD, 2);\r
- methodWriter.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/concurrent/atomic/AtomicReference", "<init>", "(Ljava/lang/Object;)V", false);\r
-\r
- methodWriter.visitVarInsn(Opcodes.ALOAD, 2);\r
- methodWriter.visitInsn(Opcodes.ARETURN);\r
- methodWriter.visitMaxs(0, 0);\r
- methodWriter.visitEnd();\r
- \r
- byte[] bytes = classWriter.toByteArray();\r
- ClassLoader classLoader = new ClassLoader() {\r
- @Override\r
- protected Class<?> findClass(String name) throws ClassNotFoundException {\r
- if(!name.equals("test.Test"))\r
- throw new ClassNotFoundException();\r
- return defineClass("test.Test", bytes, 0, bytes.length);\r
- }\r
- };\r
- Class<?> clazz = classLoader.loadClass("test.Test");\r
- Method method = clazz.getMethod("main");\r
- AtomicReference<Object> result = (AtomicReference<Object>)method.invoke(null);\r
- System.out.println(result.hashCode());\r
- //System.out.println(result.get().hashCode());\r
- }\r
- \r
-}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests.experimentation;\r
-\r
-public class TestEquals {\r
- public static boolean eqInt(int a, int b) {\r
- return a==b;\r
- }\r
- \r
- public static boolean eqDouble(double a, double b) {\r
- return a==b;\r
- }\r
- \r
- public static boolean eqObject(Object a, Object b) {\r
- return a.equals(b);\r
- }\r
-}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests.experimentation;
-
-import org.cojen.classfile.TypeDesc;
-
-public class TestTypeDesc {
- public static void main(String[] args) {
- System.out.println(TypeDesc.forClass(String.class).getFullName());
- System.out.println(TypeDesc.forClass(String.class).getDescriptor());
- System.out.println(TypeDesc.forClass(String.class).getRootName());
-
- }
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests.imports;\r
-\r
-import java.util.Random;\r
-\r
-public class Maybe4Imports {\r
-\r
- public static Object toMaybeDouble(Random r, String s) {\r
- try {\r
- return new Double(s);\r
- } catch(Exception e) {\r
- return null;\r
- }\r
- }\r
- \r
-}\r
+++ /dev/null
----
-title: CommonMark Spec
-author: John MacFarlane
-version: 0.25
-date: '2016-03-24'
-license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
-...
-
-# Introduction
-
-## What is Markdown?
-
-Markdown is a plain text format for writing structured documents,
-based on conventions used for indicating formatting in email and
-usenet posts. It was developed in 2004 by John Gruber, who wrote
-the first Markdown-to-HTML converter in perl, and it soon became
-widely used in websites. By 2014 there were dozens of
-implementations in many languages. Some of them extended basic
-Markdown syntax with conventions for footnotes, definition lists,
-tables, and other constructs, and some allowed output not just in
-HTML but in LaTeX and many other formats.
-
-## Why is a spec needed?
-
-John Gruber's [canonical description of Markdown's
-syntax](http://daringfireball.net/projects/markdown/syntax)
-does not specify the syntax unambiguously. Here are some examples of
-questions it does not answer:
-
-1. How much indentation is needed for a sublist? The spec says that
- continuation paragraphs need to be indented four spaces, but is
- not fully explicit about sublists. It is natural to think that
- they, too, must be indented four spaces, but `Markdown.pl` does
- not require that. This is hardly a "corner case," and divergences
- between implementations on this issue often lead to surprises for
- users in real documents. (See [this comment by John
- Gruber](http://article.gmane.org/gmane.text.markdown.general/1997).)
-
-2. Is a blank line needed before a block quote or heading?
- Most implementations do not require the blank line. However,
- this can lead to unexpected results in hard-wrapped text, and
- also to ambiguities in parsing (note that some implementations
- put the heading inside the blockquote, while others do not).
- (John Gruber has also spoken [in favor of requiring the blank
- lines](http://article.gmane.org/gmane.text.markdown.general/2146).)
-
-3. Is a blank line needed before an indented code block?
- (`Markdown.pl` requires it, but this is not mentioned in the
- documentation, and some implementations do not require it.)
-
- ``` markdown
- paragraph
- code?
- ```
-
-4. What is the exact rule for determining when list items get
- wrapped in `<p>` tags? Can a list be partially "loose" and partially
- "tight"? What should we do with a list like this?
-
- ``` markdown
- 1. one
-
- 2. two
- 3. three
- ```
-
- Or this?
-
- ``` markdown
- 1. one
- - a
-
- - b
- 2. two
- ```
-
- (There are some relevant comments by John Gruber
- [here](http://article.gmane.org/gmane.text.markdown.general/2554).)
-
-5. Can list markers be indented? Can ordered list markers be right-aligned?
-
- ``` markdown
- 8. item 1
- 9. item 2
- 10. item 2a
- ```
-
-6. Is this one list with a thematic break in its second item,
- or two lists separated by a thematic break?
-
- ``` markdown
- * a
- * * * * *
- * b
- ```
-
-7. When list markers change from numbers to bullets, do we have
- two lists or one? (The Markdown syntax description suggests two,
- but the perl scripts and many other implementations produce one.)
-
- ``` markdown
- 1. fee
- 2. fie
- - foe
- - fum
- ```
-
-8. What are the precedence rules for the markers of inline structure?
- For example, is the following a valid link, or does the code span
- take precedence ?
-
- ``` markdown
- [a backtick (`)](/url) and [another backtick (`)](/url).
- ```
-
-9. What are the precedence rules for markers of emphasis and strong
- emphasis? For example, how should the following be parsed?
-
- ``` markdown
- *foo *bar* baz*
- ```
-
-10. What are the precedence rules between block-level and inline-level
- structure? For example, how should the following be parsed?
-
- ``` markdown
- - `a long code span can contain a hyphen like this
- - and it can screw things up`
- ```
-
-11. Can list items include section headings? (`Markdown.pl` does not
- allow this, but does allow blockquotes to include headings.)
-
- ``` markdown
- - # Heading
- ```
-
-12. Can list items be empty?
-
- ``` markdown
- * a
- *
- * b
- ```
-
-13. Can link references be defined inside block quotes or list items?
-
- ``` markdown
- > Blockquote [foo].
- >
- > [foo]: /url
- ```
-
-14. If there are multiple definitions for the same reference, which takes
- precedence?
-
- ``` markdown
- [foo]: /url1
- [foo]: /url2
-
- [foo][]
- ```
-
-In the absence of a spec, early implementers consulted `Markdown.pl`
-to resolve these ambiguities. But `Markdown.pl` was quite buggy, and
-gave manifestly bad results in many cases, so it was not a
-satisfactory replacement for a spec.
-
-Because there is no unambiguous spec, implementations have diverged
-considerably. As a result, users are often surprised to find that
-a document that renders one way on one system (say, a github wiki)
-renders differently on another (say, converting to docbook using
-pandoc). To make matters worse, because nothing in Markdown counts
-as a "syntax error," the divergence often isn't discovered right away.
-
-## About this document
-
-This document attempts to specify Markdown syntax unambiguously.
-It contains many examples with side-by-side Markdown and
-HTML. These are intended to double as conformance tests. An
-accompanying script `spec_tests.py` can be used to run the tests
-against any Markdown program:
-
- python test/spec_tests.py --spec spec.txt --program PROGRAM
-
-Since this document describes how Markdown is to be parsed into
-an abstract syntax tree, it would have made sense to use an abstract
-representation of the syntax tree instead of HTML. But HTML is capable
-of representing the structural distinctions we need to make, and the
-choice of HTML for the tests makes it possible to run the tests against
-an implementation without writing an abstract syntax tree renderer.
-
-This document is generated from a text file, `spec.txt`, written
-in Markdown with a small extension for the side-by-side tests.
-The script `tools/makespec.py` can be used to convert `spec.txt` into
-HTML or CommonMark (which can then be converted into other formats).
-
-In the examples, the `→` character is used to represent tabs.
-
-# Preliminaries
-
-## Characters and lines
-
-Any sequence of [characters] is a valid CommonMark
-document.
-
-A [character](@) is a Unicode code point. Although some
-code points (for example, combining accents) do not correspond to
-characters in an intuitive sense, all code points count as characters
-for purposes of this spec.
-
-This spec does not specify an encoding; it thinks of lines as composed
-of [characters] rather than bytes. A conforming parser may be limited
-to a certain encoding.
-
-A [line](@) is a sequence of zero or more [characters]
-other than newline (`U+000A`) or carriage return (`U+000D`),
-followed by a [line ending] or by the end of file.
-
-A [line ending](@) is a newline (`U+000A`), a carriage return
-(`U+000D`) not followed by a newline, or a carriage return and a
-following newline.
-
-A line containing no characters, or a line containing only spaces
-(`U+0020`) or tabs (`U+0009`), is called a [blank line](@).
-
-The following definitions of character classes will be used in this spec:
-
-A [whitespace character](@) is a space
-(`U+0020`), tab (`U+0009`), newline (`U+000A`), line tabulation (`U+000B`),
-form feed (`U+000C`), or carriage return (`U+000D`).
-
-[Whitespace](@) is a sequence of one or more [whitespace
-characters].
-
-A [Unicode whitespace character](@) is
-any code point in the Unicode `Zs` class, or a tab (`U+0009`),
-carriage return (`U+000D`), newline (`U+000A`), or form feed
-(`U+000C`).
-
-[Unicode whitespace](@) is a sequence of one
-or more [Unicode whitespace characters].
-
-A [space](@) is `U+0020`.
-
-A [non-whitespace character](@) is any character
-that is not a [whitespace character].
-
-An [ASCII punctuation character](@)
-is `!`, `"`, `#`, `$`, `%`, `&`, `'`, `(`, `)`,
-`*`, `+`, `,`, `-`, `.`, `/`, `:`, `;`, `<`, `=`, `>`, `?`, `@`,
-`[`, `\`, `]`, `^`, `_`, `` ` ``, `{`, `|`, `}`, or `~`.
-
-A [punctuation character](@) is an [ASCII
-punctuation character] or anything in
-the Unicode classes `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`.
-
-## Tabs
-
-Tabs in lines are not expanded to [spaces]. However,
-in contexts where indentation is significant for the
-document's structure, tabs behave as if they were replaced
-by spaces with a tab stop of 4 characters.
-
-```````````````````````````````` example
-→foo→baz→→bim
-.
-<pre><code>foo→baz→→bim
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- →foo→baz→→bim
-.
-<pre><code>foo→baz→→bim
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- a→a
- ὐ→a
-.
-<pre><code>a→a
-ὐ→a
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- - foo
-
-→bar
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-</ul>
-````````````````````````````````
-
-```````````````````````````````` example
-- foo
-
-→→bar
-.
-<ul>
-<li>
-<p>foo</p>
-<pre><code> bar
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-```````````````````````````````` example
->→→foo
-.
-<blockquote>
-<pre><code> foo
-</code></pre>
-</blockquote>
-````````````````````````````````
-
-```````````````````````````````` example
--→→foo
-.
-<ul>
-<li>
-<pre><code> foo
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
- foo
-→bar
-.
-<pre><code>foo
-bar
-</code></pre>
-````````````````````````````````
-
-```````````````````````````````` example
- - foo
- - bar
-→ - baz
-.
-<ul>
-<li>foo
-<ul>
-<li>bar
-<ul>
-<li>baz</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-
-## Insecure characters
-
-For security reasons, the Unicode character `U+0000` must be replaced
-with the REPLACEMENT CHARACTER (`U+FFFD`).
-
-# Blocks and inlines
-
-We can think of a document as a sequence of
-[blocks](@)---structural elements like paragraphs, block
-quotations, lists, headings, rules, and code blocks. Some blocks (like
-block quotes and list items) contain other blocks; others (like
-headings and paragraphs) contain [inline](@) content---text,
-links, emphasized text, images, code, and so on.
-
-## Precedence
-
-Indicators of block structure always take precedence over indicators
-of inline structure. So, for example, the following is a list with
-two items, not a list with one item containing a code span:
-
-```````````````````````````````` example
-- `one
-- two`
-.
-<ul>
-<li>`one</li>
-<li>two`</li>
-</ul>
-````````````````````````````````
-
-
-This means that parsing can proceed in two steps: first, the block
-structure of the document can be discerned; second, text lines inside
-paragraphs, headings, and other block constructs can be parsed for inline
-structure. The second step requires information about link reference
-definitions that will be available only at the end of the first
-step. Note that the first step requires processing lines in sequence,
-but the second can be parallelized, since the inline parsing of
-one block element does not affect the inline parsing of any other.
-
-## Container blocks and leaf blocks
-
-We can divide blocks into two types:
-[container block](@)s,
-which can contain other blocks, and [leaf block](@)s,
-which cannot.
-
-# Leaf blocks
-
-This section describes the different kinds of leaf block that make up a
-Markdown document.
-
-## Thematic breaks
-
-A line consisting of 0-3 spaces of indentation, followed by a sequence
-of three or more matching `-`, `_`, or `*` characters, each followed
-optionally by any number of spaces, forms a
-[thematic break](@).
-
-```````````````````````````````` example
-***
----
-___
-.
-<hr />
-<hr />
-<hr />
-````````````````````````````````
-
-
-Wrong characters:
-
-```````````````````````````````` example
-+++
-.
-<p>+++</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-===
-.
-<p>===</p>
-````````````````````````````````
-
-
-Not enough characters:
-
-```````````````````````````````` example
---
-**
-__
-.
-<p>--
-**
-__</p>
-````````````````````````````````
-
-
-One to three spaces indent are allowed:
-
-```````````````````````````````` example
- ***
- ***
- ***
-.
-<hr />
-<hr />
-<hr />
-````````````````````````````````
-
-
-Four spaces is too many:
-
-```````````````````````````````` example
- ***
-.
-<pre><code>***
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-Foo
- ***
-.
-<p>Foo
-***</p>
-````````````````````````````````
-
-
-More than three characters may be used:
-
-```````````````````````````````` example
-_____________________________________
-.
-<hr />
-````````````````````````````````
-
-
-Spaces are allowed between the characters:
-
-```````````````````````````````` example
- - - -
-.
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
- ** * ** * ** * **
-.
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-- - - -
-.
-<hr />
-````````````````````````````````
-
-
-Spaces are allowed at the end:
-
-```````````````````````````````` example
-- - - -
-.
-<hr />
-````````````````````````````````
-
-
-However, no other characters may occur in the line:
-
-```````````````````````````````` example
-_ _ _ _ a
-
-a------
-
----a---
-.
-<p>_ _ _ _ a</p>
-<p>a------</p>
-<p>---a---</p>
-````````````````````````````````
-
-
-It is required that all of the [non-whitespace characters] be the same.
-So, this is not a thematic break:
-
-```````````````````````````````` example
- *-*
-.
-<p><em>-</em></p>
-````````````````````````````````
-
-
-Thematic breaks do not need blank lines before or after:
-
-```````````````````````````````` example
-- foo
-***
-- bar
-.
-<ul>
-<li>foo</li>
-</ul>
-<hr />
-<ul>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-Thematic breaks can interrupt a paragraph:
-
-```````````````````````````````` example
-Foo
-***
-bar
-.
-<p>Foo</p>
-<hr />
-<p>bar</p>
-````````````````````````````````
-
-
-If a line of dashes that meets the above conditions for being a
-thematic break could also be interpreted as the underline of a [setext
-heading], the interpretation as a
-[setext heading] takes precedence. Thus, for example,
-this is a setext heading, not a paragraph followed by a thematic break:
-
-```````````````````````````````` example
-Foo
----
-bar
-.
-<h2>Foo</h2>
-<p>bar</p>
-````````````````````````````````
-
-
-When both a thematic break and a list item are possible
-interpretations of a line, the thematic break takes precedence:
-
-```````````````````````````````` example
-* Foo
-* * *
-* Bar
-.
-<ul>
-<li>Foo</li>
-</ul>
-<hr />
-<ul>
-<li>Bar</li>
-</ul>
-````````````````````````````````
-
-
-If you want a thematic break in a list item, use a different bullet:
-
-```````````````````````````````` example
-- Foo
-- * * *
-.
-<ul>
-<li>Foo</li>
-<li>
-<hr />
-</li>
-</ul>
-````````````````````````````````
-
-
-## ATX headings
-
-An [ATX heading](@)
-consists of a string of characters, parsed as inline content, between an
-opening sequence of 1--6 unescaped `#` characters and an optional
-closing sequence of any number of unescaped `#` characters.
-The opening sequence of `#` characters must be followed by a
-[space] or by the end of line. The optional closing sequence of `#`s must be
-preceded by a [space] and may be followed by spaces only. The opening
-`#` character may be indented 0-3 spaces. The raw contents of the
-heading are stripped of leading and trailing spaces before being parsed
-as inline content. The heading level is equal to the number of `#`
-characters in the opening sequence.
-
-Simple headings:
-
-```````````````````````````````` example
-# foo
-## foo
-### foo
-#### foo
-##### foo
-###### foo
-.
-<h1>foo</h1>
-<h2>foo</h2>
-<h3>foo</h3>
-<h4>foo</h4>
-<h5>foo</h5>
-<h6>foo</h6>
-````````````````````````````````
-
-
-More than six `#` characters is not a heading:
-
-```````````````````````````````` example
-####### foo
-.
-<p>####### foo</p>
-````````````````````````````````
-
-
-At least one space is required between the `#` characters and the
-heading's contents, unless the heading is empty. Note that many
-implementations currently do not require the space. However, the
-space was required by the
-[original ATX implementation](http://www.aaronsw.com/2002/atx/atx.py),
-and it helps prevent things like the following from being parsed as
-headings:
-
-```````````````````````````````` example
-#5 bolt
-
-#hashtag
-.
-<p>#5 bolt</p>
-<p>#hashtag</p>
-````````````````````````````````
-
-
-A tab will not work:
-
-```````````````````````````````` example
-#→foo
-.
-<p>#→foo</p>
-````````````````````````````````
-
-
-This is not a heading, because the first `#` is escaped:
-
-```````````````````````````````` example
-\## foo
-.
-<p>## foo</p>
-````````````````````````````````
-
-
-Contents are parsed as inlines:
-
-```````````````````````````````` example
-# foo *bar* \*baz\*
-.
-<h1>foo <em>bar</em> *baz*</h1>
-````````````````````````````````
-
-
-Leading and trailing blanks are ignored in parsing inline content:
-
-```````````````````````````````` example
-# foo
-.
-<h1>foo</h1>
-````````````````````````````````
-
-
-One to three spaces indentation are allowed:
-
-```````````````````````````````` example
- ### foo
- ## foo
- # foo
-.
-<h3>foo</h3>
-<h2>foo</h2>
-<h1>foo</h1>
-````````````````````````````````
-
-
-Four spaces are too much:
-
-```````````````````````````````` example
- # foo
-.
-<pre><code># foo
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo
- # bar
-.
-<p>foo
-# bar</p>
-````````````````````````````````
-
-
-A closing sequence of `#` characters is optional:
-
-```````````````````````````````` example
-## foo ##
- ### bar ###
-.
-<h2>foo</h2>
-<h3>bar</h3>
-````````````````````````````````
-
-
-It need not be the same length as the opening sequence:
-
-```````````````````````````````` example
-# foo ##################################
-##### foo ##
-.
-<h1>foo</h1>
-<h5>foo</h5>
-````````````````````````````````
-
-
-Spaces are allowed after the closing sequence:
-
-```````````````````````````````` example
-### foo ###
-.
-<h3>foo</h3>
-````````````````````````````````
-
-
-A sequence of `#` characters with anything but [spaces] following it
-is not a closing sequence, but counts as part of the contents of the
-heading:
-
-```````````````````````````````` example
-### foo ### b
-.
-<h3>foo ### b</h3>
-````````````````````````````````
-
-
-The closing sequence must be preceded by a space:
-
-```````````````````````````````` example
-# foo#
-.
-<h1>foo#</h1>
-````````````````````````````````
-
-
-Backslash-escaped `#` characters do not count as part
-of the closing sequence:
-
-```````````````````````````````` example
-### foo \###
-## foo #\##
-# foo \#
-.
-<h3>foo ###</h3>
-<h2>foo ###</h2>
-<h1>foo #</h1>
-````````````````````````````````
-
-
-ATX headings need not be separated from surrounding content by blank
-lines, and they can interrupt paragraphs:
-
-```````````````````````````````` example
-****
-## foo
-****
-.
-<hr />
-<h2>foo</h2>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-Foo bar
-# baz
-Bar foo
-.
-<p>Foo bar</p>
-<h1>baz</h1>
-<p>Bar foo</p>
-````````````````````````````````
-
-
-ATX headings can be empty:
-
-```````````````````````````````` example
-##
-#
-### ###
-.
-<h2></h2>
-<h1></h1>
-<h3></h3>
-````````````````````````````````
-
-
-## Setext headings
-
-A [setext heading](@) consists of one or more
-lines of text, each containing at least one [non-whitespace
-character], with no more than 3 spaces indentation, followed by
-a [setext heading underline]. The lines of text must be such
-that, were they not followed by the setext heading underline,
-they would be interpreted as a paragraph: they cannot be
-interpretable as a [code fence], [ATX heading][ATX headings],
-[block quote][block quotes], [thematic break][thematic breaks],
-[list item][list items], or [HTML block][HTML blocks].
-
-A [setext heading underline](@) is a sequence of
-`=` characters or a sequence of `-` characters, with no more than 3
-spaces indentation and any number of trailing spaces. If a line
-containing a single `-` can be interpreted as an
-empty [list items], it should be interpreted this way
-and not as a [setext heading underline].
-
-The heading is a level 1 heading if `=` characters are used in
-the [setext heading underline], and a level 2 heading if `-`
-characters are used. The contents of the heading are the result
-of parsing the preceding lines of text as CommonMark inline
-content.
-
-In general, a setext heading need not be preceded or followed by a
-blank line. However, it cannot interrupt a paragraph, so when a
-setext heading comes after a paragraph, a blank line is needed between
-them.
-
-Simple examples:
-
-```````````````````````````````` example
-Foo *bar*
-=========
-
-Foo *bar*
----------
-.
-<h1>Foo <em>bar</em></h1>
-<h2>Foo <em>bar</em></h2>
-````````````````````````````````
-
-
-The content of the header may span more than one line:
-
-```````````````````````````````` example
-Foo *bar
-baz*
-====
-.
-<h1>Foo <em>bar
-baz</em></h1>
-````````````````````````````````
-
-
-The underlining can be any length:
-
-```````````````````````````````` example
-Foo
--------------------------
-
-Foo
-=
-.
-<h2>Foo</h2>
-<h1>Foo</h1>
-````````````````````````````````
-
-
-The heading content can be indented up to three spaces, and need
-not line up with the underlining:
-
-```````````````````````````````` example
- Foo
----
-
- Foo
------
-
- Foo
- ===
-.
-<h2>Foo</h2>
-<h2>Foo</h2>
-<h1>Foo</h1>
-````````````````````````````````
-
-
-Four spaces indent is too much:
-
-```````````````````````````````` example
- Foo
- ---
-
- Foo
----
-.
-<pre><code>Foo
----
-
-Foo
-</code></pre>
-<hr />
-````````````````````````````````
-
-
-The setext heading underline can be indented up to three spaces, and
-may have trailing spaces:
-
-```````````````````````````````` example
-Foo
- ----
-.
-<h2>Foo</h2>
-````````````````````````````````
-
-
-Four spaces is too much:
-
-```````````````````````````````` example
-Foo
- ---
-.
-<p>Foo
----</p>
-````````````````````````````````
-
-
-The setext heading underline cannot contain internal spaces:
-
-```````````````````````````````` example
-Foo
-= =
-
-Foo
---- -
-.
-<p>Foo
-= =</p>
-<p>Foo</p>
-<hr />
-````````````````````````````````
-
-
-Trailing spaces in the content line do not cause a line break:
-
-```````````````````````````````` example
-Foo
------
-.
-<h2>Foo</h2>
-````````````````````````````````
-
-
-Nor does a backslash at the end:
-
-```````````````````````````````` example
-Foo\
-----
-.
-<h2>Foo\</h2>
-````````````````````````````````
-
-
-Since indicators of block structure take precedence over
-indicators of inline structure, the following are setext headings:
-
-```````````````````````````````` example
-`Foo
-----
-`
-
-<a title="a lot
----
-of dashes"/>
-.
-<h2>`Foo</h2>
-<p>`</p>
-<h2><a title="a lot</h2>
-<p>of dashes"/></p>
-````````````````````````````````
-
-
-The setext heading underline cannot be a [lazy continuation
-line] in a list item or block quote:
-
-```````````````````````````````` example
-> Foo
----
-.
-<blockquote>
-<p>Foo</p>
-</blockquote>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-> foo
-bar
-===
-.
-<blockquote>
-<p>foo
-bar
-===</p>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- Foo
----
-.
-<ul>
-<li>Foo</li>
-</ul>
-<hr />
-````````````````````````````````
-
-
-A blank line is needed between a paragraph and a following
-setext heading, since otherwise the paragraph becomes part
-of the heading's content:
-
-```````````````````````````````` example
-Foo
-Bar
----
-.
-<h2>Foo
-Bar</h2>
-````````````````````````````````
-
-
-But in general a blank line is not required before or after
-setext headings:
-
-```````````````````````````````` example
----
-Foo
----
-Bar
----
-Baz
-.
-<hr />
-<h2>Foo</h2>
-<h2>Bar</h2>
-<p>Baz</p>
-````````````````````````````````
-
-
-Setext headings cannot be empty:
-
-```````````````````````````````` example
-
-====
-.
-<p>====</p>
-````````````````````````````````
-
-
-Setext heading text lines must not be interpretable as block
-constructs other than paragraphs. So, the line of dashes
-in these examples gets interpreted as a thematic break:
-
-```````````````````````````````` example
----
----
-.
-<hr />
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-- foo
------
-.
-<ul>
-<li>foo</li>
-</ul>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
- foo
----
-.
-<pre><code>foo
-</code></pre>
-<hr />
-````````````````````````````````
-
-
-```````````````````````````````` example
-> foo
------
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-<hr />
-````````````````````````````````
-
-
-If you want a heading with `> foo` as its literal text, you can
-use backslash escapes:
-
-```````````````````````````````` example
-\> foo
-------
-.
-<h2>> foo</h2>
-````````````````````````````````
-
-
-**Compatibility note:** Most existing Markdown implementations
-do not allow the text of setext headings to span multiple lines.
-But there is no consensus about how to interpret
-
-``` markdown
-Foo
-bar
----
-baz
-```
-
-One can find four different interpretations:
-
-1. paragraph "Foo", heading "bar", paragraph "baz"
-2. paragraph "Foo bar", thematic break, paragraph "baz"
-3. paragraph "Foo bar --- baz"
-4. heading "Foo bar", paragraph "baz"
-
-We find interpretation 4 most natural, and interpretation 4
-increases the expressive power of CommonMark, by allowing
-multiline headings. Authors who want interpretation 1 can
-put a blank line after the first paragraph:
-
-```````````````````````````````` example
-Foo
-
-bar
----
-baz
-.
-<p>Foo</p>
-<h2>bar</h2>
-<p>baz</p>
-````````````````````````````````
-
-
-Authors who want interpretation 2 can put blank lines around
-the thematic break,
-
-```````````````````````````````` example
-Foo
-bar
-
----
-
-baz
-.
-<p>Foo
-bar</p>
-<hr />
-<p>baz</p>
-````````````````````````````````
-
-
-or use a thematic break that cannot count as a [setext heading
-underline], such as
-
-```````````````````````````````` example
-Foo
-bar
-* * *
-baz
-.
-<p>Foo
-bar</p>
-<hr />
-<p>baz</p>
-````````````````````````````````
-
-
-Authors who want interpretation 3 can use backslash escapes:
-
-```````````````````````````````` example
-Foo
-bar
-\---
-baz
-.
-<p>Foo
-bar
----
-baz</p>
-````````````````````````````````
-
-
-## Indented code blocks
-
-An [indented code block](@) is composed of one or more
-[indented chunks] separated by blank lines.
-An [indented chunk](@) is a sequence of non-blank lines,
-each indented four or more spaces. The contents of the code block are
-the literal contents of the lines, including trailing
-[line endings], minus four spaces of indentation.
-An indented code block has no [info string].
-
-An indented code block cannot interrupt a paragraph, so there must be
-a blank line between a paragraph and a following indented code block.
-(A blank line is not needed, however, between a code block and a following
-paragraph.)
-
-```````````````````````````````` example
- a simple
- indented code block
-.
-<pre><code>a simple
- indented code block
-</code></pre>
-````````````````````````````````
-
-
-If there is any ambiguity between an interpretation of indentation
-as a code block and as indicating that material belongs to a [list
-item][list items], the list item interpretation takes precedence:
-
-```````````````````````````````` example
- - foo
-
- bar
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. foo
-
- - bar
-.
-<ol>
-<li>
-<p>foo</p>
-<ul>
-<li>bar</li>
-</ul>
-</li>
-</ol>
-````````````````````````````````
-
-
-
-The contents of a code block are literal text, and do not get parsed
-as Markdown:
-
-```````````````````````````````` example
- <a/>
- *hi*
-
- - one
-.
-<pre><code><a/>
-*hi*
-
-- one
-</code></pre>
-````````````````````````````````
-
-
-Here we have three chunks separated by blank lines:
-
-```````````````````````````````` example
- chunk1
-
- chunk2
-
-
-
- chunk3
-.
-<pre><code>chunk1
-
-chunk2
-
-
-
-chunk3
-</code></pre>
-````````````````````````````````
-
-
-Any initial spaces beyond four will be included in the content, even
-in interior blank lines:
-
-```````````````````````````````` example
- chunk1
-
- chunk2
-.
-<pre><code>chunk1
-
- chunk2
-</code></pre>
-````````````````````````````````
-
-
-An indented code block cannot interrupt a paragraph. (This
-allows hanging indents and the like.)
-
-```````````````````````````````` example
-Foo
- bar
-
-.
-<p>Foo
-bar</p>
-````````````````````````````````
-
-
-However, any non-blank line with fewer than four leading spaces ends
-the code block immediately. So a paragraph may occur immediately
-after indented code:
-
-```````````````````````````````` example
- foo
-bar
-.
-<pre><code>foo
-</code></pre>
-<p>bar</p>
-````````````````````````````````
-
-
-And indented code can occur immediately before and after other kinds of
-blocks:
-
-```````````````````````````````` example
-# Heading
- foo
-Heading
-------
- foo
-----
-.
-<h1>Heading</h1>
-<pre><code>foo
-</code></pre>
-<h2>Heading</h2>
-<pre><code>foo
-</code></pre>
-<hr />
-````````````````````````````````
-
-
-The first line can be indented more than four spaces:
-
-```````````````````````````````` example
- foo
- bar
-.
-<pre><code> foo
-bar
-</code></pre>
-````````````````````````````````
-
-
-Blank lines preceding or following an indented code block
-are not included in it:
-
-```````````````````````````````` example
-
-
- foo
-
-
-.
-<pre><code>foo
-</code></pre>
-````````````````````````````````
-
-
-Trailing spaces are included in the code block's content:
-
-```````````````````````````````` example
- foo
-.
-<pre><code>foo
-</code></pre>
-````````````````````````````````
-
-
-
-## Fenced code blocks
-
-A [code fence](@) is a sequence
-of at least three consecutive backtick characters (`` ` ``) or
-tildes (`~`). (Tildes and backticks cannot be mixed.)
-A [fenced code block](@)
-begins with a code fence, indented no more than three spaces.
-
-The line with the opening code fence may optionally contain some text
-following the code fence; this is trimmed of leading and trailing
-spaces and called the [info string](@).
-The [info string] may not contain any backtick
-characters. (The reason for this restriction is that otherwise
-some inline code would be incorrectly interpreted as the
-beginning of a fenced code block.)
-
-The content of the code block consists of all subsequent lines, until
-a closing [code fence] of the same type as the code block
-began with (backticks or tildes), and with at least as many backticks
-or tildes as the opening code fence. If the leading code fence is
-indented N spaces, then up to N spaces of indentation are removed from
-each line of the content (if present). (If a content line is not
-indented, it is preserved unchanged. If it is indented less than N
-spaces, all of the indentation is removed.)
-
-The closing code fence may be indented up to three spaces, and may be
-followed only by spaces, which are ignored. If the end of the
-containing block (or document) is reached and no closing code fence
-has been found, the code block contains all of the lines after the
-opening code fence until the end of the containing block (or
-document). (An alternative spec would require backtracking in the
-event that a closing code fence is not found. But this makes parsing
-much less efficient, and there seems to be no real down side to the
-behavior described here.)
-
-A fenced code block may interrupt a paragraph, and does not require
-a blank line either before or after.
-
-The content of a code fence is treated as literal text, not parsed
-as inlines. The first word of the [info string] is typically used to
-specify the language of the code sample, and rendered in the `class`
-attribute of the `code` tag. However, this spec does not mandate any
-particular treatment of the [info string].
-
-Here is a simple example with backticks:
-
-```````````````````````````````` example
-```
-<
- >
-```
-.
-<pre><code><
- >
-</code></pre>
-````````````````````````````````
-
-
-With tildes:
-
-```````````````````````````````` example
-~~~
-<
- >
-~~~
-.
-<pre><code><
- >
-</code></pre>
-````````````````````````````````
-
-
-The closing code fence must use the same character as the opening
-fence:
-
-```````````````````````````````` example
-```
-aaa
-~~~
-```
-.
-<pre><code>aaa
-~~~
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~
-aaa
-```
-~~~
-.
-<pre><code>aaa
-```
-</code></pre>
-````````````````````````````````
-
-
-The closing code fence must be at least as long as the opening fence:
-
-```````````````````````````````` example
-````
-aaa
-```
-``````
-.
-<pre><code>aaa
-```
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~~
-aaa
-~~~
-~~~~
-.
-<pre><code>aaa
-~~~
-</code></pre>
-````````````````````````````````
-
-
-Unclosed code blocks are closed by the end of the document
-(or the enclosing [block quote][block quotes] or [list item][list items]):
-
-```````````````````````````````` example
-```
-.
-<pre><code></code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-`````
-
-```
-aaa
-.
-<pre><code>
-```
-aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> ```
-> aaa
-
-bbb
-.
-<blockquote>
-<pre><code>aaa
-</code></pre>
-</blockquote>
-<p>bbb</p>
-````````````````````````````````
-
-
-A code block can have all empty lines as its content:
-
-```````````````````````````````` example
-```
-
-
-```
-.
-<pre><code>
-
-</code></pre>
-````````````````````````````````
-
-
-A code block can be empty:
-
-```````````````````````````````` example
-```
-```
-.
-<pre><code></code></pre>
-````````````````````````````````
-
-
-Fences can be indented. If the opening fence is indented,
-content lines will have equivalent opening indentation removed,
-if present:
-
-```````````````````````````````` example
- ```
- aaa
-aaa
-```
-.
-<pre><code>aaa
-aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- ```
-aaa
- aaa
-aaa
- ```
-.
-<pre><code>aaa
-aaa
-aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- ```
- aaa
- aaa
- aaa
- ```
-.
-<pre><code>aaa
- aaa
-aaa
-</code></pre>
-````````````````````````````````
-
-
-Four spaces indentation produces an indented code block:
-
-```````````````````````````````` example
- ```
- aaa
- ```
-.
-<pre><code>```
-aaa
-```
-</code></pre>
-````````````````````````````````
-
-
-Closing fences may be indented by 0-3 spaces, and their indentation
-need not match that of the opening fence:
-
-```````````````````````````````` example
-```
-aaa
- ```
-.
-<pre><code>aaa
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- ```
-aaa
- ```
-.
-<pre><code>aaa
-</code></pre>
-````````````````````````````````
-
-
-This is not a closing fence, because it is indented 4 spaces:
-
-```````````````````````````````` example
-```
-aaa
- ```
-.
-<pre><code>aaa
- ```
-</code></pre>
-````````````````````````````````
-
-
-
-Code fences (opening and closing) cannot contain internal spaces:
-
-```````````````````````````````` example
-``` ```
-aaa
-.
-<p><code></code>
-aaa</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~~~~
-aaa
-~~~ ~~
-.
-<pre><code>aaa
-~~~ ~~
-</code></pre>
-````````````````````````````````
-
-
-Fenced code blocks can interrupt paragraphs, and can be followed
-directly by paragraphs, without a blank line between:
-
-```````````````````````````````` example
-foo
-```
-bar
-```
-baz
-.
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-<p>baz</p>
-````````````````````````````````
-
-
-Other blocks can also occur before and after fenced code blocks
-without an intervening blank line:
-
-```````````````````````````````` example
-foo
----
-~~~
-bar
-~~~
-# baz
-.
-<h2>foo</h2>
-<pre><code>bar
-</code></pre>
-<h1>baz</h1>
-````````````````````````````````
-
-
-An [info string] can be provided after the opening code fence.
-Opening and closing spaces will be stripped, and the first word, prefixed
-with `language-`, is used as the value for the `class` attribute of the
-`code` element within the enclosing `pre` element.
-
-```````````````````````````````` example
-```ruby
-def foo(x)
- return 3
-end
-```
-.
-<pre><code class="language-ruby">def foo(x)
- return 3
-end
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~~ ruby startline=3 $%@#$
-def foo(x)
- return 3
-end
-~~~~~~~
-.
-<pre><code class="language-ruby">def foo(x)
- return 3
-end
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-````;
-````
-.
-<pre><code class="language-;"></code></pre>
-````````````````````````````````
-
-
-[Info strings] for backtick code blocks cannot contain backticks:
-
-```````````````````````````````` example
-``` aa ```
-foo
-.
-<p><code>aa</code>
-foo</p>
-````````````````````````````````
-
-
-Closing code fences cannot have [info strings]:
-
-```````````````````````````````` example
-```
-``` aaa
-```
-.
-<pre><code>``` aaa
-</code></pre>
-````````````````````````````````
-
-
-
-## HTML blocks
-
-An [HTML block](@) is a group of lines that is treated
-as raw HTML (and will not be escaped in HTML output).
-
-There are seven kinds of [HTML block], which can be defined
-by their start and end conditions. The block begins with a line that
-meets a [start condition](@) (after up to three spaces
-optional indentation). It ends with the first subsequent line that
-meets a matching [end condition](@), or the last line of
-the document, if no line is encountered that meets the
-[end condition]. If the first line meets both the [start condition]
-and the [end condition], the block will contain just that line.
-
-1. **Start condition:** line begins with the string `<script`,
-`<pre`, or `<style` (case-insensitive), followed by whitespace,
-the string `>`, or the end of the line.\
-**End condition:** line contains an end tag
-`</script>`, `</pre>`, or `</style>` (case-insensitive; it
-need not match the start tag).
-
-2. **Start condition:** line begins with the string `<!--`.\
-**End condition:** line contains the string `-->`.
-
-3. **Start condition:** line begins with the string `<?`.\
-**End condition:** line contains the string `?>`.
-
-4. **Start condition:** line begins with the string `<!`
-followed by an uppercase ASCII letter.\
-**End condition:** line contains the character `>`.
-
-5. **Start condition:** line begins with the string
-`<![CDATA[`.\
-**End condition:** line contains the string `]]>`.
-
-6. **Start condition:** line begins the string `<` or `</`
-followed by one of the strings (case-insensitive) `address`,
-`article`, `aside`, `base`, `basefont`, `blockquote`, `body`,
-`caption`, `center`, `col`, `colgroup`, `dd`, `details`, `dialog`,
-`dir`, `div`, `dl`, `dt`, `fieldset`, `figcaption`, `figure`,
-`footer`, `form`, `frame`, `frameset`, `h1`, `head`, `header`, `hr`,
-`html`, `iframe`, `legend`, `li`, `link`, `main`, `menu`, `menuitem`,
-`meta`, `nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`,
-`section`, `source`, `summary`, `table`, `tbody`, `td`,
-`tfoot`, `th`, `thead`, `title`, `tr`, `track`, `ul`, followed
-by [whitespace], the end of the line, the string `>`, or
-the string `/>`.\
-**End condition:** line is followed by a [blank line].
-
-7. **Start condition:** line begins with a complete [open tag]
-or [closing tag] (with any [tag name] other than `script`,
-`style`, or `pre`) followed only by [whitespace]
-or the end of the line.\
-**End condition:** line is followed by a [blank line].
-
-All types of [HTML blocks] except type 7 may interrupt
-a paragraph. Blocks of type 7 may not interrupt a paragraph.
-(This restriction is intended to prevent unwanted interpretation
-of long tags inside a wrapped paragraph as starting HTML blocks.)
-
-Some simple examples follow. Here are some basic HTML blocks
-of type 6:
-
-```````````````````````````````` example
-<table>
- <tr>
- <td>
- hi
- </td>
- </tr>
-</table>
-
-okay.
-.
-<table>
- <tr>
- <td>
- hi
- </td>
- </tr>
-</table>
-<p>okay.</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- <div>
- *hello*
- <foo><a>
-.
- <div>
- *hello*
- <foo><a>
-````````````````````````````````
-
-
-A block can also start with a closing tag:
-
-```````````````````````````````` example
-</div>
-*foo*
-.
-</div>
-*foo*
-````````````````````````````````
-
-
-Here we have two HTML blocks with a Markdown paragraph between them:
-
-```````````````````````````````` example
-<DIV CLASS="foo">
-
-*Markdown*
-
-</DIV>
-.
-<DIV CLASS="foo">
-<p><em>Markdown</em></p>
-</DIV>
-````````````````````````````````
-
-
-The tag on the first line can be partial, as long
-as it is split where there would be whitespace:
-
-```````````````````````````````` example
-<div id="foo"
- class="bar">
-</div>
-.
-<div id="foo"
- class="bar">
-</div>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<div id="foo" class="bar
- baz">
-</div>
-.
-<div id="foo" class="bar
- baz">
-</div>
-````````````````````````````````
-
-
-An open tag need not be closed:
-```````````````````````````````` example
-<div>
-*foo*
-
-*bar*
-.
-<div>
-*foo*
-<p><em>bar</em></p>
-````````````````````````````````
-
-
-
-A partial tag need not even be completed (garbage
-in, garbage out):
-
-```````````````````````````````` example
-<div id="foo"
-*hi*
-.
-<div id="foo"
-*hi*
-````````````````````````````````
-
-
-```````````````````````````````` example
-<div class
-foo
-.
-<div class
-foo
-````````````````````````````````
-
-
-The initial tag doesn't even need to be a valid
-tag, as long as it starts like one:
-
-```````````````````````````````` example
-<div *???-&&&-<---
-*foo*
-.
-<div *???-&&&-<---
-*foo*
-````````````````````````````````
-
-
-In type 6 blocks, the initial tag need not be on a line by
-itself:
-
-```````````````````````````````` example
-<div><a href="bar">*foo*</a></div>
-.
-<div><a href="bar">*foo*</a></div>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<table><tr><td>
-foo
-</td></tr></table>
-.
-<table><tr><td>
-foo
-</td></tr></table>
-````````````````````````````````
-
-
-Everything until the next blank line or end of document
-gets included in the HTML block. So, in the following
-example, what looks like a Markdown code block
-is actually part of the HTML block, which continues until a blank
-line or the end of the document is reached:
-
-```````````````````````````````` example
-<div></div>
-``` c
-int x = 33;
-```
-.
-<div></div>
-``` c
-int x = 33;
-```
-````````````````````````````````
-
-
-To start an [HTML block] with a tag that is *not* in the
-list of block-level tags in (6), you must put the tag by
-itself on the first line (and it must be complete):
-
-```````````````````````````````` example
-<a href="foo">
-*bar*
-</a>
-.
-<a href="foo">
-*bar*
-</a>
-````````````````````````````````
-
-
-In type 7 blocks, the [tag name] can be anything:
-
-```````````````````````````````` example
-<Warning>
-*bar*
-</Warning>
-.
-<Warning>
-*bar*
-</Warning>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<i class="foo">
-*bar*
-</i>
-.
-<i class="foo">
-*bar*
-</i>
-````````````````````````````````
-
-
-```````````````````````````````` example
-</ins>
-*bar*
-.
-</ins>
-*bar*
-````````````````````````````````
-
-
-These rules are designed to allow us to work with tags that
-can function as either block-level or inline-level tags.
-The `<del>` tag is a nice example. We can surround content with
-`<del>` tags in three different ways. In this case, we get a raw
-HTML block, because the `<del>` tag is on a line by itself:
-
-```````````````````````````````` example
-<del>
-*foo*
-</del>
-.
-<del>
-*foo*
-</del>
-````````````````````````````````
-
-
-In this case, we get a raw HTML block that just includes
-the `<del>` tag (because it ends with the following blank
-line). So the contents get interpreted as CommonMark:
-
-```````````````````````````````` example
-<del>
-
-*foo*
-
-</del>
-.
-<del>
-<p><em>foo</em></p>
-</del>
-````````````````````````````````
-
-
-Finally, in this case, the `<del>` tags are interpreted
-as [raw HTML] *inside* the CommonMark paragraph. (Because
-the tag is not on a line by itself, we get inline HTML
-rather than an [HTML block].)
-
-```````````````````````````````` example
-<del>*foo*</del>
-.
-<p><del><em>foo</em></del></p>
-````````````````````````````````
-
-
-HTML tags designed to contain literal content
-(`script`, `style`, `pre`), comments, processing instructions,
-and declarations are treated somewhat differently.
-Instead of ending at the first blank line, these blocks
-end at the first line containing a corresponding end tag.
-As a result, these blocks can contain blank lines:
-
-A pre tag (type 1):
-
-```````````````````````````````` example
-<pre language="haskell"><code>
-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-</code></pre>
-.
-<pre language="haskell"><code>
-import Text.HTML.TagSoup
-
-main :: IO ()
-main = print $ parseTags tags
-</code></pre>
-````````````````````````````````
-
-
-A script tag (type 1):
-
-```````````````````````````````` example
-<script type="text/javascript">
-// JavaScript example
-
-document.getElementById("demo").innerHTML = "Hello JavaScript!";
-</script>
-.
-<script type="text/javascript">
-// JavaScript example
-
-document.getElementById("demo").innerHTML = "Hello JavaScript!";
-</script>
-````````````````````````````````
-
-
-A style tag (type 1):
-
-```````````````````````````````` example
-<style
- type="text/css">
-h1 {color:red;}
-
-p {color:blue;}
-</style>
-.
-<style
- type="text/css">
-h1 {color:red;}
-
-p {color:blue;}
-</style>
-````````````````````````````````
-
-
-If there is no matching end tag, the block will end at the
-end of the document (or the enclosing [block quote][block quotes]
-or [list item][list items]):
-
-```````````````````````````````` example
-<style
- type="text/css">
-
-foo
-.
-<style
- type="text/css">
-
-foo
-````````````````````````````````
-
-
-```````````````````````````````` example
-> <div>
-> foo
-
-bar
-.
-<blockquote>
-<div>
-foo
-</blockquote>
-<p>bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- <div>
-- foo
-.
-<ul>
-<li>
-<div>
-</li>
-<li>foo</li>
-</ul>
-````````````````````````````````
-
-
-The end tag can occur on the same line as the start tag:
-
-```````````````````````````````` example
-<style>p{color:red;}</style>
-*foo*
-.
-<style>p{color:red;}</style>
-<p><em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<!-- foo -->*bar*
-*baz*
-.
-<!-- foo -->*bar*
-<p><em>baz</em></p>
-````````````````````````````````
-
-
-Note that anything on the last line after the
-end tag will be included in the [HTML block]:
-
-```````````````````````````````` example
-<script>
-foo
-</script>1. *bar*
-.
-<script>
-foo
-</script>1. *bar*
-````````````````````````````````
-
-
-A comment (type 2):
-
-```````````````````````````````` example
-<!-- Foo
-
-bar
- baz -->
-.
-<!-- Foo
-
-bar
- baz -->
-````````````````````````````````
-
-
-
-A processing instruction (type 3):
-
-```````````````````````````````` example
-<?php
-
- echo '>';
-
-?>
-.
-<?php
-
- echo '>';
-
-?>
-````````````````````````````````
-
-
-A declaration (type 4):
-
-```````````````````````````````` example
-<!DOCTYPE html>
-.
-<!DOCTYPE html>
-````````````````````````````````
-
-
-CDATA (type 5):
-
-```````````````````````````````` example
-<![CDATA[
-function matchwo(a,b)
-{
- if (a < b && a < 0) then {
- return 1;
-
- } else {
-
- return 0;
- }
-}
-]]>
-.
-<![CDATA[
-function matchwo(a,b)
-{
- if (a < b && a < 0) then {
- return 1;
-
- } else {
-
- return 0;
- }
-}
-]]>
-````````````````````````````````
-
-
-The opening tag can be indented 1-3 spaces, but not 4:
-
-```````````````````````````````` example
- <!-- foo -->
-
- <!-- foo -->
-.
- <!-- foo -->
-<pre><code><!-- foo -->
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- <div>
-
- <div>
-.
- <div>
-<pre><code><div>
-</code></pre>
-````````````````````````````````
-
-
-An HTML block of types 1--6 can interrupt a paragraph, and need not be
-preceded by a blank line.
-
-```````````````````````````````` example
-Foo
-<div>
-bar
-</div>
-.
-<p>Foo</p>
-<div>
-bar
-</div>
-````````````````````````````````
-
-
-However, a following blank line is needed, except at the end of
-a document, and except for blocks of types 1--5, above:
-
-```````````````````````````````` example
-<div>
-bar
-</div>
-*foo*
-.
-<div>
-bar
-</div>
-*foo*
-````````````````````````````````
-
-
-HTML blocks of type 7 cannot interrupt a paragraph:
-
-```````````````````````````````` example
-Foo
-<a href="bar">
-baz
-.
-<p>Foo
-<a href="bar">
-baz</p>
-````````````````````````````````
-
-
-This rule differs from John Gruber's original Markdown syntax
-specification, which says:
-
-> The only restrictions are that block-level HTML elements —
-> e.g. `<div>`, `<table>`, `<pre>`, `<p>`, etc. — must be separated from
-> surrounding content by blank lines, and the start and end tags of the
-> block should not be indented with tabs or spaces.
-
-In some ways Gruber's rule is more restrictive than the one given
-here:
-
-- It requires that an HTML block be preceded by a blank line.
-- It does not allow the start tag to be indented.
-- It requires a matching end tag, which it also does not allow to
- be indented.
-
-Most Markdown implementations (including some of Gruber's own) do not
-respect all of these restrictions.
-
-There is one respect, however, in which Gruber's rule is more liberal
-than the one given here, since it allows blank lines to occur inside
-an HTML block. There are two reasons for disallowing them here.
-First, it removes the need to parse balanced tags, which is
-expensive and can require backtracking from the end of the document
-if no matching end tag is found. Second, it provides a very simple
-and flexible way of including Markdown content inside HTML tags:
-simply separate the Markdown from the HTML using blank lines:
-
-Compare:
-
-```````````````````````````````` example
-<div>
-
-*Emphasized* text.
-
-</div>
-.
-<div>
-<p><em>Emphasized</em> text.</p>
-</div>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<div>
-*Emphasized* text.
-</div>
-.
-<div>
-*Emphasized* text.
-</div>
-````````````````````````````````
-
-
-Some Markdown implementations have adopted a convention of
-interpreting content inside tags as text if the open tag has
-the attribute `markdown=1`. The rule given above seems a simpler and
-more elegant way of achieving the same expressive power, which is also
-much simpler to parse.
-
-The main potential drawback is that one can no longer paste HTML
-blocks into Markdown documents with 100% reliability. However,
-*in most cases* this will work fine, because the blank lines in
-HTML are usually followed by HTML block tags. For example:
-
-```````````````````````````````` example
-<table>
-
-<tr>
-
-<td>
-Hi
-</td>
-
-</tr>
-
-</table>
-.
-<table>
-<tr>
-<td>
-Hi
-</td>
-</tr>
-</table>
-````````````````````````````````
-
-
-There are problems, however, if the inner tags are indented
-*and* separated by spaces, as then they will be interpreted as
-an indented code block:
-
-```````````````````````````````` example
-<table>
-
- <tr>
-
- <td>
- Hi
- </td>
-
- </tr>
-
-</table>
-.
-<table>
- <tr>
-<pre><code><td>
- Hi
-</td>
-</code></pre>
- </tr>
-</table>
-````````````````````````````````
-
-
-Fortunately, blank lines are usually not necessary and can be
-deleted. The exception is inside `<pre>` tags, but as described
-above, raw HTML blocks starting with `<pre>` *can* contain blank
-lines.
-
-## Link reference definitions
-
-A [link reference definition](@)
-consists of a [link label], indented up to three spaces, followed
-by a colon (`:`), optional [whitespace] (including up to one
-[line ending]), a [link destination],
-optional [whitespace] (including up to one
-[line ending]), and an optional [link
-title], which if it is present must be separated
-from the [link destination] by [whitespace].
-No further [non-whitespace characters] may occur on the line.
-
-A [link reference definition]
-does not correspond to a structural element of a document. Instead, it
-defines a label which can be used in [reference links]
-and reference-style [images] elsewhere in the document. [Link
-reference definitions] can come either before or after the links that use
-them.
-
-```````````````````````````````` example
-[foo]: /url "title"
-
-[foo]
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- [foo]:
- /url
- 'the title'
-
-[foo]
-.
-<p><a href="/url" title="the title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[Foo*bar\]]:my_(url) 'title (with parens)'
-
-[Foo*bar\]]
-.
-<p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[Foo bar]:
-<my%20url>
-'title'
-
-[Foo bar]
-.
-<p><a href="my%20url" title="title">Foo bar</a></p>
-````````````````````````````````
-
-
-The title may extend over multiple lines:
-
-```````````````````````````````` example
-[foo]: /url '
-title
-line1
-line2
-'
-
-[foo]
-.
-<p><a href="/url" title="
-title
-line1
-line2
-">foo</a></p>
-````````````````````````````````
-
-
-However, it may not contain a [blank line]:
-
-```````````````````````````````` example
-[foo]: /url 'title
-
-with blank line'
-
-[foo]
-.
-<p>[foo]: /url 'title</p>
-<p>with blank line'</p>
-<p>[foo]</p>
-````````````````````````````````
-
-
-The title may be omitted:
-
-```````````````````````````````` example
-[foo]:
-/url
-
-[foo]
-.
-<p><a href="/url">foo</a></p>
-````````````````````````````````
-
-
-The link destination may not be omitted:
-
-```````````````````````````````` example
-[foo]:
-
-[foo]
-.
-<p>[foo]:</p>
-<p>[foo]</p>
-````````````````````````````````
-
-
-Both title and destination can contain backslash escapes
-and literal backslashes:
-
-```````````````````````````````` example
-[foo]: /url\bar\*baz "foo\"bar\baz"
-
-[foo]
-.
-<p><a href="/url%5Cbar*baz" title="foo"bar\baz">foo</a></p>
-````````````````````````````````
-
-
-A link can come before its corresponding definition:
-
-```````````````````````````````` example
-[foo]
-
-[foo]: url
-.
-<p><a href="url">foo</a></p>
-````````````````````````````````
-
-
-If there are several matching definitions, the first one takes
-precedence:
-
-```````````````````````````````` example
-[foo]
-
-[foo]: first
-[foo]: second
-.
-<p><a href="first">foo</a></p>
-````````````````````````````````
-
-
-As noted in the section on [Links], matching of labels is
-case-insensitive (see [matches]).
-
-```````````````````````````````` example
-[FOO]: /url
-
-[Foo]
-.
-<p><a href="/url">Foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[ΑΓΩ]: /φου
-
-[αγω]
-.
-<p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
-````````````````````````````````
-
-
-Here is a link reference definition with no corresponding link.
-It contributes nothing to the document.
-
-```````````````````````````````` example
-[foo]: /url
-.
-````````````````````````````````
-
-
-Here is another one:
-
-```````````````````````````````` example
-[
-foo
-]: /url
-bar
-.
-<p>bar</p>
-````````````````````````````````
-
-
-This is not a link reference definition, because there are
-[non-whitespace characters] after the title:
-
-```````````````````````````````` example
-[foo]: /url "title" ok
-.
-<p>[foo]: /url "title" ok</p>
-````````````````````````````````
-
-
-This is a link reference definition, but it has no title:
-
-```````````````````````````````` example
-[foo]: /url
-"title" ok
-.
-<p>"title" ok</p>
-````````````````````````````````
-
-
-This is not a link reference definition, because it is indented
-four spaces:
-
-```````````````````````````````` example
- [foo]: /url "title"
-
-[foo]
-.
-<pre><code>[foo]: /url "title"
-</code></pre>
-<p>[foo]</p>
-````````````````````````````````
-
-
-This is not a link reference definition, because it occurs inside
-a code block:
-
-```````````````````````````````` example
-```
-[foo]: /url
-```
-
-[foo]
-.
-<pre><code>[foo]: /url
-</code></pre>
-<p>[foo]</p>
-````````````````````````````````
-
-
-A [link reference definition] cannot interrupt a paragraph.
-
-```````````````````````````````` example
-Foo
-[bar]: /baz
-
-[bar]
-.
-<p>Foo
-[bar]: /baz</p>
-<p>[bar]</p>
-````````````````````````````````
-
-
-However, it can directly follow other block elements, such as headings
-and thematic breaks, and it need not be followed by a blank line.
-
-```````````````````````````````` example
-# [Foo]
-[foo]: /url
-> bar
-.
-<h1><a href="/url">Foo</a></h1>
-<blockquote>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-
-Several [link reference definitions]
-can occur one after another, without intervening blank lines.
-
-```````````````````````````````` example
-[foo]: /foo-url "foo"
-[bar]: /bar-url
- "bar"
-[baz]: /baz-url
-
-[foo],
-[bar],
-[baz]
-.
-<p><a href="/foo-url" title="foo">foo</a>,
-<a href="/bar-url" title="bar">bar</a>,
-<a href="/baz-url">baz</a></p>
-````````````````````````````````
-
-
-[Link reference definitions] can occur
-inside block containers, like lists and block quotations. They
-affect the entire document, not just the container in which they
-are defined:
-
-```````````````````````````````` example
-[foo]
-
-> [foo]: /url
-.
-<p><a href="/url">foo</a></p>
-<blockquote>
-</blockquote>
-````````````````````````````````
-
-
-
-## Paragraphs
-
-A sequence of non-blank lines that cannot be interpreted as other
-kinds of blocks forms a [paragraph](@).
-The contents of the paragraph are the result of parsing the
-paragraph's raw content as inlines. The paragraph's raw content
-is formed by concatenating the lines and removing initial and final
-[whitespace].
-
-A simple example with two paragraphs:
-
-```````````````````````````````` example
-aaa
-
-bbb
-.
-<p>aaa</p>
-<p>bbb</p>
-````````````````````````````````
-
-
-Paragraphs can contain multiple lines, but no blank lines:
-
-```````````````````````````````` example
-aaa
-bbb
-
-ccc
-ddd
-.
-<p>aaa
-bbb</p>
-<p>ccc
-ddd</p>
-````````````````````````````````
-
-
-Multiple blank lines between paragraph have no effect:
-
-```````````````````````````````` example
-aaa
-
-
-bbb
-.
-<p>aaa</p>
-<p>bbb</p>
-````````````````````````````````
-
-
-Leading spaces are skipped:
-
-```````````````````````````````` example
- aaa
- bbb
-.
-<p>aaa
-bbb</p>
-````````````````````````````````
-
-
-Lines after the first may be indented any amount, since indented
-code blocks cannot interrupt paragraphs.
-
-```````````````````````````````` example
-aaa
- bbb
- ccc
-.
-<p>aaa
-bbb
-ccc</p>
-````````````````````````````````
-
-
-However, the first line may be indented at most three spaces,
-or an indented code block will be triggered:
-
-```````````````````````````````` example
- aaa
-bbb
-.
-<p>aaa
-bbb</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- aaa
-bbb
-.
-<pre><code>aaa
-</code></pre>
-<p>bbb</p>
-````````````````````````````````
-
-
-Final spaces are stripped before inline parsing, so a paragraph
-that ends with two or more spaces will not end with a [hard line
-break]:
-
-```````````````````````````````` example
-aaa
-bbb
-.
-<p>aaa<br />
-bbb</p>
-````````````````````````````````
-
-
-## Blank lines
-
-[Blank lines] between block-level elements are ignored,
-except for the role they play in determining whether a [list]
-is [tight] or [loose].
-
-Blank lines at the beginning and end of the document are also ignored.
-
-```````````````````````````````` example
-
-
-aaa
-
-
-# aaa
-
-
-.
-<p>aaa</p>
-<h1>aaa</h1>
-````````````````````````````````
-
-
-
-# Container blocks
-
-A [container block] is a block that has other
-blocks as its contents. There are two basic kinds of container blocks:
-[block quotes] and [list items].
-[Lists] are meta-containers for [list items].
-
-We define the syntax for container blocks recursively. The general
-form of the definition is:
-
-> If X is a sequence of blocks, then the result of
-> transforming X in such-and-such a way is a container of type Y
-> with these blocks as its content.
-
-So, we explain what counts as a block quote or list item by explaining
-how these can be *generated* from their contents. This should suffice
-to define the syntax, although it does not give a recipe for *parsing*
-these constructions. (A recipe is provided below in the section entitled
-[A parsing strategy](#appendix-a-parsing-strategy).)
-
-## Block quotes
-
-A [block quote marker](@)
-consists of 0-3 spaces of initial indent, plus (a) the character `>` together
-with a following space, or (b) a single character `>` not followed by a space.
-
-The following rules define [block quotes]:
-
-1. **Basic case.** If a string of lines *Ls* constitute a sequence
- of blocks *Bs*, then the result of prepending a [block quote
- marker] to the beginning of each line in *Ls*
- is a [block quote](#block-quotes) containing *Bs*.
-
-2. **Laziness.** If a string of lines *Ls* constitute a [block
- quote](#block-quotes) with contents *Bs*, then the result of deleting
- the initial [block quote marker] from one or
- more lines in which the next [non-whitespace character] after the [block
- quote marker] is [paragraph continuation
- text] is a block quote with *Bs* as its content.
- [Paragraph continuation text](@) is text
- that will be parsed as part of the content of a paragraph, but does
- not occur at the beginning of the paragraph.
-
-3. **Consecutiveness.** A document cannot contain two [block
- quotes] in a row unless there is a [blank line] between them.
-
-Nothing else counts as a [block quote](#block-quotes).
-
-Here is a simple example:
-
-```````````````````````````````` example
-> # Foo
-> bar
-> baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-The spaces after the `>` characters can be omitted:
-
-```````````````````````````````` example
-># Foo
->bar
-> baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-The `>` characters can be indented 1-3 spaces:
-
-```````````````````````````````` example
- > # Foo
- > bar
- > baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-Four spaces gives us a code block:
-
-```````````````````````````````` example
- > # Foo
- > bar
- > baz
-.
-<pre><code>> # Foo
-> bar
-> baz
-</code></pre>
-````````````````````````````````
-
-
-The Laziness clause allows us to omit the `>` before a
-paragraph continuation line:
-
-```````````````````````````````` example
-> # Foo
-> bar
-baz
-.
-<blockquote>
-<h1>Foo</h1>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-A block quote can contain some lazy and some non-lazy
-continuation lines:
-
-```````````````````````````````` example
-> bar
-baz
-> foo
-.
-<blockquote>
-<p>bar
-baz
-foo</p>
-</blockquote>
-````````````````````````````````
-
-
-Laziness only applies to lines that would have been continuations of
-paragraphs had they been prepended with [block quote markers].
-For example, the `> ` cannot be omitted in the second line of
-
-``` markdown
-> foo
-> ---
-```
-
-without changing the meaning:
-
-```````````````````````````````` example
-> foo
----
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-<hr />
-````````````````````````````````
-
-
-Similarly, if we omit the `> ` in the second line of
-
-``` markdown
-> - foo
-> - bar
-```
-
-then the block quote ends after the first line:
-
-```````````````````````````````` example
-> - foo
-- bar
-.
-<blockquote>
-<ul>
-<li>foo</li>
-</ul>
-</blockquote>
-<ul>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-For the same reason, we can't omit the `> ` in front of
-subsequent lines of an indented or fenced code block:
-
-```````````````````````````````` example
-> foo
- bar
-.
-<blockquote>
-<pre><code>foo
-</code></pre>
-</blockquote>
-<pre><code>bar
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> ```
-foo
-```
-.
-<blockquote>
-<pre><code></code></pre>
-</blockquote>
-<p>foo</p>
-<pre><code></code></pre>
-````````````````````````````````
-
-
-Note that in the following case, we have a paragraph
-continuation line:
-
-```````````````````````````````` example
-> foo
- - bar
-.
-<blockquote>
-<p>foo
-- bar</p>
-</blockquote>
-````````````````````````````````
-
-
-To see why, note that in
-
-```markdown
-> foo
-> - bar
-```
-
-the `- bar` is indented too far to start a list, and can't
-be an indented code block because indented code blocks cannot
-interrupt paragraphs, so it is a [paragraph continuation line].
-
-A block quote can be empty:
-
-```````````````````````````````` example
->
-.
-<blockquote>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
->
->
->
-.
-<blockquote>
-</blockquote>
-````````````````````````````````
-
-
-A block quote can have initial or final blank lines:
-
-```````````````````````````````` example
->
-> foo
->
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-````````````````````````````````
-
-
-A blank line always separates block quotes:
-
-```````````````````````````````` example
-> foo
-
-> bar
-.
-<blockquote>
-<p>foo</p>
-</blockquote>
-<blockquote>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-
-(Most current Markdown implementations, including John Gruber's
-original `Markdown.pl`, will parse this example as a single block quote
-with two paragraphs. But it seems better to allow the author to decide
-whether two block quotes or one are wanted.)
-
-Consecutiveness means that if we put these block quotes together,
-we get a single block quote:
-
-```````````````````````````````` example
-> foo
-> bar
-.
-<blockquote>
-<p>foo
-bar</p>
-</blockquote>
-````````````````````````````````
-
-
-To get a block quote with two paragraphs, use:
-
-```````````````````````````````` example
-> foo
->
-> bar
-.
-<blockquote>
-<p>foo</p>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-
-Block quotes can interrupt paragraphs:
-
-```````````````````````````````` example
-foo
-> bar
-.
-<p>foo</p>
-<blockquote>
-<p>bar</p>
-</blockquote>
-````````````````````````````````
-
-
-In general, blank lines are not needed before or after block
-quotes:
-
-```````````````````````````````` example
-> aaa
-***
-> bbb
-.
-<blockquote>
-<p>aaa</p>
-</blockquote>
-<hr />
-<blockquote>
-<p>bbb</p>
-</blockquote>
-````````````````````````````````
-
-
-However, because of laziness, a blank line is needed between
-a block quote and a following paragraph:
-
-```````````````````````````````` example
-> bar
-baz
-.
-<blockquote>
-<p>bar
-baz</p>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> bar
-
-baz
-.
-<blockquote>
-<p>bar</p>
-</blockquote>
-<p>baz</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> bar
->
-baz
-.
-<blockquote>
-<p>bar</p>
-</blockquote>
-<p>baz</p>
-````````````````````````````````
-
-
-It is a consequence of the Laziness rule that any number
-of initial `>`s may be omitted on a continuation line of a
-nested block quote:
-
-```````````````````````````````` example
-> > > foo
-bar
-.
-<blockquote>
-<blockquote>
-<blockquote>
-<p>foo
-bar</p>
-</blockquote>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
->>> foo
-> bar
->>baz
-.
-<blockquote>
-<blockquote>
-<blockquote>
-<p>foo
-bar
-baz</p>
-</blockquote>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-When including an indented code block in a block quote,
-remember that the [block quote marker] includes
-both the `>` and a following space. So *five spaces* are needed after
-the `>`:
-
-```````````````````````````````` example
-> code
-
-> not code
-.
-<blockquote>
-<pre><code>code
-</code></pre>
-</blockquote>
-<blockquote>
-<p>not code</p>
-</blockquote>
-````````````````````````````````
-
-
-
-## List items
-
-A [list marker](@) is a
-[bullet list marker] or an [ordered list marker].
-
-A [bullet list marker](@)
-is a `-`, `+`, or `*` character.
-
-An [ordered list marker](@)
-is a sequence of 1--9 arabic digits (`0-9`), followed by either a
-`.` character or a `)` character. (The reason for the length
-limit is that with 10 digits we start seeing integer overflows
-in some browsers.)
-
-The following rules define [list items]:
-
-1. **Basic case.** If a sequence of lines *Ls* constitute a sequence of
- blocks *Bs* starting with a [non-whitespace character] and not separated
- from each other by more than one blank line, and *M* is a list
- marker of width *W* followed by 0 < *N* < 5 spaces, then the result
- of prepending *M* and the following spaces to the first line of
- *Ls*, and indenting subsequent lines of *Ls* by *W + N* spaces, is a
- list item with *Bs* as its contents. The type of the list item
- (bullet or ordered) is determined by the type of its list marker.
- If the list item is ordered, then it is also assigned a start
- number, based on the ordered list marker.
-
-For example, let *Ls* be the lines
-
-```````````````````````````````` example
-A paragraph
-with two lines.
-
- indented code
-
-> A block quote.
-.
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-````````````````````````````````
-
-
-And let *M* be the marker `1.`, and *N* = 2. Then rule #1 says
-that the following is an ordered list item with start number 1,
-and the same contents as *Ls*:
-
-```````````````````````````````` example
-1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-The most important thing to notice is that the position of
-the text after the list marker determines how much indentation
-is needed in subsequent blocks in the list item. If the list
-marker takes up two spaces, and there are three spaces between
-the list marker and the next [non-whitespace character], then blocks
-must be indented five spaces in order to fall under the list
-item.
-
-Here are some examples showing how far content must be indented to be
-put under the list item:
-
-```````````````````````````````` example
-- one
-
- two
-.
-<ul>
-<li>one</li>
-</ul>
-<p>two</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- one
-
- two
-.
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
- - one
-
- two
-.
-<ul>
-<li>one</li>
-</ul>
-<pre><code> two
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
- - one
-
- two
-.
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-It is tempting to think of this in terms of columns: the continuation
-blocks must be indented at least to the column of the first
-[non-whitespace character] after the list marker. However, that is not quite right.
-The spaces after the list marker determine how much relative indentation
-is needed. Which column this indentation reaches will depend on
-how the list item is embedded in other constructions, as shown by
-this example:
-
-```````````````````````````````` example
- > > 1. one
->>
->> two
-.
-<blockquote>
-<blockquote>
-<ol>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ol>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-Here `two` occurs in the same column as the list marker `1.`,
-but is actually contained in the list item, because there is
-sufficient indentation after the last containing blockquote marker.
-
-The converse is also possible. In the following example, the word `two`
-occurs far to the right of the initial text of the list item, `one`, but
-it is not considered part of the list item, because it is not indented
-far enough past the blockquote marker:
-
-```````````````````````````````` example
->>- one
->>
- > > two
-.
-<blockquote>
-<blockquote>
-<ul>
-<li>one</li>
-</ul>
-<p>two</p>
-</blockquote>
-</blockquote>
-````````````````````````````````
-
-
-Note that at least one space is needed between the list marker and
-any following content, so these are not list items:
-
-```````````````````````````````` example
--one
-
-2.two
-.
-<p>-one</p>
-<p>2.two</p>
-````````````````````````````````
-
-
-A list item may not contain blocks that are separated by more than
-one blank line. Thus, two blank lines will end a list, unless the
-two blanks are contained in a [fenced code block].
-
-```````````````````````````````` example
-- foo
-
- bar
-
-- foo
-
-
- bar
-
-- ```
- foo
-
-
- bar
- ```
-
-- baz
-
- + ```
- foo
-
-
- bar
- ```
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-<li>
-<p>foo</p>
-</li>
-</ul>
-<p>bar</p>
-<ul>
-<li>
-<pre><code>foo
-
-
-bar
-</code></pre>
-</li>
-<li>
-<p>baz</p>
-<ul>
-<li>
-<pre><code>foo
-
-
-bar
-</code></pre>
-</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-A list item may contain any kind of block:
-
-```````````````````````````````` example
-1. foo
-
- ```
- bar
- ```
-
- baz
-
- > bam
-.
-<ol>
-<li>
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-<p>baz</p>
-<blockquote>
-<p>bam</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-A list item that contains an indented code block will preserve
-empty lines within the code block verbatim, unless there are two
-or more empty lines in a row (since as described above, two
-blank lines end the list):
-
-```````````````````````````````` example
-- Foo
-
- bar
-
- baz
-.
-<ul>
-<li>
-<p>Foo</p>
-<pre><code>bar
-
-baz
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- Foo
-
- bar
-
-
- baz
-.
-<ul>
-<li>
-<p>Foo</p>
-<pre><code>bar
-</code></pre>
-</li>
-</ul>
-<pre><code> baz
-</code></pre>
-````````````````````````````````
-
-
-Note that ordered list start numbers must be nine digits or less:
-
-```````````````````````````````` example
-123456789. ok
-.
-<ol start="123456789">
-<li>ok</li>
-</ol>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1234567890. not ok
-.
-<p>1234567890. not ok</p>
-````````````````````````````````
-
-
-A start number may begin with 0s:
-
-```````````````````````````````` example
-0. ok
-.
-<ol start="0">
-<li>ok</li>
-</ol>
-````````````````````````````````
-
-
-```````````````````````````````` example
-003. ok
-.
-<ol start="3">
-<li>ok</li>
-</ol>
-````````````````````````````````
-
-
-A start number may not be negative:
-
-```````````````````````````````` example
--1. not ok
-.
-<p>-1. not ok</p>
-````````````````````````````````
-
-
-
-2. **Item starting with indented code.** If a sequence of lines *Ls*
- constitute a sequence of blocks *Bs* starting with an indented code
- block and not separated from each other by more than one blank line,
- and *M* is a list marker of width *W* followed by
- one space, then the result of prepending *M* and the following
- space to the first line of *Ls*, and indenting subsequent lines of
- *Ls* by *W + 1* spaces, is a list item with *Bs* as its contents.
- If a line is empty, then it need not be indented. The type of the
- list item (bullet or ordered) is determined by the type of its list
- marker. If the list item is ordered, then it is also assigned a
- start number, based on the ordered list marker.
-
-An indented code block will have to be indented four spaces beyond
-the edge of the region where text will be included in the list item.
-In the following case that is 6 spaces:
-
-```````````````````````````````` example
-- foo
-
- bar
-.
-<ul>
-<li>
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-
-And in this case it is 11 spaces:
-
-```````````````````````````````` example
- 10. foo
-
- bar
-.
-<ol start="10">
-<li>
-<p>foo</p>
-<pre><code>bar
-</code></pre>
-</li>
-</ol>
-````````````````````````````````
-
-
-If the *first* block in the list item is an indented code block,
-then by rule #2, the contents must be indented *one* space after the
-list marker:
-
-```````````````````````````````` example
- indented code
-
-paragraph
-
- more code
-.
-<pre><code>indented code
-</code></pre>
-<p>paragraph</p>
-<pre><code>more code
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. indented code
-
- paragraph
-
- more code
-.
-<ol>
-<li>
-<pre><code>indented code
-</code></pre>
-<p>paragraph</p>
-<pre><code>more code
-</code></pre>
-</li>
-</ol>
-````````````````````````````````
-
-
-Note that an additional space indent is interpreted as space
-inside the code block:
-
-```````````````````````````````` example
-1. indented code
-
- paragraph
-
- more code
-.
-<ol>
-<li>
-<pre><code> indented code
-</code></pre>
-<p>paragraph</p>
-<pre><code>more code
-</code></pre>
-</li>
-</ol>
-````````````````````````````````
-
-
-Note that rules #1 and #2 only apply to two cases: (a) cases
-in which the lines to be included in a list item begin with a
-[non-whitespace character], and (b) cases in which
-they begin with an indented code
-block. In a case like the following, where the first block begins with
-a three-space indent, the rules do not allow us to form a list item by
-indenting the whole thing and prepending a list marker:
-
-```````````````````````````````` example
- foo
-
-bar
-.
-<p>foo</p>
-<p>bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- foo
-
- bar
-.
-<ul>
-<li>foo</li>
-</ul>
-<p>bar</p>
-````````````````````````````````
-
-
-This is not a significant restriction, because when a block begins
-with 1-3 spaces indent, the indentation can always be removed without
-a change in interpretation, allowing rule #1 to be applied. So, in
-the above case:
-
-```````````````````````````````` example
-- foo
-
- bar
-.
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-3. **Item starting with a blank line.** If a sequence of lines *Ls*
- starting with a single [blank line] constitute a (possibly empty)
- sequence of blocks *Bs*, not separated from each other by more than
- one blank line, and *M* is a list marker of width *W*,
- then the result of prepending *M* to the first line of *Ls*, and
- indenting subsequent lines of *Ls* by *W + 1* spaces, is a list
- item with *Bs* as its contents.
- If a line is empty, then it need not be indented. The type of the
- list item (bullet or ordered) is determined by the type of its list
- marker. If the list item is ordered, then it is also assigned a
- start number, based on the ordered list marker.
-
-Here are some list items that start with a blank line but are not empty:
-
-```````````````````````````````` example
--
- foo
--
- ```
- bar
- ```
--
- baz
-.
-<ul>
-<li>foo</li>
-<li>
-<pre><code>bar
-</code></pre>
-</li>
-<li>
-<pre><code>baz
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-When the list item starts with a blank line, the number of spaces
-following the list marker doesn't change the required indentation:
-
-```````````````````````````````` example
--
- foo
-.
-<ul>
-<li>foo</li>
-</ul>
-````````````````````````````````
-
-
-A list item can begin with at most one blank line.
-In the following example, `foo` is not part of the list
-item:
-
-```````````````````````````````` example
--
-
- foo
-.
-<ul>
-<li></li>
-</ul>
-<p>foo</p>
-````````````````````````````````
-
-
-Here is an empty bullet list item:
-
-```````````````````````````````` example
-- foo
--
-- bar
-.
-<ul>
-<li>foo</li>
-<li></li>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-It does not matter whether there are spaces following the [list marker]:
-
-```````````````````````````````` example
-- foo
--
-- bar
-.
-<ul>
-<li>foo</li>
-<li></li>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-Here is an empty ordered list item:
-
-```````````````````````````````` example
-1. foo
-2.
-3. bar
-.
-<ol>
-<li>foo</li>
-<li></li>
-<li>bar</li>
-</ol>
-````````````````````````````````
-
-
-A list may start or end with an empty list item:
-
-```````````````````````````````` example
-*
-.
-<ul>
-<li></li>
-</ul>
-````````````````````````````````
-
-
-
-4. **Indentation.** If a sequence of lines *Ls* constitutes a list item
- according to rule #1, #2, or #3, then the result of indenting each line
- of *Ls* by 1-3 spaces (the same for each line) also constitutes a
- list item with the same contents and attributes. If a line is
- empty, then it need not be indented.
-
-Indented one space:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Indented two spaces:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Indented three spaces:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Four spaces indent gives a code block:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-.
-<pre><code>1. A paragraph
- with two lines.
-
- indented code
-
- > A block quote.
-</code></pre>
-````````````````````````````````
-
-
-
-5. **Laziness.** If a string of lines *Ls* constitute a [list
- item](#list-items) with contents *Bs*, then the result of deleting
- some or all of the indentation from one or more lines in which the
- next [non-whitespace character] after the indentation is
- [paragraph continuation text] is a
- list item with the same contents and attributes. The unindented
- lines are called
- [lazy continuation line](@)s.
-
-Here is an example with [lazy continuation lines]:
-
-```````````````````````````````` example
- 1. A paragraph
-with two lines.
-
- indented code
-
- > A block quote.
-.
-<ol>
-<li>
-<p>A paragraph
-with two lines.</p>
-<pre><code>indented code
-</code></pre>
-<blockquote>
-<p>A block quote.</p>
-</blockquote>
-</li>
-</ol>
-````````````````````````````````
-
-
-Indentation can be partially deleted:
-
-```````````````````````````````` example
- 1. A paragraph
- with two lines.
-.
-<ol>
-<li>A paragraph
-with two lines.</li>
-</ol>
-````````````````````````````````
-
-
-These examples show how laziness can work in nested structures:
-
-```````````````````````````````` example
-> 1. > Blockquote
-continued here.
-.
-<blockquote>
-<ol>
-<li>
-<blockquote>
-<p>Blockquote
-continued here.</p>
-</blockquote>
-</li>
-</ol>
-</blockquote>
-````````````````````````````````
-
-
-```````````````````````````````` example
-> 1. > Blockquote
-> continued here.
-.
-<blockquote>
-<ol>
-<li>
-<blockquote>
-<p>Blockquote
-continued here.</p>
-</blockquote>
-</li>
-</ol>
-</blockquote>
-````````````````````````````````
-
-
-
-6. **That's all.** Nothing that is not counted as a list item by rules
- #1--5 counts as a [list item](#list-items).
-
-The rules for sublists follow from the general rules above. A sublist
-must be indented the same number of spaces a paragraph would need to be
-in order to be included in the list item.
-
-So, in this case we need two spaces indent:
-
-```````````````````````````````` example
-- foo
- - bar
- - baz
-.
-<ul>
-<li>foo
-<ul>
-<li>bar
-<ul>
-<li>baz</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-One is not enough:
-
-```````````````````````````````` example
-- foo
- - bar
- - baz
-.
-<ul>
-<li>foo</li>
-<li>bar</li>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-
-Here we need four, because the list marker is wider:
-
-```````````````````````````````` example
-10) foo
- - bar
-.
-<ol start="10">
-<li>foo
-<ul>
-<li>bar</li>
-</ul>
-</li>
-</ol>
-````````````````````````````````
-
-
-Three is not enough:
-
-```````````````````````````````` example
-10) foo
- - bar
-.
-<ol start="10">
-<li>foo</li>
-</ol>
-<ul>
-<li>bar</li>
-</ul>
-````````````````````````````````
-
-
-A list may be the first block in a list item:
-
-```````````````````````````````` example
-- - foo
-.
-<ul>
-<li>
-<ul>
-<li>foo</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. - 2. foo
-.
-<ol>
-<li>
-<ul>
-<li>
-<ol start="2">
-<li>foo</li>
-</ol>
-</li>
-</ul>
-</li>
-</ol>
-````````````````````````````````
-
-
-A list item can contain a heading:
-
-```````````````````````````````` example
-- # Foo
-- Bar
- ---
- baz
-.
-<ul>
-<li>
-<h1>Foo</h1>
-</li>
-<li>
-<h2>Bar</h2>
-baz</li>
-</ul>
-````````````````````````````````
-
-
-### Motivation
-
-John Gruber's Markdown spec says the following about list items:
-
-1. "List markers typically start at the left margin, but may be indented
- by up to three spaces. List markers must be followed by one or more
- spaces or a tab."
-
-2. "To make lists look nice, you can wrap items with hanging indents....
- But if you don't want to, you don't have to."
-
-3. "List items may consist of multiple paragraphs. Each subsequent
- paragraph in a list item must be indented by either 4 spaces or one
- tab."
-
-4. "It looks nice if you indent every line of the subsequent paragraphs,
- but here again, Markdown will allow you to be lazy."
-
-5. "To put a blockquote within a list item, the blockquote's `>`
- delimiters need to be indented."
-
-6. "To put a code block within a list item, the code block needs to be
- indented twice — 8 spaces or two tabs."
-
-These rules specify that a paragraph under a list item must be indented
-four spaces (presumably, from the left margin, rather than the start of
-the list marker, but this is not said), and that code under a list item
-must be indented eight spaces instead of the usual four. They also say
-that a block quote must be indented, but not by how much; however, the
-example given has four spaces indentation. Although nothing is said
-about other kinds of block-level content, it is certainly reasonable to
-infer that *all* block elements under a list item, including other
-lists, must be indented four spaces. This principle has been called the
-*four-space rule*.
-
-The four-space rule is clear and principled, and if the reference
-implementation `Markdown.pl` had followed it, it probably would have
-become the standard. However, `Markdown.pl` allowed paragraphs and
-sublists to start with only two spaces indentation, at least on the
-outer level. Worse, its behavior was inconsistent: a sublist of an
-outer-level list needed two spaces indentation, but a sublist of this
-sublist needed three spaces. It is not surprising, then, that different
-implementations of Markdown have developed very different rules for
-determining what comes under a list item. (Pandoc and python-Markdown,
-for example, stuck with Gruber's syntax description and the four-space
-rule, while discount, redcarpet, marked, PHP Markdown, and others
-followed `Markdown.pl`'s behavior more closely.)
-
-Unfortunately, given the divergences between implementations, there
-is no way to give a spec for list items that will be guaranteed not
-to break any existing documents. However, the spec given here should
-correctly handle lists formatted with either the four-space rule or
-the more forgiving `Markdown.pl` behavior, provided they are laid out
-in a way that is natural for a human to read.
-
-The strategy here is to let the width and indentation of the list marker
-determine the indentation necessary for blocks to fall under the list
-item, rather than having a fixed and arbitrary number. The writer can
-think of the body of the list item as a unit which gets indented to the
-right enough to fit the list marker (and any indentation on the list
-marker). (The laziness rule, #5, then allows continuation lines to be
-unindented if needed.)
-
-This rule is superior, we claim, to any rule requiring a fixed level of
-indentation from the margin. The four-space rule is clear but
-unnatural. It is quite unintuitive that
-
-``` markdown
-- foo
-
- bar
-
- - baz
-```
-
-should be parsed as two lists with an intervening paragraph,
-
-``` html
-<ul>
-<li>foo</li>
-</ul>
-<p>bar</p>
-<ul>
-<li>baz</li>
-</ul>
-```
-
-as the four-space rule demands, rather than a single list,
-
-``` html
-<ul>
-<li>
-<p>foo</p>
-<p>bar</p>
-<ul>
-<li>baz</li>
-</ul>
-</li>
-</ul>
-```
-
-The choice of four spaces is arbitrary. It can be learned, but it is
-not likely to be guessed, and it trips up beginners regularly.
-
-Would it help to adopt a two-space rule? The problem is that such
-a rule, together with the rule allowing 1--3 spaces indentation of the
-initial list marker, allows text that is indented *less than* the
-original list marker to be included in the list item. For example,
-`Markdown.pl` parses
-
-``` markdown
- - one
-
- two
-```
-
-as a single list item, with `two` a continuation paragraph:
-
-``` html
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-```
-
-and similarly
-
-``` markdown
-> - one
->
-> two
-```
-
-as
-
-``` html
-<blockquote>
-<ul>
-<li>
-<p>one</p>
-<p>two</p>
-</li>
-</ul>
-</blockquote>
-```
-
-This is extremely unintuitive.
-
-Rather than requiring a fixed indent from the margin, we could require
-a fixed indent (say, two spaces, or even one space) from the list marker (which
-may itself be indented). This proposal would remove the last anomaly
-discussed. Unlike the spec presented above, it would count the following
-as a list item with a subparagraph, even though the paragraph `bar`
-is not indented as far as the first paragraph `foo`:
-
-``` markdown
- 10. foo
-
- bar
-```
-
-Arguably this text does read like a list item with `bar` as a subparagraph,
-which may count in favor of the proposal. However, on this proposal indented
-code would have to be indented six spaces after the list marker. And this
-would break a lot of existing Markdown, which has the pattern:
-
-``` markdown
-1. foo
-
- indented code
-```
-
-where the code is indented eight spaces. The spec above, by contrast, will
-parse this text as expected, since the code block's indentation is measured
-from the beginning of `foo`.
-
-The one case that needs special treatment is a list item that *starts*
-with indented code. How much indentation is required in that case, since
-we don't have a "first paragraph" to measure from? Rule #2 simply stipulates
-that in such cases, we require one space indentation from the list marker
-(and then the normal four spaces for the indented code). This will match the
-four-space rule in cases where the list marker plus its initial indentation
-takes four spaces (a common case), but diverge in other cases.
-
-## Lists
-
-A [list](@) is a sequence of one or more
-list items [of the same type]. The list items
-may be separated by single [blank lines], but two
-blank lines end all containing lists.
-
-Two list items are [of the same type](@)
-if they begin with a [list marker] of the same type.
-Two list markers are of the
-same type if (a) they are bullet list markers using the same character
-(`-`, `+`, or `*`) or (b) they are ordered list numbers with the same
-delimiter (either `.` or `)`).
-
-A list is an [ordered list](@)
-if its constituent list items begin with
-[ordered list markers], and a
-[bullet list](@) if its constituent list
-items begin with [bullet list markers].
-
-The [start number](@)
-of an [ordered list] is determined by the list number of
-its initial list item. The numbers of subsequent list items are
-disregarded.
-
-A list is [loose](@) if any of its constituent
-list items are separated by blank lines, or if any of its constituent
-list items directly contain two block-level elements with a blank line
-between them. Otherwise a list is [tight](@).
-(The difference in HTML output is that paragraphs in a loose list are
-wrapped in `<p>` tags, while paragraphs in a tight list are not.)
-
-Changing the bullet or ordered list delimiter starts a new list:
-
-```````````````````````````````` example
-- foo
-- bar
-+ baz
-.
-<ul>
-<li>foo</li>
-<li>bar</li>
-</ul>
-<ul>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. foo
-2. bar
-3) baz
-.
-<ol>
-<li>foo</li>
-<li>bar</li>
-</ol>
-<ol start="3">
-<li>baz</li>
-</ol>
-````````````````````````````````
-
-
-In CommonMark, a list can interrupt a paragraph. That is,
-no blank line is needed to separate a paragraph from a following
-list:
-
-```````````````````````````````` example
-Foo
-- bar
-- baz
-.
-<p>Foo</p>
-<ul>
-<li>bar</li>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-
-`Markdown.pl` does not allow this, through fear of triggering a list
-via a numeral in a hard-wrapped line:
-
-```````````````````````````````` example
-The number of windows in my house is
-14. The number of doors is 6.
-.
-<p>The number of windows in my house is</p>
-<ol start="14">
-<li>The number of doors is 6.</li>
-</ol>
-````````````````````````````````
-
-
-Oddly, `Markdown.pl` *does* allow a blockquote to interrupt a paragraph,
-even though the same considerations might apply. We think that the two
-cases should be treated the same. Here are two reasons for allowing
-lists to interrupt paragraphs:
-
-First, it is natural and not uncommon for people to start lists without
-blank lines:
-
- I need to buy
- - new shoes
- - a coat
- - a plane ticket
-
-Second, we are attracted to a
-
-> [principle of uniformity](@):
-> if a chunk of text has a certain
-> meaning, it will continue to have the same meaning when put into a
-> container block (such as a list item or blockquote).
-
-(Indeed, the spec for [list items] and [block quotes] presupposes
-this principle.) This principle implies that if
-
- * I need to buy
- - new shoes
- - a coat
- - a plane ticket
-
-is a list item containing a paragraph followed by a nested sublist,
-as all Markdown implementations agree it is (though the paragraph
-may be rendered without `<p>` tags, since the list is "tight"),
-then
-
- I need to buy
- - new shoes
- - a coat
- - a plane ticket
-
-by itself should be a paragraph followed by a nested sublist.
-
-Our adherence to the [principle of uniformity]
-thus inclines us to think that there are two coherent packages:
-
-1. Require blank lines before *all* lists and blockquotes,
- including lists that occur as sublists inside other list items.
-
-2. Require blank lines in none of these places.
-
-[reStructuredText](http://docutils.sourceforge.net/rst.html) takes
-the first approach, for which there is much to be said. But the second
-seems more consistent with established practice with Markdown.
-
-There can be blank lines between items, but two blank lines end
-a list:
-
-```````````````````````````````` example
-- foo
-
-- bar
-
-
-- baz
-.
-<ul>
-<li>
-<p>foo</p>
-</li>
-<li>
-<p>bar</p>
-</li>
-</ul>
-<ul>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-
-As illustrated above in the section on [list items],
-two blank lines between blocks *within* a list item will also end a
-list:
-
-```````````````````````````````` example
-- foo
-
-
- bar
-- baz
-.
-<ul>
-<li>foo</li>
-</ul>
-<p>bar</p>
-<ul>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-
-Indeed, two blank lines will end *all* containing lists:
-
-```````````````````````````````` example
-- foo
- - bar
- - baz
-
-
- bim
-.
-<ul>
-<li>foo
-<ul>
-<li>bar
-<ul>
-<li>baz</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-<pre><code> bim
-</code></pre>
-````````````````````````````````
-
-
-Thus, two blank lines can be used to separate consecutive lists of
-the same type, or to separate a list from an indented code block
-that would otherwise be parsed as a subparagraph of the final list
-item:
-
-```````````````````````````````` example
-- foo
-- bar
-
-
-- baz
-- bim
-.
-<ul>
-<li>foo</li>
-<li>bar</li>
-</ul>
-<ul>
-<li>baz</li>
-<li>bim</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- foo
-
- notcode
-
-- foo
-
-
- code
-.
-<ul>
-<li>
-<p>foo</p>
-<p>notcode</p>
-</li>
-<li>
-<p>foo</p>
-</li>
-</ul>
-<pre><code>code
-</code></pre>
-````````````````````````````````
-
-
-List items need not be indented to the same level. The following
-list items will be treated as items at the same list level,
-since none is indented enough to belong to the previous list
-item:
-
-```````````````````````````````` example
-- a
- - b
- - c
- - d
- - e
- - f
- - g
- - h
-- i
-.
-<ul>
-<li>a</li>
-<li>b</li>
-<li>c</li>
-<li>d</li>
-<li>e</li>
-<li>f</li>
-<li>g</li>
-<li>h</li>
-<li>i</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-1. a
-
- 2. b
-
- 3. c
-.
-<ol>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-</li>
-<li>
-<p>c</p>
-</li>
-</ol>
-````````````````````````````````
-
-
-This is a loose list, because there is a blank line between
-two of the list items:
-
-```````````````````````````````` example
-- a
-- b
-
-- c
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-</li>
-<li>
-<p>c</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-So is this, with a empty second item:
-
-```````````````````````````````` example
-* a
-*
-
-* c
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li></li>
-<li>
-<p>c</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-These are loose lists, even though there is no space between the items,
-because one of the items directly contains two block-level elements
-with a blank line between them:
-
-```````````````````````````````` example
-- a
-- b
-
- c
-- d
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-<p>c</p>
-</li>
-<li>
-<p>d</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- a
-- b
-
- [ref]: /url
-- d
-.
-<ul>
-<li>
-<p>a</p>
-</li>
-<li>
-<p>b</p>
-</li>
-<li>
-<p>d</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-This is a tight list, because the blank lines are in a code block:
-
-```````````````````````````````` example
-- a
-- ```
- b
-
-
- ```
-- c
-.
-<ul>
-<li>a</li>
-<li>
-<pre><code>b
-
-
-</code></pre>
-</li>
-<li>c</li>
-</ul>
-````````````````````````````````
-
-
-This is a tight list, because the blank line is between two
-paragraphs of a sublist. So the sublist is loose while
-the outer list is tight:
-
-```````````````````````````````` example
-- a
- - b
-
- c
-- d
-.
-<ul>
-<li>a
-<ul>
-<li>
-<p>b</p>
-<p>c</p>
-</li>
-</ul>
-</li>
-<li>d</li>
-</ul>
-````````````````````````````````
-
-
-This is a tight list, because the blank line is inside the
-block quote:
-
-```````````````````````````````` example
-* a
- > b
- >
-* c
-.
-<ul>
-<li>a
-<blockquote>
-<p>b</p>
-</blockquote>
-</li>
-<li>c</li>
-</ul>
-````````````````````````````````
-
-
-This list is tight, because the consecutive block elements
-are not separated by blank lines:
-
-```````````````````````````````` example
-- a
- > b
- ```
- c
- ```
-- d
-.
-<ul>
-<li>a
-<blockquote>
-<p>b</p>
-</blockquote>
-<pre><code>c
-</code></pre>
-</li>
-<li>d</li>
-</ul>
-````````````````````````````````
-
-
-A single-paragraph list is tight:
-
-```````````````````````````````` example
-- a
-.
-<ul>
-<li>a</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- a
- - b
-.
-<ul>
-<li>a
-<ul>
-<li>b</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-This list is loose, because of the blank line between the
-two block elements in the list item:
-
-```````````````````````````````` example
-1. ```
- foo
- ```
-
- bar
-.
-<ol>
-<li>
-<pre><code>foo
-</code></pre>
-<p>bar</p>
-</li>
-</ol>
-````````````````````````````````
-
-
-Here the outer list is loose, the inner list tight:
-
-```````````````````````````````` example
-* foo
- * bar
-
- baz
-.
-<ul>
-<li>
-<p>foo</p>
-<ul>
-<li>bar</li>
-</ul>
-<p>baz</p>
-</li>
-</ul>
-````````````````````````````````
-
-
-```````````````````````````````` example
-- a
- - b
- - c
-
-- d
- - e
- - f
-.
-<ul>
-<li>
-<p>a</p>
-<ul>
-<li>b</li>
-<li>c</li>
-</ul>
-</li>
-<li>
-<p>d</p>
-<ul>
-<li>e</li>
-<li>f</li>
-</ul>
-</li>
-</ul>
-````````````````````````````````
-
-
-# Inlines
-
-Inlines are parsed sequentially from the beginning of the character
-stream to the end (left to right, in left-to-right languages).
-Thus, for example, in
-
-```````````````````````````````` example
-`hi`lo`
-.
-<p><code>hi</code>lo`</p>
-````````````````````````````````
-
-
-`hi` is parsed as code, leaving the backtick at the end as a literal
-backtick.
-
-## Backslash escapes
-
-Any ASCII punctuation character may be backslash-escaped:
-
-```````````````````````````````` example
-\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
-.
-<p>!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~</p>
-````````````````````````````````
-
-
-Backslashes before other characters are treated as literal
-backslashes:
-
-```````````````````````````````` example
-\→\A\a\ \3\φ\«
-.
-<p>\→\A\a\ \3\φ\«</p>
-````````````````````````````````
-
-
-Escaped characters are treated as regular characters and do
-not have their usual Markdown meanings:
-
-```````````````````````````````` example
-\*not emphasized*
-\<br/> not a tag
-\[not a link](/foo)
-\`not code`
-1\. not a list
-\* not a list
-\# not a heading
-\[foo]: /url "not a reference"
-.
-<p>*not emphasized*
-<br/> not a tag
-[not a link](/foo)
-`not code`
-1. not a list
-* not a list
-# not a heading
-[foo]: /url "not a reference"</p>
-````````````````````````````````
-
-
-If a backslash is itself escaped, the following character is not:
-
-```````````````````````````````` example
-\\*emphasis*
-.
-<p>\<em>emphasis</em></p>
-````````````````````````````````
-
-
-A backslash at the end of the line is a [hard line break]:
-
-```````````````````````````````` example
-foo\
-bar
-.
-<p>foo<br />
-bar</p>
-````````````````````````````````
-
-
-Backslash escapes do not work in code blocks, code spans, autolinks, or
-raw HTML:
-
-```````````````````````````````` example
-`` \[\` ``
-.
-<p><code>\[\`</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- \[\]
-.
-<pre><code>\[\]
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-~~~
-\[\]
-~~~
-.
-<pre><code>\[\]
-</code></pre>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<http://example.com?find=\*>
-.
-<p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<a href="/bar\/)">
-.
-<a href="/bar\/)">
-````````````````````````````````
-
-
-But they work in all other contexts, including URLs and link titles,
-link references, and [info strings] in [fenced code blocks]:
-
-```````````````````````````````` example
-[foo](/bar\* "ti\*tle")
-.
-<p><a href="/bar*" title="ti*tle">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo]
-
-[foo]: /bar\* "ti\*tle"
-.
-<p><a href="/bar*" title="ti*tle">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-``` foo\+bar
-foo
-```
-.
-<pre><code class="language-foo+bar">foo
-</code></pre>
-````````````````````````````````
-
-
-
-## Entity and numeric character references
-
-All valid HTML entity references and numeric character
-references, except those occuring in code blocks and code spans,
-are recognized as such and treated as equivalent to the
-corresponding Unicode characters. Conforming CommonMark parsers
-need not store information about whether a particular character
-was represented in the source using a Unicode character or
-an entity reference.
-
-[Entity references](@) consist of `&` + any of the valid
-HTML5 entity names + `;`. The
-document <https://html.spec.whatwg.org/multipage/entities.json>
-is used as an authoritative source for the valid entity
-references and their corresponding code points.
-
-```````````````````````````````` example
- & © Æ Ď
-¾ ℋ ⅆ
-∲ ≧̸
-.
-<p> & © Æ Ď
-¾ ℋ ⅆ
-∲ ≧̸</p>
-````````````````````````````````
-
-
-[Decimal numeric character
-references](@)
-consist of `&#` + a string of 1--8 arabic digits + `;`. A
-numeric character reference is parsed as the corresponding
-Unicode character. Invalid Unicode code points will be replaced by
-the REPLACEMENT CHARACTER (`U+FFFD`). For security reasons,
-the code point `U+0000` will also be replaced by `U+FFFD`.
-
-```````````````````````````````` example
-# Ӓ Ϡ � �
-.
-<p># Ӓ Ϡ � �</p>
-````````````````````````````````
-
-
-[Hexadecimal numeric character
-references](@) consist of `&#` +
-either `X` or `x` + a string of 1-8 hexadecimal digits + `;`.
-They too are parsed as the corresponding Unicode character (this
-time specified with a hexadecimal numeral instead of decimal).
-
-```````````````````````````````` example
-" ആ ಫ
-.
-<p>" ആ ಫ</p>
-````````````````````````````````
-
-
-Here are some nonentities:
-
-```````````````````````````````` example
-  &x; &#; &#x;
-&ThisIsNotDefined; &hi?;
-.
-<p>&nbsp &x; &#; &#x;
-&ThisIsNotDefined; &hi?;</p>
-````````````````````````````````
-
-
-Although HTML5 does accept some entity references
-without a trailing semicolon (such as `©`), these are not
-recognized here, because it makes the grammar too ambiguous:
-
-```````````````````````````````` example
-©
-.
-<p>&copy</p>
-````````````````````````````````
-
-
-Strings that are not on the list of HTML5 named entities are not
-recognized as entity references either:
-
-```````````````````````````````` example
-&MadeUpEntity;
-.
-<p>&MadeUpEntity;</p>
-````````````````````````````````
-
-
-Entity and numeric character references are recognized in any
-context besides code spans or code blocks, including
-URLs, [link titles], and [fenced code block][] [info strings]:
-
-```````````````````````````````` example
-<a href="öö.html">
-.
-<a href="öö.html">
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo](/föö "föö")
-.
-<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo]
-
-[foo]: /föö "föö"
-.
-<p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-``` föö
-foo
-```
-.
-<pre><code class="language-föö">foo
-</code></pre>
-````````````````````````````````
-
-
-Entity and numeric character references are treated as literal
-text in code spans and code blocks:
-
-```````````````````````````````` example
-`föö`
-.
-<p><code>f&ouml;&ouml;</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
- föfö
-.
-<pre><code>f&ouml;f&ouml;
-</code></pre>
-````````````````````````````````
-
-
-## Code spans
-
-A [backtick string](@)
-is a string of one or more backtick characters (`` ` ``) that is neither
-preceded nor followed by a backtick.
-
-A [code span](@) begins with a backtick string and ends with
-a backtick string of equal length. The contents of the code span are
-the characters between the two backtick strings, with leading and
-trailing spaces and [line endings] removed, and
-[whitespace] collapsed to single spaces.
-
-This is a simple code span:
-
-```````````````````````````````` example
-`foo`
-.
-<p><code>foo</code></p>
-````````````````````````````````
-
-
-Here two backticks are used, because the code contains a backtick.
-This example also illustrates stripping of leading and trailing spaces:
-
-```````````````````````````````` example
-`` foo ` bar ``
-.
-<p><code>foo ` bar</code></p>
-````````````````````````````````
-
-
-This example shows the motivation for stripping leading and trailing
-spaces:
-
-```````````````````````````````` example
-` `` `
-.
-<p><code>``</code></p>
-````````````````````````````````
-
-
-[Line endings] are treated like spaces:
-
-```````````````````````````````` example
-``
-foo
-``
-.
-<p><code>foo</code></p>
-````````````````````````````````
-
-
-Interior spaces and [line endings] are collapsed into
-single spaces, just as they would be by a browser:
-
-```````````````````````````````` example
-`foo bar
- baz`
-.
-<p><code>foo bar baz</code></p>
-````````````````````````````````
-
-
-Q: Why not just leave the spaces, since browsers will collapse them
-anyway? A: Because we might be targeting a non-HTML format, and we
-shouldn't rely on HTML-specific rendering assumptions.
-
-(Existing implementations differ in their treatment of internal
-spaces and [line endings]. Some, including `Markdown.pl` and
-`showdown`, convert an internal [line ending] into a
-`<br />` tag. But this makes things difficult for those who like to
-hard-wrap their paragraphs, since a line break in the midst of a code
-span will cause an unintended line break in the output. Others just
-leave internal spaces as they are, which is fine if only HTML is being
-targeted.)
-
-```````````````````````````````` example
-`foo `` bar`
-.
-<p><code>foo `` bar</code></p>
-````````````````````````````````
-
-
-Note that backslash escapes do not work in code spans. All backslashes
-are treated literally:
-
-```````````````````````````````` example
-`foo\`bar`
-.
-<p><code>foo\</code>bar`</p>
-````````````````````````````````
-
-
-Backslash escapes are never needed, because one can always choose a
-string of *n* backtick characters as delimiters, where the code does
-not contain any strings of exactly *n* backtick characters.
-
-Code span backticks have higher precedence than any other inline
-constructs except HTML tags and autolinks. Thus, for example, this is
-not parsed as emphasized text, since the second `*` is part of a code
-span:
-
-```````````````````````````````` example
-*foo`*`
-.
-<p>*foo<code>*</code></p>
-````````````````````````````````
-
-
-And this is not parsed as a link:
-
-```````````````````````````````` example
-[not a `link](/foo`)
-.
-<p>[not a <code>link](/foo</code>)</p>
-````````````````````````````````
-
-
-Code spans, HTML tags, and autolinks have the same precedence.
-Thus, this is code:
-
-```````````````````````````````` example
-`<a href="`">`
-.
-<p><code><a href="</code>">`</p>
-````````````````````````````````
-
-
-But this is an HTML tag:
-
-```````````````````````````````` example
-<a href="`">`
-.
-<p><a href="`">`</p>
-````````````````````````````````
-
-
-And this is code:
-
-```````````````````````````````` example
-`<http://foo.bar.`baz>`
-.
-<p><code><http://foo.bar.</code>baz>`</p>
-````````````````````````````````
-
-
-But this is an autolink:
-
-```````````````````````````````` example
-<http://foo.bar.`baz>`
-.
-<p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
-````````````````````````````````
-
-
-When a backtick string is not closed by a matching backtick string,
-we just have literal backticks:
-
-```````````````````````````````` example
-```foo``
-.
-<p>```foo``</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-`foo
-.
-<p>`foo</p>
-````````````````````````````````
-
-
-## Emphasis and strong emphasis
-
-John Gruber's original [Markdown syntax
-description](http://daringfireball.net/projects/markdown/syntax#em) says:
-
-> Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
-> emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML
-> `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML `<strong>`
-> tag.
-
-This is enough for most users, but these rules leave much undecided,
-especially when it comes to nested emphasis. The original
-`Markdown.pl` test suite makes it clear that triple `***` and
-`___` delimiters can be used for strong emphasis, and most
-implementations have also allowed the following patterns:
-
-``` markdown
-***strong emph***
-***strong** in emph*
-***emph* in strong**
-**in strong *emph***
-*in emph **strong***
-```
-
-The following patterns are less widely supported, but the intent
-is clear and they are useful (especially in contexts like bibliography
-entries):
-
-``` markdown
-*emph *with emph* in it*
-**strong **with strong** in it**
-```
-
-Many implementations have also restricted intraword emphasis to
-the `*` forms, to avoid unwanted emphasis in words containing
-internal underscores. (It is best practice to put these in code
-spans, but users often do not.)
-
-``` markdown
-internal emphasis: foo*bar*baz
-no emphasis: foo_bar_baz
-```
-
-The rules given below capture all of these patterns, while allowing
-for efficient parsing strategies that do not backtrack.
-
-First, some definitions. A [delimiter run](@) is either
-a sequence of one or more `*` characters that is not preceded or
-followed by a `*` character, or a sequence of one or more `_`
-characters that is not preceded or followed by a `_` character.
-
-A [left-flanking delimiter run](@) is
-a [delimiter run] that is (a) not followed by [Unicode whitespace],
-and (b) either not followed by a [punctuation character], or
-preceded by [Unicode whitespace] or a [punctuation character].
-For purposes of this definition, the beginning and the end of
-the line count as Unicode whitespace.
-
-A [right-flanking delimiter run](@) is
-a [delimiter run] that is (a) not preceded by [Unicode whitespace],
-and (b) either not preceded by a [punctuation character], or
-followed by [Unicode whitespace] or a [punctuation character].
-For purposes of this definition, the beginning and the end of
-the line count as Unicode whitespace.
-
-Here are some examples of delimiter runs.
-
- - left-flanking but not right-flanking:
-
- ```
- ***abc
- _abc
- **"abc"
- _"abc"
- ```
-
- - right-flanking but not left-flanking:
-
- ```
- abc***
- abc_
- "abc"**
- "abc"_
- ```
-
- - Both left and right-flanking:
-
- ```
- abc***def
- "abc"_"def"
- ```
-
- - Neither left nor right-flanking:
-
- ```
- abc *** def
- a _ b
- ```
-
-(The idea of distinguishing left-flanking and right-flanking
-delimiter runs based on the character before and the character
-after comes from Roopesh Chander's
-[vfmd](http://www.vfmd.org/vfmd-spec/specification/#procedure-for-identifying-emphasis-tags).
-vfmd uses the terminology "emphasis indicator string" instead of "delimiter
-run," and its rules for distinguishing left- and right-flanking runs
-are a bit more complex than the ones given here.)
-
-The following rules define emphasis and strong emphasis:
-
-1. A single `*` character [can open emphasis](@)
- iff (if and only if) it is part of a [left-flanking delimiter run].
-
-2. A single `_` character [can open emphasis] iff
- it is part of a [left-flanking delimiter run]
- and either (a) not part of a [right-flanking delimiter run]
- or (b) part of a [right-flanking delimiter run]
- preceded by punctuation.
-
-3. A single `*` character [can close emphasis](@)
- iff it is part of a [right-flanking delimiter run].
-
-4. A single `_` character [can close emphasis] iff
- it is part of a [right-flanking delimiter run]
- and either (a) not part of a [left-flanking delimiter run]
- or (b) part of a [left-flanking delimiter run]
- followed by punctuation.
-
-5. A double `**` [can open strong emphasis](@)
- iff it is part of a [left-flanking delimiter run].
-
-6. A double `__` [can open strong emphasis] iff
- it is part of a [left-flanking delimiter run]
- and either (a) not part of a [right-flanking delimiter run]
- or (b) part of a [right-flanking delimiter run]
- preceded by punctuation.
-
-7. A double `**` [can close strong emphasis](@)
- iff it is part of a [right-flanking delimiter run].
-
-8. A double `__` [can close strong emphasis]
- it is part of a [right-flanking delimiter run]
- and either (a) not part of a [left-flanking delimiter run]
- or (b) part of a [left-flanking delimiter run]
- followed by punctuation.
-
-9. Emphasis begins with a delimiter that [can open emphasis] and ends
- with a delimiter that [can close emphasis], and that uses the same
- character (`_` or `*`) as the opening delimiter. There must
- be a nonempty sequence of inlines between the open delimiter
- and the closing delimiter; these form the contents of the emphasis
- inline.
-
-10. Strong emphasis begins with a delimiter that
- [can open strong emphasis] and ends with a delimiter that
- [can close strong emphasis], and that uses the same character
- (`_` or `*`) as the opening delimiter.
- There must be a nonempty sequence of inlines between the open
- delimiter and the closing delimiter; these form the contents of
- the strong emphasis inline.
-
-11. A literal `*` character cannot occur at the beginning or end of
- `*`-delimited emphasis or `**`-delimited strong emphasis, unless it
- is backslash-escaped.
-
-12. A literal `_` character cannot occur at the beginning or end of
- `_`-delimited emphasis or `__`-delimited strong emphasis, unless it
- is backslash-escaped.
-
-Where rules 1--12 above are compatible with multiple parsings,
-the following principles resolve ambiguity:
-
-13. The number of nestings should be minimized. Thus, for example,
- an interpretation `<strong>...</strong>` is always preferred to
- `<em><em>...</em></em>`.
-
-14. An interpretation `<strong><em>...</em></strong>` is always
- preferred to `<em><strong>..</strong></em>`.
-
-15. When two potential emphasis or strong emphasis spans overlap,
- so that the second begins before the first ends and ends after
- the first ends, the first takes precedence. Thus, for example,
- `*foo _bar* baz_` is parsed as `<em>foo _bar</em> baz_` rather
- than `*foo <em>bar* baz</em>`. For the same reason,
- `**foo*bar**` is parsed as `<em><em>foo</em>bar</em>*`
- rather than `<strong>foo*bar</strong>`.
-
-16. When there are two potential emphasis or strong emphasis spans
- with the same closing delimiter, the shorter one (the one that
- opens later) takes precedence. Thus, for example,
- `**foo **bar baz**` is parsed as `**foo <strong>bar baz</strong>`
- rather than `<strong>foo **bar baz</strong>`.
-
-17. Inline code spans, links, images, and HTML tags group more tightly
- than emphasis. So, when there is a choice between an interpretation
- that contains one of these elements and one that does not, the
- former always wins. Thus, for example, `*[foo*](bar)` is
- parsed as `*<a href="bar">foo*</a>` rather than as
- `<em>[foo</em>](bar)`.
-
-These rules can be illustrated through a series of examples.
-
-Rule 1:
-
-```````````````````````````````` example
-*foo bar*
-.
-<p><em>foo bar</em></p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `*` is followed by
-whitespace, and hence not part of a [left-flanking delimiter run]:
-
-```````````````````````````````` example
-a * foo bar*
-.
-<p>a * foo bar*</p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `*` is preceded
-by an alphanumeric and followed by punctuation, and hence
-not part of a [left-flanking delimiter run]:
-
-```````````````````````````````` example
-a*"foo"*
-.
-<p>a*"foo"*</p>
-````````````````````````````````
-
-
-Unicode nonbreaking spaces count as whitespace, too:
-
-```````````````````````````````` example
-* a *
-.
-<p>* a *</p>
-````````````````````````````````
-
-
-Intraword emphasis with `*` is permitted:
-
-```````````````````````````````` example
-foo*bar*
-.
-<p>foo<em>bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-5*6*78
-.
-<p>5<em>6</em>78</p>
-````````````````````````````````
-
-
-Rule 2:
-
-```````````````````````````````` example
-_foo bar_
-.
-<p><em>foo bar</em></p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `_` is followed by
-whitespace:
-
-```````````````````````````````` example
-_ foo bar_
-.
-<p>_ foo bar_</p>
-````````````````````````````````
-
-
-This is not emphasis, because the opening `_` is preceded
-by an alphanumeric and followed by punctuation:
-
-```````````````````````````````` example
-a_"foo"_
-.
-<p>a_"foo"_</p>
-````````````````````````````````
-
-
-Emphasis with `_` is not allowed inside words:
-
-```````````````````````````````` example
-foo_bar_
-.
-<p>foo_bar_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-5_6_78
-.
-<p>5_6_78</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-пристаням_стремятся_
-.
-<p>пристаням_стремятся_</p>
-````````````````````````````````
-
-
-Here `_` does not generate emphasis, because the first delimiter run
-is right-flanking and the second left-flanking:
-
-```````````````````````````````` example
-aa_"bb"_cc
-.
-<p>aa_"bb"_cc</p>
-````````````````````````````````
-
-
-This is emphasis, even though the opening delimiter is
-both left- and right-flanking, because it is preceded by
-punctuation:
-
-```````````````````````````````` example
-foo-_(bar)_
-.
-<p>foo-<em>(bar)</em></p>
-````````````````````````````````
-
-
-Rule 3:
-
-This is not emphasis, because the closing delimiter does
-not match the opening delimiter:
-
-```````````````````````````````` example
-_foo*
-.
-<p>_foo*</p>
-````````````````````````````````
-
-
-This is not emphasis, because the closing `*` is preceded by
-whitespace:
-
-```````````````````````````````` example
-*foo bar *
-.
-<p>*foo bar *</p>
-````````````````````````````````
-
-
-A newline also counts as whitespace:
-
-```````````````````````````````` example
-*foo bar
-*
-.
-<p>*foo bar</p>
-<ul>
-<li></li>
-</ul>
-````````````````````````````````
-
-
-This is not emphasis, because the second `*` is
-preceded by punctuation and followed by an alphanumeric
-(hence it is not part of a [right-flanking delimiter run]:
-
-```````````````````````````````` example
-*(*foo)
-.
-<p>*(*foo)</p>
-````````````````````````````````
-
-
-The point of this restriction is more easily appreciated
-with this example:
-
-```````````````````````````````` example
-*(*foo*)*
-.
-<p><em>(<em>foo</em>)</em></p>
-````````````````````````````````
-
-
-Intraword emphasis with `*` is allowed:
-
-```````````````````````````````` example
-*foo*bar
-.
-<p><em>foo</em>bar</p>
-````````````````````````````````
-
-
-
-Rule 4:
-
-This is not emphasis, because the closing `_` is preceded by
-whitespace:
-
-```````````````````````````````` example
-_foo bar _
-.
-<p>_foo bar _</p>
-````````````````````````````````
-
-
-This is not emphasis, because the second `_` is
-preceded by punctuation and followed by an alphanumeric:
-
-```````````````````````````````` example
-_(_foo)
-.
-<p>_(_foo)</p>
-````````````````````````````````
-
-
-This is emphasis within emphasis:
-
-```````````````````````````````` example
-_(_foo_)_
-.
-<p><em>(<em>foo</em>)</em></p>
-````````````````````````````````
-
-
-Intraword emphasis is disallowed for `_`:
-
-```````````````````````````````` example
-_foo_bar
-.
-<p>_foo_bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_пристаням_стремятся
-.
-<p>_пристаням_стремятся</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo_bar_baz_
-.
-<p><em>foo_bar_baz</em></p>
-````````````````````````````````
-
-
-This is emphasis, even though the closing delimiter is
-both left- and right-flanking, because it is followed by
-punctuation:
-
-```````````````````````````````` example
-_(bar)_.
-.
-<p><em>(bar)</em>.</p>
-````````````````````````````````
-
-
-Rule 5:
-
-```````````````````````````````` example
-**foo bar**
-.
-<p><strong>foo bar</strong></p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening delimiter is
-followed by whitespace:
-
-```````````````````````````````` example
-** foo bar**
-.
-<p>** foo bar**</p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening `**` is preceded
-by an alphanumeric and followed by punctuation, and hence
-not part of a [left-flanking delimiter run]:
-
-```````````````````````````````` example
-a**"foo"**
-.
-<p>a**"foo"**</p>
-````````````````````````````````
-
-
-Intraword strong emphasis with `**` is permitted:
-
-```````````````````````````````` example
-foo**bar**
-.
-<p>foo<strong>bar</strong></p>
-````````````````````````````````
-
-
-Rule 6:
-
-```````````````````````````````` example
-__foo bar__
-.
-<p><strong>foo bar</strong></p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening delimiter is
-followed by whitespace:
-
-```````````````````````````````` example
-__ foo bar__
-.
-<p>__ foo bar__</p>
-````````````````````````````````
-
-
-A newline counts as whitespace:
-```````````````````````````````` example
-__
-foo bar__
-.
-<p>__
-foo bar__</p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the opening `__` is preceded
-by an alphanumeric and followed by punctuation:
-
-```````````````````````````````` example
-a__"foo"__
-.
-<p>a__"foo"__</p>
-````````````````````````````````
-
-
-Intraword strong emphasis is forbidden with `__`:
-
-```````````````````````````````` example
-foo__bar__
-.
-<p>foo__bar__</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-5__6__78
-.
-<p>5__6__78</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-пристаням__стремятся__
-.
-<p>пристаням__стремятся__</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo, __bar__, baz__
-.
-<p><strong>foo, <strong>bar</strong>, baz</strong></p>
-````````````````````````````````
-
-
-This is strong emphasis, even though the opening delimiter is
-both left- and right-flanking, because it is preceded by
-punctuation:
-
-```````````````````````````````` example
-foo-__(bar)__
-.
-<p>foo-<strong>(bar)</strong></p>
-````````````````````````````````
-
-
-
-Rule 7:
-
-This is not strong emphasis, because the closing delimiter is preceded
-by whitespace:
-
-```````````````````````````````` example
-**foo bar **
-.
-<p>**foo bar **</p>
-````````````````````````````````
-
-
-(Nor can it be interpreted as an emphasized `*foo bar *`, because of
-Rule 11.)
-
-This is not strong emphasis, because the second `**` is
-preceded by punctuation and followed by an alphanumeric:
-
-```````````````````````````````` example
-**(**foo)
-.
-<p>**(**foo)</p>
-````````````````````````````````
-
-
-The point of this restriction is more easily appreciated
-with these examples:
-
-```````````````````````````````` example
-*(**foo**)*
-.
-<p><em>(<strong>foo</strong>)</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**Gomphocarpus (*Gomphocarpus physocarpus*, syn.
-*Asclepias physocarpa*)**
-.
-<p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
-<em>Asclepias physocarpa</em>)</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo "*bar*" foo**
-.
-<p><strong>foo "<em>bar</em>" foo</strong></p>
-````````````````````````````````
-
-
-Intraword emphasis:
-
-```````````````````````````````` example
-**foo**bar
-.
-<p><strong>foo</strong>bar</p>
-````````````````````````````````
-
-
-Rule 8:
-
-This is not strong emphasis, because the closing delimiter is
-preceded by whitespace:
-
-```````````````````````````````` example
-__foo bar __
-.
-<p>__foo bar __</p>
-````````````````````````````````
-
-
-This is not strong emphasis, because the second `__` is
-preceded by punctuation and followed by an alphanumeric:
-
-```````````````````````````````` example
-__(__foo)
-.
-<p>__(__foo)</p>
-````````````````````````````````
-
-
-The point of this restriction is more easily appreciated
-with this example:
-
-```````````````````````````````` example
-_(__foo__)_
-.
-<p><em>(<strong>foo</strong>)</em></p>
-````````````````````````````````
-
-
-Intraword strong emphasis is forbidden with `__`:
-
-```````````````````````````````` example
-__foo__bar
-.
-<p>__foo__bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__пристаням__стремятся
-.
-<p>__пристаням__стремятся</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo__bar__baz__
-.
-<p><strong>foo__bar__baz</strong></p>
-````````````````````````````````
-
-
-This is strong emphasis, even though the closing delimiter is
-both left- and right-flanking, because it is followed by
-punctuation:
-
-```````````````````````````````` example
-__(bar)__.
-.
-<p><strong>(bar)</strong>.</p>
-````````````````````````````````
-
-
-Rule 9:
-
-Any nonempty sequence of inline elements can be the contents of an
-emphasized span.
-
-```````````````````````````````` example
-*foo [bar](/url)*
-.
-<p><em>foo <a href="/url">bar</a></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo
-bar*
-.
-<p><em>foo
-bar</em></p>
-````````````````````````````````
-
-
-In particular, emphasis and strong emphasis can be nested
-inside emphasis:
-
-```````````````````````````````` example
-_foo __bar__ baz_
-.
-<p><em>foo <strong>bar</strong> baz</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo _bar_ baz_
-.
-<p><em>foo <em>bar</em> baz</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo_ bar_
-.
-<p><em><em>foo</em> bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo *bar**
-.
-<p><em>foo <em>bar</em></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo **bar** baz*
-.
-<p><em>foo <strong>bar</strong> baz</em></p>
-````````````````````````````````
-
-
-But note:
-
-```````````````````````````````` example
-*foo**bar**baz*
-.
-<p><em>foo</em><em>bar</em><em>baz</em></p>
-````````````````````````````````
-
-
-The difference is that in the preceding case, the internal delimiters
-[can close emphasis], while in the cases with spaces, they cannot.
-
-```````````````````````````````` example
-***foo** bar*
-.
-<p><em><strong>foo</strong> bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo **bar***
-.
-<p><em>foo <strong>bar</strong></em></p>
-````````````````````````````````
-
-
-Note, however, that in the following case we get no strong
-emphasis, because the opening delimiter is closed by the first
-`*` before `bar`:
-
-```````````````````````````````` example
-*foo**bar***
-.
-<p><em>foo</em><em>bar</em>**</p>
-````````````````````````````````
-
-
-
-Indefinite levels of nesting are possible:
-
-```````````````````````````````` example
-*foo **bar *baz* bim** bop*
-.
-<p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo [*bar*](/url)*
-.
-<p><em>foo <a href="/url"><em>bar</em></a></em></p>
-````````````````````````````````
-
-
-There can be no empty emphasis or strong emphasis:
-
-```````````````````````````````` example
-** is not an empty emphasis
-.
-<p>** is not an empty emphasis</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**** is not an empty strong emphasis
-.
-<p>**** is not an empty strong emphasis</p>
-````````````````````````````````
-
-
-
-Rule 10:
-
-Any nonempty sequence of inline elements can be the contents of an
-strongly emphasized span.
-
-```````````````````````````````` example
-**foo [bar](/url)**
-.
-<p><strong>foo <a href="/url">bar</a></strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo
-bar**
-.
-<p><strong>foo
-bar</strong></p>
-````````````````````````````````
-
-
-In particular, emphasis and strong emphasis can be nested
-inside strong emphasis:
-
-```````````````````````````````` example
-__foo _bar_ baz__
-.
-<p><strong>foo <em>bar</em> baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo __bar__ baz__
-.
-<p><strong>foo <strong>bar</strong> baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____foo__ bar__
-.
-<p><strong><strong>foo</strong> bar</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo **bar****
-.
-<p><strong>foo <strong>bar</strong></strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo *bar* baz**
-.
-<p><strong>foo <em>bar</em> baz</strong></p>
-````````````````````````````````
-
-
-But note:
-
-```````````````````````````````` example
-**foo*bar*baz**
-.
-<p><em><em>foo</em>bar</em>baz**</p>
-````````````````````````````````
-
-
-The difference is that in the preceding case, the internal delimiters
-[can close emphasis], while in the cases with spaces, they cannot.
-
-```````````````````````````````` example
-***foo* bar**
-.
-<p><strong><em>foo</em> bar</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo *bar***
-.
-<p><strong>foo <em>bar</em></strong></p>
-````````````````````````````````
-
-
-Indefinite levels of nesting are possible:
-
-```````````````````````````````` example
-**foo *bar **baz**
-bim* bop**
-.
-<p><strong>foo <em>bar <strong>baz</strong>
-bim</em> bop</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo [*bar*](/url)**
-.
-<p><strong>foo <a href="/url"><em>bar</em></a></strong></p>
-````````````````````````````````
-
-
-There can be no empty emphasis or strong emphasis:
-
-```````````````````````````````` example
-__ is not an empty emphasis
-.
-<p>__ is not an empty emphasis</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____ is not an empty strong emphasis
-.
-<p>____ is not an empty strong emphasis</p>
-````````````````````````````````
-
-
-
-Rule 11:
-
-```````````````````````````````` example
-foo ***
-.
-<p>foo ***</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo *\**
-.
-<p>foo <em>*</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo *_*
-.
-<p>foo <em>_</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo *****
-.
-<p>foo *****</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo **\***
-.
-<p>foo <strong>*</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo **_**
-.
-<p>foo <strong>_</strong></p>
-````````````````````````````````
-
-
-Note that when delimiters do not match evenly, Rule 11 determines
-that the excess literal `*` characters will appear outside of the
-emphasis, rather than inside it:
-
-```````````````````````````````` example
-**foo*
-.
-<p>*<em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo**
-.
-<p><em>foo</em>*</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-***foo**
-.
-<p>*<strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-****foo*
-.
-<p>***<em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo***
-.
-<p><strong>foo</strong>*</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo****
-.
-<p><em>foo</em>***</p>
-````````````````````````````````
-
-
-
-Rule 12:
-
-```````````````````````````````` example
-foo ___
-.
-<p>foo ___</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo _\__
-.
-<p>foo <em>_</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo _*_
-.
-<p>foo <em>*</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo _____
-.
-<p>foo _____</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo __\___
-.
-<p>foo <strong>_</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo __*__
-.
-<p>foo <strong>*</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo_
-.
-<p>_<em>foo</em></p>
-````````````````````````````````
-
-
-Note that when delimiters do not match evenly, Rule 12 determines
-that the excess literal `_` characters will appear outside of the
-emphasis, rather than inside it:
-
-```````````````````````````````` example
-_foo__
-.
-<p><em>foo</em>_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-___foo__
-.
-<p>_<strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____foo_
-.
-<p>___<em>foo</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo___
-.
-<p><strong>foo</strong>_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo____
-.
-<p><em>foo</em>___</p>
-````````````````````````````````
-
-
-Rule 13 implies that if you want emphasis nested directly inside
-emphasis, you must use different delimiters:
-
-```````````````````````````````` example
-**foo**
-.
-<p><strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*_foo_*
-.
-<p><em><em>foo</em></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__foo__
-.
-<p><strong>foo</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_*foo*_
-.
-<p><em><em>foo</em></em></p>
-````````````````````````````````
-
-
-However, strong emphasis within strong emphasis is possible without
-switching delimiters:
-
-```````````````````````````````` example
-****foo****
-.
-<p><strong><strong>foo</strong></strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-____foo____
-.
-<p><strong><strong>foo</strong></strong></p>
-````````````````````````````````
-
-
-
-Rule 13 can be applied to arbitrarily long sequences of
-delimiters:
-
-```````````````````````````````` example
-******foo******
-.
-<p><strong><strong><strong>foo</strong></strong></strong></p>
-````````````````````````````````
-
-
-Rule 14:
-
-```````````````````````````````` example
-***foo***
-.
-<p><strong><em>foo</em></strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_____foo_____
-.
-<p><strong><strong><em>foo</em></strong></strong></p>
-````````````````````````````````
-
-
-Rule 15:
-
-```````````````````````````````` example
-*foo _bar* baz_
-.
-<p><em>foo _bar</em> baz_</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**foo*bar**
-.
-<p><em><em>foo</em>bar</em>*</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo __bar *baz bim__ bam*
-.
-<p><em>foo <strong>bar *baz bim</strong> bam</em></p>
-````````````````````````````````
-
-
-Rule 16:
-
-```````````````````````````````` example
-**foo **bar baz**
-.
-<p>**foo <strong>bar baz</strong></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo *bar baz*
-.
-<p>*foo <em>bar baz</em></p>
-````````````````````````````````
-
-
-Rule 17:
-
-```````````````````````````````` example
-*[bar*](/url)
-.
-<p>*<a href="/url">bar*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_foo [bar_](/url)
-.
-<p>_foo <a href="/url">bar_</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*<img src="foo" title="*"/>
-.
-<p>*<img src="foo" title="*"/></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**<a href="**">
-.
-<p>**<a href="**"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__<a href="__">
-.
-<p>__<a href="__"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*a `*`*
-.
-<p><em>a <code>*</code></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-_a `_`_
-.
-<p><em>a <code>_</code></em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-**a<http://foo.bar/?q=**>
-.
-<p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-__a<http://foo.bar/?q=__>
-.
-<p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
-````````````````````````````````
-
-
-
-## Links
-
-A link contains [link text] (the visible text), a [link destination]
-(the URI that is the link destination), and optionally a [link title].
-There are two basic kinds of links in Markdown. In [inline links] the
-destination and title are given immediately after the link text. In
-[reference links] the destination and title are defined elsewhere in
-the document.
-
-A [link text](@) consists of a sequence of zero or more
-inline elements enclosed by square brackets (`[` and `]`). The
-following rules apply:
-
-- Links may not contain other links, at any level of nesting. If
- multiple otherwise valid link definitions appear nested inside each
- other, the inner-most definition is used.
-
-- Brackets are allowed in the [link text] only if (a) they
- are backslash-escaped or (b) they appear as a matched pair of brackets,
- with an open bracket `[`, a sequence of zero or more inlines, and
- a close bracket `]`.
-
-- Backtick [code spans], [autolinks], and raw [HTML tags] bind more tightly
- than the brackets in link text. Thus, for example,
- `` [foo`]` `` could not be a link text, since the second `]`
- is part of a code span.
-
-- The brackets in link text bind more tightly than markers for
- [emphasis and strong emphasis]. Thus, for example, `*[foo*](url)` is a link.
-
-A [link destination](@) consists of either
-
-- a sequence of zero or more characters between an opening `<` and a
- closing `>` that contains no spaces, line breaks, or unescaped
- `<` or `>` characters, or
-
-- a nonempty sequence of characters that does not include
- ASCII space or control characters, and includes parentheses
- only if (a) they are backslash-escaped or (b) they are part of
- a balanced pair of unescaped parentheses that is not itself
- inside a balanced pair of unescaped parentheses.
-
-A [link title](@) consists of either
-
-- a sequence of zero or more characters between straight double-quote
- characters (`"`), including a `"` character only if it is
- backslash-escaped, or
-
-- a sequence of zero or more characters between straight single-quote
- characters (`'`), including a `'` character only if it is
- backslash-escaped, or
-
-- a sequence of zero or more characters between matching parentheses
- (`(...)`), including a `)` character only if it is backslash-escaped.
-
-Although [link titles] may span multiple lines, they may not contain
-a [blank line].
-
-An [inline link](@) consists of a [link text] followed immediately
-by a left parenthesis `(`, optional [whitespace], an optional
-[link destination], an optional [link title] separated from the link
-destination by [whitespace], optional [whitespace], and a right
-parenthesis `)`. The link's text consists of the inlines contained
-in the [link text] (excluding the enclosing square brackets).
-The link's URI consists of the link destination, excluding enclosing
-`<...>` if present, with backslash-escapes in effect as described
-above. The link's title consists of the link title, excluding its
-enclosing delimiters, with backslash-escapes in effect as described
-above.
-
-Here is a simple inline link:
-
-```````````````````````````````` example
-[link](/uri "title")
-.
-<p><a href="/uri" title="title">link</a></p>
-````````````````````````````````
-
-
-The title may be omitted:
-
-```````````````````````````````` example
-[link](/uri)
-.
-<p><a href="/uri">link</a></p>
-````````````````````````````````
-
-
-Both the title and the destination may be omitted:
-
-```````````````````````````````` example
-[link]()
-.
-<p><a href="">link</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](<>)
-.
-<p><a href="">link</a></p>
-````````````````````````````````
-
-
-The destination cannot contain spaces or line breaks,
-even if enclosed in pointy brackets:
-
-```````````````````````````````` example
-[link](/my uri)
-.
-<p>[link](/my uri)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](</my uri>)
-.
-<p>[link](</my uri>)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](foo
-bar)
-.
-<p>[link](foo
-bar)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](<foo
-bar>)
-.
-<p>[link](<foo
-bar>)</p>
-````````````````````````````````
-
-Parentheses inside the link destination may be escaped:
-
-```````````````````````````````` example
-[link](\(foo\))
-.
-<p><a href="(foo)">link</a></p>
-````````````````````````````````
-
-One level of balanced parentheses is allowed without escaping:
-
-```````````````````````````````` example
-[link]((foo)and(bar))
-.
-<p><a href="(foo)and(bar)">link</a></p>
-````````````````````````````````
-
-However, if you have parentheses within parentheses, you need to escape
-or use the `<...>` form:
-
-```````````````````````````````` example
-[link](foo(and(bar)))
-.
-<p>[link](foo(and(bar)))</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](foo(and\(bar\)))
-.
-<p><a href="foo(and(bar))">link</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link](<foo(and(bar))>)
-.
-<p><a href="foo(and(bar))">link</a></p>
-````````````````````````````````
-
-
-Parentheses and other symbols can also be escaped, as usual
-in Markdown:
-
-```````````````````````````````` example
-[link](foo\)\:)
-.
-<p><a href="foo):">link</a></p>
-````````````````````````````````
-
-
-A link can contain fragment identifiers and queries:
-
-```````````````````````````````` example
-[link](#fragment)
-
-[link](http://example.com#fragment)
-
-[link](http://example.com?foo=3#frag)
-.
-<p><a href="#fragment">link</a></p>
-<p><a href="http://example.com#fragment">link</a></p>
-<p><a href="http://example.com?foo=3#frag">link</a></p>
-````````````````````````````````
-
-
-Note that a backslash before a non-escapable character is
-just a backslash:
-
-```````````````````````````````` example
-[link](foo\bar)
-.
-<p><a href="foo%5Cbar">link</a></p>
-````````````````````````````````
-
-
-URL-escaping should be left alone inside the destination, as all
-URL-escaped characters are also valid URL characters. Entity and
-numerical character references in the destination will be parsed
-into the corresponding Unicode code points, as usual. These may
-be optionally URL-escaped when written as HTML, but this spec
-does not enforce any particular policy for rendering URLs in
-HTML or other formats. Renderers may make different decisions
-about how to escape or normalize URLs in the output.
-
-```````````````````````````````` example
-[link](foo%20bä)
-.
-<p><a href="foo%20b%C3%A4">link</a></p>
-````````````````````````````````
-
-
-Note that, because titles can often be parsed as destinations,
-if you try to omit the destination and keep the title, you'll
-get unexpected results:
-
-```````````````````````````````` example
-[link]("title")
-.
-<p><a href="%22title%22">link</a></p>
-````````````````````````````````
-
-
-Titles may be in single quotes, double quotes, or parentheses:
-
-```````````````````````````````` example
-[link](/url "title")
-[link](/url 'title')
-[link](/url (title))
-.
-<p><a href="/url" title="title">link</a>
-<a href="/url" title="title">link</a>
-<a href="/url" title="title">link</a></p>
-````````````````````````````````
-
-
-Backslash escapes and entity and numeric character references
-may be used in titles:
-
-```````````````````````````````` example
-[link](/url "title \""")
-.
-<p><a href="/url" title="title """>link</a></p>
-````````````````````````````````
-
-
-Nested balanced quotes are not allowed without escaping:
-
-```````````````````````````````` example
-[link](/url "title "and" title")
-.
-<p>[link](/url "title "and" title")</p>
-````````````````````````````````
-
-
-But it is easy to work around this by using a different quote type:
-
-```````````````````````````````` example
-[link](/url 'title "and" title')
-.
-<p><a href="/url" title="title "and" title">link</a></p>
-````````````````````````````````
-
-
-(Note: `Markdown.pl` did allow double quotes inside a double-quoted
-title, and its test suite included a test demonstrating this.
-But it is hard to see a good rationale for the extra complexity this
-brings, since there are already many ways---backslash escaping,
-entity and numeric character references, or using a different
-quote type for the enclosing title---to write titles containing
-double quotes. `Markdown.pl`'s handling of titles has a number
-of other strange features. For example, it allows single-quoted
-titles in inline links, but not reference links. And, in
-reference links but not inline links, it allows a title to begin
-with `"` and end with `)`. `Markdown.pl` 1.0.1 even allows
-titles with no closing quotation mark, though 1.0.2b8 does not.
-It seems preferable to adopt a simple, rational rule that works
-the same way in inline links and link reference definitions.)
-
-[Whitespace] is allowed around the destination and title:
-
-```````````````````````````````` example
-[link]( /uri
- "title" )
-.
-<p><a href="/uri" title="title">link</a></p>
-````````````````````````````````
-
-
-But it is not allowed between the link text and the
-following parenthesis:
-
-```````````````````````````````` example
-[link] (/uri)
-.
-<p>[link] (/uri)</p>
-````````````````````````````````
-
-
-The link text may contain balanced brackets, but not unbalanced ones,
-unless they are escaped:
-
-```````````````````````````````` example
-[link [foo [bar]]](/uri)
-.
-<p><a href="/uri">link [foo [bar]]</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link] bar](/uri)
-.
-<p>[link] bar](/uri)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link [bar](/uri)
-.
-<p>[link <a href="/uri">bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link \[bar](/uri)
-.
-<p><a href="/uri">link [bar</a></p>
-````````````````````````````````
-
-
-The link text may contain inline content:
-
-```````````````````````````````` example
-[link *foo **bar** `#`*](/uri)
-.
-<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[![moon](moon.jpg)](/uri)
-.
-<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
-````````````````````````````````
-
-
-However, links may not contain other links, at any level of nesting.
-
-```````````````````````````````` example
-[foo [bar](/uri)](/uri)
-.
-<p>[foo <a href="/uri">bar</a>](/uri)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *[bar [baz](/uri)](/uri)*](/uri)
-.
-<p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![[[foo](uri1)](uri2)](uri3)
-.
-<p><img src="uri3" alt="[foo](uri2)" /></p>
-````````````````````````````````
-
-
-These cases illustrate the precedence of link text grouping over
-emphasis grouping:
-
-```````````````````````````````` example
-*[foo*](/uri)
-.
-<p>*<a href="/uri">foo*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *bar](baz*)
-.
-<p><a href="baz*">foo *bar</a></p>
-````````````````````````````````
-
-
-Note that brackets that *aren't* part of links do not take
-precedence:
-
-```````````````````````````````` example
-*foo [bar* baz]
-.
-<p><em>foo [bar</em> baz]</p>
-````````````````````````````````
-
-
-These cases illustrate the precedence of HTML tags, code spans,
-and autolinks over link grouping:
-
-```````````````````````````````` example
-[foo <bar attr="](baz)">
-.
-<p>[foo <bar attr="](baz)"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo`](/uri)`
-.
-<p>[foo<code>](/uri)</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo<http://example.com/?search=](uri)>
-.
-<p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
-````````````````````````````````
-
-
-There are three kinds of [reference link](@)s:
-[full](#full-reference-link), [collapsed](#collapsed-reference-link),
-and [shortcut](#shortcut-reference-link).
-
-A [full reference link](@)
-consists of a [link text] immediately followed by a [link label]
-that [matches] a [link reference definition] elsewhere in the document.
-
-A [link label](@) begins with a left bracket (`[`) and ends
-with the first right bracket (`]`) that is not backslash-escaped.
-Between these brackets there must be at least one [non-whitespace character].
-Unescaped square bracket characters are not allowed in
-[link labels]. A link label can have at most 999
-characters inside the square brackets.
-
-One label [matches](@)
-another just in case their normalized forms are equal. To normalize a
-label, perform the *Unicode case fold* and collapse consecutive internal
-[whitespace] to a single space. If there are multiple
-matching reference link definitions, the one that comes first in the
-document is used. (It is desirable in such cases to emit a warning.)
-
-The contents of the first link label are parsed as inlines, which are
-used as the link's text. The link's URI and title are provided by the
-matching [link reference definition].
-
-Here is a simple example:
-
-```````````````````````````````` example
-[foo][bar]
-
-[bar]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-The rules for the [link text] are the same as with
-[inline links]. Thus:
-
-The link text may contain balanced brackets, but not unbalanced ones,
-unless they are escaped:
-
-```````````````````````````````` example
-[link [foo [bar]]][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">link [foo [bar]]</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[link \[bar][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">link [bar</a></p>
-````````````````````````````````
-
-
-The link text may contain inline content:
-
-```````````````````````````````` example
-[link *foo **bar** `#`*][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[![moon](moon.jpg)][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
-````````````````````````````````
-
-
-However, links may not contain other links, at any level of nesting.
-
-```````````````````````````````` example
-[foo [bar](/uri)][ref]
-
-[ref]: /uri
-.
-<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *bar [baz][ref]*][ref]
-
-[ref]: /uri
-.
-<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
-````````````````````````````````
-
-
-(In the examples above, we have two [shortcut reference links]
-instead of one [full reference link].)
-
-The following cases illustrate the precedence of link text grouping over
-emphasis grouping:
-
-```````````````````````````````` example
-*[foo*][ref]
-
-[ref]: /uri
-.
-<p>*<a href="/uri">foo*</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo *bar][ref]
-
-[ref]: /uri
-.
-<p><a href="/uri">foo *bar</a></p>
-````````````````````````````````
-
-
-These cases illustrate the precedence of HTML tags, code spans,
-and autolinks over link grouping:
-
-```````````````````````````````` example
-[foo <bar attr="][ref]">
-
-[ref]: /uri
-.
-<p>[foo <bar attr="][ref]"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo`][ref]`
-
-[ref]: /uri
-.
-<p>[foo<code>][ref]</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo<http://example.com/?search=][ref]>
-
-[ref]: /uri
-.
-<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
-````````````````````````````````
-
-
-Matching is case-insensitive:
-
-```````````````````````````````` example
-[foo][BaR]
-
-[bar]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-Unicode case fold is used:
-
-```````````````````````````````` example
-[Толпой][Толпой] is a Russian word.
-
-[ТОЛПОЙ]: /url
-.
-<p><a href="/url">Толпой</a> is a Russian word.</p>
-````````````````````````````````
-
-
-Consecutive internal [whitespace] is treated as one space for
-purposes of determining matching:
-
-```````````````````````````````` example
-[Foo
- bar]: /url
-
-[Baz][Foo bar]
-.
-<p><a href="/url">Baz</a></p>
-````````````````````````````````
-
-
-No [whitespace] is allowed between the [link text] and the
-[link label]:
-
-```````````````````````````````` example
-[foo] [bar]
-
-[bar]: /url "title"
-.
-<p>[foo] <a href="/url" title="title">bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo]
-[bar]
-
-[bar]: /url "title"
-.
-<p>[foo]
-<a href="/url" title="title">bar</a></p>
-````````````````````````````````
-
-
-This is a departure from John Gruber's original Markdown syntax
-description, which explicitly allows whitespace between the link
-text and the link label. It brings reference links in line with
-[inline links], which (according to both original Markdown and
-this spec) cannot have whitespace after the link text. More
-importantly, it prevents inadvertent capture of consecutive
-[shortcut reference links]. If whitespace is allowed between the
-link text and the link label, then in the following we will have
-a single reference link, not two shortcut reference links, as
-intended:
-
-``` markdown
-[foo]
-[bar]
-
-[foo]: /url1
-[bar]: /url2
-```
-
-(Note that [shortcut reference links] were introduced by Gruber
-himself in a beta version of `Markdown.pl`, but never included
-in the official syntax description. Without shortcut reference
-links, it is harmless to allow space between the link text and
-link label; but once shortcut references are introduced, it is
-too dangerous to allow this, as it frequently leads to
-unintended results.)
-
-When there are multiple matching [link reference definitions],
-the first is used:
-
-```````````````````````````````` example
-[foo]: /url1
-
-[foo]: /url2
-
-[bar][foo]
-.
-<p><a href="/url1">bar</a></p>
-````````````````````````````````
-
-
-Note that matching is performed on normalized strings, not parsed
-inline content. So the following does not match, even though the
-labels define equivalent inline content:
-
-```````````````````````````````` example
-[bar][foo\!]
-
-[foo!]: /url
-.
-<p>[bar][foo!]</p>
-````````````````````````````````
-
-
-[Link labels] cannot contain brackets, unless they are
-backslash-escaped:
-
-```````````````````````````````` example
-[foo][ref[]
-
-[ref[]: /uri
-.
-<p>[foo][ref[]</p>
-<p>[ref[]: /uri</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo][ref[bar]]
-
-[ref[bar]]: /uri
-.
-<p>[foo][ref[bar]]</p>
-<p>[ref[bar]]: /uri</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[[[foo]]]
-
-[[[foo]]]: /url
-.
-<p>[[[foo]]]</p>
-<p>[[[foo]]]: /url</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[foo][ref\[]
-
-[ref\[]: /uri
-.
-<p><a href="/uri">foo</a></p>
-````````````````````````````````
-
-
-Note that in this example `]` is not backslash-escaped:
-
-```````````````````````````````` example
-[bar\\]: /uri
-
-[bar\\]
-.
-<p><a href="/uri">bar\</a></p>
-````````````````````````````````
-
-
-A [link label] must contain at least one [non-whitespace character]:
-
-```````````````````````````````` example
-[]
-
-[]: /uri
-.
-<p>[]</p>
-<p>[]: /uri</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[
- ]
-
-[
- ]: /uri
-.
-<p>[
-]</p>
-<p>[
-]: /uri</p>
-````````````````````````````````
-
-
-A [collapsed reference link](@)
-consists of a [link label] that [matches] a
-[link reference definition] elsewhere in the
-document, followed by the string `[]`.
-The contents of the first link label are parsed as inlines,
-which are used as the link's text. The link's URI and title are
-provided by the matching reference link definition. Thus,
-`[foo][]` is equivalent to `[foo][foo]`.
-
-```````````````````````````````` example
-[foo][]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[*foo* bar][]
-
-[*foo* bar]: /url "title"
-.
-<p><a href="/url" title="title"><em>foo</em> bar</a></p>
-````````````````````````````````
-
-
-The link labels are case-insensitive:
-
-```````````````````````````````` example
-[Foo][]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">Foo</a></p>
-````````````````````````````````
-
-
-
-As with full reference links, [whitespace] is not
-allowed between the two sets of brackets:
-
-```````````````````````````````` example
-[foo]
-[]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">foo</a>
-[]</p>
-````````````````````````````````
-
-
-A [shortcut reference link](@)
-consists of a [link label] that [matches] a
-[link reference definition] elsewhere in the
-document and is not followed by `[]` or a link label.
-The contents of the first link label are parsed as inlines,
-which are used as the link's text. the link's URI and title
-are provided by the matching link reference definition.
-Thus, `[foo]` is equivalent to `[foo][]`.
-
-```````````````````````````````` example
-[foo]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[*foo* bar]
-
-[*foo* bar]: /url "title"
-.
-<p><a href="/url" title="title"><em>foo</em> bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[[*foo* bar]]
-
-[*foo* bar]: /url "title"
-.
-<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-[[bar [foo]
-
-[foo]: /url
-.
-<p>[[bar <a href="/url">foo</a></p>
-````````````````````````````````
-
-
-The link labels are case-insensitive:
-
-```````````````````````````````` example
-[Foo]
-
-[foo]: /url "title"
-.
-<p><a href="/url" title="title">Foo</a></p>
-````````````````````````````````
-
-
-A space after the link text should be preserved:
-
-```````````````````````````````` example
-[foo] bar
-
-[foo]: /url
-.
-<p><a href="/url">foo</a> bar</p>
-````````````````````````````````
-
-
-If you just want bracketed text, you can backslash-escape the
-opening bracket to avoid links:
-
-```````````````````````````````` example
-\[foo]
-
-[foo]: /url "title"
-.
-<p>[foo]</p>
-````````````````````````````````
-
-
-Note that this is a link, because a link label ends with the first
-following closing bracket:
-
-```````````````````````````````` example
-[foo*]: /url
-
-*[foo*]
-.
-<p>*<a href="/url">foo*</a></p>
-````````````````````````````````
-
-
-Full references take precedence over shortcut references:
-
-```````````````````````````````` example
-[foo][bar]
-
-[foo]: /url1
-[bar]: /url2
-.
-<p><a href="/url2">foo</a></p>
-````````````````````````````````
-
-
-In the following case `[bar][baz]` is parsed as a reference,
-`[foo]` as normal text:
-
-```````````````````````````````` example
-[foo][bar][baz]
-
-[baz]: /url
-.
-<p>[foo]<a href="/url">bar</a></p>
-````````````````````````````````
-
-
-Here, though, `[foo][bar]` is parsed as a reference, since
-`[bar]` is defined:
-
-```````````````````````````````` example
-[foo][bar][baz]
-
-[baz]: /url1
-[bar]: /url2
-.
-<p><a href="/url2">foo</a><a href="/url1">baz</a></p>
-````````````````````````````````
-
-
-Here `[foo]` is not parsed as a shortcut reference, because it
-is followed by a link label (even though `[bar]` is not defined):
-
-```````````````````````````````` example
-[foo][bar][baz]
-
-[baz]: /url1
-[foo]: /url2
-.
-<p>[foo]<a href="/url1">bar</a></p>
-````````````````````````````````
-
-
-
-## Images
-
-Syntax for images is like the syntax for links, with one
-difference. Instead of [link text], we have an
-[image description](@). The rules for this are the
-same as for [link text], except that (a) an
-image description starts with `![` rather than `[`, and
-(b) an image description may contain links.
-An image description has inline elements
-as its contents. When an image is rendered to HTML,
-this is standardly used as the image's `alt` attribute.
-
-```````````````````````````````` example
-![foo](/url "title")
-.
-<p><img src="/url" alt="foo" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo *bar*]
-
-[foo *bar*]: train.jpg "train & tracks"
-.
-<p><img src="train.jpg" alt="foo bar" title="train & tracks" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo ![bar](/url)](/url2)
-.
-<p><img src="/url2" alt="foo bar" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo [bar](/url)](/url2)
-.
-<p><img src="/url2" alt="foo bar" /></p>
-````````````````````````````````
-
-
-Though this spec is concerned with parsing, not rendering, it is
-recommended that in rendering to HTML, only the plain string content
-of the [image description] be used. Note that in
-the above example, the alt attribute's value is `foo bar`, not `foo
-[bar](/url)` or `foo <a href="/url">bar</a>`. Only the plain string
-content is rendered, without formatting.
-
-```````````````````````````````` example
-![foo *bar*][]
-
-[foo *bar*]: train.jpg "train & tracks"
-.
-<p><img src="train.jpg" alt="foo bar" title="train & tracks" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo *bar*][foobar]
-
-[FOOBAR]: train.jpg "train & tracks"
-.
-<p><img src="train.jpg" alt="foo bar" title="train & tracks" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo](train.jpg)
-.
-<p><img src="train.jpg" alt="foo" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-My ![foo bar](/path/to/train.jpg "title" )
-.
-<p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo](<url>)
-.
-<p><img src="url" alt="foo" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![](/url)
-.
-<p><img src="/url" alt="" /></p>
-````````````````````````````````
-
-
-Reference-style:
-
-```````````````````````````````` example
-![foo][bar]
-
-[bar]: /url
-.
-<p><img src="/url" alt="foo" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![foo][bar]
-
-[BAR]: /url
-.
-<p><img src="/url" alt="foo" /></p>
-````````````````````````````````
-
-
-Collapsed:
-
-```````````````````````````````` example
-![foo][]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="foo" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![*foo* bar][]
-
-[*foo* bar]: /url "title"
-.
-<p><img src="/url" alt="foo bar" title="title" /></p>
-````````````````````````````````
-
-
-The labels are case-insensitive:
-
-```````````````````````````````` example
-![Foo][]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="Foo" title="title" /></p>
-````````````````````````````````
-
-
-As with reference links, [whitespace] is not allowed
-between the two sets of brackets:
-
-```````````````````````````````` example
-![foo]
-[]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="foo" title="title" />
-[]</p>
-````````````````````````````````
-
-
-Shortcut:
-
-```````````````````````````````` example
-![foo]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="foo" title="title" /></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-![*foo* bar]
-
-[*foo* bar]: /url "title"
-.
-<p><img src="/url" alt="foo bar" title="title" /></p>
-````````````````````````````````
-
-
-Note that link labels cannot contain unescaped brackets:
-
-```````````````````````````````` example
-![[foo]]
-
-[[foo]]: /url "title"
-.
-<p>![[foo]]</p>
-<p>[[foo]]: /url "title"</p>
-````````````````````````````````
-
-
-The link labels are case-insensitive:
-
-```````````````````````````````` example
-![Foo]
-
-[foo]: /url "title"
-.
-<p><img src="/url" alt="Foo" title="title" /></p>
-````````````````````````````````
-
-
-If you just want bracketed text, you can backslash-escape the
-opening `!` and `[`:
-
-```````````````````````````````` example
-\!\[foo]
-
-[foo]: /url "title"
-.
-<p>![foo]</p>
-````````````````````````````````
-
-
-If you want a link after a literal `!`, backslash-escape the
-`!`:
-
-```````````````````````````````` example
-\![foo]
-
-[foo]: /url "title"
-.
-<p>!<a href="/url" title="title">foo</a></p>
-````````````````````````````````
-
-
-## Autolinks
-
-[Autolink](@)s are absolute URIs and email addresses inside
-`<` and `>`. They are parsed as links, with the URL or email address
-as the link label.
-
-A [URI autolink](@) consists of `<`, followed by an
-[absolute URI] not containing `<`, followed by `>`. It is parsed as
-a link to the URI, with the URI as the link's label.
-
-An [absolute URI](@),
-for these purposes, consists of a [scheme] followed by a colon (`:`)
-followed by zero or more characters other than ASCII
-[whitespace] and control characters, `<`, and `>`. If
-the URI includes these characters, they must be percent-encoded
-(e.g. `%20` for a space).
-
-For purposes of this spec, a [scheme](@) is any sequence
-of 2--32 characters beginning with an ASCII letter and followed
-by any combination of ASCII letters, digits, or the symbols plus
-("+"), period ("."), or hyphen ("-").
-
-Here are some valid autolinks:
-
-```````````````````````````````` example
-<http://foo.bar.baz>
-.
-<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<http://foo.bar.baz/test?q=hello&id=22&boolean>
-.
-<p><a href="http://foo.bar.baz/test?q=hello&id=22&boolean">http://foo.bar.baz/test?q=hello&id=22&boolean</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<irc://foo.bar:2233/baz>
-.
-<p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
-````````````````````````````````
-
-
-Uppercase is also fine:
-
-```````````````````````````````` example
-<MAILTO:FOO@BAR.BAZ>
-.
-<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
-````````````````````````````````
-
-
-Note that many strings that count as [absolute URIs] for
-purposes of this spec are not valid URIs, because their
-schemes are not registered or because of other problems
-with their syntax:
-
-```````````````````````````````` example
-<a+b+c:d>
-.
-<p><a href="a+b+c:d">a+b+c:d</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<made-up-scheme://foo,bar>
-.
-<p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<http://../>
-.
-<p><a href="http://../">http://../</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<localhost:5001/foo>
-.
-<p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
-````````````````````````````````
-
-
-Spaces are not allowed in autolinks:
-
-```````````````````````````````` example
-<http://foo.bar/baz bim>
-.
-<p><http://foo.bar/baz bim></p>
-````````````````````````````````
-
-
-Backslash-escapes do not work inside autolinks:
-
-```````````````````````````````` example
-<http://example.com/\[\>
-.
-<p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
-````````````````````````````````
-
-
-An [email autolink](@)
-consists of `<`, followed by an [email address],
-followed by `>`. The link's label is the email address,
-and the URL is `mailto:` followed by the email address.
-
-An [email address](@),
-for these purposes, is anything that matches
-the [non-normative regex from the HTML5
-spec](https://html.spec.whatwg.org/multipage/forms.html#e-mail-state-(type=email)):
-
- /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
- (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
-
-Examples of email autolinks:
-
-```````````````````````````````` example
-<foo@bar.example.com>
-.
-<p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<foo+special@Bar.baz-bar0.com>
-.
-<p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
-````````````````````````````````
-
-
-Backslash-escapes do not work inside email autolinks:
-
-```````````````````````````````` example
-<foo\+@bar.example.com>
-.
-<p><foo+@bar.example.com></p>
-````````````````````````````````
-
-
-These are not autolinks:
-
-```````````````````````````````` example
-<>
-.
-<p><></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-< http://foo.bar >
-.
-<p>< http://foo.bar ></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<m:abc>
-.
-<p><m:abc></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<foo.bar.baz>
-.
-<p><foo.bar.baz></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-http://example.com
-.
-<p>http://example.com</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo@bar.example.com
-.
-<p>foo@bar.example.com</p>
-````````````````````````````````
-
-
-## Raw HTML
-
-Text between `<` and `>` that looks like an HTML tag is parsed as a
-raw HTML tag and will be rendered in HTML without escaping.
-Tag and attribute names are not limited to current HTML tags,
-so custom tags (and even, say, DocBook tags) may be used.
-
-Here is the grammar for tags:
-
-A [tag name](@) consists of an ASCII letter
-followed by zero or more ASCII letters, digits, or
-hyphens (`-`).
-
-An [attribute](@) consists of [whitespace],
-an [attribute name], and an optional
-[attribute value specification].
-
-An [attribute name](@)
-consists of an ASCII letter, `_`, or `:`, followed by zero or more ASCII
-letters, digits, `_`, `.`, `:`, or `-`. (Note: This is the XML
-specification restricted to ASCII. HTML5 is laxer.)
-
-An [attribute value specification](@)
-consists of optional [whitespace],
-a `=` character, optional [whitespace], and an [attribute
-value].
-
-An [attribute value](@)
-consists of an [unquoted attribute value],
-a [single-quoted attribute value], or a [double-quoted attribute value].
-
-An [unquoted attribute value](@)
-is a nonempty string of characters not
-including spaces, `"`, `'`, `=`, `<`, `>`, or `` ` ``.
-
-A [single-quoted attribute value](@)
-consists of `'`, zero or more
-characters not including `'`, and a final `'`.
-
-A [double-quoted attribute value](@)
-consists of `"`, zero or more
-characters not including `"`, and a final `"`.
-
-An [open tag](@) consists of a `<` character, a [tag name],
-zero or more [attributes], optional [whitespace], an optional `/`
-character, and a `>` character.
-
-A [closing tag](@) consists of the string `</`, a
-[tag name], optional [whitespace], and the character `>`.
-
-An [HTML comment](@) consists of `<!--` + *text* + `-->`,
-where *text* does not start with `>` or `->`, does not end with `-`,
-and does not contain `--`. (See the
-[HTML5 spec](http://www.w3.org/TR/html5/syntax.html#comments).)
-
-A [processing instruction](@)
-consists of the string `<?`, a string
-of characters not including the string `?>`, and the string
-`?>`.
-
-A [declaration](@) consists of the
-string `<!`, a name consisting of one or more uppercase ASCII letters,
-[whitespace], a string of characters not including the
-character `>`, and the character `>`.
-
-A [CDATA section](@) consists of
-the string `<![CDATA[`, a string of characters not including the string
-`]]>`, and the string `]]>`.
-
-An [HTML tag](@) consists of an [open tag], a [closing tag],
-an [HTML comment], a [processing instruction], a [declaration],
-or a [CDATA section].
-
-Here are some simple open tags:
-
-```````````````````````````````` example
-<a><bab><c2c>
-.
-<p><a><bab><c2c></p>
-````````````````````````````````
-
-
-Empty elements:
-
-```````````````````````````````` example
-<a/><b2/>
-.
-<p><a/><b2/></p>
-````````````````````````````````
-
-
-[Whitespace] is allowed:
-
-```````````````````````````````` example
-<a /><b2
-data="foo" >
-.
-<p><a /><b2
-data="foo" ></p>
-````````````````````````````````
-
-
-With attributes:
-
-```````````````````````````````` example
-<a foo="bar" bam = 'baz <em>"</em>'
-_boolean zoop:33=zoop:33 />
-.
-<p><a foo="bar" bam = 'baz <em>"</em>'
-_boolean zoop:33=zoop:33 /></p>
-````````````````````````````````
-
-
-Custom tag names can be used:
-
-```````````````````````````````` example
-Foo <responsive-image src="foo.jpg" />
-.
-<p>Foo <responsive-image src="foo.jpg" /></p>
-````````````````````````````````
-
-
-Illegal tag names, not parsed as HTML:
-
-```````````````````````````````` example
-<33> <__>
-.
-<p><33> <__></p>
-````````````````````````````````
-
-
-Illegal attribute names:
-
-```````````````````````````````` example
-<a h*#ref="hi">
-.
-<p><a h*#ref="hi"></p>
-````````````````````````````````
-
-
-Illegal attribute values:
-
-```````````````````````````````` example
-<a href="hi'> <a href=hi'>
-.
-<p><a href="hi'> <a href=hi'></p>
-````````````````````````````````
-
-
-Illegal [whitespace]:
-
-```````````````````````````````` example
-< a><
-foo><bar/ >
-.
-<p>< a><
-foo><bar/ ></p>
-````````````````````````````````
-
-
-Missing [whitespace]:
-
-```````````````````````````````` example
-<a href='bar'title=title>
-.
-<p><a href='bar'title=title></p>
-````````````````````````````````
-
-
-Closing tags:
-
-```````````````````````````````` example
-</a></foo >
-.
-<p></a></foo ></p>
-````````````````````````````````
-
-
-Illegal attributes in closing tag:
-
-```````````````````````````````` example
-</a href="foo">
-.
-<p></a href="foo"></p>
-````````````````````````````````
-
-
-Comments:
-
-```````````````````````````````` example
-foo <!-- this is a
-comment - with hyphen -->
-.
-<p>foo <!-- this is a
-comment - with hyphen --></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo <!-- not a comment -- two hyphens -->
-.
-<p>foo <!-- not a comment -- two hyphens --></p>
-````````````````````````````````
-
-
-Not comments:
-
-```````````````````````````````` example
-foo <!--> foo -->
-
-foo <!-- foo--->
-.
-<p>foo <!--> foo --></p>
-<p>foo <!-- foo---></p>
-````````````````````````````````
-
-
-Processing instructions:
-
-```````````````````````````````` example
-foo <?php echo $a; ?>
-.
-<p>foo <?php echo $a; ?></p>
-````````````````````````````````
-
-
-Declarations:
-
-```````````````````````````````` example
-foo <!ELEMENT br EMPTY>
-.
-<p>foo <!ELEMENT br EMPTY></p>
-````````````````````````````````
-
-
-CDATA sections:
-
-```````````````````````````````` example
-foo <![CDATA[>&<]]>
-.
-<p>foo <![CDATA[>&<]]></p>
-````````````````````````````````
-
-
-Entity and numeric character references are preserved in HTML
-attributes:
-
-```````````````````````````````` example
-foo <a href="ö">
-.
-<p>foo <a href="ö"></p>
-````````````````````````````````
-
-
-Backslash escapes do not work in HTML attributes:
-
-```````````````````````````````` example
-foo <a href="\*">
-.
-<p>foo <a href="\*"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<a href="\"">
-.
-<p><a href="""></p>
-````````````````````````````````
-
-
-## Hard line breaks
-
-A line break (not in a code span or HTML tag) that is preceded
-by two or more spaces and does not occur at the end of a block
-is parsed as a [hard line break](@) (rendered
-in HTML as a `<br />` tag):
-
-```````````````````````````````` example
-foo
-baz
-.
-<p>foo<br />
-baz</p>
-````````````````````````````````
-
-
-For a more visible alternative, a backslash before the
-[line ending] may be used instead of two spaces:
-
-```````````````````````````````` example
-foo\
-baz
-.
-<p>foo<br />
-baz</p>
-````````````````````````````````
-
-
-More than two spaces can be used:
-
-```````````````````````````````` example
-foo
-baz
-.
-<p>foo<br />
-baz</p>
-````````````````````````````````
-
-
-Leading spaces at the beginning of the next line are ignored:
-
-```````````````````````````````` example
-foo
- bar
-.
-<p>foo<br />
-bar</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo\
- bar
-.
-<p>foo<br />
-bar</p>
-````````````````````````````````
-
-
-Line breaks can occur inside emphasis, links, and other constructs
-that allow inline content:
-
-```````````````````````````````` example
-*foo
-bar*
-.
-<p><em>foo<br />
-bar</em></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-*foo\
-bar*
-.
-<p><em>foo<br />
-bar</em></p>
-````````````````````````````````
-
-
-Line breaks do not occur inside code spans
-
-```````````````````````````````` example
-`code
-span`
-.
-<p><code>code span</code></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-`code\
-span`
-.
-<p><code>code\ span</code></p>
-````````````````````````````````
-
-
-or HTML tags:
-
-```````````````````````````````` example
-<a href="foo
-bar">
-.
-<p><a href="foo
-bar"></p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-<a href="foo\
-bar">
-.
-<p><a href="foo\
-bar"></p>
-````````````````````````````````
-
-
-Hard line breaks are for separating inline content within a block.
-Neither syntax for hard line breaks works at the end of a paragraph or
-other block element:
-
-```````````````````````````````` example
-foo\
-.
-<p>foo\</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-foo
-.
-<p>foo</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-### foo\
-.
-<h3>foo\</h3>
-````````````````````````````````
-
-
-```````````````````````````````` example
-### foo
-.
-<h3>foo</h3>
-````````````````````````````````
-
-
-## Soft line breaks
-
-A regular line break (not in a code span or HTML tag) that is not
-preceded by two or more spaces or a backslash is parsed as a
-softbreak. (A softbreak may be rendered in HTML either as a
-[line ending] or as a space. The result will be the same in
-browsers. In the examples here, a [line ending] will be used.)
-
-```````````````````````````````` example
-foo
-baz
-.
-<p>foo
-baz</p>
-````````````````````````````````
-
-
-Spaces at the end of the line and beginning of the next line are
-removed:
-
-```````````````````````````````` example
-foo
- baz
-.
-<p>foo
-baz</p>
-````````````````````````````````
-
-
-A conforming parser may render a soft line break in HTML either as a
-line break or as a space.
-
-A renderer may also provide an option to render soft line breaks
-as hard line breaks.
-
-## Textual content
-
-Any characters not given an interpretation by the above rules will
-be parsed as plain textual content.
-
-```````````````````````````````` example
-hello $.;'there
-.
-<p>hello $.;'there</p>
-````````````````````````````````
-
-
-```````````````````````````````` example
-Foo χρῆν
-.
-<p>Foo χρῆν</p>
-````````````````````````````````
-
-
-Internal spaces are preserved verbatim:
-
-```````````````````````````````` example
-Multiple spaces
-.
-<p>Multiple spaces</p>
-````````````````````````````````
-
-
-<!-- END TESTS -->
-
-# Appendix: A parsing strategy
-
-In this appendix we describe some features of the parsing strategy
-used in the CommonMark reference implementations.
-
-## Overview
-
-Parsing has two phases:
-
-1. In the first phase, lines of input are consumed and the block
-structure of the document---its division into paragraphs, block quotes,
-list items, and so on---is constructed. Text is assigned to these
-blocks but not parsed. Link reference definitions are parsed and a
-map of links is constructed.
-
-2. In the second phase, the raw text contents of paragraphs and headings
-are parsed into sequences of Markdown inline elements (strings,
-code spans, links, emphasis, and so on), using the map of link
-references constructed in phase 1.
-
-At each point in processing, the document is represented as a tree of
-**blocks**. The root of the tree is a `document` block. The `document`
-may have any number of other blocks as **children**. These children
-may, in turn, have other blocks as children. The last child of a block
-is normally considered **open**, meaning that subsequent lines of input
-can alter its contents. (Blocks that are not open are **closed**.)
-Here, for example, is a possible document tree, with the open blocks
-marked by arrows:
-
-``` tree
--> document
- -> block_quote
- paragraph
- "Lorem ipsum dolor\nsit amet."
- -> list (type=bullet tight=true bullet_char=-)
- list_item
- paragraph
- "Qui *quodsi iracundia*"
- -> list_item
- -> paragraph
- "aliquando id"
-```
-
-## Phase 1: block structure
-
-Each line that is processed has an effect on this tree. The line is
-analyzed and, depending on its contents, the document may be altered
-in one or more of the following ways:
-
-1. One or more open blocks may be closed.
-2. One or more new blocks may be created as children of the
- last open block.
-3. Text may be added to the last (deepest) open block remaining
- on the tree.
-
-Once a line has been incorporated into the tree in this way,
-it can be discarded, so input can be read in a stream.
-
-For each line, we follow this procedure:
-
-1. First we iterate through the open blocks, starting with the
-root document, and descending through last children down to the last
-open block. Each block imposes a condition that the line must satisfy
-if the block is to remain open. For example, a block quote requires a
-`>` character. A paragraph requires a non-blank line.
-In this phase we may match all or just some of the open
-blocks. But we cannot close unmatched blocks yet, because we may have a
-[lazy continuation line].
-
-2. Next, after consuming the continuation markers for existing
-blocks, we look for new block starts (e.g. `>` for a block quote.
-If we encounter a new block start, we close any blocks unmatched
-in step 1 before creating the new block as a child of the last
-matched block.
-
-3. Finally, we look at the remainder of the line (after block
-markers like `>`, list markers, and indentation have been consumed).
-This is text that can be incorporated into the last open
-block (a paragraph, code block, heading, or raw HTML).
-
-Setext headings are formed when we see a line of a paragraph
-that is a [setext heading underline].
-
-Reference link definitions are detected when a paragraph is closed;
-the accumulated text lines are parsed to see if they begin with
-one or more reference link definitions. Any remainder becomes a
-normal paragraph.
-
-We can see how this works by considering how the tree above is
-generated by four lines of Markdown:
-
-``` markdown
-> Lorem ipsum dolor
-sit amet.
-> - Qui *quodsi iracundia*
-> - aliquando id
-```
-
-At the outset, our document model is just
-
-``` tree
--> document
-```
-
-The first line of our text,
-
-``` markdown
-> Lorem ipsum dolor
-```
-
-causes a `block_quote` block to be created as a child of our
-open `document` block, and a `paragraph` block as a child of
-the `block_quote`. Then the text is added to the last open
-block, the `paragraph`:
-
-``` tree
--> document
- -> block_quote
- -> paragraph
- "Lorem ipsum dolor"
-```
-
-The next line,
-
-``` markdown
-sit amet.
-```
-
-is a "lazy continuation" of the open `paragraph`, so it gets added
-to the paragraph's text:
-
-``` tree
--> document
- -> block_quote
- -> paragraph
- "Lorem ipsum dolor\nsit amet."
-```
-
-The third line,
-
-``` markdown
-> - Qui *quodsi iracundia*
-```
-
-causes the `paragraph` block to be closed, and a new `list` block
-opened as a child of the `block_quote`. A `list_item` is also
-added as a child of the `list`, and a `paragraph` as a child of
-the `list_item`. The text is then added to the new `paragraph`:
-
-``` tree
--> document
- -> block_quote
- paragraph
- "Lorem ipsum dolor\nsit amet."
- -> list (type=bullet tight=true bullet_char=-)
- -> list_item
- -> paragraph
- "Qui *quodsi iracundia*"
-```
-
-The fourth line,
-
-``` markdown
-> - aliquando id
-```
-
-causes the `list_item` (and its child the `paragraph`) to be closed,
-and a new `list_item` opened up as child of the `list`. A `paragraph`
-is added as a child of the new `list_item`, to contain the text.
-We thus obtain the final tree:
-
-``` tree
--> document
- -> block_quote
- paragraph
- "Lorem ipsum dolor\nsit amet."
- -> list (type=bullet tight=true bullet_char=-)
- list_item
- paragraph
- "Qui *quodsi iracundia*"
- -> list_item
- -> paragraph
- "aliquando id"
-```
-
-## Phase 2: inline structure
-
-Once all of the input has been parsed, all open blocks are closed.
-
-We then "walk the tree," visiting every node, and parse raw
-string contents of paragraphs and headings as inlines. At this
-point we have seen all the link reference definitions, so we can
-resolve reference links as we go.
-
-``` tree
-document
- block_quote
- paragraph
- str "Lorem ipsum dolor"
- softbreak
- str "sit amet."
- list (type=bullet tight=true bullet_char=-)
- list_item
- paragraph
- str "Qui "
- emph
- str "quodsi iracundia"
- list_item
- paragraph
- str "aliquando id"
-```
-
-Notice how the [line ending] in the first paragraph has
-been parsed as a `softbreak`, and the asterisks in the first list item
-have become an `emph`.
-
-### An algorithm for parsing nested emphasis and links
-
-By far the trickiest part of inline parsing is handling emphasis,
-strong emphasis, links, and images. This is done using the following
-algorithm.
-
-When we're parsing inlines and we hit either
-
-- a run of `*` or `_` characters, or
-- a `[` or `![`
-
-we insert a text node with these symbols as its literal content, and we
-add a pointer to this text node to the [delimiter stack](@).
-
-The [delimiter stack] is a doubly linked list. Each
-element contains a pointer to a text node, plus information about
-
-- the type of delimiter (`[`, `![`, `*`, `_`)
-- the number of delimiters,
-- whether the delimiter is "active" (all are active to start), and
-- whether the delimiter is a potential opener, a potential closer,
- or both (which depends on what sort of characters precede
- and follow the delimiters).
-
-When we hit a `]` character, we call the *look for link or image*
-procedure (see below).
-
-When we hit the end of the input, we call the *process emphasis*
-procedure (see below), with `stack_bottom` = NULL.
-
-#### *look for link or image*
-
-Starting at the top of the delimiter stack, we look backwards
-through the stack for an opening `[` or `![` delimiter.
-
-- If we don't find one, we return a literal text node `]`.
-
-- If we do find one, but it's not *active*, we remove the inactive
- delimiter from the stack, and return a literal text node `]`.
-
-- If we find one and it's active, then we parse ahead to see if
- we have an inline link/image, reference link/image, compact reference
- link/image, or shortcut reference link/image.
-
- + If we don't, then we remove the opening delimiter from the
- delimiter stack and return a literal text node `]`.
-
- + If we do, then
-
- * We return a link or image node whose children are the inlines
- after the text node pointed to by the opening delimiter.
-
- * We run *process emphasis* on these inlines, with the `[` opener
- as `stack_bottom`.
-
- * We remove the opening delimiter.
-
- * If we have a link (and not an image), we also set all
- `[` delimiters before the opening delimiter to *inactive*. (This
- will prevent us from getting links within links.)
-
-#### *process emphasis*
-
-Parameter `stack_bottom` sets a lower bound to how far we
-descend in the [delimiter stack]. If it is NULL, we can
-go all the way to the bottom. Otherwise, we stop before
-visiting `stack_bottom`.
-
-Let `current_position` point to the element on the [delimiter stack]
-just above `stack_bottom` (or the first element if `stack_bottom`
-is NULL).
-
-We keep track of the `openers_bottom` for each delimiter
-type (`*`, `_`). Initialize this to `stack_bottom`.
-
-Then we repeat the following until we run out of potential
-closers:
-
-- Move `current_position` forward in the delimiter stack (if needed)
- until we find the first potential closer with delimiter `*` or `_`.
- (This will be the potential closer closest
- to the beginning of the input -- the first one in parse order.)
-
-- Now, look back in the stack (staying above `stack_bottom` and
- the `openers_bottom` for this delimiter type) for the
- first matching potential opener ("matching" means same delimiter).
-
-- If one is found:
-
- + Figure out whether we have emphasis or strong emphasis:
- if both closer and opener spans have length >= 2, we have
- strong, otherwise regular.
-
- + Insert an emph or strong emph node accordingly, after
- the text node corresponding to the opener.
-
- + Remove any delimiters between the opener and closer from
- the delimiter stack.
-
- + Remove 1 (for regular emph) or 2 (for strong emph) delimiters
- from the opening and closing text nodes. If they become empty
- as a result, remove them and remove the corresponding element
- of the delimiter stack. If the closing node is removed, reset
- `current_position` to the next element in the stack.
-
-- If none in found:
-
- + Set `openers_bottom` to the element before `current_position`.
- (We know that there are no openers for this kind of closer up to and
- including this point, so this puts a lower bound on future searches.)
-
- + If the closer at `current_position` is not a potential opener,
- remove it from the delimiter stack (since we know it can't
- be a closer either).
-
- + Advance `current_position` to the next element in the stack.
-
-After we're done, we remove all delimiters above `stack_bottom` from the
-delimiter stack.
-
+++ /dev/null
-import "Prelude"\r
-\r
-main :: Double -> Double\r
-main m = loop 1 0\r
- where\r
- loop x cur = if x > m\r
- then cur\r
- else loop (x+1) (cur + 1 / x)
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main :: Integer -> Double\r
-main m = sum [1/(fromInteger x) | x <- [1..m]]\r
+++ /dev/null
-\r
-\r
-class Show a where\r
- show :: a -> String\r
- \r
-class Read a where\r
- read :: String -> a\r
- \r
-combine x = show (read x)\r
---\r
-9:13-9:17: Constrain Show a contains free variables not mentioned in the type of the value.\r
-9:19-9:23: Constrain Read a contains free variables not mentioned in the type of the value.
\ No newline at end of file
+++ /dev/null
-main = "Hello" "world!"\r
---\r
-1:8-1:24: Application of non-function.\r
+++ /dev/null
-\r
-data Foo a = Foo a\r
-\r
-f :: Foo a -> a\r
-f = \Foo a -> a \r
-\r
-main = "Not to be executed"\r
---\r
-5:6-5:11: Arity is 1 but 2 patterns have been given.
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-sort p@(a,b) | Java.icmpgt a b = (b,a)\r
- | True = p\r
- \r
-main = sort (sort (2 :: Integer,1 :: Integer))\r
---\r
-(1,2)
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = do \r
- a1 = 1\r
- a2 = 1\r
- a3 = 1\r
- a4 = 1\r
- a5 = 1\r
- a6 = 1\r
- a7 = 1\r
- a8 = 1\r
- a9 = 1\r
- a10 = 1\r
- a11 = 1\r
- a12 = 1\r
- a13 = 1\r
- a14 = 1\r
- a15 = 1\r
- a16 = 1\r
- a17 = 1\r
- a18 = 1\r
- a19 = 1\r
- a20 = 1\r
- f x = x + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + \r
- a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20\r
- f 10\r
---\r
-30
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-f a b c d e f g h = a + b + c + d + e + f + g + h\r
-\r
-main = (id f) 1 2 3 4 5 6 7 8\r
---\r
-36
\ No newline at end of file
+++ /dev/null
-\r
-class Foo a where\r
- foo :: a\r
- \r
-class (Foo a) => Bar a where\r
- bar :: a\r
- \r
-instance Bar Double where\r
- foo x = x\r
- bar x = x\r
- \r
-main = foo 3.0 + bar 4.0\r
---\r
-7.0\r
-\r
-
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-data E = E String\r
-\r
-instance Additive E where\r
- zero = E "0"\r
- E a + E b = E ("(" + a + "+" + b + ")")\r
- \r
-instance Ring E where\r
- one = E "1"\r
- neg (E a) = E ("(-" + a + ")")\r
- E a - E b = E ("(" + a + "-" + b + ")")\r
- E a * E b = E ("(" + a + "*" + b + ")") \r
- fromInteger x = E (show x)\r
-\r
-eToString (E a) = a\r
-\r
-a = E "a"\r
-b = E "b"\r
-c = E "c"\r
-d = E "d"\r
-\r
-main = eToString (-a + b + (-c*d))\r
---\r
-(((-a)+b)+(-(c*d)))
\ No newline at end of file
+++ /dev/null
-main = _\r
---\r
-???
\ No newline at end of file
+++ /dev/null
-@private\r
-@inline\r
-not True = False\r
-not False = True\r
-\r
-@private\r
-@inline\r
-id x = not (not x)\r
-\r
-main = id True\r
---\r
-true
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-csvWrite :: String -> [[String]] -> <Proc> ()\r
-csvWrite fname rows = ()\r
-\r
-/// Like writeEntries but with a transformer function also for values.\r
-/// kfun key + vfun value should have the length of header.\r
-writeEntries' :: (k -> [String]) -> (v -> [String])\r
- -> String -> [String] -> [(k, v)] -> <Proc> ()\r
-writeEntries' kfun vfun fname header rows =\r
- csvWrite fname $ [header] + [kfun k + vfun v | (k, v) <- rows]\r
- \r
-main = "OK"\r
---\r
-OK
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = subChar '6' '0'\r
---\r
-6\r
+++ /dev/null
-\r
-class A a where\r
- foo :: a\r
- \r
-class A a where\r
- bar :: a\r
---\r
-5:1-6:13: Class A has already been defined in this module.
\ No newline at end of file
+++ /dev/null
-\r
-data A = A\r
-data A = B\r
---\r
-3:1-3:11: Type A has already been defined in this module.
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 6 (+)\r
-\r
-class Additive a where \r
- (+) :: a -> a -> a \r
- \r
-instance Additive Double where\r
- (+) = Java.dadd\r
-\r
-instance Additive Double where\r
- (+) = Java.dadd\r
---\r
-11:1-12:20: Duplicate definition of the instance Additive Double.
\ No newline at end of file
+++ /dev/null
-a = 1\r
-a = 2\r
-main = "Should not be executed."\r
---\r
-???
\ No newline at end of file
+++ /dev/null
-\r
-id :: Integer -> Integer\r
-id :: Double -> Double\r
-id x = x\r
---\r
-3:1-3:23: Type of id has already been declared in this module.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-f x = if x `mod` 2 == 0\r
- then x `div` 2\r
- else 3*x + 1\r
-fd x = unfoldr (\x -> do\r
- r = f x \r
- if x == 1\r
- then Nothing\r
- else Just (x,r)\r
- ) x\r
-\r
-//main :: [Integer] \r
-main = fd 7\r
---\r
-[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2]
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-(+) = Java.iadd\r
-(-) = Java.isub\r
-(*) = Java.imul\r
-\r
-data List a = Nil | Cons a (List a) \r
-\r
-compose :: List (a -> a) -> a -> a\r
-compose Nil x = x\r
-compose (Cons h t) x = compose t (h x)\r
-\r
-succ x = x + 1\r
-prec x = x - 1\r
-double x = x * 2\r
-\r
-f = compose (Cons succ (Cons double (Cons prec Nil)))\r
-main = f 13\r
---\r
-27
\ No newline at end of file
+++ /dev/null
-infixr 9 (.)\r
-\r
-@private\r
-@inline\r
-(f . g) = \x -> f (g x)\r
-\r
-@private\r
-@inline\r
-flip (x,y) = (y,x)\r
-\r
-@private\r
-@inline\r
-flip4 = flip . flip . flip . flip\r
-\r
-main = flip4 ("a", "b")\r
---\r
-(a,b)
\ No newline at end of file
+++ /dev/null
-(&&) :: Boolean -> (<e> Boolean) -> <e> Boolean\r
-a && b = if a then b else False\r
-\r
-main = False && fail "Should not be evaluated!"\r
---\r
-false
\ No newline at end of file
+++ /dev/null
-\r
-a = 14 :: Integer\r
-\r
-main = a\r
---\r
-14
\ No newline at end of file
+++ /dev/null
-\r
-data Vec2 = Vec2 Double Double\r
-data Vec3 = Vec2 Double Double Double\r
-\r
-main = "Not to be executed."\r
---\r
-3:13-3:38: Value Vec2 is already defined.
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-class Ord a where\r
- (<) :: a -> a -> Boolean\r
- min :: a -> a -> a\r
- min x y = if x < y then x else y\r
- \r
-instance Ord Integer where\r
- (<) = Java.icmplt\r
-\r
-main = min (43 :: Integer) (69 :: Integer) \r
---\r
-43
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a,b,c,d :: Either Boolean Boolean\r
-a = Left False\r
-b = Left True \r
-c = Right False\r
-d = Right True\r
-\r
-main = a == a\r
- && a < b\r
- && a < c\r
- && a < d\r
- \r
- && b > a\r
- && b == b\r
- && b < c\r
- && b < d\r
-\r
- && c > a\r
- && c > b\r
- && c == c\r
- && c < d\r
-\r
- && d > a\r
- && d > b\r
- && d > c\r
- && d == d\r
---\r
-true
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-
-data Foo = Foo Integer Long Double Float
-
-deriving instance Show Foo
-
-main = show (Foo (-1) (-1) (-1) (-1))
---
-Foo (-1) (-1) (-1.0) (-1.0)
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-
-foo n = n
- where
- if n > 0
- then 1
- else "asd"
-
-bar n = n
- where
- do
- c = n+1
- if c > 0
- then 1
- else "asd"
-
-main = foo 3 + bar 3
---
-6
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = 7 `div` 3\r
---\r
-2
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-f :: Float\r
-f = 1.0\r
-\r
-d :: Double\r
-d = 1.0\r
-\r
-d2f :: Float\r
-d2f = fromDouble d\r
-\r
-f2d :: Double\r
-f2d = toDouble f\r
-\r
-main = show (d+f2d, f+d2f)\r
---\r
-(2.0, 2.0)
\ No newline at end of file
+++ /dev/null
-app :: (Integer -> <e1> Integer) -> <e1> ((Integer -> <e2> Integer) -> <e2> Integer)\r
-app f = do\r
- a = f 1\r
- \g -> g a\r
- \r
-main = app (\x -> x) (\x -> x)\r
---\r
-1
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-importJava "java.util.regex.Pattern" where\r
- data Pattern\r
-\r
- compile :: String -> Pattern\r
- matcher :: Pattern -> String -> <Proc> Matcher\r
-\r
-importJava "java.util.regex.Matcher" where\r
- data Matcher\r
-\r
- matches :: Matcher -> <Proc> Boolean\r
-\r
-doMatch pattern text = matches (matcher pattern text)\r
-\r
-main = doMatch (compile ".*xxx.*") "fffxxooxxxlll"\r
---\r
-true
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-importJava "java.util.List" where\r
- data List a\r
-\r
- add :: List a -> a -> <Proc> Boolean\r
-\r
-importJava "java.util.ArrayList" where\r
- @JavaName "<init>"\r
- arrayList :: Integer -> <Proc> List a\r
-\r
-singleton :: a -> <Proc> List a\r
-singleton el = result\r
- where\r
- result = arrayList 1\r
- r = add result el\r
-\r
-main :: List Integer\r
-main = runProc (singleton (13 :: Integer))\r
---\r
-[13]
\ No newline at end of file
+++ /dev/null
-effectfulId :: a -> <Proc> a\r
-effectfulId x = x\r
-\r
-(.) :: (b -> <e> c) -> (a -> <e> b) -> a -> <e> c\r
-(f . g) x = f (g x)\r
-\r
-doubleId = effectfulId . effectfulId\r
-\r
-main :: Integer\r
-main = runProc (doubleId (13 :: Integer))\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-effectfulId :: a -> <Proc> a\r
-effectfulId x = x\r
-\r
-//double :: (a -> <e> a) -> a -> <e> a\r
-double f x = f (f x)\r
-\r
-doubleId = double effectfulId\r
-\r
-main :: Integer\r
-main = runProc (doubleId (13 :: Integer))\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-effectfulId :: a -> <Proc> a\r
-effectfulId x = x\r
-\r
-(.) :: (b -> <e2> c) -> (a -> <e1> b) -> a -> <e1,e2> c\r
-(f . g) x = f (g x)\r
-\r
-//doubleId :: a -> <Proc> a\r
-doubleId = effectfulId . effectfulId\r
-\r
-main :: Integer\r
-main = runProc (doubleId (13 :: Integer))\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-effectfulId :: a -> <Proc> a\r
-effectfulId x = x\r
-\r
-(.) :: (b -> <e2> c) -> (a -> <e1> b) -> a -> <e1,e2> c\r
-(f . g) x = f (g x)\r
-\r
-doubleId :: a -> <Proc> a\r
-doubleId = effectfulId . effectfulId\r
-\r
-main :: Integer\r
-main = runProc (doubleId (13 :: Integer))\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-ex1 = let in 1\r
-ex2 = let {} in 2\r
-ex3 = let {a=3} in a \r
-\r
-main = ex1 + ex2 + ex3\r
---\r
-6
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = """\r
-\(newEq () ())\r
-\(newEq True True)\r
-\(newEq False False)\r
-\(newEq True False)\r
-\(newEq False True)\r
-\(newEq (1::Integer) (1::Integer))\r
-\(newEq (1::Integer) (2::Integer))\r
-\(newEq (1::Long) (1::Long))\r
-\(newEq (1::Long) (2::Long))\r
-\(newEq (1::Double) (1::Double))\r
-\(newEq (1::Double) (2::Double))\r
-\(newEq "a" "a")\r
-\(newEq "a" "b")\r
-\(newEq (Just "a") (Just "a"))\r
-\(newEq (Just "a") (Just "b"))\r
-\(newEq Nothing Nothing)\r
-\(newEq (Just "a") Nothing)\r
-\(newEq Nothing (Just "a"))\r
-"""\r
---\r
-True\r
-True\r
-True\r
-False\r
-False\r
-True\r
-False\r
-True\r
-False\r
-True\r
-False\r
-True\r
-False\r
-True\r
-False\r
-True\r
-False\r
-False
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-import "Expressions/Equations"
-
-main = v
- where
- v = solveEquations do
- listenEquationVariable "a" $ \a -> setEquationVariable "c" (a-1)
- setEquationVariable "a" 123
- listenEquationVariable "a" $ \a -> setEquationVariable "b" (a+1)
- print v
---
-[(a,123), (b,124), (c,122)]
-
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-(+) = Java.iadd\r
-\r
-data Thunk a = /* forall s. */ Thunk s (s -> a)\r
-\r
-id :: a -> a\r
-id x = x\r
-\r
-runThunk :: Thunk a -> a\r
-runThunk (Thunk s f) = f s\r
-\r
-makeThunk :: a -> Thunk a\r
-makeThunk x = Thunk x id\r
-\r
-mapThunk :: (a -> b) -> Thunk a -> Thunk b\r
-mapThunk f (Thunk s g) = Thunk s (\x -> f (g x))\r
-\r
-a = makeThunk (13 :: Integer)\r
-b = mapThunk (\x -> x+1) a\r
-main = runThunk b\r
---\r
-14
\ No newline at end of file
+++ /dev/null
-data Thunk a = /* forall s. */ Thunk s (s -> a)\r
-\r
-mixThunks (Thunk s0 f0) (Thunk s1 f1) = f0 s1\r
-\r
-main = "Not to be executed!"\r
---\r
-3:44-3:46: Expected <a> got <b>.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-data Exp = Exp String\r
-\r
-expToString :: Exp -> String\r
-expToString (Exp s) = s\r
-\r
-instance Additive Exp where\r
- zero = Exp "0"\r
- Exp a + Exp b = Exp ("(" + a + " + " + b + ")")\r
-\r
-instance Ring Exp where\r
- one = Exp "1"\r
- neg (Exp a) = Exp ("(-" + a + ")")\r
- Exp a * Exp b = Exp ("(" + a + " * " + b + ")")\r
- Exp a - Exp b = Exp ("(" + a + " - " + b + ")")\r
- fromInteger x = Exp (show x)\r
- \r
-a = Exp "a"\r
-b = Exp "b"\r
-c = Exp "c"\r
-d = Exp "d"\r
-e = Exp "e"\r
-\r
-main = expToString (a + b*c + d*e)\r
---\r
-((a + (b * c)) + (d * e))
\ No newline at end of file
+++ /dev/null
-fib n = fib\r
---\r
-1:9-1:12: Expected <a> got <b -> <c> a>.
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-(+) = Java.iadd\r
-(-) = Java.isub\r
-(<=) = Java.icmple\r
-\r
-fibonacci x = if x <= (1 :: Integer) \r
- then 1 :: Integer \r
- else fibonacci (x - 1) \r
- + fibonacci (x - 2)\r
-\r
-main = fibonacci 10\r
---\r
-89
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-fibonacci :: Integer -> Integer\r
-fibonacci x = if x <= 1 \r
- then 1 \r
- else fibonacci (x - 1) \r
- + fibonacci (x - 2)\r
-\r
-main = fibonacci 10\r
---\r
-89
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
- \r
-class Num a where\r
- (+) :: a -> a -> a\r
- (-) :: a -> a -> a\r
-\r
-instance Num Integer where\r
- (+) = Java.iadd\r
- (-) = Java.isub\r
-\r
-(<=) = Java.icmple\r
-\r
-fibonacci x = if x <= (1 :: Integer) \r
- then 1 :: Integer\r
- else fibonacci (x - (1 :: Integer)) \r
- + fibonacci (x - (2 :: Integer))\r
-\r
-main = fibonacci 10\r
---\r
-89
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-main = foldl Java.iadd (0 :: Integer) (concat (concat (Single (1 :: Integer)) \r
- (Single (2 :: Integer))) (Single (3 :: Integer))) \r
-\r
-data Digit a = Digit1 a\r
- | Digit2 a a\r
- | Digit3 a a a\r
- | Digit4 a a a a\r
-data Node a = Node2 a a | Node3 a a a\r
-data FingerTree a = Empty | Single a | Deep (Digit a) (FingerTree (Node a)) (Digit a)\r
-\r
-insertL :: a -> FingerTree a -> FingerTree a\r
-insertL a Empty = Single a\r
-insertL a (Single b) = Deep (Digit1 a) Empty (Digit1 b)\r
-insertL a (Deep (Digit1 b) m r) = Deep (Digit2 a b) m r\r
-insertL a (Deep (Digit2 b c) m r) = Deep (Digit3 a b c) m r\r
-insertL a (Deep (Digit3 b c d) m r) = Deep (Digit4 a b c d) m r\r
-insertL a (Deep (Digit4 b c d e) m r) = Deep (Digit2 a b) (insertL (Node3 c d e) m) r\r
-\r
-insertR :: FingerTree a -> a -> FingerTree a\r
-insertR Empty a = Single a\r
-insertR (Single a) b = Deep (Digit1 a) Empty (Digit1 b)\r
-insertR (Deep l m (Digit1 a)) b = Deep l m (Digit2 a b)\r
-insertR (Deep l m (Digit2 a b)) c = Deep l m (Digit3 a b c)\r
-insertR (Deep l m (Digit3 a b c)) d = Deep l m (Digit4 a b c d)\r
-insertR (Deep l m (Digit4 a b c d)) e = Deep l (insertR m (Node3 a b c)) (Digit2 d e)\r
-\r
-foldl :: (a -> b -> a) -> a -> FingerTree b -> a\r
-foldl f init Empty = init\r
-foldl f init (Single x) = f init x\r
-foldl f init (Deep l m r) = foldlD (foldl foldlN (foldlD init l) m) r\r
- where\r
- foldlD init (Digit1 a) = f init a\r
- foldlD init (Digit2 a b) = f (f init a) b\r
- foldlD init (Digit3 a b c) = f (f (f init a) b) c\r
- foldlD init (Digit4 a b c d) = f (f (f (f init a) b) c) d\r
- \r
- foldlN init (Node2 a b) = f (f init a) b\r
- foldlN init (Node3 a b c) = f (f (f init a) b) c\r
-\r
-data View a = Nil | Cons a (FingerTree a)\r
-\r
-viewL :: FingerTree a -> View a\r
-viewL Empty = Nil\r
-viewL (Single a) = Cons a Empty\r
-viewL (Deep (Digit1 a) m r) = Cons a tail\r
- where\r
- tail = match viewL m with\r
- Nil -> digitToFingerTree r\r
- Cons h t -> Deep (nodeToDigit h) t r\r
-viewL (Deep (Digit2 a b) m r) = Cons a (Deep (Digit1 a) m r)\r
-viewL (Deep (Digit3 a b c) m r) = Cons a (Deep (Digit2 a b) m r)\r
-viewL (Deep (Digit4 a b c d) m r) = Cons a (Deep (Digit3 a b c) m r)\r
-\r
-concat :: FingerTree a -> FingerTree a -> FingerTree a\r
-concat Empty a = a\r
-concat a Empty = a\r
-concat (Single a) b = insertL a b\r
-concat a (Single b) = insertR a b\r
-concat (Deep l1 m1 r1) (Deep l2 m2 r2) = Deep l1 mm r2\r
- where\r
- mm = concatAux m1 (digitsToNodes r1 l2) m2\r
- \r
-// --- Implementation details -------------------------------------------------\r
-\r
-digitToFingerTree :: Digit a -> FingerTree a\r
-digitToFingerTree (Digit1 a) = Single a\r
-digitToFingerTree (Digit2 a b) = Deep (Digit1 a) Empty (Digit1 b)\r
-digitToFingerTree (Digit3 a b c) = Deep (Digit2 a b) Empty (Digit1 c)\r
-digitToFingerTree (Digit4 a b c d) = Deep (Digit2 a b) Empty (Digit2 c d)\r
-\r
-nodeToDigit :: Node a -> Digit a\r
-nodeToDigit (Node2 a b) = Digit2 a b\r
-nodeToDigit (Node3 a b c) = Digit3 a b c\r
- \r
-concatAux :: FingerTree a -> Digit a -> FingerTree a -> FingerTree a\r
-concatAux Empty ds a = insertLD ds a\r
-concatAux a ds Empty = insertRD a ds\r
-concatAux (Single a) ds b = insertL a (insertLD ds b)\r
-concatAux a ds (Single b) = insertR (insertRD a ds) b\r
-concatAux (Deep l1 m1 r1) ds (Deep l2 m2 r2) = Deep l1 mm r2\r
- where\r
- mm = concatAux m1 (digitsToNodes3 r1 ds r2) m2\r
-\r
-insertLD :: Digit a -> FingerTree a -> FingerTree a\r
-insertLD (Digit1 a) t = insertL a t\r
-insertLD (Digit2 a b) t = insertL a (insertL b t)\r
-insertLD (Digit3 a b c) t = insertL a (insertL b (insertL c t))\r
-insertLD (Digit4 a b c d) t = insertL a (insertL b (insertL c (insertL d t)))\r
-\r
-insertRD :: FingerTree a -> Digit a -> FingerTree a\r
-insertRD t (Digit1 a) = insertR t a\r
-insertRD t (Digit2 a b) = insertR (insertR t a) b\r
-insertRD t (Digit3 a b c) = insertR (insertR (insertR t a) b) c\r
-insertRD t (Digit4 a b c d) = insertR (insertR (insertR (insertR t a) b) c) d\r
- \r
-digitsToNodes :: Digit a -> Digit a -> Digit (Node a)\r
-digitsToNodes (Digit1 a) x = dd1 a x\r
-digitsToNodes (Digit2 a b) x = dd2 a b x \r
-digitsToNodes (Digit3 a b c) x = dd3 a b c x\r
-digitsToNodes (Digit4 a b c d) x = dd4 a b c d x \r
-\r
-digitsToNodes3 :: Digit a -> Digit a -> Digit a -> Digit (Node a)\r
-digitsToNodes3 (Digit1 a) x y = ddd1 a x y\r
-digitsToNodes3 (Digit2 a b) x y = ddd2 a b x y\r
-digitsToNodes3 (Digit3 a b c) x y = ddd3 a b c x y\r
-digitsToNodes3 (Digit4 a b c d) x y = ddd4 a b c d x y \r
- \r
-d2 a b = Digit1 (Node2 a b)\r
-d3 a b c = Digit1 (Node3 a b c)\r
-d4 a b c d = Digit2 (Node2 a b) (Node2 c d)\r
-d5 a b c d e = Digit2 (Node3 a b c) (Node2 d e)\r
-d6 a b c d e f = Digit2 (Node3 a b c) (Node3 d e f)\r
-d7 a b c d e f g = Digit3 (Node3 a b c) (Node2 d e) (Node2 f g)\r
-d8 a b c d e f g h = Digit3 (Node3 a b c) (Node3 d e f) (Node2 g h)\r
-d9 a b c d e f g h i = Digit3 (Node3 a b c) (Node3 d e f) (Node3 g h i)\r
-d10 a b c d e f g h i j = Digit4 (Node3 a b c) (Node3 d e f) (Node2 g h) (Node2 i j)\r
-d11 a b c d e f g h i j k = Digit4 (Node3 a b c) (Node3 d e f) (Node3 g h i) (Node2 j k)\r
-d12 a b c d e f g h i j k l = Digit4 (Node3 a b c) (Node3 d e f) (Node3 g h i) (Node3 j k l)\r
-\r
-dd1 a (Digit1 b) = d2 a b\r
-dd1 a (Digit2 b c) = d3 a b c\r
-dd1 a (Digit3 b c d) = d4 a b c d\r
-dd1 a (Digit4 b c d e) = d5 a b c d e\r
-dd2 a b (Digit1 c) = d3 a b c\r
-dd2 a b (Digit2 c d) = d4 a b c d\r
-dd2 a b (Digit3 c d e) = d5 a b c d e\r
-dd2 a b (Digit4 c d e f) = d6 a b c d e f\r
-dd3 a b c (Digit1 d) = d4 a b c d\r
-dd3 a b c (Digit2 d e) = d5 a b c d e\r
-dd3 a b c (Digit3 d e f) = d6 a b c d e f\r
-dd3 a b c (Digit4 d e f g) = d7 a b c d e f g\r
-dd4 a b c d (Digit1 e) = d5 a b c d e\r
-dd4 a b c d (Digit2 e f) = d6 a b c d e f\r
-dd4 a b c d (Digit3 e f g) = d7 a b c d e f g\r
-dd4 a b c d (Digit4 e f g h) = d8 a b c d e f g h\r
-dd5 a b c d e (Digit1 f) = d6 a b c d e f\r
-dd5 a b c d e (Digit2 f g) = d7 a b c d e f g\r
-dd5 a b c d e (Digit3 f g h) = d8 a b c d e f g h\r
-dd5 a b c d e (Digit4 f g h i) = d9 a b c d e f g h i\r
-dd6 a b c d e f (Digit1 g) = d7 a b c d e f g\r
-dd6 a b c d e f (Digit2 g h) = d8 a b c d e f g h\r
-dd6 a b c d e f (Digit3 g h i) = d9 a b c d e f g h i\r
-dd6 a b c d e f (Digit4 g h i j) = d10 a b c d e f g h i j\r
-dd7 a b c d e f g (Digit1 h) = d8 a b c d e f g h\r
-dd7 a b c d e f g (Digit2 h i) = d9 a b c d e f g h i\r
-dd7 a b c d e f g (Digit3 h i j) = d10 a b c d e f g h i j\r
-dd7 a b c d e f g (Digit4 h i j k) = d11 a b c d e f g h i j k\r
-dd8 a b c d e f g h (Digit1 i) = d9 a b c d e f g h i\r
-dd8 a b c d e f g h (Digit2 i j) = d10 a b c d e f g h i j\r
-dd8 a b c d e f g h (Digit3 i j k) = d11 a b c d e f g h i j k\r
-dd8 a b c d e f g h (Digit4 i j k l) = d12 a b c d e f g h i j k l\r
-\r
-ddd1 a (Digit1 b) y = dd2 a b y\r
-ddd1 a (Digit2 b c) y = dd3 a b c y\r
-ddd1 a (Digit3 b c d) y = dd4 a b c d y\r
-ddd1 a (Digit4 b c d e) y = dd5 a b c d e y\r
-ddd2 a b (Digit1 c) y = dd3 a b c y\r
-ddd2 a b (Digit2 c d) y = dd4 a b c d y\r
-ddd2 a b (Digit3 c d e) y = dd5 a b c d e y\r
-ddd2 a b (Digit4 c d e f) y = dd6 a b c d e f y\r
-ddd3 a b c (Digit1 d) y = dd4 a b c d y\r
-ddd3 a b c (Digit2 d e) y = dd5 a b c d e y\r
-ddd3 a b c (Digit3 d e f) y = dd6 a b c d e f y\r
-ddd3 a b c (Digit4 d e f g) y = dd7 a b c d e f g y\r
-ddd4 a b c d (Digit1 e) y = dd5 a b c d e y\r
-ddd4 a b c d (Digit2 e f) y = dd6 a b c d e f y\r
-ddd4 a b c d (Digit3 e f g) y = dd7 a b c d e f g y\r
-ddd4 a b c d (Digit4 e f g h) y = dd8 a b c d e f g h y\r
-\r
---\r
-6
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-f p l = (foldl (+) (map ((+)p) l)) + p\r
---\r
-3:1-3:39: Couldn't simplify all effect subsumptions away. The current compiler cannot handle this situation. Try adding more type annotations.\r
-3:25-3:31: Type [a b] -> <c> a b is not a subtype of a.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-inc :: Ref Integer -> <Proc> Integer\r
-inc r = do \r
- v = getRef r\r
- newV = v+1\r
- r := newV\r
- newV\r
-\r
-main = do\r
- r = ref 0\r
- // Because both map and for get side-effectful functions\r
- // as parameters, the fusion is not allowed.\r
- l = map (\_ -> inc r) [1..4] \r
- for l (\i -> r := i+1)\r
- getRef r\r
---\r
-5\r
+++ /dev/null
-import "Prelude"\r
-\r
-inc :: Ref Integer -> <Proc> Integer\r
-inc r = do \r
- v = getRef r\r
- newV = v+1\r
- r := newV\r
- newV\r
-\r
-main = do\r
- r = ref 0\r
- l = map (\_ -> inc r) [1..4]\r
- r := 4 // Map must be executed before this statement\r
- foldl (+) 0 l\r
---\r
-10\r
+++ /dev/null
- \r
-id :: forall a. a -> a\r
- // ^ not usually needed, but we test just that this is possible\r
-id x = x\r
-\r
-main = id (3 :: Integer)\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-build :: (forall l. l -> (a -> l -> l) -> l) -> List a\r
-build f = f Nil Cons\r
-\r
-main = build (\nil cons -> cons (1 :: Integer) (cons (2 :: Integer) nil))\r
--- \r
-(Cons 1 (Cons 2 Nil))
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-build :: (forall l. l -> (a -> l -> l) -> l) -> List a\r
-build f = f Nil Cons\r
-\r
-main = build (\nil cons -> cons (1 :: Integer) (Cons (2 :: Integer) nil))\r
- // ^^^^\r
--- \r
-7:48-7:73: Expected <a> got <List Integer>.\r
-7:69-7:72: Expected <List Integer> got <a>.
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-
-data Formula a = TrueF
- | FalseF
- | XorF (Formula a) (Formula a)
- | AndF (Formula a) (Formula a)
- | ConditionF a
- | NextF (Formula a)
- | UntilF (Formula a) (Formula a)
-
-deriving instance (Ord a) => Ord (Formula a)
-
-instance (Show a) => Show (Formula a) where
- sb <+ TrueF = sb << "true"
- sb <+ FalseF = sb << "false"
- sb <+ XorF a b = sb << "(" <+ a << " `XorF` " <+ b << ")"
- sb <+ AndF a b = sb << "(" <+ a << " &&& " <+ b << ")"
- sb <+ ConditionF c = sb <+ c
- sb <+ NextF a = sb << "(next " <+ a << ")"
- sb <+ UntilF a b = sb << "(" <+ a << " `UntilF` " <+ b << ")"
-
-xorF FalseF f2 = f2
-xorF f1 FalseF = f1
-xorF f1@(XorF h1 t1) f2@(XorF h2 t2) =
- let cmp = compare h1 h2
- in if cmp < 0
- then XorF h1 (xorF t1 f2)
- else if cmp > 0
- then XorF h2 (xorF f1 t2)
- else xorF t1 t2
-xorF f1@(XorF h1 t1) f2 =
- let cmp = compare h1 f2
- in if cmp < 0
- then XorF h1 (xorF t1 f2)
- else if cmp > 0
- then XorF f2 f1
- else t1
-xorF f1 f2@(XorF h2 t2) =
- let cmp = compare f1 h2
- in if cmp < 0
- then XorF f1 f2
- else if cmp > 0
- then XorF h2 (xorF f1 t2)
- else t2
-xorF f1 f2 =
- let cmp = compare f1 f2
- in if cmp < 0
- then XorF f1 f2
- else if cmp > 0
- then XorF f2 f1
- else TrueF
-
-notF f = xorF TrueF f
-
-TrueF &&& f2 = f2
-f1 &&& TrueF = f1
-FalseF &&& _ = FalseF
-_ &&& FalseF = FalseF
-XorF h1 t1 &&& f2 = xorF (h1 &&& f2) (t1 &&& f2)
-f1 &&& XorF h2 t2 = xorF (f1 &&& h2) (f1 &&& t2)
-f1@(AndF h1 t1) &&& f2@(AndF h2 t2) =
- let cmp = compare h1 h2
- in if cmp < 0
- then AndF h1 (t1 &&& f2)
- else if cmp > 0
- then AndF h2 (f1 &&& t2)
- else AndF h1 (t1 &&& t2)
-f1@(AndF h1 t1) &&& f2 =
- let cmp = compare h1 f2
- in if cmp < 0
- then AndF h1 (t1 &&& f2)
- else if cmp > 0
- then AndF f2 f1
- else f1
-f1 &&& f2@(AndF h2 t2) =
- let cmp = compare f1 h2
- in if cmp < 0
- then AndF f1 f2
- else if cmp > 0
- then AndF h2 (f1 &&& t2)
- else f2
-f1 &&& f2 =
- let cmp = compare f1 f2
- in if cmp < 0
- then AndF f1 f2
- else if cmp > 0
- then AndF f2 f1
- else f1
-
-f1 ||| f2 = xorF (xorF f1 f2) (f1 &&& f2)
-
-eval :: Ord a => (a -> <e> Boolean) -> Formula a -> <e> Formula a
-eval s TrueF = TrueF
-eval s FalseF = FalseF
-eval s (XorF f1 f2) = xorF (eval s f1) (eval s f2)
-eval s (AndF f1 f2) = eval s f1 &&& eval s f2
-eval s (ConditionF c) = if s c then TrueF else FalseF
-eval s (NextF f) = f
-eval s (UntilF f1 f2) = eval s f2 ||| (eval s f1 &&& UntilF f1 f2)
-
-// Concrete conditions
-
-data V = V String (Ref Boolean)
-
-instance Ord V where
- compare (V a _) (V b _) = compare a b
-instance Show V where
- sb <+ V a _ = sb <+ a
-
-cond :: String -> Ref Boolean -> Formula V
-cond name ref = ConditionF (V name ref)
-
-// Testing
-
-x = ref True
-y = ref False
-
-f = cond "x" x `UntilF` cond "y" y
-
-evalV = eval (\(V _ c) -> getRef c)
-
-main = do
- print (evalV f)
- x := False
- print (evalV f)
- y = ref True
- print (evalV f)
- x := True
- print (evalV f)
---
-()
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = (fromDynamic (toDynamic 42) :: String) + "foo"\r
---\r
-42foo
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = (fromDynamic (toDynamic "42") :: Integer) - 2\r
---\r
-40
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = arrayToList (fromDynamic (toDynamic ["42"]) :: (Array Integer))\r
---\r
-[42]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-import "Vector"\r
-\r
-main = (fromDynamic (toDynamic ["42"]) :: (Vector Double))!0\r
---\r
-42.0
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-import "Vector"\r
-\r
-main = (fromDynamic (toDynamic (mvector [42.0]))) :: [Integer]\r
---\r
-[42]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-// vvvvvv mistake, parantheses missing\r
-instance Functor (->) a where\r
- map f g x = f (g x)\r
- \r
-main = "Not to be executed."\r
---\r
-4:1-5:24: Wrong number of parameters to type class Functor.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-class Container c a b | c -> a, c -> b where\r
- get :: c -> a -> b\r
-\r
-instance Container [a] Integer a where\r
- get = (!)\r
-\r
-main = get [1,2,3,4,5] 3\r
---\r
-4
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-class Mul a b c | a b -> c where\r
- mul :: a -> b -> c\r
-\r
-instance Mul Integer Integer Integer where\r
- mul = (*)\r
-\r
-main :: Integer\r
-main = mul (mul (1 :: Integer) (2 :: Integer)) (3 :: Integer)\r
---\r
-6
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-class Functor f where\r
- map :: (a -> b) -> f a -> f b\r
- \r
-data Foo a = Foo a\r
-\r
-instance Functor Foo where\r
- map f (Foo x) = Foo (f x)\r
- \r
-instance Functor Maybe where\r
- map f Nothing = Nothing\r
- map f (Just x) = Just (f x)\r
- \r
-data List a = Nil | Cons a (List a)\r
-\r
-instance Functor List where\r
- map f Nil = Nil\r
- map f (Cons h t) = Cons (f h) (map f t)\r
- \r
-main = map (map (Java.iadd 1)) (Cons Nothing (Cons (Just (1 :: Integer)) Nil))\r
---\r
-(Cons null (Cons 2 Nil))
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = sequence [[1,2], [3,4], [5,6]]\r
-/*\r
- x <- [1,2]\r
- y <- [3,4]\r
- z <- [5,6]\r
- return [x,y,z]\r
-*/ \r
---\r
-[[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-(+) = Java.iadd\r
-\r
-data Foo = Foo Integer\r
-\r
-escapeFoo (Foo x) = x\r
-\r
-id x = x\r
-\r
-main = id (3 :: Integer) + escapeFoo (id (Foo (4 :: Integer)))\r
---\r
-7
\ No newline at end of file
+++ /dev/null
-// Idea of this test is to ensure that generic type variables\r
-// and constraints are handled correctly with mutually recursive\r
-// functions\r
-\r
-import "Prelude"\r
-\r
-deepId count x = deepId2 count x\r
-deepId2 count x = if count <= 0 then x else deepId (count-1) x\r
-\r
-main = deepId 5 "FOO"\r
---\r
-FOO
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-
-global :: Ref Integer
-global = ref 0
-
-inc :: <Proc> ()
-inc = global := getRef global + 1
-
-main = do
- inc
- inc
- getRef global
---
-2
\ No newline at end of file
+++ /dev/null
-\r
-/**\r
- * Databoard\r
- */\r
-data Binding // Private\r
-class Serializable a where\r
- getBinding :: Binding\r
-\r
-/**\r
- * Reading graph\r
- */\r
-data Resource\r
-data ReadGraph // Private\r
-class ReadTransaction where\r
- getGraph :: ReadGraph\r
-\r
-resource :: ReadTransaction => String -> Resource\r
-(#) :: ReadTransaction => Resource -> Resource -> [Resource]\r
-valueOf :: ReadTransaction => Serializable a => Resource -> a\r
-\r
-/**\r
- * Writing graph\r
- */\r
-data WriteGraph // Private\r
-data Graph a = Graph (WriteGraph -> a)\r
-\r
-instance Monad Graph where\r
- return x = Graph (\_ -> x)\r
- Graph g >>= f = \wg -> f (g wg) wg\r
- map f (Graph g) = Graph (f . g)\r
-\r
-newResource :: Graph Resource\r
-newResource = Graph __WriteGraph_newResource\r
-newLiteral :: Serializable a => a -> Graph Resource\r
-newLiteral = Graph (\wg -> \r
- literal = __WriteGraph_newResource wg\r
- _ = __WriteGraph_claimValue wg literal a getBinding\r
- literal \r
-)\r
-statement :: Resource -> Resource -> Resource -> Graph ()\r
-statement s p o = Graph (\wg -> __WriteGraph_claim wg s p o)
\ No newline at end of file
+++ /dev/null
-tableIndex :: Double -> Double
-tableIndex x
- | True = x
- where
- f _ = x
-
-main = "Foo"
---
-Foo
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-fib :: Integer -> Integer\r
-fib x | x <= 2 = 1\r
- | True = fib (x-1) + fib (x-2)\r
-\r
-main = fib 13\r
---\r
-233
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-fib :: Integer -> Integer\r
-fib x = match x with\r
- v | v <= 2 -> 1\r
- | True -> fib (v-1) + fib (v-2)\r
-\r
-main = fib 13\r
---\r
-233
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 5 minus\r
-\r
-minus = Java.isub\r
-\r
-main = 5 `minus` 3 `minus` 2\r
---\r
-0
\ No newline at end of file
+++ /dev/null
-a = ¤\r
---\r
-1:5-1:6: Illegal character '¤'.\r
+++ /dev/null
-\r
-@JavaType "org.simantics.scl.compiler.elaboration.expressions.Expression"\r
-data Expression = \r
- @JavaType "org/simantics/scl/compiler/elaboration/expressions/EIntegerLiteral"\r
- @FieldNames [value]\r
- EIntegerLiteral String\r
- | @JavaType "org.simantics.scl.compiler.elaboration.expressions.ERealLiteral"\r
- @FieldNames [value]\r
- ERealLiteral String\r
-\r
-changeType :: Expression -> Expression\r
-changeType (EIntegerLiteral value) = ERealLiteral value\r
-changeType (ERealLiteral value) = EIntegerLiteral value\r
-\r
-main :: Expression\r
-main = changeType (EIntegerLiteral "123") \r
---\r
-123
\ No newline at end of file
+++ /dev/null
-importJava "org.simantics.scl.runtime.procedure.Ref" where\r
- data Ref a\r
- \r
- @JavaName "<init>"\r
- ref :: a -> <Proc> (Ref a)\r
- \r
- @JavaName "value"\r
- getRef :: Ref a -> <Proc> a\r
- \r
- @JavaName "<set>value"\r
- (:=) :: Ref a -> a -> <Proc> ()\r
-\r
-main = do\r
- r = ref (13 :: Integer)\r
- r := (14 :: Integer)\r
- getRef r\r
---\r
-14
\ No newline at end of file
+++ /dev/null
-f a b = a\r
-f x = x\r
---\r
-2:1-2:4: Inconsistent arity. This case has arity 1 while previous cases had arity 2.
\ No newline at end of file
+++ /dev/null
-class Foo a where\r
- x :: a\r
- y :: a\r
---\r
-3:3-3:4: Unexpected token 'y' (ID). Expected one of EOF, RBRACE, SEMICOLON.
\ No newline at end of file
+++ /dev/null
-// The last character of the program is an extra closing parenthesis\r
-data List a = Nil | Cons a (List a)\r
-\r
-first Nil = 0\r
-first (Cons x _) = x\r
-\r
-reverse l = reverseAux Nil l \r
- where\r
- reverseAux accum Nil = accum\r
- reverseAux accum (Cons h t) = reverseAux (Cons h accum) t \r
-\r
-main = first (reverse l) \r
- where\r
- l = Cons 1 (Cons 2 (Cons 3 Nil)))\r
---\r
-14:37-14:38: No corresponding opening parenthesis for ')'.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-f :: Integer -> Maybe Integer\r
-f = index [(1,2),(2,4),(3,6),(4,8)]\r
-\r
-main = f 3\r
---\r
-6
\ No newline at end of file
+++ /dev/null
-main = id "Foo" \r
- where\r
- id x = x\r
---\r
-Foo
\ No newline at end of file
+++ /dev/null
-data SList a = Nil | Cons a (SList a)
-
-@inline
-copy (Cons h t) = Cons h (copy t)
-copy l = l
-
-main = "OK"
---
-OK
\ No newline at end of file
+++ /dev/null
-import "Prelude" hiding (zero, one)\r
-\r
-class MyAdditive a where\r
- zero :: a\r
- \r
-class (MyAdditive a) => MyRing a where\r
- one :: a\r
-\r
-instance MyAdditive Integer where\r
- zero = 0\r
-\r
-instance MyRing Integer where\r
- one = 1\r
- \r
-data Poly a = Poly [a]\r
-\r
-instance (MyAdditive a) => MyAdditive (Poly a) where\r
- zero = Poly []\r
-\r
-instance (MyRing a) => MyRing (Poly a) where\r
- one = Poly [one]\r
- \r
-main :: Poly Integer\r
-main = one\r
---\r
-[1]
\ No newline at end of file
+++ /dev/null
-class Functor f where\r
- map :: (a -> b) -> f a -> f b\r
- \r
-data Foo a = Foo a\r
-\r
-class Functor Foo where\r
- map f (Foo x) = Foo (f x)\r
---\r
-6:1-7:30: Class Functor has already been defined in this module.
\ No newline at end of file
+++ /dev/null
-class Foo a b where\r
- foo :: a -> b\r
-\r
-instance Foo a a where\r
- foo x = x :: a\r
-\r
-main = "OK"\r
---\r
-OK\r
-\r
+++ /dev/null
-class Foo a where\r
- infix 3 (+)\r
---\r
-2:5-2:16: Invalid declaration under class definition.
\ No newline at end of file
+++ /dev/null
-main = "Hello w�rld!"\r
---\r
-1:16-1:17: Character does not conform to UTF-8 encoding.
\ No newline at end of file
+++ /dev/null
-class Foo a where\r
- (+) :: a -> a -> a\r
-\r
-instance Foo Double where\r
- infix 3 (+)\r
- x + y = x\r
---\r
-5:5-5:16: Invalid declaration under instance definition.
\ No newline at end of file
+++ /dev/null
-@JavaType 123 "sdf"\r
-data Foo\r
-\r
-main = "Not to be executed"\r
---\r
-1:1-1:20: Invalid parameters. Expected @JavaType "className".
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-foo :: List\r
-foo = foo\r
---\r
-4:8-4:12: Expected a type with kind * but got * -> *.
\ No newline at end of file
+++ /dev/null
-class Functor f where\r
- map :: (a -> b) -> f a -> f b\r
- \r
-instance Functor Integer where\r
- map = fail "Not implemented."\r
-\r
-main = "Not to be executed."\r
---\r
-4:18-4:25: Expected a type with kind * -> * but got *.
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a List\r
-\r
---\r
-2:28-2:32: Expected a type with kind * but got ?a -> *.
\ No newline at end of file
+++ /dev/null
-
-main = \ /* no parameters */ -> 3
---
-2:30-2:32: Unexpected token '->' (ARROW). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LBRACKET, LET, LPAREN, MATCH, MDO, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION, WHEN.
+++ /dev/null
-import "INVALID_MODULE" as Foo
---
-1:1-1:31: Failed to import INVALID_MODULE, because it does not exist.
\ No newline at end of file
+++ /dev/null
-id x = x\r
-\r
-f (\x -> x) y = y\r
-\r
-main = f id "Foo"\r
---\r
-3:3-3:12: Pattern was expected here.
\ No newline at end of file
+++ /dev/null
-if x then y else z = x\r
-\r
-main = "Not to be executed."\r
---\r
-1:1-1:19: Illegal left hand side of the definition.
\ No newline at end of file
+++ /dev/null
-foo x = b\r
- where\r
- if a then b else c = x\r
-\r
-main = "Not to be executed."\r
---\r
-1:9-1:10: Couldn't resolve variable b.\r
-3:5-3:23: Pattern was expected here.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a # b # c = a + b + c\r
-\r
-main = "Not to be executed."\r
---\r
-3:1-3:10: Illegal left hand side of the definition.
\ No newline at end of file
+++ /dev/null
-data Fact = Foo | Bar\r
-\r
-rs = ruleset\r
- Foo => Bar\r
-\r
-main = "Not to be executed."\r
---\r
-4:10-4:13: Expected\r
- <[Fact]> got\r
- <Fact>.
\ No newline at end of file
+++ /dev/null
-data Fact = Foo1 | Foo2\r
-data Fact2 = Bar\r
-\r
-rs = ruleset\r
- Foo1, Foo2 <=> [Bar]\r
-\r
-main = "Not to be executed."\r
---\r
-5:19-5:22: Expected\r
- <Fact> got\r
- <Fact2>.
\ No newline at end of file
+++ /dev/null
-\r
-class Foo a where\r
- foo :: a -> Integer\r
- \r
-instance Foo Long where\r
- foo x = x\r
- \r
---\r
-6:13-6:14: Expected <Integer> got <Long>.
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-importJava "java.lang.String" where\r
- substring :: String -> Integer -> Integer -> String\r
-\r
-main = substring "01234" 1 4\r
---\r
-123
\ No newline at end of file
+++ /dev/null
-\r
-@JavaType "org.simantics.scl.runtime.tuple.Tuple3"\r
-data Tuple3 a b c =\r
- @FieldNames [c0, c1, c2] \r
- Tuple3 a b c\r
- \r
-toTuple (Tuple3 x y z) = (x, y, z)\r
-\r
-main = toTuple (Tuple3 "x" "y" "z")\r
---\r
-(x,y,z)
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-importJava "java.lang.Integer" where\r
- @JavaName "parseInt"\r
- stringToInteger :: String -> Integer\r
-\r
-main = stringToInteger "13"\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-importJava "java.math.BigInteger" where\r
- data BigInteger\r
- \r
- @JavaName "add"\r
- (+) :: BigInteger -> BigInteger -> BigInteger\r
-\r
- @JavaName "<init>"\r
- fromString :: String -> BigInteger\r
-\r
-main = fromString "123" + fromString "234"\r
---\r
-357
\ No newline at end of file
+++ /dev/null
-class Functor f where\r
- map :: (a -> b) -> f a -> f b\r
-\r
-data Either a b = Left a | Right b\r
-\r
-instance Functor (Either a) where\r
- map _ (Left x) = Left x\r
- map f (Right y) = Right (f y)\r
-\r
-id :: Integer -> Integer\r
-id x = x\r
-\r
-main = map id (Left (12 :: Integer))\r
---\r
-(Left 12)
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-importJava "gnu.trove.map.hash.TIntFloatHashMap" where\r
- data LMap\r
- \r
- @JavaName adjustOrPutValue\r
- adjustLMap_ :: LMap -> Integer -> Float -> Float -> <Proc> ()\r
- \r
-@inline\r
-adjustLMap :: LMap -> Integer -> Float -> <Proc> ()\r
-adjustLMap m k v = adjustLMap_ m k v v\r
-\r
-data LPTerm = LPTerm (LMap -> Float -> <Proc> ())\r
-\r
-instance Additive LPTerm where\r
- @inline\r
- zero = LPTerm (\_ _ -> ())\r
- @inline\r
- LPTerm a + LPTerm b = LPTerm (\m s -> do a m s ; b m s)\r
- sum ts = LPTerm (\m s -> for ts (\(LPTerm t) -> t m s))\r
-\r
-instance Ring LPTerm where\r
- @inline\r
- neg (LPTerm a) = LPTerm (\m s -> a m (-s))\r
- @inline\r
- LPTerm a - LPTerm b = LPTerm (\m s -> do a m s ; b m (-s))\r
- @inline\r
- fromInteger c = LPTerm (\m s -> adjustLMap m (-1) (fromInteger c*s))\r
- @inline\r
- one = LPTerm (\m s -> adjustLMap m (-1) s)\r
- _ * _ = fail "Multiplication is not supported."\r
-\r
-data LPProblem = LPProblem (Ref Integer)\r
-\r
-newProblem :: () -> <Proc> LPProblem\r
-newProblem _ = LPProblem (ref 0)\r
-\r
-newVar :: LPProblem -> <Proc> LPTerm\r
-newVar (LPProblem varCounter) = do\r
- curId = getRef varCounter\r
- varCounter := curId + 1\r
- LPTerm (\m s -> adjustLMap m curId s)\r
-\r
-infixl 7 (**)\r
-\r
-@inline\r
-(**) :: Float -> LPTerm -> LPTerm\r
-s0 ** LPTerm t = LPTerm (\m s -> t m (s0*s))\r
-\r
-/*\r
-data LPTerm = LPTerm Double (Map.T String Double)\r
-\r
-instance Additive LPTerm where\r
- zero = LPTerm 0 Map.empty\r
- LPTerm c1 m1 + LPTerm c2 m2 = LPTerm (c1+c2) (Map.merge (+) m1 m2)\r
-\r
-instance Ring LPTerm where\r
- one = LPTerm 1 Map.empty\r
- neg (LPTerm c m) = LPTerm (-c) (map neg m)\r
- LPTerm c1 m1 - LPTerm c2 m2 = LPTerm (c1-c2) (Map.merge (-) m1 m2)\r
- \r
- LPTerm c1 [] * LPTerm c2 m2 = LPTerm (c1*c2) (Map.merge (\x -> c1*x) m2)\r
- LPTerm c1 m1 * LPTerm c2 [] = LPTerm (c1*c2) (Map.merge (\x -> c2*x) m1)\r
- _ * _ = fail "Invalid expression: not linear."\r
- \r
- fromInteger i = LPTerm (fromInteger i) Map.empty\r
-\r
-data LPConstraint = LPConstraint String LPTerm\r
-\r
-(>==) :: LPTerm -> LPTerm -> String -> [LPConstraint]\r
-(a >== b) name = [LPConstraint name (a-b)] \r
-\r
-(<==) :: LPTerm -> LPTerm -> String -> [LPConstraint]\r
-(a <== b) name = [LPConstraint name (b-a)]\r
-\r
-*/\r
-\r
-testi () = do\r
- problem = newProblem ()\r
- a = newVar problem\r
- b = newVar problem\r
- 3 ** a + 4 ** b + 15\r
-\r
-main = "OK"\r
---\r
-OK
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-map :: (a -> b) -> List a -> List b\r
-map f Nil = Nil\r
-map f (Cons h t) = Cons (f h) (map f t)\r
-\r
-constMap :: a -> List b -> List a\r
-constMap c = map (\x -> c)\r
-\r
-main = constMap (5 :: Integer) (Cons (1 :: Integer) (Cons (2 :: Integer) (Cons (3 :: Integer) Nil)))\r
---\r
-(Cons 5 (Cons 5 (Cons 5 Nil)))
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-
-foobar x = match x with
- Left lt -> foo lt
- Right rt -> bar rt
- where
- foo x = "left " + show x
- bar x = "right " + show x
-
-main = foobar (Left "ASD" :: Either String String)
---
-left "ASD"
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-main :: List Integer\r
-main = Cons (3 :: Integer) Nil\r
---\r
-(Cons 3 Nil)
\ No newline at end of file
+++ /dev/null
-a :: [Integer]\r
-a = a\r
-\r
-main :: [Double]\r
-main = [x | x <- a]\r
---\r
-5:9-5:10: Expected <Double> got <Integer>.
\ No newline at end of file
+++ /dev/null
-a :: Integer\r
-a = a\r
-\r
-main :: [Integer]\r
-main = [x | x <- a]\r
---\r
-5:18-5:19: Expected <[a]> got <Integer>.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a = [1,2]\r
-b = [5,9]\r
-main = [(x,y) | x <- a, y <- b]\r
---\r
-[(1,5), (1,9), (2,5), (2,9)]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-dists l = sum [sqrt (dx*dx + dy*dy) \r
- | i <- [0..length l-2]\r
- , (x1,y1) = l!i\r
- , (x2,y2) = l!(i+1)\r
- , dx = x1-x2\r
- , dy = y1-y2 ]\r
- \r
-main = dists [(0,0),(1,1),(2,0)]\r
--- \r
-2.8284271247461903
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-dists l = sum [sqrt (x*x+y*y) \r
- | (x,y) <- l ]\r
- \r
-main = dists [(0,0),(1,1),(2,0)]\r
--- \r
-3.414213562373095
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
- \r
-main = foldl (+) 0 [x | y <- [1..10], x <- [1..y]]\r
--- \r
-220
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a = [1,2]\r
-b = [5,9]\r
-main = [(x, y) | x <- a, x==2, y <- b]\r
---\r
-[(2,5), (2,9)]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = [1,2,3,4]\r
---\r
-[1, 2, 3, 4]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main :: [Integer]\r
-main = [y | x <- [1..3], y = x+4]\r
---\r
-[5, 6, 7]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a = [1,2,3,4]\r
-\r
-main :: [Integer]\r
-main = [x+y | x <- a, y <- a, x!=y]\r
---\r
-[3, 4, 5, 3, 5, 6, 4, 5, 7, 5, 6, 7]\r
+++ /dev/null
-import "Prelude"\r
-\r
-main :: [Integer]\r
-main = [x | x <- [1..10], then take 3]\r
---\r
-[1, 2, 3]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main :: [Integer]\r
-main = [x | x <- [2,4,3,5,4,6], then sortBy by x]\r
---\r
-[2, 3, 4, 4, 5, 6]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a :: [Either Integer Integer]\r
-a = [Left 1, Right 2, Left 3, Right 4]\r
-\r
-lefts :: [Either a b] -> [a]\r
-lefts l = [x | Left x <- l] \r
-\r
-main :: [Integer]\r
-main = lefts a\r
---\r
-[1, 3]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a :: [Either Integer Integer]\r
-a = [Left 1, Right 2, Left 3, Right 4]\r
-\r
-lefts :: [Either a b] -> [a]\r
-lefts l = [x | y <- l, Left x = y] \r
-\r
-main :: [Integer]\r
-main = lefts a\r
---\r
-[1, 3]
\ No newline at end of file
+++ /dev/null
-main = [1 :: Integer,2 :: Integer,3 :: Integer]\r
---\r
-[1, 2, 3]
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-reverse :: List a -> List a\r
-reverse l = do \r
- reverseAux accum Nil = accum\r
- reverseAux accum (Cons h t) = reverseAux (Cons h accum) t\r
- reverseAux Nil l\r
- \r
-main = reverse (Cons (1 :: Integer) (Cons (2 :: Integer) (Cons (3 :: Integer) (Cons (4 :: Integer) Nil))))\r
---\r
-(Cons 4 (Cons 3 (Cons 2 (Cons 1 Nil))))
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-hasEvenLength :: List a -> Boolean\r
-hasEvenLength l = do \r
- even Nil = True\r
- even (Cons _ t) = odd t\r
- odd Nil = False\r
- odd (Cons _ t) = even t\r
- even l\r
-\r
-main = hasEvenLength (Cons (1 :: Integer) (Cons (2 :: Integer) (Cons (3 :: Integer) (Cons (4 :: Integer) Nil))))\r
---\r
-true
\ No newline at end of file
+++ /dev/null
-\r
-data Step s = Skip s\r
-\r
-next :: (s -> Step s) -> s -> Step s \r
-next next0 ss = match next0 ss with \r
- Skip ss -> Skip ss\r
- \r
-main = next (\x -> Skip x) (3 :: Integer)\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-\r
-first p = x\r
- where \r
- (x,y) = p\r
- \r
-main = first (3 :: Integer,4 :: Integer)\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-data Foo = Foo Double Double\r
-\r
-a = Foo 1 2\r
-\r
-b = y\r
- where\r
- Foo x y = a\r
- \r
-main = show b\r
---\r
-2.0
\ No newline at end of file
+++ /dev/null
-@macro\r
-(||) :: Boolean -> Boolean -> Boolean \r
-a || b = if a then True else b\r
-\r
-main :: Boolean\r
-main = True || (fail "This should not be executed")\r
---\r
-true
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-(==) = Java.icmpeq\r
-\r
-@macro\r
-(&<&) :: Integer -> Integer -> Integer\r
-a &<& b = if cmp == 0 then b else cmp\r
- where \r
- cmp = a\r
-\r
-main = 3 &<& 7\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-@JavaType "java.util.Collection"\r
-data Collection a\r
-\r
-@macro\r
-collectionToList :: Collection a -> [a]\r
-collectionToList = Java.unsafeCoerce\r
-\r
-singleton :: a -> Collection a\r
-singleton = Java.staticMethod "java.util.Collections.singletonList"\r
-\r
-main :: [Integer]\r
-main = collectionToList (singleton 15)\r
---\r
-[15]
\ No newline at end of file
+++ /dev/null
-@macro\r
-@inline\r
-($) :: (a -> <e> b) -> a -> <e> b\r
-f $ x = f x\r
-\r
-justExecute :: (() -> a) -> a\r
-justExecute f = f ()\r
-\r
-main :: Integer\r
-main = justExecute $ \() -> (13 :: Integer)\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-data List a = Nil | Cons a (List a)\r
-\r
-map f Nil = Nil\r
-map f (Cons h t) = Cons (f h) (map f t)\r
-\r
-map2 f l = run l\r
- where\r
- run Nil = Nil\r
- run (Cons h t) = Cons (f h) (run t)\r
-\r
-map3 f l = run l\r
- where\r
- run Nil = Nil\r
- run (Cons h t) = Cons (f h) (map f t)\r
- \r
-main = "Foo"\r
---\r
-Foo
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-l :: [Integer]\r
-l = [2,3]\r
-\r
-f :: Integer -> <Proc> [Integer]\r
-f n = [n] + [0 | i <- l]\r
- \r
-main = f 1\r
---\r
-[1, 0, 0]
\ No newline at end of file
+++ /dev/null
-import "IterN"\r
-import "Random"\r
-\r
-foo :: Integer -> <Proc> Double\r
-foo n = runRandom $ foldlN addRandom 0.0 n\r
-\r
-addRandom :: Double -> Integer -> <Random,Proc> Double\r
-addRandom v i = v + randomDouble\r
-\r
-main = "Foo"\r
---\r
-Foo
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-first :: List Integer -> Integer\r
-//first Nil = 0 :: Integer\r
-first (Cons x _) = x\r
-\r
-reverse :: List a -> List a\r
-reverse l = reverseAux Nil l \r
- where\r
- reverseAux accum Nil = accum\r
- reverseAux accum (Cons h t) = reverseAux (Cons h accum) t \r
-\r
-main :: Integer\r
-main = first (reverse l) \r
- where\r
- l = Cons (1 :: Integer) (Cons (2 :: Integer) (Cons (3 :: Integer) Nil))\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-\r
-main = match (5 :: Integer) with\r
- (1 :: Integer) -> "wrong"\r
- (2 :: Integer) -> "wrong"\r
- (5 :: Integer) -> "right"\r
- (6 :: Integer) -> "wrong"\r
- _ -> "wrong"\r
---\r
-right
\ No newline at end of file
+++ /dev/null
-\r
-a = 5 :: Long\r
-main = match a with\r
- 1 -> "wrong"\r
- 2 -> "wrong"\r
- 5 -> "right"\r
- 6 -> "wrong"\r
- _ -> "wrong"\r
---\r
-right
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-foo 1 = "one"
-foo 2 = "two"
-
-main = if True then foo (2 :: Long) else foo (1 :: Integer)
---
-two
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-dummySum [] = 0\r
-dummySum [a] = a\r
-dummySum [a,b] = a + b\r
-dummySum [a,b,c] = a + b + c\r
-dummySum l = sum l\r
-\r
-main = dummySum [] + dummySum [1] + dummySum [1,2] + dummySum [1,2,3]\r
---\r
-10
\ No newline at end of file
+++ /dev/null
-main = do \r
- match () with\r
- () -> "Hello"\r
---\r
-Hello
\ No newline at end of file
+++ /dev/null
-data Foo = Foo Integer Integer
- | Bar
-
-isFoo (Foo _) = True
-isFoo _ = False
-
-main = "Hello world!"
---
-4:7-4:14: The function is applied with too few parameters.
-
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-//first :: List Integer -> Integer\r
-first Nil = 0 :: Integer\r
-first (Cons x _) = x\r
-\r
-main = first (Cons (9 :: Integer) (Cons (8 :: Integer) Nil))\r
---\r
-9
\ No newline at end of file
+++ /dev/null
-import "Prelude" hiding (maximumBy)\r
-\r
-maximumBy :: Ord b => (a -> b) -> [a] -> a\r
-maximumBy f = snd . foldl1 maxF . map (\x -> (f x, x))\r
- where\r
- maxF (a @ (aV,_)) (b @ (bV,_)) = if aV >= bV then a else b\r
- \r
-main = maximumBy (`mod` 10) [1::Integer, 14, 23, 9, 14, 67] \r
---\r
-9
\ No newline at end of file
+++ /dev/null
-a = Nothing\r
-main = match a with\r
- Nothing -> "Correct"\r
- Just x -> "Incorrect"\r
---\r
-Correct
\ No newline at end of file
+++ /dev/null
-a = Just True\r
-main = match a with\r
- Nothing -> False\r
- Just x -> x\r
---\r
-true
\ No newline at end of file
+++ /dev/null
-a = Just "ABC"\r
-main = match a with\r
- Nothing -> "Incorrect"\r
- Just x -> x\r
---\r
-ABC
\ No newline at end of file
+++ /dev/null
-import "Prelude" hiding (fromMaybe)\r
-import "Random"\r
-\r
-importJava "org.simantics.scl.compiler.tests.imports.Maybe4Imports" where\r
- toMaybeDouble :: String -> <Random> Maybe a\r
-\r
-fromMaybe :: a -> Maybe a -> a\r
-fromMaybe _ (Just v) = v\r
-fromMaybe def _ = def\r
-\r
-f x = do\r
- a = fromMaybe (-1.0) (toMaybeDouble x)\r
- b = fromMaybe (-1.0) (toMaybeDouble ("1" + x))\r
- a+b\r
-\r
-main = withSeed 123 (f "2.0")\r
---\r
-14.0
\ No newline at end of file
+++ /dev/null
-import "Prelude" hiding (findFirst)\r
-\r
-findFirst :: (a -> <e> Maybe b) -> [a] -> Maybe b\r
-findFirst f l = loop 0\r
- where\r
- len = length l\r
- loop i \r
- | i >= len = Nothing\r
- | otherwise = match f (l!i) with\r
- s @ (Just _) -> s\r
- Nothing -> loop (i+1)\r
-\r
-main = "Not to be executed"\r
---\r
-9:29-9:36: Side-effect a is forbidden here.
\ No newline at end of file
+++ /dev/null
-class FooBar a where\r
- foo :: a -> a\r
- bar :: a -> a\r
- \r
-instance FooBar Integer where\r
- foo x = x\r
-\r
-main = "Not to be executed."\r
---\r
-5:1-6:14: Method bar is not defined.\r
- \r
-\r
+++ /dev/null
-importJava "java.util.Arrays" where\r
- toString :: MVector /*Double*/ -> String\r
-\r
-main = "Not to be executed."\r
---\r
-???
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-d = map (+1) c\r
-a = [1,2,3]\r
-c = map (+1) b\r
-b = map (+1) a\r
-e = map (+1) d\r
-\r
-main = e\r
---\r
-[5, 6, 7]
\ No newline at end of file
+++ /dev/null
-class Monad m where\r
- (>>=) :: m a -> (a -> m b) -> m b\r
-\r
-@macro\r
-(>>) :: Monad m => m a -> m b -> m b\r
-ma >> mb = ma >>= (\_ -> mb)\r
-\r
-main = "OK"\r
---\r
-OK
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a = [1, 2]\r
-b = [5, 6]\r
-\r
-main = mdo \r
- x <- a\r
- y <- b\r
- return (x+y) \r
---\r
-[6, 7, 7, 8]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a = [1, 2]\r
-b = [5, 6]\r
-\r
-main = do \r
- x <- a\r
- y <- b\r
- return (x+y) \r
---\r
-7:3-7:9: Bind statements are allowed only in mdo-blocks.\r
-8:3-8:9: Bind statements are allowed only in mdo-blocks.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-a = [1, 2]\r
-b = [5, 6]\r
-\r
-main = a >>= \x -> b >>= \y -> return (x+y) \r
---\r
-[6, 7, 7, 8]
\ No newline at end of file
+++ /dev/null
-// Idea of this test is that the missing definition should only cause\r
-// one error message pointing to the type declaration.\r
-a :: Double\r
-b :: Double\r
-b = a\r
---\r
-3:1-3:12: a is not defined.
\ No newline at end of file
+++ /dev/null
-\r
-class Foo a where\r
- foo :: a\r
-\r
-x :: Double\r
-x = foo\r
-\r
---\r
-6:5-6:8: Constraint <Foo Double> is not given and cannot be derived.
\ No newline at end of file
+++ /dev/null
-\r
-class Foo a where\r
- foo :: a\r
-\r
-y :: Double\r
-y = y\r
- \r
-x = if True then foo else y\r
---\r
-8:18-8:21: There is no instance for <Foo Double>.
\ No newline at end of file
+++ /dev/null
-infix 3 (+)\r
-\r
-a + b = a\r
-\r
-threeTimes x = x + x + x\r
---\r
-5:22-5:23: Operator + is not associative.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-deepId :: FooBar b => b -> a -> a\r
-deepId count x = deepId2 count x\r
-deepId2 count x = if count <= 0 then x else deepId (count-1) x\r
-\r
-main = deepId (5 :: Integer) "FOO"\r
---\r
-3:11-3:17: Unresolved type class FooBar.
\ No newline at end of file
+++ /dev/null
-importJava "java.lang.System" where\r
- nanoTime :: () -> <Pred> Long\r
-\r
-main = nanoTime ()\r
---\r
-2:24-2:28: Didn't find effect constructor Pred.
\ No newline at end of file
+++ /dev/null
-// Tests that match cases can be given in the same line as the scrutinee\r
-data FooBar a = Foo a | Bar a\r
-extract x = match x with Foo v -> v ; Bar v -> v\r
-main = extract (Foo (3 :: Integer))\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-"asd \r
---\r
-1:1-1:6: Unclosed string literal.
\ No newline at end of file
+++ /dev/null
-"asd \r
-\r
-\r
-asd\r
---\r
-1:1-1:6: Unclosed string literal.
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 6 (+)\r
-\r
-class Additive a where \r
- (+) :: a -> a -> a \r
- \r
-instance Additive Double where\r
- x + y = Java.dadd x y\r
-\r
-instance Additive Integer where\r
- x + y = Java.iadd x y\r
- \r
-main = ((1.0 :: Double)+(2.0 :: Double),(3::Integer)+(4::Integer))\r
---\r
-(3.0,7)\r
-\r
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 6 (+)\r
-\r
-class Additive a where \r
- (+) :: a -> a -> a \r
- \r
-instance Additive Double where\r
- x + y = Java.dadd x y\r
-\r
-instance Additive Integer where\r
- x + y = Java.iadd x y\r
- \r
-instance (Additive a, Additive b) => Additive (a,b) where\r
- (x1,y1) + (x2,y2) = (x1+x2,y1+y2)\r
- \r
-main = (1.0::Double,3::Integer) + (2.0::Double,4::Integer)\r
---\r
-(3.0,7)\r
-\r
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 7 (*)\r
-infixl 6 (+)\r
-\r
-class Additive a where \r
- (+) :: a -> a -> a \r
-\r
-class (Additive a) => Ring a where\r
- (*) :: a -> a -> a\r
-\r
-instance Additive Double where\r
- x + y = Java.dadd x y\r
-\r
-instance Ring Double where\r
- x * y = Java.dmul x y\r
-\r
-instance Additive Integer where\r
- x + y = Java.iadd x y\r
-\r
-instance Ring Integer where\r
- x * y = Java.imul x y\r
-\r
-main = (1.0 :: Double)*(2.0 :: Double)+(3.0 :: Double)*(4.0 :: Double)\r
---\r
-14.0\r
-\r
+++ /dev/null
-import "Prelude"\r
-\r
-inc :: Ring a => a -> a\r
-inc x = x + 1\r
-\r
-main :: Double\r
-main = inc 34\r
---\r
-35.0
\ No newline at end of file
+++ /dev/null
-// module Foo1
-import "Prelude"
-
-foo :: Integer -> Boolean
-foo i = i == 5
---
-// module Foo2
-import "Prelude"
-
-foo :: Integer -> Integer -> Boolean
-foo i j = i == j
---
-import "Prelude"
-import "Foo1"
-import "Foo2"
-
-main = foo 5 && foo 5 4
---
-false
\ No newline at end of file
+++ /dev/null
-// module Max1
-import "Prelude"
-
-myMax :: Ord a => a -> a -> a
-myMax = max
---
-// module Max2
-import "Prelude"
-
-myMax :: Ord a => a -> a -> a -> a
-myMax a b c = max a (max b c)
---
-import "Prelude"
-import "Max1"
-import "Max2"
-
-main = myMax (1 :: Integer) 2 3 + myMax (3 :: Integer) 2 1 + myMax 4 2 :: Integer
---
-10
-
+++ /dev/null
-// module M1
-import "Prelude"
-
-foo :: Ring a => Boolean -> a -> a
-foo True v = v+1
-foo False v = v+1
---
-// module M2
-import "Prelude"
-
-foo :: Ring a => String -> a -> a
-foo cond v = if cond=="true"
- then v+1
- else v-1
---
-import "Prelude"
-import "M1"
-import "M2"
-
-main = foo False (foo "True" 10) :: Integer
---
-10
-
+++ /dev/null
-import "Prelude"\r
-\r
-"""\r
-Parser is a function from a string and a position in the\r
-string to a possible semantics of a substring and the \r
-end of the substring.\r
-"""\r
-data Parser a = Parser (String -> Integer -> Maybe (a, Integer))\r
-\r
-runParser :: Parser a -> String -> Integer -> Maybe (a, Integer)\r
-runParser (Parser f) = f \r
-\r
-instance Functor Parser where\r
- fmap f (Parser p) = Parser (\input pos -> match p input pos with\r
- Nothing -> Nothing\r
- Just (a, newPos) -> Just (f a, newPos)\r
- )\r
-\r
-instance Monad Parser where\r
- return x = Parser (\_ pos -> Just (x, pos)) \r
- (pa >>= f) = Parser (\input pos -> match runParser pa input pos with\r
- Nothing -> Nothing\r
- Just (a, newPos) -> runParser (f a) input newPos\r
- ) \r
-\r
-(|||) :: Parser a -> Parser a -> Parser a\r
-Parser a ||| Parser b = Parser (\input pos -> match a input pos with\r
- Nothing -> b input pos\r
- Just x -> Just x\r
-) \r
-\r
-keyword :: String -> Parser ()\r
-keyword word = Parser (\input pos ->\r
- if regionMatches word 0 input pos (length word)\r
- then Just ((), pos + (length word))\r
- else Nothing\r
-)\r
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-listSepL :: Parser () -> Parser a -> Parser (List a)\r
-listSepL sep el = mdo\r
- head <- el\r
- tail <- (sep >> listSepL sep el) ||| return Nil\r
- return (Cons head tail) \r
-\r
-fromList :: List a -> [a]\r
-fromList = unfoldr gen\r
- where\r
- gen Nil = Nothing\r
- gen (Cons h t) = Just (h, t)\r
- \r
-listSep :: Parser () -> Parser a -> Parser [a] \r
-listSep sep el = fmap fromList (listSepL sep el) \r
-\r
-aOrB = (keyword "a" >> return "a") ||| (keyword "b" >> return "b")\r
-\r
-myParser = listSep (keyword ",") aOrB\r
-\r
-main = show (runParser myParser "a,b,b,a" 0)\r
---\r
-Just (["a", "b", "b", "a"], 7)
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-data CP = CP Integer String\r
-\r
-//cpName :: CP -> String\r
-cpName CP cp name = name\r
-\r
-connectionPoints :: Integer -> [(CP, CP)]\r
-connectionPoints n = []\r
-\r
-hasTerminalProblems :: Integer -> Boolean\r
-hasTerminalProblems uc =\r
- let cps = connectionPoints uc\r
- cpCount = length cps\r
- dcps = map snd cps\r
- dnames = map cpName dcps\r
- dcpNameCount = length $ unique $ sort dnames\r
- in cpCount != dcpNameCount\r
-\r
-main = "Not OK"\r
---\r
-6:8-6:10: ???
\ No newline at end of file
+++ /dev/null
-// Idea here is to test the following property:\r
-// When a function is called recursively it has locally a monomorphic type.\r
-// Therefore the definition of cons does not work even if it works\r
-// with a proper type annotation.\r
-\r
-data Vec a = Nil | Zero (Vec (a,a)) | One a (Vec (a,a))\r
-\r
-// cons :: a -> Vec a -> Vec a\r
-cons x Nil = One x Nil\r
-cons x (Zero ps) = One x ps\r
-cons x (One y ps) = Zero (cons (x, y) ps)\r
---\r
-11:21-11:42: Expected <Vec (a, a)> got <Vec a>.\r
-11:33-11:34: Type (a, a) is not a subtype of a.\r
-11:36-11:37: Type (a, a) is not a subtype of a.\r
-11:39-11:41: Expected <Vec a> got <Vec (a, a)>.
\ No newline at end of file
+++ /dev/null
-\r
-\r
-class Foo a where\r
- foo :: a\r
- \r
-data List a = Nil | Cons a (List a)\r
-\r
-r x = Cons foo (r x)\r
-\r
-main = (1.0 :: Double)\r
---\r
-1.0
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-data Poly a = Poly [a]\r
-\r
-normalize l = go (length l)\r
- where\r
- go i = if i > 0 && l!(i-1)==zero\r
- then go (i-1)\r
- else take i l \r
-\r
-instance (Eq a, Additive a) => Additive (Poly a) where\r
- zero = Poly []\r
- Poly a + Poly b = \r
- Poly ( \r
- normalize (\r
- zipWith (+) a b + \r
- if la > lb\r
- then drop lb a\r
- else drop la b\r
- )\r
- )\r
- where\r
- la = length a\r
- lb = length b \r
-\r
-instance (Eq a, Ring a) => Ring (Poly a) where\r
- one = Poly [one]\r
- neg (Poly l) = Poly (map neg l)\r
- a - b = a + (neg b)\r
- Poly a * Poly b = \r
- Poly ( if aDeg < bDeg\r
- then [ segSum n 0 n | n <- [0 ..aDeg] ]\r
- + [ segSum n 0 aDeg | n <- [aDeg+1..bDeg] ]\r
- + [ segSum n (n-bDeg) aDeg | n <- [bDeg+1..sumDeg] ]\r
- else [ segSum n 0 n | n <- [0 ..bDeg] ]\r
- + [ segSum n (n-bDeg) n | n <- [bDeg+1..aDeg] ]\r
- + [ segSum n (n-bDeg) aDeg | n <- [aDeg+1..sumDeg] ]\r
- )\r
- where \r
- aDeg = length a - 1\r
- bDeg = length b - 1\r
- sumDeg = aDeg + bDeg\r
- segSum n low high = sum [ a!i * b!(n-i) | i <- [low..high] ]\r
- fromInteger x = Poly [fromInteger x]\r
- \r
-a = Poly [4.0,5.0,8.0,3.0,2.0,1.0]\r
-b = Poly [1.0,0.0,2.0,1.0]\r
-main = a * a + a * b + b * a + b * b - (a+b)*(a+b)\r
---\r
-[]
\ No newline at end of file
+++ /dev/null
-infixr 2 l\r
-infixr 1 r\r
-\r
-l a b = a\r
-r a b = b\r
-\r
-main = (1 :: Integer) `l` (2 :: Integer) `r` (3 :: Integer) `l` (4 :: Integer)\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 7 (%)\r
-infixl 6 (+)\r
-infix 4 (==), (<)\r
-\r
-(+) = Java.iadd\r
-(%) = Java.irem\r
-(<) = Java.icmplt\r
-(==) = Java.icmpeq\r
-\r
-isPrime p = isPrimeAux (2 :: Integer) p\r
- where\r
- isPrimeAux d p = if d == p then True\r
- else if p % d == 0 then False\r
- else isPrimeAux (d+1) p\r
- \r
-nextPrime p = if isPrime p \r
- then p\r
- else nextPrime (p+(1 :: Integer)) \r
- \r
-main = nextPrime 32\r
---\r
-37
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
- \r
-main = do\r
- r = ref 13\r
- r := 14\r
- getRef r\r
---\r
-14
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-data RealWorld = RealWorld\r
-data IO a = IO (RealWorld -> (RealWorld, a))\r
-\r
-@inline\r
-unIO (IO m) = m \r
-\r
-instance Functor IO where\r
- @inline\r
- fmap f x = x >>= (return . f)\r
-\r
-instance Monad IO where\r
- @inline\r
- return x = IO (\s -> (s, x))\r
- \r
- @inline\r
- (IO m) >>= f = IO (\s -> do\r
- (newS, v) = m s\r
- unIO (f v) newS \r
- )\r
-\r
-@inline\r
-runIO :: IO a -> a\r
-runIO m = snd (unIO m RealWorld)\r
-\r
-main = runIO (return (13 :: Integer))\r
---\r
-13\r
+++ /dev/null
-import "Prelude"\r
-\r
-@private\r
-repeat :: Integer -> (() -> <e> a) -> <e> ()\r
-repeat n proc = \r
- if n > 0 then do\r
- proc ()\r
- repeat (n-1) proc\r
- else () \r
-\r
-main = do\r
- a = ref 1 \r
- repeat 3 (\() -> a := 2)\r
- getRef a\r
---\r
-2
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 7 (*)\r
-infixl 6 (+)\r
-\r
-(+) :: Double -> Double -> Double\r
-(+) = Java.dadd\r
-(*) :: Double -> Double -> Double\r
-(*) = Java.dmul\r
-\r
-importJava "java.lang.Math" where\r
- sqrt :: Double -> Double\r
- sin :: Double -> Double\r
- cos :: Double -> Double\r
-\r
-square x = x * x\r
-\r
-length x y = sqrt (square x + square y)\r
-\r
-pythagoras a = length (cos a) (sin a)\r
-\r
-main = pythagoras 2.0\r
---\r
-1.0\r
+++ /dev/null
-import "StandardLibrary"\r
-\r
-// Actual program\r
-\r
-"""This function returns either 0 or 1 such that\r
-the expected value is pi/4"""\r
-approximatePi :: () -> <Random> Double\r
-approximatePi () = if x*x + y*y < 1 then 1 else 0\r
- where\r
- x = randomDouble\r
- y = randomDouble\r
-\r
-averageOfNRepeats n f = sum [f () | n <- [1..n]] / fromInteger n\r
-\r
-betterApproximatePi () = averageOfNRepeats 1000 approximatePi * 4\r
-\r
-main = withSeed 13 (betterApproximatePi ())\r
---\r
-3.068
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = [5..9]\r
---\r
-[5, 6, 7, 8, 9]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-data XYS = XYS { x :: Double, y :: Double, s :: String }\r
-\r
-len XYS {x = x, y = y} = sqrt (x*x + y*y)\r
-\r
-main = len (XYS { x = 4, y = 3, s = "Hello world!" })\r
--- \r
-5.0
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-
-data Vec = Vec { x :: Double, y :: Double }
-deriving instance Show Vec
-
-createVec x y = Vec {x, y}
-sumVec Vec { x1, y1 } Vec { x2, y2 } = Vec { x = x1+x2, y = y1 + y2 }
-
-main = sumVec (createVec 1 2) (createVec 3 4)
---
-(Vec 4.0 6.0)
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-infixl 6 (+), (-)\r
-\r
-class Num a where \r
- (+) :: a -> a -> a\r
- (-) :: a -> a -> a\r
- isZero :: a -> Boolean\r
- one :: a \r
- \r
-instance Num Integer where\r
- x + y = Java.iadd x y\r
- x - y = Java.isub x y\r
- isZero x = Java.icmpeq Java.iconst_0 x\r
- one = Java.iconst_1\r
- \r
-even x = if isZero x then True else odd (x - one)\r
-odd x = if isZero x then False else even (x - one) \r
- \r
-main = odd (8 :: Integer)\r
---\r
-false\r
-\r
+++ /dev/null
-a = b\r
-b = a\r
-\r
-main = a\r
---\r
-???: Variables defined recursively must all be functions.
\ No newline at end of file
+++ /dev/null
-f g = a\r
- where \r
- a = g a\r
---\r
-3:11-3:12: Couldn't resolve variable a.
\ No newline at end of file
+++ /dev/null
-data Nat = O | S Nat\r
-\r
-// It is important for this test that even and or are not annotated\r
-even O = True\r
-even (S x) = odd x\r
-\r
-odd O = False\r
-odd (S x) = even x\r
-\r
-main = even (S (S (S (S (S O)))))\r
---\r
-false
\ No newline at end of file
+++ /dev/null
-(foo, bar) = (foo, "Hello world!")\r
-\r
-main = "ERROR"\r
---\r
-1:1-1:11: Illegal left hand side of the definition.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-// Version 1, 'untyped'\r
-data Color = R | B \r
-\r
-deriving instance Show Color\r
-\r
-data RB a = E | T Color (RB a) a (RB a)\r
-\r
-rbToList :: RB a -> [a]\r
-rbToList E = []\r
-rbToList (T _ l a r) = rbToList l + [a] + rbToList r\r
-\r
-deriving instance (Show a) => Show (RB a)\r
-\r
-// Insertion and membership test as by Okasaki\r
-insert :: Ord a => a -> RB a -> RB a\r
-insert x s = (match ins s with T _ a z b -> T B a z b) \r
- where\r
- ins E = T R E x E\r
- ins s = match s with\r
- T B a y b ->\r
- if x<y \r
- then balance (ins a) y b\r
- else if x>y \r
- then balance a y (ins b)\r
- else s\r
- T R a y b ->\r
- if x<y\r
- then T R (ins a) y b\r
- else if x>y \r
- then T R a y (ins b)\r
- else s\r
-\r
-member :: Ord a => a -> RB a -> Boolean\r
-member x E = False\r
-member x (T _ a y b)\r
- | x<y = member x a\r
- | x>y = member x b\r
- | otherwise = True\r
-\r
-// balance: first equation is new, to make it work with a weaker invariant\r
-balance :: RB a -> a -> RB a -> RB a\r
-balance (T R a x b) y (T R c z d) = T R (T B a x b) y (T B c z d)\r
-balance (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d)\r
-balance (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d)\r
-balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d)\r
-balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d)\r
-balance a x b = T B a x b\r
-\r
-// deletion a la SMK \r
-delete :: Ord a => a -> RB a -> RB a\r
-delete x t = (match del t with \r
- T _ a y b -> T B a y b\r
- _ -> E)\r
- where\r
- del E = E\r
- del (T _ a y b)\r
- | x<y = delformLeft a y b\r
- | x>y = delformRight a y b\r
- | otherwise = app a b\r
- delformLeft a y b= match a with\r
- T B _ _ _ -> balleft (del a) y b\r
- _ -> T R (del a) y b\r
- delformRight a y b = match b with\r
- T B _ _ _ -> balright a y (del b)\r
- _ -> T R a y (del b)\r
-\r
-balleft :: RB a -> a -> RB a -> RB a\r
-balleft (T R a x b) y c = T R (T B a x b) y c\r
-balleft bl x (T B a y b) = balance bl x (T R a y b)\r
-balleft bl x (T R (T B a y b) z c) = T R (T B bl x a) y (balance b z (sub1 c))\r
-\r
-balright :: RB a -> a -> RB a -> RB a\r
-balright a x (T R b y c) = T R a x (T B b y c)\r
-balright (T B a x b) y bl = balance (T R a x b) y bl\r
-balright (T R a x (T B b y c)) z bl = T R (balance (sub1 a) x b) y (T B c z bl)\r
-\r
-sub1 :: RB a -> RB a\r
-sub1 (T B a x b) = T R a x b\r
-sub1 _ = fail "invariance violation"\r
-\r
-app :: RB a -> RB a -> RB a\r
-app E x = x\r
-app x E = x\r
-app (T R a x b) (T R c y d) =\r
- match app b c with\r
- T R b' z c' -> T R(T R a x b') z (T R c' y d)\r
- bc -> T R a x (T R bc y d)\r
-app (T B a x b) (T B c y d) = \r
- match app b c with\r
- T R b' z c' -> T R(T B a x b') z (T B c' y d)\r
- bc -> balleft a x (T B bc y d)\r
-app a (T R b x c) = T R (app a b) x c\r
-app (T R a x b) c = T R a x (app b c)\r
-\r
-testList = [4,6,2,7,4,7,2,5]\r
-\r
-main = rbToList (foldl (flip insert) E testList)\r
---\r
-[2, 4, 5, 6, 7]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-Concat ?x ?y ?z :-
- @bbf 1
- ?z = ?x + ?y
-
- @bfb 0.5
- startsWith ?z ?x
- ?y = drop (length ?x) ?z
-
- @fbb 0.5
- endsWith ?z ?y
- ?x = take (length ?z - length ?y) ?z
-
-main = select ?y where
- Concat "Hello " ?y "Hello world!"
---
-[world!]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-MyExecute ?procedure :-
- @enforce
- Execute (?procedure "Foo")
-
-main = do
- v = ref ""
- enforce MyExecute (v :=)
- getRef v
---
-Foo
\ No newline at end of file
+++ /dev/null
-invalidProject :: (a,a) -> a\r
-invalidProject (a,a) = a\r
-\r
-main = "Not to be executed!"\r
---\r
-2:19-2:20: Repeated variable a in pattern.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-test :: () -> [Integer]\r
-test _ = do\r
- header = [0]\r
- rows = map (\foo -> map (\bar -> bar) [foo]) [1..5]\r
- foldl (+) header rows\r
- \r
-main = test ()\r
---\r
-[0, 1, 2, 3, 4, 5]
\ No newline at end of file
+++ /dev/null
-import "Prelude" hiding (scanl)\r
-\r
-scanl :: (b -> a -> <e> b) -> b -> [a] -> <e> [b]\r
-scanl f initial l = build (loop initial 0)\r
- where\r
- len = length l\r
- loop cur i accum cons = let nl = cons accum cur\r
- in if i==len\r
- then nl\r
- else loop (f cur (l!i)) (i+1) nl cons\r
- \r
-main = scanl (+) 0 [1,2,3]\r
---\r
-[0, 1, 3, 6]
\ No newline at end of file
+++ /dev/null
-import "Prelude" hiding (findFirst)\r
-\r
-infinity = 1e9\r
-\r
-@inline\r
-findFirst :: (a -> <e> Maybe b) -> [a] -> <e> Maybe b\r
-findFirst f l = loop 0\r
- where\r
- len = length l\r
- loop i \r
- | i >= len = Nothing\r
- | otherwise = match f (l!i) with\r
- s @ (Just _) -> s\r
- Nothing -> loop (i+1)\r
-\r
-dfsFirst :: (a -> <e> Boolean) -> (a -> <e> [a]) -> [a] -> <e> (Maybe a)\r
-dfsFirst acceptable successors initial = tryAll initial\r
- where\r
- tryAll l = findFirst loop l\r
- loop p \r
- | acceptable p = Just p\r
- | otherwise = tryAll (successors p)\r
-\r
-data Weighted a = Weighted a Double\r
-\r
-//type SearchAlgorithm e a =\r
-// (a -> <e> Boolean) -> (a -> <e> [Weighted a]) -> [Weighted a] -> <e> Weighted (Maybe a)\r
- \r
-//dfs :: SearchAlgorithm e a\r
-dfs :: (a -> <e> Boolean) -> (a -> <e> [Weighted a]) -> [Weighted a] -> <e> Weighted (Maybe a)\r
-dfs acceptable successors initial = foldl loop (Weighted Nothing infinity) initial\r
- where\r
- loop best@(Weighted _ bestW) (Weighted p w)\r
- | w >= bestW = best\r
- | acceptable p = Weighted (Just p) w\r
- | otherwise = foldl loop best\r
- $ map (\(Weighted p' w') -> Weighted p' (w+w'))\r
- $ successors p\r
-\r
-/*\r
-bfs :: SearchAlgorithm e a\r
-\r
-aStar :: (a -> <e> Double) -> SearchAlgorithm e a\r
-*/\r
-main = "Hello"\r
---\r
-Hello
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = map (1/) $ map (*3) [1,2,3]\r
---\r
-[0.3333333333333333, 0.16666666666666666, 0.1111111111111111]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"\r
-\r
-main = let\r
- l = [1..3] \r
- in\r
- select (?x,?y) where \r
- ?x <- l\r
- ?y <- l\r
- ?x = ?y\r
---\r
-[(1,1), (2,2), (3,3)]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-import "Minigraph"
-
-main = withGraph do
- a = resource "a"
- b = map resource ["b0", "b1", "b2", "b3", "b4"]
- r = map resource ["r0", "r1"]
-
- enforce
- Statement a (r!0) (b!0)
- Statement a (r!0) (b!1)
- Statement a (r!1) (b!4)
- Statement a (r!1) (b!3)
- Statement (b!1) (r!0) (b!2)
- R a :- {}
- R ?x :- R ?y ; Statement ?y (r!0) ?x
- S ?x :- R ?x ; Statement ?x (r!0) _
- sort $ map uriOf $ select ?x where S ?x
---
-[a, b1]
+++ /dev/null
-import "StandardLibrary"
-import "Minigraph"
-
-main = withGraph do
- a = resource "a"
- b = map resource ["b0", "b1", "b2", "b3", "b4"]
- r = map resource ["r0", "r1"]
-
- enforce
- Statement a (r!0) (b!0)
- Statement a (r!0) (b!1)
- Statement a (r!1) (b!4)
- Statement (b!1) (r!1) (b!3)
- Statement (b!1) (r!0) (b!2)
- sort $ map uriOf $ select ?x where
- Statement a (r!0) (_ : Resource { #r1 = ?x })
---
-[b3]
+++ /dev/null
-import "StandardLibrary"
-import "Minigraph"
-
-main = withGraph do
- a = resource "a"
- b = map resource ["b0", "b1", "b2"]
- r = map resource ["r0", "r1"]
-
- enforce
- Statement a (r!0) (b!0)
- Statement a (r!0) (b!1)
- Statement a (r!1) (b!1)
- Statement a (r!1) (b!2)
- sort $ map uriOf $ select ?x where
- <|> Statement a (r!0) ?x
- Statement a (r!1) ?x
---
-[b0, b1, b1, b2]
+++ /dev/null
-import "StandardLibrary"
-import "Minigraph"
-
-main = withGraph do
- r = map resource ["r0", "r1"]
- sort $ map uriOf $ select ?x where
- Statement ?y (r!0) ?x
- Statement ?x (r!1) ?y
---
-6:24-8:30: Failed to compile the query.
-Unsolved variables: ?x, ?y
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-main = select ?x where
- (?x,?y) = (1,2)
---
-[1]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-main = select ?x where
- (?x, 3) <- [(1,2),(2,3),(3,4)]
---
-[2]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-Foo ?a ?b ?l :-
- @ffb
- (?a,?b) <- ?l
-
-main = select ?x where
- Foo ?x 3 [(1,2),(2,3),(3,4)]
---
-[2]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-s1 = [1,2,3]
-s2 = [1,3]
-
-main = do
- C ?x :-
- ?x <- s1
- <!> ?x <- s2
- select ?x where C ?x
---
-[2]
\ No newline at end of file
+++ /dev/null
-class Ord a where\r
- min :: Ord a => a -> a -> a\r
-\r
-main = "Not to be executed."\r
---\r
-2:12-2:15: Unresolved type class Ord.
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-
-rt :: Serializable a => a -> a
-rt v = deserialize (serialize v)
-
-main :: String
-main = show (
- (rt "Hello", rt ()),
- (rt 1.2 :: Double, rt 1.2 :: Float, 3 :: Integer, 4 :: Long),
- rt (Just (1 :: Integer)),
- (rt [1::Integer,2,3], rt [[1::Integer,2],[3,4]], fromDoubleArray (rt (toDoubleArray [3::Double,2,1])))
- )
---
-(("Hello", ()), (1.2, 1.2, 3, 4), Just 1, ([1, 2, 3], [[1, 2], [3, 4]], [3.0, 2.0, 1.0]))
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-import "Serialization"\r
-\r
-rt :: IO a => a -> a\r
-rt v = readByteArray (writeByteArray v)\r
-\r
-main = show (\r
- (rt "Hello", rt ()),\r
- (rt 1.2 :: Double, rt 1.2 :: Float, 3 :: Integer, 4 :: Long),\r
- rt (Just (1 :: Integer)),\r
- (rt [1::Integer,2,3], rt [[1::Integer,2],[3,4]], fromDoubleArray (rt (toDoubleArray [3,2,1])))\r
- )\r
---\r
-(("Hello", ()), (1.2, 1.2, 3, 4), Just 1, ([1, 2, 3], [[1, 2], [3, 4]], [3.0, 2.0, 1.0]))
\ No newline at end of file
+++ /dev/null
-import "Prelude"
-import "Serialization" as Serialization
-
-rt :: Serialization.IO a => a -> a
-rt v = Serialization.readByteArray (Serialization.writeByteArray v)
-
-data FooBar a = Foo Integer | Bar a
-
-deriving instance (Show a) => Show (FooBar a)
-deriving instance (Serialization.IO a) => Serialization.IO (FooBar a)
-
-/*
-instance IO FooBar where
- read s = match Serialization.read s :: Integer with
- 0 -> Foo (Serialization.read s)
- 1 -> Bar (Serialization.read s)
- write s (Foo x) = do Serialization.write s (0 :: Integer) ; Serialization.write s x
- write s (Bar x) = do Serialization.write s (1 :: Integer) ; Serialization.write s x
-*/
-main = show (rt (Foo 3 :: FooBar Double))
---
-Foo 3
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"\r
-\r
-s1 = Set.set [3,2,1,4]\r
-s2 = Set.set [9,8,3,2]\r
-s1s2 = Set.union s1 s2\r
-\r
-main = show s1s2\r
---\r
-set [1, 2, 3, 4, 8, 9]
\ No newline at end of file
+++ /dev/null
-// Idea here is that the type variable in the top level type annotation\r
-// and the type annotation in the expression should be the same type.\r
-id :: a -> a\r
-id x = (x :: a)\r
-\r
-main = id "OK"\r
---\r
-OK
\ No newline at end of file
+++ /dev/null
-data List a = Nil | Cons a (List a)\r
-\r
-@private\r
-@inline\r
-build :: (forall a. a -> (b -> a -> a) -> a) -> List b\r
-build f = f Nil Cons\r
-\r
-@private\r
-foldr :: (a -> b -> b) -> b -> List a -> b\r
-foldr cons nil Nil = nil\r
-foldr cons nil (Cons h t) = cons h (foldr cons nil t)\r
-\r
-@private\r
-@inline\r
-singleton :: a -> List a\r
-singleton x = build (\nil cons -> cons x nil)\r
-\r
-@private\r
-@inline\r
-last :: List a -> a -> a\r
-last l def = foldr (\x _ -> x) def l\r
-\r
-main = last (singleton "Hello") "Foo"\r
---\r
-Hello
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = show [(1,2),(3,4),(5,6)]\r
---\r
-[(1, 2), (3, 4), (5, 6)]
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-// --- Signals ------------------------------------------------------\r
-\r
-data Signal =\r
- SigSum [Signal]\r
- | SigConst Double\r
- | SigNeg Signal\r
- | SigMul [Signal]\r
-\r
-deriving instance Eq Signal\r
-deriving instance Hashable Signal\r
-deriving instance Show Signal\r
-\r
-instance Additive Signal where\r
- zero = SigConst 0\r
- a + b = SigSum [a,b]\r
- sum l = SigSum l\r
-\r
-instance Ring Signal where\r
- one = SigConst 1\r
- neg a = SigNeg a\r
- fromInteger i = SigConst (fromInteger i)\r
- a * b = SigMul [a,b]\r
-\r
-/*\r
-instance Real Signal where\r
- fromDouble d = SigConst d\r
-*/\r
-\r
-main :: Signal\r
-main = 1 + 2 * 3 - 4 \r
---\r
-???
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = (sin + const 1) 0\r
---\r
-1.0
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main :: [Integer]\r
-main = sort [1,5,2,4,3]\r
---\r
-[1, 2, 3, 4, 5]
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-importJava "org.simantics.scl.runtime.Lists" where\r
- sortWith :: (a -> a -> Integer) -> [a] -> [a]\r
-\r
-//@JavaStaticMethod "org.simantics.scl.runtime.Lists.sortWith"\r
-//sortWith :: (a -> a -> Integer) -> [a] -> [a]\r
-\r
-\r
-//sortWith = Java.staticMethod "org.simantics.scl.runtime.Lists.sortWith"\r
-\r
-dumbCompare :: a -> a -> Integer\r
-dumbCompare x y = 0\r
-\r
-dumbSort = sortWith dumbCompare \r
-\r
-main = "Foo"\r
---\r
-Foo
\ No newline at end of file
+++ /dev/null
-data Either a b = Left a | Right b\r
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-data Nat = Zero | Succ Nat\r
-\r
-sum Zero a = a\r
-sum a Zero = a\r
-sum (Succ a) (Succ b) = Succ (Succ (sum a b))\r
-\r
-sum_append xs ys\r
- = go Zero (Left xs)\r
- where\r
- go z (Left xs)\r
- = match xs with\r
- Nil -> go z (Right ys)\r
- Cons x xs' -> go (sum x z) (Left xs')\r
- go z (Right ys)\r
- = match ys with\r
- Nil -> z\r
- Cons y ys' -> go (sum y z) (Right ys')\r
-\r
-main = "Hello world!"\r
---\r
-Hello world!
\ No newline at end of file
+++ /dev/null
-main = fail "badly"
---
-???
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-data Either a b = Left a | Right b\r
-\r
-data Stream a = Stream (s -> Step a s) s\r
-data Step a s = Done | Yield a s | Skip s\r
-\r
-// stream :: [a] -> Stream a\r
-// unstream :: Stream a -> [a] \r
-// streamRev :: [a] -> Stream a\r
-// unstreamRev :: Stream a -> [a]\r
-\r
-//toStream :: [a] -> Stream a\r
-//toStream l = Stream (\i -> if i >= length l then Done else Yield (get l i) (i+1)) 0\r
-\r
-filterS :: (a -> Boolean) -> Stream a -> Stream a\r
-filterS p (Stream next0 s0) = Stream next s0\r
- where\r
- next s = match next s with\r
- Done -> Done\r
- Skip s -> Skip s \r
- Yield a s -> if p a then Yield a s else Skip s\r
-\r
-mapS :: (a -> b) -> Stream a -> Stream b\r
-mapS f (Stream next0 s0) = Stream next s0\r
- where\r
- next s = match next0 s with\r
- Done -> Done\r
- Skip s -> Skip s \r
- Yield a s -> Yield (f a) s\r
- \r
-appendS :: Stream a -> Stream a -> Stream a\r
-appendS (Stream next1 s1) (Stream next2 s2) = Stream next (Left s1)\r
- where\r
- next (Left s) = match next1 s with\r
- Done -> Skip (Right s2)\r
- Skip s -> Skip (Left s) \r
- Yield a s -> Yield a (Left s)\r
- next (Right s) = match next2 s with\r
- Done -> Done\r
- Skip s -> Skip (Right s) \r
- Yield a s -> Yield a (Right s) \r
-\r
-decomposeS :: Stream a -> Maybe (a, Stream a)\r
-decomposeS (Stream next s0) = loop s0\r
- where\r
- loop s = match next s with\r
- Done -> Nothing\r
- Skip s -> loop s\r
- Yield a s -> Just (a, Stream next s) \r
-\r
-returnS :: a -> Stream a\r
-returnS x = Stream next True\r
- where \r
- next True = Yield x False\r
- next False = Done\r
- \r
-isEmptyS :: Stream a -> Boolean \r
-isEmptyS (Stream next s0) = loop s0\r
- where\r
- loop s = match next s with\r
- Done -> True\r
- Skip s -> loop s \r
- Yield _ _ -> False\r
- \r
-foldlS :: (a -> b -> a) -> a -> Stream b -> a\r
-foldlS f init (Stream next s0) = go init s0\r
- where\r
- go cur s = match next s with\r
- Done -> cur\r
- Skip s -> go cur s\r
- Yield x s -> go (f cur x) s\r
- \r
-scanlS :: (a -> b -> a) -> a -> Stream b -> Stream a\r
-scanlS f init (Stream next0 s0) = Stream next (s0, init)\r
- where\r
- next (s,v) = match next0 s with\r
- Done -> Done\r
- Skip s -> Skip (s, v)\r
- Yield x s -> Yield v (s, f v x) \r
- \r
-concatMapS :: (a -> Stream b) -> Stream a -> Stream b\r
-concatMapS f (Stream next0 s0) = Stream next (s0, Nothing)\r
- where\r
- next (s, Nothing) = match next0 s with\r
- Done -> Done\r
- Skip s -> Skip (s, Nothing)\r
- Yield x s -> Skip (s, Just (f x))\r
- next (s0, Just (Stream next1 s1)) = match next1 s1 with\r
- Done -> Skip (s0, Nothing)\r
- Skip s -> Skip (s0, Just (Stream next1 s))\r
- Yield x s -> Yield x (s0, Just (Stream next1 s))\r
-\r
-zipWithS :: (a -> b -> c) -> Stream a -> Stream b -> Stream c\r
-zipWithS f (Stream next0 s0) (Stream next1 s1) = Stream next (s0, s1, Nothing)\r
- where\r
- next (s0, s1, Nothing) = match next0 s0 with\r
- Done -> Done\r
- Skip s -> Skip (s, s1, Nothing)\r
- Yield x s -> Skip (s, s1, Just x)\r
- next (s0, s1, Just x) = match next1 s1 with\r
- Done -> Done\r
- Skip s -> Skip (s0, s, Just x)\r
- Yield y s -> Yield (f x y) (s0, s, Nothing)\r
-\r
-guardS :: Boolean -> Stream a -> Stream a\r
-guardS b (Stream next0 s0) = Stream next (b, s0)\r
- where\r
- next (False, _) = Done\r
- next (True, s) = match next0 s with\r
- Done -> Done\r
- Skip s -> Skip (True, s)\r
- Yield x s -> Yield x (True, s)\r
-/*\r
-takeS :: Integer -> Stream a -> Stream a\r
-takeS count (Stream next0 s0) = Stream next (count, s0)\r
- where\r
- next (count, s) = if count <= 0 then Done\r
- else match next0 s with\r
- Done -> Done\r
- | Skip s -> Skip (count, s)\r
- | Yield x s -> Yield x (count, s)\r
-*/\r
-repeatS :: a -> Stream a\r
-repeatS v = Stream next ()\r
- where\r
- next () = Yield v ()\r
-\r
-iterateS :: (a -> a) -> a -> Stream a\r
-iterateS f v = Stream next v\r
- where\r
- next v = Yield v (f v)\r
- \r
-main :: Integer\r
-main = foldlS Java.iadd (0 :: Integer) \r
- (appendS (appendS (returnS (1 :: Integer)) \r
- (returnS (2 :: Integer))) (returnS (3 :: Integer)))\r
---\r
-6
\ No newline at end of file
+++ /dev/null
-main = "a\nb\"c\'d"\r
---\r
-a\r
-b"c'd\r
---\r
-main = "a\u0053"\r
---\r
-aS\r
---\r
-main = "a\xb"\r
---\r
-1:8-1:10: Illegal string escape character.\r
+++ /dev/null
-import "Prelude"\r
-\r
-f x = x + 1\r
-\r
-g a b = """\(a) + \(b) = \(a+b)"""\r
-\r
-main = "f 3 = \(f 3), " + g 1 2\r
---\r
-f 3 = 4, 1 + 2 = 3
\ No newline at end of file
+++ /dev/null
-stringSum :: String -> Integer\r
-stringSum "(\(a),\(b),\(c))" = a + b + c\r
-\r
-main = stringSum "(1,2,3)"\r
---\r
-6
\ No newline at end of file
+++ /dev/null
-main :: Integer\r
-main = match "Bar" with\r
- "Foo" -> 1\r
- "Bar" -> 2\r
- _ -> 3\r
---\r
-2
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-f :: Integer -> Double\r
-f m = sum [1/(fromInteger x) | x <- [1..m]]\r
-\r
-main = f 100\r
---\r
-5.187377517639621\r
+++ /dev/null
-import "StandardLibrary"\r
-\r
-main = do \r
- (r,t) = Debug.time (foldl (+) 0 \r
- $ map (\(_,_,z) -> z) \r
- $ [(a,b,c) | a <- [1..50], b <- [1..50], c <- [1..50], a*a + b*b == c*c])\r
- print t\r
- r\r
---\r
-1172
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = sin 1 2\r
---\r
-3:8-3:11: Constrain Real (a -> b) contains free variables not mentioned in the type of the value.\r
-3:14-3:15: Constrain Ring a contains free variables not mentioned in the type of the value.
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-import "Minigraph"
-import "MMap" as MMap
-
-consistsOf :: <Graph> Integer
-consistsOf = resource "consistsOf"
-instanceOf :: <Graph> Integer
-instanceOf = resource "instanceOf"
-areConnected :: <Graph> Integer
-areConnected = resource "areConnected"
-from :: <Graph> Integer
-from = resource "from"
-to :: <Graph> Integer
-to = resource "to"
-
-element :: <Graph> Integer
-element = resource "Element"
-connection :: <Graph> Integer
-connection = resource "Connection"
-
-mapping relation MapDiagrams Integer Integer
-
-rule ElementsRule where
- @when
- MapDiagrams ?dA ?dB
-
- @from
- Statement ?dA consistsOf ?elA
- Statement ?elA instanceOf element
-
- @to
- Statement ?dB consistsOf ?elB
- Statement ?elB instanceOf element
-
- @where
- MapElements ?elA ?elB
-
-rule ConnectionsRule where
- @when
- MapElements ?elA1 ?elB1
- MapElements ?elA2 ?elB2
-
- @from
- Statement ?elA1 areConnected ?elA2
-
- @to
- Statement ?conn instanceOf connection
- Statement ?conn from ?elB1
- Statement ?conn to ?elB2
-
-foo :: <Graph,Proc> ()
-foo = transformation OneShotForward where
- MapDiagrams 0 0
-
-main = withGraph do
- foo
- "OK"
---
-OK
+++ /dev/null
-import "StandardLibrary"
-
-mapping relation Fib Integer Integer
-
-rule FibRecurrence where
- @when
- Fib ?n ?a
- Fib (?n+1) ?b
- ?n < 20
-
- @where
- Fib (?n+2) (?a + 1)
-/*
-rule PrintIt where
- @when
- Fib ?n ?a
-
- @to
- Execute (print "\(?n) -> \(?a)")
-*/
-main = transformation OneShotForward where
- Fib 0 1
- Fib 1 1
---
-()
+++ /dev/null
-import "StandardLibrary"
-
-mapping relation Fib Integer Integer
-
-rule FibRecurrence where
- @when
- Fib ?n (?a + ?b)
- ?n >= 2
-
- @where
- Fib (?n-1) ?b
- Fib (?n-2) ?a
-
-rule Init where
- @when
- Fib ?x 1
- ?x < 2
-
-rule Seed where
- @where
- Fib 20 ?hmm
-
-rule PrintIt where
- @when
- Fib ?n ?a
-
- @to
- Execute (print "\(?n) -> \(?a)")
-
-main = transformation OneShotForward where
---
-()
+++ /dev/null
-import "StandardLibrary"
-
-mapping relation M Integer (Integer,Integer)
-
-rule Mix where
- @when
- M ?a (?b, ?c)
- ?a <= 10
-
- @where
- M (?a + 1) (?c, ?b)
-
-rule PrintIt where
- @when
- M ?a (?b,?c)
-
- @to
- Execute (print "\(?a) -> \(?b), \(?c)")
-
-rule Seed where
- @where
- M 0 (1,?x)
- M 10 (?y,2)
-
-main = transformation OneShotForward where
---
-()
+++ /dev/null
-import "StandardLibrary"
-
-Foo ?x :-
- @enforce 1
- Execute (?x := (1 :: Integer))
-
-Bar ?x :-
- @enforce 2
- Execute (if getRef ?x == 1 then () else fail "Test failed.")
-
-rule DoIt where
- @from
- ?x = ref (0 :: Integer)
-
- @to
- Bar ?x
- Foo ?x
-
-main :: ()
-main = transformation OneShotForward where
---
-()
+++ /dev/null
-import "StandardLibrary"
-
-mapping relation Foo String String
-
-rule DoIt where
- @when
- Foo ?a ?b
-
- @to
- Foo ?b "c"
-
-main = transformation OneShotForward where
- Foo "a" "b"
---
-10:9-10:11: Cannot resolve the variable ?b using the source patterns.
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"
-
-Foo ?x :-
- @enforce
- Execute (iterList printString [?x :: String])
-
-
-rule DoIt where
- @to
- Foo "Hello world!"
-
-main = transformation OneShotForward where
---
-()
+++ /dev/null
-import "StandardLibrary"
-
-rule A where
- @to
- Execute (print "A")
-
-rule B where
- @to
- Execute (print "B")
-
-rule C where
- @to
- Execute (print "C")
-
-main = transformation OneShotForward where
---
-()
+++ /dev/null
-id0 () = ()\r
-\r
-id0A :: () -> ()\r
-id0A () = ()\r
-\r
-id2 (a,b) = (a,b)\r
-\r
-id2A :: (a,b) -> (a,b)\r
-id2A (a,b) = (a,b)\r
-\r
-id3 (a,b,c) = (a,b,c)\r
-\r
-id3A :: (a,b,c) -> (a,b,c)\r
-id3A (a,b,c) = (a,b,c)\r
-\r
-main = id3 (1 :: Integer,id0 (),3 :: Integer)\r
---\r
-(1,(),3)
\ No newline at end of file
+++ /dev/null
-// This is just a restricted version of Tuples test\r
-id0 () = ()\r
-\r
-main = id0 ()\r
---\r
-()
\ No newline at end of file
+++ /dev/null
-\r
-type Id = Integer\r
-\r
-incrementId :: Id -> Id\r
-incrementId x = x\r
-\r
-main = incrementId 3\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-type List a = [a]
-
-convert :: List Integer -> List Double
-convert v = v
-
-main = "Not to be executed."
---
-4:13-4:14: Expected <[Double]> got <[Integer]>.
\ No newline at end of file
+++ /dev/null
-type IntegerList = [Integer]
-type DoubleList = [Double]
-
-convert :: IntegerList -> DoubleList
-convert v = v
-
-main = "Not to be executed."
---
-5:13-5:14: Expected <[Double]> got <[Integer]>.
\ No newline at end of file
+++ /dev/null
-type Foo = Bar
-type Bar = Integer
-main = 1 :: Foo
---
-1
---
-type Bar = Integer
-type Foo = Bar
-main = 1 :: Foo
---
-1
---
-type Foo = Foo
-main = 1 :: Foo
---
-1:1-1:15: Type alias has a self reference.
---
-type Foo = Bar
-type Bar = Foo
-main = 1 :: Foo
---
-1:1-1:15: Recursively defined type alias (Foo, Bar).
\ No newline at end of file
+++ /dev/null
-id x = x :: Integer\r
-\r
-main = id "foo"\r
---\r
-3:11-3:16: Expected <Integer> got <String>.
\ No newline at end of file
+++ /dev/null
-id (x :: Integer) = x\r
-\r
-main = id "foo"\r
---\r
-3:11-3:16: Expected <Integer> got <String>.
\ No newline at end of file
+++ /dev/null
-\r
-class Foo a where\r
- foo :: a -> Integer\r
- \r
-instance Foo Integer where\r
- foo x = x\r
- \r
-main = foo (13 :: Integer)\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-(+) = Java.iadd\r
-\r
-class Foo a where\r
- foo :: a -> Integer\r
- /*\r
-class (Foo a) => Bar a where\r
- bar :: a -> Integer\r
- */\r
-instance Foo Integer where\r
- foo x = x+1\r
- /* \r
-instance Bar Integer where\r
- bar x = x+2\r
-*/\r
-data X a = X a\r
-\r
-instance (Foo a) => Foo (X a) where\r
- foo (X a) = foo a\r
- /*\r
-instance (Bar a) => Bar (X a) where\r
- bar (X a) = bar a*/\r
- \r
-main = foo (X (1 :: Integer))\r
-// + bar (X (2 :: Integer))\r
---\r
-2
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-importJava "org.simantics.scl.runtime.Lists" where\r
- foldl :: (a -> b -> a) -> a -> [b] -> a\r
-\r
-class Additive a where\r
- zero :: a\r
- (+) :: a -> a -> a \r
- \r
- sum :: [a] -> a\r
- sum = foldl (+) zero \r
- \r
-instance (Additive a, Additive b, Additive c) => Additive (a, b, c) where\r
- zero = (zero, zero, zero)\r
- (a0, b0, c0) + (a1, b1, c1) = (a0+a1, b0+b1, c0+c1)\r
- \r
-main = "OK"\r
---\r
-OK
\ No newline at end of file
+++ /dev/null
-data Foo1 a = Foo1 a\r
-data Foo2 a = Foo2 a\r
-\r
-foo1 :: Foo1 a -> a\r
-foo1 (Foo1 x) = x\r
-\r
-foo2 :: Foo2 a -> a\r
-foo2 (Foo2 x) = x\r
-\r
-class Makeable s where\r
- make :: a -> s a\r
-\r
-instance Makeable Foo1 where\r
- make = Foo1\r
-\r
-instance Makeable Foo2 where\r
- make = Foo2\r
-\r
-class (Makeable f) => Foo f where\r
- foo :: f a -> a\r
-\r
-class (Makeable b) => Bar b where\r
- bar :: b a -> a\r
-\r
-class (Makeable b) => Baz b where\r
- baz :: b a -> a\r
-\r
-class (Makeable b) => Bim b where\r
- bim :: b a -> a\r
-\r
-instance Foo Foo1 where\r
- foo = foo1\r
- \r
-instance Bar Foo2 where\r
- bar = foo2\r
- \r
-instance (Bar b) => Baz b where\r
- baz = bar\r
-\r
-instance Bim Foo1 where\r
- bim = foo1\r
-\r
-instance (Baz b) => Bim b where\r
- bim = baz\r
-\r
-doFoo1 (Foo1 x) = x\r
-doFoo2 (Foo2 x) = x\r
-\r
-useBim :: Bim b => (forall a. b a -> a) -> a -> [a]\r
-useBim doit x = [doit (make x), bim (make x :: Foo1 a)]\r
-\r
-main = "OK"\r
---\r
-"OK"\r
+++ /dev/null
-import "Prelude"\r
-\r
-distance (x1,y1) (x2,y2) = let dx = x1-x2\r
- dy = y1-y2\r
- in sqrt (dx*dx + dy*dy) print x1\r
---\r
-5:31-5:35: Constrain Real ((a -> <b> ()) -> ((c -> <d> ()) -> <h> e -> <g> f) -> <j> i) contains free variables not mentioned in the type of the value.\r
-5:52-5:57: Constrain Show a contains free variables not mentioned in the type of the value.\r
-5:58-5:60: Unification of types failed.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = typeOf (\(a,b) -> a+b :: Double)\r
---\r
-(Double, Double) -> Double
\ No newline at end of file
+++ /dev/null
-id x = x\r
-main = id id (5 :: Integer)\r
---\r
-5
\ No newline at end of file
+++ /dev/null
-a :: Double
-a = a
-
-id :: Integer -> Integer
-id x = x
-
-b = id a
---
-7:8-7:9: Expected <Integer> got <Double>.
\ No newline at end of file
+++ /dev/null
-a :: Integer\r
-a = a\r
-\r
-id :: Integer -> Integer\r
-id x = x\r
-\r
-b = id a a\r
---\r
-7:5-7:11: Function of arity 1 is applied with 2 parameters.
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = -5\r
---\r
--5
\ No newline at end of file
+++ /dev/null
-\r
-foo :: Integer\r
-// foo = 0\r
-\r
---\r
-2:1-2:15: foo is not defined.
\ No newline at end of file
+++ /dev/null
-a = =
-b = 4
---
-1:5-1:6: Unexpected token '=' (EQUALS). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LBRACKET, LET, LPAREN, MATCH, MDO, MINUS, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION, WHEN.
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java
-import "StandardLibrary"
-import "Unification"
-
-pair :: Default a => Default b => UTag (a, b) (Unifiable a, Unifiable b)
-pair = uTag 0 (\(ua, ub) -> (extract ua, extract ub)) Java.unsafeCoerce
-
-/*triple :: Default a => Default b => Default c =>
- UTag (a, b, c) (Unifiable a, Unifiable b, Unifiable c)*/
-triple = uTag 0 (\(ua, ub, uc) -> (extract ua, extract ub, extract uc)) Java.unsafeCoerce
-
-main :: (Integer,Integer,Integer)
-main = do
- um1 = createUMap
- um2 = createUMap
- v1 = uVar
- v2 = uVar
- v3 = uVar
- vX = uVar
- putUMap um1 "a" (uCons triple (v1, v2, v3))
- putUMap um1 "a" (uCons triple (v2, v3, v1))
- putUMap um1 "a" (uCons triple (vX, uVar, uVar))
- putUMap um2 "b" vX
- putUMapC um2 "b" 12
-
- getUMap um1 "a"
---
-(12,12,12)
\ No newline at end of file
+++ /dev/null
-\r
-@sdlfkmsdlfkm\r
-main = "Not to be executed"\r
---\r
-2:1-2:14: Unknown annotation.
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-instance Monoid List where\r
- zero = Nil\r
- \r
---\r
-4:10-4:16: Couldn't resolve class Monoid.
\ No newline at end of file
+++ /dev/null
-main :: List Integer\r
-main = 13\r
---\r
-1:9-1:13: Didn't find type constructor List.
\ No newline at end of file
+++ /dev/null
-class Functor f where\r
- map :: (a -> b) -> f a -> f b\r
-\r
-data Iddd a = Idd a\r
-\r
-instance Functor Idd where\r
- map (Idd x) = x\r
---\r
-6:18-6:21: Didn't find type constructor Idd.
\ No newline at end of file
+++ /dev/null
-a = b\r
-\r
---\r
-1:5-1:6: Couldn't resolve variable b.
\ No newline at end of file
+++ /dev/null
-\r
-a = a\r
-b = b\r
-c = a + b\r
-\r
---\r
-4:7-4:8: Couldn't resolve variable +.
\ No newline at end of file
+++ /dev/null
-\r
-data List a = Nil | Cons a (List a)\r
-\r
-data Foo = Foo\r
-\r
-main = Foo `Cons` (Foo `Cons` Nil)\r
---\r
-(Cons Foo (Cons Foo Nil))
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-import "Vector"\r
-\r
-main = fromDynamic (toDynamic (vector [3 :: Double])) :: [Double]\r
---\r
-[3.0]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"\r
-\r
-a :: Vector Double\r
-a = vector [1,2,3]\r
-\r
-main = map (a !) [0..length a-1]\r
---\r
-[1.0, 2.0, 3.0]
\ No newline at end of file
+++ /dev/null
-import "StandardLibrary"\r
-\r
-convertDataset :: [Double] -> [Double] -> Vector (Vector Double)\r
-convertDataset xs ys = vector [vector xs, vector ys]\r
-\r
-main = "Foo"\r
---\r
-Foo
\ No newline at end of file
+++ /dev/null
-importJava "java.util.List" where\r
- data List a\r
- \r
- @JavaName add\r
- addList :: List a -> a -> <Proc> Boolean\r
-\r
-importJava "java.util.ArrayList" where\r
- @JavaName "<init>"\r
- newList :: () -> <Proc> (List a)\r
-\r
-main = do\r
- l = newList ()\r
- addList l (3 :: Integer)\r
- l\r
---\r
-[3]
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-class Foo a where\r
- foo :: a -> () -> a\r
- \r
-instance Foo Integer where\r
- foo x () = x\r
- \r
-idWithFoo x = foo x () \r
- \r
-main = idWithFoo (13 :: Integer)\r
---\r
-13
\ No newline at end of file
+++ /dev/null
-import "JavaBuiltin" as Java\r
-\r
-data Foo = Foo ()\r
-\r
-\r
-ff = Foo ()\r
-\r
-gg () = 3 :: Integer\r
-\r
-main = gg (match ff with Foo a -> a)\r
---\r
-3
\ No newline at end of file
+++ /dev/null
-\r
-while :: (<e> Boolean) -> (<e> a) -> <e> ()\r
-while cond body = loop ()\r
- where loop _ = if cond\r
- then do body ; loop ()\r
- else ()\r
-\r
-main = "FOO"\r
---\r
-FOO
\ No newline at end of file
+++ /dev/null
-import "Prelude" hiding (while)\r
-\r
-while :: Maybe Boolean -> Maybe a -> Maybe ()\r
-while condM bodyM = mdo\r
- cond <- condM\r
- if cond \r
- then bodyM >> while condM bodyM\r
- else return ()\r
-\r
-main = "FOO"\r
---\r
-FOO
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-main = do\r
- a = ref 1\r
- b = ref 0\r
- while (getRef a < 5) do\r
- b := getRef b + 1\r
- a := getRef a + 1\r
- getRef b \r
---\r
-4
\ No newline at end of file
+++ /dev/null
-\r
-class Foo a where\r
- foo :: a\r
- bar = foo\r
- \r
-main = "Not to be executed."\r
---\r
-4:5-4:14: Method bar is not defined in this class.
\ No newline at end of file
+++ /dev/null
-\r
-class Foo a where\r
- foo :: a\r
- \r
-instance Foo Integer where\r
- foo = foo\r
- bar = foo\r
- \r
-main = "Not to be executed."\r
---\r
-7:5-7:14: Method bar is not defined in the type class Foo.
\ No newline at end of file
+++ /dev/null
-> 1+1
-2
-> 1-1
-0
-> 1+1.0
-2.0
-> 2*5
-10
-> 4/3
-1.3333333333333333
-> 4 `div` 3
-1
\ No newline at end of file
+++ /dev/null
-> id x = x
-> id 2
-2
-> id "Hello!"
-"Hello!"
-
-> id = \x -> x
-> id 2
-2
-
-> fib 0 = 1
-> fib 1 = 1
-> fib n = fib (n-1) + fib (n-2)
-
-> fib 2
-2
-> fib 3
-3
-> fib 4
-5
\ No newline at end of file
+++ /dev/null
-> f x = x + 1
-> f 3
-4
-> f 4.5
-5.5
\ No newline at end of file
+++ /dev/null
-> [1,2,3]
-[1, 2, 3]
-
-> [5..9]
-[5, 6, 7, 8, 9]
+++ /dev/null
-package org.simantics.scl.compiler.tests.unit;
-
-import org.junit.Test;
-import org.simantics.scl.compiler.environment.Environment;
-import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
-import org.simantics.scl.compiler.errors.Locations;
-import org.simantics.scl.compiler.internal.elaboration.constraints2.ConstraintSolver;
-import org.simantics.scl.compiler.tests.TestBase;
-import org.simantics.scl.compiler.types.TCon;
-import org.simantics.scl.compiler.types.TMetaVar;
-import org.simantics.scl.compiler.types.Types;
-import org.simantics.scl.compiler.types.kinds.Kinds;
-
-public class TestConstraintSolver {
-
- public final TCon COLLECTION = Types.con("Collection", "Collection");
-
- @Test
- public void testConstraintSolver() throws Exception {
- EnvironmentSpecification environmentSpecification = new EnvironmentSpecification();
- environmentSpecification.importModule("Builtin", "");
- environmentSpecification.importModule("Prelude", "");
- environmentSpecification.importModule("Collection", "");
-
- Environment environment = TestBase.PRELUDE_MODULE_REPOSITORY
- .createRuntimeEnvironment(environmentSpecification,
- getClass().getClassLoader()).getEnvironment();
-
- ConstraintSolver solver = new ConstraintSolver(environment);
-
- TMetaVar a = Types.metaVar(Kinds.STAR);
- TMetaVar b = Types.metaVar(Kinds.STAR);
- solver.addDemand(Types.pred(COLLECTION, Types.list(a), b), Locations.NO_LOCATION);
-
- solver.print();
- }
-
-}
+++ /dev/null
-package org.simantics.scl.compiler.tests.unit;\r
-\r
-import java.util.Collection;\r
-\r
-import org.junit.Test;\r
-import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;\r
-import org.simantics.scl.compiler.environment.filter.NamespaceFilter;\r
-import org.simantics.scl.compiler.environment.filter.NamespaceFilters;\r
-import org.simantics.scl.compiler.environment.filter.NegativeNamespaceFilter;\r
-import org.simantics.scl.compiler.environment.filter.PositiveNamespaceFilter;\r
-\r
-import gnu.trove.set.hash.THashSet;\r
-import junit.framework.Assert;\r
-\r
-public class TestNamespaceFilter {\r
- \r
- private void testBooleanOperations(Collection<String> all, NamespaceFilter a, NamespaceFilter b) {\r
- {\r
- NamespaceFilter c = NamespaceFilters.union(a, b);\r
- //System.out.println("union(" + a + ", " + b + ") = " + c);\r
- for(String name : all)\r
- Assert.assertEquals(\r
- a.isValueIncluded(name) || b.isValueIncluded(name),\r
- c.isValueIncluded(name));\r
- }\r
- {\r
- NamespaceFilter c = NamespaceFilters.intersection(a, b);\r
- //System.out.println("intersection(" + a + ", " + b + ") = " + c);\r
- for(String name : all)\r
- Assert.assertEquals(\r
- a.isValueIncluded(name) && b.isValueIncluded(name),\r
- c.isValueIncluded(name));\r
- }\r
- }\r
-\r
- private void testBooleanOperations(THashSet<String> a, THashSet<String> b) {\r
- THashSet<String> all = new THashSet<String>();\r
- all.addAll(a);\r
- all.addAll(b);\r
- all.add("dummy");\r
- \r
- PositiveNamespaceFilter pa = new PositiveNamespaceFilter(a);\r
- NegativeNamespaceFilter na = new NegativeNamespaceFilter(a);\r
- PositiveNamespaceFilter pb = new PositiveNamespaceFilter(b);\r
- NegativeNamespaceFilter nb = new NegativeNamespaceFilter(b);\r
- testBooleanOperations(all, pa, pb);\r
- testBooleanOperations(all, na, pb);\r
- testBooleanOperations(all, pa, nb);\r
- testBooleanOperations(all, na, nb);\r
- }\r
- \r
- private void testBooleanOperations(THashSet<String> a) {\r
- THashSet<String> all = new THashSet<String>();\r
- all.addAll(a);\r
- all.add("dummy");\r
- \r
- PositiveNamespaceFilter pa = new PositiveNamespaceFilter(a);\r
- NegativeNamespaceFilter na = new NegativeNamespaceFilter(a);\r
- testBooleanOperations(all, pa, AcceptAllNamespaceFilter.INSTANCE);\r
- testBooleanOperations(all, na, AcceptAllNamespaceFilter.INSTANCE);\r
- testBooleanOperations(all, AcceptAllNamespaceFilter.INSTANCE, pa);\r
- testBooleanOperations(all, AcceptAllNamespaceFilter.INSTANCE, na);\r
- testBooleanOperations(all, AcceptAllNamespaceFilter.INSTANCE, AcceptAllNamespaceFilter.INSTANCE);\r
- }\r
- \r
- @Test\r
- public void testBooleanOperations() {\r
- for(int p=0;p<8;++p) {\r
- THashSet<String> a = new THashSet<String>();\r
- for(int i=0;i<3;++i)\r
- if(((p >> i) & 1) == 1)\r
- a.add(String.valueOf(i));\r
- testBooleanOperations(a);\r
- }\r
- \r
- for(int p=0;p<64;++p) {\r
- THashSet<String> a = new THashSet<String>();\r
- THashSet<String> b = new THashSet<String>();\r
- for(int i=0;i<3;++i) {\r
- if(((p >> i) & 1) == 1)\r
- a.add(String.valueOf(i));\r
- if(((p >> (i+3)) & 1) == 1)\r
- b.add(String.valueOf(i));\r
- }\r
- testBooleanOperations(a, b);\r
- }\r
- }\r
- \r
-}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests.unit;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.junit.Assert;\r
-import org.junit.Test;\r
-import org.simantics.scl.compiler.errors.ErrorLog;\r
-import org.simantics.scl.compiler.internal.elaboration.subsumption.SubSolver;\r
-import org.simantics.scl.compiler.internal.elaboration.subsumption.Subsumption;\r
-import org.simantics.scl.compiler.types.TMetaVar;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\r
-import org.simantics.scl.compiler.types.util.Polarity;\r
-\r
-\r
-public class TestSubSolver {\r
-\r
- @Test\r
- public void testBipolarBounded() {\r
- ErrorLog errorLog = new ErrorLog();\r
- ArrayList<Subsumption> subsumptions = new ArrayList<Subsumption>();\r
- ArrayList<Type> potentialSingletonEffects = new ArrayList<Type>();\r
- \r
- TMetaVar in = Types.metaVar(Kinds.EFFECT);\r
- TMetaVar out = Types.metaVar(Kinds.EFFECT);\r
- in.addPolarity(Polarity.NEGATIVE);\r
- out.addPolarity(Polarity.POSITIVE);\r
- subsumptions.add(new Subsumption(0, Types.READ_GRAPH, out));\r
- subsumptions.add(new Subsumption(0, in, out));\r
- \r
- SubSolver solver = new SubSolver(errorLog, subsumptions, potentialSingletonEffects, 0);\r
- solver.solve();\r
- Assert.assertEquals("", errorLog.getErrorsAsString());\r
- }\r
- \r
-}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests.unit;\r
-\r
-import org.junit.Test;\r
-import org.simantics.scl.compiler.environment.Environment;\r
-import org.simantics.scl.compiler.environment.Environments;\r
-import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
-import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
-import org.simantics.scl.compiler.tests.TestBase;\r
-import org.simantics.scl.compiler.types.Type;\r
-\r
-public class TestTypeParser {\r
- \r
- @Test\r
- public void testTypeParser() throws Exception {\r
- EnvironmentSpecification spec = new EnvironmentSpecification();\r
- spec.importModule("Builtin", "");\r
- spec.importModule("Prelude", "");\r
- RuntimeEnvironment runtimeEnvironment =\r
- TestBase.PRELUDE_MODULE_REPOSITORY.createRuntimeEnvironment(spec, getClass().getClassLoader());\r
- Environment environment = runtimeEnvironment.getEnvironment();\r
- Type type = Environments.getType(environment, "String -> <Proc> ()");\r
- System.out.println(type);\r
- }\r
- \r
-}\r
VALUE_NUMBER_INT :: JsonToken\r
VALUE_STRING :: JsonToken\r
VALUE_TRUE :: JsonToken\r
-instance Eq JsonToken where\r
- (==) = Java.equals\r
\r
importJava "com.fasterxml.jackson.core.JsonParser" where\r
data JsonParser\r
data JsonField = JsonField String Json\r
\r
deriving instance Show Json\r
-deriving instance Eq Json\r
deriving instance Show JsonField\r
-deriving instance Eq JsonField\r
\r
instance Json Json where\r
writeJson g (JsonString value) = writeString g value\r
makeTypeEqual _ _ = ()\r
\r
@private\r
-testValue :: Json a => Show a => Eq a => a -> <Proc> ()\r
+testValue :: Json a => Show a => a -> <Proc> ()\r
testValue v1 = do\r
v2 = toJsonString v1\r
v3 = fromJsonString v2\r
\r
setAttribute :: Element -> String -> String -> <Proc> ()\r
\r
- @JavaName equals\r
- equalsElement :: Element -> Element -> Boolean\r
-\r
-instance Eq Element where\r
- (==) = equalsElement\r
-\r
importJava "org.jdom2.Attribute" where\r
data Attribute\r
\r
importJava "org.simantics.db.ReadGraph" where\r
data ReadGraphX\r
\r
-importJava "java.lang.Object" where \r
- @JavaName equals\r
- resourceEquals :: Resource -> Resource -> Boolean\r
- @JavaName hashCode\r
- resourceHash :: Resource -> Integer\r
-\r
-instance Eq Resource where\r
- (==) = resourceEquals\r
-\r
instance Ord Resource where\r
compare a b = compare (resourceId a) (resourceId b)\r
- \r
-instance Hashable Resource where\r
- hashP = hashP . resourceHash\r
- \r
+ \r
instance Show Resource where\r
show r = "#" + show (resourceId r)\r
\r
include "Simantics/DB"\r
import "Simantics/DB" as DB\r
\r
-importJava "java.lang.Object" where\r
- @JavaName equals\r
- """\r
-Function **variableEquals** compares the given input variables and returns True if they are the same.\r
-\r
-Example:\r
-\r
- import "Simantics/Variables"\r
- import "Apros/Module"\r
- my_variable_1 = moduleVariable "PO01"\r
- my_variable_2 = moduleVariable "PO02"\r
- variableEquals my_variable_1 my_variable_2\r
- \r
- > False\r
- \r
- """\r
- variableEquals :: Variable -> Variable -> Boolean\r
- @JavaName hashCode\r
- variableHash :: Variable -> Integer\r
-\r
-instance Eq Variable where\r
- (==) = variableEquals\r
- \r
-instance Hashable Variable where\r
- hashP = hashP . variableHash\r
-\r
importJava "org.simantics.db.layer0.variable.Variables" where\r
@JavaName getVariable\r
"""\r
Bundle-Activator: org.simantics.scl.osgi.internal.Activator
Require-Bundle: org.eclipse.core.runtime,
gnu.trove3;bundle-version="3.0.0",
- org.simantics.scl.compiler;bundle-version="0.2.0";visibility:=reexport
+ org.simantics.scl.compiler;bundle-version="0.6.0";visibility:=reexport
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.simantics.scl.osgi,
org.simantics.scl.osgi.internal
-Service-Component: OSGI-INF/org.simantics.scl.osgi.internal.BundleTestScriptRepository.xml,
+Service-Component: OSGI-INF/org.simantics.scl.osgi.internal.BundleModuleSourceRepository.xml,
OSGI-INF/org.simantics.scl.osgi.internal.FileSystemModuleSourceRepository.xml,
- OSGI-INF/org.simantics.scl.osgi.internal.BundleModuleSourceRepository.xml
+ OSGI-INF/org.simantics.scl.osgi.internal.BundleTestScriptRepository.xml
Import-Package: org.osgi.service.component,
org.osgi.service.component.annotations
bin.includes = META-INF/,\\r
.,\\r
scl/,\\r
- OSGI-INF/org.simantics.scl.osgi.internal.BundleTestScriptRepository.xml,\\r
+ OSGI-INF/org.simantics.scl.osgi.internal.BundleModuleSourceRepository.xml,\\r
OSGI-INF/org.simantics.scl.osgi.internal.FileSystemModuleSourceRepository.xml,\\r
- OSGI-INF/org.simantics.scl.osgi.internal.BundleModuleSourceRepository.xml\r
+ OSGI-INF/org.simantics.scl.osgi.internal.BundleTestScriptRepository.xml\r
src.includes = scl/\r
package org.simantics.scl.osgi.internal;\r
\r
-import java.io.File;\r
import java.io.IOException;\r
import java.io.InputStream;\r
import java.net.URISyntaxException;\r
Bundle-Version: 0.4.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.simantics.scl.runtime,
+ org.simantics.scl.runtime.chr,
org.simantics.scl.runtime.collection,
org.simantics.scl.runtime.exceptions,
org.simantics.scl.runtime.function,
instance Arbitrary Character where
arbitrary = genRandom randomCharacter
instance CoArbitrary Character where
- variateSeed _ seed v = seed + fromInteger (hash (showCharacter v))
+ variateSeed _ seed v = seed + fromInteger (hashCode (showCharacter v))
"""Generates a random string that is a valid SCL or Java identifier"""
arbitraryIdentifier = Gen $ \n -> string (Vector.vectorF (1+randomN (max n 1))
instance Arbitrary String where
arbitrary = Gen $ \n -> string (Vector.vectorF (randomN (1+n)) (\_ -> randomCharacter))
instance CoArbitrary String where
- variateSeed _ seed v = seed + fromInteger (hash v)
+ variateSeed _ seed v = seed + fromInteger (hashCode v)
instance Arbitrary () where
arbitrary = genRandom ()
@JavaName size
length :: T a -> <Proc> Integer
-contains :: Eq a => T a -> a -> <Proc> Boolean
+contains :: T a -> a -> <Proc> Boolean
contains l a = loop 0
where
len = length l
@JavaName intValue
toIntegerBigInteger :: BigInteger -> Integer
-instance Eq BigInteger where
- (==) = equalsBigInteger
-
instance Show BigInteger where
show = showBigInteger
min = minBigInteger
max = maxBigInteger
-instance Hashable BigInteger where
- hashP v x = hashBigInteger v + 31*x
-
instance Additive BigInteger where
zero = zeroBigInteger
(+) = addBigInteger
all :: (El a -> <e> Boolean) -> a -> <e> Boolean
filter :: (El a -> <e> Boolean) -> a -> <e> a
partition :: (El a -> <e> Boolean) -> a -> <e> (a,a)
- groupBy :: Hashable b => (El a -> b) -> [(b, a)]
+ groupBy :: (El a -> b) -> [(b, a)]
uniqueElement :: a -> El a // may fail
fromList :: [El a] -> a
toList :: a -> [El a]
foldl1 :: (El a -> El a -> <e> El a) -> a -> <e> a
foldr1 :: (El a -> El a -> <e> El a) -> a -> <e> a
- elem :: Eq (El a) => El a -> a -> Boolean
- elemIndex :: Eq (El a) => El a -> a -> Maybe Integer
- elemIndices :: Eq (El a) => El a -> a -> [Integer]
+ elem :: El a -> a -> Boolean
+ elemIndex :: El a -> a -> Maybe Integer
+ elemIndices :: El a -> a -> [Integer]
find :: (El a -> <e> Boolean) -> a -> <e> Maybe (El a)
findIndex :: (El a -> <e> Boolean) -> a -> <e> Maybe Integer
findIndices :: (El a -> <e> Boolean) -> a -> <e> [Integer]
"Get a component type of a composite data type"\r
@JavaName getComponentType\r
datatypeComponentType :: Datatype -> ChildReference -> Datatype\r
- \r
- @private\r
- @JavaName equals\r
- datatypeEquals :: Datatype -> Datatype -> Boolean \r
+\r
\r
instance Show Datatype where\r
show = showDatatype\r
\r
-instance Eq Datatype where\r
- (==) = datatypeEquals\r
-\r
/// Binding ///\r
\r
importJava "org.simantics.databoard.binding.Binding" where\r
@JavaName compare\r
compareObjects :: Serializable a => a -> a -> Integer\r
\r
- "Return true, if two serializable values are equal" \r
- @JavaName equals\r
- serializableEq :: Serializable a => a -> a -> Boolean\r
- \r
"The default value of a serializable type"\r
@JavaName createDefault\r
serializableDefaultValue :: Serializable a => a\r
@JavaName getComponentBinding\r
getComponentBinding :: Binding a -> ChildReference -> Binding b\r
\r
- @private\r
- @JavaName equals\r
- bindingEquals :: Binding a -> Binding a -> Boolean\r
- \r
-instance Eq (Binding a) where\r
- (==) = bindingEquals\r
-\r
"Get a child data component of a composite serializable value"\r
getSerializableComponent :: Serializable a => Serializable b => a -> ChildReference -> b\r
getSerializableComponent object ref = getSerializableComponent_ object ref binding\r
***********************************************************/
importJava "java.util.Arrays" where
- @private
- @JavaName equals
- equalsDoubleArray :: DoubleArray -> DoubleArray -> Boolean
-
@private
@JavaName toString
showDoubleArray :: DoubleArray -> String
@JavaName toArray
listToArray :: [a] -> Array a
-instance Eq DoubleArray where
- (==) = equalsDoubleArray
instance Show DoubleArray where
show = showDoubleArray
infixl 7 (*), (/), div, mod
infixl 6 (+), (-)
infixl 5 (\\), (<<), (<+)
-infix 4 (==), (!=), (<), (<=), (>=), (>)
+infix 4 (!=), (<), (<=), (>=), (>)
infixr 3 (&&), (&<&)
infixr 2 (||), orElse, morelse
infixr 1 (>>=), (>>), (:=)
/// Comparison ///
-"""
-The class of types whose elements can be compared for equality.
-Method `(==)` must be implemented in instances.
-"""
-class Eq a where
- "Equality"
- (==) :: a -> a -> Boolean
- "Inequality: `a != b = not (a == b)`"
- (!=) :: a -> a -> Boolean
-
- a != b = not (a == b)
+@inline
+(!=) :: a -> a -> Boolean
+a != b = not (a == b)
"""
The class of linearly ordered types.
Method `compare` must be implemented in instances.
"""
-class (Eq a) => Ord a where
+class Ord a where
"""
`compare x y` returns a negative number, if `x` is smaller than `y`,
a positive number, if `x` is bigger than `y` and zero if they are equal.
where
minF a b = if fst a <= fst b then a else b
-"""
-The class of types with method to compute hash codes.
-"""
-class (Eq a) => Hashable a where
- "`hashP v seed` computes the hash code of `v` using `seed` as a seed."
- hashP :: a -> Integer -> Integer
-
-"`hash v` computes the hash code of `v`"
-hash :: Hashable a => a -> Integer
-hash a = hashP a 1166136261
-
/// Functions ///
/*
instance Functor ((->) a) where
@JavaName parseByte
readByte :: String -> Byte
-instance Eq Byte where
- (==) = Java.bcmpeq
- (!=) = Java.bcmpne
-
instance Ord Byte where
(<) = Java.bcmplt
(<=) = Java.bcmple
@JavaName parseShort
readShort :: String -> Short
-instance Eq Short where
- (==) = Java.scmpeq
- (!=) = Java.scmpne
-
instance Ord Short where
(<) = Java.scmplt
(<=) = Java.scmple
@JavaName parseInt
readInteger :: String -> Integer
-instance Eq Integer where
- (==) = Java.icmpeq
- (!=) = Java.icmpne
-
instance Ord Integer where
(<) = Java.icmplt
(<=) = Java.icmple
(>) = Java.icmpgt
(>=) = Java.icmpge
-
-instance Hashable Integer where
- hashP v x = Java.ixor v (Java.imul x 16777619) // prime for FNV-1 hash
instance Additive Integer where
zero = Java.iconst_0
@JavaName parseLong
readLong :: String -> Long
-instance Eq Long where
- (==) = Java.lcmpeq
- (!=) = Java.lcmpne
-
instance Ord Long where
(<) = Java.lcmplt
(<=) = Java.lcmple
(>) = Java.lcmpgt
(>=) = Java.lcmpge
-
-instance Hashable Long where
- hashP v x = Java.l2i (Java.lxor v (Java.lushr v 32)) + x*16777619
instance Additive Long where
zero = Java.lconst_0
"Converts 32-bit floating point number to a 32-bit integer with the same byte level representation."
floatToIntBits :: Float -> Integer
-instance Eq Float where
- (==) = Java.fcmpeq
- (!=) = Java.fcmpne
-
instance Ord Float where
compare = compareFloat
(<) = Java.fcmplt
(>) = Java.fcmpgt
(>=) = Java.fcmpge
-instance Hashable Float where
- hashP v x = hashP (floatToIntBits v) x
-
instance Additive Float where
zero = Java.fconst_0
(+) = Java.fadd
isNaN :: Double -> Boolean
isInfinite :: Double -> Boolean
-instance Eq Double where
- (==) = Java.dcmpeq
- (!=) = Java.dcmpne
-
instance Ord Double where
compare = compareDouble
(<) = Java.dcmplt
(<=) = Java.dcmple
(>) = Java.dcmpgt
- (>=) = Java.dcmpge
-
-instance Hashable Double where
- hashP v x = hashP (doubleToLongBits v) x
+ (>=) = Java.dcmpge
instance Additive Double where
zero = Java.dconst_0
"Returns true, if the given character is a digit."
isDigit :: Character -> Boolean
-instance Eq Character where
- (==) = Java.ccmpeq
- (!=) = Java.ccmpne
-
instance Ord Character where
(<) = Java.ccmplt
(<=) = Java.ccmple
otherwise :: Boolean
otherwise = True
-instance Eq Boolean where
- a == b = if a then b else not b
- a != b = if a then not b else b
-
instance Ord Boolean where
compare False False = 0
compare False True = neg 1
fromJust :: Maybe a -> a
fromJust (Just a) = a
-deriving instance (Eq a) => Eq (Maybe a)
deriving instance (Ord a) => Ord (Maybe a)
deriving instance (Show a) => Show (Maybe a)
-deriving instance (Hashable a) => Hashable (Maybe a)
instance Functor Maybe where
fmap _ Nothing = Nothing
"""
data Either a b = Left a | Right b
-deriving instance (Eq a, Eq b) => Eq (Either a b)
deriving instance (Ord a, Ord b) => Ord (Either a b)
deriving instance (Show a, Show b) => Show (Either a b)
-deriving instance (Hashable a, Hashable b) => Hashable (Either a b)
instance Functor (Either a) where
fmap _ (Left x) = Left x
@JavaName "compareTo"
compareString :: String -> String -> Integer
@private
-// @JavaName "hashCode"
-// hashString :: String -> Integer
- @private
- @JavaName "equals"
- equalsString :: String -> String -> Boolean
- @private
@JavaName "length"
lengthString :: String -> Integer
@JavaName "<init>"
string :: Vector Character -> String
-instance Eq String where
- (==) = equalsString
-
-instance Hashable String where
- hashP x v = Java.hashCode x + v*16777619
-
instance Ord String where
compare = compareString
/// Tuple0 ///
-instance Eq () where
- () == () = True
-
instance Ord () where
compare () () = 0
-instance Hashable () where
- hashP () x = x
-
instance Additive () where
zero = ()
() + () = ()
snd :: (a,b) -> b
snd (x,y) = y
-instance (Eq a, Eq b) => Eq (a, b) where
- (a0, b0) == (a1, b1) = a0 == a1 && b0 == b1
-
instance (Ord a, Ord b) => Ord (a, b) where
compare (a0, b0) (a1, b1) = compare a0 a1 &<& compare b0 b1
-instance (Hashable a, Hashable b) => Hashable (a, b) where
- hashP (a,b) x = hashP b $ hashP a x
-
instance (Additive a, Additive b) => Additive (a, b) where
zero = (zero, zero)
(a0, b0) + (a1, b1) = (a0+a1, b0+b1)
/// Tuple3 ///
-instance (Eq a, Eq b, Eq c) => Eq (a, b, c) where
- (a0, b0, c0) == (a1, b1, c1) = a0 == a1 && b0 == b1 && c0 == c1
-
instance (Ord a, Ord b, Ord c) => Ord (a, b, c) where
compare (a0, b0, c0) (a1, b1, c1) = compare a0 a1 &<& compare b0 b1 &<& compare c0 c1
-instance (Hashable a, Hashable b, Hashable c) => Hashable (a, b, c) where
- hashP (a,b,c) x = hashP c $ hashP b $ hashP a x
-
instance (Additive a, Additive b, Additive c) => Additive (a, b, c) where
zero = (zero, zero, zero)
(a0, b0, c0) + (a1, b1, c1) = (a0+a1, b0+b1, c0+c1)
/// Tuple4 ///
-instance (Eq a, Eq b, Eq c, Eq d) => Eq (a, b, c, d) where
- (a0, b0, c0, d0) == (a1, b1, c1, d1) = a0 == a1 && b0 == b1 && c0 == c1 && d0 == d1
-
instance (Ord a, Ord b, Ord c, Ord d) => Ord (a, b, c, d) where
compare (a0, b0, c0, d0) (a1, b1, c1, d1) =
compare a0 a1 &<& compare b0 b1 &<& compare c0 c1 &<& compare d0 d1
-instance (Hashable a, Hashable b, Hashable c, Hashable d) => Hashable (a, b, c, d) where
- hashP (a,b,c,d) x = hashP d $ hashP c $ hashP b $ hashP a x
-
instance (Additive a, Additive b, Additive c, Additive d) => Additive (a, b, c, d) where
zero = (zero, zero, zero, zero)
(a0, b0, c0, d0) + (a1, b1, c1, d1) = (a0+a1, b0+b1, c0+c1, d0+d1)
/// Tuple5 ///
-instance (Eq a, Eq b, Eq c, Eq d, Eq e) => Eq (a, b, c, d, e) where
- (a0, b0, c0, d0, e0) == (a1, b1, c1, d1, e1) =
- a0 == a1 && b0 == b1 && c0 == c1 && d0 == d1 && e0 == e1
-
instance (Ord a, Ord b, Ord c, Ord d, Ord e) => Ord (a, b, c, d, e) where
compare (a0, b0, c0, d0, e0) (a1, b1, c1, d1, e1) =
compare a0 a1 &<& compare b0 b1 &<& compare c0 c1 &<& compare d0 d1 &<& compare e0 e1
-
-instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e)
- => Hashable (a, b, c, d, e) where
- hashP (a,b,c,d,e) x = hashP e $ hashP d $ hashP c $ hashP b $ hashP a x
instance (Additive a, Additive b, Additive c, Additive d, Additive e) => Additive (a, b, c, d, e) where
zero = (zero, zero, zero, zero, zero)
/// Lists ///
-instance (Eq a) => Eq [a] where
- a == b = lA == lB && loop 0
- where
- lA = length a
- lB = length b
- loop i = i>=lA || (a!i == b!i && loop (i+1))
-
instance (Ord a) => Ord [a] where
compare a b = loop 0
where
then 1
else compare (a!i) (b!i) &<& loop (i+1)
-instance (Hashable a) => Hashable [a] where
- hashP a x = loop 0 x
- where
- lA = length a
- loop i x = if i == lA
- then x
- else loop (i+1) (hashP (a!i) x)
-
instance Functor [] where
fmap = mapList
//build :: (forall a. a -> (a -> b -> <e> a) -> <e> a) -> <e> [b]
"`elem el lst` return true, if `el` occurs in the list `lst`."
-elem :: Eq a => a -> [a] -> Boolean
+elem :: a -> [a] -> Boolean
elem el l = loop 0
where
len = length l
| otherwise = False
"`elemMaybe v1 (Just v2)` returns true if `v1 == v2`. `elemMaybe v1 Nothing` is always false."
-elemMaybe :: Eq a => a -> Maybe a -> Boolean
+elemMaybe :: a -> Maybe a -> Boolean
elemMaybe el m = match m with
Just el2 -> el == el2
Nothing -> False
"""
Computes a list that contains only elements that belongs to both input lists.
"""
-intersect :: Eq a => [a] -> [a] -> [a]
+intersect :: [a] -> [a] -> [a]
intersect a b = filter f a
where
f e = elem e b
len = length l
"Tries to find the given key from the list of key-value pairs and returns the corresponding value."
-lookup :: Eq a => a -> [(a, b)] -> Maybe b
+lookup :: a -> [(a, b)] -> Maybe b
lookup el l = do
len = length l
loop i = if i < len
Given a list of key-value pairs, the function produces a function that finds a value
efficiently for the given key.
"""
-index :: Hashable a => [(a,b)] -> a -> Maybe b
-index = indexWith hash (==)
+index :: [(a,b)] -> a -> Maybe b
+index = indexWith hashCode (==)
"""
Given a list of values and a function computing a key for each value, the function produces a function that finds a value
effeciently for the given key.
"""
-indexBy :: Hashable b => (a -> b) -> [a] -> b -> Maybe a
+indexBy :: (a -> b) -> [a] -> b -> Maybe a
indexBy f l = index [(f x, x) | x <- l]
"Groups a list values by a key computed by the given function."
-groupBy :: Hashable b => (a -> <e> b) -> [a] -> <e> [(b, [a])]
-groupBy f l = groupWith hash (==) f id l
+groupBy :: (a -> <e> b) -> [a] -> <e> [(b, [a])]
+groupBy f l = groupWith hashCode (==) f id l
"Groups a list of key-value pairs by the keys."
-group :: Hashable a => [(a,b)] -> [(a, [b])]
-group = groupWith hash (==) fst snd
+group :: [(a,b)] -> [(a, [b])]
+group = groupWith hashCode (==) fst snd
"Removes duplicates (all but the first occurrence) from the list but otherwise preserves the order of the elements."
-unique :: Eq a => [a] -> [a]
+unique :: [a] -> [a]
unique = uniqueWith (==)
"Like `unique`, but uses the given function for finding the key values used for uniqueness testing."
-uniqueBy :: Eq b => (a -> b) -> [a] -> [a]
+uniqueBy :: (a -> b) -> [a] -> [a]
uniqueBy f = uniqueWith (\a b -> f a == f b)
//sortAndUniqueBy :: Ord b => (a -> b) -> [a] -> [a]
//sortAndUniqueBy f = map snd . uniqueWith (\a b -> fst a == fst b) . sortBy fst . map (\x -> (f x, x))
"`a \\\\ b` removes all elements of `b` from the list `a`."
-(\\) :: Eq a => [a] -> [a] -> [a]
+(\\) :: [a] -> [a] -> [a]
(\\) = deleteAllBy (==)
/// Dynamic ///
data SList a = Nil | Cons a (SList a)
-deriving instance (Eq a) => Eq (SList a)
deriving instance (Ord a) => Ord (SList a)
-deriving instance (Hashable a) => Hashable (SList a)
deriving instance (Show a) => Show (SList a)
@inline
mapFirstVector f v = mapFirstN (\i -> f (getVector v i)) (lengthVector v)
@inline
-containsVector :: Eq a => a -> Vector a -> Boolean
+containsVector :: a -> Vector a -> Boolean
containsVector x v = foldlN (\result i -> result || (v!i == x)) False (lengthVector v)
@inline
--- /dev/null
+/*\r
+ * Copyright 2014 the original author or authors.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package org.simantics.scl.runtime.chr;\r
+\r
+import static java.util.Arrays.binarySearch;\r
+\r
+import java.util.Arrays;\r
+\r
+/**\r
+ * This class is adapted from MutableQHashObjSetGO class generated by Koloboke library.\r
+ * It is used by code generated by SCL compiler.\r
+ */\r
+public class CHRHashIndex {\r
+\r
+ private static final double MIN_LOAD = 1.0 / 3.0;\r
+ private static final double MAX_LOAD = 2.0 / 3.0;\r
+ private static final double TARGET_LOAD = 0.5;\r
+ private static final double GROWTH_FACTOR = 2.0;\r
+ private static final int INITIAL_CAPACITY = 10;\r
+\r
+ private static final Object REMOVED = new Object();\r
+ private static final Object FREE = null;\r
+\r
+ ////////////////////////////\r
+ // Fields\r
+\r
+ /** The current number of occupied slots in the hash. */\r
+ private int size;\r
+\r
+ private int maxSize;\r
+\r
+ /** The current number of free slots in the hash. */\r
+ private int freeSlots;\r
+\r
+ private int minFreeSlots;\r
+\r
+ private int removedSlots;\r
+\r
+ private Object[] set;\r
+\r
+ private static int mix(int hash) {\r
+ return hash & Integer.MAX_VALUE;\r
+ }\r
+\r
+ private boolean noRemoved() {\r
+ return removedSlots == 0;\r
+ }\r
+\r
+ /**\r
+ * Creates data structures with a prime capacity at or near the minimum\r
+ * needed to hold {@code size} elements without triggering a rehash.\r
+ *\r
+ * <p>Should be called only in constructors and externalization code.\r
+ */\r
+ private void init(int size) {\r
+ this.size = 0;\r
+ internalInit(targetCapacity(size));\r
+ }\r
+\r
+ private void internalInit(int capacity) {\r
+ initSlotCounts(capacity);\r
+ allocateArrays(capacity);\r
+ }\r
+\r
+ private void initSlotCounts(int capacity) {\r
+ // No sense in trying to rehash after each insertion\r
+ // if the capacity is already reached the limit.\r
+ maxSize = !isMaxCapacity(capacity) ? maxSize(capacity) : capacity - 1;\r
+ minFreeSlots = minFreeSlots(capacity, size, MAX_LOAD, maxSize);\r
+ int freeSlots = this.freeSlots = capacity - size;\r
+ // free could be less than minFreeSlots only in case when capacity\r
+ // is not sufficient to comply load factor (due to saturation with\r
+ // Java array size limit). Set minFreeSlots to a half of free to avoid\r
+ // too often (instant) rehashing in this case.\r
+ if (freeSlots < minFreeSlots) this.minFreeSlots = (freeSlots + 1) / 2;\r
+ removedSlots = 0;\r
+ }\r
+\r
+ private static int minFreeSlots(int capacity, int size, double maxLoad, int maxSize) {\r
+ double load = (double) size / (double) capacity;\r
+ // See "Tombstones purge from hashtable: theory and practice" wiki page\r
+ double rehashLoad =\r
+ 0.55 + 0.721 * load - 0.274 * load * load;\r
+\r
+ int minFreeSlots;\r
+ // minFreeSlots shouldn't be less than `capacity - maxSize`\r
+ if (rehashLoad > maxLoad) {\r
+ minFreeSlots = (int) ((double) capacity * (1.0 - rehashLoad));\r
+ } else {\r
+ minFreeSlots = capacity - maxSize;\r
+ }\r
+ // Need at least one free slot for open addressing\r
+ return minFreeSlots > 0 ? minFreeSlots : 1;\r
+ }\r
+\r
+ /////////////////////////////\r
+ // Modification hooks and rehash logic\r
+\r
+ public boolean shrink() {\r
+ int newCapacity = targetCapacity(size);\r
+ if (removedSlots > 0 || newCapacity < set.length) {\r
+ rehash(newCapacity);\r
+ return true;\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ private boolean tryRehashForExpansion(int newCapacity) {\r
+ // No sense in rehashing for expansion if we already reached Java array\r
+ // size limit.\r
+ if (newCapacity > set.length || removedSlots > 0) {\r
+ rehash(newCapacity);\r
+ return true;\r
+ } else {\r
+ if (freeSlots < minFreeSlots)\r
+ minFreeSlots = (freeSlots + 1) / 2;\r
+ return false;\r
+ }\r
+ }\r
+\r
+ public boolean ensureCapacity(long minSize) {\r
+ int intMinSize = (int) Math.min(minSize, (long) Integer.MAX_VALUE);\r
+ if (minSize < 0L)\r
+ throw new IllegalArgumentException(\r
+ "Min size should be positive, " + minSize + " given.");\r
+ int additionalSize = intMinSize - size;\r
+ if (additionalSize <= 0)\r
+ return false;\r
+ if (intMinSize > maxSize || freeSlots - additionalSize < minFreeSlots) {\r
+ return tryRehashForExpansion(targetCapacity(intMinSize));\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ private void postRemoveHook() {\r
+ size--;\r
+ removedSlots++;\r
+ }\r
+\r
+ private void postFreeSlotInsertHook() {\r
+ if (++size > maxSize) {\r
+ if (tryRehashForExpansion(grownCapacity()))\r
+ return;\r
+ }\r
+ if (--freeSlots < minFreeSlots) {\r
+ if (!tryRehashIfTooFewFreeSlots() && freeSlots == 0) {\r
+ throw new CHRHashOverflowException();\r
+ }\r
+ }\r
+ }\r
+\r
+ private void postRemovedSlotInsertHook() {\r
+ if (++size > maxSize) {\r
+ if (tryRehashForExpansion(grownCapacity()))\r
+ return;\r
+ }\r
+ removedSlots--;\r
+ }\r
+\r
+ private boolean tryRehashIfTooFewFreeSlots() {\r
+ if (removedSlots > 0) {\r
+ rehash(targetCapacity(size));\r
+ return true;\r
+ } else {\r
+ return tryRehashForExpansion(grownCapacity());\r
+ }\r
+ }\r
+\r
+ /** For initial hash table construction and rehash to target load (shrink, tombstones purge). */\r
+ private int targetCapacity(int size) {\r
+ return capacity(size, targetLoadInverse.scaleUpper(size));\r
+ }\r
+ \r
+ /** The highest qHash prime below Integer.MAX_VALUE (which is a qHash prime too). */\r
+ private static final int MAX_INT_CAPACITY = 2147483587;\r
+\r
+\r
+ private boolean isMaxCapacity(int capacity) {\r
+ return capacity >= MAX_INT_CAPACITY;\r
+ }\r
+\r
+ private int grownCapacity() {\r
+ return nearestGreaterCapacity(grow(set.length), size);\r
+ }\r
+\r
+ protected boolean keyEquals(Object a, Object b) {\r
+ return a.equals(b);\r
+ }\r
+\r
+ protected int keyHashCode(Object key) {\r
+ return key.hashCode();\r
+ }\r
+\r
+\r
+ public boolean contains(Object key) {\r
+ return index(key) >= 0;\r
+ }\r
+\r
+ private int index(Object key) {\r
+ // noinspection unchecked\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ Object cur;\r
+ if ((cur = keys[index = mix(keyHashCode(key)) % (capacity = keys.length)]) == key) {\r
+ // key is present\r
+ return index;\r
+ } else {\r
+ if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return -1;\r
+ } else {\r
+ if (cur != REMOVED) {\r
+ if (keyEquals(key, cur)) {\r
+ // key is present\r
+ return index;\r
+ } else {\r
+ if (noRemoved()) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == key) {\r
+ // key is present\r
+ return bIndex;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return -1;\r
+ }\r
+ else if (keyEquals(key, cur)) {\r
+ // key is present\r
+ return bIndex;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == key) {\r
+ // key is present\r
+ return fIndex;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return -1;\r
+ }\r
+ else if (keyEquals(key, cur)) {\r
+ // key is present\r
+ return fIndex;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == key) {\r
+ // key is present\r
+ return bIndex;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return -1;\r
+ }\r
+ else if (cur != REMOVED && keyEquals(key, cur)) {\r
+ // key is present\r
+ return bIndex;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == key) {\r
+ // key is present\r
+ return fIndex;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return -1;\r
+ }\r
+ else if (cur != REMOVED && keyEquals(key, cur)) {\r
+ // key is present\r
+ return fIndex;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private void allocateArrays(int capacity) {\r
+ set = new Object[capacity];\r
+ // not necessary because FREE = null\r
+ // Arrays.fill(set, FREE);\r
+ }\r
+\r
+\r
+ public Object[] toArray() {\r
+ Object[] result = new Object[size];\r
+ if (size == 0)\r
+ return result;\r
+ int resultIndex = 0;\r
+ Object[] keys = set;\r
+ if (noRemoved()) {\r
+ for (int i = keys.length - 1; i >= 0; i--) {\r
+ Object key;\r
+ // noinspection unchecked\r
+ if ((key = keys[i]) != FREE) {\r
+ result[resultIndex++] = key;\r
+ }\r
+ }\r
+ } else {\r
+ for (int i = keys.length - 1; i >= 0; i--) {\r
+ Object key;\r
+ // noinspection unchecked\r
+ if ((key = keys[i]) != FREE && key != REMOVED) {\r
+ result[resultIndex++] = key;\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ public <T> T[] toArray(T[] a) {\r
+ if (a.length < size) {\r
+ Class<?> elementType = a.getClass().getComponentType();\r
+ a = (T[]) java.lang.reflect.Array.newInstance(elementType, size);\r
+ }\r
+ if (size == 0) {\r
+ if (a.length > 0)\r
+ a[0] = null;\r
+ return a;\r
+ }\r
+ int resultIndex = 0;\r
+ Object[] keys = set;\r
+ if (noRemoved()) {\r
+ for (int i = keys.length - 1; i >= 0; i--) {\r
+ Object key;\r
+ // noinspection unchecked\r
+ if ((key = keys[i]) != FREE) {\r
+ a[resultIndex++] = (T) key;\r
+ }\r
+ }\r
+ } else {\r
+ for (int i = keys.length - 1; i >= 0; i--) {\r
+ Object key;\r
+ // noinspection unchecked\r
+ if ((key = keys[i]) != FREE && key != REMOVED) {\r
+ a[resultIndex++] = (T) key;\r
+ }\r
+ }\r
+ }\r
+ if (a.length > resultIndex)\r
+ a[resultIndex] = null;\r
+ return a;\r
+ }\r
+\r
+ private void rehash(int newCapacity) {\r
+ Object[] keys = set;\r
+ int removedSlots = this.removedSlots;\r
+ internalInit(newCapacity);\r
+ Object[] newKeys = set;\r
+ int capacity = newKeys.length;\r
+ if (removedSlots == 0) {\r
+ for (int i = keys.length - 1; i >= 0; i--) {\r
+ Object key;\r
+ // noinspection unchecked\r
+ if ((key = keys[i]) != FREE) {\r
+ int index;\r
+ if (newKeys[index = mix(keyHashCode(key)) % capacity] != FREE) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if (newKeys[bIndex] == FREE) {\r
+ index = bIndex;\r
+ break;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if (newKeys[fIndex] == FREE) {\r
+ index = fIndex;\r
+ break;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ newKeys[index] = key;\r
+ }\r
+ }\r
+ } else {\r
+ for (int i = keys.length - 1; i >= 0; i--) {\r
+ Object key;\r
+ // noinspection unchecked\r
+ if ((key = keys[i]) != FREE && key != REMOVED) {\r
+ int index;\r
+ if (newKeys[index = mix(keyHashCode(key)) % capacity] != FREE) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if (newKeys[bIndex] == FREE) {\r
+ index = bIndex;\r
+ break;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if (newKeys[fIndex] == FREE) {\r
+ index = fIndex;\r
+ break;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ newKeys[index] = key;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ public void clear() {\r
+ size = 0;\r
+ freeSlots = set.length;\r
+ removedSlots = 0;\r
+ Arrays.fill(set, FREE);\r
+ }\r
+\r
+\r
+ public CHRHashIndex() {\r
+ init(INITIAL_CAPACITY);\r
+ }\r
+\r
+ public boolean add(Object key) {\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ Object cur;\r
+ keyAbsentFreeSlot:\r
+ if ((cur = keys[index = mix(keyHashCode(key)) % (capacity = keys.length)]) != FREE) {\r
+ if (cur == key) {\r
+ // key is present\r
+ return false;\r
+ } else {\r
+ int firstRemoved;\r
+ if (cur != REMOVED) {\r
+ if (!keyEquals(key, cur)) {\r
+ if (noRemoved()) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE) {\r
+ index = bIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else if (cur == key || (keyEquals(key, cur))) {\r
+ // key is present\r
+ return false;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE) {\r
+ index = fIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else if (cur == key || (keyEquals(key, cur))) {\r
+ // key is present\r
+ return false;\r
+ }\r
+ step += 2;\r
+ }\r
+ } else {\r
+ firstRemoved = -1;\r
+ }\r
+ } else {\r
+ // key is present\r
+ return false;\r
+ }\r
+ } else {\r
+ firstRemoved = index;\r
+ }\r
+ keyAbsentRemovedSlot: {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE) {\r
+ if (firstRemoved < 0) {\r
+ index = bIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else {\r
+ break keyAbsentRemovedSlot;\r
+ }\r
+ } else if (cur == key) {\r
+ // key is present\r
+ return false;\r
+ } else if (cur != REMOVED) {\r
+ if (keyEquals(key, cur)) {\r
+ // key is present\r
+ return false;\r
+ }\r
+ } else if (firstRemoved < 0) {\r
+ firstRemoved = bIndex;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE) {\r
+ if (firstRemoved < 0) {\r
+ index = fIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else {\r
+ break keyAbsentRemovedSlot;\r
+ }\r
+ } else if (cur == key) {\r
+ // key is present\r
+ return false;\r
+ } else if (cur != REMOVED) {\r
+ if (keyEquals(key, cur)) {\r
+ // key is present\r
+ return false;\r
+ }\r
+ } else if (firstRemoved < 0) {\r
+ firstRemoved = fIndex;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ // key is absent, removed slot\r
+ keys[firstRemoved] = key;\r
+ postRemovedSlotInsertHook();\r
+ return true;\r
+ }\r
+ }\r
+ // key is absent, free slot\r
+ keys[index] = key;\r
+ postFreeSlotInsertHook();\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Assumes that the given value doesn't already exist in the index\r
+ * (only optimized with this assumption, the method works correctly\r
+ * even if the assumption does not hold).\r
+ * Returns the old equal element that the given value replaces or\r
+ * null if there is no such elements.\r
+ */\r
+ public Object addFreshAndReturnOld(Object key) {\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ Object cur;\r
+ keyAbsentFreeSlot: if ((cur = keys[index = mix(keyHashCode(key)) % (capacity = keys.length)]) != FREE) {\r
+ int firstRemoved;\r
+ if (cur != REMOVED) {\r
+ if (!keyEquals(key, cur)) {\r
+ if (noRemoved()) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE) {\r
+ index = bIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else if (keyEquals(key, cur)) {\r
+ keys[bIndex] = key;\r
+ return cur;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE) {\r
+ index = fIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else if (keyEquals(key, cur)) {\r
+ keys[fIndex] = key;\r
+ return cur;\r
+ }\r
+ step += 2;\r
+ }\r
+ } else {\r
+ firstRemoved = -1;\r
+ }\r
+ } else {\r
+ keys[index] = key;\r
+ return cur;\r
+ }\r
+ } else {\r
+ firstRemoved = index;\r
+ }\r
+ keyAbsentRemovedSlot: {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE) {\r
+ if (firstRemoved < 0) {\r
+ index = bIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else {\r
+ break keyAbsentRemovedSlot;\r
+ }\r
+ } else if (cur != REMOVED) {\r
+ if (keyEquals(key, cur)) {\r
+ keys[bIndex] = key;\r
+ return cur;\r
+ }\r
+ } else if (firstRemoved < 0) {\r
+ firstRemoved = bIndex;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE) {\r
+ if (firstRemoved < 0) {\r
+ index = fIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else {\r
+ break keyAbsentRemovedSlot;\r
+ }\r
+ } else if (cur != REMOVED) {\r
+ if (keyEquals(key, cur)) {\r
+ keys[fIndex] = key;\r
+ return cur;\r
+ }\r
+ } else if (firstRemoved < 0) {\r
+ firstRemoved = fIndex;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ // key is absent, removed slot\r
+ keys[firstRemoved] = key;\r
+ postRemovedSlotInsertHook();\r
+ return null;\r
+ }\r
+ // key is absent, free slot\r
+ keys[index] = key;\r
+ postFreeSlotInsertHook();\r
+ return null;\r
+ }\r
+ \r
+ public Object addFreshAndReturnOldNoRemovals(Object key) {\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ Object cur;\r
+ keyAbsentFreeSlot: if ((cur = keys[index = mix(keyHashCode(key)) % (capacity = keys.length)]) != FREE) {\r
+ if (!keyEquals(key, cur)) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE) {\r
+ index = bIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else if (keyEquals(key, cur)) {\r
+ keys[bIndex] = key;\r
+ return cur;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE) {\r
+ index = fIndex;\r
+ break keyAbsentFreeSlot;\r
+ } else if (keyEquals(key, cur)) {\r
+ keys[fIndex] = key;\r
+ return cur;\r
+ }\r
+ step += 2;\r
+ }\r
+ } else {\r
+ keys[index] = key;\r
+ return cur;\r
+ }\r
+ }\r
+ // key is absent, free slot\r
+ keys[index] = key;\r
+ postFreeSlotInsertHook();\r
+ return null;\r
+ }\r
+\r
+ public boolean remove(Object key) {\r
+ // noinspection unchecked\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ Object cur;\r
+ keyPresent:\r
+ if ((cur = keys[index = mix(keyHashCode(key)) % (capacity = keys.length)]) != key) {\r
+ if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return false;\r
+ } else {\r
+ if (cur != REMOVED) {\r
+ if (keyEquals(key, cur)) {\r
+ break keyPresent;\r
+ } else {\r
+ if (noRemoved()) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == key) {\r
+ index = bIndex;\r
+ break keyPresent;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return false;\r
+ }\r
+ else if (keyEquals(key, cur)) {\r
+ index = bIndex;\r
+ break keyPresent;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == key) {\r
+ index = fIndex;\r
+ break keyPresent;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return false;\r
+ }\r
+ else if (keyEquals(key, cur)) {\r
+ index = fIndex;\r
+ break keyPresent;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == key) {\r
+ index = bIndex;\r
+ break keyPresent;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return false;\r
+ }\r
+ else if (cur != REMOVED && keyEquals(key, cur)) {\r
+ index = bIndex;\r
+ break keyPresent;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == key) {\r
+ index = fIndex;\r
+ break keyPresent;\r
+ } else if (cur == FREE) {\r
+ // key is absent, free slot\r
+ return false;\r
+ }\r
+ else if (cur != REMOVED && keyEquals(key, cur)) {\r
+ index = fIndex;\r
+ break keyPresent;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ }\r
+ // key is present\r
+ keys[index] = REMOVED;\r
+ postRemoveHook();\r
+ return true;\r
+ }\r
+ \r
+ /**\r
+ * Assumes that the key exists in the index. Removes it.\r
+ */\r
+ public void removeKnownToExistKey(Object key) {\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ keyPresent: if (keys[index = mix(keyHashCode(key)) % (capacity = keys.length)] != key) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if (keys[bIndex] == key) {\r
+ index = bIndex;\r
+ break keyPresent;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if (keys[fIndex] == key) {\r
+ index = fIndex;\r
+ break keyPresent;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ keys[index] = REMOVED;\r
+ postRemoveHook();\r
+ }\r
+ \r
+ /**\r
+ * Assumes that the key exists in the index. Replaces it with an equal key.\r
+ */\r
+ public void replaceKnownToExistKey(Object key, Object replacement) {\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ keyPresent: if (keys[index = mix(keyHashCode(key)) % (capacity = keys.length)] != key) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if (keys[bIndex] == key) {\r
+ index = bIndex;\r
+ break keyPresent;\r
+ }\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if (keys[fIndex] == key) {\r
+ index = fIndex;\r
+ break keyPresent;\r
+ }\r
+ step += 2;\r
+ }\r
+ }\r
+ keys[index] = replacement;\r
+ }\r
+\r
+ public Object getEqual(Object key) {\r
+ // noinspection unchecked\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ Object cur;\r
+ if ((cur = keys[index = mix(keyHashCode(key)) % (capacity = keys.length)]) == FREE)\r
+ return null;\r
+ if (cur != REMOVED) {\r
+ if (keyEquals(key, cur))\r
+ return cur;\r
+ if (noRemoved()) {\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE)\r
+ return null;\r
+ else if (keyEquals(key, cur))\r
+ return cur;\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE)\r
+ return null;\r
+ else if (keyEquals(key, cur))\r
+ return cur;\r
+ step += 2;\r
+ }\r
+ }\r
+ }\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE)\r
+ return null;\r
+ else if (cur != REMOVED && keyEquals(key, cur))\r
+ return cur;\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE)\r
+ return null;\r
+ else if (cur != REMOVED && keyEquals(key, cur))\r
+ return cur;\r
+ step += 2;\r
+ }\r
+ }\r
+\r
+ public Object getEqualNoRemovals(Object key) {\r
+ Object[] keys = set;\r
+ int capacity, index;\r
+ Object cur;\r
+ if ((cur = keys[index = mix(keyHashCode(key)) % (capacity = keys.length)]) == FREE)\r
+ return null;\r
+ if (keyEquals(key, cur))\r
+ return cur;\r
+ int bIndex = index, fIndex = index, step = 1;\r
+ while (true) {\r
+ if ((bIndex -= step) < 0) bIndex += capacity;\r
+ if ((cur = keys[bIndex]) == FREE)\r
+ return null;\r
+ else if (keyEquals(key, cur))\r
+ return cur;\r
+ int t;\r
+ if ((t = (fIndex += step) - capacity) >= 0) fIndex = t;\r
+ if ((cur = keys[fIndex]) == FREE)\r
+ return null;\r
+ else if (keyEquals(key, cur))\r
+ return cur;\r
+ step += 2;\r
+ }\r
+ }\r
+ \r
+ private static final Scaler minLoadInverse = Scaler.by(1.0 / MIN_LOAD);\r
+ private static final Scaler targetLoadInverse = Scaler.by(1.0 / TARGET_LOAD);\r
+ private static final Scaler maxLoad = Scaler.by(MAX_LOAD);\r
+ private static final Scaler maxLoadInverse = Scaler.by(1.0 / MAX_LOAD);\r
+ private static final Scaler growthFactor = Scaler.by(GROWTH_FACTOR);\r
+\r
+ /**\r
+ * Computes hash table capacity for the given size and min load of this config.\r
+ *\r
+ * @param size size of the hash table to compute capacity for\r
+ * @return if the given size is non-negative, returns the least int capacity such that\r
+ * size / capacity < {@code config().getMinLoad()}, or {@code Integer.MAX_VALUE}\r
+ * if there is no such capacity. If size is negative, result is undefined.\r
+ */\r
+ private static int maxCapacity(int size) {\r
+ return minLoadInverse.scaleUpper(size);\r
+ }\r
+\r
+ /**\r
+ * Computes hash table capacity for the given size and max load of this config.\r
+ *\r
+ * @param size size of the hash table to compute capacity for\r
+ * @return if the given size is non-negative, returns the least int capacity such that\r
+ * size / capacity < {@code config().getMaxLoad()}, or {@code Integer.MAX_VALUE}\r
+ * if there is no such capacity. If size is negative, result is undefined.\r
+ */\r
+ private static int minCapacity(int size) {\r
+ return maxLoadInverse.scaleUpper(size);\r
+ }\r
+\r
+ private static int maxSize(int capacity) {\r
+ return maxLoad.scaleLower(capacity);\r
+ }\r
+\r
+ /**\r
+ * Computes grown hash table capacity for the given capacity and growth factor of this config.\r
+ *\r
+ * @param capacity capacity of the hash table to grow\r
+ * @return if the given capacity is non-negative, returns the least int capacity\r
+ * such that |new capacity - the given capacity * {@code config().getGrowthFactor()}| <\r
+ * 1, or {@code Integer.MAX_VALUE} if there is no such capacity.\r
+ * If the given capacity is negative, result is undefined.\r
+ */\r
+ private static int grow(int capacity) {\r
+ return growthFactor.scaleLower(capacity);\r
+ }\r
+ \r
+ /**\r
+ * Chooses lesser or greater capacity, which one is better for the given {@code size} and\r
+ * hash config. (The {@code desiredCapacity} is just precomputed\r
+ * {@code conf.targetCapacity(size)}).\r
+ *\r
+ * <p>Chooses the capacity which is closer to the {@code desiredCapacity} and conform min or\r
+ * max capacity bounds for the given {@code size} and hash config.\r
+ *\r
+ * <p>If both {@code lesserCapacity} and {@code greaterCapacity} are out of these bounds,\r
+ * {@code onFail} value is returned.\r
+ *\r
+ * @param conf the {@code HashConfigWrapper}\r
+ * @param size should be non-negative\r
+ * @param desiredCapacity precomputed {@code conf.targetCapacity(size)}\r
+ * @param lesserCapacity should be greater than the {@code size} but lesser\r
+ * than the {@code desiredCapacity}\r
+ * @param greaterCapacity should be greater than the {@code desiredCapacity}\r
+ * @param onFail the value to return if both {@code lesserCapacity} and {@code greaterCapacity}\r
+ * are lesser than min size and greater than max size respectively\r
+ * for the given hash config and size\r
+ * @return {@code lesserCapacity} or {@code greaterCapacity}\r
+ * @see #chooseBetter(HashConfigWrapper, long, long, long, long, long)\r
+ */\r
+ private static int chooseBetter(int size,\r
+ int desiredCapacity, int lesserCapacity, int greaterCapacity, int onFail) {\r
+ assert 0 <= size;\r
+ assert size < lesserCapacity && lesserCapacity < desiredCapacity;\r
+ assert desiredCapacity < greaterCapacity;\r
+ if (greaterCapacity - desiredCapacity <= desiredCapacity - lesserCapacity &&\r
+ greaterCapacity <= maxCapacity(size)) {\r
+ return greaterCapacity;\r
+ }\r
+ return lesserCapacity >= minCapacity(size) ? lesserCapacity : onFail;\r
+ }\r
+ \r
+ private static int capacity(int size, int desiredCapacity) {\r
+ int lesserCapacity, greaterCapacity;\r
+ if (desiredCapacity <= MAX_LOOKUP_CAPACITY) {\r
+ int smallTableIndex = SMALL_LOOKUP_TABLE_INDICES[desiredCapacity];\r
+ greaterCapacity = SMALL_LOOKUP_TABLE_CAPACITIES[smallTableIndex];\r
+ if (greaterCapacity == desiredCapacity || smallTableIndex == 0)\r
+ return greaterCapacity;\r
+ lesserCapacity = SMALL_LOOKUP_TABLE_CAPACITIES[smallTableIndex - 1];\r
+ }\r
+ else if (desiredCapacity <= MAX_REGULAR_CHAR_CAPACITY) {\r
+ int capIndex = binarySearch(REGULAR_CHAR_CAPACITIES, (char) desiredCapacity);\r
+ if (capIndex >= 0) // desiredCapacity is found in REGULAR_CHAR_CAPACITIES\r
+ return desiredCapacity;\r
+ capIndex = ~capIndex;\r
+ lesserCapacity = capIndex > 0 ?\r
+ (int) REGULAR_CHAR_CAPACITIES[capIndex - 1] : MAX_LOOKUP_CAPACITY;\r
+ greaterCapacity = REGULAR_CHAR_CAPACITIES[capIndex];\r
+ }\r
+ else if (desiredCapacity <= MAX_REGULAR_INT_CAPACITY) {\r
+ int capIndex = binarySearch(REGULAR_INT_CAPACITIES, desiredCapacity);\r
+ if (capIndex >= 0) // desiredCapacity is found in REGULAR_INT_CAPACITIES\r
+ return desiredCapacity;\r
+ capIndex = ~capIndex;\r
+ lesserCapacity = capIndex > 0 ?\r
+ REGULAR_INT_CAPACITIES[capIndex - 1] : MAX_REGULAR_CHAR_CAPACITY;\r
+ greaterCapacity = REGULAR_INT_CAPACITIES[capIndex];\r
+ }\r
+ else {\r
+ // Since size could be virtual (expected), don't prematurely throw\r
+ // HashOverflowException. If sizes near to Integer.MAX_VALUE is the case,\r
+ // version accepting long size should be used.\r
+ return MAX_INT_CAPACITY;\r
+ }\r
+ return chooseBetter(size, desiredCapacity, lesserCapacity, greaterCapacity,\r
+ greaterCapacity);\r
+ }\r
+\r
+ /** For grow rehash. */\r
+ private static int nearestGreaterCapacity(int desiredCapacity, int currentSize) {\r
+ assert currentSize >= 0 : "currentSize must be non-negative";\r
+ if (desiredCapacity <= MAX_LOOKUP_CAPACITY)\r
+ return SMALL_LOOKUP_TABLE_CAPACITIES[SMALL_LOOKUP_TABLE_INDICES[desiredCapacity]];\r
+ if (desiredCapacity <= MAX_REGULAR_CHAR_CAPACITY) {\r
+ int capIndex = binarySearch(REGULAR_CHAR_CAPACITIES, (char) desiredCapacity);\r
+ // capIndex >= 0 => desiredCapacity IS a regular capacity\r
+ return capIndex < 0 ? REGULAR_CHAR_CAPACITIES[~capIndex] : desiredCapacity;\r
+ }\r
+ final boolean simpleArrays = true;\r
+ if (desiredCapacity <= MAX_REGULAR_INT_CAPACITY) {\r
+ int capIndex = binarySearch(REGULAR_INT_CAPACITIES, desiredCapacity);\r
+ return capIndex < 0 ? REGULAR_INT_CAPACITIES[~capIndex] : desiredCapacity;\r
+ }\r
+ int maxCapacity = MAX_INT_CAPACITY;\r
+ // overflow-aware\r
+ if (currentSize - maxCapacity < 0)\r
+ return maxCapacity;\r
+ if (simpleArrays && currentSize - Integer.MAX_VALUE < 0) {\r
+ // Integer.MAX_VALUE is also a qHash prime, but likely will cause OutOfMemoryError\r
+ return Integer.MAX_VALUE;\r
+ } else {\r
+ // QHash must have at least 1 free slot\r
+ throw new CHRHashOverflowException();\r
+ }\r
+ }\r
+\r
+ private static final char[] SMALL_LOOKUP_TABLE_CAPACITIES = new char[] {\r
+ 7, 11, 19, 23, 31, 43, 47, 59, 67, 71,\r
+ 79, 83, 103, 107, 127, 131, 139, 151, 163, 167,\r
+ 179, 191, 199, 211, 223, 227, 239, 251, 263, 271,\r
+ 283, 307, 311, 331, 347, 359, 367, 379, 383, 419,\r
+ 431, 439, 443, 463, 467, 479, 487, 491, 499, 503,\r
+ 523, 547, 563, 571, 587, 599, 607, 619, 631, 643,\r
+ 647, 659, 683, 691, 719, 727, 739, 743, 751, 787,\r
+ 811, 823, 827, 839, 859, 863, 883, 887, 907, 911,\r
+ 919, 947, 967, 971, 983, 991, 1019\r
+ };\r
+\r
+ private static final byte[] SMALL_LOOKUP_TABLE_INDICES = new byte[] {\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,\r
+ 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,\r
+ 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,\r
+ 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,\r
+ 5, 5, 5, 5, 6, 6, 6, 6, 7, 7,\r
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
+ 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,\r
+ 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,\r
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,\r
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\r
+ 12, 12, 12, 12, 13, 13, 13, 13, 14, 14,\r
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\r
+ 14, 14, 14, 14, 14, 14, 14, 14, 15, 15,\r
+ 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,\r
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\r
+ 17, 17, 18, 18, 18, 18, 18, 18, 18, 18,\r
+ 18, 18, 18, 18, 19, 19, 19, 19, 20, 20,\r
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\r
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\r
+ 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,\r
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\r
+ 23, 23, 24, 24, 24, 24, 24, 24, 24, 24,\r
+ 24, 24, 24, 24, 25, 25, 25, 25, 26, 26,\r
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\r
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\r
+ 27, 27, 28, 28, 28, 28, 28, 28, 28, 28,\r
+ 28, 28, 28, 28, 29, 29, 29, 29, 29, 29,\r
+ 29, 29, 30, 30, 30, 30, 30, 30, 30, 30,\r
+ 30, 30, 30, 30, 31, 31, 31, 31, 31, 31,\r
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,\r
+ 31, 31, 31, 31, 31, 31, 31, 31, 32, 32,\r
+ 32, 32, 33, 33, 33, 33, 33, 33, 33, 33,\r
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,\r
+ 33, 33, 34, 34, 34, 34, 34, 34, 34, 34,\r
+ 34, 34, 34, 34, 34, 34, 34, 34, 35, 35,\r
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,\r
+ 36, 36, 36, 36, 36, 36, 36, 36, 37, 37,\r
+ 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,\r
+ 38, 38, 38, 38, 39, 39, 39, 39, 39, 39,\r
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,\r
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,\r
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,\r
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\r
+ 40, 40, 41, 41, 41, 41, 41, 41, 41, 41,\r
+ 42, 42, 42, 42, 43, 43, 43, 43, 43, 43,\r
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,\r
+ 43, 43, 43, 43, 44, 44, 44, 44, 45, 45,\r
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,\r
+ 46, 46, 46, 46, 46, 46, 46, 46, 47, 47,\r
+ 47, 47, 48, 48, 48, 48, 48, 48, 48, 48,\r
+ 49, 49, 49, 49, 50, 50, 50, 50, 50, 50,\r
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,\r
+ 50, 50, 50, 50, 51, 51, 51, 51, 51, 51,\r
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,\r
+ 51, 51, 51, 51, 51, 51, 51, 51, 52, 52,\r
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,\r
+ 52, 52, 52, 52, 53, 53, 53, 53, 53, 53,\r
+ 53, 53, 54, 54, 54, 54, 54, 54, 54, 54,\r
+ 54, 54, 54, 54, 54, 54, 54, 54, 55, 55,\r
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,\r
+ 56, 56, 56, 56, 56, 56, 56, 56, 57, 57,\r
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,\r
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,\r
+ 58, 58, 59, 59, 59, 59, 59, 59, 59, 59,\r
+ 59, 59, 59, 59, 60, 60, 60, 60, 61, 61,\r
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,\r
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,\r
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,\r
+ 62, 62, 62, 62, 63, 63, 63, 63, 63, 63,\r
+ 63, 63, 64, 64, 64, 64, 64, 64, 64, 64,\r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,\r
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,\r
+ 65, 65, 65, 65, 65, 65, 65, 65, 66, 66,\r
+ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,\r
+ 67, 67, 67, 67, 68, 68, 68, 68, 68, 68,\r
+ 68, 68, 69, 69, 69, 69, 69, 69, 69, 69,\r
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,\r
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,\r
+ 69, 69, 69, 69, 69, 69, 69, 69, 70, 70,\r
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,\r
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,\r
+ 70, 70, 71, 71, 71, 71, 71, 71, 71, 71,\r
+ 71, 71, 71, 71, 72, 72, 72, 72, 73, 73,\r
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,\r
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,\r
+ 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,\r
+ 75, 75, 75, 75, 76, 76, 76, 76, 76, 76,\r
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,\r
+ 76, 76, 76, 76, 77, 77, 77, 77, 78, 78,\r
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,\r
+ 78, 78, 78, 78, 78, 78, 78, 78, 79, 79,\r
+ 79, 79, 80, 80, 80, 80, 80, 80, 80, 80,\r
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,\r
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,\r
+ 81, 81, 81, 81, 81, 81, 81, 81, 82, 82,\r
+ 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,\r
+ 82, 82, 82, 82, 82, 82, 82, 82, 83, 83,\r
+ 83, 83, 84, 84, 84, 84, 84, 84, 84, 84,\r
+ 84, 84, 84, 84, 85, 85, 85, 85, 85, 85,\r
+ 85, 85, 86, 86, 86, 86, 86, 86, 86, 86,\r
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,\r
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86\r
+ };\r
+\r
+ /** Compile-time constant expression */\r
+ private static final int MAX_LOOKUP_CAPACITY = 1019;\r
+ static {\r
+ if (MAX_LOOKUP_CAPACITY !=\r
+ SMALL_LOOKUP_TABLE_CAPACITIES[SMALL_LOOKUP_TABLE_CAPACITIES.length - 1]) {\r
+ throw new AssertionError();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * These capacities and other regular capacities from {@link #REGULAR_INT_CAPACITIES}\r
+ * and {@link #REGULAR_LONG_CAPACITIES} arrays are generated using a single command\r
+ * {@code $ java QHashCapacities 40 0.005}, i. e. trying to keep 0.5% max difference between\r
+ * neighbouring capacities.\r
+ *\r
+ * @see {@link #main(String[])}\r
+ * @see {@link #generateRegularCapacities(long, double)}\r
+ */\r
+ private static final char[] REGULAR_CHAR_CAPACITIES = new char[] {\r
+ 1031, 1039,\r
+ 1051, 1063, 1087, 1091, 1103, 1123, 1151, 1163, 1171, 1187,\r
+ 1223, 1231, 1259, 1279, 1283, 1291, 1303, 1307, 1319, 1327,\r
+ 1367, 1399, 1423, 1427, 1439, 1447, 1451, 1459, 1471, 1483,\r
+ 1487, 1499, 1511, 1523, 1531, 1543, 1559, 1567, 1571, 1579,\r
+ 1583, 1607, 1619, 1627, 1663, 1667, 1699, 1723, 1747, 1759,\r
+ 1783, 1787, 1811, 1823, 1831, 1847, 1867, 1871, 1879, 1907,\r
+ 1931, 1951, 1979, 1987, 1999, 2003, 2011, 2027, 2039, 2063,\r
+ 2083, 2087, 2099, 2111, 2131, 2143, 2179, 2203, 2207, 2239,\r
+ 2243, 2251, 2267, 2287, 2311, 2339, 2347, 2351, 2371, 2383,\r
+ 2399, 2411, 2423, 2447, 2459, 2467, 2503, 2531, 2539, 2543,\r
+ 2551, 2579, 2591, 2647, 2659, 2663, 2671, 2683, 2687, 2699,\r
+ 2707, 2711, 2719, 2731, 2767, 2791, 2803, 2819, 2843, 2851,\r
+ 2879, 2887, 2903, 2927, 2939, 2963, 2971, 2999, 3011, 3019,\r
+ 3023, 3067, 3079, 3083, 3119, 3163, 3167, 3187, 3191, 3203,\r
+ 3251, 3259, 3271, 3299, 3307, 3319, 3323, 3331, 3343, 3347,\r
+ 3359, 3371, 3391, 3407, 3463, 3467, 3491, 3499, 3511, 3527,\r
+ 3539, 3547, 3559, 3571, 3583, 3607, 3623, 3631, 3643, 3659,\r
+ 3671, 3691, 3719, 3727, 3739, 3767, 3779, 3803, 3823, 3847,\r
+ 3851, 3863, 3907, 3911, 3919, 3923, 3931, 3943, 3947, 3967,\r
+ 4003, 4007, 4019, 4027, 4051, 4079, 4091, 4099, 4111, 4127,\r
+ 4139, 4159, 4211, 4219, 4231, 4243, 4259, 4271, 4283, 4327,\r
+ 4339, 4363, 4391, 4423, 4447, 4451, 4463, 4483, 4507, 4519,\r
+ 4523, 4547, 4567, 4583, 4591, 4603, 4639, 4643, 4651, 4663,\r
+ 4679, 4691, 4703, 4723, 4751, 4759, 4783, 4787, 4799, 4831,\r
+ 4871, 4903, 4919, 4931, 4943, 4951, 4967, 4987, 4999, 5003,\r
+ 5011, 5023, 5039, 5051, 5059, 5087, 5099, 5107, 5119, 5147,\r
+ 5167, 5171, 5179, 5227, 5231, 5279, 5303, 5323, 5347, 5351,\r
+ 5387, 5399, 5407, 5419, 5431, 5443, 5471, 5479, 5483, 5503,\r
+ 5507, 5519, 5527, 5531, 5563, 5591, 5623, 5639, 5647, 5651,\r
+ 5659, 5683, 5711, 5743, 5779, 5783, 5791, 5807, 5827, 5839,\r
+ 5843, 5851, 5867, 5879, 5903, 5923, 5927, 5939, 5987, 6007,\r
+ 6011, 6043, 6047, 6067, 6079, 6091, 6131, 6143, 6151, 6163,\r
+ 6199, 6203, 6211, 6247, 6263, 6271, 6287, 6299, 6311, 6323,\r
+ 6343, 6359, 6367, 6379, 6427, 6451, 6491, 6547, 6551, 6563,\r
+ 6571, 6599, 6607, 6619, 6659, 6679, 6691, 6703, 6719, 6763,\r
+ 6779, 6791, 6803, 6823, 6827, 6863, 6871, 6883, 6899, 6907,\r
+ 6911, 6947, 6959, 6967, 6971, 6983, 6991, 7019, 7027, 7039,\r
+ 7043, 7079, 7103, 7127, 7151, 7159, 7187, 7207, 7211, 7219,\r
+ 7243, 7247, 7283, 7307, 7331, 7351, 7411, 7451, 7459, 7487,\r
+ 7499, 7507, 7523, 7547, 7559, 7583, 7591, 7603, 7607, 7639,\r
+ 7643, 7687, 7691, 7699, 7703, 7723, 7727, 7759, 7823, 7867,\r
+ 7879, 7883, 7907, 7919, 7927, 7951, 7963, 8011, 8039, 8059,\r
+ 8087, 8111, 8123, 8147, 8167, 8171, 8179, 8191, 8219, 8231,\r
+ 8243, 8263, 8287, 8291, 8311, 8363, 8387, 8419, 8423, 8431,\r
+ 8443, 8447, 8467, 8527, 8539, 8543, 8563, 8599, 8623, 8627,\r
+ 8647, 8663, 8699, 8707, 8719, 8731, 8747, 8779, 8783, 8803,\r
+ 8807, 8819, 8831, 8839, 8863, 8867, 8887, 8923, 8951, 8963,\r
+ 8971, 8999, 9007, 9011, 9043, 9059, 9067, 9091, 9103, 9127,\r
+ 9151, 9187, 9199, 9203, 9227, 9239, 9283, 9311, 9319, 9323,\r
+ 9343, 9371, 9391, 9403, 9419, 9431, 9439, 9463, 9467, 9479,\r
+ 9491, 9511, 9539, 9547, 9551, 9587, 9619, 9623, 9631, 9643,\r
+ 9679, 9719, 9739, 9743, 9767, 9787, 9791, 9803, 9811, 9839,\r
+ 9851, 9859, 9871, 9883, 9887, 9907, 9923, 9931, 9967, 10007,\r
+ 10039, 10067, 10079, 10091, 10099, 10103, 10111, 10139, 10151, 10159,\r
+ 10163, 10211, 10223, 10243, 10247, 10259, 10267, 10271, 10303, 10331,\r
+ 10343, 10391, 10399, 10427, 10459, 10463, 10487, 10499, 10531, 10559,\r
+ 10567, 10607, 10627, 10631, 10639, 10651, 10663, 10667, 10687, 10691,\r
+ 10711, 10723, 10739, 10771, 10799, 10831, 10847, 10859, 10867, 10883,\r
+ 10891, 10903, 10939, 10979, 10987, 11003, 11027, 11047, 11059, 11071,\r
+ 11083, 11087, 11119, 11131, 11159, 11171, 11239, 11243, 11251, 11279,\r
+ 11287, 11299, 11311, 11351, 11383, 11399, 11411, 11423, 11443, 11447,\r
+ 11467, 11471, 11483, 11491, 11503, 11519, 11527, 11551, 11579, 11587,\r
+ 11699, 11719, 11731, 11743, 11779, 11783, 11807, 11827, 11831, 11839,\r
+ 11863, 11867, 11887, 11903, 11923, 11927, 11939, 11959, 11971, 11987,\r
+ 12007, 12011, 12043, 12071, 12107, 12119, 12143, 12163, 12203, 12211,\r
+ 12227, 12239, 12251, 12263, 12323, 12343, 12347, 12379, 12391, 12451,\r
+ 12479, 12487, 12491, 12503, 12511, 12527, 12539, 12547, 12583, 12611,\r
+ 12619, 12647, 12659, 12671, 12703, 12739, 12743, 12763, 12791, 12799,\r
+ 12823, 12899, 12919, 12979, 13043, 13099, 13159, 13219, 13259, 13291,\r
+ 13339, 13399, 13463, 13523, 13567, 13619, 13679, 13711, 13763, 13831,\r
+ 13879, 13931, 13999, 14051, 14083, 14143, 14207, 14243, 14303, 14323,\r
+ 14387, 14431, 14503, 14563, 14627, 14683, 14723, 14779, 14851, 14923,\r
+ 14983, 15031, 15083, 15131, 15187, 15259, 15307, 15383, 15439, 15511,\r
+ 15551, 15607, 15667, 15727, 15787, 15859, 15919, 15991, 16063, 16111,\r
+ 16187, 16267, 16339, 16411, 16427, 16487, 16547, 16619, 16691, 16747,\r
+ 16811, 16879, 16963, 17047, 17123, 17207, 17291, 17359, 17443, 17519,\r
+ 17579, 17659, 17747, 17807, 17891, 17959, 18043, 18119, 18199, 18287,\r
+ 18367, 18427, 18503, 18583, 18671, 18719, 18787, 18839, 18899, 18959,\r
+ 19051, 19139, 19231, 19319, 19379, 19423, 19507, 19603, 19687, 19751,\r
+ 19843, 19927, 20023, 20123, 20219, 20287, 20347, 20443, 20543, 20611,\r
+ 20707, 20807, 20879, 20939, 21011, 21107, 21179, 21283, 21379, 21467,\r
+ 21559, 21647, 21739, 21839, 21943, 22039, 22147, 22247, 22343, 22447,\r
+ 22531, 22639, 22751, 22859, 22943, 23027, 23131, 23227, 23339, 23447,\r
+ 23563, 23663, 23767, 23879, 23971, 24043, 24151, 24239, 24359, 24379,\r
+ 24499, 24571, 24683, 24799, 24907, 25031, 25111, 25219, 25339, 25463,\r
+ 25579, 25679, 25799, 25903, 25999, 26099, 26227, 26339, 26407, 26539,\r
+ 26627, 26759, 26879, 27011, 27143, 27271, 27407, 27527, 27631, 27751,\r
+ 27883, 28019, 28151, 28279, 28387, 28499, 28619, 28751, 28879, 29023,\r
+ 29167, 29303, 29443, 29587, 29723, 29851, 29983, 30119, 30259, 30391,\r
+ 30539, 30671, 30803, 30931, 31079, 31231, 31387, 31543, 31699, 31847,\r
+ 31963, 32099, 32251, 32371, 32531, 32687, 32839, 32887, 33023, 33179,\r
+ 33331, 33479, 33647, 33811, 33967, 34123, 34231, 34403, 34543, 34703,\r
+ 34871, 35023, 35171, 35339, 35507, 35671, 35803, 35951, 36131, 36299,\r
+ 36451, 36587, 36767, 36943, 37123, 37307, 37447, 37619, 37799, 37987,\r
+ 38167, 38351, 38543, 38671, 38851, 39043, 39227, 39419, 39607, 39779,\r
+ 39971, 40151, 40343, 40499, 40699, 40847, 41039, 41243, 41443, 41647,\r
+ 41843, 41983, 42179, 42359, 42571, 42743, 42943, 43151, 43331, 43543,\r
+ 43759, 43943, 44131, 44351, 44563, 44771, 44959, 45179, 45403, 45599,\r
+ 45823, 46051, 46271, 46471, 46687, 46919, 47111, 47339, 47563, 47791,\r
+ 48023, 48259, 48491, 48731, 48947, 49171, 49391, 49627, 49871, 50111,\r
+ 50359, 50587, 50839, 51031, 51263, 51511, 51767, 52027, 52259, 52511,\r
+ 52747, 53003, 53267, 53527, 53791, 54059, 54311, 54583, 54851, 55079,\r
+ 55331, 55579, 55843, 56123, 56383, 56659, 56911, 57191, 57467, 57719,\r
+ 57991, 58271, 58543, 58831, 59107, 59387, 59659, 59951, 60251, 60527,\r
+ 60811, 61091, 61379, 61687, 61991, 62299, 62591, 62903, 63179, 63487,\r
+ 63803, 64123, 64439, 64747, 65063, 65371\r
+ };\r
+\r
+ /** Compile-time constant expression */\r
+ private static final int MAX_REGULAR_CHAR_CAPACITY = 65371;\r
+ static {\r
+ if (MAX_REGULAR_CHAR_CAPACITY !=\r
+ REGULAR_CHAR_CAPACITIES[REGULAR_CHAR_CAPACITIES.length - 1])\r
+ throw new AssertionError();\r
+ }\r
+\r
+\r
+ private static final int[] REGULAR_INT_CAPACITIES = new int[] {\r
+ 65687, 65827, 66103, 66431,\r
+ 66751, 67079, 67391, 67699, 68023, 68351, 68687, 69031, 69371, 69691,\r
+ 69991, 70327, 70627, 70979, 71327, 71647, 71947, 72271, 72623, 72931,\r
+ 73291, 73643, 73999, 74323, 74687, 75011, 75367, 75731, 76091, 76463,\r
+ 76819, 77167, 77527, 77899, 78259, 78607, 78979, 79319, 79687, 80039,\r
+ 80407, 80803, 81203, 81611, 82003, 82387, 82787, 83203, 83563, 83891,\r
+ 84299, 84691, 85103, 85523, 85931, 86351, 86783, 87211, 87643, 88079,\r
+ 88499, 88919, 89363, 89759, 90187, 90631, 91079, 91499, 91939, 92399,\r
+ 92863, 93307, 93763, 94219, 94687, 95131, 95603, 96059, 96527, 96979,\r
+ 97459, 97919, 98387, 98867, 99347, 99823, 100291, 100787, 101267, 101719,\r
+ 102191, 102667, 103171, 103687, 104207, 104707, 105227, 105751, 106279, 106787,\r
+ 107323, 107827, 108343, 108883, 109423, 109943, 110479, 111031, 111539, 112067,\r
+ 112603, 113159, 113719, 114259, 114799, 115363, 115931, 116491, 117071, 117659,\r
+ 118247, 118831, 119419, 119963, 120539, 121123, 121687, 122263, 122867, 123479,\r
+ 124067, 124643, 125243, 125863, 126443, 127031, 127607, 128239, 128879, 129499,\r
+ 130147, 130783, 131363, 131543, 132199, 132859, 133519, 134171, 134807, 135463,\r
+ 136139, 136811, 137491, 138179, 138863, 139511, 140191, 140891, 141587, 142271,\r
+ 142979, 143687, 144379, 145091, 145799, 146519, 147211, 147919, 148627, 149371,\r
+ 150107, 150847, 151603, 152363, 153107, 153871, 154619, 155371, 156119, 156887,\r
+ 157667, 158443, 159223, 160019, 160807, 161611, 162419, 163211, 164023, 164839,\r
+ 165667, 166487, 167311, 168151, 168991, 169823, 170647, 171491, 172331, 173183,\r
+ 174047, 174907, 175783, 176651, 177511, 178403, 179287, 180179, 181003, 181871,\r
+ 182779, 183691, 184607, 185519, 186451, 187367, 188291, 189199, 190147, 191047,\r
+ 192007, 192971, 193939, 194911, 195887, 196871, 197831, 198811, 199783, 200771,\r
+ 201743, 202751, 203767, 204751, 205759, 206779, 207799, 208843, 209887, 210907,\r
+ 211927, 212987, 214003, 215051, 216119, 217199, 218279, 219371, 220447, 221539,\r
+ 222587, 223667, 224683, 225751, 226819, 227947, 228983, 230123, 231271, 232391,\r
+ 233551, 234659, 235783, 236947, 238099, 239287, 240479, 241603, 242807, 244003,\r
+ 245171, 246371, 247607, 248851, 250091, 251323, 252559, 253787, 255043, 256307,\r
+ 257591, 258871, 260171, 261427, 262723, 263951, 265271, 266587, 267887, 269219,\r
+ 270563, 271919, 273271, 274579, 275911, 277223, 278591, 279967, 281363, 282767,\r
+ 284159, 285559, 286987, 288403, 289843, 291299, 292759, 294223, 295699, 297151,\r
+ 298631, 300119, 301579, 303091, 304559, 306083, 307583, 309091, 310643, 312199,\r
+ 313679, 315247, 316819, 318403, 319967, 321547, 323123, 324743, 326351, 327967,\r
+ 329587, 331231, 332887, 334547, 336199, 337859, 339467, 341171, 342871, 344587,\r
+ 346303, 348011, 349759, 351503, 353263, 355027, 356803, 358591, 360391, 362143,\r
+ 363959, 365779, 367603, 369407, 371227, 373091, 374939, 376787, 378667, 380563,\r
+ 382463, 384359, 386279, 388211, 390151, 392099, 394063, 396031, 398011, 399979,\r
+ 401939, 403951, 405947, 407923, 409967, 412019, 414083, 416147, 418199, 420263,\r
+ 422311, 424423, 426527, 428639, 430783, 432931, 435103, 437263, 439459, 441667,\r
+ 443867, 446087, 448303, 450479, 452731, 454991, 457267, 459523, 461803, 464119,\r
+ 466423, 468739, 471091, 473443, 475807, 478171, 480563, 482947, 485347, 487783,\r
+ 490207, 492647, 495119, 497587, 500083, 502543, 505067, 507599, 510127, 512663,\r
+ 515191, 517739, 520339, 522947, 525571, 528163, 530807, 533447, 536111, 538799,\r
+ 541483, 544199, 546919, 549623, 552379, 555143, 557927, 560719, 563503, 566311,\r
+ 569083, 571939, 574799, 577627, 580471, 583367, 586291, 589187, 592139, 595087,\r
+ 598051, 601031, 604031, 607043, 610063, 613099, 616171, 619247, 622331, 625451,\r
+ 628583, 631711, 634859, 638023, 641227, 644431, 647659, 650911, 654163, 657431,\r
+ 660727, 664043, 667363, 670711, 674059, 677387, 680783, 684191, 687623, 691051,\r
+ 694511, 697979, 701479, 704999, 708527, 712067, 715639, 719179, 722783, 726367,\r
+ 729991, 733651, 737327, 741007, 744727, 748463, 752183, 755959, 759719, 763523,\r
+ 767323, 771143, 775007, 778871, 782783, 786659, 790567, 794531, 798487, 802471,\r
+ 806503, 810539, 814579, 818659, 822763, 826879, 831023, 835123, 839303, 843503,\r
+ 847727, 851971, 856187, 860479, 864803, 869119, 873463, 877843, 882239, 886651,\r
+ 891103, 895571, 900019, 904531, 909071, 913639, 918199, 922807, 927403, 931999,\r
+ 936679, 941383, 946091, 950839, 955607, 960383, 965179, 970027, 974891, 979787,\r
+ 984703, 989623, 994559, 999491, 1004483, 1009483, 1014547, 1019639, 1024703, 1029823,\r
+ 1034983, 1040167, 1045391, 1050631, 1054171, 1059439, 1064743, 1070087, 1075463, 1080847,\r
+ 1086259, 1091711, 1097179, 1102691, 1108223, 1113787, 1119359, 1124983, 1130627, 1136299,\r
+ 1142003, 1147739, 1153487, 1159283, 1165103, 1170947, 1176827, 1182739, 1188667, 1194631,\r
+ 1200607, 1206619, 1212671, 1218727, 1224823, 1230967, 1237139, 1243343, 1249559, 1255811,\r
+ 1262119, 1268447, 1274803, 1281187, 1287623, 1294087, 1300571, 1307063, 1313623, 1320191,\r
+ 1326791, 1333411, 1340107, 1346827, 1353551, 1360327, 1367159, 1374007, 1380887, 1387783,\r
+ 1394747, 1401739, 1408763, 1415803, 1422899, 1430027, 1437199, 1444411, 1451603, 1458871,\r
+ 1466147, 1473503, 1480903, 1488343, 1495751, 1503247, 1510759, 1518343, 1525963, 1533583,\r
+ 1541251, 1548947, 1556719, 1564499, 1572359, 1580251, 1588159, 1596107, 1604123, 1612183,\r
+ 1620247, 1628383, 1636543, 1644691, 1652947, 1661243, 1669543, 1677899, 1686319, 1694767,\r
+ 1703267, 1711799, 1720399, 1729043, 1737691, 1746419, 1755179, 1763959, 1772819, 1781699,\r
+ 1790599, 1799591, 1808627, 1817663, 1826771, 1835923, 1845119, 1854379, 1863671, 1873019,\r
+ 1882403, 1891859, 1901359, 1910891, 1920487, 1930099, 1939787, 1949527, 1959283, 1969111,\r
+ 1978927, 1988839, 1998827, 2008807, 2018899, 2029003, 2039179, 2049419, 2059711, 2069959,\r
+ 2080339, 2090771, 2101259, 2106551, 2117119, 2127739, 2138387, 2149127, 2159923, 2170771,\r
+ 2181671, 2192623, 2203631, 2214691, 2225819, 2236987, 2248223, 2259503, 2270803, 2282207,\r
+ 2293567, 2305091, 2316667, 2328307, 2340007, 2351731, 2363507, 2375327, 2387243, 2399207,\r
+ 2411243, 2423359, 2435519, 2447743, 2460043, 2472403, 2484803, 2497259, 2509807, 2522407,\r
+ 2535059, 2547791, 2560583, 2573423, 2586343, 2599327, 2612383, 2625487, 2638651, 2651899,\r
+ 2665199, 2678551, 2692003, 2705519, 2719111, 2732759, 2746423, 2760223, 2774071, 2788007,\r
+ 2802011, 2816059, 2830151, 2844367, 2858623, 2872967, 2887363, 2901839, 2916383, 2930999,\r
+ 2945707, 2960467, 2975339, 2990279, 3005267, 3020351, 3035507, 3050759, 3066067, 3081443,\r
+ 3096911, 3112391, 3127979, 3143671, 3159439, 3175259, 3191099, 3207119, 3223223, 3239419,\r
+ 3255683, 3272039, 3288479, 3304991, 3321583, 3338263, 3355031, 3371867, 3388799, 3405791,\r
+ 3422807, 3439987, 3457271, 3474599, 3492043, 3509587, 3527219, 3544907, 3562711, 3580579,\r
+ 3598519, 3616583, 3634727, 3652991, 3671347, 3689771, 3708283, 3726911, 3745631, 3764443,\r
+ 3783343, 3802283, 3821327, 3840479, 3859759, 3879023, 3898483, 3918067, 3937751, 3957479,\r
+ 3977339, 3997307, 4017359, 4037531, 4057799, 4078187, 4098659, 4119239, 4139923, 4160711,\r
+ 4181579, 4202567, 4210807, 4231943, 4253203, 4274551, 4295999, 4317571, 4339207, 4361003,\r
+ 4382879, 4404899, 4426999, 4449227, 4471559, 4494019, 4516571, 4539247, 4562039, 4584959,\r
+ 4607987, 4631131, 4654399, 4677779, 4701239, 4724831, 4748563, 4772399, 4796371, 4820443,\r
+ 4844659, 4868999, 4893419, 4918007, 4942687, 4967491, 4992419, 5017447, 5042647, 5067967,\r
+ 5093423, 5119007, 5144707, 5170519, 5196467, 5222579, 5248787, 5275159, 5301623, 5328251,\r
+ 5355019, 5381927, 5408947, 5436127, 5463391, 5490787, 5518351, 5546071, 5573927, 5601907,\r
+ 5630039, 5658307, 5686739, 5715299, 5743987, 5772847, 5801843, 5830963, 5860243, 5889683,\r
+ 5919271, 5948939, 5978831, 6008867, 6038999, 6069311, 6099767, 6130391, 6161063, 6192023,\r
+ 6223099, 6254359, 6285787, 6317327, 6349043, 6380939, 6412999, 6445223, 6477599, 6510107,\r
+ 6542803, 6575671, 6608639, 6641839, 6675211, 6708739, 6742363, 6776207, 6810247, 6844447,\r
+ 6878803, 6913351, 6948079, 6982907, 7017979, 7053223, 7088611, 7124231, 7159987, 7195963,\r
+ 7232111, 7268423, 7304939, 7341647, 7378531, 7415599, 7452859, 7490303, 7527911, 7565627,\r
+ 7603627, 7641791, 7680191, 7718771, 7757543, 7796491, 7835647, 7874983, 7914551, 7954319,\r
+ 7994279, 8034451, 8074811, 8115383, 8156147, 8197099, 8238247, 8279627, 8321227, 8363023,\r
+ 8405003, 8419511, 8461787, 8504291, 8546999, 8589923, 8633063, 8676431, 8719987, 8763803,\r
+ 8807803, 8852059, 8896483, 8941171, 8986091, 9031207, 9076579, 9122143, 9167923, 9213979,\r
+ 9260263, 9306779, 9353483, 9400463, 9447667, 9495139, 9542843, 9590699, 9638891, 9687323,\r
+ 9735991, 9784903, 9834047, 9883463, 9933059, 9982939, 10033063, 10083443, 10134107, 10185011,\r
+ 10236179, 10287587, 10339267, 10391219, 10443431, 10495907, 10548623, 10601627, 10654871, 10708403,\r
+ 10762211, 10816271, 10870619, 10925227, 10980059, 11035223, 11090627, 11146279, 11202251, 11258483,\r
+ 11314987, 11371807, 11428931, 11486347, 11544047, 11602043, 11660339, 11718923, 11777791, 11836963,\r
+ 11896427, 11956199, 12016187, 12076567, 12137183, 12198139, 12259399, 12320983, 12382823, 12445039,\r
+ 12507559, 12570403, 12633559, 12697039, 12760843, 12824899, 12889339, 12954079, 13019143, 13084531,\r
+ 13150279, 13216331, 13282723, 13349411, 13416463, 13483751, 13551467, 13619563, 13687987, 13756739,\r
+ 13825831, 13895291, 13965103, 14035279, 14105759, 14176619, 14247847, 14319419, 14391359, 14463667,\r
+ 14536307, 14609351, 14682719, 14756491, 14830603, 14905123, 14980019, 15055259, 15130903, 15206899,\r
+ 15283291, 15360071, 15437239, 15514783, 15592739, 15671087, 15749819, 15828947, 15908423, 15988363,\r
+ 16068691, 16149431, 16230491, 16312039, 16394003, 16476371, 16559159, 16642343, 16725971, 16810007,\r
+ 16836587, 16921183, 17006167, 17091623, 17177507, 17263783, 17350519, 17437691, 17525243, 17613307,\r
+ 17701807, 17790739, 17880067, 17969911, 18060187, 18150911, 18242083, 18333703, 18425819, 18518363,\r
+ 18611419, 18704927, 18798907, 18893351, 18988267, 19083679, 19179551, 19275847, 19372699, 19470019,\r
+ 19567811, 19666123, 19764947, 19864267, 19964059, 20064371, 20165143, 20266391, 20368211, 20470547,\r
+ 20573411, 20676791, 20780659, 20885071, 20989967, 21095423, 21201347, 21307859, 21414923, 21522511,\r
+ 21630659, 21739351, 21848579, 21958367, 22068647, 22179511, 22290943, 22402951, 22515511, 22628651,\r
+ 22742303, 22856527, 22971259, 23086667, 23202643, 23319227, 23436407, 23554099, 23672459, 23791399,\r
+ 23910947, 24031087, 24151807, 24273163, 24395023, 24517607, 24640799, 24764611, 24889043, 25014071,\r
+ 25139767, 25266071, 25393031, 25520623, 25648867, 25777639, 25907143, 26037299, 26168099, 26299571,\r
+ 26431723, 26564507, 26697991, 26832139, 26966963, 27102419, 27238559, 27375419, 27512951, 27651191,\r
+ 27790127, 27929723, 28070071, 28211123, 28352887, 28495351, 28638539, 28782419, 28927039, 29072399,\r
+ 29218403, 29365207, 29512739, 29661043, 29810023, 29959819, 30110347, 30261643, 30413707, 30566519,\r
+ 30720119, 30874483, 31029587, 31185443, 31342139, 31499599, 31657783, 31816847, 31976723, 32137403,\r
+ 32298863, 32461159, 32624239, 32788099, 32952839, 33118391, 33284803, 33452047, 33619979, 33670103,\r
+ 33839243, 34009279, 34180163, 34351879, 34524491, 34697951, 34872283, 35047483, 35223599, 35400583,\r
+ 35578471, 35757247, 35936903, 36117467, 36298943, 36481343, 36664651, 36848891, 37033987, 37220047,\r
+ 37407059, 37595027, 37783927, 37973783, 38164571, 38356327, 38548999, 38742707, 38937319, 39132979,\r
+ 39329627, 39527123, 39725723, 39925339, 40125947, 40327571, 40530199, 40733867, 40938523, 41144203,\r
+ 41350943, 41558687, 41767483, 41977367, 42188287, 42400243, 42613303, 42827431, 43042631, 43258907,\r
+ 43476287, 43694747, 43914307, 44134931, 44356639, 44579503, 44803511, 45028639, 45254899, 45482291,\r
+ 45710831, 45940523, 46171351, 46403347, 46636519, 46870867, 47106379, 47343083, 47580983, 47820079,\r
+ 48060359, 48301867, 48544583, 48788503, 49033651, 49280003, 49527619, 49776479, 50026607, 50277979,\r
+ 50530619, 50784523, 51039683, 51296159, 51553903, 51812927, 52073279, 52334951, 52597891, 52862143,\r
+ 53127779, 53394727, 53663039, 53932651, 54203659, 54476027, 54749771, 55024859, 55301359, 55579243,\r
+ 55858459, 56139079, 56421151, 56704667, 56989571, 57275927, 57563699, 57852943, 58143583, 58435703,\r
+ 58729331, 59024443, 59321039, 59619127, 59918687, 60219779, 60522379, 60826511, 61132163, 61439239,\r
+ 61747963, 62058247, 62370079, 62683463, 62998451, 63314959, 63633079, 63952799, 64274159, 64597111,\r
+ 64921699, 65247907, 65575747, 65905267, 66236431, 66569267, 66903779, 67239967, 67338643, 67677007,\r
+ 68017067, 68358739, 68702143, 69047299, 69394219, 69742919, 70093327, 70445519, 70799507, 71155267,\r
+ 71512787, 71872127, 72233279, 72596243, 72961039, 73327651, 73696111, 74066411, 74438591, 74812651,\r
+ 75188591, 75566347, 75946067, 76327703, 76711231, 77096707, 77484083, 77873431, 78264727, 78657983,\r
+ 79053187, 79450363, 79849543, 80250763, 80654027, 81059287, 81466579, 81875951, 82287379, 82700791,\r
+ 83116367, 83534023, 83953763, 84375623, 84799619, 85225739, 85653947, 86084287, 86516863, 86951603,\r
+ 87388531, 87827647, 88268987, 88712527, 89158283, 89606287, 90056467, 90508987, 90963799, 91420867,\r
+ 91880263, 92341967, 92805983, 93272327, 93741019, 94212031, 94685419, 95161219, 95639387, 96119927,\r
+ 96602903, 97088339, 97576163, 98066491, 98559259, 99054523, 99552227, 100052467, 100555243, 101060539,\r
+ 101568287, 102078679, 102591631, 103107119, 103625239, 104145887, 104669179, 105195127, 105723743, 106254899,\r
+ 106788827, 107325451, 107864747, 108406763, 108951503, 109498943, 110049059, 110602031, 111157807, 111716383,\r
+ 112277699, 112841863, 113408767, 113978507, 114551263, 115126883, 115705351, 116286743, 116871091, 117458347,\r
+ 118048547, 118641739, 119237927, 119837059, 120439243, 121044431, 121652599, 122263903, 122878211, 123495683,\r
+ 124116191, 124739887, 125366567, 125996539, 126629663, 127265951, 127905443, 128548139, 129194083, 129843299,\r
+ 130495763, 131151491, 131810491, 132472831, 133138519, 133807547, 134479879, 134673607, 135350351, 136030471,\r
+ 136714027, 137400979, 138091427, 138785203, 139482599, 140183503, 140887919, 141595859, 142307287, 143022359,\r
+ 143741047, 144463339, 145189259, 145918711, 146651903, 147388823, 148129447, 148873787, 149621891, 150373759,\r
+ 151129399, 151888843, 152652103, 153419159, 154190087, 154964867, 155743583, 156526207, 157312763, 158103259,\r
+ 158897743, 159696211, 160498699, 161305211, 162115787, 162930419, 163749119, 164571971, 165398927, 166230007,\r
+ 167065303, 167904791, 168748499, 169596463, 170448683, 171305207, 172165991, 173031143, 173900563, 174774427,\r
+ 175652671, 176535311, 177422411, 178313951, 179209991, 180110471, 181015519, 181925111, 182839303, 183758039,\r
+ 184681411, 185609447, 186542099, 187479491, 188421539, 189368371, 190319959, 191276291, 192237431, 193203431,\r
+ 194174191, 195149939, 196130579, 197116159, 198106663, 199102151, 200102579, 201108043, 202118563, 203134123,\r
+ 204154859, 205180751, 206211799, 207248011, 208289351, 209336027, 210387907, 211445131, 212507651, 213575503,\r
+ 214648699, 215727247, 216811267, 217900763, 218995739, 220096183, 221202119, 222313643, 223430791, 224553523,\r
+ 225681923, 226815983, 227955727, 229101203, 230252411, 231409439, 232572299, 233740999, 234915539, 236095939,\r
+ 237282343, 238474711, 239672963, 240877339, 242087771, 243304219, 244526851, 245755619, 246990559, 248231707,\r
+ 249479099, 250732739, 251992667, 253258879, 254531507, 255810559, 257096039, 258387967, 259686391, 260991287,\r
+ 262302791, 263620879, 264945587, 266276947, 267614983, 268959767, 269344759, 270698227, 272058491, 273425591,\r
+ 274799579, 276180431, 277568219, 278963011, 280364803, 281773571, 283189499, 284612527, 286042723, 287480071,\r
+ 288924599, 290376451, 291835627, 293302123, 294775991, 296257271, 297745967, 299242171, 300745843, 302257051,\r
+ 303775919, 305302427, 306836599, 308378407, 309928027, 311485423, 313050587, 314623703, 316204703, 317793559,\r
+ 319390507, 320995471, 322608491, 324229639, 325858867, 327496339, 329142019, 330795991, 332458267, 334128887,\r
+ 335807831, 337495303, 339191227, 340895683, 342608719, 344330351, 346060571, 347799511, 349547071, 351303583,\r
+ 353068907, 354843119, 356626211, 358418243, 360219283, 362029403, 363848627, 365676923, 367514491, 369361231,\r
+ 371217299, 373082707, 374957483, 376841587, 378735251, 380638387, 382551083, 384473399, 386405387, 388347103,\r
+ 390298547, 392259767, 394230899, 396211903, 398202899, 400203871, 402214927, 404236087, 406267391, 408308899,\r
+ 410360539, 412422631, 414495091, 416577947, 418671283, 420775151, 422889583, 425014571, 427150247, 429296719,\r
+ 431453983, 433622011, 435800971, 437990923, 440191879, 442403887, 444627019, 446861267, 449106787, 451363571,\r
+ 453631727, 455911259, 458202211, 460504699, 462818767, 465144487, 467481851, 469831003, 472191851, 474564667,\r
+ 476949379, 479346103, 481754807, 484175663, 486608687, 489053951, 491511491, 493981363, 496463519, 498958307,\r
+ 501465563, 503985479, 506518063, 509063299, 511621387, 514192271, 516776131, 519372859, 521982751, 524605747,\r
+ 527241899, 529891199, 532553939, 535230083, 537919639, 538685971, 541392743, 544113239, 546847447, 549595367,\r
+ 552357139, 555132803, 557922367, 560725951, 563543663, 566375527, 569221603, 572081959, 574956703, 577845787,\r
+ 580749511, 583667831, 586600783, 589548499, 592511039, 595488451, 598480807, 601488211, 604510703, 607548371,\r
+ 610601371, 613669687, 616753427, 619852679, 622967503, 626097991, 629244167, 632406163, 635584031, 638777903,\r
+ 641987839, 645213847, 648456091, 651714607, 654989519, 658280863, 661588783, 664913323, 668254571, 671612587,\r
+ 674987507, 678379379, 681788203, 685214251, 688657483, 692117983, 695595931, 699091331, 702604327, 706134991,\r
+ 709683371, 713249591, 716833727, 720435851, 724056107, 727694531, 731351279, 735026371, 738719939, 742432063,\r
+ 746162863, 749912399, 753680731, 757468067, 761274403, 765099883, 768944587, 772808551, 776691959, 780594923,\r
+ 784517507, 788459759, 792421843, 796403831, 800405831, 804427927, 808470259, 812532911, 816615971, 820719539,\r
+ 824843651, 828988331, 833154031, 837340703, 841548427, 845777279, 850027351, 854298799, 858591751, 862906279,\r
+ 867242491, 871600487, 875980379, 880382287, 884806283, 889252471, 893721071, 898212083, 902725711, 907261963,\r
+ 911821051, 916403011, 921007907, 925636079, 930287503, 934962299, 939660587, 944382499, 949128119, 953897599,\r
+ 958691051, 963508519, 968350231, 973216267, 978106799, 983021807, 987961591, 992926211, 997915771, 1002930347,\r
+ 1007970143, 1013035271, 1018125743, 1023241907, 1028383823, 1033551523, 1038745151, 1043964947, 1049210831, 1054483151,\r
+ 1059782051, 1065107587, 1070459851, 1075839019, 1077368339, 1082782187, 1088223299, 1093691743, 1099187591, 1104711019,\r
+ 1110262327, 1115841499, 1121448739, 1127084059, 1132747771, 1138439959, 1144160711, 1149910183, 1155688603, 1161496079,\r
+ 1167332711, 1173198647, 1179094079, 1185019067, 1190973899, 1196958667, 1202973511, 1209018599, 1215094019, 1221199951,\r
+ 1227336631, 1233504079, 1239702463, 1245932059, 1252193003, 1258485419, 1264809463, 1271165167, 1277552923, 1283972759,\r
+ 1290424799, 1296909343, 1303426459, 1309976287, 1316559071, 1323174883, 1329823987, 1336506463, 1343222567, 1349972251,\r
+ 1356756031, 1363573879, 1370425967, 1377312463, 1384233491, 1391189419, 1398180307, 1405206307, 1412267611, 1419364259,\r
+ 1426496711, 1433664959, 1440869279, 1448109779, 1455386671, 1462700131, 1470050363, 1477437523, 1484861771, 1492323307,\r
+ 1499822383, 1507359151, 1514933747, 1522546447, 1530197423, 1537886851, 1545614899, 1553381771, 1561187699, 1569032827,\r
+ 1576917379, 1584841567, 1592805583, 1600809611, 1608853859, 1616938507, 1625063819, 1633229951, 1641437099, 1649685467,\r
+ 1657975307, 1666306819, 1674680207, 1683095671, 1691553427, 1700053627, 1708596587, 1717182347, 1725811267, 1734483643,\r
+ 1743199571, 1751959367, 1760763107, 1769611087, 1778503583, 1787440747, 1796422847, 1805449999, 1814522603, 1823640799,\r
+ 1832804767, 1842014791, 1851271043, 1860573907, 1869923411, 1879319999, 1888763743, 1898254999, 1907793931, 1917380807,\r
+ 1927015879, 1936699351, 1946431363, 1956212243, 1966042451, 1975922059, 1985851247, 1995830323, 2005859543, 2015939239,\r
+ 2026069559, 2036250751, 2046483151, 2056766983, 2067102431, 2077489807, 2087929451, 2098421519, 2108966287, 2119564099,\r
+ 2130215159, 2140919723,\r
+ };\r
+\r
+\r
+ // Compile-time constant expressions\r
+ private static final int MAX_REGULAR_CAPACITY_FOR_DOUBLED_ARRAY = 107325451;\r
+ private static final int MAX_REGULAR_INT_CAPACITY = 2140919723;\r
+ static {\r
+ if (MAX_REGULAR_INT_CAPACITY != REGULAR_INT_CAPACITIES[REGULAR_INT_CAPACITIES.length - 1] ||\r
+ binarySearch(REGULAR_INT_CAPACITIES, MAX_REGULAR_CAPACITY_FOR_DOUBLED_ARRAY) < 0)\r
+ throw new AssertionError();\r
+ }\r
+ \r
+ /**\r
+ * Class for precise and fast scaling non-negative integers by positive doubles.\r
+ *\r
+ * <p>Used in {@link com.koloboke.collect.impl.hash.HashConfigWrapper}.\r
+ *\r
+ * <p>Latencies of operations on floating stack, required for simple approach scaling\r
+ * <pre>\r
+ * Haswell Steamroller\r
+ * FILD (long -> double) 6 11\r
+ * FMUL 5 5\r
+ * FDIV 10-24 9-37\r
+ * FIST (double -> long) 7 7\r
+ * </pre>\r
+ *\r
+ * <p>In major cases {@code Scaler} allows to replace this\r
+ * with megamorphic call cost + a few clock cycles.\r
+ */\r
+ private static class Scaler {\r
+\r
+ public static Scaler by(double scale) {\r
+ if (Double.isNaN(scale) || scale <= 0.0 || Double.isInfinite(scale))\r
+ throw new IllegalArgumentException(\r
+ "Scale should be a finite positive number, " + scale + " is given");\r
+ if (scale == 0.25) return BY_0_25;\r
+ // Special "precise" BigDecimal forms for scales which are inversions of custom\r
+ // scales are needed to preserve inversion consistency\r
+ if (scale == 1.0 / 3.0) return BY_3_0_INVERSE;\r
+ if (scale == 0.5) return BY_0_5;\r
+ if (scale == 1 / 1.5) return BY_1_5_INVERSE;\r
+ if (scale == 0.75) return BY_0_75;\r
+ if (scale == 1.0) return BY_1_0;\r
+ if (scale == 1.0 / 0.75) return BY_0_75_INVERSE;\r
+ if (scale == 1.5) return BY_1_5;\r
+ if (scale == 2.0) return BY_2_0;\r
+ if (scale == 3.0) return BY_3_0;\r
+ if (scale == 4.0) return BY_4_0;\r
+ return new Scaler(scale);\r
+ }\r
+\r
+ static final Scaler BY_0_25 = new Scaler(0.25) {\r
+ @Override public int scaleUpper(int n) { check(n); return (n >> 2) + 1 ; }\r
+ @Override public int scaleLower(int n) { check(n); return n >> 2 ; }\r
+ };\r
+\r
+ static final Scaler BY_3_0_INVERSE = new Scaler(1.0 / 3.0);\r
+\r
+ static final Scaler BY_0_5 = new Scaler(0.5) {\r
+ @Override public int scaleUpper(int n) { check(n); return (n >> 1) + 1 ; }\r
+ @Override public int scaleLower(int n) { check(n); return n >> 1 ; }\r
+ };\r
+\r
+ static final Scaler BY_1_5_INVERSE = new Scaler(1.0 / 1.5);\r
+\r
+ static final Scaler BY_0_75 = new Scaler(0.75) {\r
+ @Override public int scaleUpper(int n) { check(n); int r = n - (n >> 2); return (n & 3 ) != 0 ? r : r + 1 ; }\r
+ @Override public int scaleLower(int n) { check(n); int r = n - (n >> 2); return (n & 3 ) != 0 ? r - 1 : r ; }\r
+ };\r
+\r
+ static final Scaler BY_1_0 = new Scaler(1.0) {\r
+ @Override public int scaleUpper(int n) { check(n); return n < Integer.MAX_VALUE ? n + 1 : Integer.MAX_VALUE; }\r
+ @Override public int scaleLower(int n) { check(n); return n ; }\r
+ };\r
+\r
+ static final Scaler BY_0_75_INVERSE = new Scaler(1.0 / 0.75);\r
+\r
+ static final Scaler BY_1_5 = new Scaler(1.5) {\r
+ @Override public int scaleUpper(int n) { check(n); return n <= 1431655764 ? n + (n >> 1) + 1 : Integer.MAX_VALUE; }\r
+ @Override public int scaleLower(int n) { check(n); return n <= 1431655764 ? n + (n >> 1) : Integer.MAX_VALUE; }\r
+ };\r
+\r
+ static final Scaler BY_2_0 = new Scaler(2.0) {\r
+ @Override public int scaleUpper(int n) { check(n); return n < (1 << 30) ? (n << 1) + 1 : Integer.MAX_VALUE; }\r
+ @Override public int scaleLower(int n) { check(n); return n < (1 << 30) ? (n << 1) : Integer.MAX_VALUE; }\r
+ };\r
+\r
+ static final Scaler BY_3_0 = new Scaler(3.0) {\r
+ @Override public int scaleUpper(int n) { check(n); return n <= 715827882 ? n + (n << 1) + 1 : Integer.MAX_VALUE; }\r
+ @Override public int scaleLower(int n) { check(n); return n <= 715827882 ? n + (n << 1) : Integer.MAX_VALUE; }\r
+ };\r
+\r
+ static final Scaler BY_4_0 = new Scaler(4.0) {\r
+ @Override public int scaleUpper(int n) { check(n); return n < (1 << 29) ? (n << 2) + 1 : Integer.MAX_VALUE; }\r
+ @Override public int scaleLower(int n) { check(n); return n < (1 << 29) ? (n << 2) : Integer.MAX_VALUE; }\r
+ };\r
+\r
+ private static void check(int n) {\r
+ assert n >= 0 : "n should be non-negative, otherwise result is undefined";\r
+ }\r
+\r
+ final double scale;\r
+\r
+ private Scaler(double scale) {\r
+ this.scale = scale;\r
+ }\r
+\r
+ public int scaleUpper(int n) {\r
+ check(n);\r
+ int lower = (int) ((double) n * scale);\r
+ return lower < Integer.MAX_VALUE ? lower + 1 : Integer.MAX_VALUE;\r
+ }\r
+\r
+ public int scaleLower(int n) {\r
+ check(n);\r
+ return (int) ((double) n * scale);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2014 the original author or authors.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+\r
+package org.simantics.scl.runtime.chr;\r
+\r
+/**\r
+ * An exception thrown when element or entry couldn't be inserted into the hash container\r
+ * due to implementation limitations.\r
+ */\r
+public class CHRHashOverflowException extends IllegalStateException {\r
+ private static final long serialVersionUID = 0L;\r
+ public CHRHashOverflowException() {\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.scl.runtime.chr;\r
+\r
+public interface Fact {\r
+ /**\r
+ * Activates the fact with the given priority. The method returns\r
+ * the new priority of the fact or a negative number if the fact\r
+ * is deactivated.\r
+ */\r
+ int activate(Object context, int priority);\r
+ boolean isAlive();\r
+}\r
--- /dev/null
+package org.simantics.scl.runtime.chr;\r
+\r
+import java.util.Arrays;\r
+\r
+public class FactActivationQueue {\r
+ public static final boolean TRACE = false;\r
+ \r
+ private final PriorityContainer[] containers;\r
+ private PriorityContainer[] activeContainers = new PriorityContainer[8];\r
+ private int activeContainerCount; \r
+\r
+ public FactActivationQueue(int priorityCount) {\r
+ if(TRACE)\r
+ System.out.println("priorityCount = " + priorityCount);\r
+ containers = new PriorityContainer[priorityCount];\r
+ for(int i=0;i<priorityCount;++i)\r
+ containers[i] = new PriorityContainer(i); \r
+ }\r
+ \r
+ /**\r
+ * Adds a new fact with a given priority\r
+ */\r
+ public void add(int priority, Fact item) {\r
+ if(TRACE)\r
+ System.out.println("FactActivationQueue.add " + priority + "@" + item);\r
+ PriorityContainer container = containers[priority];\r
+ if(container.size == 0)\r
+ activateContainer(container);\r
+ container.push(item);\r
+ }\r
+ \r
+ private void activateContainer(PriorityContainer container) {\r
+ if(TRACE)\r
+ System.out.println("FactActivationQueue.activate priority " + container.priority);\r
+ if(activeContainers.length == activeContainerCount)\r
+ activeContainers = Arrays.copyOf(activeContainers, activeContainerCount*2);\r
+ adjustUpwards(activeContainerCount, container);\r
+ ++activeContainerCount;\r
+ }\r
+\r
+ private void deactivateContainer() {\r
+ --activeContainerCount;\r
+ adjustDownwards(0, activeContainers[activeContainerCount]);\r
+ activeContainers[activeContainerCount] = null;\r
+ }\r
+\r
+ private void adjustDownwards(int pos, PriorityContainer item) {\r
+ int priority = item.priority;\r
+ while(true) {\r
+ int npos = 2*pos+1;\r
+ if(npos+1 >= activeContainerCount) {\r
+ if(npos >= activeContainerCount)\r
+ break;\r
+ PriorityContainer item1 = activeContainers[npos];\r
+ if(priority > item1.priority) {\r
+ activeContainers[pos] = item1;\r
+ activeContainers[npos] = item;\r
+ return;\r
+ }\r
+ else\r
+ break;\r
+ }\r
+ PriorityContainer item1 = activeContainers[npos];\r
+ PriorityContainer item2 = activeContainers[npos+1];\r
+ if(priority < item1.priority) {\r
+ if(priority < item2.priority)\r
+ break;\r
+ }\r
+ else {\r
+ if(item1.priority < item2.priority) {\r
+ activeContainers[pos] = item1;\r
+ pos = npos;\r
+ continue;\r
+ }\r
+ }\r
+ activeContainers[pos] = item2;\r
+ pos = npos+1;\r
+ }\r
+ activeContainers[pos] = item;\r
+ }\r
+\r
+ private void adjustUpwards(int pos, PriorityContainer item) {\r
+ int priority = item.priority;\r
+ while(pos > 0) {\r
+ int npos = (pos-1)/2;\r
+ PriorityContainer item1 = activeContainers[npos];\r
+ if(item1.priority > priority) {\r
+ activeContainers[pos] = item1;\r
+ pos = npos;\r
+ }\r
+ else\r
+ break;\r
+ }\r
+ activeContainers[pos] = item;\r
+ }\r
+ \r
+ /**\r
+ * Activates all facts with priority less than the current priority\r
+ */\r
+ public void activate(Object context, int currentPriority) {\r
+ if(TRACE)\r
+ System.out.println("FactActivationQueue.activate " + currentPriority);\r
+ while(activeContainerCount > 0) {\r
+ PriorityContainer topContainer = activeContainers[0];\r
+ int priority = topContainer.priority;\r
+ if(priority >= currentPriority)\r
+ return;\r
+ \r
+ Fact fact = topContainer.pop();\r
+ if(topContainer.size == 0)\r
+ deactivateContainer();\r
+ \r
+ int newPriority = fact.activate(context, priority);\r
+ if(TRACE)\r
+ System.out.println(" [" + currentPriority + "] " + fact + " oldPriority=" + priority + ", newPriority=" + newPriority);\r
+ if(newPriority >= 0)\r
+ add(newPriority, fact);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.runtime.chr;\r
+\r
+import java.util.Arrays;\r
+\r
+class PriorityContainer {\r
+ private static final boolean CLEANUP_ENABLED = true;\r
+ \r
+ final int priority;\r
+ Fact[] facts = new Fact[4];\r
+ int size;\r
+\r
+ public PriorityContainer(int priority) {\r
+ this.priority = priority;\r
+ }\r
+ \r
+ public void push(Fact item) {\r
+ if(size == facts.length)\r
+ increaseCapacity();\r
+ facts[size++] = item;\r
+ }\r
+\r
+ private void increaseCapacity() {\r
+ if(CLEANUP_ENABLED) {\r
+ // Cleanup dead facts\r
+ int j=0;\r
+ for(int i=0;i<size;++i) {\r
+ Fact fact = facts[i];\r
+ if(fact.isAlive())\r
+ facts[j++] = fact;\r
+ }\r
+ size = j;\r
+ }\r
+ \r
+ // Resize if necessary\r
+ if(size >= facts.length*3/4)\r
+ facts = Arrays.copyOf(facts, size*2);\r
+ }\r
+\r
+ public Fact pop() {\r
+ return facts[--size];\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.runtime.tests;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.LinkedHashSet;\r
+import java.util.List;\r
+import java.util.Random;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.simantics.scl.runtime.chr.CHRHashIndex;\r
+\r
+import gnu.trove.map.hash.TIntObjectHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class TestCHRHashIndex {\r
+ \r
+ Random random;\r
+ Store store;\r
+ Store2 store2;\r
+ THashSet<Fact> aliveFacts = new THashSet<Fact>(); \r
+ \r
+ public static class Store {\r
+ CHRHashIndex bfIndex = new CHRHashIndex() {\r
+ @Override\r
+ protected boolean keyEquals(Object a, Object b) {\r
+ return ((Fact)a).a == ((Fact)b).a;\r
+ }\r
+ @Override\r
+ protected int keyHashCode(Object key) {\r
+ return ((Fact)key).a;\r
+ }\r
+ };\r
+ }\r
+ \r
+ public static class Store2 {\r
+ TIntObjectHashMap<LinkedHashSet<Fact>> bfIndex = new TIntObjectHashMap<LinkedHashSet<Fact>>(); \r
+ }\r
+ \r
+ public static class Fact {\r
+ public int a; // key\r
+ public int b;\r
+ public Fact bfPrev;\r
+ public Fact bfNext;\r
+ \r
+ public Fact(int a, int b) {\r
+ this.a = a;\r
+ this.b = b;\r
+ }\r
+ \r
+ public void add(Store store) {\r
+ bfNext = (Fact)store.bfIndex.addFreshAndReturnOld(this);\r
+ if(bfNext != null)\r
+ bfNext.bfPrev = this;\r
+ }\r
+ \r
+ public void remove(Store store) {\r
+ if(bfPrev == null) {\r
+ if(bfNext == null)\r
+ store.bfIndex.removeKnownToExistKey(this);\r
+ else {\r
+ bfNext.bfPrev = null;\r
+ store.bfIndex.replaceKnownToExistKey(this, bfNext);\r
+ }\r
+ }\r
+ else {\r
+ bfPrev.bfNext = bfNext;\r
+ if(bfNext != null)\r
+ bfNext.bfPrev = bfPrev;\r
+ }\r
+ }\r
+ \r
+ public List<Fact> get(Store store) {\r
+ Object r = store.bfIndex.getEqual(this);\r
+ if(r == null)\r
+ return Collections.emptyList();\r
+ else {\r
+ ArrayList<Fact> result = new ArrayList<Fact>(); \r
+ for(Fact cur=(Fact)r;cur!=null;cur=cur.bfNext)\r
+ result.add(cur);\r
+ Collections.reverse(result);\r
+ return result;\r
+ }\r
+ }\r
+ \r
+ public void add(Store2 store) {\r
+ LinkedHashSet<Fact> set = store.bfIndex.get(a);\r
+ if(set == null) {\r
+ set = new LinkedHashSet<>();\r
+ store.bfIndex.put(a, set);\r
+ }\r
+ set.add(this);\r
+ }\r
+ \r
+ public void remove(Store2 store) {\r
+ store.bfIndex.get(a).remove(this);\r
+ }\r
+ \r
+ public List<Fact> get(Store2 store) {\r
+ LinkedHashSet<Fact> set = store.bfIndex.get(a);\r
+ if(set == null)\r
+ return Collections.emptyList();\r
+ else\r
+ return new ArrayList<Fact>(set);\r
+ }\r
+ }\r
+ \r
+ @Before\r
+ public void init() {\r
+ random = new Random(123L);\r
+ store = new Store();\r
+ store2 = new Store2();\r
+ }\r
+ \r
+ public Fact createFact(int maxA, int maxB) {\r
+ return new Fact(random.nextInt(maxA), random.nextInt(maxB));\r
+ }\r
+ \r
+ public void add(Fact fact) {\r
+ fact.add(store);\r
+ fact.add(store2);\r
+ aliveFacts.add(fact);\r
+ }\r
+ \r
+ public void remove(Fact fact) {\r
+ fact.remove(store);\r
+ fact.remove(store2);\r
+ aliveFacts.remove(fact);\r
+ }\r
+ \r
+ public void checkConsistency() {\r
+ TIntHashSet keys = new TIntHashSet();\r
+ for(Fact fact : aliveFacts)\r
+ keys.add(fact.a);\r
+ Fact temp = new Fact(0, 0);\r
+ for(int a : keys.toArray()) {\r
+ temp.a = a;\r
+ Assert.assertEquals(temp.get(store2), temp.get(store));\r
+ }\r
+ TIntHashSet keys2 = new TIntHashSet();\r
+ for(Fact fact : store.bfIndex.toArray(new Fact[keys.size()]))\r
+ keys2.add(fact.a);\r
+ Assert.assertEquals(keys, keys2);\r
+ }\r
+ \r
+ @Test\r
+ public void testStore() {\r
+ for(int i=0;;++i) {\r
+ System.out.println("Run " + i);\r
+ for(int j=0;j<1000000;++j)\r
+ add(createFact(10000, 1000000));\r
+ checkConsistency();\r
+ ArrayList<Fact> factArray = new ArrayList<Fact>(aliveFacts);\r
+ Collections.shuffle(factArray, random);\r
+ for(Fact fact : factArray.subList(100000, factArray.size()))\r
+ remove(fact);\r
+ checkConsistency();\r
+ }\r
+ }\r
+ \r
+}\r
--- /dev/null
+package org.simantics.scl.runtime.tests;\r
+\r
+import java.util.Random;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+import org.simantics.scl.runtime.chr.Fact;\r
+import org.simantics.scl.runtime.chr.FactActivationQueue;\r
+\r
+import gnu.trove.list.array.TIntArrayList;\r
+\r
+public class TestFactActivationQueue {\r
+ public static Random RANDOM = new Random();\r
+ \r
+ private static class MyFact implements Fact {\r
+ TIntArrayList list;\r
+ int priority;\r
+\r
+ public MyFact(TIntArrayList list, int priority) {\r
+ this.list = list;\r
+ this.priority = priority;\r
+ }\r
+\r
+ @Override\r
+ public int activate(Object context, int priority) {\r
+ Assert.assertEquals(this.priority, priority);\r
+ list.add(priority);\r
+ return -1;\r
+ }\r
+\r
+ @Override\r
+ public boolean isAlive() {\r
+ return true;\r
+ }\r
+ }\r
+ \r
+ private void testRandomly(int priorities, int size) {\r
+ FactActivationQueue queue = new FactActivationQueue(priorities);\r
+ TIntArrayList list = new TIntArrayList(size); \r
+ for(int i=0;i<size;++i) {\r
+ int val = RANDOM.nextInt(priorities);\r
+ queue.add(val, new MyFact(list, val));\r
+ }\r
+ queue.activate(null, priorities);\r
+ Assert.assertEquals(size, list.size());\r
+ for(int i=1;i<list.size();++i) {\r
+ int a = list.get(i-1);\r
+ int b = list.get(i);\r
+ Assert.assertTrue(a <= b);\r
+ }\r
+ }\r
+ \r
+ @Test\r
+ public void testRandomly() {\r
+ for(int i=0;i<10000;++i)\r
+ testRandomly(10, 10000);\r
+ }\r
+}\r
org.simantics.scl.runtime;bundle-version="0.2.0",
gnu.trove3;bundle-version="3.0.0",
org.simantics.scl.osgi;bundle-version="1.0.0",
- org.simantics.scl.compiler,
+ org.simantics.scl.compiler;bundle-version="0.6.0",
org.junit;bundle-version="4.12.0";resolution:=optional
Export-Package: org.simantics.scl.ui.console,
org.simantics.scl.ui.editor,
package org.simantics.scl.ui.editor;\r
\r
import org.eclipse.jface.preference.IPreferenceStore;\r
-import org.eclipse.jface.resource.FontDescriptor;\r
import org.eclipse.jface.resource.ResourceManager;\r
import org.eclipse.jface.text.DefaultInformationControl;\r
+import org.eclipse.jface.text.DefaultTextHover;\r
import org.eclipse.jface.text.IDocument;\r
import org.eclipse.jface.text.IInformationControl;\r
import org.eclipse.jface.text.IInformationControlCreator;\r
import org.eclipse.jface.text.ITextHover;\r
-import org.eclipse.jface.text.TextAttribute;\r
import org.eclipse.jface.text.contentassist.ContentAssistant;\r
import org.eclipse.jface.text.contentassist.IContentAssistant;\r
import org.eclipse.jface.text.presentation.IPresentationReconciler;\r
-import org.eclipse.jface.text.presentation.PresentationReconciler;\r
-import org.eclipse.jface.text.rules.DefaultDamagerRepairer;\r
-import org.eclipse.jface.text.rules.EndOfLineRule;\r
-import org.eclipse.jface.text.rules.IRule;\r
-import org.eclipse.jface.text.rules.ITokenScanner;\r
-import org.eclipse.jface.text.rules.IWordDetector;\r
-import org.eclipse.jface.text.rules.MultiLineRule;\r
-import org.eclipse.jface.text.rules.PatternRule;\r
-import org.eclipse.jface.text.rules.RuleBasedScanner;\r
-import org.eclipse.jface.text.rules.Token;\r
-import org.eclipse.jface.text.rules.WordRule;\r
import org.eclipse.jface.text.source.DefaultAnnotationHover;\r
import org.eclipse.jface.text.source.IAnnotationHover;\r
import org.eclipse.jface.text.source.ISourceViewer;\r
import org.eclipse.jface.text.source.SourceViewerConfiguration;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.graphics.Font;\r
-import org.eclipse.swt.graphics.RGB;\r
import org.eclipse.swt.widgets.Shell;\r
import org.eclipse.ui.editors.text.EditorsUI;\r
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;\r
import org.simantics.scl.ui.Activator;\r
import org.simantics.scl.ui.editor.completion.SCLCompletionAssistProcessor;\r
-import org.simantics.scl.ui.editor.completion.SCLEditorTextHover;\r
import org.simantics.scl.ui.editor.completion.SCLTextEditorEnvironment;\r
-import org.simantics.scl.ui.info.SCLInfo;\r
+import org.simantics.scl.ui.editor2.SCLPresentationReconciler;\r
\r
public class SCLSourceViewerConfigurationNew extends SourceViewerConfiguration {\r
\r
}\r
\r
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {\r
- PresentationReconciler reconciler = new PresentationReconciler();\r
- \r
- DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getSclTokenScanner());\r
- \r
- reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);\r
- reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);\r
- \r
- return reconciler;\r
- }\r
- \r
- private static final FontDescriptor FONT_NORMAL = FontDescriptor.createFrom("Consolas", 10, SWT.NORMAL);\r
- private static final FontDescriptor FONT_BOLD = FontDescriptor.createFrom("Consolas", 10, SWT.BOLD);\r
- \r
- ITokenScanner getSclTokenScanner() {\r
- RuleBasedScanner scanner = new RuleBasedScanner();\r
- \r
- Font font = resourceManager.createFont(FONT_NORMAL);\r
- Font boldFont = resourceManager.createFont(FONT_BOLD);\r
- \r
- Token defaultToken = new Token(\r
- new TextAttribute(\r
- resourceManager.createColor(new RGB(0, 0, 0)),\r
- null,\r
- 0,\r
- font\r
- ));\r
- Token string = new Token(new TextAttribute(\r
- resourceManager.createColor(new RGB(42, 0, 255)),\r
- null,\r
- 0,\r
- font\r
- ));\r
- Token reserved = new Token(\r
- new TextAttribute(\r
- resourceManager.createColor(new RGB(127, 0, 85)),\r
- null,\r
- SWT.BOLD,\r
- boldFont\r
- ));\r
- Token comment = new Token(new TextAttribute(\r
- resourceManager.createColor(new RGB(63, 127, 95)),\r
- null,\r
- 0,\r
- font\r
- ));\r
-\r
- WordRule reservedWord = new WordRule(new IWordDetector() { \r
- @Override\r
- public boolean isWordStart(char c) {\r
- return Character.isJavaIdentifierStart(c);\r
- }\r
- \r
- @Override\r
- public boolean isWordPart(char c) {\r
- return Character.isJavaIdentifierPart(c) || c=='.';\r
- }\r
- });\r
-\r
- for(String word : SCLInfo.RESERVED_WORDS)\r
- reservedWord.addWord(word, reserved);\r
- \r
- IRule[] rules = new IRule[] {\r
- //new MultiLineRule("\"\"\"", "\"\"\"", string),\r
- new PatternRule("\"", "\"", string, '\\', true),\r
- new MultiLineRule("/*", "*/", comment),\r
- new EndOfLineRule("//", comment),\r
- reservedWord\r
- };\r
- scanner.setRules(rules);\r
- scanner.setDefaultReturnToken(defaultToken);\r
- \r
- return scanner;\r
+ return new SCLPresentationReconciler(resourceManager);\r
}\r
\r
@Override\r
public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {\r
- return new SCLEditorTextHover(sourceViewer, sclTextEditorEnvironment);\r
+ //return new SCLEditorTextHover(sourceViewer, sclTextEditorEnvironment);\r
+ return new DefaultTextHover(sourceViewer);\r
}\r
\r
@Override\r
\r
import java.io.StringReader;\r
import java.util.ArrayList;\r
-import java.util.Arrays;\r
import java.util.Collections;\r
import java.util.Comparator;\r
import java.util.List;\r
import org.simantics.scl.compiler.module.ImportDeclaration;\r
import org.simantics.scl.compiler.module.Module;\r
import org.simantics.scl.compiler.module.repository.ImportFailureException;\r
-import org.simantics.scl.compiler.source.TextualModuleSource;\r
import org.simantics.scl.compiler.types.TCon;\r
import org.simantics.scl.osgi.SCLOsgi;\r
\r
String contents = document.get();\r
String[] lines = contents.split("\\R+");\r
List<ImportDeclaration> imports = new ArrayList<>();\r
- imports.addAll(Arrays.asList(TextualModuleSource.DEFAULT_IMPORTS));\r
+ imports.add(new ImportDeclaration("StandardLibrary", ""));\r
for (String line : lines) {\r
line = line.trim();\r
if (line.startsWith("import") || line.startsWith("include")) {\r
--- /dev/null
+package org.simantics.scl.ui.editor2;\r
+\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;\r
+import org.eclipse.jface.text.rules.IToken;\r
+\r
+public class DebugPartionTokenScanner implements IPartitionTokenScanner {\r
+ IPartitionTokenScanner base;\r
+\r
+ public DebugPartionTokenScanner(IPartitionTokenScanner base) {\r
+ this.base = base;\r
+ }\r
+\r
+ @Override\r
+ public void setRange(IDocument document, int offset, int length) {\r
+ System.out.println(">>> setRange(" + offset + ", " + length + ")");\r
+ base.setRange(document, offset, length);\r
+ }\r
+\r
+ @Override\r
+ public IToken nextToken() {\r
+ IToken result = base.nextToken();\r
+ System.out.println(">>> nextToken -> " + result + " " + result.getData());\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public int getTokenOffset() {\r
+ int result = base.getTokenOffset();\r
+ System.out.println(">>> getTokenOffset -> " + result);\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public int getTokenLength() {\r
+ int result = base.getTokenLength();\r
+ System.out.println(">>> getTokenLength -> " + result);\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {\r
+ System.out.println(">>> setPartialRange(" + offset + ", " + length + ", " + contentType + ", " + partitionOffset + ")");\r
+ base.setPartialRange(document, offset, length, contentType, partitionOffset);\r
+ }\r
+ \r
+ \r
+}\r
import org.eclipse.jface.operation.IRunnableContext;\r
import org.eclipse.jface.text.Document;\r
import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IDocumentPartitioner;\r
+import org.eclipse.jface.text.rules.FastPartitioner;\r
import org.eclipse.jface.text.source.AnnotationModel;\r
import org.eclipse.jface.text.source.IAnnotationModel;\r
import org.eclipse.ui.texteditor.AbstractDocumentProvider;\r
new Status(Status.ERROR, "org.simantics.scl.ui", "Reading SCL module failed.", e)\r
);\r
}\r
+ IDocumentPartitioner partitioner = new FastPartitioner(new SCLPartitionScanner(), SCLPartitionScanner.PARTITION_TYPES);\r
+ partitioner.connect(document);\r
+ document.setDocumentPartitioner(partitioner);\r
sourceViewer.updateCompletionAssistModuleName(source.getModuleName());\r
return document;\r
}\r
--- /dev/null
+package org.simantics.scl.ui.editor2;\r
+\r
+import org.eclipse.jface.text.rules.EndOfLineRule;\r
+import org.eclipse.jface.text.rules.IPredicateRule;\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.MultiLineRule;\r
+import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;\r
+import org.eclipse.jface.text.rules.SingleLineRule;\r
+import org.eclipse.jface.text.rules.Token;\r
+\r
+public class SCLPartitionScanner extends RuleBasedPartitionScanner {\r
+ public static final String SCL_COMMENT = "COMMENT";\r
+ public static final String SCL_STRING = "STRING";\r
+ \r
+ public static final IToken COMMENT_TOKEN = new Token(SCL_COMMENT);\r
+ public static final IToken STRING_TOKEN = new Token(SCL_STRING);\r
+ \r
+ public static final String[] PARTITION_TYPES = new String[] {\r
+ SCL_COMMENT,\r
+ SCL_STRING\r
+ };\r
+ \r
+ public SCLPartitionScanner() {\r
+ super();\r
+\r
+ setPredicateRules(new IPredicateRule[] {\r
+ new EndOfLineRule("//", COMMENT_TOKEN),\r
+ new MultiLineRule("\"\"\"", "\"\"\"", STRING_TOKEN, (char) 0, true),\r
+ new SingleLineRule("\"", "\"", STRING_TOKEN, '\\'),\r
+ new MultiLineRule("/*", "*/", COMMENT_TOKEN, (char) 0, true),\r
+ });\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.ui.editor2;\r
+\r
+import org.eclipse.jface.resource.FontDescriptor;\r
+import org.eclipse.jface.resource.ResourceManager;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.TextAttribute;\r
+import org.eclipse.jface.text.presentation.PresentationReconciler;\r
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;\r
+import org.eclipse.jface.text.rules.IRule;\r
+import org.eclipse.jface.text.rules.ITokenScanner;\r
+import org.eclipse.jface.text.rules.IWhitespaceDetector;\r
+import org.eclipse.jface.text.rules.IWordDetector;\r
+import org.eclipse.jface.text.rules.RuleBasedScanner;\r
+import org.eclipse.jface.text.rules.Token;\r
+import org.eclipse.jface.text.rules.WhitespaceRule;\r
+import org.eclipse.jface.text.rules.WordRule;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Font;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.simantics.scl.ui.info.SCLInfo;\r
+\r
+public class SCLPresentationReconciler extends PresentationReconciler {\r
+ private static final FontDescriptor FONT_NORMAL = FontDescriptor.createFrom("Consolas", 10, SWT.NORMAL);\r
+ private static final FontDescriptor FONT_BOLD = FontDescriptor.createFrom("Consolas", 10, SWT.BOLD);\r
+ \r
+ public SCLPresentationReconciler(ResourceManager resourceManager) {\r
+ Font font = resourceManager.createFont(FONT_NORMAL);\r
+ {\r
+ DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new SingleTokenScanner(new TextAttribute(\r
+ resourceManager.createColor(new RGB(63, 127, 95)),\r
+ null,\r
+ 0,\r
+ font\r
+ )));\r
+ setDamager(dr, SCLPartitionScanner.SCL_COMMENT);\r
+ setRepairer(dr, SCLPartitionScanner.SCL_COMMENT);\r
+ }\r
+ {\r
+ DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new StringTokenScanner(new TextAttribute(\r
+ resourceManager.createColor(new RGB(42, 0, 255)),\r
+ null,\r
+ 0,\r
+ font\r
+ )));\r
+ setDamager(dr, SCLPartitionScanner.SCL_STRING);\r
+ setRepairer(dr, SCLPartitionScanner.SCL_STRING);\r
+ }\r
+ {\r
+ DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getSclTokenScanner(resourceManager));\r
+\r
+ setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);\r
+ setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);\r
+ }\r
+ }\r
+ \r
+ private static ITokenScanner getSclTokenScanner(ResourceManager resourceManager) {\r
+ RuleBasedScanner scanner = new RuleBasedScanner();\r
+ \r
+ Token defaultToken = new Token(\r
+ new TextAttribute(\r
+ resourceManager.createColor(new RGB(0, 0, 0)),\r
+ null,\r
+ 0,\r
+ resourceManager.createFont(FONT_NORMAL)\r
+ ));\r
+ Token reserved = new Token(\r
+ new TextAttribute(\r
+ resourceManager.createColor(new RGB(127, 0, 85)),\r
+ null,\r
+ SWT.BOLD,\r
+ resourceManager.createFont(FONT_BOLD)\r
+ ));\r
+\r
+ WordRule reservedWord = new WordRule(new IWordDetector() {\r
+ @Override\r
+ public boolean isWordStart(char c) {\r
+ return ('a' <= c && c <= 'z')\r
+ || ('A' <= c && c <= 'Z')\r
+ || c == '_' || c == '?';\r
+ }\r
+ @Override\r
+ public boolean isWordPart(char c) {\r
+ return ('a' <= c && c <= 'z')\r
+ || ('A' <= c && c <= 'Z')\r
+ || ('0' <= c && c <= '9')\r
+ || c == '_' || c == '.' || c == '\'';\r
+ }\r
+ }, defaultToken);\r
+\r
+ for(String word : SCLInfo.RESERVED_WORDS)\r
+ reservedWord.addWord(word, reserved);\r
+ \r
+ scanner.setRules(new IRule[] {\r
+ new WhitespaceRule(new IWhitespaceDetector() {\r
+ @Override\r
+ public boolean isWhitespace(char c) {\r
+ return c==' ' || c=='\t' || c=='\n' || c=='\r';\r
+ }\r
+ }, defaultToken),\r
+ reservedWord\r
+ });\r
+ scanner.setDefaultReturnToken(defaultToken);\r
+ \r
+ return scanner;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.scl.ui.editor2;\r
+\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.RuleBasedScanner;\r
+import org.eclipse.jface.text.rules.Token;\r
+\r
+public class SingleTokenScanner extends RuleBasedScanner {\r
+ public SingleTokenScanner(Object attribute) {\r
+ setDefaultReturnToken(new Token(attribute));\r
+ }\r
+ \r
+ @Override\r
+ public IToken nextToken() {\r
+ return super.nextToken();\r
+ }\r
+ \r
+ @Override\r
+ public void setRange(IDocument document, int offset, int length) {\r
+ super.setRange(document, offset, length);\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.scl.ui.editor2;\r
+\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.RuleBasedScanner;\r
+import org.eclipse.jface.text.rules.Token;\r
+\r
+public class StringTokenScanner extends RuleBasedScanner {\r
+ public StringTokenScanner(Object attribute) {\r
+ setDefaultReturnToken(new Token(attribute));\r
+ }\r
+ \r
+ @Override\r
+ public IToken nextToken() {\r
+ return super.nextToken();\r
+ }\r
+ \r
+ @Override\r
+ public void setRange(IDocument document, int offset, int length) {\r
+ super.setRange(document, offset, length);\r
+ }\r
+}
\ No newline at end of file
"select",\r
"enforce",\r
"transformation",\r
+ "when"\r
};\r
\r
}\r
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: org.junit;bundle-version="4.12.0",
org.simantics.scl.compiler;bundle-version="0.5.0",
- org.simantics.scl.osgi;bundle-version="1.0.4",
gnu.trove3,
+ org.simantics.scl.osgi;bundle-version="1.0.4",
org.objectweb.asm.util,
+ ch.qos.logback.classic;bundle-version="1.1.7",
+ ch.qos.logback.core;bundle-version="1.1.7",
+ org.apache.commons.collections;bundle-version="3.2.2",
org.eclipse.equinox.ds;bundle-version="1.4.300"
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<configuration>\r
+\r
+ <appender name="console" class="ch.qos.logback.core.ConsoleAppender">\r
+ <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->\r
+ <encoder>\r
+ <pattern>%-5p [%d] %c: %m%n%rEx</pattern>\r
+ </encoder>\r
+ </appender>\r
+\r
+ <appender name="async-console" class="ch.qos.logback.classic.AsyncAppender">\r
+ <appender-ref ref="console" />\r
+ </appender>\r
+\r
+ <root level="debug">\r
+ <appender-ref ref="async-console" />\r
+ </root>\r
+</configuration>
\ No newline at end of file
package org.simantics.scl.compiler.tests;
-import org.junit.Ignore;
import org.junit.Test;
public class ActiveTests extends TestBase {
*/
//@Test public void CityoptSetup() { test(); }
- @Test public void EmptyLet() { test(); }
}
-package org.simantics.scl.compiler.tests;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-
-@RunWith(Suite.class)
-@SuiteClasses({
- ActiveTests.class
-})
-public class TestActive {
-}
+package org.simantics.scl.compiler.tests;\r
+\r
+import org.junit.runner.RunWith;\r
+import org.junit.runners.Suite;\r
+import org.junit.runners.Suite.SuiteClasses;\r
+import org.simantics.scl.compiler.tests.markdown.MarkdownTests;\r
+\r
+@RunWith(Suite.class)\r
+@SuiteClasses({\r
+ TestRegression.class,\r
+ ActiveTests.class,\r
+ MarkdownTests.class\r
+})\r
+public class AllTestsForCoverage {\r
+\r
+}\r
package org.simantics.scl.compiler.tests;
-import org.junit.AfterClass;
-import org.junit.Ignore;
import org.junit.Test;
-import org.simantics.scl.compiler.errors.Failable;
-import org.simantics.scl.compiler.module.Module;
-import org.simantics.scl.compiler.module.coverage.CoverageUtils;
-import org.simantics.scl.compiler.module.coverage.ModuleCoverage;
import org.simantics.scl.compiler.top.ValueNotFound;
-import org.simantics.scl.runtime.profiling.BranchPoint;
public class ModuleRegressionTests extends TestBase {
@Test public void ClashingData() { test(); }
@Test public void ClashingInstance() { test(); }
@Test public void ClashingValueType() { test(); }
+ @Test public void ClosingBrace() { test(); }
@Test public void Collaz() { test(); }
@Test public void Compose() { test(); }
@Test public void Composition() { test(); }
@Test public void Effects4() { test(); }
@Test public void Effects5() { test(); }
@Test public void Effects6() { test(); }
+ @Test public void EmptyLet() { test(); }
@Test(expected=ValueNotFound.class)
public void EmptyModule() throws ValueNotFound {
test(new String[]{"EmptyModule"}, new String[]{""});
@Test public void Fibonacci2() { test(); }
@Test public void Fibonacci3() { test(); }
@Test public void FingerTree() { test(); }
- @Ignore
- @Test public void FoldMissingInitialValue() { test(); }
@Test public void FoldlBuild1() { test(); }
@Test public void FoldlBuild2() { test(); }
+ @Test public void FoldMissingInitialValue() { test(); }
@Test public void Forall1() { test(); }
@Test public void Forall2() { test(); }
@Test public void Forall3() { test(); }
- @Ignore
@Test public void Formula() { test(); }
@Test public void FromDynamic() { test(); }
@Test public void FromDynamic2() { test(); }
@Test public void GuardedExpressionBug() { test(); }
@Test public void Guards1() { test(); }
@Test public void Guards2() { test(); }
- @Test public void IdAsOperator() { test(); }
+ @Test public void IdAsOperator() { test(); }
+ @Test public void IfWithoutElse() { test(); }
@Test public void IllegalChar() { test(); }
@Test public void ImportJavaConstructor() { test(); }
@Test public void ImportRef() { test(); }
@Test public void JavaTypes() { test(); }
@Test public void Kinds1() { test(); }
@Test public void Lambda() { test(); }
+ @Test public void LambdaMatch() { test(); }
@Test public void Layout1() { test(); }
@Test public void List() { test(); }
- @Test public void ListError1() { test(); }
- @Test public void ListError2() { test(); }
+ @Test public void ListError1() { test(); }
+ @Test public void ListError2() { test(); }
@Test public void ListSyntax() { test(); }
@Test public void ListSyntax10() { test(); }
@Test public void ListSyntax11() { test(); }
@Test public void Macros1() { test(); }
@Test public void Macros2() { test(); }
@Test public void Macros4() { test(); }
- @Test public void Map1() { test(); }
- @Test public void MarketModel() { test(); }
+ @Test public void Map1() { test(); }
+ @Test public void MarketModel() { test(); }
@Test public void Matching() { test(); }
@Test public void Matching2() { test(); }
@Test public void Matching4() { test(); }
@Test public void MatchingWithoutTypeAnnotations() { test(); }
@Test public void MaximumBy() { test(); }
@Test public void Maybe1() { test(); }
- @Test public void Maybe2() { test(); }
- @Test public void Maybe3() { test(); }
+ @Test public void Maybe2() { test(); }
+ @Test public void Maybe3() { test(); }
@Test public void Maybe4() { test(); }
@Test public void MissingEffect() { test(); }
@Test public void MissingMethod() { test(); }
@Test public void ModuleInitialization() { test(); }
@Test public void MonadBug1() { test(); }
- @Test public void MonadSyntax1() { test(); }
@Test public void Monads1() { test(); }
- @Test public void NoDefinitionErrorMessage() { test(); }
+ @Test public void MonadSyntax1() { test(); }
+ @Test public void NoDefinitionErrorMessage() { test(); }
@Test public void NoInstance() { test(); }
@Test public void NoInstance2() { test(); }
@Test public void NonassociativeOperator() { test(); }
@Test public void NonexistentTypeClassInAnnotation() { test(); }
- @Test public void NonexistingEffect() { test(); }
- @Test public void OneLineMatch() { test(); }
+ @Test public void NonexistingEffect() { test(); }
+ @Test public void OneLineMatch() { test(); }
@Test public void OpenString1() { test(); }
@Test public void OpenString2() { test(); }
@Test public void OverloadedArithmetic1() { test(); }
@Test public void OverloadedArithmetic2() { test(); }
@Test public void OverloadedArithmetic3() { test(); }
@Test public void OverloadedLiterals2() { test(); }
- @Ignore
- @Test public void Overloading1() { test(); }
- @Test public void Parsing() { test(); }
+ @Test public void Overloading1() { test(); }
+ @Test public void Parsing() { test(); }
@Test public void PolymorphicRecursion() { test(); }
@Test public void PolymorphicRecursion2() { test(); }
- @Test public void Polynomials() { test(); }
- @Test public void PrecedenceOfNonoperators() { test(); }
+ @Test public void Polynomials() { test(); }
+ @Test public void PrecedenceOfNonoperators() { test(); }
@Test public void Primes() { test(); }
@Test public void Proc1() { test(); }
@Test public void Proc2() { test(); }
@Test public void RecursiveValues4() { test(); }
@Test public void RedBlackTrees() { test(); }
@Test public void Relations1() { test(); }
- @Test public void Relations2() { test(); }
- @Test public void RepeatedVariableInPattern() { test(); }
- @Test public void SSATypingBug() { test(); }
+ @Test public void Relations2() { test(); }
+ @Test public void RepeatedVariableInPattern() { test(); }
@Test public void Scanl() { test(); }
@Test public void Search() { test(); }
@Test public void Sections() { test(); }
@Test public void SelfReferringContextInTypeClass() { test(); }
@Test public void Serialization2() { test(); }
@Test public void Serialization3() { test(); }
+ @Test public void Serialization4() { test(); }
@Test public void SharedTypeVariable() { test(); }
@Test public void ShortcutFusion() { test(); }
@Test public void Show1() { test(); }
@Test public void SinConst1() { test(); }
@Test public void Sort() { test(); }
@Test public void Sort2() { test(); }
+ @Test public void SSATypingBug() { test(); }
@Test public void StreamFusion() { test(); }
@Test public void StringEscape() { test(); }
@Test public void StringInterpolation1() { test(); }
- @Test public void StringMatching1() { test(); }
+ @Test public void StringInterpolation2() { test(); }
+ @Test public void StringInterpolation3() { test(); }
+ @Test public void StringMatching1() { test(); }
@Test public void SumOfInverses2() { test(); }
@Test public void TooManyParametersToSin() { test(); }
@Test public void Transformation1() { test(); }
@Test public void TypeAliasRefsToTypeAlias() { test(); }
@Test public void TypeAnnotation1() { test(); }
@Test public void TypeAnnotation2() { test(); }
- @Test public void TypeClass() { test(); }
- @Test public void TypeClassBug1() { test(); }
+ @Test public void TypeClass() { test(); }
+ @Test public void TypeClassBug1() { test(); }
@Test(timeout=1000L) public void TypeInferenceBug2() { test(); }
@Test public void TypeOf1() { test(); }
@Test public void TypingBug1() { test(); }
@Test public void Unification1() { test(); }
@Test public void UnknownAnnotation() { test(); }
@Test public void UnresolvedClass() { test(); }
- @Test public void UnresolvedTypeInAnnotation() { test(); }
- @Test public void UnresolvedTypeInInstance() { test(); }
- @Test public void UnresolvedVariable() { test(); }
- @Test public void UnresolvedVariable2() { test(); }
+ @Test public void UnresolvedTypeInAnnotation() { test(); }
+ @Test public void UnresolvedTypeInInstance() { test(); }
+ @Test public void UnresolvedVariable() { test(); }
+ @Test public void UnresolvedVariable2() { test(); }
@Test public void ValueAsOperator() { test(); }
@Test public void ValueConversion() { test(); }
@Test public void Vector1() { test(); }
@Test public void Vector2() { test(); }
+ @Test public void ViewPatterns1() { test(); }
@Test public void Void1() { test(); }
@Test public void Void2() { test(); }
@Test public void Void3() { test(); }
- @Test public void While() { test(); }
+ @Test public void While() { test(); }
@Test public void While2() { test(); }
- @Test public void While3() { test(); }
+ @Test public void While3() { test(); }
@Test public void WrongDefaultMethod() { test(); }
@Test public void WrongInstanceMethod() { test(); }
+ /*
@AfterClass
public static void checkCoverage() {
Failable<Module> maybeModule = PRELUDE_MODULE_REPOSITORY.getModule("Prelude");
System.out.println(bp.getCodeSize());
printCoverageTree(bp.getChildren(), ind+1);
}
- }
+ }*/
}
import org.simantics.scl.compiler.module.repository.UpdateListener;
import org.simantics.scl.compiler.source.ModuleSource;
import org.simantics.scl.compiler.source.StringModuleSource;
-import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
import org.simantics.scl.compiler.source.repository.MapModuleSourceRepository;
-import org.simantics.scl.compiler.source.repository.SourceRepositories;
import org.simantics.scl.compiler.top.ValueNotFound;
public class TestBase {
package org.simantics.scl.compiler.tests;\r
\r
+import org.junit.Assert;\r
import org.junit.Test;\r
import org.simantics.scl.compiler.elaboration.java.Builtins;\r
import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;\r
import org.simantics.scl.compiler.top.ExpressionEvaluator;\r
\r
-import junit.framework.Assert;\r
-\r
public class TestClassNaming {\r
\r
private static class SimpleModuleSource extends StringModuleSource {\r
import org.junit.Test;
import org.simantics.scl.compiler.commands.CommandSession;
import org.simantics.scl.compiler.module.repository.ModuleRepository;
-import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
-import org.simantics.scl.compiler.source.repository.SourceRepositories;
import org.simantics.scl.runtime.reporting.AbstractSCLReportingHandler;
import org.simantics.scl.runtime.reporting.SCLReportingHandler;
import java.util.Arrays;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.runtime.function.Function;
import org.simantics.scl.runtime.tuple.Tuple0;
-import junit.framework.Assert;
-
public class TestExpressionEvaluator {
public static final boolean TIMING = false;
-package org.simantics.scl.compiler.tests.markdown;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.nio.charset.Charset;
-
-import org.simantics.scl.compiler.markdown.internal.MarkdownParser;
-import org.simantics.scl.compiler.markdown.nodes.Node;
-
-public class RunMarkdownTests {
-
- public static int FAILED = 0;
- public static int SUCCEEDED = 1;
- public static int SKIPPED = 2;
-
- public static void main(String[] args) throws IOException {
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(
- RunMarkdownTests.class.getResourceAsStream("spec.txt"),
- Charset.forName("UTF-8")));
-
- StringBuilder in = new StringBuilder();
- StringBuilder out = new StringBuilder();
- int state = 0;
- int testId = 0;
- int passed = 0;
- int failed = 0;
- int skipped = 0;
- while(true) {
- String line = reader.readLine();
- if(line == null)
- break;
- switch(state) {
- case 0:
- if(line.equals("```````````````````````````````` example"))
- ++state;
- break;
- case 1:
- if(line.equals("."))
- ++state;
- else {
- if(in.length() > 0)
- in.append('\n');
- in.append(line);
- }
- break;
- case 2:
- if(line.equals("````````````````````````````````")) {
- ++testId;
- int status = test(testId, in.toString(), out.toString());
- if(status == SUCCEEDED)
- ++passed;
- else if(status == FAILED)
- ++failed;
- else
- ++skipped;
- in = new StringBuilder();
- out = new StringBuilder();
- state = 0;
- }
- else {
- if(out.length() > 0)
- out.append('\n');
- out.append(line);
- }
- break;
- }
- }
-
- System.out.println("Passed: " + passed + "/" + testId);
- System.out.println("Failed: " + failed + "/" + testId);
- System.out.println("Skipped: " + skipped + "/" + testId);
- }
-
- public static int test(int id, String in, String out) throws IOException {
- MarkdownParser parser = new MarkdownParser();
- Node node = parser.parseDocument(new StringReader(in.replace('\u2192', '\t')));
-
- String result = node.toHtml().replace('\t', '\u2192');
-
- boolean passed = result.equals(out);
-
- if(!passed) {
- System.out.println("Example " + id); // + (passed ? " passed" : " failed"));
- System.out.println("---- in --------------------------------------------------------------------");
- System.out.println(in);
- System.out.println("---- expected --------------------------------------------------------------");
- System.out.println(out);
- System.out.println("---- actual ----------------------------------------------------------------");
- System.out.println(result);
- System.out.println("----------------------------------------------------------------------------");
- System.out.println();
- }
-
- return passed ? SUCCEEDED : FAILED;
- }
-
-}
+package org.simantics.scl.compiler.tests.markdown;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.IOException;\r
+import java.io.InputStreamReader;\r
+import java.io.StringReader;\r
+import java.nio.charset.Charset;\r
+\r
+import org.junit.Test;\r
+import org.simantics.scl.compiler.markdown.internal.MarkdownParser;\r
+import org.simantics.scl.compiler.markdown.nodes.Node;\r
+\r
+public class MarkdownTests {\r
+ \r
+ public static int FAILED = 0;\r
+ public static int SUCCEEDED = 1;\r
+ public static int SKIPPED = 2;\r
+ \r
+ @Test\r
+ public void markdownTests() throws IOException {\r
+ BufferedReader reader = new BufferedReader(\r
+ new InputStreamReader(\r
+ MarkdownTests.class.getResourceAsStream("spec.txt"),\r
+ Charset.forName("UTF-8")));\r
+ \r
+ StringBuilder in = new StringBuilder();\r
+ StringBuilder out = new StringBuilder();\r
+ int state = 0;\r
+ int testId = 0;\r
+ int passed = 0;\r
+ int failed = 0;\r
+ int skipped = 0;\r
+ while(true) {\r
+ String line = reader.readLine();\r
+ if(line == null)\r
+ break;\r
+ switch(state) {\r
+ case 0:\r
+ if(line.equals("```````````````````````````````` example"))\r
+ ++state;\r
+ break;\r
+ case 1:\r
+ if(line.equals("."))\r
+ ++state;\r
+ else {\r
+ if(in.length() > 0)\r
+ in.append('\n');\r
+ in.append(line);\r
+ }\r
+ break;\r
+ case 2:\r
+ if(line.equals("````````````````````````````````")) {\r
+ ++testId;\r
+ int status = test(testId, in.toString(), out.toString());\r
+ if(status == SUCCEEDED)\r
+ ++passed;\r
+ else if(status == FAILED)\r
+ ++failed;\r
+ else\r
+ ++skipped;\r
+ in = new StringBuilder();\r
+ out = new StringBuilder();\r
+ state = 0;\r
+ }\r
+ else {\r
+ if(out.length() > 0)\r
+ out.append('\n');\r
+ out.append(line);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ \r
+ System.out.println("Passed: " + passed + "/" + testId);\r
+ System.out.println("Failed: " + failed + "/" + testId);\r
+ System.out.println("Skipped: " + skipped + "/" + testId);\r
+ }\r
+\r
+ public static int test(int id, String in, String out) throws IOException {\r
+ MarkdownParser parser = new MarkdownParser();\r
+ Node node = parser.parseDocument(new StringReader(in.replace('\u2192', '\t')));\r
+ \r
+ String result = node.toHtml().replace('\t', '\u2192');\r
+ \r
+ boolean passed = result.equals(out);\r
+ \r
+ if(!passed) {\r
+ System.out.println("Example " + id); // + (passed ? " passed" : " failed"));\r
+ System.out.println("---- in --------------------------------------------------------------------");\r
+ System.out.println(in);\r
+ System.out.println("---- expected --------------------------------------------------------------");\r
+ System.out.println(out);\r
+ System.out.println("---- actual ----------------------------------------------------------------");\r
+ System.out.println(result);\r
+ System.out.println("----------------------------------------------------------------------------");\r
+ System.out.println();\r
+ }\r
+ \r
+ return passed ? SUCCEEDED : FAILED;\r
+ }\r
+ \r
+}\r
+++ /dev/null
-package org.simantics.scl.compiler.tests.markdown;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.nio.charset.Charset;
-
-import org.simantics.scl.compiler.markdown.internal.MarkdownParser;
-import org.simantics.scl.compiler.markdown.nodes.Node;
-
-public class RunMarkdownTests {
-
- public static int FAILED = 0;
- public static int SUCCEEDED = 1;
- public static int SKIPPED = 2;
-
- public static void main(String[] args) throws IOException {
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(
- RunMarkdownTests.class.getResourceAsStream("spec.txt"),
- Charset.forName("UTF-8")));
-
- StringBuilder in = new StringBuilder();
- StringBuilder out = new StringBuilder();
- int state = 0;
- int testId = 0;
- int passed = 0;
- int failed = 0;
- int skipped = 0;
- while(true) {
- String line = reader.readLine();
- if(line == null)
- break;
- switch(state) {
- case 0:
- if(line.equals("```````````````````````````````` example"))
- ++state;
- break;
- case 1:
- if(line.equals("."))
- ++state;
- else {
- if(in.length() > 0)
- in.append('\n');
- in.append(line);
- }
- break;
- case 2:
- if(line.equals("````````````````````````````````")) {
- ++testId;
- int status = test(testId, in.toString(), out.toString());
- if(status == SUCCEEDED)
- ++passed;
- else if(status == FAILED)
- ++failed;
- else
- ++skipped;
- in = new StringBuilder();
- out = new StringBuilder();
- state = 0;
- }
- else {
- if(out.length() > 0)
- out.append('\n');
- out.append(line);
- }
- break;
- }
- }
-
- System.out.println("Passed: " + passed + "/" + testId);
- System.out.println("Failed: " + failed + "/" + testId);
- System.out.println("Skipped: " + skipped + "/" + testId);
- }
-
- public static int test(int id, String in, String out) throws IOException {
- MarkdownParser parser = new MarkdownParser();
- Node node = parser.parseDocument(new StringReader(in.replace('\u2192', '\t')));
-
- String result = node.toHtml().replace('\t', '\u2192');
-
- boolean passed = result.equals(out);
-
- if(!passed) {
- System.out.println("Example " + id); // + (passed ? " passed" : " failed"));
- System.out.println("---- in --------------------------------------------------------------------");
- System.out.println(in);
- System.out.println("---- expected --------------------------------------------------------------");
- System.out.println(out);
- System.out.println("---- actual ----------------------------------------------------------------");
- System.out.println(result);
- System.out.println("----------------------------------------------------------------------------");
- System.out.println();
- }
-
- return passed ? SUCCEEDED : FAILED;
- }
-
-}
---
title: CommonMark Spec
author: John MacFarlane
-version: 0.25
-date: '2016-03-24'
+version: 0.26
+date: '2016-07-15'
license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
...
Markdown is a plain text format for writing structured documents,
based on conventions used for indicating formatting in email and
usenet posts. It was developed in 2004 by John Gruber, who wrote
-the first Markdown-to-HTML converter in perl, and it soon became
-widely used in websites. By 2014 there were dozens of
-implementations in many languages. Some of them extended basic
-Markdown syntax with conventions for footnotes, definition lists,
-tables, and other constructs, and some allowed output not just in
-HTML but in LaTeX and many other formats.
+the first Markdown-to-HTML converter in Perl, and it soon became
+ubiquitous. In the next decade, dozens of implementations were
+developed in many languages. Some extended the original
+Markdown syntax with conventions for footnotes, tables, and
+other document elements. Some allowed Markdown documents to be
+rendered in formats other than HTML. Websites like Reddit,
+StackOverflow, and GitHub had millions of people using Markdown.
+And Markdown started to be used beyond the web, to author books,
+articles, slide shows, letters, and lecture notes.
+
+What distinguishes Markdown from many other lightweight markup
+syntaxes, which are often easier to write, is its readability.
+As Gruber writes:
+
+> The overriding design goal for Markdown's formatting syntax is
+> to make it as readable as possible. The idea is that a
+> Markdown-formatted document should be publishable as-is, as
+> plain text, without looking like it's been marked up with tags
+> or formatting instructions.
+> (<http://daringfireball.net/projects/markdown/>)
+
+The point can be illustrated by comparing a sample of
+[AsciiDoc](http://www.methods.co.nz/asciidoc/) with
+an equivalent sample of Markdown. Here is a sample of
+AsciiDoc from the AsciiDoc manual:
+
+```
+1. List item one.
++
+List item one continued with a second paragraph followed by an
+Indented block.
++
+.................
+$ ls *.sh
+$ mv *.sh ~/tmp
+.................
++
+List item continued with a third paragraph.
+
+2. List item two continued with an open block.
++
+--
+This paragraph is part of the preceding list item.
+
+a. This list is nested and does not require explicit item
+continuation.
++
+This paragraph is part of the preceding list item.
+
+b. List item b.
+
+This paragraph belongs to item two of the outer list.
+--
+```
+
+And here is the equivalent in Markdown:
+```
+1. List item one.
+
+ List item one continued with a second paragraph followed by an
+ Indented block.
+
+ $ ls *.sh
+ $ mv *.sh ~/tmp
+
+ List item continued with a third paragraph.
+
+2. List item two continued with an open block.
+
+ This paragraph is part of the preceding list item.
+
+ 1. This list is nested and does not require explicit item continuation.
+
+ This paragraph is part of the preceding list item.
+
+ 2. List item b.
+
+ This paragraph belongs to item two of the outer list.
+```
+
+The AsciiDoc version is, arguably, easier to write. You don't need
+to worry about indentation. But the Markdown version is much easier
+to read. The nesting of list items is apparent to the eye in the
+source, not just in the processed document.
## Why is a spec needed?
## Tabs
Tabs in lines are not expanded to [spaces]. However,
-in contexts where indentation is significant for the
-document's structure, tabs behave as if they were replaced
-by spaces with a tab stop of 4 characters.
+in contexts where whitespace helps to define block structure,
+tabs behave as if they were replaced by spaces with a tab stop
+of 4 characters.
+
+Thus, for example, a tab can be used instead of four spaces
+in an indented code block. (Note, however, that internal
+tabs are passed through as literal tabs, not expanded to
+spaces.)
```````````````````````````````` example
→foo→baz→→bim
</code></pre>
````````````````````````````````
-
```````````````````````````````` example
→foo→baz→→bim
.
</code></pre>
````````````````````````````````
-
```````````````````````````````` example
a→a
ὐ→a
</code></pre>
````````````````````````````````
+In the following example, a continuation paragraph of a list
+item is indented with a tab; this has exactly the same effect
+as indentation with four spaces would:
```````````````````````````````` example
- foo
</ul>
````````````````````````````````
+Normally the `>` that begins a block quote may be followed
+optionally by a space, which is not considered part of the
+content. In the following case `>` is followed by a tab,
+which is treated as if it were expanded into spaces.
+Since one of theses spaces is considered part of the
+delimiter, `foo` is considered to be indented six spaces
+inside the block quote context, so we get an indented
+code block starting with two spaces.
+
```````````````````````````````` example
>→→foo
.
</ul>
````````````````````````````````
+```````````````````````````````` example
+#→Foo
+.
+<h1>Foo</h1>
+````````````````````````````````
+
+```````````````````````````````` example
+*→*→*→
+.
+<hr />
+````````````````````````````````
## Insecure characters
````````````````````````````````
-A tab will not work:
-
-```````````````````````````````` example
-#→foo
-.
-<p>#→foo</p>
-````````````````````````````````
-
-
This is not a heading, because the first `#` is escaped:
```````````````````````````````` example
meets a [start condition](@) (after up to three spaces
optional indentation). It ends with the first subsequent line that
meets a matching [end condition](@), or the last line of
-the document, if no line is encountered that meets the
+the document or other [container block]), if no line is encountered that meets the
[end condition]. If the first line meets both the [start condition]
and the [end condition], the block will contain just that line.
`article`, `aside`, `base`, `basefont`, `blockquote`, `body`,
`caption`, `center`, `col`, `colgroup`, `dd`, `details`, `dialog`,
`dir`, `div`, `dl`, `dt`, `fieldset`, `figcaption`, `figure`,
-`footer`, `form`, `frame`, `frameset`, `h1`, `head`, `header`, `hr`,
+`footer`, `form`, `frame`, `frameset`,
+`h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `head`, `header`, `hr`,
`html`, `iframe`, `legend`, `li`, `link`, `main`, `menu`, `menuitem`,
`meta`, `nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`,
`section`, `source`, `summary`, `table`, `tbody`, `td`,
main :: IO ()
main = print $ parseTags tags
</code></pre>
+okay
.
<pre language="haskell"><code>
import Text.HTML.TagSoup
main :: IO ()
main = print $ parseTags tags
</code></pre>
+<p>okay</p>
````````````````````````````````
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
+okay
.
<script type="text/javascript">
// JavaScript example
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
+<p>okay</p>
````````````````````````````````
p {color:blue;}
</style>
+okay
.
<style
type="text/css">
p {color:blue;}
</style>
+<p>okay</p>
````````````````````````````````
bar
baz -->
+okay
.
<!-- Foo
bar
baz -->
+<p>okay</p>
````````````````````````````````
echo '>';
?>
+okay
.
<?php
echo '>';
?>
+<p>okay</p>
````````````````````````````````
}
}
]]>
+okay
.
<![CDATA[
function matchwo(a,b)
}
}
]]>
+<p>okay</p>
````````````````````````````````
````````````````````````````````
-The Laziness clause allows us to omit the `>` before a
-paragraph continuation line:
+The Laziness clause allows us to omit the `>` before
+[paragraph continuation text]:
```````````````````````````````` example
> # Foo
````````````````````````````````
-Note that in the following case, we have a paragraph
-continuation line:
+Note that in the following case, we have a [lazy
+continuation line]:
```````````````````````````````` example
> foo
the `- bar` is indented too far to start a list, and can't
be an indented code block because indented code blocks cannot
-interrupt paragraphs, so it is a [paragraph continuation line].
+interrupt paragraphs, so it is [paragraph continuation text].
A block quote can be empty:
1. **Basic case.** If a sequence of lines *Ls* constitute a sequence of
blocks *Bs* starting with a [non-whitespace character] and not separated
from each other by more than one blank line, and *M* is a list
- marker of width *W* followed by 0 < *N* < 5 spaces, then the result
+ marker of width *W* followed by 1 ≤ *N* ≤ 4 spaces, then the result
of prepending *M* and the following spaces to the first line of
*Ls*, and indenting subsequent lines of *Ls* by *W + N* spaces, is a
list item with *Bs* as its contents. The type of the list item
If the list item is ordered, then it is also assigned a start
number, based on the ordered list marker.
+ Exceptions: When the first list item in a [list] interrupts
+ a paragraph---that is, when it starts on a line that would
+ otherwise count as [paragraph continuation text]---then (a)
+ the lines *Ls* must not begin with a blank line, and (b) if
+ the list item is ordered, the start number must be 1.
+
For example, let *Ls* be the lines
```````````````````````````````` example
````````````````````````````````
-A list item may not contain blocks that are separated by more than
-one blank line. Thus, two blank lines will end a list, unless the
-two blanks are contained in a [fenced code block].
+A list item may contain blocks that are separated by more than
+one blank line.
```````````````````````````````` example
-- foo
-
- bar
-
- foo
bar
-
-- ```
- foo
-
-
- bar
- ```
-
-- baz
-
- + ```
- foo
-
-
- bar
- ```
.
<ul>
<li>
<p>foo</p>
<p>bar</p>
</li>
-<li>
-<p>foo</p>
-</li>
-</ul>
-<p>bar</p>
-<ul>
-<li>
-<pre><code>foo
-
-
-bar
-</code></pre>
-</li>
-<li>
-<p>baz</p>
-<ul>
-<li>
-<pre><code>foo
-
-
-bar
-</code></pre>
-</li>
-</ul>
-</li>
</ul>
````````````````````````````````
A list item that contains an indented code block will preserve
-empty lines within the code block verbatim, unless there are two
-or more empty lines in a row (since as described above, two
-blank lines end the list):
+empty lines within the code block verbatim.
```````````````````````````````` example
- Foo
bar
+
baz
.
<ul>
<p>Foo</p>
<pre><code>bar
-baz
-</code></pre>
-</li>
-</ul>
-````````````````````````````````
-
-```````````````````````````````` example
-- Foo
-
- bar
-
-
- baz
-.
-<ul>
-<li>
-<p>Foo</p>
-<pre><code>bar
+baz
</code></pre>
</li>
</ul>
-<pre><code> baz
-</code></pre>
````````````````````````````````
-
Note that ordered list start numbers must be nine digits or less:
```````````````````````````````` example
</ul>
````````````````````````````````
+However, an empty list item cannot interrupt a paragraph:
+
+```````````````````````````````` example
+foo
+*
+
+foo
+1.
+.
+<p>foo
+*</p>
+<p>foo
+1.</p>
+````````````````````````````````
4. **Indentation.** If a sequence of lines *Ls* constitutes a list item
- foo
- bar
- baz
+ - boo
.
<ul>
<li>foo
<ul>
<li>bar
<ul>
-<li>baz</li>
+<li>baz
+<ul>
+<li>boo</li>
+</ul>
+</li>
</ul>
</li>
</ul>
- foo
- bar
- baz
+ - boo
.
<ul>
<li>foo</li>
<li>bar</li>
<li>baz</li>
+<li>boo</li>
</ul>
````````````````````````````````
A [list](@) is a sequence of one or more
list items [of the same type]. The list items
-may be separated by single [blank lines], but two
-blank lines end all containing lists.
+may be separated by any number of blank lines.
Two list items are [of the same type](@)
if they begin with a [list marker] of the same type.
</ul>
````````````````````````````````
-
`Markdown.pl` does not allow this, through fear of triggering a list
via a numeral in a hard-wrapped line:
-```````````````````````````````` example
+``` markdown
The number of windows in my house is
14. The number of doors is 6.
-.
-<p>The number of windows in my house is</p>
-<ol start="14">
-<li>The number of doors is 6.</li>
-</ol>
-````````````````````````````````
-
+```
-Oddly, `Markdown.pl` *does* allow a blockquote to interrupt a paragraph,
-even though the same considerations might apply. We think that the two
-cases should be treated the same. Here are two reasons for allowing
-lists to interrupt paragraphs:
+Oddly, though, `Markdown.pl` *does* allow a blockquote to
+interrupt a paragraph, even though the same considerations might
+apply.
-First, it is natural and not uncommon for people to start lists without
-blank lines:
+In CommonMark, we do allow lists to interrupt paragraphs, for
+two reasons. First, it is natural and not uncommon for people
+to start lists without blank lines:
- I need to buy
- - new shoes
- - a coat
- - a plane ticket
+``` markdown
+I need to buy
+- new shoes
+- a coat
+- a plane ticket
+```
Second, we are attracted to a
(Indeed, the spec for [list items] and [block quotes] presupposes
this principle.) This principle implies that if
- * I need to buy
- - new shoes
- - a coat
- - a plane ticket
+``` markdown
+ * I need to buy
+ - new shoes
+ - a coat
+ - a plane ticket
+```
is a list item containing a paragraph followed by a nested sublist,
as all Markdown implementations agree it is (though the paragraph
may be rendered without `<p>` tags, since the list is "tight"),
then
- I need to buy
- - new shoes
- - a coat
- - a plane ticket
+``` markdown
+I need to buy
+- new shoes
+- a coat
+- a plane ticket
+```
by itself should be a paragraph followed by a nested sublist.
-Our adherence to the [principle of uniformity]
-thus inclines us to think that there are two coherent packages:
+Since it is well established Markdown practice to allow lists to
+interrupt paragraphs inside list items, the [principle of
+uniformity] requires us to allow this outside list items as
+well. ([reStructuredText](http://docutils.sourceforge.net/rst.html)
+takes a different approach, requiring blank lines before lists
+even inside other list items.)
-1. Require blank lines before *all* lists and blockquotes,
- including lists that occur as sublists inside other list items.
+In order to solve of unwanted lists in paragraphs with
+hard-wrapped numerals, we allow only lists starting with `1` to
+interrupt paragraphs. Thus,
-2. Require blank lines in none of these places.
+```````````````````````````````` example
+The number of windows in my house is
+14. The number of doors is 6.
+.
+<p>The number of windows in my house is
+14. The number of doors is 6.</p>
+````````````````````````````````
-[reStructuredText](http://docutils.sourceforge.net/rst.html) takes
-the first approach, for which there is much to be said. But the second
-seems more consistent with established practice with Markdown.
+We may still get an unintended result in cases like
-There can be blank lines between items, but two blank lines end
-a list:
+```````````````````````````````` example
+The number of windows in my house is
+1. The number of doors is 6.
+.
+<p>The number of windows in my house is</p>
+<ol>
+<li>The number of doors is 6.</li>
+</ol>
+````````````````````````````````
+
+but this rule should prevent most spurious list captures.
+
+There can be any number of blank lines between items:
```````````````````````````````` example
- foo
<li>
<p>bar</p>
</li>
-</ul>
-<ul>
-<li>baz</li>
-</ul>
-````````````````````````````````
-
-
-As illustrated above in the section on [list items],
-two blank lines between blocks *within* a list item will also end a
-list:
-
-```````````````````````````````` example
-- foo
-
-
- bar
-- baz
-.
-<ul>
-<li>foo</li>
-</ul>
-<p>bar</p>
-<ul>
-<li>baz</li>
+<li>
+<p>baz</p>
+</li>
</ul>
````````````````````````````````
-
-Indeed, two blank lines will end *all* containing lists:
-
```````````````````````````````` example
- foo
- bar
<ul>
<li>bar
<ul>
-<li>baz</li>
+<li>
+<p>baz</p>
+<p>bim</p>
+</li>
</ul>
</li>
</ul>
</li>
</ul>
-<pre><code> bim
-</code></pre>
````````````````````````````````
-Thus, two blank lines can be used to separate consecutive lists of
-the same type, or to separate a list from an indented code block
-that would otherwise be parsed as a subparagraph of the final list
-item:
+To separate consecutive lists of the same type, or to separate a
+list from an indented code block that would otherwise be parsed
+as a subparagraph of the final list item, you can insert a blank HTML
+comment:
```````````````````````````````` example
- foo
- bar
+<!-- -->
- baz
- bim
<li>foo</li>
<li>bar</li>
</ul>
+<!-- -->
<ul>
<li>baz</li>
<li>bim</li>
- foo
+<!-- -->
code
.
<p>foo</p>
</li>
</ul>
+<!-- -->
<pre><code>code
</code></pre>
````````````````````````````````
````````````````````````````````
+Not all [Unicode whitespace] (for instance, non-breaking space) is
+collapsed, however:
+
+```````````````````````````````` example
+`a b`
+.
+<p><code>a b</code></p>
+````````````````````````````````
+
+
Q: Why not just leave the spaces, since browsers will collapse them
anyway? A: Because we might be targeting a non-HTML format, and we
shouldn't rely on HTML-specific rendering assumptions.
9. Emphasis begins with a delimiter that [can open emphasis] and ends
with a delimiter that [can close emphasis], and that uses the same
- character (`_` or `*`) as the opening delimiter. There must
- be a nonempty sequence of inlines between the open delimiter
- and the closing delimiter; these form the contents of the emphasis
- inline.
+ character (`_` or `*`) as the opening delimiter. The
+ opening and closing delimiters must belong to separate
+ [delimiter runs]. If one of the delimiters can both
+ open and close emphasis, then the sum of the lengths of the
+ delimiter runs containing the opening and closing delimiters
+ must not be a multiple of 3.
10. Strong emphasis begins with a delimiter that
[can open strong emphasis] and ends with a delimiter that
[can close strong emphasis], and that uses the same character
- (`_` or `*`) as the opening delimiter.
- There must be a nonempty sequence of inlines between the open
- delimiter and the closing delimiter; these form the contents of
- the strong emphasis inline.
+ (`_` or `*`) as the opening delimiter. The
+ opening and closing delimiters must belong to separate
+ [delimiter runs]. If one of the delimiters can both open
+ and close strong emphasis, then the sum of the lengths of
+ the delimiter runs containing the opening and closing
+ delimiters must not be a multiple of 3.
11. A literal `*` character cannot occur at the beginning or end of
`*`-delimited emphasis or `**`-delimited strong emphasis, unless it
so that the second begins before the first ends and ends after
the first ends, the first takes precedence. Thus, for example,
`*foo _bar* baz_` is parsed as `<em>foo _bar</em> baz_` rather
- than `*foo <em>bar* baz</em>`. For the same reason,
- `**foo*bar**` is parsed as `<em><em>foo</em>bar</em>*`
- rather than `<strong>foo*bar</strong>`.
+ than `*foo <em>bar* baz</em>`.
16. When there are two potential emphasis or strong emphasis spans
with the same closing delimiter, the shorter one (the one that
*foo bar
*
.
-<p>*foo bar</p>
-<ul>
-<li></li>
-</ul>
+<p>*foo bar
+*</p>
````````````````````````````````
<p><em>foo <strong>bar</strong> baz</em></p>
````````````````````````````````
-
-But note:
-
```````````````````````````````` example
*foo**bar**baz*
.
-<p><em>foo</em><em>bar</em><em>baz</em></p>
+<p><em>foo<strong>bar</strong>baz</em></p>
````````````````````````````````
+Note that in the preceding case, the interpretation
+
+``` markdown
+<p><em>foo</em><em>bar<em></em>baz</em></p>
+```
+
+
+is precluded by the condition that a delimiter that
+can both open and close (like the `*` after `foo`)
+cannot form emphasis if the sum of the lengths of
+the delimiter runs containing the opening and
+closing delimiters is a multiple of 3.
+
+The same condition ensures that the following
+cases are all strong emphasis nested inside
+emphasis, even when the interior spaces are
+omitted:
-The difference is that in the preceding case, the internal delimiters
-[can close emphasis], while in the cases with spaces, they cannot.
```````````````````````````````` example
***foo** bar*
````````````````````````````````
-Note, however, that in the following case we get no strong
-emphasis, because the opening delimiter is closed by the first
-`*` before `bar`:
-
```````````````````````````````` example
*foo**bar***
.
-<p><em>foo</em><em>bar</em>**</p>
+<p><em>foo<strong>bar</strong></em></p>
````````````````````````````````
-
Indefinite levels of nesting are possible:
```````````````````````````````` example
````````````````````````````````
-But note:
-
```````````````````````````````` example
**foo*bar*baz**
.
-<p><em><em>foo</em>bar</em>baz**</p>
+<p><strong>foo<em>bar</em>baz</strong></p>
````````````````````````````````
-The difference is that in the preceding case, the internal delimiters
-[can close emphasis], while in the cases with spaces, they cannot.
-
```````````````````````````````` example
***foo* bar**
.
````````````````````````````````
-```````````````````````````````` example
-**foo*bar**
-.
-<p><em><em>foo</em>bar</em>*</p>
-````````````````````````````````
-
-
```````````````````````````````` example
*foo __bar *baz bim__ bam*
.
````````````````````````````````
+Titles must be separated from the link using a [whitespace].
+Other [Unicode whitespace] like non-breaking space doesn't work.
+
+```````````````````````````````` example
+[link](/url "title")
+.
+<p><a href="/url%C2%A0%22title%22">link</a></p>
+````````````````````````````````
+
+
Nested balanced quotes are not allowed without escaping:
```````````````````````````````` example
[link reference definition] elsewhere in the
document and is not followed by `[]` or a link label.
The contents of the first link label are parsed as inlines,
-which are used as the link's text. the link's URI and title
+which are used as the link's text. The link's URI and title
are provided by the matching link reference definition.
Thus, `[foo]` is equivalent to `[foo][]`.
````````````````````````````````
-Full references take precedence over shortcut references:
+Full and compact references take precedence over shortcut
+references:
```````````````````````````````` example
[foo][bar]
<p><a href="/url2">foo</a></p>
````````````````````````````````
+```````````````````````````````` example
+[foo][]
+
+[foo]: /url1
+.
+<p><a href="/url1">foo</a></p>
+````````````````````````````````
+
+Inline links also take precedence:
+
+```````````````````````````````` example
+[foo]()
+
+[foo]: /url1
+.
+<p><a href="">foo</a></p>
+````````````````````````````````
+
+```````````````````````````````` example
+[foo](not a link)
+
+[foo]: /url1
+.
+<p><a href="/url1">foo</a>(not a link)</p>
+````````````````````````````````
In the following case `[bar][baz]` is parsed as a reference,
`[foo]` as normal text:
A regular line break (not in a code span or HTML tag) that is not
preceded by two or more spaces or a backslash is parsed as a
-softbreak. (A softbreak may be rendered in HTML either as a
+[softbreak](@). (A softbreak may be rendered in HTML either as a
[line ending] or as a space. The result will be the same in
browsers. In the examples here, a [line ending] will be used.)
[lazy continuation line].
2. Next, after consuming the continuation markers for existing
-blocks, we look for new block starts (e.g. `>` for a block quote.
+blocks, we look for new block starts (e.g. `>` for a block quote).
If we encounter a new block start, we close any blocks unmatched
in step 1 before creating the new block as a child of the last
matched block.
--- /dev/null
+import "Prelude"\r
+\r
+slowSum :: [Integer] -> <Proc> Integer\r
+slowSum list = getRef answer\r
+ where\r
+ answer = ref 0\r
+ \r
+ constraint El Integer\r
+ \r
+ ?x <- list => El ?x\r
+ -El ?x, -El ?y => El (?x + ?y)\r
+ El ?x => answer := ?x\r
+ \r
+main = slowSum [1,6,9]\r
+--\r
+16\r
+--\r
+import "Prelude"\r
+\r
+slowGcd :: [Integer] -> <Proc> Integer\r
+slowGcd list = getRef answer\r
+ where\r
+ answer = ref 0\r
+ \r
+ constraint Gcd Integer\r
+ \r
+ ?x <- list => Gcd ?x\r
+ -Gcd 0 => True\r
+ -Gcd ?m, Gcd ?n, ?n <= ?m => Gcd (?m `mod` ?n)\r
+ Gcd ?answer => answer := ?answer\r
+ \r
+main = slowGcd [12,20]\r
+--\r
+4\r
+--\r
+import "Prelude"\r
+\r
+isReachable :: [(Integer,Integer)] -> Integer -> Integer -> <Proc> Boolean\r
+isReachable edges a b = getRef answer\r
+ where\r
+ answer = ref False\r
+ \r
+ constraint Edge Integer Integer\r
+ constraint Reachable Integer\r
+ \r
+ (?x,?y) <- edges => Edge ?x ?y\r
+ True => Reachable a\r
+ Reachable ?x, Edge ?x ?y => Reachable ?y\r
+ Reachable b => answer := True\r
+\r
+graph :: [(Integer, Integer)]\r
+graph = [(0,1), (1,2), (2,3), (4,5)]\r
+\r
+main = (isReachable graph 0 3, isReachable graph 0 5)\r
+--\r
+(true,false)\r
+--\r
+import "StandardLibrary"\r
+\r
+primes1 limit = MList.freeze answer\r
+ where\r
+ answer = MList.create ()\r
+ MList.add answer 2\r
+ \r
+ constraint Prime Integer\r
+ constraint PrimeCandidate Integer\r
+ \r
+ True => PrimeCandidate 3\r
+ -PrimeCandidate ?x, ?x > limit => True\r
+ -PrimeCandidate ?x, Prime ?y, ?x `mod` ?y = 0 => PrimeCandidate (?x + 2)\r
+ -PrimeCandidate ?x => MList.add answer ?x, Prime ?x, PrimeCandidate (?x + 2)\r
+\r
+main = primes1 30\r
+--\r
+[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]\r
+--\r
+import "StandardLibrary"\r
+\r
+powersOfTwo n = sort (MList.freeze answer)\r
+ where\r
+ answer = MList.create ()\r
+ \r
+ constraint N Integer\r
+ \r
+ ?i <- [1..n] => N 1\r
+ -N ?x, -N ?x => N (2*?x)\r
+ N ?x => MList.add answer ?x\r
+ \r
+main = powersOfTwo 25\r
+--\r
+[1, 8, 16]\r
+--\r
+import "StandardLibrary"\r
+\r
+main = MList.freeze answer\r
+ where\r
+ answer = MList.create ()\r
+ add = MList.add answer\r
+ \r
+ constraint A\r
+ constraint B\r
+ constraint C\r
+ \r
+ A => add "A1"\r
+ B => add "B1"\r
+ C => add "C1"\r
+ A => add "A2"\r
+ B => add "B2"\r
+ C => add "C2"\r
+ \r
+ True => A\r
+ -A => B\r
+ -B => C\r
+--\r
+[A1, A2, B1, B2, C1, C2] \r
+--\r
+import "StandardLibrary"\r
+\r
+graph = [("1","2"), ("2","3"), ("3","4"), ("3","5"), ("1","4"), ("5","5")]\r
+\r
+main = sort (MList.freeze answer)\r
+ where\r
+ answer = MList.create ()\r
+ \r
+ constraint Init\r
+ constraint Edge String String\r
+ constraint Degree String Integer\r
+ \r
+ True => Init\r
+ (?x, ?y) <- graph => Edge ?x ?y\r
+ \r
+ Init, Edge ?x ?y => Degree ?x 1, Degree ?y 1\r
+ Init, -Degree ?x ?a, -Degree ?x ?b => Degree ?x (?a + ?b)\r
+ -Init => True\r
+\r
+ -Degree ?x 0 => print "Remove node \(?x)"\r
+ -Degree ?x ?a, -Edge ?x ?x => Degree ?x (?a - 2), print "Remove loop (\(?x),\(?x))"\r
+ -Degree ?x ?a, -Edge ?x ?y, -Degree ?y ?b, (?a==1 || ?b==1) => Degree ?x (?a - 1), Degree ?y (?b - 1), print "Remove dangling edge (\(?x),\(?y))"\r
+ -Degree ?y 2, -Edge ?x ?y, -Edge ?y ?z => Edge ?x ?z, print "Simplify path (\(?x),\(?y),\(?z))"\r
+ \r
+ Edge ?x ?y => MList.add answer (?x, ?y)\r
+--\r
+[(1,4), (1,4)]\r
+--\r
+import "StandardLibrary"\r
+\r
+uniq :: [a] -> <Proc> [a]\r
+uniq l = MList.freeze answer\r
+ where\r
+ answer = MList.create ()\r
+ \r
+ constraint El a\r
+ ?x <- l => El ?x\r
+ -El ?x, El ?x => True\r
+ El ?x => MList.add answer ?x\r
+ \r
+main = sort $ uniq [1,1,2,2,3]\r
+--\r
+[1, 2, 3]
\ No newline at end of file
--- /dev/null
+import "Prelude"\r
+\r
+gSum :: Additive a => [a] -> <Proc> a\r
+gSum list = getRef answer\r
+ where\r
+ answer = ref zero\r
+ \r
+ constraint El a\r
+ \r
+ ?x <- list => El ?x\r
+ -El ?x, -El ?y => El (?x + ?y)\r
+ El ?x => answer := ?x\r
+ \r
+main = (gSum [1,6,9], gSum [1.0,6.0,9.0]) \r
+--\r
+(16,16.0)\r
+--\r
+import "StandardLibrary"\r
+\r
+topologicalSort :: [(a,a)] -> <Proc> [a]\r
+topologicalSort dependencies = MList.freeze answer\r
+ where\r
+ answer = MList.create ()\r
+ \r
+ (?x,?y) <- dependencies => Dep ?x ?y, InDegree ?x 0, InDegree ?y 1\r
+ -InDegree ?x ?a, -InDegree ?x ?b => InDegree ?x (?a + ?b)\r
+ InDegree ?x 0 => AdjustInDegrees ?x, MList.add answer ?x\r
+ AdjustInDegrees ?x, Dep ?x ?y => InDegree ?y (-1)\r
+ \r
+main = topologicalSort [(2,4),(3,7),(7,2),(1,3)]\r
+--\r
+[1, 3, 7, 2, 4]\r
+--\r
+import "StandardLibrary"\r
+\r
+topologicalSort :: Show a => [(a,a)] -> <Proc> [a]\r
+topologicalSort dependencies = MList.freeze answer\r
+ where\r
+ answer = MList.create ()\r
+ \r
+ -Candidate ?x, Candidate ?x => True\r
+ (?x,?y) <- dependencies => Dep ?x ?y, Candidate ?x\r
+ -Candidate ?x, Dep _ ?x => True\r
+ Candidate ?x => MList.add answer ?x \r
+ Candidate ?x, -Dep ?x ?y => Candidate ?y\r
+\r
+main = topologicalSort [(2,4),(3,7),(7,2),(1,3)]\r
+--\r
+[1, 3, 7, 2, 4]\r
--- /dev/null
+import "Prelude"\r
+\r
+main = ()\r
+ where\r
+ A ?x => print ?x\r
+ A ?x, not A (?x+1) => A (?x-1)\r
+ True => A 0\r
+--\r
+()\r
+ \r
+\r
--- /dev/null
+)\r
+--\r
+1:1-1:2: No corresponding opening parenthesis for ')'.\r
+--\r
+}\r
+--\r
+1:1-1:2: No corresponding opening parenthesis for '}'.\r
+--\r
+]\r
+--\r
+1:1-1:2: No corresponding opening parenthesis for ']'.
\ No newline at end of file
import "Prelude"\r
\r
+newEq = (==)\r
+\r
main = """\r
\(newEq () ())\r
\(newEq True True)\r
\r
f p l = (foldl (+) (map ((+)p) l)) + p\r
--\r
-3:1-3:39: Couldn't simplify all effect subsumptions away. The current compiler cannot handle this situation. Try adding more type annotations.\r
3:25-3:31: Type [a b] -> <c> a b is not a subtype of a.
\ No newline at end of file
--- /dev/null
+import "Prelude"\r
+\r
+main = do\r
+ x = ref 3\r
+ if 2 > 1\r
+ then x := 4\r
+ if 1 > 2\r
+ then x := 8\r
+ getRef x\r
+--\r
+4
\ No newline at end of file
main = \ /* no parameters */ -> 3
--
-2:30-2:32: Unexpected token '->' (ARROW). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LBRACKET, LET, LPAREN, MATCH, MDO, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION, WHEN.
+2:30-2:32: Unexpected token '->' (ARROW). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LAMBDA_MATCH, LBRACKET, LET, LPAREN, MATCH, MDO, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION.
\ No newline at end of file
--- /dev/null
+import "Prelude"\r
+\r
+f :: Maybe String -> String\r
+f = \match\r
+ Just a -> a\r
+ Nothing -> ""\r
+\r
+main = f Nothing + f (Just "foo")\r
+--\r
+foo\r
import "JavaBuiltin" as Java\r
\r
-(==) = Java.icmpeq\r
-\r
@macro\r
(&<&) :: Integer -> Integer -> Integer\r
a &<& b = if cmp == 0 then b else cmp\r
then go (i-1)\r
else take i l \r
\r
-instance (Eq a, Additive a) => Additive (Poly a) where\r
+instance (Additive a) => Additive (Poly a) where\r
zero = Poly []\r
Poly a + Poly b = \r
Poly ( \r
la = length a\r
lb = length b \r
\r
-instance (Eq a, Ring a) => Ring (Poly a) where\r
+instance (Ring a) => Ring (Poly a) where\r
one = Poly [one]\r
neg (Poly l) = Poly (map neg l)\r
a - b = a + (neg b)\r
\r
infixl 7 (%)\r
infixl 6 (+)\r
-infix 4 (==), (<)\r
+infix 4 (<)\r
\r
(+) = Java.iadd\r
(%) = Java.irem\r
(<) = Java.icmplt\r
-(==) = Java.icmpeq\r
\r
isPrime p = isPrimeAux (2 :: Integer) p\r
where\r
--- /dev/null
+import "StandardLibrary"\r
+\r
+rt :: Serializable a => a -> a\r
+rt v = deserialize (serialize v)\r
+\r
+main :: String\r
+main = do\r
+ a = (1 :: Integer,"asd")\r
+ b = MMap.create ()\r
+ MMap.put b "asdasd" (4 :: Long)\r
+ show (rt a, MMap.get (rt b) "asdasd")\r
+--\r
+((1, "asd"), Just 4)
\ No newline at end of file
| SigNeg Signal\r
| SigMul [Signal]\r
\r
-deriving instance Eq Signal\r
-deriving instance Hashable Signal\r
deriving instance Show Signal\r
\r
instance Additive Signal where\r
-stringSum :: String -> Integer\r
-stringSum "(\(a),\(b),\(c))" = a + b + c\r
+import "Prelude"\r
\r
-main = stringSum "(1,2,3)"\r
+main = match "abc123def" with\r
+ "abc\(x)fed" -> "X\(x)"\r
+ "cba\(x)def" -> "Y\(x)"\r
+ "abc\(x)def" -> "Z\(x)"\r
+ x -> "W\(x)"\r
--\r
-6
\ No newline at end of file
+Z123
\ No newline at end of file
--- /dev/null
+import "Prelude"\r
+// Test optimized special cases\r
+\r
+main = let\r
+ a = "123"\r
+ b = "456"\r
+ c = "\(a)"\r
+ d = "abc\(b)"\r
+ e = "\(d)def"\r
+ in "\(c)\(e)"\r
+--\r
+123abc456def
\ No newline at end of file
@where
Fib (?n+2) (?a + 1)
-/*
+
rule PrintIt where
@when
Fib ?n ?a
@to
Execute (print "\(?n) -> \(?a)")
-*/
+
main = transformation OneShotForward where
Fib 0 1
Fib 1 1
a = =
b = 4
--
-1:5-1:6: Unexpected token '=' (EQUALS). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LBRACKET, LET, LPAREN, MATCH, MDO, MINUS, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION, WHEN.
\ No newline at end of file
+1:5-1:6: Unexpected token '=' (EQUALS). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LAMBDA_MATCH, LBRACKET, LET, LPAREN, MATCH, MDO, MINUS, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION.
\ No newline at end of file
--- /dev/null
+import "Prelude"\r
+\r
+f :: String -> String\r
+f (split "/" -> [a,b]) = "\(a)foo\(b)"\r
+f (split "/" -> [a,b,c]) = "\(a)foo\(b)bar\(c)"\r
+f str = str\r
+\r
+main = f "123" + f "abc/def" + f "123/456/789"\r
+--\r
+123abcfoodef123foo456bar789\r
--- /dev/null
+package org.simantics.scl.compiler.tests.unit;\r
+\r
+import java.lang.reflect.Constructor;\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.Method;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo;\r
+import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;\r
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;\r
+import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;\r
+import org.simantics.scl.compiler.module.repository.ModuleRepository;\r
+import org.simantics.scl.compiler.runtime.MutableClassLoader;\r
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
+import org.simantics.scl.compiler.tests.InitialRepository;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+\r
+public class TestCHRCodeGenerator {\r
+ @Test\r
+ public void testCodeGenerator() throws Throwable {\r
+ try {\r
+ ModuleRepository repository = InitialRepository.getInitialRepository();\r
+ RuntimeEnvironment environment = repository.createRuntimeEnvironment(EnvironmentSpecification.of("StandardLibrary", "", "Builtin", ""), getClass().getClassLoader());\r
+ JavaNamingPolicy policy = new JavaNamingPolicy("Expression");\r
+ JavaTypeTranslator jtt = new JavaTypeTranslator(environment.getEnvironment());\r
+ CompilationContext compilationContext = new CompilationContext();\r
+ compilationContext.environment = environment.getEnvironment();\r
+ compilationContext.javaTypeTranslator = jtt;\r
+ compilationContext.namingPolicy = policy;\r
+ ModuleBuilder moduleBuilder = new ModuleBuilder(policy, jtt);\r
+ \r
+ CHRRuleset ruleset = new CHRRuleset(); \r
+ CHRConstraint exampleFact = new CHRConstraint(Locations.NO_LOCATION, "ExampleFact", new Type[] { Types.INTEGER, Types.INTEGER });\r
+ ruleset.constraints.add(exampleFact);\r
+ \r
+ System.out.println("==============================================================================================");\r
+ ruleset.initializeCodeGeneration(compilationContext);\r
+ exampleFact.indices.put(0, new IndexInfo(0, "ff", null, null));\r
+ exampleFact.indices.put(1, new IndexInfo(1, "bf", null, null));\r
+ exampleFact.indices.put(2, new IndexInfo(2, "fb", null, null));\r
+ exampleFact.indices.put(3, new IndexInfo(3, "bb", null, null));\r
+ exampleFact.setMayBeRemoved();\r
+\r
+ CHRCodeGenerator.generateStore(moduleBuilder, ruleset);\r
+ \r
+ MutableClassLoader classLoader = environment.getMutableClassLoader();\r
+ classLoader.addClasses(moduleBuilder.getClasses());\r
+ \r
+ String storeClassName = ruleset.storeClassName.replace('/', '.');\r
+ Class<?> storeClass = classLoader.loadClass(storeClassName);\r
+ Class<?> factClass = classLoader.loadClass(storeClassName+"$ExampleFact");\r
+ Constructor<?> factConstructor = factClass.getConstructor(int.class, int.class, int.class);\r
+ Method addMethod = factClass.getMethod("add", storeClass);\r
+ Method removeMethod = factClass.getMethod("remove", storeClass);\r
+ Method getMethod = storeClass.getMethod("ExampleFact$bf", int.class);\r
+ Field nextField = factClass.getField("bfNext");\r
+ \r
+ Object store = storeClass.newInstance();\r
+ Object fact1 = factConstructor.newInstance(0, 1,2);\r
+ Object fact2 = factConstructor.newInstance(0, 1,3);\r
+ Object fact3 = factConstructor.newInstance(0, 2,4);\r
+ Object fact4 = factConstructor.newInstance(0, 1,4);\r
+ addMethod.invoke(fact1, store);\r
+ addMethod.invoke(fact4, store);\r
+ addMethod.invoke(fact2, store);\r
+ addMethod.invoke(fact3, store);\r
+ removeMethod.invoke(fact4, store);\r
+ {\r
+ Object f1 = getMethod.invoke(store, 1);\r
+ Assert.assertEquals(fact2, f1);\r
+ Object f2 = nextField.get(f1);\r
+ Assert.assertEquals(fact1, f2);\r
+ Object f3 = nextField.get(f2);\r
+ Assert.assertEquals(null, f3);\r
+ }\r
+ removeMethod.invoke(fact2, store);\r
+ {\r
+ Object f1 = getMethod.invoke(store, 1);\r
+ Assert.assertEquals(fact1, f1);\r
+ Object f2 = nextField.get(f1);\r
+ Assert.assertEquals(null, f2);\r
+ }\r
+ addMethod.invoke(fact2, store);\r
+ removeMethod.invoke(fact1, store);\r
+ {\r
+ Object f1 = getMethod.invoke(store, 1);\r
+ Assert.assertEquals(fact2, f1);\r
+ Object f2 = nextField.get(f1);\r
+ Assert.assertEquals(null, f2);\r
+ }\r
+ removeMethod.invoke(fact2, store);\r
+ {\r
+ Object f1 = getMethod.invoke(store, 1);\r
+ Assert.assertEquals(null, f1);\r
+ }\r
+ } catch(Throwable e) {\r
+ e.printStackTrace();\r
+ throw e;\r
+ }\r
+ }\r
+ \r
+}\r
\r
import java.util.Collection;\r
\r
+import org.junit.Assert;\r
import org.junit.Test;\r
import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;\r
import org.simantics.scl.compiler.environment.filter.NamespaceFilter;\r
import org.simantics.scl.compiler.environment.filter.PositiveNamespaceFilter;\r
\r
import gnu.trove.set.hash.THashSet;\r
-import junit.framework.Assert;\r
\r
public class TestNamespaceFilter {\r
\r