Bundle-ManifestVersion: 2
Bundle-Name: Silk icon set
Bundle-SymbolicName: com.famfamfam.silk
-Bundle-Version: 1.3
+Bundle-Version: 1.3.0
Bundle-Vendor: Semantum Oy
if (parent != null) {\r
_additions.add(new Object[] { ss.getRandomAccessId(parent), ss.getRandomAccessId(entry.component), name, types, id != null ? id.indexString() : "" });\r
} else {\r
- System.err.println("resource " + entry.component + ": no parent for entry " + name + " " + types);\r
+ //System.err.println("resource " + entry.component + ": no parent for entry " + name + " " + types);\r
}\r
} else {\r
- System.err.println("resource " + entry.component + ": " + name + " " + types);\r
+ //System.err.println("resource " + entry.component + ": " + name + " " + types);\r
}\r
} else if(_entry instanceof ComponentModification) {\r
ComponentModification entry = (ComponentModification)_entry;\r
output.. = bin/\r
bin.includes = META-INF/,\\r
.,\\r
- bin/msijni.dll,\\r
- bin/msijni64.dll,\\r
+ msijni.dll,\\r
+ msijni64.dll,\\r
VC90.2008.SP1.KB2467174.redist.x64.exe,\\r
VC90.2008.SP1.KB2467174.redist.x86.exe\r
src.includes = native/\r
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.simantics.db.procore.ui
Import-Package:
- org.osgi.framework;version="1.3.0",
+ org.eclipse.core.runtime,
org.eclipse.jface.dialogs,
org.eclipse.jface.operation,
- org.eclipse.core.runtime,
org.eclipse.swt.widgets,
- org.eclipse.ui,
+ org.osgi.framework;version="1.3.0",
org.simantics.db,
- org.simantics.db.exception,
org.simantics.db.common.utils,
+ org.simantics.db.exception,
org.simantics.db.server;visibility:=reexport
Require-Bundle: org.simantics.db.procore;bundle-version="1.2.1"
\r
import org.eclipse.swt.widgets.Display;\r
import org.eclipse.swt.widgets.Shell;\r
-import org.eclipse.ui.IWorkbench;\r
-import org.eclipse.ui.IWorkbenchWindow;\r
import org.simantics.db.DatabaseUserAgent;\r
import org.simantics.db.exception.InternalException;\r
import org.simantics.db.procore.ProCoreDriver;\r
\r
public final class ProCoreUserAgent implements DatabaseUserAgent {\r
- private static Shell getShell(IWorkbench workbench) {\r
- IWorkbenchWindow wbw = workbench.getActiveWorkbenchWindow();\r
+ private static Shell getShell() {\r
Shell shell = null;\r
- if (null != wbw) {\r
- shell = wbw.getShell();\r
- } else {\r
- Display d = getDisplay();\r
- if (d == null)\r
- return null;\r
- shell = d.getActiveShell();\r
- if (null == shell) {\r
- Shell[] shells = d.getShells();\r
- if (null != shells && shells.length > 0)\r
- shell = shells[0];\r
- }\r
+ Display d = getDisplay();\r
+ if (d == null)\r
+ return null;\r
+ shell = d.getActiveShell();\r
+ if (null == shell) {\r
+ Shell[] shells = d.getShells();\r
+ if (null != shells && shells.length > 0)\r
+ shell = shells[0];\r
}\r
return shell;\r
}\r
d = Display.getDefault();\r
return d;\r
}\r
- private IWorkbench workbench;\r
- public ProCoreUserAgent(IWorkbench workbench) {\r
- this.workbench = workbench;\r
- }\r
- private Shell getShell() {\r
- return getShell(workbench);\r
- }\r
@Override\r
public boolean handleStart(InternalException exception) {\r
Shell shell = getShell();\r
.,\\r
win32.x86/,\\r
win32.x86_64/,\\r
- linux.x86/,\\r
linux.x86_64/\r
output.. = bin/\r
bin.includes = META-INF/,\\r
.,\\r
- graphs/*.tg,\\r
graph.tg\r
src.includes = graph/\r
bin.includes = META-INF/,\\r
.,\\r
plugin.xml,\\r
- document.war,\\r
webdefault.xml,\\r
scl/,\\r
src.includes = scl/\r
output.. = bin/\r
bin.includes = META-INF/,\\r
.,\\r
- graphs/*.tg,\\r
graph.tg\r
src.includes = graph/\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry exported="true" kind="lib" path="jna-4.2.1.jar"/>\r
+ <classpathentry kind="lib" path="jna-platform-4.2.1.jar"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.nativemem</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7\r
+org.eclipse.jdt.core.compiler.compliance=1.7\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.7\r
--- /dev/null
+eclipse.preferences.version=1\r
+pluginProject.extensions=false\r
+resolve.requirebundle=false\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Native Memory Tracking
+Bundle-SymbolicName: org.simantics.nativemem
+Bundle-Version: 1.0.0.qualifier
+Bundle-Vendor: Semantum Oy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ClassPath: .,
+ jna-4.2.1.jar,
+ jna-platform-4.2.1.jar
+Export-Package: org.simantics.nativemem
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ jna-4.2.1.jar,\\r
+ jna-platform-4.2.1.jar\r
--- /dev/null
+package org.simantics.nativemem;\r
+\r
+import org.simantics.nativemem.internal.Arch;\r
+import org.simantics.nativemem.internal.OS;\r
+import org.simantics.nativemem.internal.Psapi32;\r
+import org.simantics.nativemem.internal.Psapi64;\r
+\r
+import com.sun.jna.platform.win32.Kernel32;\r
+import com.sun.jna.platform.win32.WinNT.HANDLE;\r
+\r
+\r
+public class NativeMem {\r
+\r
+ /**\r
+ * @param out\r
+ * the structure to write the result into or <code>null</code> to\r
+ * create a new structure\r
+ * @return the result structure\r
+ */\r
+ public static ProcessMemoryCounters getMemoryCounters(ProcessMemoryCounters out) {\r
+ if (out == null)\r
+ out = new ProcessMemoryCounters();\r
+\r
+ OS os = OS.calculate();\r
+ Arch arch = Arch.calculate();\r
+ switch (os) {\r
+ case WINDOWS: {\r
+ HANDLE proc = Kernel32.INSTANCE.GetCurrentProcess();\r
+ switch (arch) {\r
+ case X86: {\r
+ Psapi32.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi32.PROCESS_MEMORY_COUNTERS_EX();\r
+ boolean ok = Psapi32.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());\r
+ if (ok)\r
+ pmem.writeTo(out);\r
+ return out;\r
+ }\r
+\r
+ case X86_64: {\r
+ Psapi64.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi64.PROCESS_MEMORY_COUNTERS_EX();\r
+ boolean ok = Psapi64.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());\r
+ if (ok)\r
+ pmem.writeTo(out);\r
+ return out;\r
+ }\r
+\r
+ default:\r
+ throw new UnsupportedOperationException("Architecture " + arch + " not supported on operating system " + os);\r
+ }\r
+ }\r
+\r
+ default:\r
+ throw new UnsupportedOperationException("Operating system " + os + " not supported");\r
+ }\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.nativemem;\r
+\r
+/**\r
+ * Architecture-independent version of the Windows PsApi PROCESS_MEMORY_COUNTERS\r
+ * structure.\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class ProcessMemoryCounters {\r
+ public int PageFaultCount;\r
+ public long PeakWorkingSetSize;\r
+ public long WorkingSetSize;\r
+ public long QuotaPeakPagedPoolUsage;\r
+ public long QuotaPagedPoolUsage;\r
+ public long QuotaPeakNonPagedPoolUsage;\r
+ public long QuotaNonPagedPoolUsage;\r
+ public long PagefileUsage;\r
+ public long PeakPagefileUsage;\r
+ public long PrivateUsage;\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "ProcessMemoryCounters [PageFaultCount="\r
+ + PageFaultCount + ", PeakWorkingSetSize=" + PeakWorkingSetSize\r
+ + ", WorkingSetSize=" + WorkingSetSize\r
+ + ", QuotaPeakPagedPoolUsage=" + QuotaPeakPagedPoolUsage\r
+ + ", QuotaPagedPoolUsage=" + QuotaPagedPoolUsage\r
+ + ", QuotaPeakNonPagedPoolUsage=" + QuotaPeakNonPagedPoolUsage\r
+ + ", QuotaNonPagedPoolUsage=" + QuotaNonPagedPoolUsage\r
+ + ", PagefileUsage=" + PagefileUsage + ", PeakPagefileUsage="\r
+ + PeakPagefileUsage + ", PrivateUsage=" + PrivateUsage + "]";\r
+ }\r
+\r
+ public String toHumanReadableString() {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append("ProcessMemoryCounters [\n\tPageFaultCount = ").append(PageFaultCount)\r
+ .append(",\n\tPeakWorkingSetSize = ").append(toMb(PeakWorkingSetSize))\r
+ .append(" MB,\n\tWorkingSetSize = ").append(toMb(WorkingSetSize))\r
+ .append(" MB,\n\tQuotaPeakPagedPoolUsage = ").append(toMb(QuotaPeakPagedPoolUsage))\r
+ .append(" MB,\n\tQuotaPagedPoolUsage = ").append(toMb(QuotaPagedPoolUsage))\r
+ .append(" MB,\n\tQuotaPeakNonPagedPoolUsage = ").append(toMb(QuotaPeakNonPagedPoolUsage))\r
+ .append(" MB,\n\tQuotaNonPagedPoolUsage = ").append(toMb(QuotaNonPagedPoolUsage))\r
+ .append(" MB,\n\tPagefileUsage = ").append(toMb(PagefileUsage))\r
+ .append(" MB,\n\tPeakPagefileUsage = ").append(toMb(PeakPagefileUsage))\r
+ .append(" MB,\n\tPrivateUsage = ").append(toMb(PrivateUsage))\r
+ .append(" MB]");\r
+ return sb.toString();\r
+ }\r
+\r
+ private double toMb(long bytes) {\r
+ return (double) bytes / 1048576.0;\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.nativemem.internal;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public enum Arch {\r
+ PPC, PPC_64, SPARC, X86, X86_64, UNKNOWN;\r
+\r
+ public static Arch calculate() {\r
+ String osArch = System.getProperty("os.arch");\r
+ assert osArch != null;\r
+ osArch = osArch.toLowerCase();\r
+ if (osArch.equals("i386") || osArch.equals("i586") || osArch.equals("i686") || osArch.equals("x86"))\r
+ return X86;\r
+ if (osArch.startsWith("amd64") || osArch.startsWith("x86_64"))\r
+ return X86_64;\r
+ if (osArch.equals("ppc"))\r
+ return PPC;\r
+ if (osArch.startsWith("ppc"))\r
+ return PPC_64;\r
+ if (osArch.startsWith("sparc"))\r
+ return SPARC;\r
+ return UNKNOWN;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.nativemem.internal;\r
+\r
+public enum OS {\r
+ APPLE, LINUX, SUN, WINDOWS, UNKNOWN;\r
+\r
+ public static OS calculate() {\r
+ String osName = System.getProperty("os.name");\r
+ assert osName != null;\r
+ osName = osName.toLowerCase();\r
+ if (osName.startsWith("mac os x"))\r
+ return APPLE;\r
+ if (osName.startsWith("windows"))\r
+ return WINDOWS;\r
+ if (osName.startsWith("linux"))\r
+ return LINUX;\r
+ if (osName.startsWith("sun"))\r
+ return SUN;\r
+ return UNKNOWN;\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.nativemem.internal;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+import org.simantics.nativemem.ProcessMemoryCounters;\r
+\r
+import com.sun.jna.Native;\r
+import com.sun.jna.Structure;\r
+import com.sun.jna.platform.win32.WinNT.HANDLE;\r
+import com.sun.jna.win32.StdCallLibrary;\r
+\r
+public interface Psapi32 extends StdCallLibrary {\r
+\r
+ Psapi32 INSTANCE = (Psapi32) Native.loadLibrary("Psapi", Psapi32.class);\r
+\r
+ /*\r
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms684874%28v=vs.85%29.aspx\r
+ */\r
+ public static class PROCESS_MEMORY_COUNTERS_EX extends Structure {\r
+ public int cb;\r
+ public int PageFaultCount;\r
+ public int PeakWorkingSetSize;\r
+ public int WorkingSetSize;\r
+ public int QuotaPeakPagedPoolUsage;\r
+ public int QuotaPagedPoolUsage;\r
+ public int QuotaPeakNonPagedPoolUsage;\r
+ public int QuotaNonPagedPoolUsage;\r
+ public int PagefileUsage;\r
+ public int PeakPagefileUsage;\r
+ public int PrivateUsage;\r
+\r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ protected List getFieldOrder() {\r
+ return PROCESS_MEMORY_COUNTERS_EX_FIELDS;\r
+ }\r
+\r
+ static final List<String> PROCESS_MEMORY_COUNTERS_EX_FIELDS = Arrays.asList(new String[] { \r
+ "cb", "PageFaultCount",\r
+ "PeakWorkingSetSize", "WorkingSetSize",\r
+ "QuotaPeakPagedPoolUsage", "QuotaPagedPoolUsage",\r
+ "QuotaPeakNonPagedPoolUsage", "QuotaNonPagedPoolUsage",\r
+ "PagefileUsage", "PeakPagefileUsage", "PrivateUsage"\r
+ });\r
+\r
+ public void writeTo(ProcessMemoryCounters to) {\r
+ to.PageFaultCount = PageFaultCount;\r
+ to.PeakWorkingSetSize = PeakWorkingSetSize;\r
+ to.WorkingSetSize = WorkingSetSize;\r
+ to.QuotaPeakPagedPoolUsage = QuotaPeakPagedPoolUsage;\r
+ to.QuotaPagedPoolUsage = QuotaPagedPoolUsage;\r
+ to.QuotaPeakNonPagedPoolUsage = QuotaPeakNonPagedPoolUsage;\r
+ to.QuotaNonPagedPoolUsage = QuotaNonPagedPoolUsage;\r
+ to.PagefileUsage = PagefileUsage;\r
+ to.PeakPagefileUsage = PeakPagefileUsage;\r
+ to.PrivateUsage = PrivateUsage;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms683219%28v=vs.85%29.aspx\r
+ */\r
+ boolean GetProcessMemoryInfo(HANDLE Process, PROCESS_MEMORY_COUNTERS_EX ppsmemCounters, int cb);\r
+\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.nativemem.internal;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+import org.simantics.nativemem.ProcessMemoryCounters;\r
+\r
+import com.sun.jna.Native;\r
+import com.sun.jna.Structure;\r
+import com.sun.jna.platform.win32.WinNT.HANDLE;\r
+import com.sun.jna.win32.StdCallLibrary;\r
+\r
+public interface Psapi64 extends StdCallLibrary {\r
+\r
+ Psapi64 INSTANCE = (Psapi64) Native.loadLibrary("Psapi", Psapi64.class);\r
+\r
+ /*\r
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms684874%28v=vs.85%29.aspx\r
+ */\r
+ public static class PROCESS_MEMORY_COUNTERS_EX extends Structure {\r
+ public int cb;\r
+ public int PageFaultCount;\r
+ public long PeakWorkingSetSize;\r
+ public long WorkingSetSize;\r
+ public long QuotaPeakPagedPoolUsage;\r
+ public long QuotaPagedPoolUsage;\r
+ public long QuotaPeakNonPagedPoolUsage;\r
+ public long QuotaNonPagedPoolUsage;\r
+ public long PagefileUsage;\r
+ public long PeakPagefileUsage;\r
+ public long PrivateUsage;\r
+\r
+ @SuppressWarnings("rawtypes")\r
+ @Override\r
+ protected List getFieldOrder() {\r
+ return PROCESS_MEMORY_COUNTERS_EX_FIELDS;\r
+ }\r
+\r
+ private static final List<String> PROCESS_MEMORY_COUNTERS_EX_FIELDS = Arrays.asList(new String[] { \r
+ "cb", "PageFaultCount",\r
+ "PeakWorkingSetSize", "WorkingSetSize",\r
+ "QuotaPeakPagedPoolUsage", "QuotaPagedPoolUsage",\r
+ "QuotaPeakNonPagedPoolUsage", "QuotaNonPagedPoolUsage",\r
+ "PagefileUsage", "PeakPagefileUsage", "PrivateUsage"\r
+ });\r
+\r
+ public void writeTo(ProcessMemoryCounters to) {\r
+ to.PageFaultCount = PageFaultCount;\r
+ to.PeakWorkingSetSize = PeakWorkingSetSize;\r
+ to.WorkingSetSize = WorkingSetSize;\r
+ to.QuotaPeakPagedPoolUsage = QuotaPeakPagedPoolUsage;\r
+ to.QuotaPagedPoolUsage = QuotaPagedPoolUsage;\r
+ to.QuotaPeakNonPagedPoolUsage = QuotaPeakNonPagedPoolUsage;\r
+ to.QuotaNonPagedPoolUsage = QuotaNonPagedPoolUsage;\r
+ to.PagefileUsage = PagefileUsage;\r
+ to.PeakPagefileUsage = PeakPagefileUsage;\r
+ to.PrivateUsage = PrivateUsage;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms683219%28v=vs.85%29.aspx\r
+ */\r
+ boolean GetProcessMemoryInfo(HANDLE Process, PROCESS_MEMORY_COUNTERS_EX ppsmemCounters, int cb);\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.nativemem.internal;\r
+\r
+import org.simantics.nativemem.NativeMem;\r
+import org.simantics.nativemem.ProcessMemoryCounters;\r
+\r
+public class Test {\r
+\r
+ public static void main(String[] args) {\r
+ ProcessMemoryCounters mem = NativeMem.getMemoryCounters(null);\r
+ System.out.println(mem.toHumanReadableString());\r
+ }\r
+\r
+}\r
package org.cojen.classfile;
-import java.io.Serializable;
import java.io.Externalizable;
-import java.io.ObjectOutput;
-import java.io.ObjectInput;
import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.io.ObjectStreamException;
+import java.io.Serializable;
import java.lang.reflect.Method;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
import org.cojen.util.WeakCanonicalSet;
package org.cojen.classfile;
import java.io.Serializable;
-import java.io.Externalizable;
-import java.io.ObjectOutput;
-import java.io.ObjectInput;
-import java.io.IOException;
-import java.io.ObjectStreamException;
import java.lang.ref.SoftReference;
import java.lang.reflect.Array;
import java.util.Collections;
return false;
}
- Object writeReplace() throws ObjectStreamException {
- return new External(mDescriptor);
- }
-
private static class PrimitiveType extends TypeDesc {
private transient final int mCode;
private transient TypeDesc mArrayType;
}
}
}
-
- private static class External implements Externalizable {
- private String mDescriptor;
-
- public External() {
- }
-
- public External(String desc) {
- mDescriptor = desc;
- }
-
- public void writeExternal(ObjectOutput out) throws IOException {
- out.writeUTF(mDescriptor);
- }
-
- public void readExternal(ObjectInput in) throws IOException {
- mDescriptor = in.readUTF();
- }
-
- public Object readResolve() throws ObjectStreamException {
- return forDescriptor(mDescriptor);
- }
- }
}
package org.simantics.scl.compiler.commands;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectProcedure;
-import gnu.trove.set.hash.THashSet;
-
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import org.simantics.scl.runtime.reporting.SCLReportingHandler;
import org.simantics.scl.runtime.tuple.Tuple0;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
public class CommandSession {
package org.simantics.scl.compiler.commands;
-import gnu.trove.map.hash.THashMap;
-
import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
import org.simantics.scl.compiler.top.ExpressionEvaluator;
import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.runtime.function.Function1;
+import gnu.trove.map.hash.THashMap;
+
public class ValueToStringConverter {
final RuntimeEnvironment environment;
final THashMap<Type, Function1> showInstances = new THashMap<Type, Function1>();
package org.simantics.scl.compiler.compilation;\r
\r
-import gnu.trove.map.hash.TObjectLongHashMap;\r
-\r
import java.util.ArrayList;\r
\r
+import gnu.trove.map.hash.TObjectLongHashMap;\r
+\r
public class CompilationTimer {\r
private long initialTime, previousTime;\r
private ArrayList<TimerEntry> entries = new ArrayList<TimerEntry>();\r
package org.simantics.scl.compiler.compilation;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.module.ConcreteModule;
import org.simantics.scl.compiler.types.TCon;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
public class DocumentationGeneration {
THashMap<String, DDocumentationAst> valueDocumentation;
THashMap<String, DDocumentationAst> typeDocumentation;
package org.simantics.scl.compiler.compilation;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.simantics.scl.compiler.environment.AmbiguousNameException;\r
import org.simantics.scl.compiler.environment.Environment;\r
import org.simantics.scl.compiler.errors.ErrorLog;\r
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
\r
public class NameExistenceChecks {\r
public static void checkIfValueExists(ErrorLog errorLog, long location,\r
Environment environment, String name) {\r
- try {\r
- SCLValue value = environment.getLocalNamespace().getValue(name);\r
- if(value != null)\r
+ if(SCLCompilerConfiguration.ALLOW_OVERLOADING)\r
+ return;\r
+ else {\r
+ try {\r
+ SCLValue value = environment.getLocalNamespace().getValue(name);\r
+ if(value != null)\r
+ errorLog.log(location,\r
+ "Value " + name + " is already defined in the module " + \r
+ value.getName().module + \r
+ " that is imported to the default namespace.");\r
+ } catch(AmbiguousNameException e) {\r
errorLog.log(location,\r
- "Value " + name + " is already defined in the module " + \r
- value.getName().module + \r
- " that is imported to the default namespace.");\r
- } catch(AmbiguousNameException e) {\r
- errorLog.log(location,\r
- "Value " + name + " is already defined in the modules " + \r
- e.conflictingModules[0] + " and " + e.conflictingModules[1] + \r
- " that are imported to the default namespace.");\r
+ "Value " + name + " is already defined in the modules " + \r
+ e.conflictingModules[0] + " and " + e.conflictingModules[1] + \r
+ " that are imported to the default namespace.");\r
+ }\r
}\r
}\r
\r
package org.simantics.scl.compiler.compilation;
-import gnu.trove.procedure.TObjectProcedure;
-
+import java.util.Arrays;
import java.util.function.Consumer;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.environment.filter.NamespaceFilter;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.module.Module;
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
import org.simantics.scl.compiler.types.TCon;
+import gnu.trove.procedure.TObjectProcedure;
+
public class NamespaceOfModule implements Namespace {
private final Namespace base;
private final Module module;
@Override
public SCLValue getValue(String name) throws AmbiguousNameException {
SCLValue value = module.getValue(name);
+ if(SCLCompilerConfiguration.ALLOW_OVERLOADING) {
+ SCLValue value2;
+ try {
+ value2 = base.getValue(name);
+ } catch(AmbiguousNameException e) {
+ if(value != null) {
+ String[] conflictingModules = Arrays.copyOf(e.conflictingModules, e.conflictingModules.length+1);
+ conflictingModules[e.conflictingModules.length] = module.getName();
+ throw new AmbiguousNameException(Arrays.asList(conflictingModules), e.name);
+ }
+ else
+ throw e;
+ }
+ if(value == null)
+ return value2;
+ if(value2 == null)
+ return value;
+ throw new AmbiguousNameException(Arrays.asList(value.getName().module, value2.getName().module), value.getName().name);
+ }
+ else {
if(value != null)
return value;
return base.getValue(name);
+ }
}
@Override
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.lambda;
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc;
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.vars;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder;
import org.simantics.scl.compiler.elaboration.expressions.ETransformation;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
import org.simantics.scl.compiler.types.kinds.Kinds;
import org.simantics.scl.compiler.types.util.Polarity;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
public class TypeChecking {
final ErrorLog errorLog;
final Environment environment;
context.pushEffectUpperBound(expression.location, Types.PROC);
expression = expression.checkType(context, value.getType());
context.popEffectUpperBound();
+ for(EAmbiguous overloaded : context.overloadedExpressions)
+ overloaded.assertResolved(errorLog);
value.setExpression(expression);
ArrayList<EVariable> constraintDemand = context.getConstraintDemand();
@Override
public void run() {
Type type = value.getType();
+
Expression expression = value.getExpression();
try {
context.pushEffectUpperBound(expression.location, Types.PROC);
expression = expression.checkType(context, type);
context.popEffectUpperBound();
+ for(EAmbiguous overloaded : context.overloadedExpressions)
+ overloaded.assertResolved(errorLog);
expression.getType().addPolarity(Polarity.POSITIVE);
context.solveSubsumptions(expression.getLocation());
ArrayList<EVariable> demands = context.getConstraintDemand();
+++ /dev/null
-package org.simantics.scl.compiler.compilation;
-
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply;
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.applyTypes;
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.lambda;
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc;
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.vars;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
-import java.util.ArrayList;
-
-import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
-import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder;
-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.SCLValue;
-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.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 org.simantics.scl.compiler.internal.elaboration.constraints.ExpressionAugmentation;
-import org.simantics.scl.compiler.internal.elaboration.constraints.ReducedConstraints;
-import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
-import org.simantics.scl.compiler.module.ConcreteModule;
-import org.simantics.scl.compiler.types.TPred;
-import org.simantics.scl.compiler.types.TVar;
-import org.simantics.scl.compiler.types.Type;
-import org.simantics.scl.compiler.types.Types;
-import org.simantics.scl.compiler.types.kinds.Kinds;
-import org.simantics.scl.compiler.types.util.Polarity;
-
-public class TypeCheckingOld {
- public static final boolean PRINT_VALUES = false;
-
- ErrorLog errorLog;
- Environment environment;
- ConcreteModule module;
-
- ConstraintEnvironment ce;
- ArrayList<SCLValue[]> valuesWithoutTypeAnnotation = new ArrayList<SCLValue[]>();
- ArrayList<SCLValue> valuesWithTypeAnnotation = new ArrayList<SCLValue>();
-
- public TypeCheckingOld(ErrorLog errorLog, Environment environment,
- ConcreteModule module) {
- this.errorLog = errorLog;
- this.environment = environment;
- this.module = module;
- }
-
- public void typeCheck() {
- ce = new ConstraintEnvironment(environment);
- groupValueDefinitionsByDependency();
- typeCheckValuesWithoutTypeAnnotations();
- typeCheckValuesWithTypeAnnotations();
- typeCheckRules();
- }
-
- private void groupValueDefinitionsByDependency() {
- // Collect all untyped names
- final ArrayList<SCLValue> values = new ArrayList<SCLValue>();
- for(SCLValue value : module.getValues()) {
- if(value.getExpression() != null) {
- if(value.getType() == null)
- values.add(value);
- else
- valuesWithTypeAnnotation.add(value);
- }
- }
-
- // Create inverse
- final TObjectIntHashMap<Object> allRefs =
- new TObjectIntHashMap<Object>(values.size()*2, 0.5f, -1);
- for(int i=0;i<values.size();++i)
- allRefs.put(values.get(i), i);
-
- // Create groups
- new StronglyConnectedComponents(values.size()) {
-
- TIntHashSet set = new TIntHashSet();
-
- @Override
- protected void reportComponent(int[] component) {
- SCLValue[] valueComponent = new SCLValue[component.length];
- for(int i=0;i<component.length;++i)
- valueComponent[i] = values.get(component[i]);
- valuesWithoutTypeAnnotation.add(valueComponent);
- }
-
- @Override
- protected int[] findDependencies(int u) {
- Expression expression = values.get(u).getExpression();
- expression.collectRefs(allRefs, set);
-
- int[] result = set.toArray();
- set.clear();
-
- return result;
- }
-
- }.findComponents();
- }
-
- private void typeCheckValuesWithoutTypeAnnotations() {
- for(SCLValue[] group : valuesWithoutTypeAnnotation) {
- if(PRINT_VALUES) {
- System.out.println("---------------------------------------------");
- System.out.print("---");
- for(SCLValue value : group)
- System.out.print(" " + value.getName());
- System.out.println();
- }
-
- for(int i=0;i<group.length;++i)
- group[i].setType(Types.metaVar(Kinds.STAR));
-
- TypingContext context = new TypingContext(errorLog, environment);
- context.recursiveValues = new THashSet<SCLValue>();
- for(SCLValue value : group)
- context.recursiveValues.add(value);
-
- @SuppressWarnings("unchecked")
- ArrayList<EVariable>[] constraintDemands = new ArrayList[group.length];
-
- @SuppressWarnings("unchecked")
- ArrayList<EPlaceholder>[] recursiveReferences = new ArrayList[group.length];
- for(int i=0;i<group.length;++i) {
- context.recursiveReferences = new ArrayList<EPlaceholder>();
-
- SCLValue value = group[i];
- Expression expression = value.getExpression();
- expression = expression.checkType(context, value.getType());
- value.setExpression(expression);
-
- ArrayList<EVariable> constraintDemand = context.getConstraintDemand();
- if(!constraintDemand.isEmpty()) {
- constraintDemands[i] = constraintDemand;
- context.resetConstraintDemand();
- }
-
- recursiveReferences[i] = context.recursiveReferences;
- }
-
- for(Type type : Types.getTypes(group))
- type.addPolarity(Polarity.POSITIVE);
- context.solveSubsumptions(group[0].getExpression().getLocation());
- ArrayList<Constraint> allUnsolvedConstraints = new ArrayList<Constraint>();
-
- @SuppressWarnings("unchecked")
- ArrayList<Variable>[] freeEvidence = new ArrayList[group.length];
- for(int i=0;i<group.length;++i) {
- if(constraintDemands[i] != null) {
- SCLValue value = group[i];
- Expression expression = value.getExpression();
-
- ReducedConstraints red = ConstraintSolver.solve(
- ce, new ArrayList<TPred>(0), constraintDemands[i],
- true /*!Types.isFunction(expression.getType())*/);
-
- expression = ExpressionAugmentation.augmentSolved(
- red.solvedConstraints,
- expression);
- value.setExpression(expression);
- value.setType(expression.getType());
-
- for(Constraint c : red.unsolvedConstraints)
- if(c.constraint.isGround()) {
- 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) {
- allUnsolvedConstraints.add(c);
- fe.add(c.evidence);
- }
- freeEvidence[i] = fe;
- }
- else {
- group[i].setExpression(group[i].getExpression().decomposeMatching());
- freeEvidence[i] = new ArrayList<Variable>(0);
- }
- }
-
- THashSet<TVar> varSet = new THashSet<TVar>();
- for(int i=0;i<group.length;++i) {
- SCLValue value = group[i];
- Type type = value.getType();
- type = type.convertMetaVarsToVars();
- value.setType(type);
- varSet.addAll(Types.freeVars(type));
- }
-
- TVar[] vars = varSet.toArray(new TVar[varSet.size()]);
-
- // Collect all constraints needed in the group
- THashSet<TPred> constraintSet = new THashSet<TPred>();
- for(int i=0;i<group.length;++i) {
- for(Variable evidence : freeEvidence[i]) {
- constraintSet.add((TPred)evidence.getType());
- }
- }
- TPred[] constraints = constraintSet.toArray(new TPred[constraintSet.size()]);
- for(TPred constraint : constraints)
- if(constraint.containsMetaVars()) {
- for(Constraint c : allUnsolvedConstraints) {
- if(Types.equals(c.constraint, constraint)) {
- errorLog.log(c.getDemandLocation(),
- "Constrain " + constraint +
- " contains free variables not mentioned in the type of the value.");
- break;
- }
- }
- }
-
-
- // TODO copy to TypeChecking2 from this onwards
- for(int i=0;i<group.length;++i) {
- // Create evidence array of every value in the group that has the variables
- // in the same array as in the shared array
- ArrayList<Variable> fe = freeEvidence[i];
- THashMap<TPred, Variable> indexedEvidence = new THashMap<TPred, Variable>(fe.size());
- for(Variable v : fe)
- indexedEvidence.put((TPred)v.getType(), v);
- fe.clear();
- for(TPred c : constraints) {
- Variable var = indexedEvidence.get(c);
- if(var == null) {
- // These are variables that are not directly needed in
- // this definition but in the definitions that are
- // recursively called
- var = new Variable("evX");
- var.setType(c);
- fe.add(var);
- }
- fe.add(var);
- }
-
- // Add evidence parameters to the functions
- SCLValue value = group[i];
- value.setExpression(lambda(Types.NO_EFFECTS, fe, value.getExpression())
- .closure(vars));
- value.setType(Types.forAll(vars,
- Types.constrained(constraints, value.getType())));
-
- // Add evidence parameters to recursive calls
- for(EPlaceholder ref : recursiveReferences[i]) {
- ref.expression = loc(ref.expression.location, apply(
- Types.NO_EFFECTS,
- applyTypes(ref.expression, vars),
- vars(fe)));
- }
- }
- }
- }
-
- private void typeCheckValuesWithTypeAnnotations() {
- ArrayList<TPred> givenConstraints = new ArrayList<TPred>();
- for(SCLValue value : valuesWithTypeAnnotation) {
- Type type = value.getType();
- if(type != null) {
- if(PRINT_VALUES) {
- System.out.println("---------------------------------------------");
- System.out.println("--- " + value.getName() + " :: " + type);
- }
- Expression expression = value.getExpression();
- ArrayList<TVar> vars = new ArrayList<TVar>();
- type = Types.removeForAll(type, vars);
- type = Types.removePred(type, givenConstraints);
-
- /*System.out.println("---------------------------------------------");
- TypeUnparsingContext tuc = new TypeUnparsingContext();
- System.out.println("--- " + value.getName() + " :: " + type.toString(tuc));
- for(TPred t : givenConstraints)
- System.out.println(">>> " + t.toString(tuc));
- */
- TypingContext context = new TypingContext(errorLog, environment);
- //System.out.println(expression);
- expression = expression.checkType(context, type);
- //System.out.println(expression);
- expression.getType().addPolarity(Polarity.POSITIVE);
- context.solveSubsumptions(expression.getLocation());
- ArrayList<EVariable> demands = context.getConstraintDemand();
- if(!demands.isEmpty() || !givenConstraints.isEmpty()) {
- ReducedConstraints red =
- ConstraintSolver.solve(ce, givenConstraints, demands, true);
- givenConstraints.clear();
- for(Constraint c : red.unsolvedConstraints) {
- errorLog.log(c.getDemandLocation(),
- "Constraint <"+c.constraint+"> is not given and cannot be derived.");
- }
- if(errorLog.isEmpty()) { // To prevent exceptions
- expression = ExpressionAugmentation.augmentSolved(
- red.solvedConstraints,
- expression);
- expression = ExpressionAugmentation.augmentUnsolved(
- red.givenConstraints,
- expression);
- }
- }
- else {
- if(errorLog.isEmpty()) // To prevent exceptions
- expression = expression.decomposeMatching();
- }
- expression = expression.closure(vars.toArray(new TVar[vars.size()]));
- value.setExpression(expression);
- }
- }
- }
-
- public void typeCheckRules() {
- TypingContext context = new TypingContext(errorLog, environment);
- for(TransformationRule rule : module.getRules()) {
- context.pushEffectUpperBound(rule.location, Types.metaVar(Kinds.EFFECT));
- rule.checkType(context);
- rule.setEffect(Types.canonical(context.popEffectUpperBound()));
- }
- context.solveSubsumptions(Locations.NO_LOCATION);
-
- ArrayList<EVariable> demands = context.getConstraintDemand();
- if(!demands.isEmpty()) {
- ReducedConstraints red =
- ConstraintSolver.solve(ce, new ArrayList<TPred>(), demands, true);
- for(Constraint c : red.unsolvedConstraints) {
- errorLog.log(c.getDemandLocation(),
- "Constraint <"+c.constraint+"> is not given and cannot be derived.");
- }
- }
-
- 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.");
- break;
- }
-
- /*for(Rule rule : module.getRules()) {
- System.out.println(rule.name);
- for(Variable variable : rule.variables)
- System.out.println(" " + variable.getName() + " :: " + variable.getType());
- }*/
- }
-}
package org.simantics.scl.compiler.compilation;
-import gnu.trove.impl.Constants;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.TVar;
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
/**
* Schedules the order of type checking.
*
package org.simantics.scl.compiler.compilation;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.ArrayList;
import java.util.Collection;
import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.TVar;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
public interface TypeInferableDefinition {
long getLocation();
Collection<Object> getDefinedObjects();
package org.simantics.scl.compiler.constants;
-import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
import org.simantics.scl.compiler.types.Type;
package org.simantics.scl.compiler.constants;
-import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
import org.simantics.scl.compiler.types.Type;
package org.simantics.scl.compiler.constants.generic;
-import gnu.trove.map.hash.THashMap;
-
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.simantics.scl.compiler.constants.generic.MethodRef.StaticMethodRef;
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
+import gnu.trove.map.hash.THashMap;
+
/**
* This class is a reference to a Java class that contains a map of MethodRef for each
* method declared by the referenced class.
package org.simantics.scl.compiler.elaboration.contexts;
-import gnu.trove.list.array.TLongArrayList;
-import gnu.trove.map.hash.THashMap;
-
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.types.exceptions.MatchException;
import org.simantics.scl.compiler.types.util.MultiFunction;
+import gnu.trove.list.array.TLongArrayList;
+import gnu.trove.map.hash.THashMap;
+
public class SimplificationContext implements EnvironmentalContext {
Environment environment;
ErrorLog errorLog;
package org.simantics.scl.compiler.elaboration.contexts;
-import gnu.trove.list.array.TIntArrayList;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectProcedure;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import java.util.Arrays;
import org.simantics.scl.compiler.common.precedence.Associativity;
import org.simantics.scl.compiler.common.precedence.Precedence;
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.expressions.EEntityTypeAnnotation;
import org.simantics.scl.compiler.elaboration.expressions.EError;
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;
+import org.simantics.scl.compiler.types.Type;
+
+import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
public class TranslationContext extends TypeTranslationContext implements EnvironmentalContext {
}
private Expression resolveIn(long location, Namespace namespace, String name) {
- SCLValue value = resolveValueIn(location, namespace, name);
+ SCLValue value;
+ try {
+ value = resolveValueIn(location, namespace, name);
+ } catch (AmbiguousNameException e) {
+ if(SCLCompilerConfiguration.ALLOW_OVERLOADING) {
+ EAmbiguous.Alternative[] alternatives = new EAmbiguous.Alternative[e.conflictingModules.length];
+ //System.out.println("Overloading:");
+ for(int i=0;i<e.conflictingModules.length;++i) {
+ Name altName = Name.create(e.conflictingModules[i], e.name);
+ //System.out.println(" " + altName);
+ SCLValue altValue = environment.getValue(altName);
+ alternatives[i] = new EAmbiguous.Alternative() {
+ @Override
+ public Type getType() {
+ return altValue.getType();
+ }
+
+ @Override
+ public Expression realize() {
+ EConstant expression = new EConstant(altValue);
+ expression.location = location;
+ return expression;
+ }
+
+ @Override
+ public String toString() {
+ return altValue.getName().toString().replace('/', '.');
+ }
+ };
+ }
+ EAmbiguous expression = new EAmbiguous(alternatives);
+ expression.location = location;
+ return expression;
+ }
+ else {
+ errorLog.log(location, e.getMessage());
+ value = null;
+ }
+ }
if(value == null)
return new EError(location);
return new EConstant(location, value);
return prec;
}
- private SCLValue resolveValueIn(long location, Namespace namespace, final String name) {
- try {
+ private SCLValue resolveValueIn(long location, Namespace namespace, final String name) throws AmbiguousNameException {
SCLValue value = namespace.getValue(name);
if(value == null) {
StringBuilder message = new StringBuilder();
return null;
}
return value;
- } catch (AmbiguousNameException e) {
- errorLog.log(location, e.getMessage());
- return null;
- }
}
public Case translateCase(Expression lhs, Expression rhs) {
package org.simantics.scl.compiler.elaboration.contexts;
-import gnu.trove.map.hash.THashMap;
-
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.errors.ErrorLog;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
import org.simantics.scl.compiler.types.kinds.Kind;
import org.simantics.scl.compiler.types.kinds.Kinds;
+import gnu.trove.map.hash.THashMap;
+
public class TypeTranslationContext {
Environment environment;
package org.simantics.scl.compiler.elaboration.contexts;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
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.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.types.kinds.Kinds;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
public class TypingContext implements EnvironmentalContext {
private ErrorLog errorLog;
public THashSet<SCLValue> recursiveValues;
public ArrayList<EPlaceholder> recursiveReferences;
+ // Overloading
+ public ArrayList<EAmbiguous> overloadedExpressions = new ArrayList<EAmbiguous>();
+
//TypeUnparsingContext tuc = new TypeUnparsingContext();
Environment environment;
* Instantiates type abstractions and constraints from the value.
*/
public Expression instantiate(Expression expr) {
- Type type = Types.weakCanonical(expr.getType());
+ Type type = Types.canonical(expr.getType());
while(type instanceof TForAll) {
TForAll forAll = (TForAll)type;
TVar var = forAll.var;
* type applications, lambdas and effect subsumptions.
*/
public Expression subsume(Expression expr, Type b) {
- b = Types.weakCanonical(b);
+ b = Types.canonical(b);
/*if(b instanceof TForAll) {
TForAll forAll = (TForAll)b;
TVar var = forAll.var;
\r
@Override\r
public void checkType(TypingContext context) {\r
- guard = guard.inferType(context);\r
+ guard = guard.checkIgnoredType(context);\r
}\r
\r
@Override\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\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.TypingContext;\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 abstract class ASTExpression extends SimplifiableExpression {\r
public ASTExpression() {\r
}\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.internal.parsing.Symbol;\r
import org.simantics.scl.compiler.types.Type;\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 Case extends Symbol {\r
public Expression[] patterns;\r
public Expression value;\r
patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);\r
value = value.checkType(context, requiredType);\r
}\r
+ \r
+ public void checkIgnoredType(TypingContext context, Type[] parameterTypes) {\r
+ if(patterns.length != parameterTypes.length) {\r
+ context.getErrorLog().log(location, "This case has different arity ("+patterns.length+\r
+ ") than than the first case (+"+parameterTypes.length+"+).");\r
+ return;\r
+ }\r
+ for(int i=0;i<patterns.length;++i)\r
+ patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);\r
+ value = value.checkIgnoredType(context);\r
+ }\r
\r
public void decorate(ExpressionDecorator decorator) {\r
for(int i=0;i<patterns.length;++i)\r
expression = expression.checkBasicType(context, requiredType);
return this;
}
+
+ @Override
+ public Expression checkIgnoredType(TypingContext context) {
+ expression = expression.checkIgnoredType(context);
+ return this;
+ }
}
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.types.Skeletons;
+import org.simantics.scl.compiler.types.TMetaVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+import org.simantics.scl.compiler.types.exceptions.UnificationException;
+import org.simantics.scl.compiler.types.util.TypeListener;
+import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EAmbiguous extends SimplifiableExpression {
+ public static final boolean DEBUG = false;
+
+ Alternative[] alternatives;
+ boolean[] active;
+ int activeCount;
+ transient TypingContext context;
+ Expression resolvedExpression;
+
+ public abstract static class Alternative {
+ public abstract Type getType();
+ public abstract Expression realize();
+ }
+
+ public EAmbiguous(Alternative[] alternatives) {
+ this.alternatives = alternatives;
+ this.active = new boolean[alternatives.length];
+ for(int i=0;i<alternatives.length;++i)
+ this.active[i] = true;
+ this.activeCount = alternatives.length;
+ }
+
+ @Override
+ public void collectRefs(TObjectIntHashMap<Object> allRefs,
+ TIntHashSet refs) {
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ throw new InternalCompilerError();
+ }
+
+ private Type getCommonSkeleton() {
+ Type[] types = new Type[activeCount];
+ for(int i=0,j=0;i<alternatives.length;++i)
+ if(active[i])
+ types[j++] = Types.instantiateAndStrip(alternatives[i].getType());
+ return Skeletons.commonSkeleton(context.getEnvironment(), types);
+ }
+
+ private void filterActive() {
+ THashMap<TMetaVar,Type> unifications = new THashMap<TMetaVar,Type>();
+ Type requiredType = getType();
+ if(DEBUG)
+ System.out.println("EAmbigious.filterActive with " + requiredType);
+ for(int i=0;i<alternatives.length;++i)
+ if(active[i]) {
+ unifications.clear();
+ Type alternativeType = Types.instantiateAndStrip(alternatives[i].getType());
+ if(DEBUG)
+ System.out.println(" " + alternativeType);
+ if(!Skeletons.areSkeletonsCompatible(unifications, alternativeType, requiredType)) {
+ active[i] = false;
+ --activeCount;
+ }
+ }
+ if(DEBUG)
+ System.out.println(" activeCount = " + activeCount);
+ }
+
+ private String getNoMatchDescription(Type requiredType) {
+ StringBuilder b = new StringBuilder();
+ b.append("Expected <");
+ requiredType.toString(new TypeUnparsingContext(), b);
+ b.append(">, but no alteratives match the type: ");
+ for(int i=0;i<alternatives.length;++i) {
+ b.append("\n ");
+ b.append(alternatives[i]);
+ b.append(" :: ");
+ alternatives[i].getType().toString(new TypeUnparsingContext(), b);
+ }
+ b.append('.');
+ return b.toString();
+ }
+
+ private String getAmbiguousDescription(Type requiredType) {
+ StringBuilder b = new StringBuilder();
+ b.append("Expected <");
+ requiredType.toString(new TypeUnparsingContext(), b);
+ b.append(">, but multiple values match the type: ");
+ for(int i=0;i<alternatives.length;++i) {
+ b.append("\n ");
+ b.append(alternatives[i]);
+ b.append(" :: ");
+ alternatives[i].getType().toString(new TypeUnparsingContext(), b);
+ }
+ b.append('.');
+ return b.toString();
+ }
+
+
+ private void resolveTo(int i) {
+ if(DEBUG)
+ System.out.println("EAmbigious.resolve to " + alternatives[i]);
+ resolvedExpression = context.instantiate(alternatives[i].realize());
+ Type requiredType = getType();
+ try {
+ Types.unify(resolvedExpression.getType(), requiredType);
+ } catch (UnificationException e) {
+ context.getErrorLog().log(location, getNoMatchDescription(requiredType));
+ }
+ }
+
+ private void listenType() {
+ if(DEBUG)
+ System.out.println("EAmbigious.listenType " + getType());
+ new TypeListener() {
+ @Override
+ public void notifyAboutChange() {
+ if(DEBUG)
+ System.out.println("EAmbigious.notifyAboutChange " + getType());
+ Type requiredType = getType();
+ filterActive();
+ if(activeCount == 0) {
+ context.getErrorLog().log(location, getNoMatchDescription(requiredType));
+ return;
+ }
+ else if(activeCount == 1) {
+ for(int i=0;i<alternatives.length;++i)
+ if(active[i]) {
+ resolveTo(i);
+ return;
+ }
+ }
+ Type commonType = getCommonSkeleton();
+ try {
+ Skeletons.unifySkeletons(requiredType, commonType);
+ listenType();
+ } catch (UnificationException e) {
+ context.getErrorLog().log(location, getNoMatchDescription(requiredType));
+ }
+ }
+ }.listenSkeleton(getType());
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ this.context = context;
+ context.overloadedExpressions.add(this);
+ setType(getCommonSkeleton());
+ listenType();
+ return this;
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ throw new InternalCompilerError("EAmbiguousConstant should not exist in resolve phase.");
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION)
+ location = loc;
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ return this;
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ if(resolvedExpression != null)
+ return resolvedExpression;
+ else {
+ context.getErrorLog().log(location, getAmbiguousDescription(getType()));
+ return this;
+ }
+ }
+
+ public void assertResolved(ErrorLog errorLog) {
+ if(resolvedExpression == null)
+ errorLog.log(location, getAmbiguousDescription(getType()));
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+}
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.constants.NoRepConstant;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
import org.simantics.scl.compiler.internal.interpreted.IListLiteral;\r
import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
+import org.simantics.scl.compiler.types.Skeletons;\r
+import org.simantics.scl.compiler.types.TFun;\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.kinds.Kinds;\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 EApply extends Expression {\r
Expression function;\r
Expression[] parameters;\r
return new IApply(function.toIExpression(target), parametersI);\r
}\r
\r
- @Override\r
- public Expression inferType(TypingContext context) {\r
+ private void inferType(TypingContext context, boolean ignoreResult) {\r
function = function.inferType(context);\r
function = context.instantiate(function);\r
MultiFunction mfun;\r
setType(Types.metaVar(Kinds.STAR));\r
for(int i=0;i<parameters.length;++i)\r
parameters[i] = parameters[i].inferType(context);\r
- return this;\r
+ return;\r
+ }\r
+ if((ignoreResult && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun &&\r
+ Types.canonical(mfun.effect) == Types.NO_EFFECTS) ||\r
+ (context.isInPattern() && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun)) {\r
+ context.getErrorLog().log(location, "The function is applied with too few parameters.");\r
}\r
\r
// Check parameter types\r
\r
context.declareEffect(location, mfun.effect);\r
setType(mfun.returnType);\r
-\r
+ }\r
+ \r
+ @Override\r
+ public Expression inferType(TypingContext context) {\r
+ inferType(context, false);\r
+ return this;\r
+ }\r
+ \r
+ @Override\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ inferType(context, true);\r
+ if(Types.canonical(getType()) != Types.UNIT)\r
+ return new ESimpleLet(location, null, this, new ELiteral(NoRepConstant.PUNIT));\r
return this;\r
}\r
\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.types.Types;\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 EApplyType extends Expression { \r
Expression expression;\r
Type parameter;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\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 EAsPattern extends Expression {\r
\r
Variable var;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\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.types.exceptions.UnificationException;\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 EBind extends SimplifiableExpression {\r
public Expression pattern;\r
public Expression value;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.names.Name;\r
import org.simantics.scl.compiler.types.util.MultiFunction;\r
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\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 EConstant extends Expression {\r
SCLValue value;\r
Type[] typeParameters;\r
return this;\r
}\r
else\r
- return this;\r
+ return applyPUnit(context);\r
}\r
\r
@Override\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.types.Types;\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 EEnforce extends SimplifiableExpression {\r
\r
Query query;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.*;\r
-import gnu.trove.map.hash.THashMap;\r
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc;\r
\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.elaboration.java.EqRelation;\r
import org.simantics.scl.compiler.errors.Locations;\r
import org.simantics.scl.compiler.internal.parsing.Token;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class EEntityTypeAnnotation extends ASTExpression {\r
\r
Expression expression;\r
return this;\r
}\r
\r
+ @Override\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ return inferType(context);\r
+ }\r
+\r
@Override\r
public Expression simplify(SimplificationContext context) {\r
context.getErrorLog().log(location, "Equations should be transformed into other expressions before simplification phase.");\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.types.exceptions.MatchException;\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 EError extends Expression {\r
\r
public EError(long loc, Type type) {\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.types.exceptions.MatchException;\r
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\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 EExternalConstant extends Expression {\r
Object value;\r
\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.names.Name;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.types.Types;\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 EFieldAccess extends SimplifiableExpression {\r
\r
private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.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 EGetConstraint extends SimplifiableExpression {\r
TPred constraint;\r
EVariable evidence;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.types.Types;\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 EIf extends Expression {\r
public Expression condition;\r
public Expression then_;\r
return this;\r
}\r
\r
+ @Override\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ condition = condition.checkType(context, Types.BOOLEAN);\r
+ then_ = then_.checkIgnoredType(context);\r
+ else_ = else_.checkIgnoredType(context);\r
+ return this;\r
+ }\r
+ \r
@Override\r
public Expression decorate(ExpressionDecorator decorator) {\r
condition = condition.decorate(decorator);\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.constants.DoubleConstant;\r
import org.simantics.scl.compiler.constants.FloatConstant;\r
import org.simantics.scl.compiler.types.Types;\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 EIntegerLiteral extends SimplifiableExpression {\r
public String value;\r
EVariable constraint;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.types.kinds.Kinds;\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 ELambda extends SimplifiableExpression {\r
public Case[] cases;\r
Type effect = Types.NO_EFFECTS;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.types.Types;\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 ELambdaType extends Expression {\r
public TVar[] parameters;\r
public Expression value;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.types.exceptions.MatchException;\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 ELet extends Expression {\r
public Assignment[] assignments;\r
public Expression in;\r
in = in.checkType(context, requiredType);\r
return this;\r
}\r
+ \r
+ @Override\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ checkAssignments(context);\r
+ in = in.checkIgnoredType(context);\r
+ return this;\r
+ }\r
\r
@Override\r
public Expression decorate(ExpressionDecorator decorator) {\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.types.Types;\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 EListComprehension extends SimplifiableExpression {\r
\r
public Expression head;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.types.Types;\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 EListLiteral extends SimplifiableExpression {\r
\r
Expression[] components;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.constants.Constant;\r
import org.simantics.scl.compiler.types.exceptions.MatchException;\r
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\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 ELiteral extends Expression {\r
Constant value;\r
\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\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.ssa.exits.Throw;\r
import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler;\r
import org.simantics.scl.compiler.internal.elaboration.matching.Row;\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 EMatch extends Expression {\r
\r
public Expression[] scrutinee;\r
CodeWriter joinPoint = w.createBlock(getType());\r
CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function\r
PatternMatchingCompiler.split(w, env, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);\r
- failurePoint.throw_(location, "Matching failure at: " + toString());\r
+ failurePoint.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());\r
w.continueAs(joinPoint);\r
return w.getParameters()[0];\r
}\r
setType(requiredType);\r
return this;\r
}\r
+ \r
+ @Override\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ Type[] scrutineeTypes = new Type[scrutinee.length];\r
+ for(int i=0;i<scrutinee.length;++i) {\r
+ scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));\r
+ scrutineeTypes[i] = scrutinee[i].getType();\r
+ }\r
+ for(Case case_ : cases)\r
+ case_.checkIgnoredType(context, scrutineeTypes);\r
+ setType(Types.UNIT);\r
+ return this;\r
+ }\r
\r
@Override\r
public Expression decorate(ExpressionDecorator decorator) {\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectObjectProcedure;\r
-\r
import java.util.ArrayList;\r
import java.util.List;\r
\r
import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
import org.simantics.scl.compiler.errors.Locations;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectObjectProcedure;\r
+\r
public class EPreLet extends ASTExpression {\r
\r
List<LetStatement> assignments;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;\r
import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;\r
import org.simantics.scl.compiler.elaboration.relations.LocalRelation;\r
import org.simantics.scl.compiler.errors.Locations;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class EPreRuleset extends ASTExpression {\r
\r
RuleStatement[] statements;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.constants.DoubleConstant;\r
import org.simantics.scl.compiler.constants.FloatConstant;\r
import org.simantics.scl.compiler.types.Types;\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 ERealLiteral extends SimplifiableExpression {\r
public String value;\r
EVariable constraint;\r
return new EError(constructor.location);
}
THashMap<String,FieldAssignment> recordMap = new THashMap<String,FieldAssignment>(fields.length);
- for(FieldAssignment field : fields)
- recordMap.put(field.name, field);
+ for(FieldAssignment field : fields) {
+ if(field.value == null) {
+ String bestMatch = null;
+ int bestMatchLength = 0;
+ for(int i=0;i<fieldNames.length;++i) {
+ String fieldName = fieldNames[i];
+ if(field.name.startsWith(fieldName) && fieldName.length() > bestMatchLength) {
+ bestMatch = fieldName;
+ bestMatchLength = fieldName.length();
+ }
+ }
+ if(bestMatch == null) {
+ context.getErrorLog().log(field.location, "Invalid shorthand field " + field.name + " is defined twice.");
+ return new EError(location);
+ }
+ field.value = new EVar(field.location, field.name);
+ field.name = bestMatch;
+ }
+ if(recordMap.put(field.name, field) != null) {
+ context.getErrorLog().log(field.location, "Field " + field.name + " is defined more than once.");
+ return new EError(location);
+ }
+ }
Expression[] parameters = new Expression[fieldNames.length];
boolean error = false;
for(int i=0;i<fieldNames.length;++i) {
if(location == Locations.NO_LOCATION) {
location = loc;
for(FieldAssignment field : fields)
- field.value.setLocationDeep(loc);
+ if(field.value != null)
+ field.value.setLocationDeep(loc);
}
}
return compile(context);\r
}\r
\r
+ @Override\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ checkRuleTypes(context);\r
+ in = in.checkIgnoredType(context);\r
+ return compile(context);\r
+ }\r
+ \r
@Override\r
public void collectFreeVariables(THashSet<Variable> vars) {\r
for(DatalogRule rule : rules) {\r
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.seq;\r
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.tuple;\r
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\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.types.exceptions.MatchException;\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 ESelect extends SimplifiableExpression {\r
\r
private final Type ARRAY_LIST = Types.con("ArrayList", "T"); \r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.types.kinds.Kinds;\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 ESimpleLambda extends Expression {\r
public Variable parameter;\r
public Expression value;\r
\r
private void checkBinding(TypingContext context) {\r
if(variable == null)\r
- value = value.inferType(context);\r
+ value = value.checkIgnoredType(context);\r
else if(variable.getType() == null) {\r
value = value.inferType(context);\r
variable.setType(value.getType());\r
in = in.checkType(context, requiredType);\r
return this;\r
}\r
+ \r
+ @Override\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ checkBinding(context);\r
+ in = in.checkIgnoredType(context);\r
+ return this;\r
+ }\r
\r
@Override\r
public Expression decorate(ExpressionDecorator decorator) {\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
import java.util.Collections;\r
import java.util.Comparator;\r
import org.simantics.scl.compiler.types.Types;\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 ETransformation extends SimplifiableExpression {\r
public static final Object TRANSFORMATION_RULES_TYPECHECKED = new Object();\r
\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.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 ETypeAnnotation extends SimplifiableExpression {\r
Expression value;\r
Type type;\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.types.kinds.Kinds;\r
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\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 EVariable extends Expression {\r
public static final EVariable[] EMPTY_ARRAY = new EVariable[0];\r
\r
\r
@Override\r
public Expression inferType(TypingContext context) {\r
- if(context.isInPattern())\r
+ if(context.isInPattern()) {\r
variable.setType(Types.metaVar(Kinds.STAR));\r
- return this;\r
+ return this;\r
+ }\r
+ else\r
+ return applyPUnit(context);\r
}\r
\r
@Override\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.types.exceptions.UnificationException;\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 EWhen extends SimplifiableExpression {\r
\r
public Query query;\r
for(Variable variable : variables)\r
variable.setType(Types.metaVar(Kinds.STAR));\r
query.checkType(context);\r
- action.checkType(context, Types.UNIT);\r
+ action.checkIgnoredType(context);\r
\r
// Compile query\r
return compile(context);\r
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.common.precedence.Precedence;\r
+import org.simantics.scl.compiler.constants.NoRepConstant;\r
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.types.kinds.Kinds;\r
import org.simantics.scl.compiler.types.util.Typed;\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 abstract class Expression extends Symbol implements Typed {\r
public static final Expression[] EMPTY_ARRAY = new Expression[0];\r
\r
public Expression inferType(TypingContext context) {\r
return checkBasicType(context, Types.metaVar(Kinds.STAR));\r
}\r
- \r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- return context.subsume(inferType(context), requiredType);\r
- }\r
+\r
+ public Expression checkBasicType(TypingContext context, Type requiredType) {\r
+ return context.subsume(inferType(context), requiredType);\r
+ }\r
+ \r
+ protected Expression applyPUnit(EnvironmentalContext context) {\r
+ Type type = Types.canonical(getType());\r
+ if(type instanceof TFun) {\r
+ TFun fun = (TFun)type;\r
+ if(fun.getCanonicalDomain() == Types.PUNIT) {\r
+ EApply result = new EApply(location, this, new ELiteral(NoRepConstant.PUNIT));\r
+ result.effect = fun.getCanonicalEffect();\r
+ return result;\r
+ }\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Expression checkIgnoredType(TypingContext context) {\r
+ Expression expression = inferType(context);\r
+ if(Types.canonical(expression.getType()) != Types.UNIT)\r
+ expression = new ESimpleLet(location, null, expression, new ELiteral(NoRepConstant.PUNIT));\r
+ return expression;\r
+ }\r
\r
/**\r
* Checks the type of the expression against the given type. Adds type\r
public final Expression checkType(TypingContext context, Type requiredType) {\r
//System.out.println("checkType: " + this + " :: " + requiredType);\r
if(!context.isInPattern()) {\r
- requiredType = Types.weakCanonical(requiredType);\r
+ requiredType = Types.canonical(requiredType);\r
if(requiredType instanceof TForAll) {\r
TForAll forAll = (TForAll)requiredType;\r
TVar var = forAll.var;\r
public interface ExpressionTransformer {
+ Expression transform(EAmbiguous expression);
Expression transform(EApply expression);
Expression transform(EApplyType expression);
Expression transform(EAsPattern expression);
package org.simantics.scl.compiler.elaboration.expressions;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
import org.simantics.scl.compiler.errors.Locations;\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.ssa.exits.Throw;\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
\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 GuardedExpressionGroup extends Expression {\r
public GuardedExpression[] expressions;\r
\r
CodeWriter failure = w.createBlock();\r
compile(env, w, success.getContinuation(), failure.getContinuation());\r
w.continueAs(success);\r
- failure.throw_(location, "Matching failure at: " + toString());\r
+ failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());\r
return result;\r
//throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation.");\r
}\r
ExpressionTransformer, QueryTransformer, ListQualifierTransformer, StatementVisitor,
EquationVisitor {
+ @Override
+ public Expression transform(EAmbiguous expression) {
+ return expression;
+ }
+
@Override
public Expression transform(EApply expression) {
expression.function = expression.function.accept(this);
package org.simantics.scl.compiler.elaboration.expressions.accessor;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.internal.elaboration.utils.ExpressionDecorator;\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 ExpressionAccessor extends FieldAccessor {\r
public Expression fieldName;\r
\r
package org.simantics.scl.compiler.elaboration.expressions.accessor;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.internal.elaboration.utils.ExpressionDecorator;\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 abstract class FieldAccessor extends Symbol {\r
public char accessSeparator;\r
\r
\r
@Override\r
public Expression toExpression(EnvironmentalContext context, boolean monadic, Expression in) {\r
- Variable var = new Variable("_");\r
- if(monadic)\r
+ if(monadic) {\r
+ Variable var = new Variable("_");\r
return new EBind(location, new EVariable(location, var), value, in);\r
+ }\r
else\r
- return new ESimpleLet(location, var, value, in);\r
+ return new ESimpleLet(location, null, value, in);\r
}\r
\r
@Override\r
package org.simantics.scl.compiler.elaboration.expressions.list;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.internal.elaboration.utils.ExpressionDecorator;\r
import org.simantics.scl.compiler.types.Type;\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 ListAssignment extends ListQualifier {\r
public Expression pattern;\r
public Expression value;\r
package org.simantics.scl.compiler.elaboration.expressions.list;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.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 ListGenerator extends ListQualifier {\r
public Expression pattern;\r
public Expression value;\r
package org.simantics.scl.compiler.elaboration.expressions.list;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.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 ListGuard extends ListQualifier {\r
public Expression condition;\r
\r
package org.simantics.scl.compiler.elaboration.expressions.list;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.internal.parsing.Symbol;\r
import org.simantics.scl.compiler.types.Type;\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 abstract class ListQualifier extends Symbol {\r
\r
public abstract void checkType(TypingContext context);\r
package org.simantics.scl.compiler.elaboration.expressions.list;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.internal.elaboration.utils.ExpressionDecorator;\r
import org.simantics.scl.compiler.types.Type;\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 ListSeq extends ListQualifier {\r
public ListQualifier a;\r
public ListQualifier b;\r
package org.simantics.scl.compiler.elaboration.expressions.list;\r
\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\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.types.exceptions.UnificationException;\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 ListThen extends ListQualifier {\r
public ListQualifier left;\r
public Expression transformer;\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.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.EEquations;\r
import org.simantics.scl.compiler.elaboration.expressions.EError;\r
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
import org.simantics.scl.compiler.elaboration.expressions.EMatch;\r
import org.simantics.scl.compiler.elaboration.expressions.EPlaceholder;\r
-import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;\r
import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral;\r
import org.simantics.scl.compiler.elaboration.expressions.ERuleset;\r
import org.simantics.scl.compiler.elaboration.expressions.ESelect;\r
ESimpleLet let = (ESimpleLet)expression;\r
Variable variable = let.getVariable();\r
Expression value = let.getValue();\r
- if("_".equals(variable.getName()))\r
+ if(variable == null || "_".equals(variable.getName()))\r
printAsDo(value);\r
else {\r
newLine();\r
package org.simantics.scl.compiler.elaboration.java;
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.*;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.constant;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.string;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;
import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.constants.generic.CallJava;
package org.simantics.scl.compiler.elaboration.macros;
-import gnu.trove.map.hash.THashMap;
-
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
+import gnu.trove.map.hash.THashMap;
+
/**
* This is a macro rule that replaces an application with
* the definition of the function.
package org.simantics.scl.compiler.elaboration.modules;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import java.util.ArrayList;\r
\r
import org.cojen.classfile.TypeDesc;\r
import org.simantics.scl.compiler.types.Types;\r
import org.simantics.scl.compiler.types.kinds.Kinds;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class TypeClass extends TypeConstructor {\r
public final TPred[] context;\r
public final TCon name;\r
package org.simantics.scl.compiler.elaboration.modules;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import org.simantics.scl.compiler.constants.Constant;\r
import org.simantics.scl.compiler.elaboration.errors.ElabNode;\r
import org.simantics.scl.compiler.types.TPred;\r
import org.simantics.scl.compiler.types.TVar;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class TypeClassInstance extends ElabNode {\r
public final TypeClass typeClass;\r
public final TPred[] context; \r
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.Arrays;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
import org.simantics.scl.compiler.elaboration.query.pre.QPreExists;
import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
import org.simantics.scl.compiler.errors.Locations;
-import org.simantics.scl.compiler.types.Type;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
public abstract class QAbstractCombiner extends Query {
public Query[] queries;
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
import org.simantics.scl.compiler.errors.Locations;
-import org.simantics.scl.compiler.types.Type;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
public abstract class QAbstractModifier extends Query {
public Query query;
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TIntObjectHashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.ArrayList;
import java.util.Set;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
public class QAtom extends Query {
public SCLRelation relation;
public Type[] typeParameters;
public Expression[] parameters;
-
+
public QAtom(SCLRelation relation, Expression ... parameters) {
this.relation = relation;
this.parameters = parameters;
}
-
+
public QAtom(SCLRelation relation, Type[] typeParameters, Expression ... parameters) {
this.relation = relation;
this.typeParameters = typeParameters;
for(Expression parameter : parameters)
parameter.collectFreeVariables(vars);
}
-
+
@Override
public void checkType(TypingContext context) {
// Type parameters
typeParameters = new Type[typeVariables.length];
for(int i=0;i<typeVariables.length;++i)
typeParameters[i] = Types.metaVar(typeVariables[i].getKind());
-
+
// Check parameter types
Type[] parameterTypes = relation.getParameterTypes();
if(parameterTypes.length != parameters.length)
parameters[i] = parameters[i]
.checkType(context, parameterTypes[i].replace(typeVariables, typeParameters));
}
-
+
public Expression generateEnforce(EnforcingContext context) {
Variable[] variables = new Variable[parameters.length];
for(int i=0;i<variables.length;++i)
private static class VariableMaskProcedure implements VariableProcedure {
ConstraintCollectionContext context;
long requiredVariablesMask = 0L;
-
+
public VariableMaskProcedure(ConstraintCollectionContext context) {
this.context = context;
}
requiredVariablesMask |= 1L << id;
}
}
-
+
@Override
public void collectConstraints(ConstraintCollectionContext context) {
try {
}
}
}
-
+
// Combine required and optional variables
TIntHashSet allVariablesSet = new TIntHashSet();
for(int v : optionalVariableByParameter)
if(v >= 0)
allVariablesSet.add(v);
-
+
context.addConstraint(new RelationConstraint(allVariablesSet.toArray(), varParameters, this,
optionalVariableByParameter, procedure.requiredVariablesMask));
} catch(Exception e) {
context.getQueryCompilationContext().getTypingContext().getErrorLog().log(location, e);
}
}
-
+
private static void collectRefs(SCLRelation relation, TObjectIntHashMap<Object> allRefs,
TIntHashSet refs) {
if(relation instanceof CompositeRelation) {
for(Expression parameter : parameters)
parameter.collectRefs(allRefs, refs);
}
-
+
@Override
public void collectVars(TObjectIntHashMap<Variable> allVars,
TIntHashSet vars) {
return new Diff[] { new Diff(diffable.id, new QConjunction(eqs)) };
}
}
-
+
private static boolean containsReferenceTo(
CompositeRelation relation,
THashMap<SCLRelation, Diffable> diffables) {
else
return this;
}
-
+
@Override
public void setLocationDeep(long loc) {
if(location == Locations.NO_LOCATION) {
parameter.setLocationDeep(loc);
}
}
-
+
@Override
public void accept(QueryVisitor visitor) {
visitor.visit(this);
}
list.add(this);
}
-
+
@Override
public Query accept(QueryTransformer transformer) {
return transformer.transform(this);
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TIntObjectHashMap;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+
public class QConjunction extends QAbstractCombiner {
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TLongObjectHashMap;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.ArrayList;
import java.util.Set;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TLongObjectHashMap;
+import gnu.trove.set.hash.TIntHashSet;
+
public class QDisjunction extends QAbstractCombiner {
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.Collection;
import java.util.Set;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.kinds.Kinds;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
public class QExists extends QAbstractModifier {
Variable[] variables;
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.types.Type;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
public class QMapping extends Query {
public final MappingRelation mappingRelation;
public final Expression[] parameters;
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.TIntHashSet;
-
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.relations.LocalRelation;
import org.simantics.scl.compiler.types.Type;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.TIntHashSet;
+
public class QNegation extends QAbstractModifier {
package org.simantics.scl.compiler.elaboration.query;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TIntObjectHashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.ArrayList;
import java.util.Set;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.internal.parsing.Symbol;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
public abstract class Query extends Symbol {
public static final Query[] EMPTY_ARRAY = new Query[0];
package org.simantics.scl.compiler.elaboration.query.compilation;
-import gnu.trove.impl.Constants;
-import gnu.trove.map.hash.TObjectIntHashMap;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
public class ConstraintCollectionContext {
QueryCompilationContext context;
ArrayList<Variable> variables = new ArrayList<Variable>();
package org.simantics.scl.compiler.elaboration.query.compilation;
-import gnu.trove.map.hash.TLongObjectHashMap;
-import gnu.trove.procedure.TLongObjectProcedure;
-
import java.util.ArrayList;
import java.util.Collections;
+import gnu.trove.map.hash.TLongObjectHashMap;
+import gnu.trove.procedure.TLongObjectProcedure;
+
public class DynamicProgrammingOrdering {
final ConstraintCollectionContext collectionContext;
int variableCount;
package org.simantics.scl.compiler.elaboration.query.compilation;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectObjectProcedure;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectObjectProcedure;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
public class ExpressionConstraint extends QueryConstraint {\r
Variable variable;\r
Expression expression;\r
package org.simantics.scl.compiler.elaboration.query.pre;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.query.Query;
import org.simantics.scl.compiler.elaboration.query.QueryVisitor;
import org.simantics.scl.compiler.elaboration.query.compilation.ConstraintCollectionContext;
-import org.simantics.scl.compiler.types.Type;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
/**
* Query classes that may exist before resolving
package org.simantics.scl.compiler.elaboration.relations;
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.*;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.newVar;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.tuple;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;
+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.Variable;
import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext;
import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
-import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;
import org.simantics.scl.compiler.common.names.Name;
-import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
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.query.compilation.QueryCompilationContext;
-import org.simantics.scl.compiler.errors.Locations;
-import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
package org.simantics.scl.compiler.elaboration.rules;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectObjectProcedure;
-import gnu.trove.procedure.TObjectProcedure;
-import gnu.trove.set.hash.THashSet;
-
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.kinds.Kinds;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
public class TransformationRule extends Symbol {
public static final TransformationRule[] EMPTY_ARRAY = new TransformationRule[0];
package org.simantics.scl.compiler.environment;\r
\r
-import gnu.trove.procedure.TObjectProcedure;\r
-\r
import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;\r
import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
import org.simantics.scl.compiler.types.util.ProcedureType;\r
\r
+import gnu.trove.procedure.TObjectProcedure;\r
+\r
public abstract class AbstractLocalEnvironment implements LocalEnvironment {\r
\r
@Override\r
package org.simantics.scl.compiler.environment;
-import gnu.trove.map.hash.THashMap;
-
import java.util.Collection;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
import org.simantics.scl.compiler.module.Module;
+import gnu.trove.map.hash.THashMap;
+
public class ConcreteEnvironment extends AbstractEnvironment {
private final THashMap<String, Module> moduleMap;
package org.simantics.scl.compiler.environment;
-import gnu.trove.procedure.TObjectProcedure;
-
import java.util.function.Consumer;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.types.TCon;
+import gnu.trove.procedure.TObjectProcedure;
+
public enum EmptyNamespace implements Namespace {
INSTANCE;
package org.simantics.scl.compiler.environment;
-import gnu.trove.procedure.TObjectProcedure;
-
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.Type;
+import gnu.trove.procedure.TObjectProcedure;
+
public class Environments {
/**
* Get the SCLValue object representing an SCL value defined in a given environment.
package org.simantics.scl.compiler.environment;\r
\r
-import gnu.trove.procedure.TObjectProcedure;\r
-\r
import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.util.ProcedureType;\r
\r
+import gnu.trove.procedure.TObjectProcedure;\r
+\r
/**\r
* Provides local variable names for expressions\r
* that do not need to defined in any module.\r
package org.simantics.scl.compiler.environment;
-import gnu.trove.procedure.TObjectProcedure;
-
import java.util.function.Consumer;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.types.TCon;
+import gnu.trove.procedure.TObjectProcedure;
+
public interface Namespace {
/**
* Find a sub-namespace with a given name
package org.simantics.scl.compiler.environment;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectProcedure;
-
import java.util.ArrayList;
import java.util.function.Consumer;
import org.simantics.scl.compiler.module.Module;
import org.simantics.scl.compiler.types.TCon;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+
public class NamespaceImpl implements Namespace {
private final THashMap<String, Namespace> namespaceMap;
package org.simantics.scl.compiler.environment;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import java.util.Map;\r
\r
import org.simantics.scl.compiler.environment.NamespaceImpl.ModuleImport;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class NamespaceSpec {\r
public final THashMap<String, NamespaceSpec> namespaceMap = new THashMap<String, NamespaceSpec>();\r
public final THashMap<String, ModuleImport> moduleMap = new THashMap<String, ModuleImport>();\r
package org.simantics.scl.compiler.environment.filter;\r
\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import org.simantics.scl.compiler.elaboration.expressions.EVar;\r
import org.simantics.scl.compiler.module.ImportDeclaration.ImportSpec;\r
\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public class NamespaceFilters {\r
public static NamespaceFilter createFromSpec(ImportSpec spec) {\r
if(spec.hiding) {\r
package org.simantics.scl.compiler.errors;
-import gnu.trove.list.array.TIntArrayList;
-
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
+import gnu.trove.list.array.TIntArrayList;
+
public class CompilationErrorFormatter {
public static int[] rows(Reader reader) throws IOException {
package org.simantics.scl.compiler.internal.codegen.analysis;\r
\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import org.simantics.scl.compiler.common.names.Name;\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.ssa.binders.ValRefBinder;\r
import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public class LoopAnalysis {\r
\r
/**\r
package org.simantics.scl.compiler.internal.codegen.analysis;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\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.constants.SCLConstant;\r
import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;\r
import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public abstract class StatementBrowser {\r
\r
THashSet<SSABlock> visited;\r
package org.simantics.scl.compiler.internal.codegen.optimization;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import org.simantics.scl.compiler.common.names.Name;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class OptimizationMap {\r
\r
public static final THashMap<Name, Optimization> OPTIMIZATIONS = new THashMap<Name, Optimization>();\r
package org.simantics.scl.compiler.internal.codegen.references;
-import gnu.trove.map.hash.THashMap;
-
import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
import org.simantics.scl.compiler.internal.codegen.ssa.binders.BoundVarBinder;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
+import gnu.trove.map.hash.THashMap;
+
public final class BoundVar extends Val {
public BoundVarBinder parent;
Type type;
package org.simantics.scl.compiler.internal.codegen.references;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.internal.codegen.types.BTypes;\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.exceptions.MatchException;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
\r
public abstract class Val implements IVal {\r
\r
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.utils.Constants;
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.SSAValidationContext;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.runtime.exceptions.MatchingException;
public class Throw extends SSAExit {
- private static final TypeDesc RuntimeException =
+ public static final TypeDesc RuntimeException =
TypeDesc.forClass(RuntimeException.class);
+ public static final TypeDesc MatchingException =
+ TypeDesc.forClass(MatchingException.class);
+ TypeDesc exceptionClass;
String description;
- public Throw(String description) {
+ public Throw(TypeDesc exceptionClass, String description) {
+ this.exceptionClass = exceptionClass;
this.description = description;
}
public void generateCode(MethodBuilder mb) {
//mb.push(exception.getBinding());
//cb.mapLineNumber(location);
- mb.newObject(RuntimeException);
+ mb.newObject(exceptionClass);
mb.dup();
- mb.loadConstant(description);
- mb.invokeConstructor(RuntimeException, new TypeDesc[] {TypeDesc.STRING});
+ if(description == null)
+ mb.invokeConstructor(exceptionClass, Constants.EMPTY_TYPEDESC_ARRAY);
+ else {
+ mb.loadConstant(description);
+ mb.invokeConstructor(exceptionClass, new TypeDesc[] {TypeDesc.STRING});
+ }
mb.throwObject();
}
@Override
public SSAExit copy(CopyContext context) {
- return new Throw(description);
+ return new Throw(exceptionClass, description);
}
@Override
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
-import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
\r
public class LetApply extends LetStatement implements ValRefBinder {\r
private ValRef function;\r
package org.simantics.scl.compiler.internal.codegen.ssa.statements;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
import org.simantics.scl.compiler.types.TVar;\r
import org.simantics.scl.compiler.types.Type;\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
long recursiveGroupLocation;\r
SSAFunction firstFunction;\r
return new MethodBuilder(this, moduleBuilder, (access&Opcodes.ACC_STATIC) != 0, methodVisitor, params);
}
- private MethodVisitor augmentMethodVisitor(String methodName, MethodVisitor methodVisitor) {
+ private MethodVisitor augmentMethodVisitor(final String methodName, MethodVisitor methodVisitor) {
if(SCLCompilerConfiguration.TRACE_MAX_METHOD_SIZE && moduleBuilder != null) {
methodVisitor = new CodeSizeEvaluator(methodVisitor) {
@Override
package org.simantics.scl.compiler.internal.codegen.utils;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\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.continuations.ContRef;\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
+\r
public class CopyContext {\r
\r
THashMap<Val, Val> valMap = new THashMap<Val, Val>();\r
package org.simantics.scl.compiler.internal.codegen.utils;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import java.util.ArrayDeque;\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.types.Type;\r
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public class PrintingContext {\r
\r
THashMap<Object, String> names = new THashMap<Object, String>(); \r
package org.simantics.scl.compiler.internal.codegen.utils;
-import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
import org.cojen.classfile.TypeDesc;
import org.simantics.scl.runtime.SCLContext;
package org.simantics.scl.compiler.internal.codegen.utils;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.procedure.TObjectIntProcedure;
-import gnu.trove.set.hash.THashSet;
-
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.constants.SCLConstant;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TObjectIntProcedure;
+import gnu.trove.set.hash.THashSet;
+
public class SSAValidationContext {
public THashSet<BoundVar> validBoundVariables = new THashSet<BoundVar>();
-package org.simantics.scl.compiler.internal.codegen.writer;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.internal.codegen.continuations.Branch;\r
-import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;\r
-import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\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.references.ValRef;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.exits.If;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.exits.Switch;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions;\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
-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
-public class CodeWriter {\r
-\r
- ModuleWriter moduleWriter;\r
- SSABlock block;\r
- \r
- CodeWriter(ModuleWriter moduleWriter, SSABlock block) {\r
- this.moduleWriter = moduleWriter;\r
- this.block = block;\r
- }\r
-\r
- public IVal apply(int lineNumber, IVal function, IVal ... parameters) {\r
- try {\r
- MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);\r
- return applyWithEffect(lineNumber,\r
- mfun.effect,\r
- mfun.returnType,\r
- function, parameters);\r
- } catch (MatchException e) {\r
- throw new InternalCompilerError(e);\r
- }\r
- }\r
- \r
- public IVal applyWithEffectChecked(int lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {\r
- try {\r
- MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);\r
- if(!Types.equals(effect, mfun.effect))\r
- throw new InternalCompilerError();\r
- if(!Types.equals(returnType, mfun.returnType))\r
- throw new InternalCompilerError();\r
- } catch (MatchException e) {\r
- throw new InternalCompilerError(e);\r
- } \r
- return applyWithEffect(lineNumber, effect, returnType, function, parameters);\r
- }\r
- \r
- public IVal applyWithEffect(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {\r
- BoundVar var = new BoundVar(returnType);\r
- LetApply apply = new LetApply(var,\r
- effect,\r
- function.createOccurrence(), \r
- ValRef.createOccurrences(parameters));\r
- apply.location = location;\r
- block.addStatement(apply);\r
- return var;\r
- }\r
- \r
- public CodeWriter createBlock(Type ... parameterTypes) {\r
- SSABlock newBlock = new SSABlock(parameterTypes);\r
- block.getParent().addBlock(newBlock);\r
- return new CodeWriter(moduleWriter, newBlock);\r
- }\r
- \r
- public CodeWriter createFunction(TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {\r
- if(SCLCompilerConfiguration.DEBUG)\r
- if(effect == null)\r
- throw new InternalCompilerError();\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
- \r
- this.block.addStatement(new LetFunctions(function));\r
- return new CodeWriter(moduleWriter, block);\r
- }\r
- \r
- public RecursiveDefinitionWriter createRecursiveDefinition() {\r
- LetFunctions let = new LetFunctions();\r
- block.addStatement(let);\r
- return new RecursiveDefinitionWriter(moduleWriter, let);\r
- }\r
- \r
- public void continueAs(CodeWriter codeWriter) {\r
- this.block = codeWriter.block;\r
- codeWriter.block = null;\r
- }\r
- \r
- public IVal[] getParameters() {\r
- return block.getParameters();\r
- }\r
- \r
- public ICont getContinuation() {\r
- return block;\r
- }\r
- \r
- public void jump(ICont cont, IVal ... parameters) {\r
- block.setExit(new Jump(cont.createOccurrence(), \r
- ValRef.createOccurrences(parameters)));\r
- block = null;\r
- }\r
- \r
- public void if_(IVal condition, ICont thenTarget, ICont elseTarget) {\r
- block.setExit(new If(condition.createOccurrence(), \r
- thenTarget.createOccurrence(), \r
- elseTarget.createOccurrence()));\r
- block = null;\r
- }\r
-\r
- public void return_(IVal val) {\r
- jump(block.getParent().getReturnCont(), val);\r
- }\r
-\r
- public void switch_(IVal val, Branch[] branches) {\r
- block.setExit(new Switch(val.createOccurrence(), BranchRef.toBranchRefs(branches)));\r
- block = null;\r
- }\r
-\r
- public void throw_(long location, String description) {\r
- Throw exit = new Throw(description);\r
- exit.location = location;\r
- block.setExit(exit);\r
- block = null;\r
- }\r
- \r
- public ModuleWriter getModuleWriter() {\r
- return moduleWriter;\r
- }\r
-\r
- public SSAFunction getFunction() {\r
- return block.getParent();\r
- } \r
-}\r
+package org.simantics.scl.compiler.internal.codegen.writer;
+
+import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.internal.codegen.continuations.Branch;
+import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+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.exits.If;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Switch;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
+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.top.SCLCompilerConfiguration;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+import org.simantics.scl.compiler.types.util.MultiFunction;
+
+public class CodeWriter {
+
+ ModuleWriter moduleWriter;
+ SSABlock block;
+
+ CodeWriter(ModuleWriter moduleWriter, SSABlock block) {
+ this.moduleWriter = moduleWriter;
+ this.block = block;
+ }
+
+ public IVal apply(int lineNumber, IVal function, IVal ... parameters) {
+ try {
+ MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
+ return applyWithEffect(lineNumber,
+ mfun.effect,
+ mfun.returnType,
+ function, parameters);
+ } catch (MatchException e) {
+ throw new InternalCompilerError(e);
+ }
+ }
+
+ public IVal applyWithEffectChecked(int lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {
+ try {
+ MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
+ if(!Types.equals(effect, mfun.effect))
+ throw new InternalCompilerError();
+ if(!Types.equals(returnType, mfun.returnType))
+ throw new InternalCompilerError();
+ } catch (MatchException e) {
+ throw new InternalCompilerError(e);
+ }
+ return applyWithEffect(lineNumber, effect, returnType, function, parameters);
+ }
+
+ public IVal applyWithEffect(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {
+ BoundVar var = new BoundVar(returnType);
+ LetApply apply = new LetApply(var,
+ effect,
+ function.createOccurrence(),
+ ValRef.createOccurrences(parameters));
+ apply.location = location;
+ block.addStatement(apply);
+ return var;
+ }
+
+ public CodeWriter createBlock(Type ... parameterTypes) {
+ SSABlock newBlock = new SSABlock(parameterTypes);
+ block.getParent().addBlock(newBlock);
+ return new CodeWriter(moduleWriter, newBlock);
+ }
+
+ public CodeWriter createFunction(TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {
+ if(SCLCompilerConfiguration.DEBUG)
+ if(effect == null)
+ throw new InternalCompilerError();
+ SSAFunction function = new SSAFunction(typeParameters, effect, returnType);
+ SSABlock block = new SSABlock(parameterTypes);
+ function.addBlock(block);
+ BoundVar target = new BoundVar(function.getType());
+ function.setTarget(target);
+
+ this.block.addStatement(new LetFunctions(function));
+ return new CodeWriter(moduleWriter, block);
+ }
+
+ public RecursiveDefinitionWriter createRecursiveDefinition() {
+ LetFunctions let = new LetFunctions();
+ block.addStatement(let);
+ return new RecursiveDefinitionWriter(moduleWriter, let);
+ }
+
+ public void continueAs(CodeWriter codeWriter) {
+ this.block = codeWriter.block;
+ codeWriter.block = null;
+ }
+
+ public IVal[] getParameters() {
+ return block.getParameters();
+ }
+
+ public ICont getContinuation() {
+ return block;
+ }
+
+ public void jump(ICont cont, IVal ... parameters) {
+ block.setExit(new Jump(cont.createOccurrence(),
+ ValRef.createOccurrences(parameters)));
+ block = null;
+ }
+
+ public void if_(IVal condition, ICont thenTarget, ICont elseTarget) {
+ block.setExit(new If(condition.createOccurrence(),
+ thenTarget.createOccurrence(),
+ elseTarget.createOccurrence()));
+ block = null;
+ }
+
+ public void return_(IVal val) {
+ jump(block.getParent().getReturnCont(), val);
+ }
+
+ public void switch_(IVal val, Branch[] branches) {
+ block.setExit(new Switch(val.createOccurrence(), BranchRef.toBranchRefs(branches)));
+ block = null;
+ }
+
+ public void throw_(long location, TypeDesc exceptionClass, String description) {
+ Throw exit = new Throw(exceptionClass, description);
+ exit.location = location;
+ block.setExit(exit);
+ block = null;
+ }
+
+ public ModuleWriter getModuleWriter() {
+ return moduleWriter;
+ }
+
+ public SSAFunction getFunction() {
+ return block.getParent();
+ }
+}
package org.simantics.scl.compiler.internal.codegen.writer;
-import gnu.trove.map.hash.THashMap;
-
import java.util.Map;
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.runtime.tuple.Tuple2;
+import gnu.trove.map.hash.THashMap;
+
public class ModuleWriter {
SSAModule module;
package org.simantics.scl.compiler.internal.deriving;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import org.simantics.scl.compiler.types.TCon;\r
import org.simantics.scl.compiler.types.Types;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class InstanceDerivers {\r
private static final THashMap<TCon, InstanceDeriver> MAP = \r
new THashMap<TCon, InstanceDeriver>();\r
package org.simantics.scl.compiler.internal.elaboration.constraints;
-import gnu.trove.map.hash.THashMap;
-
import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.ClassConstant;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.THashMap;
+
public class ConstraintEnvironment {
Environment environment;
package org.simantics.scl.compiler.internal.elaboration.constraints;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
class ConstraintSet {
private static int id = 0;
package org.simantics.scl.compiler.internal.elaboration.constraints;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
import java.util.Collections;\r
import org.simantics.scl.compiler.types.util.TConComparator;\r
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public class ConstraintSolver {\r
\r
public static THashSet<TCon> DEFAULTS_IGNORE = new THashSet<TCon>(); \r
package org.simantics.scl.compiler.internal.elaboration.constraints;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectObjectProcedure;\r
-\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.types.TApply;\r
import org.simantics.scl.compiler.types.Types;\r
import org.simantics.scl.compiler.types.util.MultiApply;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectObjectProcedure;\r
+\r
public class InstanceTree<T> {\r
\r
Node<T> root;\r
package org.simantics.scl.compiler.internal.elaboration.constraints2;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectObjectProcedure;
-
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.TPred;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+
public class ConstraintSolver {
final Environment environment;
private final THashMap<TCon, ConstraintStore> constraintStores =
package org.simantics.scl.compiler.internal.elaboration.constraints2;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectProcedure;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+
class ConstraintStore {
private final ConstraintSolver solver;
package org.simantics.scl.compiler.internal.elaboration.matching;
-import gnu.trove.map.hash.THashMap;
-
import java.util.ArrayList;
import java.util.List;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.exceptions.MatchException;
+import gnu.trove.map.hash.THashMap;
+
public class PatternMatchingCompiler {
private static class ExpressionMatrix {
import java.util.ArrayList;
import org.simantics.scl.compiler.elaboration.expressions.Case;
+import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EApplyType;
import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;
return expression;
}
+ @Override
+ public Expression transform(EAmbiguous expression) {
+ ++codeCounter;
+ return super.transform(expression);
+ }
+
@Override
public Expression transform(EApply expression) {
++codeCounter;
package org.simantics.scl.compiler.internal.elaboration.subsumption;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import java.util.ArrayDeque;\r
import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.types.util.Polarity;\r
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public class SubSolver {\r
\r
public static final boolean DEBUG = false;\r
package org.simantics.scl.compiler.internal.elaboration.transformations;
-import gnu.trove.procedure.TObjectObjectProcedure;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.elaboration.rules.SectionName;
import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
+import gnu.trove.procedure.TObjectObjectProcedure;
+
public class DecomposedRule {
final TransformationRule rule;
final ArrayList<Query> sourceQueries = new ArrayList<Query>();
package org.simantics.scl.compiler.internal.elaboration.transformations;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TIntObjectHashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.top.SCLExpressionCompilationException;
import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+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");
package org.simantics.scl.compiler.internal.elaboration.transformations;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.codegen.references.IVal;
-import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
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.compiler.types.util.MultiApply;
import org.simantics.scl.compiler.types.util.MultiFunction;
+import gnu.trove.map.hash.THashMap;
+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");
@Override
public int hashCode() {
if(hashCode == 0) {
- TypeHashCodeContext hcContext = new TypeHashCodeContext();
- hcContext.append(function.hashCode());
+ int hash = HashCodeUtils.SEED;
+ hash = HashCodeUtils.update(hash, function.hashCode());
for(Type typeParameter : typeParameters)
- typeParameter.updateHashCode(hcContext);
- hashCode = hcContext.getResult();
+ hash = typeParameter.hashCode(hash);
+ hashCode = hash;
}
return hashCode;
}
package org.simantics.scl.compiler.internal.parsing.declarations;
-import gnu.trove.map.hash.THashMap;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.elaboration.query.Query;
+import gnu.trove.map.hash.THashMap;
+
public class DRuleAst extends DeclarationAst {
public final boolean isAbstract;
public final String name;
package org.simantics.scl.compiler.internal.parsing.translation;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import java.util.ArrayList;\r
import java.util.Collection;\r
\r
import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;\r
import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class RelationRepository {\r
THashMap<String, ArrayList<DRelationAst>> relations = \r
new THashMap<String, ArrayList<DRelationAst>>();\r
package org.simantics.scl.compiler.internal.types;
-import gnu.trove.map.hash.THashMap;
-
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.kinds.Kinds;
import org.simantics.scl.compiler.types.util.ITypeEnvironment;
+import gnu.trove.map.hash.THashMap;
+
public class TypeElaborationContext {
THashMap<String, TVar> vars;
package org.simantics.scl.compiler.internal.types;
-import gnu.trove.map.hash.TObjectIntHashMap;
-
import org.simantics.scl.compiler.types.TVar;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
public class TypeHashCodeContext {
public static final int APPLY = 0x12345678;
package org.simantics.scl.compiler.internal.types.effects;
-import gnu.trove.map.hash.TObjectIntHashMap;
-
import java.util.ArrayList;
import java.util.Collection;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
public class EffectIdMap {
public static final int MIN = 0;
package org.simantics.scl.compiler.markdown.html;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectProcedure;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import java.util.ArrayList;\r
import java.util.Collections;\r
import java.util.List;\r
\r
import org.simantics.scl.compiler.source.repository.ModuleSourceRepository;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectProcedure;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
public class HierarchicalDocumentationRef implements Comparable<HierarchicalDocumentationRef> {\r
final String name;\r
final ArrayList<HierarchicalDocumentationRef> children = new ArrayList<HierarchicalDocumentationRef>();\r
package org.simantics.scl.compiler.markdown.html;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectProcedure;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import java.util.Collections;
import org.simantics.scl.compiler.types.Types;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
public class SCLDocumentationExtensionNodeHandler implements ExtensionNodeHandler {
final ModuleRepository moduleRepository;
package org.simantics.scl.compiler.markdown.inlines;
-import gnu.trove.map.hash.THashMap;
-
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
+import gnu.trove.map.hash.THashMap;
+
public class Entities {
public static final THashMap<String, String> ENTITY_MAP = new THashMap<String, String>();
public static int MAX_ENTITY_LENGTH;
package org.simantics.scl.compiler.markdown.inlines;
-import gnu.trove.map.hash.THashMap;
-
import org.simantics.scl.compiler.markdown.internal.Scanner;
import org.simantics.scl.compiler.markdown.nodes.AutolinkNode;
import org.simantics.scl.compiler.markdown.nodes.CodeNode;
import org.simantics.scl.compiler.markdown.nodes.Reference;
import org.simantics.scl.compiler.markdown.nodes.TextNode;
+import gnu.trove.map.hash.THashMap;
+
public class Subject {
THashMap<String, Reference> referenceMap;
StringBuilder input;
package org.simantics.scl.compiler.markdown.internal;
-import gnu.trove.map.hash.TCharObjectHashMap;
-
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
+import gnu.trove.map.hash.TCharObjectHashMap;
+
public class HtmlEscape {
private static final Charset UTF8 = Charset.forName("UTF-8");
package org.simantics.scl.compiler.markdown.internal;
-import gnu.trove.map.hash.THashMap;
-
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import org.simantics.scl.compiler.markdown.nodes.ParagraphNode;
import org.simantics.scl.compiler.markdown.nodes.Reference;
+import gnu.trove.map.hash.THashMap;
+
public class MarkdownParser {
public static final boolean DEBUG = false;
public static final int CODE_INDENT = 4;
package org.simantics.scl.compiler.markdown.internal;
-import gnu.trove.set.hash.THashSet;
-
import org.simantics.scl.compiler.markdown.inlines.Subject;
+import gnu.trove.set.hash.THashSet;
+
public class Scanner {
public int level;
package org.simantics.scl.compiler.module;
-import gnu.trove.map.hash.THashMap;
-
import java.util.Collection;
import java.util.Collections;
import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.runtime.profiling.BranchPoint;
+import gnu.trove.map.hash.THashMap;
+
public abstract class LazyModule implements Module {
String moduleName;
package org.simantics.scl.compiler.module.repository;\r
\r
-import gnu.trove.procedure.TObjectProcedure;\r
-\r
import java.util.ArrayList;\r
import java.util.List;\r
import java.util.regex.Pattern;\r
import org.simantics.scl.compiler.errors.Failable;\r
import org.simantics.scl.compiler.module.Module;\r
\r
+import gnu.trove.procedure.TObjectProcedure;\r
+\r
public class ModuleRepositories {\r
public static List<SCLValue> allValuesMatching(final ModuleRepository repository, String pattern) {\r
final Pattern compiledPattern = pattern == null ? null \r
package org.simantics.scl.compiler.runtime;
-import gnu.trove.map.hash.THashMap;
-
import java.util.Map;
import org.simantics.scl.compiler.constants.Constant;
+import gnu.trove.map.hash.THashMap;
+
public class ExpressionClassLoader extends ClassLoader implements MutableClassLoader {
public static final boolean VALIDATE_CLASS_NAMES = true;
public static final boolean TRACE_CLASS_CREATION = false;
package org.simantics.scl.compiler.runtime;
-import gnu.trove.map.hash.THashMap;
-
import java.util.Map;
import org.simantics.scl.compiler.constants.Constant;
+import gnu.trove.map.hash.THashMap;
+
public interface MutableClassLoader {
public static final String SCL_PACKAGE_PREFIX = "scl.";
package org.simantics.scl.compiler.runtime;
-import gnu.trove.map.hash.THashMap;
-
import org.simantics.scl.compiler.environment.Environment;
+import gnu.trove.map.hash.THashMap;
+
public class RuntimeEnvironmentImpl implements RuntimeEnvironment {
private final Environment environment;
package org.simantics.scl.compiler.runtime;\r
\r
-import gnu.trove.map.hash.THashMap;\r
-\r
import java.util.Collection;\r
\r
+import gnu.trove.map.hash.THashMap;\r
+\r
public class RuntimeModuleMap {\r
THashMap<String, RuntimeModule> moduleMap = new THashMap<String, RuntimeModule>(); \r
\r
import java.io.IOException;
import java.io.InputStream;
-import java.nio.charset.Charset;
import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
import org.simantics.scl.compiler.internal.codegen.types.RuntimeJavaReferenceValidator;
package org.simantics.scl.compiler.source.repository;
-import gnu.trove.procedure.TObjectProcedure;
-import gnu.trove.set.hash.THashSet;
-
import java.io.IOException;
import java.net.URL;
import org.simantics.scl.compiler.source.ClassModuleSource;
import org.simantics.scl.compiler.source.ModuleSource;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
public class ClassModuleSourceRepository extends AbstractModuleSourceRepository {
private final Class<?> clazz;
package org.simantics.scl.compiler.source.repository;
-import gnu.trove.procedure.TObjectProcedure;
-
import org.simantics.scl.compiler.module.repository.UpdateListener;
import org.simantics.scl.compiler.source.ModuleSource;
+import gnu.trove.procedure.TObjectProcedure;
+
public class CompositeModuleSourceRepository implements ModuleSourceRepository {
public final ModuleSourceRepository[] children;
package org.simantics.scl.compiler.source.repository;
-import gnu.trove.procedure.TObjectProcedure;
-import gnu.trove.set.hash.THashSet;
-
import java.io.File;
import java.io.IOException;
import org.simantics.scl.compiler.source.FileModuleSource;
import org.simantics.scl.compiler.source.ModuleSource;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
public class FileModuleSourceRepository extends AbstractModuleSourceRepository {
private final File path;
package org.simantics.scl.compiler.source.repository;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectProcedure;
-
import org.simantics.scl.compiler.module.Module;
import org.simantics.scl.compiler.module.repository.UpdateListener;
import org.simantics.scl.compiler.source.ModuleSource;
import org.simantics.scl.compiler.source.PrecompiledModuleSource;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+
/**
* An implementation of {@link ModuleSourceRepository} as a finite map.
* This implementation does not support listening module changes,
package org.simantics.scl.compiler.source.repository;
-import gnu.trove.procedure.TObjectProcedure;
-
import org.simantics.scl.compiler.module.repository.ModuleRepository;
import org.simantics.scl.compiler.module.repository.UpdateListener;
import org.simantics.scl.compiler.source.ModuleSource;
+import gnu.trove.procedure.TObjectProcedure;
+
/**
* An interface for locating modules descriptors and listening if they change.
* An instance of this interface is used to create a {@link ModuleRepository}.
package org.simantics.scl.compiler.top;
-import gnu.trove.set.hash.THashSet;
-
import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.simantics.scl.runtime.function.FunctionImpl1;
import org.simantics.scl.runtime.tuple.Tuple0;
+import gnu.trove.set.hash.THashSet;
+
public class ExpressionEvaluator {
public static final boolean TRACE_INTERPRETATION_VS_COMPILATION = false;
package org.simantics.scl.compiler.top;
-import gnu.trove.impl.Constants;
-import gnu.trove.map.hash.TObjectIntHashMap;
-
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
public class ExpressionInterpretationContext {
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;
+
}
--- /dev/null
+package org.simantics.scl.compiler.types;
+
+import org.simantics.scl.compiler.environment.Environment;
+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.Kinds;
+
+import gnu.trove.map.hash.THashMap;
+
+public class Skeletons {
+
+ public static Type canonicalSkeleton(Type type) {
+ while(type instanceof TMetaVar) {
+ TMetaVar metaVar = (TMetaVar)type;
+ if(metaVar.ref != null)
+ type = metaVar.ref;
+ else if(metaVar.skeletonRef != null)
+ type = metaVar.skeletonRef;
+ else
+ return metaVar;
+ }
+ return type;
+ }
+
+ public static Type canonicalSkeleton(THashMap<TMetaVar,Type> unifications, Type type) {
+ while(type instanceof TMetaVar) {
+ TMetaVar metaVar = (TMetaVar)type;
+ if(metaVar.ref != null)
+ type = metaVar.ref;
+ else if(metaVar.skeletonRef != null)
+ type = metaVar.skeletonRef;
+ else {
+ Type temp = unifications.get(metaVar);
+ if(temp == null)
+ return metaVar;
+ else
+ type = temp;
+ }
+ }
+ return type;
+ }
+
+ public static boolean doesSkeletonContain(THashMap<TMetaVar,Type> unifications, Type type, TMetaVar metaVar) {
+ type = canonicalSkeleton(unifications, type);
+ if(type == metaVar)
+ return true;
+ if(type instanceof TFun) {
+ TFun fun = (TFun)type;
+ return doesSkeletonContain(unifications, fun.domain, metaVar)
+ || doesSkeletonContain(unifications, fun.range, metaVar);
+ }
+ if(type instanceof TApply) {
+ TApply apply = (TApply)type;
+ return doesSkeletonContain(unifications, apply.function, metaVar)
+ || doesSkeletonContain(unifications, apply.parameter, metaVar);
+ }
+ if(type instanceof TForAll) {
+ TForAll forAll = (TForAll)type;
+ return doesSkeletonContain(unifications, forAll.type, metaVar);
+ }
+ if(type instanceof TPred) {
+ TPred pred = (TPred)type;
+ for(Type param : pred.parameters)
+ if(doesSkeletonContain(unifications, param, metaVar))
+ return true;
+ return false;
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Returns true, if unification of the skeletons of the types would succeed.
+ */
+ public static boolean areSkeletonsCompatible(THashMap<TMetaVar,Type> unifications, Type a, Type b) {
+ a = canonicalSkeleton(unifications, a);
+ b = canonicalSkeleton(unifications, b);
+ if(a == b)
+ return true;
+ Class<?> ca = a.getClass();
+ Class<?> cb = b.getClass();
+
+ if(ca == TMetaVar.class) {
+ TMetaVar ma = (TMetaVar)a;
+ if(doesSkeletonContain(unifications, b, ma))
+ return false;
+ unifications.put(ma, b);
+ return true;
+ }
+ if(cb == TMetaVar.class) {
+ TMetaVar mb = (TMetaVar)b;
+ if(doesSkeletonContain(unifications, a, mb))
+ return false;
+ unifications.put(mb, a);
+ return true;
+ }
+ if(ca != cb)
+ return false;
+ if(ca == TFun.class) {
+ TFun funA = (TFun)a;
+ TFun funB = (TFun)b;
+ return areSkeletonsCompatible(unifications, funA.domain, funB.domain)
+ && areSkeletonsCompatible(unifications, funA.range, funB.range);
+ }
+ if(ca == TApply.class) {
+ TApply applyA = (TApply)a;
+ TApply applyB = (TApply)b;
+ return areSkeletonsCompatible(unifications, applyA.function, applyB.function)
+ && areSkeletonsCompatible(unifications, applyA.parameter, applyB.parameter);
+ }
+ if(ca == TPred.class) {
+ TPred predA = (TPred)a;
+ TPred predB = (TPred)b;
+ if(predA.typeClass != predB.typeClass)
+ return false;
+ for(int i=0;i<predA.parameters.length;++i)
+ if(!areSkeletonsCompatible(unifications, predA.parameters[i], predB.parameters[i]))
+ return false;
+ return true;
+ }
+ if(ca == TForAll.class) {
+ TForAll forAllA = (TForAll)a;
+ TForAll forAllB = (TForAll)b;
+ TVar temp = Types.var(forAllA.var.getKind());
+ return areSkeletonsCompatible(unifications,
+ forAllA.type.replace(forAllA.var, temp),
+ forAllB.type.replace(forAllB.var, temp));
+ }
+ return false;
+ }
+
+ public static void unifySkeletons(Type a, Type b) throws UnificationException {
+ a = canonicalSkeleton(a);
+ b = canonicalSkeleton(b);
+
+ if(a == b)
+ return;
+ if(a instanceof TMetaVar) {
+ ((TMetaVar) a).setSkeletonRef(b);
+ return;
+ }
+ if(b instanceof TMetaVar) {
+ ((TMetaVar) b).setSkeletonRef(a);
+ return;
+ }
+
+ Class<?> ca = a.getClass();
+ Class<?> cb = b.getClass();
+ if(ca != cb) {
+ throw new UnificationException(a, b);
+ }
+ if(ca == TApply.class)
+ //unifySkeletons((TApply)a, (TApply)b);
+ Types.unify(a, b);
+ else if(ca == TFun.class)
+ unifySkeletons((TFun)a, (TFun)b);
+ else if(ca == TForAll.class)
+ unifySkeletons((TForAll)a, (TForAll)b);
+ else if(ca == TPred.class)
+ //unifySkeletons((TPred)a, (TPred)b);
+ Types.unify(a, b);
+ else if(ca == TUnion.class)
+ unifySkeletons((TUnion)a, (TUnion)b);
+ else // ca == TCon.class || ca = TVar.class
+ throw new UnificationException(a, b);
+ }
+
+ public static void unifySkeletons(TFun a, TFun b) throws UnificationException {
+ unifySkeletons(a.domain, b.domain);
+ unifySkeletons(a.range, b.range);
+ }
+
+ public static void unifySkeletons(TApply a, TApply b) throws UnificationException {
+ unifySkeletons(a.function, b.function);
+ unifySkeletons(a.parameter, b.parameter);
+ }
+
+ public static void unifySkeletons(TForAll a, TForAll b) throws UnificationException {
+ try {
+ Kinds.unify(a.var.getKind(), b.var.getKind());
+ } catch (KindUnificationException e) {
+ throw new UnificationException(a, b);
+ }
+ TVar newVar = Types.var(a.var.getKind());
+ unifySkeletons(a.type.replace(a.var, newVar), b.type.replace(b.var, newVar));
+ }
+
+ public static void unifySkeletons(TPred a, TPred b) throws UnificationException {
+ if(a.typeClass != b.typeClass
+ || a.parameters.length != b.parameters.length)
+ throw new UnificationException(a, b);
+ for(int i=0;i<a.parameters.length;++i)
+ unifySkeletons(a.parameters[i], b.parameters[i]);
+ }
+
+ public static void unifySkeletons(TUnion a, TUnion b) throws UnificationException {
+ // Nothing to do
+ }
+
+ public static Type commonSkeleton(Environment context, Type[] types) {
+ THashMap<Type[], TMetaVar> metaVarMap = new THashMap<Type[], TMetaVar>() {
+ @Override
+ protected boolean equals(Object a, Object b) {
+ return Types.equals((Type[])a, (Type[])b);
+ }
+ @Override
+ protected int hash(Object a) {
+ Type[] types = (Type[])a;
+ int hash = HashCodeUtils.SEED;
+ for(Type type : types)
+ hash = type.hashCode(hash);
+ return hash;
+ }
+ };
+ return commonSkeleton(context, metaVarMap, types);
+ }
+
+ private static TMetaVar metaVarFor(Environment context, THashMap<Type[], TMetaVar> metaVarMap, Type[] types) {
+ TMetaVar result = metaVarMap.get(types);
+ if(result == null) {
+ try {
+ result = Types.metaVar(types[0].inferKind(context));
+ } catch (KindUnificationException e) {
+ result = Types.metaVar(Kinds.STAR);
+ }
+ metaVarMap.put(types, result);
+ }
+ return result;
+ }
+
+ /**
+ * Finds the most specific type that can be unified with the all the types
+ * given as a parameter.
+ */
+ private static Type commonSkeleton(Environment context, THashMap<Type[], TMetaVar> metaVarMap, Type[] types) {
+ for(int i=0;i<types.length;++i)
+ types[i] = canonicalSkeleton(types[i]);
+
+ Type first = types[0];
+ Class<?> clazz = first.getClass();
+ for(int i=1;i<types.length;++i)
+ if(types[i].getClass() != clazz)
+ return metaVarFor(context, metaVarMap, types);
+
+ if(clazz == TCon.class) {
+ for(int i=1;i<types.length;++i)
+ if(types[i] != first)
+ return metaVarFor(context, metaVarMap, types);
+ return first;
+ }
+ else if(clazz == TApply.class) {
+ Type[] functions = new Type[types.length];
+ Type[] parameters = new Type[types.length];
+ for(int i=0;i<types.length;++i) {
+ TApply apply = (TApply)types[i];
+ functions[i] = apply.function;
+ parameters[i] = apply.parameter;
+ }
+ return Types.apply(
+ commonSkeleton(context, metaVarMap, functions),
+ commonSkeleton(context, metaVarMap, parameters));
+ }
+ else if(clazz == TFun.class) {
+ Type[] domains = new Type[types.length];
+ Type[] effects = new Type[types.length];
+ Type[] ranges = new Type[types.length];
+ for(int i=0;i<types.length;++i) {
+ TFun fun = (TFun)types[i];
+ if(fun.domain instanceof TPred)
+ return metaVarFor(context, metaVarMap, types);
+ domains[i] = fun.domain;
+ effects[i] = fun.effect;
+ ranges[i] = fun.range;
+ }
+ return Types.functionE(
+ commonSkeleton(context, metaVarMap, domains),
+ commonEffect(effects),
+ commonSkeleton(context, metaVarMap, ranges));
+ }
+ else
+ return metaVarFor(context, metaVarMap, types);
+ }
+
+ private static Type commonEffect(Type[] effects) {
+ Type first = effects[0];
+ for(int i=1;i<effects.length;++i)
+ if(!Types.equals(first, effects[i]))
+ return Types.metaVar(Kinds.EFFECT);
+ return first;
+ }
+}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import java.util.List;
import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TApplyAst;
import org.simantics.scl.compiler.internal.types.ast.TListAst;
import org.simantics.scl.compiler.types.util.TMultiApply;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
/**
* @author Hannu Niemistö
*/
public class TApply extends Type {
- public final Type function;
- public final Type parameter;
+ public Type function;
+ public Type parameter;
public TApply(Type function, Type parameter) {
if(NULL_CHECKS) {
Kind parameterKind = parameter.inferKind(context);
Kinds.unify(functionKind, Kinds.arrow(parameterKind, requiredKind));
}
+
+ @Override
+ public Kind getKind(Environment context) {
+ Kind functionKind = function.getKind(context);
+ return Kinds.rangeOfArrow(functionKind);
+ }
@Override
public boolean containsMetaVars() {
else
return new TApply(newFunction, newParameter);
}
+
+ @Override
+ public int hashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
+ hash = function.hashCode(hash);
+ hash = parameter.hashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
+ hash = function.hashCode(hash, boundVars);
+ hash = parameter.hashCode(hash, boundVars);
+ return hash;
+ }
+
+ public Type getCanonicalFunction() {
+ if(function instanceof TMetaVar)
+ function = function.canonical();
+ return function;
+ }
+
+ public Type getCanonicalParameter() {
+ if(parameter instanceof TMetaVar)
+ parameter = parameter.canonical();
+ return parameter;
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ if(this == other)
+ return true;
+ if(!other.getClass().equals(TApply.class))
+ return false;
+ TApply apply = (TApply)other;
+ return getCanonicalFunction().equalsCanonical(apply.getCanonicalFunction())
+ && getCanonicalParameter().equalsCanonical(apply.getCanonicalParameter());
+ }
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.internal.codegen.utils.NameMangling;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TConAst;
import org.simantics.scl.compiler.internal.types.ast.TypeAst;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
/**
* This class represents an SCL type constant with a name given in a module.
*/
-public class TCon extends Type {
+public final class TCon extends Type {
public final String module;
public final String name;
public Kind inferKind(Environment context) throws KindUnificationException {
return context.getTypeConstructor(this).kind;
}
+
+ public Kind getKind(Environment context) {
+ return context.getTypeConstructor(this).kind;
+ }
@Override
public boolean containsMetaVars() {
public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
return this;
}
+
+ @Override
+ public int hashCode(int hash) {
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ return this == other;
+ }
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
+import java.util.Arrays;
import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TForAllAst;
import org.simantics.scl.compiler.internal.types.ast.TypeAst;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+
public class TForAll extends Type {
public final TVar var;
- public final Type type;
+ public Type type;
TForAll(TVar var, Type type) {
if(NULL_CHECKS) {
// Should never get here
return new TMetaVar(Kinds.STAR);
}
+
+ @Override
+ public int hashCode(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.hashCode(hash, boundVars);
+ }
+
+ @Override
+ public int hashCode(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.hashCode(hash, boundVars);
+ }
+
+ public Type getCanonicalType() {
+ if(type instanceof TMetaVar)
+ type = type.canonical();
+ return type;
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ if(this == other)
+ return true;
+ if(!other.getClass().equals(TForAll.class))
+ return false;
+ TForAll forAll = (TForAll)other;
+ return getCanonicalType().equalsCanonical(forAll.getCanonicalType().replace(forAll.var, var));
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return Kinds.STAR;
+ }
+
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TEffectAst;
import org.simantics.scl.compiler.internal.types.ast.TFunctionAst;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
public class TFun extends Type {
- public final Type domain;
- public final Type effect;
- public final Type range;
+ public Type domain;
+ public Type effect;
+ public Type range;
TFun(Type domain, Type effect, Type range) {
if(domain == null)
Type newRange = range.copySkeleton(metaVarMap);
return new TFun(newDomain, newEffect, newRange);
}
+
+ @Override
+ public int hashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.hashCode(hash);
+ hash = effect.hashCode(hash);
+ hash = range.hashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.hashCode(hash, boundVars);
+ hash = effect.hashCode(hash, boundVars);
+ hash = range.hashCode(hash, boundVars);
+ return hash;
+ }
+
+ public Type getCanonicalDomain() {
+ if(domain instanceof TMetaVar)
+ domain = domain.canonical();
+ return domain;
+ }
+
+ public Type getCanonicalEffect() {
+ if(effect instanceof TMetaVar)
+ effect = effect.canonical();
+ return effect;
+ }
+
+ public Type getCanonicalRange() {
+ if(range instanceof TMetaVar)
+ range = range.canonical();
+ return range;
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ if(this == other)
+ return true;
+ if(!other.getClass().equals(TFun.class))
+ return false;
+ TFun fun = (TFun)other;
+ return getCanonicalDomain().equalsCanonical(fun.getCanonicalDomain())
+ && getCanonicalEffect().equalsCanonical(fun.getCanonicalEffect())
+ && getCanonicalRange().equalsCanonical(fun.getCanonicalRange());
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return Kinds.STAR;
+ }
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TVarAst;
import org.simantics.scl.compiler.internal.types.ast.TypeAst;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
/**
*/
public class TMetaVar extends Type {
public static final TMetaVar[] EMPTY_ARRAY = new TMetaVar[0];
+ public static final boolean DEBUG = false;
Type ref = null;
+ Type skeletonRef = null;
Polarity polarity = Polarity.NO_POLARITY;
private Kind kind;
+ private TMetaVarListener listener;
+
+ public static abstract class TMetaVarListener {
+ private Object prev; // TMetaVarListener or TMetaVar
+ private TMetaVarListener next;
+
+ public abstract void notifyAboutChange();
+
+ public void remove() {
+ if(prev == null)
+ return; // Not added or not anymore listening TMetaVar
+ if(prev instanceof TMetaVar)
+ ((TMetaVar)prev).listener = next;
+ else
+ ((TMetaVarListener)prev).next = next;
+ if(next != null) {
+ next.prev = prev;
+ next = null;
+ }
+ prev = null;
+ }
+ }
TMetaVar(Kind kind) {
this.kind = kind;
ref.collectEffectMetaVars(vars);
}
- public void setRef(Type a) throws UnificationException {
- a = Types.weakCanonical(a);
- if(a.contains(this))
- throw new UnificationException(this, a);
- ref = a;
+ public void setRef(Type type) throws UnificationException {
+ if(DEBUG)
+ System.out.println("setRef " + System.identityHashCode(this) + " -> " + type);
+ if(ref != null)
+ throw new InternalCompilerError("Method setRef should be called only for unbound meta variables.");
+ if(type.contains(this))
+ throw new UnificationException(this, type);
+ ref = type;
if(polarity != Polarity.NO_POLARITY)
- a.addPolarity(polarity);
+ type.addPolarity(polarity);
+ if(skeletonRef != null) {
+ Type skeleton = skeletonRef;
+ skeletonRef = null;
+ Skeletons.unifySkeletons(skeleton, type);
+ }
+ fireNotifyAboutChange();
}
public Type getRef() {
@Override
public boolean contains(TMetaVar other) {
- if(ref == null)
- return this == other;
- else
+ if(ref != null)
return ref.contains(other);
+ else if(skeletonRef != null)
+ return skeletonRef.contains(other);
+ else
+ return this == other;
}
@Override
return result;
}
}
+
+ public void setSkeletonRef(Type type) throws UnificationException {
+ if(DEBUG)
+ System.out.println("setSkeletonRef " + System.identityHashCode(this) + " -> " + type);
+ if(ref != null || skeletonRef != null)
+ throw new InternalCompilerError("Method setRef should be called only for unbound meta variables.");
+ if(type.contains(this))
+ throw new UnificationException(this, type);
+ this.skeletonRef = type;
+ fireNotifyAboutChange();
+ }
+
+ @Override
+ public int hashCode(int hash) {
+ if(ref == null)
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ else
+ return ref.hashCode(hash);
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ if(ref == null)
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ else
+ return ref.hashCode(hash, boundVars);
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ return this == other;
+ }
+
+ @Override
+ public Type canonical() {
+ if(ref == null)
+ return this;
+ else
+ return ref = ref.canonical();
+ }
+
+ public void addListener(TMetaVarListener newListener) {
+ if(DEBUG)
+ System.out.println("addListener " + System.identityHashCode(this));
+ newListener.next = listener;
+ newListener.prev = this;
+ if(listener != null)
+ listener.prev = newListener;
+ listener = newListener;
+ }
+
+ private void fireNotifyAboutChange() {
+ if(DEBUG)
+ System.out.println("fireNotifyAboutChange " + System.identityHashCode(this) + " " + ref);
+ TMetaVarListener cur = listener;
+ listener = null;
+ while(cur != null) {
+ if(DEBUG)
+ System.out.println(" call listener");
+ cur.prev = null; // This prevents TMetaVarListener.remove from doing anything
+ cur.notifyAboutChange();
+ TMetaVarListener next = cur.next;
+ cur.next = null;
+ cur = next;
+ }
+ }
+
+ public TMetaVarListener getLatestListener() {
+ return listener;
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return kind;
+ }
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TApplyAst;
import org.simantics.scl.compiler.internal.types.ast.TypeAst;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
public class TPred extends Type {
newParameters[i] = parameters[i].copySkeleton(metaVarMap);
return new TPred(typeClass, parameters);
}
+
+ @Override
+ public int hashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, PRED_HASH);
+ hash = typeClass.hashCode(hash);
+ for(Type parameter : parameters)
+ hash = parameter.hashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, PRED_HASH);
+ hash = typeClass.hashCode(hash, boundVars);
+ for(Type parameter : parameters)
+ hash = parameter.hashCode(hash, boundVars);
+ return hash;
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ if(this == other)
+ return true;
+ if(!other.getClass().equals(TPred.class))
+ return false;
+ TPred pred = (TPred)other;
+ if(typeClass != pred.typeClass || parameters.length != pred.parameters.length)
+ return false;
+ for(int i=0;i<parameters.length;++i)
+ if(!Types.canonical(parameters[i]).equalsCanonical(Types.canonical(pred.parameters[i])))
+ return false;
+ return true;
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return Kinds.STAR;
+ }
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TConAst;
import org.simantics.scl.compiler.internal.types.ast.TypeAst;
+import org.simantics.scl.compiler.types.kinds.Kind;
+import org.simantics.scl.compiler.types.kinds.Kinds;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
public class TUnion extends Type {
public final Type[] effects;
public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
return Types.NO_EFFECTS;
}
+
+ @Override
+ public int hashCode(int hash) {
+ int sum = UNION_HASH;
+ for(Type effect : effects)
+ sum += effect.hashCode(HashCodeUtils.SEED);
+ return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ int sum = UNION_HASH;
+ for(Type effect : effects)
+ sum += effect.hashCode(HashCodeUtils.SEED, boundVars);
+ return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ if(this == other)
+ return true;
+ if(!other.getClass().equals(TUnion.class))
+ return false;
+ TUnion union = (TUnion)other;
+ int length = effects.length;
+ if(length != union.effects.length)
+ return false;
+ if(length == 0)
+ return true;
+ for(int i=0;i<length;++i) {
+ effects[i] = effects[i].canonical();
+ union.effects[i] = union.effects[i].canonical();
+ }
+ if(length == 2) {
+ if(effects[0].equalsCanonical(union.effects[0]))
+ return effects[1].equalsCanonical(union.effects[1]);
+ else
+ return effects[0].equalsCanonical(union.effects[1]) &&
+ effects[1].equalsCanonical(union.effects[0]);
+ }
+ loop: for(int i=0;i<length;++i) {
+ Type effect = effects[i];
+ for(int j=i;j<length;++j)
+ if(effect.equalsCanonical(union.effects[j])) {
+ if(j > i) {
+ effect = union.effects[i];
+ union.effects[i] = union.effects[j];
+ union.effects[j] = effect;
+ }
+ continue loop;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return Kinds.EFFECT;
+ }
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TVarAst;
import org.simantics.scl.compiler.internal.types.ast.TypeAst;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+
-public class TVar extends Type {
+public final class TVar extends Type {
public static final TVar[] EMPTY_ARRAY = new TVar[0];
private Kind kind;
public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
return this;
}
+
+ @Override
+ public int hashCode(int hash) {
+ return HashCodeUtils.update(hash, System.identityHashCode(this));
+ }
+
+ @Override
+ public int hashCode(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;
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return kind;
+ }
}
package org.simantics.scl.compiler.types;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
-
import java.util.ArrayList;
import java.util.Map;
import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.HashCodeUtils;
import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
import org.simantics.scl.compiler.internal.types.ast.TypeAst;
import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
import org.simantics.scl.compiler.types.util.Polarity;
import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
/**
public static final int METAVAR_ID = 5;
public static final int VAR_ID = 6;
public static final int UNION_ID = 7;
- public static final int ALIAS_ID = 8;
+ protected static final int APPLY_HASH = HashCodeUtils.preprocessValue(0);
+ protected static final int FORALL_HASH = HashCodeUtils.preprocessValue(1);
+ protected static final int FUN_HASH = HashCodeUtils.preprocessValue(2);
+ protected static final int PRED_HASH = HashCodeUtils.preprocessValue(3);
+ protected static final int UNION_HASH = HashCodeUtils.preprocessValue(4);
+ protected static final int BOUND_VAR_HASH = HashCodeUtils.preprocessValue(5);
/*
* This class is not meant to be extended outside of this package.
@Override
public int hashCode() {
- TypeHashCodeContext context = new TypeHashCodeContext();
- updateHashCode(context);
- return context.getResult();
+ return hashCode(HashCodeUtils.SEED);
}
public abstract void updateHashCode(TypeHashCodeContext context);
+ public abstract int hashCode(int hash);
+ public abstract int hashCode(int hash, TVar[] boundVars);
public abstract void collectFreeVars(ArrayList<TVar> vars);
* Creates an independent copy of the type, but replaces all effects by metavars
*/
public abstract Type copySkeleton(THashMap<TMetaVar,TMetaVar> metaVarMap);
+
+ public abstract boolean equalsCanonical(Type other);
+
+ public Type canonical() {
+ return this;
+ }
+
+ public abstract Kind getKind(Environment context);
}
\ No newline at end of file
function = apply(function, parameter);
return function;
}
-
- /**
- * Get the concrete type or alias type pointed to by a chain of type meta-variables,
- * or the last metavariable in the link, if it is not linked to an actual type.
- * Unlike {@link #canonical(Type)}, this method does not resolve type aliases.
- */
- public static Type weakCanonical(Type type) {
- while(true) {
- if(type instanceof TMetaVar) {
- TMetaVar metaVar = (TMetaVar)type;
- if(metaVar.ref == null)
- return type;
- else
- type = metaVar.ref;
- }
- else
- return type;
- }
- }
/**
- * Get the concrete type pointed to by a chain of type meta-variables. Unlike {@link #weakCanonical(Type)}
- * this method also resolves type aliases.
+ * Get the concrete type pointed to by a chain of type meta-variables.
*/
public static Type canonical(Type type) {
while(type instanceof TMetaVar) {
}
public static void unify(Type a, Type b) throws UnificationException {
- a = weakCanonical(a);
- b = weakCanonical(b);
+ a = canonical(a);
+ b = canonical(b);
if(a == b)
return;
if(a instanceof TMetaVar) {
e.getMessage()));
}
}
+
+ public static Type instantiateAndStrip(Type type) {
+ while(true) {
+ if(type instanceof TForAll) {
+ TForAll forAll = (TForAll)type;
+ type = forAll.type.replace(forAll.var, metaVar(forAll.var.getKind()));
+ }
+ else if(type instanceof TFun) {
+ TFun fun = (TFun)type;
+ if(fun.domain instanceof TPred || fun.domain == Types.PUNIT)
+ type = fun.range;
+ else
+ return type;
+ }
+ else if(type instanceof TMetaVar) {
+ TMetaVar metaVar = (TMetaVar)type;
+ if(metaVar.ref == null)
+ return type;
+ else
+ type = metaVar.ref;
+ }
+ else
+ return type;
+ }
+ }
+
}
package org.simantics.scl.compiler.types.kinds;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
public class Kinds {
public static boolean equals(Kind a, Kind b) {
return equalsCanonical(canonical(a), canonical(b));
+ }
+
+ public static Kind rangeOfArrow(Kind kind) {
+ kind = canonical(kind);
+ if(kind instanceof KArrow)
+ return ((KArrow)kind).range;
+ else if(kind instanceof KMetaVar) {
+ Kind domain = Kinds.metaVar();
+ Kind range = Kinds.metaVar();
+ try {
+ ((KMetaVar)kind).setRef(arrow(domain, range));
+ } catch (KindUnificationException e) {
+ // Should not fail because kind is canonical
+ e.printStackTrace();
+ }
+ return range;
+ }
+ else
+ throw new InternalCompilerError("Assumed arrow kind but encountered " + kind + ".");
}
}
--- /dev/null
+package org.simantics.scl.compiler.types.util;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.types.Skeletons;
+import org.simantics.scl.compiler.types.TApply;
+import org.simantics.scl.compiler.types.TForAll;
+import org.simantics.scl.compiler.types.TFun;
+import org.simantics.scl.compiler.types.TMetaVar;
+import org.simantics.scl.compiler.types.TMetaVar.TMetaVarListener;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.Type;
+
+public abstract class TypeListener {
+ private ArrayList<TMetaVarListener> metaVarListeners = new ArrayList<TMetaVarListener>(2);
+ public abstract void notifyAboutChange();
+
+ private static class SubListener extends TMetaVarListener {
+ private final TypeListener parent;
+ public SubListener(TypeListener parent) {
+ this.parent = parent;
+ } @Override
+ public void notifyAboutChange() {
+ for(TMetaVarListener otherListeners : parent.metaVarListeners)
+ otherListeners.remove();
+ parent.notifyAboutChange();
+ }
+ };
+
+ public void listenSkeleton(Type type) {
+ type = Skeletons.canonicalSkeleton(type);
+ if(type instanceof TMetaVar) {
+ TMetaVar metaVar = (TMetaVar)type;
+ TMetaVarListener latestListener = metaVar.getLatestListener();
+ if(latestListener instanceof SubListener &&
+ ((SubListener)latestListener).parent == this)
+ return;
+
+ SubListener subListener = new SubListener(this);
+ metaVarListeners.add(subListener);
+ metaVar.addListener(subListener);
+ }
+ else if(type instanceof TApply) {
+ TApply apply = (TApply)type;
+ listenSkeleton(apply.function);
+ listenSkeleton(apply.parameter);
+ }
+ else if(type instanceof TFun) {
+ TFun fun = (TFun)type;
+ listenSkeleton(fun.domain);
+ listenSkeleton(fun.range);
+ }
+ else if(type instanceof TForAll) {
+ TForAll forAll = (TForAll)type;
+ listenSkeleton(forAll.type);
+ }
+ else if(type instanceof TPred) {
+ TPred pred = (TPred)type;
+ for(Type parameter : pred.parameters)
+ listenSkeleton(parameter);
+ }
+ }
+}
--- /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.TMetaVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+\r
+public class TypeTree<T> {\r
+ \r
+ public static class Case<T> {\r
+ public Type[] types;\r
+ public T result;\r
+ }\r
+ \r
+ private static class Node<T> {\r
+ Case<T>[] cases;\r
+ Branch<T>[] branches;\r
+\r
+ public Node(Case<T>[] cases) {\r
+ this.cases = cases;\r
+ this.branches = new Branch[cases[0].types.length];\r
+ }\r
+ \r
+ Branch<T> getBranch(int i) {\r
+ // TODO\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ private static class Branch<T> {\r
+\r
+ public void improve(Iterator<T> iterator) {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ public static class Iterator<T> {\r
+ Node<T> node;\r
+ Type[] scrutinee;\r
+ \r
+ public Iterator(Node<T> node, Type[] scrutinee) {\r
+ this.node = node;\r
+ this.scrutinee = scrutinee;\r
+ }\r
+ \r
+ public void improve() {\r
+ for(int i=0;i<scrutinee.length;++i) {\r
+ Type type = scrutinee[i] = Skeletons.canonicalSkeleton(scrutinee[i]);\r
+ if(!(type instanceof TMetaVar)) {\r
+ Branch<T> branch = node.getBranch(i);\r
+ if(branch != null) {\r
+ branch.improve(this);\r
+ --i;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ Node<T> root;\r
+ \r
+ public TypeTree(Case<T>[] cases) {\r
+ this.root = new Node<T>(cases);\r
+ }\r
+ \r
+ public Iterator<T> iterator(Type ... scrutinee) {\r
+ return new Iterator<T>(root, scrutinee);\r
+ }\r
+}\r
public ActiveTests() { super("scl"); }
@Test public void Equations1() { test(); }
- @Test public void Equality() { test(); }
- @Test public void ModuleInitialization() { test(); }
-
- @Test public void ImportJavaConstructor() { test(); }
- @Test public void MarketModel() { test(); }
@Test public void MarketModel2() { test(); }
- @Ignore
+ @Test public void Overloading2() { test(); }
+ @Test public void Overloading3() { test(); }
+ //@Ignore
@Test public void PatternError() { test(); }
- @Test public void TypeAliasRefsToTypeAlias() { test(); }
+ @Test public void Serialization() { test(); }
@Ignore
@Test public void TypeClass2() { test(); }
@Test public void TypeClassBug2() { 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.Test;
-
-public class FutureTests extends TestBase {
-
- public FutureTests() { super("scl"); }
-
- @Test public void BigInstances() { test(); }
- @Test public void Matching3() { test(); }
- @Test public void Seq() { test(); }
-
-}
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 RegressionTestsWithoutPrelude extends TestBase {
-
- public RegressionTestsWithoutPrelude() { super("scl"); }
+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 Effects6() { test(); }
@Test(expected=ValueNotFound.class)
public void EmptyModule() throws ValueNotFound {
- test("EmptyModule", "");
+ 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 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 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 Matching5() { 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 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 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.codeSize);
+ printCoverageTree(bp.children, ind+1);
+ }
+ }
+
}
@RunWith(Suite.class)
@SuiteClasses({
- RegressionTestsWithoutPrelude.class,
- RegressionTestsWithPrelude.class,
+ ModuleRegressionTests.class,
TestExpressionEvaluator.class,
TestCommandSession.class
})
+++ /dev/null
-package org.simantics.scl.compiler.tests;
-
-import org.junit.Test;
-
-public class RegressionTestsWithPrelude extends TestBase {
-
- public RegressionTestsWithPrelude() { super("scl"); }
-
- @Test public void BigContext() { test(); }
- @Test public void BigFunction() { test(); }
- @Test public void BinaryOperators1() { test(); }
- @Test public void Bug4450() { test(); }
- @Test public void Character1() { test(); }
- @Test public void Collaz() { test(); }
- @Test public void Deriving1() { test(); }
- @Test public void Deriving3() { test(); }
- @Test public void Deriving4() { test(); }
- @Test public void Div() { test(); }
- @Test public void DoubleConversion() { test(); }
- @Test public void ExpressionParsing() { test(); }
- @Test public void Fibonacci2() { test(); }
- @Test public void FoldlBuild1() { test(); }
- @Test public void FoldlBuild2() { test(); }
- @Test public void FoldMissingInitialValue() { 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 FunctorM1() { test(); }
- @Test public void GenericMutualRecursion() { test(); }
- @Test public void GlobalVariables() { test(); }
- @Test public void Guards1() { test(); }
- @Test public void Guards2() { test(); }
- @Test public void Hashable1() { test(); }
- @Test public void Hashable2() { test(); }
- @Test public void Index() { test(); }
- @Test public void InstanceHierarchy() { test(); }
- @Test public void InvalidModule() { test(); }
- @Test public void Layout1() { test(); }
- @Test public void ListSyntax() { 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 ListSyntax10() { test(); }
- @Test public void ListSyntax11() { test(); }
- @Test public void ListSyntax12() { test(); }
- @Test public void LocalDefinitions5() { test(); }
- @Test public void Matching4() { test(); }
- @Test public void MaximumBy() { test(); }
- @Test public void Maybe4() { test(); }
- @Test public void MissingEffect() { test(); }
- @Test public void Monads1() { test(); }
- @Test public void MonadSyntax1() { test(); }
- @Test public void NonexistentTypeClassInAnnotation() { test(); }
- @Test public void OverloadedLiterals2() { test(); }
- @Test public void Parsing() { test(); }
- @Test public void Polynomials() { test(); }
- @Test public void Proc1() { test(); }
- @Test public void Proc2() { test(); }
- @Test public void Proc3() { test(); }
- @Test public void Random1() { test(); }
- @Test public void RangeSyntax() { test(); }
- @Test public void Record1() { test(); }
- @Test public void RedBlackTrees() { test(); }
- @Test public void Relations1() { test(); }
- @Test public void Relations2() { 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 Serialization() { test(); }
- @Test public void Serialization2() { test(); }
- @Test public void Serialization3() { test(); }
- @Test public void Show1() { test(); }
- @Test public void SinConst1() { test(); }
- @Test public void Sort() { test(); }
- @Test public void SSATypingBug() { test(); }
- @Test public void StringInterpolation1() { 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(timeout=1000L) public void TypeInferenceBug2() { test(); }
- @Test public void TypeOf1() { test(); }
- @Test public void UnaryMinus() { test(); }
- @Test public void Unification1() { test(); }
- @Test public void ValueConversion() { test(); }
- @Test public void Vector1() { test(); }
- @Test public void Vector2() { test(); }
- @Test public void While2() { test(); }
- @Test public void While3() { test(); }
-
-}
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.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;
SourceRepositories.BUILTIN_SOURCE_REPOSITORY,
SourceRepositories.PRELUDE_SOURCE_REPOSITORY
));
- private static final Pattern TEST_SEPARATOR = Pattern.compile("^-- *$", Pattern.MULTILINE);
+ private static final Pattern TEST_SEPARATOR = Pattern.compile("^--+ *$", Pattern.MULTILINE);
private static final Charset UTF8 = Charset.forName("UTF-8");
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);
- for(int i=0;i<testParts.length;i+=2) {
- String input = testParts[i];
- String expectedOutput = testParts[i+1];
- String actualOutput = test(testModuleName, input);
+
+ 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));
return text.trim().replace("\r\n", "\n");
}
- protected String test(String testModuleName, String input) throws ValueNotFound {
+ 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(new StringModuleSource(
- testModuleName, getClass().getClassLoader(), input) {
- @Override
- protected ImportDeclaration[] getBuiltinImports(UpdateListener listener) {
- return ImportDeclaration.ONLY_BUILTINS;
- }
- }
- ));
- Failable<Module> result = testEnvironment.getModule(testModuleName);
+ new MapModuleSourceRepository(moduleSources));
+ int lastId = moduleNames.length-1;
+ Failable<Module> result = testEnvironment.getModule(moduleNames[lastId]);
if(!result.didSucceed())
- return ((Failure)result).toString(input);
+ return ((Failure)result).toString(moduleTexts[lastId]);
else {
- Object main = testEnvironment.getRuntimeModule(testModuleName).getResult().getValue("main");
+ Object main = testEnvironment.getRuntimeModule(moduleNames[lastId]).getResult().getValue("main");
return String.valueOf(main);
}
}
}
String text = new String(buffer, 0, pos, UTF8);
String[] result = TEST_SEPARATOR.split(text);
- if(result.length % 2 == 1) {
- result = Arrays.copyOf(result, result.length+2);
- result[result.length-1] = "";
+ 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 {
package org.simantics.scl.compiler.tests;\r
\r
-import junit.framework.Assert;\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.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 java.util.Arrays;
-import junit.framework.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;
Assert.assertEquals(sum, result);
}
}
-
- @Test
- public void testSeq() throws Exception {
- String expressionText = "Sequences.runSequence mdo\n" +
- " repeatForever mdo\n" +
- " Sequences.wait 2\n" +
- " Sequences.stop";
-
- try {
- Object result = new ExpressionEvaluator(runtimeEnvironment, expressionText)
- .parseAsBlock(true)
- .eval();
- } catch(SCLExpressionCompilationException e) {
- System.out.println(CompilationErrorFormatter.toString(expressionText, e.getErrors()));
- throw e;
- }
- }
}
--- /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());
+
+ }
+}
public UnimplementedTests() { super("scl"); }
+ @Test public void BigInstances() { test(); }
@Test public void BlankExpression() { test(); }
@Test public void ClashingValueDefinition() { test(); }
@Test public void FunctionalDependencies1() { test(); }
+++ /dev/null
-import "Prelude"\r
-\r
-data Vec2 = Vec2 Double Double\r
-\r
-deriving instance Eq Vec2\r
-\r
-main = Vec2 1 1 == Vec2 1 1\r
---\r
-true
\ 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"
+
+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
-l :: [Integer]\r
-l = [1,2,3,4,5]\r
-main = hash l - foldl (\c x -> 31*c + x) 0 l\r
---\r
--1625180697
\ No newline at end of file
+++ /dev/null
-import "Prelude"\r
-\r
-l :: [Double]\r
-l = [1,2,3,4,5]\r
-main = hash l\r
---\r
-849277455
\ 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, 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, LBRACKET, LET, LPAREN, MATCH, MDO, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION, WHEN.
--- /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
+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
+// 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"
+
+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 "Prelude"\r
-import "JavaBuiltin" as Java\r
-\r
-class Seq seq el where\r
- myLength :: seq -> Integer\r
- myGet :: seq -> Integer -> el\r
-\r
-instance (b ~ Character) => Seq String b where\r
- myLength = Java.method "length"\r
- myGet = Java.method "charAt"\r
- \r
-instance (b ~ a) => Seq [a] b where\r
- myLength = Java.method "size"\r
- myGet = Java.method "get"\r
-\r
-//main :: (Character, String)\r
-main = (myGet "abc" 1, myGet ["a", "b", "c"] 1)\r
---\r
-(b,b)
\ 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
-a = =\r
-b = 4\r
---\r
-1:5-1:6: Unexpected token '=' (EQUALS). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LBRACKET, LET, LPAREN, MATCH, MDO, MINUS, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION, WHEN.\r
+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
package org.simantics.scl.compiler.tests.unit;\r
\r
-import gnu.trove.set.hash.THashSet;\r
-\r
import java.util.Collection;\r
\r
-import junit.framework.Assert;\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.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
\r
public void checkUpdates() {\r
- System.out.println(url + " checkUpdates");\r
if(digest != null && listeners != null) {\r
byte[] newDigest = computeDigest();\r
if(!Arrays.equals(digest, newDigest)) {\r
\r
@Override\r
public void update(String newSourceText) {\r
- System.out.println(url + " update");\r
try {\r
Path path = getPath();\r
Files.write(path, newSourceText.getBytes(Charset.forName("UTF-8")));\r
try {
CommandSession session = new CommandSession(SCLOsgi.MODULE_REPOSITORY, handler);
new TestScriptExecutor(session, reader, handler).execute();
- } catch(Throwable e) {
- CommandSession.formatException(handler, e);
- throw e;
} finally {
reader.close();
}
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: org.simantics.scl.runtime,
org.simantics.scl.runtime.collection,
- org.simantics.scl.runtime.equations,
+ org.simantics.scl.runtime.exceptions,
org.simantics.scl.runtime.function,
org.simantics.scl.runtime.io,
org.simantics.scl.runtime.lazy,
bin.includes = META-INF/,\\r
.,\\r
scl/,\\r
- schema/,\\r
- plugin.xml
\ No newline at end of file
+ schema/
\ No newline at end of file
package org.simantics.scl.runtime;
-import gnu.trove.map.hash.TCustomHashMap;
-import gnu.trove.set.hash.THashSet;
-import gnu.trove.strategy.HashingStrategy;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import org.simantics.scl.runtime.function.FunctionImpl2;
import org.simantics.scl.runtime.tuple.Tuple2;
+import gnu.trove.map.hash.TCustomHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.strategy.HashingStrategy;
+
@SuppressWarnings({"rawtypes", "unchecked"})
public class Lists {
\r
import gnu.trove.map.hash.THashMap;\r
\r
-import java.util.Map;\r
-\r
public class SCLContext extends THashMap<String,Object> {\r
private static ThreadLocal<SCLContext> CONTEXT = new ThreadLocal<SCLContext>();\r
private static ThreadLocal<OldContextNode> OLD_CONTEXT = new ThreadLocal<OldContextNode>();\r
\r
import java.util.ArrayList;\r
import java.util.Collections;\r
-import java.util.Comparator;\r
import java.util.List;\r
\r
import org.simantics.scl.runtime.SCLContext;\r
--- /dev/null
+package org.simantics.scl.runtime.exceptions;\r
+\r
+public class MatchingException extends RuntimeException {\r
+ private static final long serialVersionUID = -3364111368224089448L;\r
+\r
+ public MatchingException() {\r
+ super();\r
+ }\r
+ \r
+ public MatchingException(String message) {\r
+ super(message);\r
+ }\r
+}\r
package org.simantics.scl.runtime.io;\r
\r
-import gnu.trove.list.array.TByteArrayList;\r
-\r
import java.io.EOFException;\r
import java.io.IOException;\r
import java.io.InputStream;\r
import java.io.OutputStream;\r
import java.nio.charset.Charset;\r
\r
+import gnu.trove.list.array.TByteArrayList;\r
+\r
public class SclIO {\r
\r
private static final Charset UTF8 = Charset.forName("UTF-8");\r
package org.simantics.scl.runtime.minigraph;
-import gnu.trove.impl.Constants;
-import gnu.trove.map.hash.TIntObjectHashMap;
-import gnu.trove.map.hash.TLongObjectHashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.procedure.TIntProcedure;
-import gnu.trove.set.hash.TIntHashSet;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.simantics.scl.runtime.function.Function;
import org.simantics.scl.runtime.tuple.Tuple0;
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.map.hash.TLongObjectHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
public class Minigraph {
private static final int[] EMPTY_INT_ARRAY = new int[0];
package org.simantics.scl.runtime.unification;
-import gnu.trove.map.hash.THashMap;
-
import java.util.Map;
import org.simantics.scl.runtime.function.Function;
import org.simantics.scl.runtime.tuple.Tuple0;
+import gnu.trove.map.hash.THashMap;
+
public class UMapUtils {
public static void put(Map<Object,Object> map, Object key, Object value) {
if(map.containsKey(key))
output.. = bin/\r
bin.includes = META-INF/,\\r
.,\\r
- graphs/*.tg,\\r
graph.tg\r
src.includes = graph/\r
output.. = bin/\r
bin.includes = META-INF/,\\r
.,\\r
- graphs/*.tg,\\r
graph.tg\r
src.includes = graph/\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="src" path="examples"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.threadlog</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+#Fri Oct 30 22:48:46 EET 2009\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Threadlog
+Bundle-SymbolicName: org.simantics.threadlog
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.threadlog.internal.Activator
+Require-Bundle: org.eclipse.core.runtime,
+ gnu.trove2;bundle-version="2.0.0"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Export-Package: org.simantics.threadlog
--- /dev/null
+###############################################################################\r
+# Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+# in Industry THTH ry.\r
+# All rights reserved. This program and the accompanying materials\r
+# are made available under the terms of the Eclipse Public License v1.0\r
+# which accompanies this distribution, and is available at\r
+# http://www.eclipse.org/legal/epl-v10.html\r
+#\r
+# Contributors:\r
+# VTT Technical Research Centre of Finland - initial API and implementation\r
+###############################################################################\r
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog.examples;\r
+\r
+import static org.simantics.threadlog.ThreadLog.BEGIN;\r
+\r
+import org.simantics.threadlog.Task;\r
+import org.simantics.threadlog.ui.ThreadLogController;\r
+\r
+public class Example1 {\r
+\r
+ public static void main(String[] args) throws InterruptedException {\r
+ ThreadLogController.start();\r
+ \r
+ while(true) {\r
+ Thread.sleep(50);\r
+ Task t = BEGIN("Foo");\r
+ Thread.sleep(100);\r
+ t.end();\r
+ } \r
+ }\r
+ \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog;\r
+\r
+public interface Task {\r
+ void end();\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog;\r
+\r
+import gnu.trove.TDoubleArrayList;\r
+import gnu.trove.TLongArrayList;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.BufferedOutputStream;\r
+import java.io.DataInput;\r
+import java.io.DataInputStream;\r
+import java.io.DataOutput;\r
+import java.io.DataOutputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.StreamCorruptedException;\r
+import java.util.ArrayList;\r
+\r
+public class ThreadLog {\r
+\r
+ private static final transient String HDR = "TLOG";\r
+ private static final transient int CURRENT_VERSION = 1;\r
+\r
+ static ThreadLog defaultLog;\r
+\r
+ ArrayList<String> tasks = new ArrayList<String>();\r
+ TDoubleArrayList times = new TDoubleArrayList();\r
+ TLongArrayList threads = new TLongArrayList();\r
+\r
+ public double[] getTimes() {\r
+ return times.toNativeArray();\r
+ }\r
+\r
+ public String[] getTasks() {\r
+ return tasks.toArray(new String[tasks.size()]);\r
+ }\r
+\r
+ public long[] getThreads() {\r
+ return threads.toNativeArray();\r
+ }\r
+\r
+ private class TaskImpl implements Task {\r
+ public String name;\r
+ public long thread;\r
+ public long beginTime;\r
+\r
+ public TaskImpl(String name) {\r
+ this.name = name;\r
+ this.thread = Thread.currentThread().getId();\r
+ this.beginTime = System.nanoTime();\r
+ }\r
+\r
+ @Override\r
+ public void end() {\r
+ long endTime = System.nanoTime();\r
+ synchronized(tasks) {\r
+ tasks.add(name);\r
+ times.add(beginTime*1e-9);\r
+ times.add(endTime*1e-9);\r
+ threads.add(thread);\r
+ }\r
+ }\r
+ }\r
+\r
+ private static enum DummyTask implements Task {\r
+ INSTANCE;\r
+\r
+ @Override\r
+ public void end() {\r
+ }\r
+ }\r
+\r
+ public Task begin(String name) {\r
+ return new TaskImpl(name);\r
+ }\r
+\r
+ public static Task BEGIN(String name) {\r
+ try {\r
+ if(defaultLog != null)\r
+ return defaultLog.begin(name);\r
+ } catch(NullPointerException e) {\r
+ }\r
+ return DummyTask.INSTANCE;\r
+ }\r
+\r
+ public static ThreadLog setDefaultThreadLog(ThreadLog log) {\r
+ ThreadLog currentLog = defaultLog;\r
+ defaultLog = log;\r
+ return currentLog;\r
+ }\r
+\r
+ // ------------------------------------------------------------------------\r
+ // SERIALIZATION\r
+ // ------------------------------------------------------------------------\r
+\r
+ public static ThreadLog deserialize(File file) throws IOException {\r
+ DataInputStream in = null;\r
+ try {\r
+ in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));\r
+ ThreadLog log = new ThreadLog();\r
+ log.doDeserialize(in);\r
+ return log;\r
+ } finally {\r
+ if (in != null) {\r
+ in.close();\r
+ }\r
+ }\r
+ }\r
+\r
+ public static ThreadLog deserialize(DataInput in) throws IOException {\r
+ ThreadLog log = new ThreadLog();\r
+ log.doDeserialize(in);\r
+ return log;\r
+ }\r
+\r
+ private void doDeserialize(DataInput in) throws IOException {\r
+ String hdr = in.readUTF();\r
+ if (!HDR.equals(hdr)) {\r
+ throw new StreamCorruptedException("invalid header '" + hdr + "', expected " + HDR);\r
+ }\r
+ int ver = in.readInt();\r
+ if (ver == CURRENT_VERSION) {\r
+ int taskCount = in.readInt();\r
+ for (int i = 0; i < taskCount; ++i) {\r
+ String task = in.readUTF();\r
+ double beginTime = in.readDouble();\r
+ double endTime = in.readDouble();\r
+ long threadId = in.readLong();\r
+ tasks.add(task);\r
+ times.add(beginTime);\r
+ times.add(endTime);\r
+ threads.add(threadId);\r
+ }\r
+ } else {\r
+ throw new StreamCorruptedException("unrecognized log version: " + ver);\r
+ }\r
+ }\r
+\r
+ public void serialize(File file) throws IOException {\r
+ DataOutputStream out = null;\r
+ try {\r
+ out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));\r
+ serialize(out);\r
+ } finally {\r
+ if (out != null) {\r
+ out.close();\r
+ }\r
+ }\r
+ }\r
+\r
+ public void serialize(DataOutput out) throws IOException {\r
+ out.writeUTF(HDR);\r
+ out.writeInt(CURRENT_VERSION);\r
+ int len = tasks.size();\r
+ out.writeInt(len);\r
+ for (int i = 0; i < len; ++i) {\r
+ out.writeUTF(tasks.get(i));\r
+ out.writeDouble(times.getQuick(i*2));\r
+ out.writeDouble(times.getQuick(i*2+1));\r
+ out.writeLong(threads.getQuick(i));\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog.internal;\r
+\r
+import org.eclipse.core.runtime.Plugin;\r
+import org.osgi.framework.BundleContext;\r
+import org.simantics.threadlog.ui.ThreadLogController;\r
+\r
+/**\r
+ * The activator class controls the plug-in life cycle\r
+ */\r
+public class Activator extends Plugin {\r
+\r
+ // The plug-in ID\r
+ public static final String PLUGIN_ID = "org.simantics.threadlog";\r
+\r
+ // The shared instance\r
+ private static Activator plugin;\r
+ \r
+ /**\r
+ * The constructor\r
+ */\r
+ public Activator() {\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext context) throws Exception {\r
+ super.start(context);\r
+ plugin = this;\r
+ \r
+ ThreadLogController.start();\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext context) throws Exception {\r
+ plugin = null;\r
+ super.stop(context);\r
+ }\r
+\r
+ /**\r
+ * Returns the shared instance\r
+ *\r
+ * @return the shared instance\r
+ */\r
+ public static Activator getDefault() {\r
+ return plugin;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog.ui;\r
+\r
+public class Interval implements Comparable<Interval> {\r
+ String text;\r
+ double begin;\r
+ double end;\r
+ \r
+ public Interval(String text, double begin, double end) {\r
+ this.text = text;\r
+ this.begin = begin;\r
+ this.end = end;\r
+ }\r
+\r
+ @Override\r
+ public int compareTo(Interval o) {\r
+ return Double.compare(begin, o.begin);\r
+ } \r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog.ui;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+public class Lane {\r
+ List<Interval> intervals = new ArrayList<Interval>();\r
+ \r
+ public void addInterval(Interval interval) {\r
+ intervals.add(interval);\r
+ }\r
+ \r
+ public double getEnd() {\r
+ return intervals.get(intervals.size()-1).end;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog.ui;\r
+\r
+import java.awt.GridLayout;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.io.IOException;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JFileChooser;\r
+import javax.swing.JFrame;\r
+import javax.swing.filechooser.FileNameExtensionFilter;\r
+\r
+import org.simantics.threadlog.ThreadLog;\r
+\r
+public class ThreadLogController extends JFrame {\r
+\r
+ private static final long serialVersionUID = -2487997716157625672L;\r
+ \r
+ boolean isLogging = false;\r
+ JButton logButton;\r
+ JButton loadButton;\r
+\r
+ public ThreadLogController() {\r
+ super("Thread log controller");\r
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);\r
+\r
+ logButton = new JButton("Start logging");\r
+ logButton.addActionListener(new ActionListener() {\r
+\r
+ @Override\r
+ public void actionPerformed(ActionEvent e) {\r
+ if(isLogging) {\r
+ logButton.setText("Start logging");\r
+ isLogging = false;\r
+ ThreadLog log = ThreadLog.setDefaultThreadLog(null);\r
+\r
+ ThreadLogVisualizer visualizer = new ThreadLogVisualizer();\r
+ visualizer.setLog(log);\r
+ visualizer.setVisible(true);\r
+ }\r
+ else {\r
+ logButton.setText("Stop logging");\r
+ isLogging = true;\r
+ ThreadLog.setDefaultThreadLog(new ThreadLog());\r
+ }\r
+ }\r
+\r
+ });\r
+ loadButton = new JButton("Load log");\r
+ loadButton.addActionListener(new ActionListener() {\r
+ @Override\r
+ public void actionPerformed(ActionEvent e) {\r
+ JFileChooser chooser = new JFileChooser();\r
+ FileNameExtensionFilter filter = new FileNameExtensionFilter(\r
+ "Thread Logs (*.tlog)", "tlog", "tlog");\r
+ chooser.setFileFilter(filter);\r
+ int returnVal = chooser.showOpenDialog(ThreadLogController.this);\r
+ if (returnVal != JFileChooser.APPROVE_OPTION)\r
+ return;\r
+\r
+ try {\r
+ ThreadLog log = ThreadLog.deserialize(chooser.getSelectedFile());\r
+ ThreadLogVisualizer visualizer = new ThreadLogVisualizer();\r
+ visualizer.setLog(log);\r
+ visualizer.setVisible(true);\r
+ } catch (IOException ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+ });\r
+ getContentPane().setLayout(new GridLayout(2, 1));\r
+ getContentPane().add(logButton);\r
+ getContentPane().add(loadButton);\r
+\r
+ setSize(200, 100);\r
+ }\r
+\r
+ public static void start() {\r
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {\r
+ public void run() {\r
+ new ThreadLogController().setVisible(true);\r
+ }\r
+ });\r
+ }\r
+\r
+ public static void main(String[] args) {\r
+ start();\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog.ui;\r
+\r
+import gnu.trove.TLongObjectHashMap;\r
+import gnu.trove.TObjectProcedure;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.KeyEvent;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+\r
+import javax.swing.AbstractAction;\r
+import javax.swing.JButton;\r
+import javax.swing.JFileChooser;\r
+import javax.swing.JFrame;\r
+import javax.swing.JToolBar;\r
+import javax.swing.filechooser.FileNameExtensionFilter;\r
+\r
+import org.simantics.threadlog.Task;\r
+import org.simantics.threadlog.ThreadLog;\r
+\r
+public class ThreadLogVisualizer extends JFrame {\r
+\r
+ private static final long serialVersionUID = 6250996509358338304L;\r
+ \r
+ TimeLineViewer viewer = new TimeLineViewer();\r
+ JToolBar toolbar = new JToolBar("Thread Log Visualizer Tools");\r
+ JButton saveButton = new JButton(new SaveAction());\r
+\r
+ ThreadLog currentLog;\r
+\r
+ public ThreadLogVisualizer() {\r
+ super("Thread log visualizer");\r
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);\r
+ setSize(800, 600);\r
+\r
+ getContentPane().setLayout(new BorderLayout());\r
+ getContentPane().add(toolbar, BorderLayout.NORTH);\r
+ getContentPane().add(viewer, BorderLayout.CENTER);\r
+\r
+ toolbar.add(saveButton);\r
+ }\r
+\r
+ class SaveAction extends AbstractAction {\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public SaveAction() {\r
+ super("Save");\r
+ putValue(SHORT_DESCRIPTION, "Save the Current Log");\r
+ putValue(MNEMONIC_KEY, KeyEvent.VK_S);\r
+ }\r
+\r
+ @Override\r
+ public void actionPerformed(ActionEvent e) {\r
+ JFileChooser chooser = new JFileChooser();\r
+ FileNameExtensionFilter filter = new FileNameExtensionFilter(\r
+ "Thread Logs (*.tlog)", "tlog", "tlog");\r
+ chooser.setFileFilter(filter);\r
+ int returnVal = chooser.showSaveDialog(ThreadLogVisualizer.this);\r
+ if (returnVal != JFileChooser.APPROVE_OPTION)\r
+ return;\r
+\r
+ try {\r
+ currentLog.serialize(chooser.getSelectedFile());\r
+ } catch (IOException ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ public void setLog(ThreadLog log) {\r
+ this.currentLog = log;\r
+\r
+ String[] tasks = log.getTasks();\r
+ double[] times = log.getTimes();\r
+\r
+ // Relativize to the first task\r
+ double minTime = Double.POSITIVE_INFINITY;\r
+ double maxTime = Double.NEGATIVE_INFINITY;\r
+\r
+ for(int i=0;i<times.length;i+=2) {\r
+ double temp = times[i];\r
+ if(temp < minTime)\r
+ minTime = temp;\r
+\r
+ temp = times[i+1];\r
+ if(temp > maxTime)\r
+ maxTime = temp;\r
+ }\r
+ for(int i=0;i<times.length;++i)\r
+ times[i] -= minTime;\r
+ maxTime -= minTime;\r
+\r
+ // Group intervals by thread\r
+ TLongObjectHashMap<ArrayList<Interval>> intervals = new TLongObjectHashMap<ArrayList<Interval>>();\r
+ long[] threads = log.getThreads();\r
+ for(int i=0;i<tasks.length;++i) {\r
+ long thread = threads[i];\r
+ ArrayList<Interval> in = intervals.get(thread);\r
+ if(in == null) {\r
+ in = new ArrayList<Interval>();\r
+ intervals.put(thread, in);\r
+ }\r
+ in.add(new Interval(tasks[i], times[i*2], times[i*2+1]));\r
+ }\r
+\r
+ // Create lanes\r
+ viewer.clear();\r
+ intervals.forEachValue(new TObjectProcedure<ArrayList<Interval>>() {\r
+\r
+ @Override\r
+ public boolean execute(ArrayList<Interval> intervals) {\r
+ Collections.sort(intervals);\r
+ ArrayList<Lane> lanes = new ArrayList<Lane>();\r
+\r
+ int curLaneId = -1;\r
+ Lane curLane = null;\r
+ for(Interval in : intervals) {\r
+ if(curLane == null || in.begin < curLane.getEnd()) {\r
+ ++curLaneId;\r
+ if(curLaneId < lanes.size())\r
+ curLane = lanes.get(curLaneId);\r
+ else {\r
+ curLane = new Lane();\r
+ lanes.add(curLane);\r
+ }\r
+ }\r
+ else {\r
+ while(curLaneId > 0) {\r
+ Lane prevLane = lanes.get(curLaneId-1);\r
+ if(prevLane.getEnd() > in.begin)\r
+ break;\r
+ --curLaneId;\r
+ curLane = prevLane;\r
+ }\r
+ }\r
+ curLane.addInterval(in);\r
+ }\r
+\r
+ for(Lane lane : lanes)\r
+ viewer.addLane(lane);\r
+ return true;\r
+ }\r
+\r
+ });\r
+\r
+ // update viewer\r
+ viewer.repaint();\r
+ }\r
+\r
+ public void saveImage() {\r
+\r
+ }\r
+\r
+ public static void main(String[] args) throws Exception {\r
+ ThreadLog.setDefaultThreadLog(new ThreadLog());\r
+\r
+ {\r
+ Task A = ThreadLog.BEGIN("A");\r
+ Thread.sleep(200);\r
+ Task B = ThreadLog.BEGIN("B");\r
+ Thread.sleep(100);\r
+ B.end();\r
+ Thread.sleep(100);\r
+ Task C = ThreadLog.BEGIN("C");\r
+ Thread.sleep(100);\r
+ C.end();\r
+ A.end();\r
+ }\r
+\r
+ ThreadLogVisualizer vis = new ThreadLogVisualizer();\r
+ vis.setLog(ThreadLog.setDefaultThreadLog(null));\r
+ vis.setVisible(true);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.threadlog.ui;\r
+\r
+import java.awt.Color;\r
+import java.awt.Dimension;\r
+import java.awt.Graphics;\r
+import java.awt.Graphics2D;\r
+import java.awt.Shape;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.event.MouseMotionAdapter;\r
+import java.awt.event.MouseWheelEvent;\r
+import java.awt.event.MouseWheelListener;\r
+import java.awt.geom.Rectangle2D;\r
+import java.awt.geom.RoundRectangle2D;\r
+import java.text.DecimalFormat;\r
+import java.text.Format;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Timer;\r
+import java.util.TimerTask;\r
+\r
+import javax.swing.JPanel;\r
+\r
+public class TimeLineViewer extends JPanel {\r
+\r
+ private static final long serialVersionUID = -7410066541298449720L;\r
+ \r
+ public static long TOOL_TIP_DELAY = 500;\r
+ public static double MIN_GRID_LINE_SEPARATION = 15;\r
+ \r
+ // Time line data\r
+ List<Lane> lanes = new ArrayList<Lane>();\r
+ \r
+ // For panning and zooming\r
+ double xScale = 100.0;\r
+ double xOffset = 0.0;\r
+ double yOffset = 0.0;\r
+ int oldX;\r
+ int oldY;\r
+ \r
+ // Tool tips\r
+ Timer toolTipTimer = new Timer();\r
+ class ToolTipTask extends TimerTask {\r
+\r
+ @Override\r
+ public void run() {\r
+ System.out.println("show tooltip"); \r
+ }\r
+ \r
+ }\r
+ \r
+ public TimeLineViewer() {\r
+ addMouseListener(new MouseAdapter() {\r
+ @Override\r
+ public void mousePressed(MouseEvent e) {\r
+ oldX = e.getX();\r
+ oldY = e.getY();\r
+ }\r
+ });\r
+ addMouseMotionListener(new MouseMotionAdapter() { \r
+ @Override\r
+ public void mouseDragged(MouseEvent e) {\r
+ int curX = e.getX();\r
+ int curY = e.getY();\r
+ int diffX = curX - oldX;\r
+ int diffY = curY - oldY;\r
+ oldX = curX;\r
+ oldY = curY;\r
+ \r
+ xOffset -= diffX/xScale;\r
+ yOffset -= diffY;\r
+ repaint();\r
+ }\r
+ TimerTask toolTipTask;\r
+ @Override\r
+ public void mouseMoved(MouseEvent e) {\r
+ if(toolTipTask != null)\r
+ toolTipTask.cancel();\r
+ toolTipTask = new ToolTipTask();\r
+ toolTipTimer.schedule(toolTipTask, TOOL_TIP_DELAY);\r
+ }\r
+ });\r
+ addMouseWheelListener(new MouseWheelListener() { \r
+ @Override\r
+ public void mouseWheelMoved(MouseWheelEvent e) {\r
+ xOffset += e.getX() / xScale;\r
+ xScale *= Math.pow(1.25, -e.getWheelRotation());\r
+ xOffset -= e.getX() / xScale;\r
+ repaint();\r
+ }\r
+ });\r
+ }\r
+ \r
+ public void addLane(Lane lane) {\r
+ lanes.add(lane);\r
+ }\r
+ \r
+ public void clear() {\r
+ lanes.clear();\r
+ }\r
+ \r
+ public void paintIntervals(Graphics2D g) { \r
+ for(int laneId=0;laneId < lanes.size();++laneId) {\r
+ Lane lane = lanes.get(laneId);\r
+ \r
+ double y = 35.0*laneId - yOffset;\r
+ double height = 30.0;\r
+ \r
+ for(Interval interval : lane.intervals) {\r
+ double x = (interval.begin - xOffset) * xScale; \r
+ double width = (interval.end - interval.begin) * xScale;\r
+ \r
+ Shape shape = new RoundRectangle2D.Double(x, y, width, height, 10.0, 10.0);\r
+ g.setColor(Color.WHITE);\r
+ g.fill(shape);\r
+ g.setColor(Color.BLACK);\r
+ g.draw(shape);\r
+ \r
+ Rectangle2D bounds = g.getFontMetrics().getStringBounds(interval.text, g);\r
+ if(bounds.getWidth() < width)\r
+ g.drawString(interval.text, (float)(x+0.5*(width-bounds.getWidth())), (float)(y+20.0));\r
+ }\r
+ }\r
+ }\r
+ \r
+ public void paintGrid(Graphics2D g) {\r
+ Dimension dim = getSize();\r
+ \r
+ g.setBackground(Color.WHITE);\r
+ g.clearRect(0, 0, dim.width, dim.height);\r
+ \r
+ double stepsize = 0.001;\r
+ double majorStepsize;\r
+ while(true) {\r
+ majorStepsize = stepsize * 5.0;\r
+ if(stepsize * xScale >= MIN_GRID_LINE_SEPARATION)\r
+ break;\r
+ stepsize = majorStepsize;\r
+ majorStepsize = stepsize * 2.0;\r
+ if(stepsize * xScale >= MIN_GRID_LINE_SEPARATION)\r
+ break;\r
+ stepsize = majorStepsize;\r
+ }\r
+ \r
+ double firstP = Math.ceil(xOffset / stepsize) * stepsize;\r
+ double lastP = Math.floor((xOffset + dim.width / xScale) / stepsize) * stepsize;\r
+ if(firstP < 0.0)\r
+ firstP = 0.0;\r
+\r
+ Format format = new DecimalFormat();\r
+ for(double p = firstP;p <= lastP; p+=stepsize) {\r
+ int x = (int)((p - xOffset) * xScale);\r
+ if(Math.abs(p/majorStepsize - Math.round(p/majorStepsize)) < 1e-3) {\r
+ g.setColor(Color.BLACK);\r
+ String text = format.format(p);\r
+ Rectangle2D bounds = g.getFontMetrics().getStringBounds(text, g);\r
+ g.drawString(text, (float)(x-bounds.getWidth()*0.5), 12.0f); \r
+ }\r
+ else\r
+ g.setColor(Color.LIGHT_GRAY);\r
+ g.drawLine(x, 14, x, (int)dim.getHeight());\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void paint(Graphics _g) {\r
+ Graphics2D g = (Graphics2D)_g; \r
+ \r
+ paintGrid(g);\r
+ paintIntervals(g);\r
+ }\r
+ \r
+}\r
output.. = bin/\r
bin.includes = META-INF/,\\r
.\r
-javacSource=1.6\r
-javacTarget=1.6\r
-
\ No newline at end of file
<module>org.simantics.diagram.profile</module>\r
<module>org.simantics.document</module>\r
<module>org.simantics.document.base.ontology</module>\r
+ <module>org.simantics.document.linking.ontology</module>\r
<module>org.simantics.document.linking.ui</module>\r
<module>org.simantics.document.ontology</module>\r
<module>org.simantics.document.server</module>\r
<module>org.simantics.modeling.template2d.ontology</module>\r
<module>org.simantics.modeling.template2d.ui</module>\r
<module>org.simantics.modeling.ui</module>\r
+ <module>org.simantics.nativemem</module>\r
<module>org.simantics.objmap2</module>\r
<module>org.simantics.platform.ui.ontology</module>\r
<module>org.simantics.project</module>\r
<module>org.simantics.scl.commands</module>\r
<module>org.simantics.scl.compiler</module>\r
<module>org.simantics.scl.compiler.dummy</module>\r
+ <module>org.simantics.scl.data</module>\r
<module>org.simantics.scl.db</module>\r
<module>org.simantics.scl.expressions</module>\r
<module>org.simantics.scl.osgi</module>\r
<module>org.simantics.structural.ui</module>\r
<module>org.simantics.structural2</module>\r
<module>org.simantics.team.ui</module>\r
+ <module>org.simantics.threadlog</module>\r
<module>org.simantics.trend</module>\r
<module>org.simantics.ui</module>\r
<module>org.simantics.user.ontology</module>\r
<module>org.simantics.workbench</module>\r
<module>org.simantics.workbench.ontology</module>\r
<module>org.simantics.workbench.search</module>\r
+ <module>winterwell.markdown</module>\r
</modules>\r
</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="lib" path="lib/markdownj-1.0.2b4-0.3.0.jar"/>
+ <classpathentry kind="lib" path="lib/net.sf.paperclips_1.0.1.jar"/>
+ <classpathentry kind="lib" path="lib/winterwell.utils.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>winterwell.markdown</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Markdown
+Bundle-SymbolicName: winterwell.markdown;singleton:=true
+Bundle-Version: 1.2.0.qualifier
+Bundle-Activator: winterwell.markdown.Activator
+Bundle-Vendor: Winterwell Associates Ltd
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.editors,
+ org.eclipse.jface.text,
+ org.eclipse.core.resources,
+ org.eclipse.ui.views,
+ org.eclipse.jface,
+ org.eclipse.swt,
+ org.eclipse.ui.workbench
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
+Import-Package: org.eclipse.core.internal.resources,
+ org.eclipse.jface.text,
+ org.eclipse.ui.texteditor
+Bundle-ClassPath: .,target/classes,lib/markdownj-1.0.2b4-0.3.0.jar,
+ lib/winterwell.utils.jar,
+ lib/net.sf.paperclips_1.0.1.jar
+Export-Package: com.petebevin.markdown,
+ com.petebevin.markdown.test,
+ net.sf.paperclips,
+ net.sf.paperclips.decorator,
+ winterwell.markdown,
+ winterwell.markdown.editors,
+ winterwell.markdown.pagemodel,
+ winterwell.markdown.preferences,
+ winterwell.markdown.views,
+ winterwell.utils,
+ winterwell.utils.containers,
+ winterwell.utils.gui,
+ winterwell.utils.io,
+ winterwell.utils.reporting,
+ winterwell.utils.threads,
+ winterwell.utils.time,
+ winterwell.utils.web
--- /dev/null
+source.. = src/
+bin.includes = META-INF/,\
+ plugin.xml,\
+ icons/,\
+ .,\
+ lib/
+src.includes = src/,\
+ pom.xml,\
+ plugin.xml,\
+ icons/,\
+ lib/,\
+ .project,\
+ .classpath,\
+ META-INF/,\
+ build.properties
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.7"?>
+<plugin>
+
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ name="Markdown Editor"
+ extensions="txt,md,mdown,markdown,mdwn"
+ icon="icons/notepad.gif"
+ contributorClass="winterwell.markdown.editors.ActionBarContributor"
+ class="winterwell.markdown.editors.MarkdownEditor"
+ id="winterwell.markdown.editors.MarkdownEditor"
+ default="true">
+ </editor>
+
+ <editor
+ class="winterwell.markdown.editors.MarkdownEditor"
+ contributorClass="winterwell.markdown.editors.ActionBarContributor"
+ default="true"
+ extensions="litcoffee"
+ icon="icons/coffee.png"
+ id="org.nodeclipse.ui.editors.LitCoffeeEditor"
+ name="LitCoffee (Markdown) Editor">
+ </editor>
+
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ allPopups="false"
+ locationURI="toolbar:winterwell.markdown.views.MarkdownPreview">
+ <command
+ commandId="winterwell.markdown.commands.OpenGfmView"
+ icon="icons/github-cat_yellow.png"
+ style="push">
+ </command>
+ <command
+ commandId="winterwell.markdown.commands.Preferences"
+ icon="icons/settings16_yellow.png"
+ style="push">
+ </command>
+ </menuContribution>
+ <menuContribution
+ allPopups="false"
+ locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
+ <toolbar
+ id="winterwell.markdown.MarkdownEditor">
+ <command
+ commandId="winterwell.markdown.commands.OpenMdView"
+ icon="icons/notepad.gif"
+ style="push">
+ <visibleWhen
+ checkEnabled="true">
+ </visibleWhen>
+ </command>
+ </toolbar>
+ </menuContribution>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ defaultHandler="winterwell.markdown.commands.OpenGfmView"
+ id="winterwell.markdown.commands.OpenGfmView"
+ name="Open GitHub Flavored Markdown View">
+ </command>
+ <command
+ id="winterwell.markdown.commands.OpenMdView"
+ name="Open Markdown View">
+ </command>
+ <command
+ defaultHandler="winterwell.markdown.commands.Preferences"
+ id="winterwell.markdown.commands.Preferences"
+ name="Preferences">
+ </command>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.views">
+ <category
+ id="winterwell.markdown"
+ name="Markdown"/>
+ <view
+ category="winterwell.markdown"
+ class="winterwell.markdown.views.MarkdownPreview"
+ icon="icons/notepad.gif"
+ id="winterwell.markdown.views.MarkdownPreview"
+ name="Markdown View"/>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ class="winterwell.markdown.preferences.MarkdownPreferencePage"
+ id="winterwell.markdown.preferences.MarkdownPreferencePage"
+ name="Markdown"
+ category="org.eclipse.ui.preferencePages.GeneralTextEditor">
+ <keywordReference
+ id="winterwell.markdown.prefsKeywordReference">
+ </keywordReference>
+ </page>
+ </extension>
+ <extension
+ point="org.eclipse.ui.keywords">
+ <keyword
+ id="winterwell.markdown.prefsKeywordReference"
+ label="word wrapping tool tags">
+ </keyword>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ defaultHandler="winterwell.markdown.editors.FormatAction"
+ description="Format the paragraph under the caret to fit the print margins by inserting/removing line-breaks"
+ id="winterwell.markdown.formatParagraphCommand"
+ name="Format paragraph">
+ </command>
+ </extension>
+ <extension
+ point="org.eclipse.ui.bindings">
+ <key
+ commandId="winterwell.markdown.formatParagraphCommand"
+ contextId="org.eclipse.ui.contexts.window"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="Alt+Q">
+ </key>
+ </extension>
+ <extension
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ id="winterwell.markdown.actionSet"
+ label="winterwell.markdown.actionSet">
+ <action
+ class="winterwell.markdown.editors.FormatAction"
+ definitionId="winterwell.markdown.formatParagraphCommand"
+ id="winterwell.markdown.formatParagraphAction"
+ label="Format paragraph"
+ menubarPath="edit"
+ style="push">
+ </action>
+ </actionSet>
+ </extension>
+ <extension
+ point="org.eclipse.ui.handlers">
+ <handler
+ class="winterwell.markdown.commands.OpenMdView"
+ commandId="winterwell.markdown.commands.OpenMdView">
+ <activeWhen>
+ <with
+ variable="activeEditorId">
+ <equals
+ value="winterwell.markdown.editors.MarkdownEditor">
+ </equals>
+ </with>
+ </activeWhen>
+ </handler>
+ </extension>
+
+</plugin>
--- /dev/null
+package winterwell.markdown;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+import winterwell.markdown.preferences.MarkdownPreferencePage;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "winterwell.markdown";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ doInstall();
+ MarkdownPreferencePage.setDefaultPreferences(getPreferenceStore());
+ }
+
+ // ?? Have this method called by start(), saving a reminder so it doesn't repeat itself??
+ private void doInstall() {
+ // ??Try to make this the default for file types -- but is this possible??
+ // c.f. http://stackoverflow.com/questions/15877123/eclipse-rcp-programmatically-associate-file-type-with-editor
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
--- /dev/null
+package winterwell.markdown;
+
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Nodeclipse Log Util
+ * @author Lamb Gao, Paul Verest
+ */
+public class LogUtil {
+
+ public static void info(String message) {
+ log(IStatus.INFO, IStatus.OK, message, null);
+ }
+
+ public static void error(Throwable exception) {
+ error("Unexpected Exception", exception);
+ }
+
+ public static void error(String message) {
+ error(message, null);
+ }
+
+ public static void error(String message, Throwable exception) {
+ log(IStatus.ERROR, IStatus.ERROR, message, exception);
+ }
+
+ public static void log(int severity, int code, String message, Throwable exception) {
+ log(createStatus(severity, code, message, exception));
+ }
+
+ public static IStatus createStatus(int severity, int code, String message, Throwable exception) {
+ return new Status(severity, Activator.PLUGIN_ID, code, message, exception);
+ }
+
+ public static void log(IStatus status) {
+ ILog log = Activator.getDefault().getLog();
+ log.log(status);
+ }
+}
--- /dev/null
+/**\r
+ * Basic String manipulation utilities.\r
+ * (c) Winterwell 2010 and ThinkTank Mathematics 2007\r
+ */\r
+package winterwell.markdown;\r
+\r
+import java.math.BigInteger;\r
+import java.security.MessageDigest;\r
+import java.security.NoSuchAlgorithmException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.regex.Pattern;\r
+\r
+import winterwell.utils.Mutable;\r
+import winterwell.utils.containers.Pair;\r
+\r
+/**\r
+ * A collection of general-purpose String handling methods.\r
+ * \r
+ * @author daniel.winterstein\r
+ */\r
+public final class StringMethods {\r
+\r
+ /**\r
+ * Removes xml tags, comment blocks and script blocks.\r
+ * \r
+ * @param page\r
+ * @return the page with all xml tags removed.\r
+ */\r
+ public static String stripTags(String page) {\r
+ // This code is rather ugly, but it does the job\r
+ StringBuilder stripped = new StringBuilder(page.length());\r
+ boolean inTag = false;\r
+ // Comment blocks and script blocks are given special treatment\r
+ boolean inComment = false;\r
+ boolean inScript = false;\r
+ // Go through the text\r
+ for (int i = 0; i < page.length(); i++) {\r
+ char c = page.charAt(i);\r
+ // First check whether we are ignoring text\r
+ if (inTag) {\r
+ if (c == '>')\r
+ inTag = false;\r
+ } else if (inComment) {\r
+ if (c == '>' && page.charAt(i - 1) == '-'\r
+ && page.charAt(i - 1) == '-') {\r
+ inComment = false;\r
+ }\r
+ } else if (inScript) {\r
+ if (c == '>' && page.substring(i - 7, i).equals("/script")) {\r
+ inScript = false;\r
+ }\r
+ } else {\r
+ // Check for the start of a tag - looks for '<' followed by any\r
+ // non-whitespace character\r
+ if (c == '<' && !Character.isWhitespace(page.charAt(i + 1))) {\r
+ // Comment, script-block or tag?\r
+ if (page.charAt(i + 1) == '!' && page.charAt(i + 2) == '-'\r
+ && page.charAt(i + 3) == '-') {\r
+ inComment = true;\r
+ } else if (i + 8 < page.length()\r
+ && page.substring(i + 1, i + 7).equals("script")) {\r
+ inScript = true;\r
+ i += 7;\r
+ } else\r
+ inTag = true; // Normal tag by default\r
+ } else {\r
+ // Append all non-tag chars\r
+ stripped.append(c);\r
+ }\r
+ } // end if...\r
+ }\r
+ return stripped.toString();\r
+ }\r
+ \r
+ /**\r
+ * The local line-end string. \n on unix, \r\n on windows, \r on mac.\r
+ */\r
+ public static final String LINEEND = System.getProperty("line.separator");\r
+\r
+ /**\r
+ * @param s\r
+ * @return A version of s where the first letter is uppercase and all others\r
+ * are lowercase\r
+ */\r
+ public static final String capitalise(final String s) {\r
+ return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();\r
+ }\r
+\r
+ /**\r
+ * Convert all line breaks into the system line break.\r
+ */\r
+ public static final String convertLineBreaks(String text) {\r
+ return convertLineBreaks(text, LINEEND);\r
+ }\r
+\r
+ /**\r
+ * Convert all line breaks into the specified line break.\r
+ */\r
+ public static final String convertLineBreaks(String text, String br) {\r
+ text = text.replaceAll("\r\n", br);\r
+ text = text.replaceAll("\r", br);\r
+ text = text.replaceAll("\n", br);\r
+ return text;\r
+ }\r
+\r
+ /**\r
+ * @param string\r
+ * @param character\r
+ * @return the number of times character appears in the string\r
+ * @author Sam Halliday\r
+ */\r
+ static public int countCharsInString(String string, char character) {\r
+ int count = 0;\r
+ for (char c : string.toCharArray()) {\r
+ if (c == character) {\r
+ count++;\r
+ }\r
+ }\r
+ return count;\r
+ }\r
+\r
+ /**\r
+ * \r
+ * E.g.\r
+ * <code>findEnclosingRegion("text with a [region] inside", 15, '[', ']')</code>\r
+ * is (??,??)\r
+ * \r
+ * @param text\r
+ * @param offset\r
+ * @param start\r
+ * @param end\r
+ * @return the smallest enclosed region (including start and end chars, the\r
+ * 1st number is inclusive, the 2nd exclusive), or null if none. So\r
+ * text.subString(start,end) is the specified region\r
+ */\r
+ public static Pair<Integer> findEnclosingRegion(String text, int offset,\r
+ char startMarker, char endMarker) {\r
+ // Forward\r
+ int end = findEnclosingRegion2(text, offset, endMarker, 1);\r
+ if (end == -1)\r
+ return null;\r
+ end++; // end is exclusive\r
+ // Backward\r
+ int start = findEnclosingRegion2(text, offset, startMarker, -1);\r
+ if (start == -1)\r
+ return null;\r
+ // Sanity\r
+ assert text.substring(start, end).charAt(0) == startMarker;\r
+ assert text.substring(start, end).endsWith("" + endMarker);\r
+ // Done\r
+ return new Pair<Integer>(start, end);\r
+ }\r
+\r
+ private static int findEnclosingRegion2(String text, int offset,\r
+ char endMarker, int direction) {\r
+ while (offset > -1 && offset < text.length()) {\r
+ char c = text.charAt(offset);\r
+ if (c == endMarker)\r
+ return offset;\r
+ offset += direction;\r
+ }\r
+ return -1;\r
+ }\r
+\r
+ /**\r
+ * A convenience wrapper for\r
+ * {@link #findEnclosingRegion(String, int, char, char)} E.g. <code>\r
+ findEnclosingRegion("text with a [region] inside", 15, '[', ']') .equals("[region]");\r
+ </code>\r
+ * \r
+ * @param text\r
+ * @param offset\r
+ * @param start\r
+ * @param end\r
+ * @return the smallest enclosed region (including start and end chars), or\r
+ * null if none.\r
+ */\r
+ public static String findEnclosingText(String text, int offset,\r
+ char startMarker, char endMarker) {\r
+ Pair<Integer> region = findEnclosingRegion(text, offset, startMarker,\r
+ endMarker);\r
+ if (region == null)\r
+ return null;\r
+ String s = text.substring(region.first, region.second);\r
+ return s;\r
+ }\r
+\r
+ /**\r
+ * Format a block of text to use the given line-width. I.e. adjust the line\r
+ * breaks. Also known as <i>hard</i> line-wrapping. Paragraphs are\r
+ * recognised by a line of blank space between them (e.g. two returns).\r
+ * <p>\r
+ * Note: a side-effect of this method is that it converts all line-breaks\r
+ * into the local system's line-breaks. E.g. on Windows, \n will become \r\n\r
+ * \r
+ * @param text\r
+ * The text to format\r
+ * @param lineWidth\r
+ * The number of columns in a line. Typically 78 or 80.\r
+ * @param respectLeadingCharacters\r
+ * Can be null. If set, the specified leading characters will be\r
+ * copied if the line is split. Use with " \t" to keep indented\r
+ * paragraphs properly indented. Use with "> \t" to also handle\r
+ * email-style quoting. Note that respected leading characters\r
+ * receive no special treatment when they are used inside a\r
+ * paragraph.\r
+ * @return A copy of text, formatted to the given line-width.\r
+ * <p>\r
+ * TODO: recognise paragraphs by changes in the respected leading\r
+ * characters\r
+ */\r
+ public static String format(String text, int lineWidth, int tabWidth,\r
+ String respectLeadingCharacters) {\r
+ // Switch to Linux line breaks for easier internal workings\r
+ text = convertLineBreaks(text, "\n");\r
+ // Find paragraphs\r
+ List<String> paras = format2_splitParagraphs(text,\r
+ respectLeadingCharacters);\r
+ // Rebuild text\r
+ StringBuilder sb = new StringBuilder(text.length() + 10);\r
+ for (String p : paras) {\r
+ String fp = format3_oneParagraph(p, lineWidth, tabWidth,\r
+ respectLeadingCharacters);\r
+ sb.append(fp);\r
+ // Paragraphs end with a double line break\r
+ sb.append("\n\n");\r
+ }\r
+ // Pop the last line breaks\r
+ sb.delete(sb.length() - 2, sb.length());\r
+ // Convert line breaks to system ones\r
+ text = convertLineBreaks(sb.toString());\r
+ // Done\r
+ return text;\r
+ }\r
+\r
+ private static List<String> format2_splitParagraphs(String text,\r
+ String respectLeadingCharacters) {\r
+ List<String> paras = new ArrayList<String>();\r
+ Mutable.Int index = new Mutable.Int(0);\r
+ // TODO The characters prefacing this paragraph\r
+ String leadingChars = "";\r
+ while (index.value < text.length()) {\r
+ // One paragraph\r
+ boolean inSpace = false;\r
+ int start = index.value;\r
+ while (index.value < text.length()) {\r
+ char c = text.charAt(index.value);\r
+ index.value++;\r
+ if (!Character.isWhitespace(c)) {\r
+ inSpace = false;\r
+ continue;\r
+ }\r
+ // Line end?\r
+ if (c == '\r' || c == '\n') {\r
+ // // Handle MS Windows 2 character \r\n line breaks\r
+ // if (index.value < text.length()) {\r
+ // char c2 = text.charAt(index.value);\r
+ // if (c=='\r' && c2=='\n') index.value++; // Push on past\r
+ // the 2nd line break char\r
+ // }\r
+ // Double line end - indicating a paragraph break\r
+ if (inSpace)\r
+ break;\r
+ inSpace = true;\r
+ }\r
+ // TODO Other paragraph markers, spotted by a change in\r
+ // leadingChars\r
+ }\r
+ String p = text.substring(start, index.value);\r
+ paras.add(p);\r
+ }\r
+ // Done\r
+ return paras;\r
+ }\r
+\r
+ /**\r
+ * Format a block of text to fit the given line width\r
+ * \r
+ * @param p\r
+ * @param lineWidth\r
+ * @param tabWidth\r
+ * @param respectLeadingCharacters\r
+ * @return\r
+ */\r
+ private static String format3_oneParagraph(String p, int lineWidth,\r
+ int tabWidth, String respectLeadingCharacters) {\r
+ // Collect the reformatted paragraph\r
+ StringBuilder sb = new StringBuilder(p.length() + 10); // Allow for\r
+ // some extra\r
+ // line-breaks\r
+ // Get respected leading chars\r
+ String leadingChars = format4_getLeadingChars(p,\r
+ respectLeadingCharacters);\r
+ // First Line\r
+ sb.append(leadingChars);\r
+ int lineLength = leadingChars.length();\r
+ int index = leadingChars.length();\r
+ // Loop\r
+ while (index < p.length()) {\r
+ // Get the next word\r
+ StringBuilder word = new StringBuilder();\r
+ char c = p.charAt(index);\r
+ index++;\r
+ while (!Character.isWhitespace(c)) {\r
+ word.append(c);\r
+ if (index == p.length())\r
+ break;\r
+ c = p.charAt(index);\r
+ index++;\r
+ }\r
+ // Break the line if the word will not fit\r
+ if (lineLength + word.length() > lineWidth && lineLength != 0) {\r
+ trimEnd(sb);\r
+ sb.append('\n'); // lineEnd(sb);\r
+ // New line\r
+ sb.append(leadingChars);\r
+ lineLength = leadingChars.length();\r
+ }\r
+ // Add word\r
+ sb.append(word);\r
+ lineLength += word.length();\r
+ // Add the whitespace\r
+ if (index != p.length() && lineLength < lineWidth) {\r
+ if (c == '\n') {\r
+ c = ' ';\r
+ }\r
+ sb.append(c);\r
+ lineLength += (c == '\t') ? tabWidth : 1;\r
+ }\r
+ }\r
+ // A final trim\r
+ trimEnd(sb);\r
+ // Done\r
+ return sb.toString();\r
+ }\r
+\r
+ /**\r
+ * \r
+ * @param text\r
+ * @param respectLeadingCharacters\r
+ * Can be null\r
+ * @return The characters at the beginning of text which are respected. E.g.\r
+ * ("> Hello", " \t>") --> "> "\r
+ */\r
+ private static String format4_getLeadingChars(String text,\r
+ String respectLeadingCharacters) {\r
+ if (respectLeadingCharacters == null)\r
+ return "";\r
+ // Line-breaks cannot be respected\r
+ assert respectLeadingCharacters.indexOf('\n') == -1;\r
+ // Look for the first non-respected char\r
+ for (int i = 0; i < text.length(); i++) {\r
+ char c = text.charAt(i);\r
+ if (respectLeadingCharacters.indexOf(c) == -1) {\r
+ // Return the previous chars\r
+ return text.substring(0, i);\r
+ }\r
+ }\r
+ // All chars are respected\r
+ return text;\r
+ }\r
+\r
+ /**\r
+ * Ensure that line ends with the right line-end character(s)\r
+ */\r
+ public static final String lineEnd(String line) {\r
+ // strip possibly inappropriate line-endings\r
+ if (line.endsWith("\n")) {\r
+ line = line.substring(0, line.length() - 1);\r
+ }\r
+ if (line.endsWith("\r\n")) {\r
+ line = line.substring(0, line.length() - 2);\r
+ }\r
+ if (line.endsWith("\r")) {\r
+ line = line.substring(0, line.length() - 1);\r
+ }\r
+ // add in proper line end\r
+ if (!line.endsWith(LINEEND)) {\r
+ line += LINEEND;\r
+ }\r
+ return line;\r
+ }\r
+\r
+ /**\r
+ * Ensure that line ends with the right line-end character(s). This is more\r
+ * efficient than the version for Strings.\r
+ * \r
+ * @param line\r
+ */\r
+ public static final void lineEnd(final StringBuilder line) {\r
+ if (line.length() == 0) {\r
+ line.append(LINEEND);\r
+ return;\r
+ }\r
+ // strip possibly inappropriate line-endings\r
+ final char last = line.charAt(line.length() - 1);\r
+ if (last == '\n') {\r
+ if ((line.length() > 1) && (line.charAt(line.length() - 2) == '\r')) {\r
+ // \r\n\r
+ line.replace(line.length() - 2, line.length(), LINEEND);\r
+ return;\r
+ }\r
+ line.replace(line.length() - 1, line.length(), LINEEND);\r
+ return;\r
+ }\r
+ if (last == '\r') {\r
+ line.replace(line.length() - 1, line.length(), LINEEND);\r
+ return;\r
+ }\r
+ line.append(LINEEND);\r
+ return;\r
+ }\r
+\r
+\r
+ \r
+ /**\r
+ * @param string\r
+ * @return the MD5 sum of the string using the default charset. Null if\r
+ * there was an error in calculating the hash.\r
+ * @author Sam Halliday\r
+ */\r
+ public static String md5Hash(String string) {\r
+ MessageDigest md5 = null;\r
+ try {\r
+ md5 = MessageDigest.getInstance("MD5");\r
+ } catch (NoSuchAlgorithmException e) {\r
+ // ignore this exception, we know MD5 exists\r
+ }\r
+ md5.update(string.getBytes());\r
+ BigInteger hash = new BigInteger(1, md5.digest());\r
+ return hash.toString(16);\r
+ }\r
+\r
+ /**\r
+ * Removes HTML-style tags from a string.\r
+ * \r
+ * @param s\r
+ * a String from which to remove tags\r
+ * @return a string with all instances of <.*> removed.\r
+ */\r
+ public static String removeTags(String s) {\r
+ StringBuffer sb = new StringBuffer();\r
+ boolean inTag = false;\r
+ for (int i = 0; i < s.length(); i++) {\r
+ char c = s.charAt(i);\r
+ if (c == '<')\r
+ inTag = true;\r
+ if (!inTag)\r
+ sb.append(c);\r
+ if (c == '>')\r
+ inTag = false;\r
+ }\r
+ return sb.toString();\r
+ }\r
+\r
+ /**\r
+ * Repeat a character.\r
+ * \r
+ * @param c\r
+ * @param i\r
+ * @return A String consisting of i x c.\r
+ * @example assert repeat('-', 5).equals("-----");\r
+ */\r
+ public static String repeat(Character c, int i) {\r
+ StringBuilder dashes = new StringBuilder(i);\r
+ for (int j = 0; j < i; j++)\r
+ dashes.append(c);\r
+ return dashes.toString();\r
+ }\r
+\r
+ /**\r
+ * Split a piece of text into separate lines. The line breaks are left at\r
+ * the end of each line.\r
+ * \r
+ * @param text\r
+ * @return The individual lines in the text.\r
+ */\r
+ public static List<String> splitLines(String text) {\r
+ List<String> lines = new ArrayList<String>();\r
+ // Search for lines\r
+ int start = 0;\r
+ for (int i = 0; i < text.length(); i++) {\r
+ char c = text.charAt(i);\r
+ if (c == '\r' || c == '\n') {\r
+ // Handle MS Windows 2 character \r\n line breaks\r
+ if (i + 1 < text.length()) {\r
+ char c2 = text.charAt(i + 1);\r
+ if (c == '\r' && c2 == '\n')\r
+ i++;\r
+ }\r
+ // Get the line, with the line break\r
+ String line = text.substring(start, i + 1);\r
+ lines.add(line);\r
+ start = i + 1;\r
+ }\r
+ }\r
+ // Last one\r
+ if (start != text.length()) {\r
+ String line = text.substring(start);\r
+ lines.add(line);\r
+ }\r
+ return lines;\r
+ }\r
+\r
+ /**\r
+ * Remove <i>trailing</i> whitespace. c.f. String#trim() which removes\r
+ * leading and trailing whitespace.\r
+ * \r
+ * @param sb\r
+ */\r
+ private static void trimEnd(StringBuilder sb) {\r
+ while (true) {\r
+ // Get the last character\r
+ int i = sb.length() - 1;\r
+ if (i == -1)\r
+ return; // Quit if sb is empty\r
+ char c = sb.charAt(i);\r
+ if (!Character.isWhitespace(c))\r
+ return; // Finish?\r
+ sb.deleteCharAt(i); // Remove and continue\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns true if the string is just whitespace, or empty, or null.\r
+ * \r
+ * @param s\r
+ */\r
+ public static final boolean whitespace(final String s) {\r
+ if (s == null) {\r
+ return true;\r
+ }\r
+ for (int i = 0; i < s.length(); i++) {\r
+ final char c = s.charAt(i);\r
+ if (!Character.isWhitespace(c)) {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * @param text\r
+ * @return the number of words in text. Uses a crude whitespace\r
+ * measure.\r
+ */\r
+ public static int wordCount(String text) {\r
+ String[] bits = text.split("\\W+");\r
+ int wc = 0;\r
+ for (String string : bits) {\r
+ if (!whitespace(string)) wc++;\r
+ }\r
+ return wc;\r
+ }\r
+\r
+}\r
--- /dev/null
+package winterwell.markdown.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+
+import winterwell.markdown.LogUtil;
+
+public class OpenGfmView extends AbstractHandler {
+
+ @Override
+ public Object execute(final ExecutionEvent event) throws ExecutionException {
+ try {
+ IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ String gfmViewId = "code.satyagraha.gfm.viewer.views.GfmView";
+ IViewPart gfmView = activePage.showView(gfmViewId);
+ activePage.activate(gfmView);
+ } catch (PartInitException e) {
+ showError(e);
+ } catch (Exception e) {
+ showError(e);
+ }
+ return null;
+ }
+
+ private void showError(Exception e) {
+ String title = "Exception while opening GitHub Flavored Markdown View";
+ String message = title+" (code.satyagraha.gfm.viewer.views.GfmView)"
+ +"\nCheck Error Log View and continue at https://github.com/winterstein/Eclipse-Markdown-Editor-Plugin/issues/42"
+ +"\n\nYou can also right-click file in Project Explorer"
+ +"\n and select \"Show in GFM view\".";
+ LogUtil.error(message, e);
+ MessageDialog.openError(Display.getDefault().getActiveShell(), title , message);
+ }
+}
--- /dev/null
+package winterwell.markdown.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+import winterwell.markdown.LogUtil;
+
+public class OpenMdView extends AbstractHandler {
+
+ @Override
+ public Object execute(final ExecutionEvent event) throws ExecutionException {
+ try {
+ IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage();
+ String mdViewId = "winterwell.markdown.views.MarkdownPreview";
+ IViewPart mdView = activePage.showView(mdViewId);
+ activePage.activate(mdView);
+ } catch (PartInitException e) {
+ showError(e);
+ } catch (Exception e) {
+ showError(e);
+ }
+ return null;
+ }
+
+ private void showError(Exception e) {
+ String title = "Exception while opening Markdown View";
+ String message = title+" (winterwell.markdown.views.MarkdownPreview)"
+ +"\nCheck Error Log View";
+ LogUtil.error(message, e);
+ MessageDialog.openError(Display.getDefault().getActiveShell(), title , message);
+ }
+}
--- /dev/null
+package winterwell.markdown.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+
+public class Preferences extends AbstractHandler {
+
+ @Override
+ public Object execute(final ExecutionEvent event) throws ExecutionException {
+ PreferenceDialog pref = PreferencesUtil.createPreferenceDialogOn(
+ PlatformUI.getWorkbench().getDisplay().getActiveShell(),
+ "winterwell.markdown.preferences.MarkdownPreferencePage", null, null);
+ pref.open();
+ return null;
+ }
+}
--- /dev/null
+package winterwell.markdown.editors;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.editors.text.TextEditorActionContributor;
+
+import winterwell.markdown.views.MarkdownPreview;
+
+public class ActionBarContributor extends TextEditorActionContributor {
+
+ private static IEditorPart activeEditor = null;
+
+// IAction print = new PrintAction();
+
+ public void setActiveEditor(IEditorPart targetEditor) {
+ super.setActiveEditor(targetEditor);
+ activeEditor = targetEditor;
+ // add print action
+ IActionBars bars= getActionBars();
+ if (bars != null) {
+// todo bars.setGlobalActionHandler(ActionFactory.PRINT.getId(), print);
+// bars.updateActionBars();
+ }
+ // Update preview?
+ if (MarkdownPreview.preview != null) {
+ MarkdownPreview.preview.update();
+ }
+ }
+ public static IEditorPart getActiveEditor() {
+ return activeEditor;
+ }
+
+ @Override
+ public void contributeToMenu(IMenuManager menu) {
+ super.contributeToMenu(menu);
+ // Add format action
+ IMenuManager edit = menu.findMenuUsingPath("edit");
+ if (edit != null) {
+ edit.add(new FormatAction());
+ }
+ // Add Export action
+ IMenuManager file = menu.findMenuUsingPath("file");
+ if (file != null) {
+ file.appendToGroup("import.ext", new ExportHTMLAction());
+ }
+ }
+
+}
--- /dev/null
+package winterwell.markdown.editors;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public class ColorManager {
+
+ protected Map fColorTable = new HashMap(10);
+
+ public void dispose() {
+ Iterator e = fColorTable.values().iterator();
+ while (e.hasNext())
+ ((Color) e.next()).dispose();
+ }
+ public Color getColor(RGB rgb) {
+ Color color = (Color) fColorTable.get(rgb);
+ if (color == null) {
+ color = new Color(Display.getCurrent(), rgb);
+ fColorTable.put(rgb, color);
+ }
+ return color;
+ }
+}
--- /dev/null
+/**\r
+ * Copyright winterwell Mathematics Ltd.\r
+ * @author Daniel Winterstein\r
+ * 11 Jan 2007\r
+ */\r
+package winterwell.markdown.editors;\r
+\r
+import org.eclipse.core.runtime.Assert;\r
+import org.eclipse.jface.text.rules.ICharacterScanner;\r
+import org.eclipse.jface.text.rules.IRule;\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.MultiLineRule;\r
+import org.eclipse.jface.text.rules.Token;\r
+\r
+/**\r
+ * \r
+ *\r
+ * @author Daniel Winterstein\r
+ */\r
+public class EmphasisRule implements IRule {\r
+ private static char[][] fDelimiters = null;\r
+ private char[] fSequence;\r
+ protected IToken fToken;\r
+\r
+\r
+ public EmphasisRule(String marker, IToken token) {\r
+ assert marker.equals("*") || marker.equals("_") || marker.equals("**")\r
+ || marker.equals("***") || marker.equals("`") || marker.equals("``");\r
+ Assert.isNotNull(token);\r
+ fSequence = marker.toCharArray();\r
+ fToken = token;\r
+ }\r
+ \r
+ // Copied from org.eclipse.jface.text.rules.PatternRule\r
+ protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) {\r
+ for (int i = 1; i < sequence.length; i++) {\r
+ int c = scanner.read();\r
+ if (c == ICharacterScanner.EOF && eofAllowed) {\r
+ return true;\r
+ } else if (c != sequence[i]) {\r
+ // Non-matching character detected, rewind the scanner back to\r
+ // the start.\r
+ // Do not unread the first character.\r
+ for (int j = i; j > 0; j--)\r
+ scanner.unread();\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /*\r
+ * @see IRule#evaluate(ICharacterScanner)\r
+ * \r
+ * @since 2.0\r
+ */\r
+ public IToken evaluate(ICharacterScanner scanner) {\r
+ // Should be connected only on the right side\r
+ scanner.unread();\r
+ boolean sawSpaceBefore = Character.isWhitespace(scanner.read());\r
+ if (!sawSpaceBefore && scanner.getColumn() != 0) {\r
+ return Token.UNDEFINED;\r
+ }\r
+\r
+ int c = scanner.read();\r
+ // Should be connected only on right side\r
+ if (c != fSequence[0] || !sequenceDetected(scanner, fSequence, false)) {\r
+ scanner.unread();\r
+ return Token.UNDEFINED;\r
+ }\r
+ int readCount = fSequence.length;\r
+ if (fDelimiters == null) {\r
+ fDelimiters = scanner.getLegalLineDelimiters();\r
+ }\r
+ // Start sequence detected\r
+ int delimiterFound = 0;\r
+ // Is it a list item marker, or just a floating *?\r
+ if (sawSpaceBefore) {\r
+ boolean after = Character.isWhitespace(scanner.read());\r
+ scanner.unread();\r
+ if (after)\r
+ delimiterFound = 2;\r
+ }\r
+\r
+ while (delimiterFound < 2\r
+ && (c = scanner.read()) != ICharacterScanner.EOF) {\r
+ readCount++;\r
+\r
+ if (!sawSpaceBefore && c == fSequence[0]\r
+ && sequenceDetected(scanner, fSequence, false)) {\r
+ return fToken;\r
+ }\r
+\r
+ int i;\r
+ for (i = 0; i < fDelimiters.length; i++) {\r
+ if (c == fDelimiters[i][0]\r
+ && sequenceDetected(scanner, fDelimiters[i], true)) {\r
+ delimiterFound++;\r
+ break;\r
+ }\r
+ }\r
+ if (i == fDelimiters.length)\r
+ delimiterFound = 0;\r
+ sawSpaceBefore = Character.isWhitespace(c);\r
+ }\r
+ // Reached ICharacterScanner.EOF\r
+ for (; readCount > 0; readCount--)\r
+ scanner.unread();\r
+ return Token.UNDEFINED;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package winterwell.markdown.editors;
+
+import java.io.File;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPathEditorInput;
+
+import winterwell.utils.io.FileUtils;
+
+
+public class ExportHTMLAction extends Action {
+ public ExportHTMLAction() {
+ super("Export to HTML");
+ }
+ @Override
+ public void run() {
+ IEditorPart ed = ActionBarContributor.getActiveEditor();
+ if (!(ed instanceof MarkdownEditor)) {
+ return;
+ }
+ MarkdownEditor editor = (MarkdownEditor) ed;
+ IEditorInput i = editor.getEditorInput();
+ if (i instanceof IPathEditorInput) {
+ IPathEditorInput input = (IPathEditorInput) i;
+ IPath path = input.getPath();
+ path = path.removeFileExtension();
+ path = path.addFileExtension("html");
+ File file = path.toFile();
+ String html = editor.getMarkdownPage().html();
+ FileUtils.write(file, html);
+ }
+ }
+
+}
--- /dev/null
+package winterwell.markdown.editors;
+
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.source.ISourceViewer;
+
+import winterwell.markdown.pagemodel.MarkdownFormatter;
+import winterwell.markdown.pagemodel.MarkdownPage;
+import winterwell.markdown.pagemodel.MarkdownPage.KLineType;
+import winterwell.utils.containers.IntRange;
+
+/**
+ * TODO An action for formatting text (via hard wrapping, i.e. inserting returns).
+ *
+ *
+ * @author daniel
+ */
+public class FormatAction extends Action implements IHandler {
+
+ public FormatAction() {
+ super("&Format paragraph");
+ setActionDefinitionId("winterwell.markdown.formatParagraphCommand");
+ setToolTipText("Format the paragraph under the caret by inserting/removing line-breaks");
+ }
+
+ @Override
+ public void run() {
+ try {
+ MarkdownEditor ed = (MarkdownEditor) ActionBarContributor.getActiveEditor();
+ if (ed == null) return; // The active editor is not a markdown editor.
+ int cols = ed.getPrintColumns();
+ // Do we have a selection?
+ ITextSelection s = (ITextSelection) ed.getSelectionProvider().getSelection();
+ if (s != null && s.getLength() > 0) {
+ formatSelectedRegion(ed, s, cols);
+ return;
+ }
+ // Where is the caret?
+ ISourceViewer viewer = ed.getViewer();
+ int caretOffset = viewer.getTextWidget().getCaretOffset();
+ int lineNum = ed.getDocument().getLineOfOffset(caretOffset);
+ // Get a paragraph region
+ MarkdownPage page = ed.getMarkdownPage();
+ IRegion pRegion = getParagraph(page, lineNum, ed.getDocument());
+ if (pRegion==null) {
+ // Not in a paragraph - so give up
+ // TODO tell the user why we've given up
+ return;
+ }
+ String paragraph = ed.getDocument().get(pRegion.getOffset(), pRegion.getLength());
+ // Format
+ String formatted = MarkdownFormatter.format(paragraph, cols);
+ if (formatted.equals(paragraph)) return; // No change!
+ // Replace the unformatted region with the new formatted one
+ ed.getDocument().replace(pRegion.getOffset(), pRegion.getLength(), formatted);
+ // Done
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ }
+
+ private void formatSelectedRegion(MarkdownEditor ed, ITextSelection s, int cols)
+ throws BadLocationException {
+ int start = s.getStartLine();
+ int end = s.getEndLine();
+ IDocument doc = ed.getDocument();
+ int soff = doc.getLineOffset(start);
+ int eoff = lineEndOffset(end, doc);
+ IntRange editedRegion = new IntRange(soff, eoff);
+ MarkdownPage page = ed.getMarkdownPage();
+ StringBuilder sb = new StringBuilder(s.getLength());
+ for(int i=start; i<=end; i++) {
+ IRegion para = getParagraph(page, i, ed.getDocument());
+ if (para==null) {
+ sb.append(page.getText().get(i));
+ continue;
+ }
+ String paragraph = ed.getDocument().get(para.getOffset(), para.getLength());
+// int lines = StrUtils.splitLines(paragraph).length;
+ String formatted = MarkdownFormatter.format(paragraph, cols);
+ // append formatted and move forward
+ sb.append(formatted);
+ CharSequence le = lineEnd(i, doc);
+ sb.append(le);
+ int pEnd = doc.getLineOfOffset(para.getOffset()+para.getLength());
+ i = pEnd;
+ // Adjust edited region?
+ IntRange pr = new IntRange(para.getOffset(),
+ para.getOffset()+para.getLength()+le.length());
+ editedRegion = new IntRange(Math.min(pr.low, editedRegion.low),
+ Math.max(pr.high, editedRegion.high));
+ }
+ // Replace the unformatted region with the new formatted one
+ String old = doc.get(editedRegion.low, editedRegion.size());
+ String newText = sb.toString();
+ if (old.equals(newText)) return;
+ ed.getDocument().replace(editedRegion.low, editedRegion.size(), newText);
+ }
+
+ private CharSequence lineEnd(int line, IDocument doc) throws BadLocationException {
+ int eoff = doc.getLineOffset(line) + doc.getLineInformation(line).getLength();
+ char c = doc.getChar(eoff);
+ if (c=='\r' && doc.getLength() > eoff+1
+ && doc.getChar(eoff+1) =='\n') return "\r\n";
+ return ""+c;
+ }
+
+ private int lineEndOffset(int end, IDocument doc)
+ throws BadLocationException {
+ int eoff = doc.getLineOffset(end) + doc.getLineInformation(end).getLength();
+ // Include line end
+ char c = doc.getChar(eoff);
+ if (c=='\r' && doc.getLength() > eoff+1
+ && doc.getChar(eoff+1) =='\n') eoff += 2;
+ else eoff += 1;
+ return eoff;
+ }
+
+ /**
+ *
+ * @param page
+ * @param lineNum
+ * @param doc
+ * @return region of paragraph containing this line, or null
+ * @throws BadLocationException
+ */
+ private IRegion getParagraph(MarkdownPage page, int lineNum, IDocument doc)
+ throws BadLocationException {
+ // Get doc info
+ List<String> lines = page.getText();
+ List<KLineType> lineInfo = page.getLineTypes();
+ // Check we are in a paragraph or list
+ KLineType pType = lineInfo.get(lineNum);
+ switch(pType) {
+ case NORMAL: break;
+ default: // Not in a paragraph, so we cannot format.
+ return null;
+ }
+ // Work out the paragraph
+ // Beginning
+ int start;
+ for(start=lineNum; start>-1; start--) {
+ if (lineInfo.get(start) != pType) {
+ start++;
+ break;
+ }
+ }
+ // End
+ int end;
+ for(end=lineNum; end<lines.size(); end++) {
+ if (lineInfo.get(end) != pType) {
+ end--;
+ break;
+ }
+ }
+ // Get offset info
+ int sOff = doc.getLineOffset(start);
+ IRegion endLine = doc.getLineInformation(end); // exclude final line end
+ int eOff = endLine.getOffset()+endLine.getLength();
+ return new Region(sOff, eOff-sOff);
+ }
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // Ignore
+ }
+
+ public void dispose() {
+ // Ignore
+ }
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ run();
+ return null;
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // Ignore
+ }
+
+}
--- /dev/null
+/**\r
+ * Copyright winterwell Mathematics Ltd.\r
+ * @author Daniel Winterstein\r
+ * 11 Jan 2007\r
+ */\r
+package winterwell.markdown.editors;\r
+\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.PatternRule;\r
+\r
+/**\r
+ * \r
+ *\r
+ * @author Daniel Winterstein\r
+ */\r
+public class HeaderRule extends PatternRule {\r
+ \r
+ public HeaderRule(IToken token) { \r
+ super("#", null, token, (char) 0, true, true);\r
+ setColumnConstraint(0);\r
+ }\r
+}\r
--- /dev/null
+/**\r
+ * @author Telmo Brugnara\r
+ * 10 Feb 2014\r
+ */\r
+package winterwell.markdown.editors;\r
+\r
+import org.eclipse.jface.text.rules.ICharacterScanner;\r
+import org.eclipse.jface.text.rules.IRule;\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.Token;\r
+\r
+public class HeaderWithUnderlineRule implements IRule {\r
+\r
+ IToken successToken = null;\r
+ \r
+ public HeaderWithUnderlineRule(IToken token) {\r
+ successToken = token;\r
+ }\r
+ \r
+ public IToken evaluate(ICharacterScanner scanner) {\r
+ int c = -1;\r
+ int scanCount = 0;\r
+ if (scanner.getColumn()==0) {\r
+ do {\r
+ c = scanner.read();\r
+ scanCount++;\r
+ } while (!isNewLine((char) c) && c != ICharacterScanner.EOF);\r
+ if(c == ICharacterScanner.EOF) {\r
+ // is not a header\r
+ for(int i=0;i<scanCount;i++) { scanner.unread(); }\r
+ return Token.UNDEFINED;\r
+ }\r
+ c = scanner.read();\r
+ scanCount++;\r
+ if(c == '\r') {\r
+ c = scanner.read();\r
+ scanCount++;\r
+ }\r
+ if(!isUnderline((char) c)) {\r
+ // is not a header\r
+ for(int i=0;i<scanCount;i++) { scanner.unread(); }\r
+ return Token.UNDEFINED;\r
+ }\r
+ do {\r
+ c = scanner.read();\r
+ scanCount++;\r
+ if(isNewLine((char) c) || c == ICharacterScanner.EOF) {\r
+ //scanner.unread();\r
+ return successToken;\r
+ }\r
+ if(!isUnderline((char) c) && !isWhitespace((char) c) && c != '\r') {\r
+ // is not a header\r
+ for(int i=0;i<scanCount;i++) { scanner.unread(); }\r
+ return Token.UNDEFINED;\r
+ }\r
+ } while (true);\r
+ }\r
+\r
+ return Token.UNDEFINED;\r
+ }\r
+ \r
+ boolean isNewLine(char c) {\r
+ return c == '\n';\r
+ }\r
+\r
+ boolean isUnderline(char c) {\r
+ return c == '=' || c == '-';\r
+ }\r
+\r
+ boolean isWhitespace(char c) {\r
+ return c == ' ' || c == '\t';\r
+ }\r
+}\r
--- /dev/null
+/**
+ * Copyright winterwell Mathematics Ltd.
+ * @author Daniel Winterstein
+ * 11 Jan 2007
+ */
+package winterwell.markdown.editors;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.core.runtime.Assert;
+
+/**
+ *
+ *
+ * @author Amir Pakdel
+ */
+public class LinkRule implements IRule {
+ private static char[][] fDelimiters = null;
+ protected IToken fToken;
+
+ public LinkRule(IToken token) {
+ Assert.isNotNull(token);
+ fToken= token;
+ }
+
+ /*
+ * @see IPredicateRule#getSuccessToken()
+ * @since 2.0
+ */
+ public IToken getSuccessToken() {
+ return fToken;
+ }
+
+
+ // Copied from org.eclipse.jface.text.rules.PatternRule
+ protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) {
+ for (int i= 1; i < sequence.length; i++) {
+ int c= scanner.read();
+ if (c == ICharacterScanner.EOF && eofAllowed) {
+ return true;
+ } else if (c != sequence[i]) {
+ // Non-matching character detected, rewind the scanner back to the start.
+ // Do not unread the first character.
+ scanner.unread();
+ for (int j= i-1; j > 0; j--)
+ scanner.unread();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * @see IRule#evaluate(ICharacterScanner)
+ * @since 2.0
+ */
+ public IToken evaluate(ICharacterScanner scanner) {
+ int c;
+ if ((c = scanner.read()) != '[') {
+ if ((c != 'h' || ( !sequenceDetected(scanner, "http://".toCharArray(), false) && !sequenceDetected(scanner, "https://".toCharArray(), false) ))
+ && (c != 'f' || !sequenceDetected(scanner, "ftp://".toCharArray(), false)) ) {
+ // Not even a non-standard link
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+ //+ preventing NPE (Non-standard link should not be below as comment above suggests) by Paul Verest
+ if (fDelimiters == null) {
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+ // Non-standard link
+ while ((c = scanner.read()) != ICharacterScanner.EOF && !Character.isWhitespace(c)) {
+ for (int i = 0; i < fDelimiters.length; i++) {
+ if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) {
+ return fToken;
+ }
+ }
+ }
+ return fToken;
+ }
+ if (fDelimiters == null) {
+ fDelimiters = scanner.getLegalLineDelimiters();
+ }
+ int readCount = 1;
+
+ // Find '](' and then find ')'
+ boolean sequenceFound = false;
+ int delimiterFound = 0;
+ while ((c = scanner.read()) != ICharacterScanner.EOF && delimiterFound < 2) {
+ readCount++;
+ if ( !sequenceFound && c == ']') {
+ c = scanner.read();
+ if (c == '(') {
+ readCount++;
+ sequenceFound = true;
+ } else {
+ scanner.unread();
+ }
+ } else if (c == ')') { // '](' is already found
+ return fToken;
+ }
+
+ int i;
+ for (i = 0; i < fDelimiters.length; i++) {
+ if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) {
+ delimiterFound ++;
+ break;
+ }
+ }
+ if (i == fDelimiters.length)
+ delimiterFound = 0;
+ }
+
+ for (; readCount > 0; readCount--)
+ scanner.unread();
+ return Token.UNDEFINED;
+ }
+
+}
--- /dev/null
+/**\r
+ * Copyright winterwell Mathematics Ltd.\r
+ * @author Daniel Winterstein\r
+ * 11 Jan 2007\r
+ */\r
+package winterwell.markdown.editors;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Arrays;\r
+\r
+import org.eclipse.core.runtime.Assert;\r
+import org.eclipse.jface.text.rules.ICharacterScanner;\r
+import org.eclipse.jface.text.rules.IRule;\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.Token;\r
+\r
+/**\r
+ * \r
+ *\r
+ * @author Daniel Winterstein\r
+ */\r
+public class ListRule implements IRule {\r
+ private ArrayList<Integer> markerList;\r
+ protected IToken fToken;\r
+ \r
+ public ListRule(IToken token) { \r
+ Assert.isNotNull(token);\r
+ fToken= token;\r
+ }\r
+ \r
+\r
+ /*\r
+ * @see IRule#evaluate(ICharacterScanner)\r
+ * @since 2.0\r
+ */\r
+ public IToken evaluate(ICharacterScanner scanner) {\r
+ if (scanner.getColumn() != 0) {\r
+ return Token.UNDEFINED;\r
+ }\r
+// // Fast mode\r
+// if (scanner.read() != '-') {\r
+// scanner.unread();\r
+// return Token.UNDEFINED;\r
+// }\r
+// if (Character.isWhitespace(scanner.read())) {\r
+// return fToken;\r
+// }\r
+// scanner.unread();\r
+// scanner.unread();\r
+// return Token.UNDEFINED;\r
+// // Fast mode\r
+ int readCount = 0;\r
+ int c;\r
+ while ((c = scanner.read()) != ICharacterScanner.EOF) {\r
+ readCount++;\r
+ if( !Character.isWhitespace( c ) ) {\r
+ int after = scanner.read();\r
+// readCount++;\r
+ scanner.unread();\r
+// if ( markerList.contains(c) && Character.isWhitespace( after ) ) {\r
+ if ( (c == '-' || c == '+' || c == '*') \r
+ && Character.isWhitespace( after ) ) {\r
+ return fToken;\r
+ } else {\r
+ for (; readCount > 0; readCount--)\r
+ scanner.unread();\r
+ return Token.UNDEFINED;\r
+ }\r
+ }\r
+ }\r
+ // Reached ICharacterScanner.EOF\r
+ for (; readCount > 0; readCount--)\r
+ scanner.unread();\r
+ return Token.UNDEFINED;\r
+ }\r
+}\r
--- /dev/null
+package winterwell.markdown.editors;
+
+import org.eclipse.swt.graphics.RGB;
+
+public interface MDColorConstants {
+ RGB COMMENT = new RGB(128, 0, 0);
+ RGB HEADER = new RGB(0, 0, 128);
+ RGB DEFAULT = new RGB(0, 0, 0);
+}
--- /dev/null
+package winterwell.markdown.editors;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+
+public class MDConfiguration extends TextSourceViewerConfiguration {
+ private ColorManager colorManager;
+
+ public MDConfiguration(ColorManager colorManager, IPreferenceStore prefStore) {
+ super(prefStore);
+ this.colorManager = colorManager;
+ }
+
+ @Override
+ public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+ MDScanner scanner = new MDScanner(colorManager);
+ PresentationReconciler pr = (PresentationReconciler) super.getPresentationReconciler(sourceViewer); // FIXME
+ DefaultDamagerRepairer ddr = new DefaultDamagerRepairer(scanner);
+ pr.setRepairer(ddr, IDocument.DEFAULT_CONTENT_TYPE);
+ pr.setDamager(ddr, IDocument.DEFAULT_CONTENT_TYPE);
+ return pr;
+ }
+
+
+ @Override
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ // This awful mess adds in update support
+ // Get super strategy
+ IReconciler rs = super.getReconciler(sourceViewer);
+ if (true) return rs; // Seems to work fine?!
+ final IReconcilingStrategy fsuperStrategy = rs==null? null : rs.getReconcilingStrategy("text");
+ // Add our own
+ IReconcilingStrategy strategy = new IReconcilingStrategy() {
+ private IDocument doc;
+ public void reconcile(IRegion partition) {
+ MarkdownEditor ed = MarkdownEditor.getEditor(doc);
+ if (ed != null) ed.updatePage(partition);
+ if (fsuperStrategy!=null) fsuperStrategy.reconcile(partition);
+ }
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ MarkdownEditor ed = MarkdownEditor.getEditor(doc);
+ if (ed != null) ed.updatePage(subRegion);
+ if (fsuperStrategy!=null) fsuperStrategy.reconcile(dirtyRegion, subRegion);
+ }
+ public void setDocument(IDocument document) {
+ this.doc = document;
+ if (fsuperStrategy!=null) fsuperStrategy.setDocument(document);
+ }
+ };
+ // Make a reconciler
+ MonoReconciler m2 = new MonoReconciler(strategy, true);
+ m2.setIsIncrementalReconciler(true);
+ m2.setProgressMonitor(new NullProgressMonitor());
+ m2.setDelay(500);
+ // Done
+ return m2;
+ }
+
+ @SuppressWarnings("unused")
+ @Override
+ public ITextHover getTextHover(ISourceViewer sourceViewer,
+ String contentType) {
+ if (true) return super.getTextHover(sourceViewer, contentType);
+ // Add hover support for images
+ return new MDTextHover();
+ }
+}
+
+
--- /dev/null
+/**\r
+ * Copyright winterwell Mathematics Ltd.\r
+ * @author Daniel Winterstein\r
+ * 13 Jan 2007\r
+ */\r
+package winterwell.markdown.editors;\r
+\r
+import org.eclipse.jface.preference.IPreferenceStore;\r
+import org.eclipse.jface.preference.PreferenceConverter;\r
+import org.eclipse.jface.text.TextAttribute;\r
+import org.eclipse.jface.text.rules.IRule;\r
+import org.eclipse.jface.text.rules.IWhitespaceDetector;\r
+import org.eclipse.jface.text.rules.MultiLineRule;\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.swt.SWT;\r
+\r
+import winterwell.markdown.Activator;\r
+import winterwell.markdown.preferences.MarkdownPreferencePage;\r
+\r
+/**\r
+ * \r
+ *\r
+ * @author Daniel Winterstein\r
+ */\r
+public class MDScanner extends RuleBasedScanner {\r
+ ColorManager cm;\r
+ public MDScanner(ColorManager cm) {\r
+ this.cm = cm;\r
+ IPreferenceStore pStore = Activator.getDefault().getPreferenceStore();\r
+ Token heading = new Token(new TextAttribute(cm.getColor(PreferenceConverter.getColor(pStore, MarkdownPreferencePage.PREF_HEADER)), null, SWT.BOLD));\r
+ Token comment = new Token(new TextAttribute(cm.getColor(PreferenceConverter.getColor(pStore, MarkdownPreferencePage.PREF_COMMENT))));\r
+ Token emphasis = new Token(new TextAttribute(cm.getColor(PreferenceConverter.getColor(pStore, MarkdownPreferencePage.PREF_DEFUALT)), null, SWT.ITALIC));\r
+ Token list = new Token(new TextAttribute(cm.getColor(PreferenceConverter.getColor(pStore, MarkdownPreferencePage.PREF_HEADER)), null, SWT.BOLD));\r
+ Token link = new Token(new TextAttribute(cm.getColor(PreferenceConverter.getColor(pStore, MarkdownPreferencePage.PREF_LINK)), null, TextAttribute.UNDERLINE));\r
+ Token code = new Token(new TextAttribute(\r
+ cm.getColor(PreferenceConverter.getColor(pStore, MarkdownPreferencePage.PREF_CODE)),\r
+ cm.getColor(PreferenceConverter.getColor(pStore, MarkdownPreferencePage.PREF_CODE_BG)),\r
+ SWT.NORMAL));\r
+ setRules(new IRule[] {\r
+ new LinkRule(link),\r
+ new HeaderRule(heading),\r
+ new HeaderWithUnderlineRule(heading),\r
+ new ListRule(list),\r
+ new EmphasisRule("_", emphasis),\r
+ new EmphasisRule("***", emphasis),\r
+ new EmphasisRule("**", emphasis),\r
+ new EmphasisRule("*", emphasis),\r
+ new EmphasisRule("``", code),\r
+ new EmphasisRule("`", code),\r
+ new MultiLineRule("<!--", "-->", comment),\r
+ // WhitespaceRule messes up with the rest of rules\r
+// new WhitespaceRule(new IWhitespaceDetector() {\r
+// public boolean isWhitespace(char c) {\r
+// return Character.isWhitespace(c);\r
+// }\r
+// }),\r
+ });\r
+ }\r
+}\r
--- /dev/null
+/**
+ * (c) Winterwell 2010 and ThinkTank Mathematics 2007
+ */
+package winterwell.markdown.editors;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+
+import winterwell.markdown.StringMethods;
+import winterwell.utils.containers.Pair;
+
+/**
+ *
+ *
+ * @author daniel
+ */
+public class MDTextHover implements ITextHover //, ITextHoverExtension
+{
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion region) {
+ try {
+ IDocument doc = textViewer.getDocument();
+ String text = doc.get(region.getOffset(), region.getLength());
+ return "<b>"+text+"</b>";
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ try {
+ IDocument doc = textViewer.getDocument();
+ int line = doc.getLineOfOffset(offset);
+ int lineOffset = doc.getLineOffset(line);
+ int lineLength = doc.getLineLength(line);
+ String text = doc.get(lineOffset, lineLength);
+ // Look for image tags
+ Pair<Integer> altRegion;
+ Pair<Integer> urlRegion =
+ StringMethods.findEnclosingRegion(text, offset-lineOffset, '(', ')');
+ if (urlRegion==null) {
+ altRegion = StringMethods.findEnclosingRegion(text, offset-lineOffset, '[', ']');
+ if (altRegion == null) return null;
+ urlRegion = StringMethods.findEnclosingRegion(text, altRegion.second, '(', ')');
+ } else {
+ altRegion = StringMethods.findEnclosingRegion(text, urlRegion.first-1, '[', ']');
+ }
+ if (urlRegion==null || altRegion==null) return null;
+ // Is it an image link?
+ if (text.charAt(altRegion.first-1) != '!') return null;
+ Region r = new Region(urlRegion.first+1+lineOffset, urlRegion.second-urlRegion.first-2);
+ return r;
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+// public IInformationControlCreator getHoverControlCreator() {
+// return new IInformationControlCreator() {
+// public IInformationControl createInformationControl(Shell parent) {
+// int style= fIsFocusable ? SWT.V_SCROLL | SWT.H_SCROLL : SWT.NONE;
+//
+// if (BrowserInformationControl.isAvailable(parent)) {
+// final int shellStyle= SWT.TOOL | (fIsFocusable ? SWT.RESIZE : SWT.NO_TRIM);
+// return new BrowserInformationControl(parent, shellStyle, style, null);
+// }
+// return new DefaultInformationControl(parent, style, new HTMLTextPresenter());
+// }
+// };
+// }
+
+}
--- /dev/null
+/**\r
+ * Copyright winterwell Mathematics Ltd.\r
+ * @author Daniel Winterstein\r
+ * 11 Jan 2007\r
+ */\r
+package winterwell.markdown.editors;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IAction;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.DocumentEvent;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IDocumentListener;\r
+import org.eclipse.jface.text.IRegion;\r
+import org.eclipse.jface.text.Region;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.ITreeContentProvider;\r
+import org.eclipse.jface.viewers.LabelProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.ui.IActionBars;\r
+import org.eclipse.ui.part.IPageSite;\r
+import org.eclipse.ui.texteditor.IDocumentProvider;\r
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;\r
+\r
+import winterwell.markdown.pagemodel.MarkdownPage;\r
+import winterwell.markdown.pagemodel.MarkdownPage.Header;\r
+import winterwell.markdown.pagemodel.MarkdownPage.KLineType;\r
+import winterwell.utils.StrUtils;\r
+import winterwell.utils.Utils;\r
+import winterwell.utils.web.WebUtils;\r
+\r
+/**\r
+ *\r
+ *\r
+ * @author Daniel Winterstein\r
+ */\r
+public final class MarkdownContentOutlinePage extends ContentOutlinePage {\r
+\r
+ /**\r
+ *\r
+ *\r
+ * @author Daniel Winterstein\r
+ */\r
+ public final class ContentProvider implements ITreeContentProvider,\r
+ IDocumentListener {\r
+\r
+ // protected final static String SEGMENTS= "__md_segments";\r
+ // //$NON-NLS-1$\r
+ // protected IPositionUpdater fPositionUpdater= new\r
+ // DefaultPositionUpdater(SEGMENTS);\r
+ private MarkdownPage fContent;\r
+ // protected List fContent= new ArrayList(10);\r
+ private MarkdownEditor fTextEditor;\r
+\r
+ private void parse() {\r
+ fContent = fTextEditor.getMarkdownPage();\r
+ }\r
+\r
+ /*\r
+ * @see IContentProvider#inputChanged(Viewer, Object, Object)\r
+ */\r
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+ // Detach from old\r
+ if (oldInput != null) {\r
+ IDocument document = fDocumentProvider.getDocument(oldInput);\r
+ if (document != null) {\r
+ document.removeDocumentListener(this);\r
+ }\r
+ }\r
+ fContent = null;\r
+ // Attach to new\r
+ if (newInput == null)\r
+ return;\r
+ IDocument document = fDocumentProvider.getDocument(newInput);\r
+ if (document == null)\r
+ return;\r
+ fTextEditor = MarkdownEditor.getEditor(document);\r
+ document.addDocumentListener(this);\r
+ parse();\r
+ }\r
+\r
+ /*\r
+ * @see IContentProvider#dispose\r
+ */\r
+ public void dispose() {\r
+ fContent = null;\r
+ }\r
+\r
+ /*\r
+ * @see IContentProvider#isDeleted(Object)\r
+ */\r
+ public boolean isDeleted(Object element) {\r
+ return false;\r
+ }\r
+\r
+ /*\r
+ * @see IStructuredContentProvider#getElements(Object)\r
+ */\r
+ public Object[] getElements(Object element) {\r
+ return fContent.getHeadings(null).toArray();\r
+ }\r
+\r
+ /*\r
+ * @see ITreeContentProvider#hasChildren(Object)\r
+ */\r
+ public boolean hasChildren(Object element) {\r
+ if (element == fInput) {\r
+ return true;\r
+ }\r
+ if (element instanceof MarkdownPage.Header) {\r
+ MarkdownPage.Header header = (MarkdownPage.Header) element;\r
+ return header.getSubHeaders().size() > 0;\r
+ }\r
+ ;\r
+ return false;\r
+ }\r
+\r
+ /*\r
+ * @see ITreeContentProvider#getParent(Object)\r
+ */\r
+ public Object getParent(Object element) {\r
+ if (!(element instanceof MarkdownPage.Header))\r
+ return null;\r
+ return ((MarkdownPage.Header) element).getParent();\r
+ }\r
+\r
+ /*\r
+ * @see ITreeContentProvider#getChildren(Object)\r
+ */\r
+ public Object[] getChildren(Object element) {\r
+ if (element == fInput) {\r
+ return fContent.getHeadings(null).toArray();\r
+ }\r
+ if (!(element instanceof MarkdownPage.Header))\r
+ return null;\r
+ return ((MarkdownPage.Header) element).getSubHeaders().toArray();\r
+ }\r
+\r
+ public void documentAboutToBeChanged(DocumentEvent event) {\r
+ // nothing\r
+ }\r
+\r
+ public void documentChanged(DocumentEvent event) {\r
+ parse();\r
+ update();\r
+ }\r
+ }\r
+\r
+ private Object fInput = null;\r
+ private final IDocumentProvider fDocumentProvider;\r
+ private final MarkdownEditor fTextEditor;\r
+ protected boolean showWordCounts;\r
+ private List<Header> selectedHeaders;\r
+\r
+ /**\r
+ * @param documentProvider\r
+ * @param mdEditor\r
+ */\r
+ public MarkdownContentOutlinePage(IDocumentProvider documentProvider,\r
+ MarkdownEditor mdEditor) {\r
+ fDocumentProvider = documentProvider;\r
+ fTextEditor = mdEditor;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc) Method declared on ContentOutlinePage\r
+ */\r
+ @Override\r
+ public void createControl(Composite parent) {\r
+ super.createControl(parent);\r
+ TreeViewer viewer = getTreeViewer();\r
+ viewer.setContentProvider(new ContentProvider());\r
+ // Add word count annotations\r
+ viewer.setLabelProvider(new LabelProvider() {\r
+ @Override\r
+ public String getText(Object element) {\r
+ if (!(element instanceof MarkdownPage.Header))\r
+ return super.getText(element);\r
+ Header header = ((MarkdownPage.Header) element);\r
+ String hText = header.toString();\r
+ if (!showWordCounts)\r
+ return hText;\r
+ IRegion region = getRegion(header);\r
+ String text;\r
+ try {\r
+ text = fTextEditor.getDocument().get(region.getOffset(),\r
+ region.getLength());\r
+ text = WebUtils.stripTags(text);\r
+ text = text.replaceAll("#", "").trim();\r
+ assert text.startsWith(hText);\r
+ text = text.substring(hText.length());\r
+ int wc = StrUtils.wordCount(text);\r
+ return hText + " (" + wc + ":" + text.length() + ")";\r
+ } catch (BadLocationException e) {\r
+ return hText;\r
+ }\r
+ }\r
+ });\r
+ viewer.addSelectionChangedListener(this);\r
+\r
+ if (fInput != null)\r
+ viewer.setInput(fInput);\r
+\r
+ // Buttons\r
+ IPageSite site = getSite();\r
+ IActionBars bars = site.getActionBars();\r
+ IToolBarManager toolbar = bars.getToolBarManager();\r
+ // Word count action\r
+ Action action = new Action("123", IAction.AS_CHECK_BOX) {\r
+ @Override\r
+ public void run() {\r
+ showWordCounts = isChecked();\r
+ update();\r
+ }\r
+ };\r
+ action.setToolTipText("Show/hide section word:character counts");\r
+ toolbar.add(action);\r
+ // +/- actions\r
+ action = new Action("<") {\r
+ @Override\r
+ public void run() {\r
+ doPromoteDemote(-1);\r
+ }\r
+ };\r
+ action.setToolTipText("Promote the selected section\n -- move it up a level.");\r
+ toolbar.add(action);\r
+ //\r
+ action = new Action(">") {\r
+ @Override\r
+ public void run() {\r
+ doPromoteDemote(1);\r
+ }\r
+ };\r
+ action.setToolTipText("Demote the selected section\n -- move it down a level.");\r
+ toolbar.add(action);\r
+ // up/down actions\r
+ action = new Action("/\\") {\r
+ @Override\r
+ public void run() {\r
+ try {\r
+ doMove(-1);\r
+ } catch (BadLocationException e) {\r
+ throw Utils.runtime(e);\r
+ }\r
+ }\r
+ };\r
+ action.setToolTipText("Move the selected section earlier");\r
+ toolbar.add(action);\r
+ //\r
+ action = new Action("\\/") {\r
+ @Override\r
+ public void run() {\r
+ try {\r
+ doMove(1);\r
+ } catch (BadLocationException e) {\r
+ throw Utils.runtime(e);\r
+ }\r
+ }\r
+ };\r
+ action.setToolTipText("Move the selected section later");\r
+ toolbar.add(action);\r
+ // Collapse\r
+ ImageDescriptor id = ImageDescriptor.createFromFile(getClass(), "collapseall.gif");\r
+ action = new Action("collapse", id) {\r
+ @Override\r
+ public void run() {\r
+ doCollapseAll();\r
+ }\r
+ };\r
+ action.setImageDescriptor(id);\r
+ action.setToolTipText("Collapse outline tree");\r
+ toolbar.add(action);\r
+ // Sync\r
+ id = ImageDescriptor.createFromFile(getClass(), "synced.gif");\r
+ action = new Action("sync") {\r
+ @Override\r
+ public void run() {\r
+ try {\r
+ doSyncToEditor();\r
+ } catch (BadLocationException e) {\r
+ throw Utils.runtime(e);\r
+ }\r
+ }\r
+ };\r
+ action.setImageDescriptor(id);\r
+ action.setToolTipText("Link with editor");\r
+ toolbar.add(action);\r
+ // Add edit ability\r
+ viewer.getControl().addKeyListener(new KeyListener() {\r
+ public void keyPressed(KeyEvent e) {\r
+ if (e.keyCode==SWT.F2) {\r
+ doEditHeader();\r
+ }\r
+ }\r
+ public void keyReleased(KeyEvent e) {\r
+ //\r
+ }\r
+ });\r
+ }\r
+\r
+ /**\r
+ * @throws BadLocationException\r
+ *\r
+ */\r
+ protected void doSyncToEditor() throws BadLocationException {\r
+ TreeViewer viewer = getTreeViewer();\r
+ if (viewer == null) return;\r
+ // Get header\r
+ MarkdownPage page = fTextEditor.getMarkdownPage();\r
+ int caretOffset = fTextEditor.getViewer().getTextWidget().getCaretOffset();\r
+ IDocument doc = fTextEditor.getDocument();\r
+ int line = doc.getLineOfOffset(caretOffset);\r
+ List<KLineType> lineTypes = page.getLineTypes();\r
+ for(; line>-1; line--) {\r
+ KLineType lt = lineTypes.get(line);\r
+ if (lt.toString().startsWith("H")) break;\r
+ }\r
+ if (line<0) return;\r
+ Header header = (Header) page.getPageObject(line);\r
+ // Set\r
+ IStructuredSelection selection = new StructuredSelection(header);\r
+ viewer.setSelection(selection , true);\r
+ }\r
+\r
+ void doEditHeader() {\r
+ TreeViewer viewer = getTreeViewer();\r
+ viewer.editElement(selectedHeaders.get(0), 0);\r
+ }\r
+\r
+ protected void doCollapseAll() {\r
+ TreeViewer viewer = getTreeViewer();\r
+ if (viewer == null) return;\r
+// Control control = viewer.getControl();\r
+// if (control != null && !control.isDisposed()) {\r
+// control.setRedraw(false);\r
+ viewer.collapseAll();\r
+// control.setRedraw(true);\r
+// }\r
+ }\r
+\r
+ /**\r
+ * Move the selected sections up/down\r
+ * @param i 1 or -1. 1==move later, -1=earlier\r
+ * @throws BadLocationException\r
+ */\r
+ protected void doMove(int i) throws BadLocationException {\r
+ assert i==1 || i==-1;\r
+ if (selectedHeaders == null || selectedHeaders.size() == 0)\r
+ return;\r
+ // Get text region to move\r
+ MarkdownPage.Header first = selectedHeaders.get(0);\r
+ MarkdownPage.Header last = selectedHeaders.get(selectedHeaders.size()-1);\r
+ int start = fTextEditor.getDocument().getLineOffset(\r
+ first.getLineNumber());\r
+ IRegion r = getRegion(last);\r
+ int end = r.getOffset() + r.getLength();\r
+ int length = end - start;\r
+ // Get new insertion point\r
+ int insert;\r
+ if (i==1) {\r
+ Header nextSection = last.getNext();\r
+ if (nextSection==null) return;\r
+ IRegion nr = getRegion(nextSection);\r
+ insert = nr.getOffset()+nr.getLength();\r
+ } else {\r
+ Header prevSection = first.getPrevious();\r
+ if (prevSection==null) return;\r
+ IRegion nr = getRegion(prevSection);\r
+ insert = nr.getOffset();\r
+ }\r
+ // Get text\r
+ String text = fTextEditor.getDocument().get();\r
+ // Move text\r
+ String section = text.substring(start, end);\r
+ String pre, post;\r
+ if (i==1) {\r
+ pre = text.substring(0, start) + text.substring(end, insert);\r
+ post = text.substring(insert);\r
+ } else {\r
+ pre = text.substring(0, insert);\r
+ post = text.substring(insert,start)+text.substring(end);\r
+ }\r
+ text = pre + section + post;\r
+ assert text.length() == fTextEditor.getDocument().get().length() :\r
+ text.length()-fTextEditor.getDocument().get().length()+" chars gained/lost";\r
+ // Update doc\r
+ fTextEditor.getDocument().set(text);\r
+ }\r
+\r
+ /**\r
+ * Does not support -------- / ========= underlining, only # headers\r
+ * @param upDown 1 for demote (e.g. h2 -> h3), -1 for promote (e.g. h2 -> h1)\r
+ */\r
+ protected void doPromoteDemote(int upDown) {\r
+ assert upDown==1 || upDown==-1;\r
+ if (selectedHeaders == null || selectedHeaders.size() == 0)\r
+ return;\r
+ HashSet<Header> toAdjust = new HashSet<Header>(selectedHeaders);\r
+ HashSet<Header> adjusted = new HashSet<Header>();\r
+ // Adjust\r
+ MarkdownPage mdPage = fTextEditor.getMarkdownPage();\r
+ List<String> lines = new ArrayList<String>(mdPage.getText());\r
+ while(toAdjust.size() != 0) {\r
+ Header h = toAdjust.iterator().next();\r
+ toAdjust.remove(h);\r
+ adjusted.add(h);\r
+ String line = lines.get(h.getLineNumber());\r
+ if (upDown==-1) {\r
+ if (h.getLevel() == 1) return; // Level 1; can't promote\r
+ if (line.startsWith("##")) line = line.substring(1);\r
+ else {\r
+ return; // TODO support for ------ / ========\r
+ }\r
+ } else line = "#" + line;\r
+ int ln = h.getLineNumber();\r
+ lines.set(ln, line);\r
+ // kids\r
+ ArrayList<Header> kids = new ArrayList<Header>(h.getSubHeaders());\r
+ for (Header header : kids) {\r
+ if ( ! adjusted.contains(header)) toAdjust.add(header);\r
+ }\r
+ }\r
+ // Set\r
+ StringBuilder sb = new StringBuilder();\r
+ for (String line : lines) {\r
+ sb.append(line);\r
+ }\r
+ fTextEditor.getDocument().set(sb.toString());\r
+ }\r
+\r
+ /**\r
+ * The region of text for this header. This includes the header itself.\r
+ * @param header\r
+ * @return\r
+ * @throws BadLocationException\r
+ */\r
+ protected IRegion getRegion(Header header) {\r
+ try {\r
+ IDocument doc = fTextEditor.getDocument();\r
+ // Line numbers\r
+ int start = header.getLineNumber();\r
+ Header next = header.getNext();\r
+ int end;\r
+ if (next != null) {\r
+ end = next.getLineNumber() - 1;\r
+ } else {\r
+ end = doc.getNumberOfLines() - 1;\r
+ }\r
+ int offset = doc.getLineOffset(start);\r
+ IRegion ei = doc.getLineInformation(end);\r
+ int length = ei.getOffset() + ei.getLength() - offset;\r
+ return new Region(offset, length);\r
+ } catch (BadLocationException ex) {\r
+ throw Utils.runtime(ex);\r
+ }\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc) Method declared on ContentOutlinePage\r
+ */\r
+ @Override\r
+ public void selectionChanged(SelectionChangedEvent event) {\r
+ super.selectionChanged(event);\r
+ selectedHeaders = null;\r
+ ISelection selection = event.getSelection();\r
+ if (selection.isEmpty())\r
+ return;\r
+ if (!(selection instanceof IStructuredSelection))\r
+ return;\r
+ try {\r
+ IStructuredSelection strucSel = (IStructuredSelection) selection;\r
+ Object[] sections = strucSel.toArray();\r
+ selectedHeaders = (List) Arrays.asList(sections);\r
+ MarkdownPage.Header first = (Header) sections[0];\r
+ MarkdownPage.Header last = (Header) sections[sections.length - 1];\r
+ int start = fTextEditor.getDocument().getLineOffset(\r
+ first.getLineNumber());\r
+ int length;\r
+ if (first == last) {\r
+ length = fTextEditor.getDocument().getLineLength(\r
+ first.getLineNumber());\r
+ } else {\r
+ IRegion r = getRegion(last);\r
+ int end = r.getOffset() + r.getLength();\r
+ length = end - start;\r
+ }\r
+ fTextEditor.setHighlightRange(start, length, true);\r
+ } catch (Exception x) {\r
+ System.out.println(x.getStackTrace());\r
+ fTextEditor.resetHighlightRange();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Sets the input of the outline page\r
+ *\r
+ * @param input\r
+ * the input of this outline page\r
+ */\r
+ public void setInput(Object input) {\r
+ fInput = input;\r
+ update();\r
+ }\r
+\r
+ /**\r
+ * Updates the outline page.\r
+ */\r
+ public void update() {\r
+ TreeViewer viewer = getTreeViewer();\r
+\r
+ if (viewer != null) {\r
+ Control control = viewer.getControl();\r
+ if (control != null && !control.isDisposed()) {\r
+ control.setRedraw(false);\r
+ viewer.setInput(fInput);\r
+ viewer.expandAll();\r
+ control.setRedraw(true);\r
+ }\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+package winterwell.markdown.editors;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
+import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPathEditorInput;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+import winterwell.markdown.Activator;
+import winterwell.markdown.pagemodel.MarkdownPage;
+import winterwell.markdown.pagemodel.MarkdownPage.Header;
+import winterwell.markdown.preferences.MarkdownPreferencePage;
+import winterwell.markdown.views.MarkdownPreview;
+
+
+/**
+ * Text editor with markdown support.
+ * @author Daniel Winterstein
+ */
+public class MarkdownEditor extends TextEditor implements IDocumentListener
+{
+
+ /**
+ * Maximum length for a task tag message
+ */
+ private static final int MAX_TASK_MSG_LENGTH = 80;
+ private ColorManager colorManager;
+ private MarkdownContentOutlinePage fOutlinePage = null;
+
+ IDocument oldDoc = null;
+
+ private MarkdownPage page;
+
+
+ private boolean pageDirty = true;
+
+ private ProjectionSupport projectionSupport;
+ private final IPreferenceStore pStore;
+ private IPropertyChangeListener prefChangeListener;
+
+
+ public MarkdownEditor() {
+ super();
+ pStore = Activator.getDefault().getPreferenceStore();
+ colorManager = new ColorManager();
+ setSourceViewerConfiguration(new MDConfiguration(colorManager, getPreferenceStore()));
+ }
+
+
+ @Override
+ public void createPartControl(Composite parent) {
+ // Over-ride to add code-folding support
+ super.createPartControl(parent);
+ if (getSourceViewer() instanceof ProjectionViewer) {
+ ProjectionViewer viewer =(ProjectionViewer)getSourceViewer();
+ projectionSupport = new ProjectionSupport(viewer,getAnnotationAccess(),getSharedColors());
+ projectionSupport.install();
+ //turn projection mode on
+ viewer.doOperation(ProjectionViewer.TOGGLE);
+ }
+ }
+
+ /**
+ * Returns the editor's source viewer. May return null before the editor's part has been created and after disposal.
+ */
+ public ISourceViewer getViewer() {
+ return getSourceViewer();
+ }
+
+ @Override
+ protected ISourceViewer createSourceViewer(Composite parent,
+ IVerticalRuler ruler, int styles) {
+// if (true) return super.createSourceViewer(parent, ruler, styles);
+ // Create with code-folding
+ ISourceViewer viewer = new ProjectionViewer(parent, ruler,
+ getOverviewRuler(), isOverviewRulerVisible(), styles);
+ // ensure decoration support has been created and configured.
+ SourceViewerDecorationSupport decSupport = getSourceViewerDecorationSupport(viewer);
+// SourceViewer viewer = (SourceViewer) super.createSourceViewer(parent, ruler, styles);
+ // Setup word-wrapping
+ final StyledText widget = viewer.getTextWidget();
+ // Listen to pref changes
+ prefChangeListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ if (event.getProperty().equals(MarkdownPreferencePage.PREF_WORD_WRAP)) {
+ widget.setWordWrap(MarkdownPreferencePage.wordWrap());
+ }
+ }
+ };
+ pStore.addPropertyChangeListener(prefChangeListener);
+ // Switch on word-wrapping
+ if (MarkdownPreferencePage.wordWrap()) {
+ widget.setWordWrap(true);
+ }
+ return viewer;
+ }
+
+ public void dispose() {
+ if (pStore != null) {
+ pStore.removePropertyChangeListener(prefChangeListener);
+ }
+ colorManager.dispose();
+ super.dispose();
+ }
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ }
+
+ public void documentChanged(DocumentEvent event) {
+ pageDirty = true;
+ }
+
+ @Override
+ protected void doSetInput(IEditorInput input) throws CoreException {
+ // Detach from old
+ if (oldDoc!= null) {
+ oldDoc.removeDocumentListener(this);
+ if (doc2editor.get(oldDoc) == this) doc2editor.remove(oldDoc);
+ }
+ // Set
+ super.doSetInput(input);
+ // Attach as a listener to new doc
+ IDocument doc = getDocument();
+ oldDoc = doc;
+ if (doc==null) return;
+ doc.addDocumentListener(this);
+ doc2editor.put(doc, this);
+ // Initialise code folding
+ haveRunFolding = false;
+ updateSectionFoldingAnnotations(null);
+ }
+
+ @Override
+ protected void editorSaved() {
+ if (MarkdownPreview.preview != null) {
+ // Update the preview when the file is saved
+ MarkdownPreview.preview.update();
+ }
+ }
+
+ public Object getAdapter(Class required) {
+ if (IContentOutlinePage.class.equals(required)) {
+ if (fOutlinePage == null) {
+ fOutlinePage= new MarkdownContentOutlinePage(getDocumentProvider(), this);
+ if (getEditorInput() != null)
+ fOutlinePage.setInput(getEditorInput());
+ }
+ return fOutlinePage;
+ }
+ return super.getAdapter(required);
+ }
+ public IDocument getDocument() {
+ IEditorInput input = getEditorInput();
+ IDocumentProvider docProvider = getDocumentProvider();
+ return docProvider==null? null : docProvider.getDocument(input);
+ }
+ /**
+ *
+ * @return The {@link MarkdownPage} for the document being edited, or null
+ * if unavailable.
+ */
+ public MarkdownPage getMarkdownPage() {
+ if (pageDirty) updateMarkdownPage();
+ return page;
+ }
+
+ public int getPrintColumns() {
+ return getPreferenceStore().getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN);
+ }
+
+ /**
+ * @return The text of the editor's document, or null if unavailable.
+ */
+ public String getText() {
+ IDocument doc = getDocument();
+ return doc==null? null : doc.get();
+ }
+
+ private void updateMarkdownPage() {
+ String text = getText();
+ if (text==null) text="";
+ page = new MarkdownPage(text);
+ pageDirty = false;
+ }
+
+ void updateTaskTags(IRegion region) {
+ try {
+ boolean useTags = pStore.getBoolean(MarkdownPreferencePage.PREF_TASK_TAGS);
+ if (!useTags) return;
+ // Get task tags
+// IPreferenceStore peuistore = EditorsUI.getPreferenceStore();
+//// IPreferenceStore pStore_jdt = org.eclipse.jdt.core.compiler.getDefault().getPreferenceStore();
+// String tagString = peuistore.getString("org.eclipse.jdt.core.compiler.taskTags");
+ String tagString = pStore.getString(MarkdownPreferencePage.PREF_TASK_TAGS_DEFINED);
+ List<String> tags = Arrays.asList(tagString.split(","));
+ // Get resource for editor
+ IFile docFile = getResource(this);
+ // Get existing tasks
+ IMarker[] taskMarkers = docFile.findMarkers(IMarker.TASK, true, IResource.DEPTH_INFINITE);
+ List<IMarker> markers = new ArrayList<IMarker>(Arrays.asList(taskMarkers));
+// Collections.sort(markers, c) sort for efficiency
+ // Find tags in doc
+ List<String> text = getMarkdownPage().getText();
+ for(int i=1; i<=text.size(); i++) {
+ String line = text.get(i-1); // wierd off-by-one bug
+ for (String tag : tags) {
+ tag = tag.trim();
+ int tagIndex = line.indexOf(tag);
+ if (tagIndex == -1) continue;
+ IMarker exists = updateTaskTags2_checkExisting(i, tagIndex, line, markers);
+ if (exists!=null) {
+ markers.remove(exists);
+ continue;
+ }
+ IMarker marker = docFile.createMarker(IMarker.TASK);
+ //Once we have a marker object, we can set its attributes
+ marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_NORMAL);
+ String msg = line.substring(line.indexOf(tag), Math.min(tagIndex+MAX_TASK_MSG_LENGTH, line.length()-1));
+ marker.setAttribute(IMarker.MESSAGE, msg);
+ marker.setAttribute(IMarker.LINE_NUMBER, i);
+ }
+ }
+ // Remove old markers
+ for (IMarker m : markers) {
+ try {
+ m.delete();
+ } catch (Exception ex) {
+ //
+ }
+ }
+ } catch (Exception ex) {
+ //
+ }
+ }
+
+ /**
+ * Find an existing marker, if there is one.
+ * @param i
+ * @param tagIndex
+ * @param line
+ * @param markers
+ * @return
+ */
+ private IMarker updateTaskTags2_checkExisting(int i, int tagIndex,
+ String line, List<IMarker> markers) {
+ String tagMessage = line.substring(tagIndex).trim();
+ for (IMarker marker : markers) {
+ try {
+ Integer lineNum = (Integer) marker.getAttribute(IMarker.LINE_NUMBER);
+ if (i != lineNum) continue;
+ String txt = ((String) marker.getAttribute(IMarker.MESSAGE)).trim();
+ if (tagMessage.equals(txt)) return marker;
+ } catch (Exception ex) {
+ // Ignore
+ }
+ }
+ return null;
+ }
+
+
+ private IFile getResource(MarkdownEditor markdownEditor) {
+ IPathEditorInput input = (IPathEditorInput) getEditorInput();
+ IPath path = input.getPath();
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceRoot root = workspace.getRoot();
+ IFile[] files = root.findFilesForLocation(path);
+ if (files.length != 1) return null;
+ IFile docFile = files[0];
+ return docFile;
+ }
+
+
+ /**
+ * @param doc
+ * @return
+ */
+ public static MarkdownEditor getEditor(IDocument doc) {
+ return doc2editor.get(doc);
+ }
+
+ private static final Map<IDocument, MarkdownEditor> doc2editor = new HashMap<IDocument, MarkdownEditor>();
+
+
+ /**
+ * @param region
+ *
+ */
+ public void updatePage(IRegion region) {
+// if (!pageDirty) return;
+ updateTaskTags(region);
+ updateSectionFoldingAnnotations(region);
+ }
+
+
+ private static final Annotation[] ANNOTATION_ARRAY = new Annotation[0];
+
+ private static final Position[] POSITION_ARRAY = new Position[0];
+
+ private boolean haveRunFolding = false;
+ private Map<Annotation, Position> oldAnnotations = new HashMap<Annotation, Position>(0);
+
+ /**
+ * @param region can be null
+ */
+ private void updateSectionFoldingAnnotations(IRegion region) {
+ if (!haveRunFolding) region = null; // Do the whole doc
+ if ( ! (getSourceViewer() instanceof ProjectionViewer)) return;
+ ProjectionViewer viewer = ((ProjectionViewer)getSourceViewer());
+ MarkdownPage mPage = getMarkdownPage();
+ List<Header> headers = mPage.getHeadings(null);
+ // this will hold the new annotations along
+ // with their corresponding positions
+ Map<Annotation, Position> annotations = new HashMap<Annotation, Position>();
+ IDocument doc = getDocument();
+ updateSectionFoldingAnnotations2(doc, headers, annotations, doc.getLength());
+ // Filter existing ones
+ Position[] newValues = annotations.values().toArray(POSITION_ARRAY);
+ List<Annotation> deletedAnnotations = new ArrayList<Annotation>();
+ for(Entry<Annotation, Position> ae : oldAnnotations.entrySet()) {
+ Position oldp = ae.getValue();
+ boolean stillExists = false;
+ for (Position newp : newValues) {
+ if (oldp.equals(newp)) {
+ annotations.remove(newp);
+ stillExists = true;
+ break;
+ }
+ }
+ if (!stillExists && intersectsRegion(oldp, region)) {
+ deletedAnnotations.add(ae.getKey());
+ }
+ }
+ // Filter out-of-region ones
+ for(Annotation a : annotations.keySet().toArray(ANNOTATION_ARRAY)) {
+ Position p = annotations.get(a);
+ if (!intersectsRegion(p , region)) annotations.remove(a);
+ }
+ // Adjust the page
+ ProjectionAnnotationModel annotationModel = viewer.getProjectionAnnotationModel();
+ if (annotationModel==null) return;
+ annotationModel.modifyAnnotations(deletedAnnotations.toArray(ANNOTATION_ARRAY), annotations, null);
+ // Remember old values
+ oldAnnotations.putAll(annotations);
+ for (Annotation a : deletedAnnotations) {
+ oldAnnotations.remove(a);
+ }
+ haveRunFolding = true;
+ }
+
+
+ /**
+ * @param p
+ * @param region
+ * @return true if p overlaps with region, or if region is null
+ */
+ private boolean intersectsRegion(Position p, IRegion region) {
+ if (region==null) return true;
+ if (p.offset > region.getOffset()+region.getLength()) return false;
+ if (p.offset+p.length < region.getOffset()) return false;
+ return true;
+ }
+
+
+ /**
+ * Calculate where to fold, sticking the info into newAnnotations
+ * @param doc
+ * @param headers
+ * @param newAnnotations
+ * @param endParent
+ */
+ private void updateSectionFoldingAnnotations2(IDocument doc, List<Header> headers,
+ Map<Annotation, Position> newAnnotations, int endParent) {
+ for (int i=0; i<headers.size(); i++) {
+ Header header = headers.get(i);
+ ProjectionAnnotation annotation = new ProjectionAnnotation();
+ try {
+ int line = header.getLineNumber();
+ int start = doc.getLineOffset(line);
+ int end = (i==headers.size()-1)? endParent
+ : doc.getLineOffset(headers.get(i+1).getLineNumber());
+ Position position = new Position(start, end-start);
+ newAnnotations.put(annotation, position);
+ // Recurse
+ List<Header> subHeaders = header.getSubHeaders();
+ if (subHeaders.size() > 0) {
+ updateSectionFoldingAnnotations2(doc, subHeaders, newAnnotations, end);
+ }
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+ }
+ }
+
+
+}
+
+
+
+/*
+
+ <?xml version="1.0" encoding="UTF-8" ?>
+- <templates>
+ <template name="updateSWT" description="Performs an update to an SWT control in the SWT thread" context="java" enabled="true">${control}.getDisplay().syncExec(new Runnable() { public void run() { ${control}.${cursor} } });</template>
+ <template name="findView" description="Find a workbench view by ID" context="java" enabled="true" deleted="false">${viewType} ${view} = null; IWorkbenchWindow ${window} = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (${window} != null) { IWorkbenchPage ${activePage} = ${window}.getActivePage(); if (${activePage} != null) ${view} = (${viewType}) ${activePage}.findView("${viewID}"); } if (${view} != null) { ${cursor}//${todo}: Add operations for opened view }</template>
+ <template name="getActiveEditor" description="Retrieves the currently active editor in the active page" context="java" enabled="true" deleted="false">IEditorPart ${editor} = null; IWorkbenchWindow ${window} = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (${window} != null) { IWorkbenchPage ${activePage} = ${window}.getActivePage(); if (${activePage} != null) ${editor} = ${activePage}.getActiveEditor(); } if (${editor} != null) { ${cursor}//${todo}: Add operations for active editor }</template>
+ IEditorPart editor = null;
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window != null) {
+ IWorkbenchPage activePage = window.getActivePage();
+ if (activePage != null) editor = activePage.getActiveEditor();
+ }
+ if (editor != null) {
+ // todo: Add operations for active editor
+ }
+
+ <template name="openDialog" description="Creates and opens a JFace dialog" context="java" enabled="true" deleted="false">${dialogType} ${dialog} = new ${dialogType}(${cursor}); ${dialog}.create(); //${todo}: Complete dialog creation if (${dialog}.open() == Dialog.OK) { //${todo}: Perform actions on success };</template>
+ <template name="scanExtensionRegistry" description="Scans the extension registry for extensions of a given extension point" context="java" enabled="true" deleted="false">IExtensionRegistry ${registry} = Platform.getExtensionRegistry(); IExtensionPoint ${point} = ${registry}.getExtensionPoint(${pluginId}, ${expointId}); IExtension[] ${extensions} = ${point}.getExtensions(); for (int ${index} = 0; ${index} < ${extensions}.length; ${index}++) { IConfigurationElement[] ${elements} = ${extensions}[${index}].getConfigurationElements(); for (int ${index2} = 0; ${index2} < ${elements}.length; ${index2}++) { IConfigurationElement ${element} = ${elements}[${index2}]; String ${attValue} = ${element}.getAttribute(${attName}); ${cursor}//${todo}: Implement processing for configuration element } }</template>
+ <template name="showView" description="finds a workbench view by ID and shows it" context="java" enabled="true" deleted="false">${viewType} ${view} = null; IWorkbenchWindow ${window} = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (${window} != null) { IWorkbenchPage ${activePage} = ${window}.getActivePage(); if (${activePage} != null) try { ${view} = (${viewType}) ${activePage}.showView("${viewID}"); } catch (${Exception} e) { // ${todo}: handle exception } } if (${view} != null) { ${cursor} }</template>
+ <template name="signalError" description="Shows an error message in the editors status line" context="java" enabled="true" deleted="false">IEditorActionBarContributor ${contributor} = ${editor}.getEditorSite().getActionBarContributor(); if (${contributor} instanceof EditorActionBarContributor) { IActionBars ${actionBars} = ((EditorActionBarContributor) ${contributor}).getActionBars(); if (${actionBars} != null) { IStatusLineManager ${manager} = ${actionBars}.getStatusLineManager(); if (${manager} != null) ${manager}.setErrorMessage(msg); } }</template>
+ </templates>
+
+*/
\ No newline at end of file
--- /dev/null
+//package winterwell.markdown.editors;
+//
+//import java.util.List;
+//
+//import net.sf.paperclips.PaperClips;
+//import net.sf.paperclips.Print;
+//import net.sf.paperclips.PrintJob;
+//import net.sf.paperclips.TextPrint;
+//
+//import org.eclipse.core.commands.ExecutionEvent;
+//import org.eclipse.core.commands.ExecutionException;
+//import org.eclipse.core.commands.IHandler;
+//import org.eclipse.core.commands.IHandlerListener;
+//import org.eclipse.jface.action.Action;
+//import org.eclipse.jface.text.BadLocationException;
+//import org.eclipse.jface.text.DocumentEvent;
+//import org.eclipse.jface.text.IDocument;
+//import org.eclipse.jface.text.IDocumentListener;
+//import org.eclipse.jface.text.IRegion;
+//import org.eclipse.jface.text.ITextSelection;
+//import org.eclipse.jface.text.Region;
+//import org.eclipse.jface.text.source.ISourceViewer;
+//import org.eclipse.jface.viewers.ISelection;
+//import org.eclipse.swt.SWT;
+//import org.eclipse.swt.printing.PrintDialog;
+//import org.eclipse.swt.printing.PrinterData;
+//import org.eclipse.swt.widgets.Display;
+//import org.eclipse.ui.IEditorPart;
+//import org.eclipse.ui.IPropertyListener;
+//import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+//
+//import winterwell.markdown.pagemodel.MarkdownFormatter;
+//import winterwell.markdown.pagemodel.MarkdownPage;
+//import winterwell.markdown.pagemodel.MarkdownPage.KLineType;
+//import winterwell.utils.containers.Pair;
+//import winterwell.utils.containers.Range;
+//
+///**
+// * Print the file
+// *
+// *
+// * @author daniel
+// */
+//public class PrintAction extends Action {
+//
+// public PrintAction() {
+// super("Print...");
+// }
+//
+// @Override
+// public void run() {
+// try {
+// MarkdownEditor ed = (MarkdownEditor) ActionBarContributor.getActiveEditor();
+// if (ed == null) return; // The active editor is not a markdown editor.
+// PrintDialog dialog = new PrintDialog(Display.getDefault().getActiveShell(), SWT.NONE);
+// PrinterData printerData = dialog.open ();
+// if (printerData == null) return;
+// Print doc = new TextPrint(ed.getText());
+// PrintJob job = new PrintJob(ed.getTitle(), doc );
+// PaperClips.print(job, printerData);
+// // Done
+// } catch (Exception ex) {
+// System.out.println(ex);
+// }
+// }
+//
+//
+//
+// public void dispose() {
+// // Ignore
+// }
+//
+//
+//}
+//
\ No newline at end of file
--- /dev/null
+
+package winterwell.markdown.pagemodel;
+
+import java.util.List;
+
+import winterwell.utils.StrUtils;
+
+/**
+ * Formats a string that is compatible with the Markdown syntax.
+ * Strings must not include headers.
+ *
+ * @author Howard Abrams
+ */
+public class MarkdownFormatter
+{
+ // Expect everyone to simply use the public static methods...
+ private MarkdownFormatter ()
+ {
+ }
+
+ /**
+ * Formats a collection of lines to a particular width and honors typical
+ * Markdown syntax and formatting.
+ *
+ * The method <i>assumes</i> that if the first line ends with a line
+ * termination character, all the other lines will as well.
+ *
+ * @param lines A list of strings that should be formatted and wrapped.
+ * @param lineWidth The width of the page
+ * @return A string containing each
+ */
+ public static String format (List<String> lines, int lineWidth)
+ {
+ if (lines == null)
+ return null; // Should we return an empty string?
+
+ final String lineEndings;
+ if ( lines.get(0).endsWith ("\r\n") )
+ lineEndings = "\r\n";
+ else if ( lines.get(0).endsWith ("\r") )
+ lineEndings = "\r";
+ else
+ lineEndings = StrUtils.LINEEND;
+
+ final StringBuilder buf = new StringBuilder();
+ for (String line : lines) {
+ buf.append (line);
+ buf.append (' '); // We can add extra spaces with impunity, and this
+ // makes sure our lines don't run together.
+ }
+ return format ( buf.toString(), lineWidth, lineEndings );
+ }
+
+
+ /**
+ * Formats a string of text. The formatting does line wrapping at the
+ * <code>lineWidth</code> boundary, but it also honors the formatting
+ * of initial paragraph lines, allowing indentation of the entire
+ * paragraph.
+ *
+ * @param text The line of text to format
+ * @param lineWidth The width of the lines
+ * @return A string containing the formatted text.
+ */
+ public static String format ( final String text, final int lineWidth)
+ {
+ return format(text, lineWidth, StrUtils.LINEEND);
+ }
+
+ /**
+ * Formats a string of text. The formatting does line wrapping at the
+ * <code>lineWidth</code> boundary, but it also honors the formatting
+ * of initial paragraph lines, allowing indentation of the entire
+ * paragraph.
+ *
+ * @param text The line of text to format
+ * @param lineWidth The width of the lines
+ * @param lineEnding The line ending that overrides the default System value
+ * @return A string containing the formatted text.
+ */
+ public static String format (final String text, final int lineWidth, final String lineEnding)
+ {
+ return new String( format(text.toCharArray (), lineWidth, lineEnding));
+ }
+
+ /**
+ * The available cursor position states as it sits in the buffer.
+ */
+ private enum StatePosition {
+ /** The beginning of a paragraph ... the start of the buffer */
+ BEGIN_FIRST_LINE,
+
+ /** The beginning of the next line, which may be completely ignored. */
+ BEGIN_OTHER_LINE,
+
+ /** The beginning of a new line that will not be ignored, but appended. */
+ BEGIN_NEW_LINE,
+
+ /** The middle of a line. */
+ MIDDLE_OF_LINE
+ }
+
+ /**
+ * The method that does the work of formatting a string of text. The text,
+ * however, is a character array, which is more efficient to work with.
+ *
+ * TODO: Should we make the format(char[]) method public?
+ *
+ * @param text The line of text to format
+ * @param lineWidth The width of the lines
+ * @param lineEnding The line ending that overrides the default System value
+ * @return A string containing the formatted text.
+ */
+ static char[] format ( final char[] text, final int lineWidth, final String lineEnding )
+ {
+ final StringBuilder word = new StringBuilder();
+ final StringBuilder indent = new StringBuilder();
+ final StringBuilder buffer = new StringBuilder(text.length + 10);
+
+ StatePosition state = StatePosition.BEGIN_FIRST_LINE;
+ int lineLength = 0;
+
+ // There are times when we will run across a character(s) that will
+ // cause us to stop doing word wrap until we get to the
+ // "end of non-wordwrap" character(s).
+ //
+ // If this string is set to null, it tells us to "do" word-wrapping.
+ char endWordwrap1 = 0;
+ char endWordwrap2 = 0;
+
+ // We loop one character past the end of the loop, and when we get to
+ // this position, we assign 'c' to be 0 ... as a marker for the end of
+ // the string...
+
+ for (int i = 0; i <= text.length; i++)
+ {
+ final char c;
+ if (i < text.length)
+ c = text[i];
+ else
+ c = 0;
+
+ final char nextChar;
+ if (i+1 < text.length)
+ nextChar = text[i+1];
+ else
+ nextChar = 0;
+
+ // Are we actually word-wrapping?
+ if (endWordwrap1 != 0) {
+ // Did we get the ending sequence of the non-word-wrap?
+ if ( ( endWordwrap2 == 0 && c == endWordwrap1 ) ||
+ ( c == endWordwrap1 && nextChar == endWordwrap2 ) )
+ endWordwrap1 = 0;
+ buffer.append (c);
+ lineLength++;
+
+ if (endWordwrap1 == 0 && endWordwrap2 != 0) {
+ buffer.append (nextChar);
+ lineLength++;
+ i++;
+ }
+ continue;
+ }
+
+ // Check to see if we got one of our special non-word-wrapping
+ // character sequences ...
+
+ if ( c == '[' ) { // [Hyperlink]
+ endWordwrap1 = ']';
+ }
+ else if ( c == '*' && nextChar == '*' ) { // **Bold**
+ endWordwrap1 = '*';
+ endWordwrap2 = '*';
+ } // *Italics*
+ else if ( c == '*' && state == StatePosition.MIDDLE_OF_LINE ) {
+ endWordwrap1 = '*';
+ }
+ else if ( c == '`' ) { // `code`
+ endWordwrap1 = '`';
+ }
+ else if ( c == '(' && nextChar == '(' ) { // ((Footnote))
+ endWordwrap1 = ')';
+ endWordwrap2 = ')';
+ }
+ else if ( c == '!' && nextChar == '[' ) { // ![Image]
+ endWordwrap1 = ')';
+ }
+
+ // We are no longer doing word-wrapping, so tidy the situation up...
+ if (endWordwrap1 != 0) {
+ if (word.length() > 0)
+ lineLength = addWordToBuffer (lineWidth, lineEnding, word, indent, buffer, lineLength);
+ else if (buffer.length() > 0 && buffer.charAt (buffer.length()-1) != ']' )
+ buffer.append(' ');
+ // We are adding an extra space for most situations, unless we get a
+ // [link][ref] where we want them to be together without a space.
+
+ buffer.append (c);
+ lineLength++;
+ continue;
+ }
+
+ // Normal word-wrapping processing continues ...
+
+ if (state == StatePosition.BEGIN_FIRST_LINE)
+ {
+ if ( c == '\n' || c == '\r' ) { // Keep, but ignore initial line feeds
+ buffer.append (c);
+ lineLength = 0;
+ continue;
+ }
+
+ if (Character.isWhitespace (c))
+ indent.append (c);
+ else if ( (c == '*' || c == '-' || c == '.' ) &&
+ Character.isWhitespace (nextChar) )
+ indent.append (' ');
+ else if ( Character.isDigit (c) && nextChar == '.' &&
+ Character.isWhitespace (text[i+2]))
+ indent.append (' ');
+ else if ( c == '>' )
+ indent.append ('>');
+ else
+ state = StatePosition.MIDDLE_OF_LINE;
+
+ // If we are still in the initial state, then put 'er in...
+ if (state == StatePosition.BEGIN_FIRST_LINE) {
+ buffer.append (c);
+ lineLength++;
+ }
+ }
+
+ // While it would be more accurate to explicitely state the range of
+ // possibilities, with something like:
+ // EnumSet.range (StatePosition.BEGIN_OTHER_LINE, StatePosition.MIDDLE_OF_LINE ).contains (state)
+ // We know that what is left is just the BEGIN_FIRST_LINE ...
+
+ if ( state != StatePosition.BEGIN_FIRST_LINE )
+ {
+ // If not the middle of the line, then it must be at the first of a line
+ // Either BEGIN_OTHER_LINE or BEGIN_NEW_LINE
+ if (state != StatePosition.MIDDLE_OF_LINE)
+ {
+ if ( Character.isWhitespace(c) || c == '>' || c == '.' )
+ word.append (c);
+ else if ( ( ( c == '*' || c == '-' ) && Character.isWhitespace (nextChar) ) ||
+ ( Character.isDigit(c) && nextChar == '.' && Character.isWhitespace( text[i+2] ) ) ) {
+ word.append (c);
+ state = StatePosition.BEGIN_NEW_LINE;
+ }
+ else {
+ if (state == StatePosition.BEGIN_NEW_LINE) {
+ buffer.append (word);
+ lineLength = word.substring ( word.indexOf("\n")+1 ).length();
+ }
+ word.setLength (0);
+ state = StatePosition.MIDDLE_OF_LINE;
+ }
+ }
+
+ if (state == StatePosition.MIDDLE_OF_LINE)
+ {
+ // Are we at the end of a word? Then we need to calculate whether
+ // to wrap the line or not.
+ //
+ // This condition does double duty, in that is also serves to
+ // ignore multiple spaces and special characters that may be at
+ // the beginning of the line.
+ if ( Character.isWhitespace(c) || c == 0 )
+ {
+ if ( word.length() > 0) {
+ lineLength = addWordToBuffer (lineWidth, lineEnding, word, indent, buffer, lineLength);
+ }
+ // Do we we two spaces at the end of the line? Honor this...
+ else if ( c == ' ' && ( nextChar == '\r' || nextChar == '\n' ) &&
+ state != StatePosition.BEGIN_OTHER_LINE ) {
+ buffer.append (" ");
+ buffer.append (lineEnding);
+ lineLength = 0;
+ }
+
+ if ( c == '\r' || c == '\n' ) {
+ state = StatePosition.BEGIN_OTHER_LINE;
+ word.append(c);
+ }
+
+ // Linefeeds are completely ignored and just treated as whitespace,
+ // unless, of course, there are two of 'em... and of course, end of
+ // lines are simply evil on Windows machines.
+
+ if ( (c == '\n' && nextChar == '\n') || // Unix-style line-ends
+ ( c == '\r' && nextChar == '\n' && // Windows-style line-ends
+ text[i+2] == '\r' && text[i+3] == '\n' ) )
+ {
+ state = StatePosition.BEGIN_FIRST_LINE;
+ word.setLength(0);
+ indent.setLength (0);
+ lineLength = 0;
+
+ if (c == '\r') { // If we are dealing with Windows-style line-ends,
+ i++; // we need to skip past the next character...
+ buffer.append("\r\n");
+ } else
+ buffer.append(c);
+ }
+
+ } else {
+ word.append (c);
+ state = StatePosition.MIDDLE_OF_LINE;
+ }
+ }
+ }
+ }
+
+ return buffer.toString().toCharArray();
+ }
+
+ /**
+ * Adds a word to the buffer, performing word wrap if necessary.
+ * @param lineWidth The current width of the line
+ * @param lineEnding The line ending to append, if necessary
+ * @param word The word to append
+ * @param indent The indentation string to insert, if necesary
+ * @param buffer The buffer to perform all this stuff to
+ * @param lineLength The current length of the current line
+ * @return The new length of the current line
+ */
+ private static int addWordToBuffer (final int lineWidth, final String lineEnding,
+ final StringBuilder word,
+ final StringBuilder indent,
+ final StringBuilder buffer, int lineLength)
+ {
+ if ( word.length() + lineLength + 1 > lineWidth )
+ {
+ buffer.append (lineEnding);
+ buffer.append (indent);
+ buffer.append (word);
+
+ lineLength = indent.length() + word.length();
+ }
+ else {
+ if ( lineLength > indent.length() )
+ buffer.append (' ');
+ buffer.append (word);
+ lineLength += word.length() + 1;
+ }
+ word.setLength (0);
+ return lineLength;
+ }
+}
--- /dev/null
+//package winterwell.markdown.pagemodel;
+//
+//import java.util.Arrays;
+//import java.util.List;
+//
+//import junit.framework.TestCase;
+//// import winterwell.utils.MarkdownFormatter;
+//
+///**
+// * Test methods in the StringMethods utility class.
+// */
+//public class MarkdownFormatterTest extends TestCase
+//{
+// /**
+// * The local line-end string. \n on unix, \r\n on windows.
+// * I really want to run through all of these tests with both styles.
+// * We'll come back to that sort of a trick.
+// */
+// // public String LINEEND = System.getProperty("line.separator");
+// public static final String LINEEND = "\r\n";
+//
+// /**
+// * Test default word wrapping of a long line of normal text.
+// */
+// public void testFormatStringInt ()
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come to the aid of " +
+// "their coopertino lattes, and " +
+// "begin the process of singing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to the aid of" + LINEEND + // This line is 30 characters
+// "their coopertino lattes, and" + LINEEND +
+// "begin the process of singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 30, LINEEND));
+// }
+//
+// /**
+// * If the initial part of the line contains some spaces, we use that as
+// * the "indentation" for every other line.
+// * @throws Exception
+// */
+// public void testIndentOfSpaces () throws Exception
+// {
+// final String LONG_LINE =
+// " Now is the time for all good " +
+// "chickens to come to the aid of " +
+// "their coopertino lattes, and " +
+// "begin the process of singing.";
+// final String EXPECTED =
+// " Now is the time for all good" + LINEEND +
+// " chickens to come to the aid of" + LINEEND +
+// " their coopertino lattes, and" + LINEEND +
+// " begin the process of singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * Can we maintain the format of text that is already formatted?
+// * @throws Exception
+// */
+// public void testAlreadyFormatted () throws Exception
+// {
+// final String LONG_LINE =
+// " Now is the time for all good" + LINEEND +
+// " chickens to come to the aid of" + LINEEND +
+// " their coopertino lattes, and" + LINEEND +
+// " begin the process of singing.";
+// assertEquals (LONG_LINE, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * Formatting a single line is all fine and dandy, but what about
+// * formatting multiple paragraphs, that is, blank lines.
+// * @throws Exception
+// */
+// public void testMultipleParagraphs () throws Exception
+// {
+// final String LONG_LINE =
+// " Now is the time for all good " +
+// "chickens to come to their aid." + LINEEND + LINEEND +
+// " And drink coopertino lattes, and " +
+// "begin the process of singing.";
+// final String EXPECTED =
+// " Now is the time for all good" + LINEEND +
+// " chickens to come to their aid." + LINEEND + LINEEND +
+// " And drink coopertino lattes," + LINEEND +
+// " and begin the process of" + LINEEND + " singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What if the section we are formatting, begins with line feeds?
+// * Do we keep 'em? Might as well. :-)
+// * @throws Exception
+// */
+// public void testInitialLineFeeds () throws Exception
+// {
+// final String LONG_LINE = LINEEND + LINEEND + LINEEND +
+// " Now is the time for all good" + LINEEND +
+// " chickens to come to the aid of" + LINEEND +
+// " their coopertino lattes, and" + LINEEND +
+// " begin the process of singing.";
+// assertEquals (LONG_LINE, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * We need to be able to format bulleted lists appropriately.
+// * @throws Exception
+// */
+// public void testSingleBulletedList () throws Exception
+// {
+// final String LONG_LINE =
+// " * Now is the time for all good " +
+// "chickens to come to the aid of " + LINEEND +
+// "their coopertino lattes, and " +
+// "begin the process of singing.";
+// final String EXPECTED =
+// " * Now is the time for all good" + LINEEND +
+// " chickens to come to the aid of" + LINEEND +
+// " their coopertino lattes, and" + LINEEND +
+// " begin the process of singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with multiple bulleted lists.
+// * @throws Exception
+// */
+// public void testMultipleBulletedList () throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to:" + LINEEND + LINEEND +
+// " * Cluck" + LINEEND +
+// " * Sing" + LINEEND +
+// " * Drink coopertino lattes.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to:" + LINEEND + LINEEND +
+// " * Cluck" + LINEEND +
+// " * Sing" + LINEEND +
+// " * Drink coopertino lattes.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with multiple bulleted lists.
+// * @throws Exception
+// */
+// public void testMultipleDashedBulletedList () throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to:" + LINEEND + LINEEND +
+// " - Cluck" + LINEEND +
+// " - Sing" + LINEEND +
+// " - Drink coopertino lattes.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to:" + LINEEND + LINEEND +
+// " - Cluck" + LINEEND +
+// " - Sing" + LINEEND +
+// " - Drink coopertino lattes.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * Tests whether we can have nested bulleted lists.
+// * @throws Exception
+// */
+// public void testSubindentedBulletedLists () throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to:" + LINEEND + LINEEND +
+// " * Cluck, cluck, cluck till their little feets hurt:" + LINEEND +
+// " * Do it again and again and again and again." + LINEEND +
+// " * And maybe again and again if their mommy's say so." + LINEEND +
+// " * We can indent really, really, deep with three levels of subitems." + LINEEND +
+// " * But we aren't sure if this is getting ridiculous or just plain expected." + LINEEND +
+// " * Sing, sing, sing till their little voices break:" + LINEEND +
+// " * Do it again and again and again and again." + LINEEND +
+// " * And maybe again and again if their mommy's say so." + LINEEND +
+// " * Drink coopertino lattes.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to:" + LINEEND + LINEEND +
+// " * Cluck, cluck, cluck till their" + LINEEND +
+// " little feets hurt:" + LINEEND +
+// " * Do it again and again and" + LINEEND +
+// " again and again." + LINEEND +
+// " * And maybe again and again if" + LINEEND +
+// " their mommy's say so." + LINEEND +
+// " * We can indent really," + LINEEND +
+// " really, deep with three" + LINEEND +
+// " levels of subitems." + LINEEND +
+// " * But we aren't sure if this" + LINEEND +
+// " is getting ridiculous or " + LINEEND +
+// " just plain expected." + LINEEND +
+// " * Sing, sing, sing till their" + LINEEND +
+// " little voices break:" + LINEEND +
+// " * Do it again and again and" + LINEEND +
+// " again and again." + LINEEND +
+// " * And maybe again and again if" + LINEEND +
+// " their mommy's say so." + LINEEND +
+// " * Drink coopertino lattes.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * Tests whether we can have nested bulleted lists.
+// * @throws Exception
+// */
+// public void testSubindentedBulletedLists2 () throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to:" + LINEEND + LINEEND +
+// " * Cluck, cluck, cluck till their little feets hurt:" + LINEEND + LINEEND +
+// " * Do it again and again and again and again." + LINEEND + LINEEND +
+// " * And maybe again and again if their mommy's say so." + LINEEND + LINEEND +
+// " * We can indent really, really, deep with three levels of subitems." + LINEEND + LINEEND +
+// " * But we aren't sure if this is getting ridiculous or just plain expected." + LINEEND + LINEEND +
+// " * Sing, sing, sing till their little voices break:" + LINEEND + LINEEND +
+// " * Do it again and again and again and again." + LINEEND + LINEEND +
+// " * And maybe again and again if their mommy's say so." + LINEEND + LINEEND +
+// " * Drink coopertino lattes.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to:" + LINEEND + LINEEND +
+// " * Cluck, cluck, cluck till their" + LINEEND +
+// " little feets hurt:" + LINEEND + LINEEND +
+// " * Do it again and again and" + LINEEND +
+// " again and again." + LINEEND + LINEEND +
+// " * And maybe again and again if" + LINEEND +
+// " their mommy's say so." + LINEEND + LINEEND +
+// " * We can indent really," + LINEEND +
+// " really, deep with three" + LINEEND +
+// " levels of subitems." + LINEEND + LINEEND +
+// " * But we aren't sure if this" + LINEEND +
+// " is getting ridiculous or" + LINEEND +
+// " just plain expected." + LINEEND + LINEEND +
+// " * Sing, sing, sing till their" + LINEEND +
+// " little voices break:" + LINEEND + LINEEND +
+// " * Do it again and again and" + LINEEND +
+// " again and again." + LINEEND + LINEEND +
+// " * And maybe again and again if" + LINEEND +
+// " their mommy's say so." + LINEEND + LINEEND +
+// " * Drink coopertino lattes.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with a numeric list?
+// * @throws Exception
+// */
+// public void testSingleNumericList () throws Exception
+// {
+// final String LONG_LINE =
+// " 2. Now is the time for all good " +
+// "chickens to come to the aid of " +
+// "their coopertino lattes, and " +
+// "begin the process of singing.";
+// final String EXPECTED =
+// " 2. Now is the time for all good" + LINEEND +
+// " chickens to come to the aid of" + LINEEND +
+// " their coopertino lattes, and" + LINEEND +
+// " begin the process of singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with multiple bulleted lists.
+// * @throws Exception
+// */
+// public void testMultipleNumericList () throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to:" + LINEEND + LINEEND +
+// " 1. Cluck" + LINEEND +
+// " 2. Sing" + LINEEND +
+// " 3. Drink coopertino lattes.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to:" + LINEEND + LINEEND +
+// " 1. Cluck" + LINEEND +
+// " 2. Sing" + LINEEND +
+// " 3. Drink coopertino lattes.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with sections that should not be word wrapped, like
+// * the text between brackets (since they are hyperlinks).
+// * @throws Exception
+// */
+// public void testNoWordWrapBracket() throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come to [the spurious and costly][3] " +
+// "aid of their coopertino cups, " +
+// "and begin sing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to [the spurious and costly][3]" + LINEEND +
+// "aid of their coopertino cups, and" + LINEEND +
+// "begin sing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+// /**
+// * What about dealing with bracketed sections with no extra white space
+// * @throws Exception
+// */
+// public void testNoWordWrapBracket2() throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come to[the spurious and costly][3] " +
+// "aid of their coopertino cups, " +
+// "and begin sing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to[the spurious and costly][3]" + LINEEND +
+// "aid of their coopertino cups, and" + LINEEND +
+// "begin sing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with bold sections that should not be word wrapped.
+// * @throws Exception
+// */
+// public void testNoWordWrapDoubleAsterix() throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come to **the spurious and costly** " +
+// "aid of their coopertino cups, " +
+// "and begin sing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to **the spurious and costly**" + LINEEND +
+// "aid of their coopertino cups, and" + LINEEND +
+// "begin sing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with italic sections that should not be word wrapped
+// * @throws Exception
+// */
+// public void testNoWordWrapSingleAsterix() throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come to *the spurious and costly* " +
+// "aid of their coopertino cups, " +
+// "and begin sing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to *the spurious and costly*" + LINEEND +
+// "aid of their coopertino cups, and" + LINEEND +
+// "begin sing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with sections that are code should not be broken.
+// * @throws Exception
+// */
+// public void testNoWordWrapCode() throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come to `the spurious and costly` " +
+// "aid of their coopertino cups, " +
+// "and begin sing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to `the spurious and costly`" + LINEEND +
+// "aid of their coopertino cups, and" + LINEEND +
+// "begin sing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+// /**
+// * What about dealing with double parenthesis sections ... these shouldn't
+// * be broken up.
+// * @throws Exception
+// */
+// public void testNoWordWrapDoubleParens() throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come to ((the spurious and costly)) " +
+// "aid of their coopertino cups, " +
+// "and begin sing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to ((the spurious and costly))" + LINEEND +
+// "aid of their coopertino cups, and" + LINEEND +
+// "begin sing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 34, LINEEND));
+// }
+//
+//
+// /**
+// * If a line, embedded in a paragraph has two spaces at the end of the line,
+// * these need to be honored and maintained.
+// * @throws Exception
+// */
+// public void testLineBreaksHonored () throws Exception
+// {
+// final String LONG_LINE =
+// "Now is the time for all good " +
+// "chickens to come " + LINEEND +
+// "to the aid of their coopertino lattes, and " +
+// "begin the process of singing.";
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come " + LINEEND +
+// "to the aid of their coopertino" + LINEEND +
+// "lattes, and begin the process of" + LINEEND +
+// "singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 33, LINEEND));
+// }
+//
+// /**
+// * A "blockquote" in Markdown can accept > characters at the beginning
+// * of all of the lines.
+// * @throws Exception
+// */
+// public void testBlockQuoteSimple () throws Exception
+// {
+// final String LONG_LINE =
+// " > Now is the time for all good " +
+// "chickens to come to the aid of " +
+// "their coopertino <lattes>, and " +
+// "begin the process of singing.";
+// final String EXPECTED =
+// " > Now is the time for all good" + LINEEND +
+// " > chickens to come to the aid of" + LINEEND +
+// " > their coopertino <lattes>, and" + LINEEND +
+// " > begin the process of singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (LONG_LINE, 33, LINEEND));
+// }
+//
+// /**
+// * A "blockquote" in Markdown can accept > characters at the beginning
+// * of all of the lines. Can we accept a version that is already formatted?
+// * @throws Exception
+// */
+// public void testBlockQuoteAlreadyFormatted () throws Exception
+// {
+// final String EXPECTED =
+// " > Now is the time for all good" + LINEEND +
+// " > chickens to come to the aid of" + LINEEND +
+// " > their coopertino <lattes>, and" + LINEEND +
+// " > begin the process of singing.";
+// assertEquals (EXPECTED, MarkdownFormatter.format (EXPECTED, 33, LINEEND));
+// }
+//
+// /**
+// * Tests that the "list" interface works if each string does not have
+// * carriage returns.
+// * @throws Exception
+// */
+// public void testListWithoutLinefeeds () throws Exception
+// {
+// final String lineend = System.getProperty("line.separator");
+//
+// final List<String> lines = Arrays.asList ( new String[] {
+// "Now is the time for all good",
+// "chickens to come to the aid of",
+// "their coopertino lattes, and",
+// "begin the process of singing."
+// } );
+// final String EXPECTED =
+// "Now is the time for all good" + lineend +
+// "chickens to come to the aid of" + lineend + // This line is 30 characters
+// "their coopertino lattes, and" + lineend +
+// "begin the process of singing.";
+//
+// final String RESULTS = MarkdownFormatter.format (lines, 30);
+// assertEquals (EXPECTED, RESULTS);
+// }
+//
+// /**
+// * Tests that the "list" interface works if each string has carriage returns.
+// * @throws Exception
+// */
+// public void testListWithLinefeeds () throws Exception
+// {
+// final List<String> lines = Arrays.asList ( new String[] {
+// "Now is the time for all good chickens to come" + LINEEND,
+// "to the aid of" + LINEEND,
+// "their coopertino lattes, and" + LINEEND,
+// "begin the process of singing."
+// } );
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to the aid of" + LINEEND + // This line is 30 characters
+// "their coopertino lattes, and" + LINEEND +
+// "begin the process of singing.";
+//
+// final String RESULTS = MarkdownFormatter.format (lines, 30);
+// assertEquals (EXPECTED, RESULTS);
+// }
+//
+// /**
+// * Tests that we don't break up image tags.
+// * @throws Exception
+// */
+// public void testImageTags () throws Exception
+// {
+// final List<String> lines = Arrays.asList ( new String[] {
+// "Now is the time for all good chickens to come " +
+// "to the aid ![Some text description](http://www.google.com/images/logo.gif)" + LINEEND,
+// "their coopertino lattes, and" + LINEEND,
+// "begin the process of singing."
+// } );
+// final String EXPECTED =
+// "Now is the time for all good" + LINEEND +
+// "chickens to come to the aid " + // This line is 30 characters
+// "![Some text description](http://www.google.com/images/logo.gif)" + LINEEND +
+// "their coopertino lattes, and" + LINEEND +
+// "begin the process of singing.";
+//
+// final String RESULTS = MarkdownFormatter.format (lines, 30);
+// assertEquals (EXPECTED, RESULTS);
+// }
+//}
--- /dev/null
+/**\r
+ * Copyright winterwell Mathematics Ltd.\r
+ * @author Daniel Winterstein\r
+ * 11 Jan 2007\r
+ */\r
+package winterwell.markdown.pagemodel;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.jface.preference.IPreferenceStore;\r
+\r
+import winterwell.markdown.Activator;\r
+import winterwell.markdown.StringMethods;\r
+import winterwell.markdown.preferences.MarkdownPreferencePage;\r
+import winterwell.utils.FailureException;\r
+import winterwell.utils.Process;\r
+import winterwell.utils.StrUtils;\r
+import winterwell.utils.Utils;\r
+import winterwell.utils.io.FileUtils;\r
+\r
+import com.petebevin.markdown.MarkdownProcessor;\r
+\r
+/**\r
+ * Understands Markdown syntax.\r
+ * \r
+ * @author Daniel Winterstein\r
+ */\r
+public class MarkdownPage {\r
+\r
+ /**\r
+ * Strip leading and trailing #s and whitespace\r
+ * \r
+ * @param line\r
+ * @return cleaned up line\r
+ */\r
+ private String cleanHeader(String line) {\r
+ for (int j = 0; j < line.length(); j++) {\r
+ char c = line.charAt(j);\r
+ if (c != '#' && !Character.isWhitespace(c)) {\r
+ line = line.substring(j);\r
+ break;\r
+ }\r
+ }\r
+ for (int j = line.length() - 1; j > 0; j--) {\r
+ char c = line.charAt(j);\r
+ if (c != '#' && !Character.isWhitespace(c)) {\r
+ line = line.substring(0, j + 1);\r
+ break;\r
+ }\r
+ }\r
+ return line;\r
+ }\r
+\r
+ /**\r
+ * Represents information about a section header. E.g. ## Misc Warblings\r
+ * \r
+ * @author daniel\r
+ */\r
+ public class Header {\r
+ /**\r
+ * 1 = top-level (i.e. #), 2= 2nd-level (i.e. ##), etc.\r
+ */\r
+ final int level;\r
+ /**\r
+ * The text of the Header\r
+ */\r
+ final String heading;\r
+ /**\r
+ * Sub-sections, if any\r
+ */\r
+ final List<Header> subHeaders = new ArrayList<Header>();\r
+ /**\r
+ * The line on which this header occurs.\r
+ */\r
+ final int lineNumber;\r
+\r
+ public int getLineNumber() {\r
+ return lineNumber;\r
+ }\r
+\r
+ /**\r
+ * \r
+ * @return the next section (at this depth if possible), null if none\r
+ */\r
+ public Header getNext() {\r
+ if (parent == null) {\r
+ int ti = level1Headers.indexOf(this);\r
+ if (ti == -1 || ti == level1Headers.size() - 1)\r
+ return null;\r
+ return level1Headers.get(ti + 1);\r
+ }\r
+ int i = parent.subHeaders.indexOf(this);\r
+ assert i != -1 : this;\r
+ if (i == parent.subHeaders.size() - 1)\r
+ return parent.getNext();\r
+ return parent.subHeaders.get(i + 1);\r
+ }\r
+ /**\r
+ * \r
+ * @return the next section (at this depth if possible), null if none\r
+ */\r
+ public Header getPrevious() {\r
+ if (parent == null) {\r
+ int ti = level1Headers.indexOf(this);\r
+ if (ti == -1 || ti == 0)\r
+ return null;\r
+ return level1Headers.get(ti - 1);\r
+ }\r
+ int i = parent.subHeaders.indexOf(this);\r
+ assert i != -1 : this;\r
+ if (i == 0)\r
+ return parent.getPrevious();\r
+ return parent.subHeaders.get(i - 1);\r
+ }\r
+ \r
+\r
+ /**\r
+ * The parent section. Can be null.\r
+ */\r
+ private Header parent;\r
+\r
+ /**\r
+ * Create a marker for a section Header\r
+ * \r
+ * @param level\r
+ * 1 = top-level (i.e. #), 2= 2nd-level (i.e. ##), etc.\r
+ * @param lineNumber\r
+ * The line on which this header occurs\r
+ * @param heading\r
+ * The text of the Header, trimmed of #s\r
+ * @param currentHeader\r
+ * The previous Header. This is used to find the parent\r
+ * section if there is one. Can be null.\r
+ */\r
+ Header(int level, int lineNumber, String heading, Header currentHeader) {\r
+ this.lineNumber = lineNumber;\r
+ this.level = level;\r
+ this.heading = cleanHeader(heading);\r
+ // Heading Tree\r
+ setParent(currentHeader);\r
+ }\r
+\r
+ private void setParent(Header currentHeader) {\r
+ if (currentHeader == null) {\r
+ parent = null;\r
+ return;\r
+ }\r
+ if (currentHeader.level < level) {\r
+ parent = currentHeader;\r
+ parent.subHeaders.add(this);\r
+ return;\r
+ }\r
+ setParent(currentHeader.parent);\r
+ }\r
+\r
+ public Header getParent() {\r
+ return parent;\r
+ }\r
+\r
+ /**\r
+ * Sub-sections. May be zero-length, never null.\r
+ */\r
+ public List<Header> getSubHeaders() {\r
+ return subHeaders;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return heading;\r
+ }\r
+\r
+ public int getLevel() {\r
+ return level;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The raw text, broken up into individual lines.\r
+ */\r
+ private List<String> lines;\r
+\r
+ /**\r
+ * The raw text, broken up into individual lines.\r
+ */\r
+ public List<String> getText() {\r
+ return Collections.unmodifiableList(lines);\r
+ }\r
+\r
+ public enum KLineType {\r
+ NORMAL, H1, H2, H3, H4, H5, H6, BLANK,\r
+ // TODO LIST, BLOCKQUOTE,\r
+ /** A line marking Markdown info about the preceding line, e.g. ====== */\r
+ MARKER,\r
+ /** A line containing meta-data, e.g. title: My Page */\r
+ META\r
+ }\r
+\r
+ /**\r
+ * Information about each line.\r
+ */\r
+ private List<KLineType> lineTypes;\r
+ private Map<Integer,Object> pageObjects = new HashMap<Integer, Object>();\r
+\r
+ // TODO meta-data, footnotes, tables, link & image attributes\r
+ private static Pattern multiMarkdownTag = Pattern.compile("^([\\w].*):(.*)");\r
+ private Map<String, String> multiMarkdownTags = new HashMap<String, String>();\r
+ \r
+ // Regular expression for Github support\r
+ private static Pattern githubURLDetection = Pattern.compile("((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])");\r
+\r
+ /**\r
+ * The top-level headers. FIXME handle documents which have a 2nd level\r
+ * header before any 1st level ones\r
+ */\r
+ private final List<Header> level1Headers = new ArrayList<Header>();\r
+ private final IPreferenceStore pStore;\r
+\r
+ /**\r
+ * Create a page.\r
+ * \r
+ * @param text\r
+ */\r
+ public MarkdownPage(String text) {\r
+ pStore = Activator.getDefault().getPreferenceStore();\r
+ setText(text);\r
+ }\r
+\r
+ /**\r
+ * Reset the text for this page.\r
+ * \r
+ * @param text\r
+ */\r
+ private void setText(String text) {\r
+ // Get lines\r
+ lines = StringMethods.splitLines(text);\r
+ // Clean out old\r
+ level1Headers.clear();\r
+ lineTypes = new ArrayList<KLineType>(lines.size());\r
+ pageObjects.clear();\r
+ // Dummy level-1 header in case there are none \r
+ Header dummyTopHeader = new Header(1, 0, "", null);\r
+ level1Headers.add(dummyTopHeader);\r
+ Header currentHeader = dummyTopHeader; \r
+ // Identify line types \r
+ int lineNum = 0;\r
+\r
+ // Check if we should support the Multi-Markdown Metadata\r
+ boolean multiMarkdownMetadataSupport =\r
+ pStore.getBoolean(MarkdownPreferencePage.PREF_MULTIMARKDOWN_METADATA);\r
+ \r
+ // Multi-markdown header\r
+ if (multiMarkdownMetadataSupport) {\r
+ // The key is the text before the colon, and the data is the text\r
+ // after the\r
+ // colon. In the above example, notice that there are two lines of\r
+ // information\r
+ // for the Author key. If you end a line with “space-space-newline”,\r
+ // the newline\r
+ // will be included when converted to other formats.\r
+ //\r
+ // There must not be any whitespace above the metadata, and the\r
+ // metadata block\r
+ // ends with the first whitespace only line. The metadata is\r
+ // stripped from the\r
+ // document before it is passed on to the syntax parser.\r
+ \r
+ //\r
+ // Check if the Metdatas are valid\r
+ //\r
+ boolean validMetadata = true;\r
+ for (lineNum = 0; lineNum < lines.size(); lineNum++) {\r
+ String line = lines.get(lineNum);\r
+ if (Utils.isBlank(line)) {\r
+ break;\r
+ }\r
+ Matcher m = multiMarkdownTag.matcher(line);\r
+ if (!m.find()) {\r
+ if (lineNum == 0) {\r
+ // No MultiMarkdown metadata\r
+ validMetadata = false;\r
+ break;\r
+ } else if (!line.matches("^\\s.*\n")) {\r
+ // The next line was not intended (ie. it does not start\r
+ // with a whitespace)\r
+ validMetadata = false;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ // Valid Metadatas have been found. We need to retrieve these keys/values.\r
+ if (validMetadata) {\r
+ String data = "";\r
+ String tag = "";\r
+ for (lineNum = 0; lineNum < lines.size(); lineNum++) {\r
+ String line = lines.get(lineNum);\r
+ if (Utils.isBlank(line)) {\r
+ break;\r
+ }\r
+ Matcher m = multiMarkdownTag.matcher(line);\r
+ if (!m.find()) {\r
+ if (lineNum == 0) {\r
+ break;\r
+ }\r
+ // Multi-line tag\r
+ lineTypes.add(KLineType.META);\r
+ data += StrUtils.LINEEND + line.trim();\r
+ multiMarkdownTags.put(tag, data);\r
+ } else {\r
+ lineTypes.add(KLineType.META);\r
+ tag = m.group(0);\r
+ data = m.group(1).trim();\r
+ if (m.group(1).endsWith(line))\r
+ multiMarkdownTags.put(tag, data);\r
+ }\r
+ }\r
+ } else {\r
+ lineNum = 0;\r
+ }\r
+ }\r
+ for (; lineNum < lines.size(); lineNum++) {\r
+ String line = lines.get(lineNum);\r
+ // Headings\r
+ int h = numHash(line);\r
+ String hLine = line;\r
+ int hLineNum = lineNum;\r
+ int underline = -1;\r
+ if (lineNum != 0) {\r
+ underline = just(line, '=') ? 1 : just(line, '-') ? 2 : -1;\r
+ }\r
+ if (underline != -1) {\r
+ h = underline;\r
+ hLineNum = lineNum - 1;\r
+ hLine = lines.get(lineNum - 1);\r
+ lineTypes.set(hLineNum, KLineType.values()[h]);\r
+ lineTypes.add(KLineType.MARKER);\r
+ }\r
+ // Create a Header object\r
+ if (h > 0) {\r
+ if (underline == -1)\r
+ lineTypes.add(KLineType.values()[h]);\r
+ Header header = new Header(h, hLineNum, hLine, currentHeader);\r
+ if (h == 1) {\r
+ level1Headers.add(header);\r
+ }\r
+ pageObjects.put(hLineNum, header);\r
+ currentHeader = header;\r
+ continue;\r
+ }\r
+ // TODO List\r
+ // TODO Block quote\r
+ // Blank line\r
+ if (Utils.isBlank(line)) {\r
+ lineTypes.add(KLineType.BLANK);\r
+ continue;\r
+ }\r
+ // Normal\r
+ lineTypes.add(KLineType.NORMAL);\r
+ } // end line-loop\r
+ // Remove dummy header?\r
+ if (dummyTopHeader.getSubHeaders().size() == 0) {\r
+ level1Headers.remove(dummyTopHeader);\r
+ }\r
+ \r
+ boolean githubSyntaxSupport =\r
+ pStore.getBoolean(MarkdownPreferencePage.PREF_GITHUB_SYNTAX);\r
+ if (githubSyntaxSupport) {\r
+ /*\r
+ * Support Code block\r
+ */\r
+ boolean inCodeBlock = false;\r
+ for (lineNum = 0; lineNum < lines.size(); lineNum++) {\r
+ String line = lines.get(lineNum);\r
+ // Found the start or end of a code block\r
+ if (line.matches("^```.*\n")) {\r
+ // We reverse the boolean value\r
+ inCodeBlock = !inCodeBlock;\r
+\r
+ // We force the line to be blank. But we mark it as normal\r
+ // to prevent to be stripped\r
+ lines.set(lineNum, "\n");\r
+ lineTypes.set(lineNum, KLineType.NORMAL);\r
+ continue;\r
+ }\r
+ if (inCodeBlock) {\r
+ lines.set(lineNum, " " + line);\r
+ }\r
+ }\r
+ \r
+ /*\r
+ * Support for URL Detection\r
+ * We search for links that are not captured by Markdown syntax\r
+ */\r
+ for (lineNum = 0; lineNum < lines.size(); lineNum++) {\r
+ String line = lines.get(lineNum);\r
+ // When a link has been replaced we need to scan again the string\r
+ // as the offsets have changed (we add '<' and '>' to the link to\r
+ // be interpreted by the markdown library)\r
+ boolean urlReplaced;\r
+\r
+ do {\r
+ urlReplaced = false;\r
+ Matcher m = githubURLDetection.matcher(line);\r
+ while (m.find()) {\r
+ // Ignore the URL following the format <link>\r
+ if ((m.start() - 1 >= 0) && (m.end() < line.length()) &&\r
+ (line.charAt(m.start() - 1) == '<') &&\r
+ (line.charAt(m.end()) == '>'))\r
+ {\r
+ continue;\r
+ }\r
+ \r
+ // Ignore the URL following the format [description](link)\r
+ if ((m.start() - 2 >= 0) && (m.end() < line.length()) &&\r
+ (line.charAt(m.start() - 2) == ']') &&\r
+ (line.charAt(m.start() - 1) == '(') &&\r
+ (line.charAt(m.end()) == ')'))\r
+ {\r
+ continue;\r
+ }\r
+ \r
+ // Ignore the URL following the format [description](link "title")\r
+ if ((m.start() - 2 >= 0) && (m.end() + 1 < line.length()) &&\r
+ (line.charAt(m.start() - 2) == ']') &&\r
+ (line.charAt(m.start() - 1) == '(') &&\r
+ (line.charAt(m.end()) == ' ') &&\r
+ (line.charAt(m.end() + 1) == '"'))\r
+ {\r
+ continue;\r
+ }\r
+ \r
+ if (m.start() - 1 >= 0) {\r
+ // Case when the link is at the beginning of the string\r
+ line = line.substring(0, m.start()) + "<" + m.group(0) + ">" + line.substring(m.end());\r
+ } else {\r
+ line = "<" + m.group(0) + ">" + line.substring(m.end());\r
+ }\r
+ \r
+ // We replaced the string in the array\r
+ lines.set(lineNum, line);\r
+ urlReplaced = true;\r
+ break;\r
+ }\r
+ } while (urlReplaced);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param line\r
+ * @param c\r
+ * @return true if line is just cs (and whitespace at the start/end)\r
+ */\r
+ boolean just(String line, char c) {\r
+ return line.matches("\\s*"+c+"+\\s*");\r
+ }\r
+\r
+ /**\r
+ * @param line\r
+ * @return The number of # symbols prepending the line.\r
+ */\r
+ private int numHash(String line) {\r
+ for (int i = 0; i < line.length(); i++) {\r
+ if (line.charAt(i) != '#')\r
+ return i;\r
+ }\r
+ return line.length();\r
+ }\r
+\r
+ /**\r
+ * \r
+ * @param parent\r
+ * Can be null for top-level\r
+ * @return List of sub-headers. Never null. FIXME handle documents which\r
+ * have a 2nd level header before any 1st level ones\r
+ */\r
+ public List<Header> getHeadings(Header parent) {\r
+ if (parent == null) {\r
+ return Collections.unmodifiableList(level1Headers);\r
+ }\r
+ return Collections.unmodifiableList(parent.subHeaders);\r
+ }\r
+\r
+ // public WebPage getWebPage() {\r
+ // WebPage page = new WebPage();\r
+ // // Add the lines, one by one\r
+ // boolean inParagraph = false;\r
+ // for (int i=0; i<lines.size(); i++) {\r
+ // String line = lines.get(i);\r
+ // KLineType type = lineTypes.get(i);\r
+ // switch(type) {\r
+ // // Heading?\r
+ // case H1: case H2: case H3:\r
+ // case H4: case H5: case H6:\r
+ // if (inParagraph) page.addText("</p>");\r
+ // line = cleanHeader(line);\r
+ // page.addText("<"+type+">"+line+"</"+type+">");\r
+ // continue;\r
+ // case MARKER: // Ignore\r
+ // continue;\r
+ // // TODO List?\r
+ // // TODO Block quote?\r
+ // }\r
+ // // Paragraph end?\r
+ // if (Utils.isBlank(line)) {\r
+ // if (inParagraph) page.addText("</p>");\r
+ // continue;\r
+ // }\r
+ // // Paragraph start?\r
+ // if (!inParagraph) {\r
+ // page.addText("<p>");\r
+ // inParagraph = true;\r
+ // }\r
+ // // Plain text\r
+ // page.addText(line);\r
+ // }\r
+ // return page;\r
+ // }\r
+\r
+ /**\r
+ * Get the HTML for this page. Uses the MarkdownJ project.\r
+ */\r
+ public String html() {\r
+ // Section numbers??\r
+ boolean sectionNumbers = pStore\r
+ .getBoolean(MarkdownPreferencePage.PREF_SECTION_NUMBERS);\r
+ // Chop out multi-markdown header\r
+ StringBuilder sb = new StringBuilder();\r
+ assert lines.size() == lineTypes.size();\r
+ for (int i = 0, n = lines.size(); i < n; i++) {\r
+ KLineType type = lineTypes.get(i);\r
+ if (type == KLineType.META)\r
+ continue;\r
+ String line = lines.get(i);\r
+ if (sectionNumbers && isHeader(type) && line.contains("$section")) {\r
+ // TODO Header section = headers.get(i);\r
+ // String secNum = section.getSectionNumber();\r
+ // line.replace("$section", secNum);\r
+ }\r
+ sb.append(line);\r
+ }\r
+ String text = sb.toString();\r
+ // Use external converter?\r
+ final String cmd = pStore\r
+ .getString(MarkdownPreferencePage.PREF_MARKDOWN_COMMAND);\r
+ if (Utils.isBlank(cmd)\r
+ || (cmd.startsWith("(") && cmd.contains("MarkdownJ"))) {\r
+ // Use MarkdownJ\r
+ MarkdownProcessor markdown = new MarkdownProcessor();\r
+ // MarkdownJ doesn't convert £s for some reason\r
+ text = text.replace("£", "£");\r
+ String html = markdown.markdown(text);\r
+ return html;\r
+ }\r
+ // Attempt to run external command\r
+ try {\r
+ final File md = File.createTempFile("tmp", ".md");\r
+ FileUtils.write(md, text);\r
+ Process process = new Process(cmd+" "+md.getAbsolutePath());\r
+ process.run();\r
+ int ok = process.waitFor(10000);\r
+ if (ok != 0) throw new FailureException(cmd+" failed:\n"+process.getError());\r
+ String html = process.getOutput();\r
+ FileUtils.delete(md);\r
+ return html;\r
+ } catch (Exception e) {\r
+ throw Utils.runtime(e);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param type\r
+ * @return\r
+ */\r
+ private boolean isHeader(KLineType type) {\r
+ return type == KLineType.H1 || type == KLineType.H2\r
+ || type == KLineType.H3 || type == KLineType.H4\r
+ || type == KLineType.H5 || type == KLineType.H6;\r
+ }\r
+\r
+ /**\r
+ * Return the raw text of this page.\r
+ */\r
+ @Override\r
+ public String toString() {\r
+ StringBuilder sb = new StringBuilder();\r
+ for (String line : lines) {\r
+ sb.append(line);\r
+ }\r
+ return sb.toString();\r
+ }\r
+\r
+ /**\r
+ * Line type information for the raw text.\r
+ * \r
+ * @return\r
+ */\r
+ public List<KLineType> getLineTypes() {\r
+ return Collections.unmodifiableList(lineTypes);\r
+ }\r
+\r
+ /**\r
+ * @param line\r
+ * @return\r
+ */\r
+ public Object getPageObject(int line) { \r
+ return pageObjects.get(line);\r
+ }\r
+\r
+}\r
--- /dev/null
+package winterwell.markdown.pagemodel;
+
+import java.io.File;
+import java.util.List;
+
+import winterwell.markdown.pagemodel.MarkdownPage.Header;
+import winterwell.utils.io.FileUtils;
+
+
+
+public class MarkdownPageTest //extends TestCase
+{
+
+ public static void main(String[] args) {
+ MarkdownPageTest mpt = new MarkdownPageTest();
+ mpt.testGetHeadings();
+ }
+
+ public void testGetHeadings() {
+ // problem caused by a line beginning --, now fixed
+ String txt = FileUtils.read(new File(
+ "/home/daniel/winterwell/companies/DTC/projects/DTC-bayes/report1.txt"));
+ MarkdownPage p = new MarkdownPage(txt);
+ List<Header> h1s = p.getHeadings(null);
+ Header h1 = h1s.get(0);
+ List<Header> h2s = h1.getSubHeaders();
+ assert h2s.size() > 2;
+ }
+
+}
--- /dev/null
+package winterwell.markdown.preferences;
+
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.ColorFieldEditor;
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+import winterwell.markdown.Activator;
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class MarkdownPreferencePage
+ extends FieldEditorPreferencePage
+ implements IWorkbenchPreferencePage {
+
+ public static final String PREF_FOLDING = "Pref_Folding";
+ public static final String PREF_WORD_WRAP = "Pref_WordWrap";
+ public static final String PREF_TASK_TAGS = "Pref_TaskTagsOn";
+ public static final String PREF_TASK_TAGS_DEFINED = "Pref_TaskTags";
+ public static final String PREF_SECTION_NUMBERS = "Pref_SectionNumbers";
+
+ public static final String PREF_MARKDOWN_COMMAND = "Pref_Markdown_Command";
+ private static final String MARKDOWNJ = "(use built-in MarkdownJ converter)";
+
+
+ public static final String PREF_DEFUALT = "Pref_Default";
+ public static final String PREF_COMMENT = "Pref_Comment";
+ public static final String PREF_HEADER = "Pref_Header";
+ public static final String PREF_LINK = "Pref_Link";
+ public static final String PREF_CODE = "Pref_Code";
+ public static final String PREF_CODE_BG = "Pref_Code_Background";
+
+ public static final String PREF_GITHUB_SYNTAX = "Pref_Github_Syntax";
+ public static final String PREF_MULTIMARKDOWN_METADATA = "Pref_MultiMarkdown_Metadata";
+
+ private static final RGB DEF_DEFAULT = new RGB(0, 0, 0);
+ private static final RGB DEF_COMMENT = new RGB(128, 0, 0);
+ private static final RGB DEF_HEADER = new RGB(0, 128, 0);
+ private static final RGB DEF_LINK = new RGB(106, 131, 199);
+ private static final RGB DEF_CODE = new RGB(0, 0, 0);
+ private static final RGB DEF_CODE_BG = new RGB(244,244,244);
+
+ public MarkdownPreferencePage() {
+ super(GRID);
+ IPreferenceStore pStore = Activator.getDefault().getPreferenceStore();
+ setDefaultPreferences(pStore);
+ setPreferenceStore(pStore);
+ setDescription("Settings for the Markdown text editor. See also the general text editor preferences.");
+ }
+
+ public static void setDefaultPreferences(IPreferenceStore pStore) {
+ pStore.setDefault(PREF_WORD_WRAP, false);
+ pStore.setDefault(PREF_FOLDING, true);
+ pStore.setDefault(PREF_TASK_TAGS, true);
+ pStore.setDefault(PREF_TASK_TAGS_DEFINED, "TODO,FIXME,??");
+ pStore.setDefault(PREF_MARKDOWN_COMMAND, MARKDOWNJ);
+ pStore.setDefault(PREF_SECTION_NUMBERS, true);
+ pStore.setDefault(PREF_GITHUB_SYNTAX, true);
+ pStore.setDefault(PREF_MULTIMARKDOWN_METADATA, false);
+
+ PreferenceConverter.setDefault(pStore, PREF_DEFUALT, DEF_DEFAULT);
+ PreferenceConverter.setDefault(pStore, PREF_COMMENT, DEF_COMMENT);
+ PreferenceConverter.setDefault(pStore, PREF_HEADER, DEF_HEADER);
+ PreferenceConverter.setDefault(pStore, PREF_LINK, DEF_LINK);
+ PreferenceConverter.setDefault(pStore, PREF_CODE, DEF_CODE);
+ PreferenceConverter.setDefault(pStore, PREF_CODE_BG, DEF_CODE_BG);
+ }
+
+ /**
+ * Creates the field editors. Field editors are abstractions of
+ * the common GUI blocks needed to manipulate various types
+ * of preferences. Each field editor knows how to save and
+ * restore itself.
+ */
+ @Override
+ public void createFieldEditors() {
+ // Word wrap
+ BooleanFieldEditor fd = new BooleanFieldEditor(PREF_WORD_WRAP,
+ "Soft word wrapping \r\n"
++"Note: may cause line numbers and related \r\n" +
+ "functionality to act a bit strangely",
+ getFieldEditorParent());
+ addField(fd);
+ // Task tags
+ fd = new BooleanFieldEditor(PREF_TASK_TAGS,
+ "Manage tasks using task tags \r\n" +
+ "If true, this will add and delete tags in sync with edits.",
+ getFieldEditorParent());
+ addField(fd);
+ StringFieldEditor tags = new StringFieldEditor(PREF_TASK_TAGS_DEFINED,
+ "Task tags\nComma separated list of recognised task tags.", getFieldEditorParent());
+ addField(tags);
+ // Code folding
+ fd = new BooleanFieldEditor(PREF_FOLDING,
+ "Document folding, a.k.a. outline support",
+ getFieldEditorParent());
+ addField(fd);
+ // Command line
+// addField(new DummyField() {
+// protected void makeComponent(Composite parent) {
+// Label label = new Label(parent, 0);
+// label.setText("Hello!");
+// GridData gd = new GridData(100, 20);
+// label.setLayoutData(gd);
+// }
+// });
+ StringFieldEditor cmd = new StringFieldEditor(PREF_MARKDOWN_COMMAND,
+ "UNSTABLE: Command-line to run Markdown.\r\n" +
+ "This should take in a file and output to std-out.\n" +
+ "Leave blank to use the built-in Java converter.", getFieldEditorParent());
+ addField(cmd);
+
+ ColorFieldEditor def = new ColorFieldEditor(PREF_DEFUALT, "Default text", getFieldEditorParent());
+ addField(def);
+
+ ColorFieldEditor com = new ColorFieldEditor(PREF_COMMENT, "Comment", getFieldEditorParent());
+ addField(com);
+
+ ColorFieldEditor link = new ColorFieldEditor(PREF_LINK, "Link", getFieldEditorParent());
+ addField(link);
+
+ ColorFieldEditor head = new ColorFieldEditor(PREF_HEADER, "Header and List indicator", getFieldEditorParent());
+ addField(head);
+
+ ColorFieldEditor code = new ColorFieldEditor(PREF_CODE, "Code", getFieldEditorParent());
+ addField(code);
+
+ ColorFieldEditor codeBg = new ColorFieldEditor(PREF_CODE_BG, "Code Background", getFieldEditorParent());
+ addField(codeBg);
+
+ /*
+ * Fields for the preview window
+ */
+
+ // Github Syntax support
+ fd = new BooleanFieldEditor(PREF_GITHUB_SYNTAX,
+ "Support Github Syntax",
+ getFieldEditorParent());
+ addField(fd);
+
+ // Multi-Markdown support
+ fd = new BooleanFieldEditor(PREF_MULTIMARKDOWN_METADATA,
+ "Support Multi-Markdown Metadata",
+ getFieldEditorParent());
+ addField(fd);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+
+ }
+
+ public static boolean wordWrap() {
+ IPreferenceStore pStore = Activator.getDefault().getPreferenceStore();
+ if (! pStore.contains(MarkdownPreferencePage.PREF_WORD_WRAP)) {
+ return false;
+ }
+ return pStore.getBoolean(MarkdownPreferencePage.PREF_WORD_WRAP);
+ }
+
+}
+
+abstract class DummyField extends FieldEditor {
+ @Override
+ protected void adjustForNumColumns(int numColumns) {
+ // do nothing
+ }
+ @Override
+ protected void doFillIntoGrid(Composite parent, int numColumns) {
+ makeComponent(parent);
+ }
+ abstract protected void makeComponent(Composite parent);
+
+ @Override
+ protected void doLoad() {
+ //
+ }
+ @Override
+ protected void doLoadDefault() {
+ //
+ }
+
+ @Override
+ protected void doStore() {
+ //
+ }
+
+ @Override
+ public int getNumberOfControls() {
+ return 1;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package winterwell.markdown.views;
+
+
+import java.io.File;
+import java.net.URI;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPathEditorInput;
+import org.eclipse.ui.part.ViewPart;
+
+import winterwell.markdown.editors.ActionBarContributor;
+import winterwell.markdown.editors.MarkdownEditor;
+import winterwell.markdown.pagemodel.MarkdownPage;
+
+
+
+
+public class MarkdownPreview extends ViewPart {
+
+ public static MarkdownPreview preview = null;
+
+ private Browser viewer = null;
+
+ /**
+ * The constructor.
+ */
+ public MarkdownPreview() {
+ preview = this;
+ }
+
+ /**
+ * This is a callback that will allow us
+ * to create the viewer and initialize it.
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+ viewer = new Browser(parent, SWT.MULTI); // | SWT.H_SCROLL | SWT.V_SCROLL
+ }
+
+
+
+
+ /**
+ * Passing the focus request to the viewer's control.
+ */
+ @Override
+ public void setFocus() {
+ if (viewer==null) return;
+ viewer.setFocus();
+ update();
+ }
+
+ public void update() {
+ if (viewer==null) return;
+ try {
+ IEditorPart editor = ActionBarContributor.getActiveEditor();
+ if (!(editor instanceof MarkdownEditor)) {
+ viewer.setText("");
+ return;
+ }
+ MarkdownEditor ed = (MarkdownEditor) editor;
+ MarkdownPage page = ed.getMarkdownPage();
+ String html = page.html();
+ html = addBaseURL(editor, html);
+ if (page != null) viewer.setText(html);
+ else viewer.setText("");
+ } catch (Exception ex) {
+ // Smother
+ System.out.println(ex);
+
+ if (viewer != null && !viewer.isDisposed())
+ viewer.setText(ex.getMessage());
+ }
+ }
+
+ /**
+ * Adjust the URL base to be the file's directory.
+ * @param editor
+ * @param html
+ * @return
+ */
+ private String addBaseURL(IEditorPart editor, String html) {
+ try {
+ IPathEditorInput input = (IPathEditorInput) editor.getEditorInput();
+ IPath path = input.getPath();
+ path = path.removeLastSegments(1);
+ File f = path.toFile();
+ URI fileURI = f.toURI();
+ String html2 = "<html><head><base href='"+fileURI+"' /></head><body>\r\n"+html
+ +"\r\n</body></html>";
+ return html2;
+ } catch (Exception ex) {
+ return html;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/target/**\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>com.lowagie.text.feature</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.FeatureBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.FeatureNature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+bin.includes = feature.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<feature\r
+ id="com.lowagie.text"\r
+ label="iText"\r
+ version="2.1.7"\r
+ provider-name="VTT Technical Research Centre of Finland">\r
+\r
+ <description url="http://www.lowagie.com/iText/">\r
+ iText is a library that allows you to generate PDF files on the\r
+fly.\r
+ </description>\r
+\r
+ <copyright url="http://www.lowagie.com/iText/">\r
+ Copyright © 1999-2007 by Bruno Lowagie, Adolf Baeyensstraat 121, 9040 Gent, BELGIUM\r
+ </copyright>\r
+\r
+ <license url="http://www.lowagie.com/iText/MPL-1.1.txt">\r
+ MOZILLA PUBLIC LICENSE\r
+ Version 1.1\r
+\r
+ ---------------\r
+\r
+1. Definitions.\r
+\r
+ 1.0.1. "Commercial Use" means distribution or otherwise making the\r
+ Covered Code available to a third party.\r
+\r
+ 1.1. "Contributor" means each entity that creates or contributes to\r
+ the creation of Modifications.\r
+\r
+ 1.2. "Contributor Version" means the combination of the Original\r
+ Code, prior Modifications used by a Contributor, and the Modifications\r
+ made by that particular Contributor.\r
+\r
+ 1.3. "Covered Code" means the Original Code or Modifications or the\r
+ combination of the Original Code and Modifications, in each case\r
+ including portions thereof.\r
+\r
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally\r
+ accepted in the software development community for the electronic\r
+ transfer of data.\r
+\r
+ 1.5. "Executable" means Covered Code in any form other than Source\r
+ Code.\r
+\r
+ 1.6. "Initial Developer" means the individual or entity identified\r
+ as the Initial Developer in the Source Code notice required by Exhibit\r
+ A.\r
+\r
+ 1.7. "Larger Work" means a work which combines Covered Code or\r
+ portions thereof with code not governed by the terms of this License.\r
+\r
+ 1.8. "License" means this document.\r
+\r
+ 1.8.1. "Licensable" means having the right to grant, to the maximum\r
+ extent possible, whether at the time of the initial grant or\r
+ subsequently acquired, any and all of the rights conveyed herein.\r
+\r
+ 1.9. "Modifications" means any addition to or deletion from the\r
+ substance or structure of either the Original Code or any previous\r
+ Modifications. When Covered Code is released as a series of files, a\r
+ Modification is:\r
+ A. Any addition to or deletion from the contents of a file\r
+ containing Original Code or previous Modifications.\r
+\r
+ B. Any new file that contains any part of the Original Code or\r
+ previous Modifications.\r
+\r
+ 1.10. "Original Code" means Source Code of computer software code\r
+ which is described in the Source Code notice required by Exhibit A as\r
+ Original Code, and which, at the time of its release under this\r
+ License is not already Covered Code governed by this License.\r
+\r
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or\r
+ hereafter acquired, including without limitation, method, process,\r
+ and apparatus claims, in any patent Licensable by grantor.\r
+\r
+ 1.11. "Source Code" means the preferred form of the Covered Code for\r
+ making modifications to it, including all modules it contains, plus\r
+ any associated interface definition files, scripts used to control\r
+ compilation and installation of an Executable, or source code\r
+ differential comparisons against either the Original Code or another\r
+ well known, available Covered Code of the Contributor's choice. The\r
+ Source Code can be in a compressed or archival form, provided the\r
+ appropriate decompression or de-archiving software is widely available\r
+ for no charge.\r
+\r
+ 1.12. "You" (or "Your") means an individual or a legal entity\r
+ exercising rights under, and complying with all of the terms of, this\r
+ License or a future version of this License issued under Section 6.1.\r
+ For legal entities, "You" includes any entity which controls, is\r
+ controlled by, or is under common control with You. For purposes of\r
+ this definition, "control" means (a) the power, direct or indirect,\r
+ to cause the direction or management of such entity, whether by\r
+ contract or otherwise, or (b) ownership of more than fifty percent\r
+ (50%) of the outstanding shares or beneficial ownership of such\r
+ entity.\r
+\r
+2. Source Code License.\r
+\r
+ 2.1. The Initial Developer Grant.\r
+ The Initial Developer hereby grants You a world-wide, royalty-free,\r
+ non-exclusive license, subject to third party intellectual property\r
+ claims:\r
+ (a) under intellectual property rights (other than patent or\r
+ trademark) Licensable by Initial Developer to use, reproduce,\r
+ modify, display, perform, sublicense and distribute the Original\r
+ Code (or portions thereof) with or without Modifications, and/or\r
+ as part of a Larger Work; and\r
+\r
+ (b) under Patents Claims infringed by the making, using or\r
+ selling of Original Code, to make, have made, use, practice,\r
+ sell, and offer for sale, and/or otherwise dispose of the\r
+ Original Code (or portions thereof).\r
+\r
+ (c) the licenses granted in this Section 2.1(a) and (b) are\r
+ effective on the date Initial Developer first distributes\r
+ Original Code under the terms of this License.\r
+\r
+ (d) Notwithstanding Section 2.1(b) above, no patent license is\r
+ granted: 1) for code that You delete from the Original Code; 2)\r
+ separate from the Original Code; or 3) for infringements caused\r
+ by: i) the modification of the Original Code or ii) the\r
+ combination of the Original Code with other software or devices.\r
+\r
+ 2.2. Contributor Grant.\r
+ Subject to third party intellectual property claims, each Contributor\r
+ hereby grants You a world-wide, royalty-free, non-exclusive license\r
+\r
+ (a) under intellectual property rights (other than patent or\r
+ trademark) Licensable by Contributor, to use, reproduce, modify,\r
+ display, perform, sublicense and distribute the Modifications\r
+ created by such Contributor (or portions thereof) either on an\r
+ unmodified basis, with other Modifications, as Covered Code\r
+ and/or as part of a Larger Work; and\r
+\r
+ (b) under Patent Claims infringed by the making, using, or\r
+ selling of Modifications made by that Contributor either alone\r
+ and/or in combination with its Contributor Version (or portions\r
+ of such combination), to make, use, sell, offer for sale, have\r
+ made, and/or otherwise dispose of: 1) Modifications made by that\r
+ Contributor (or portions thereof); and 2) the combination of\r
+ Modifications made by that Contributor with its Contributor\r
+ Version (or portions of such combination).\r
+\r
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are\r
+ effective on the date Contributor first makes Commercial Use of\r
+ the Covered Code.\r
+\r
+ (d) Notwithstanding Section 2.2(b) above, no patent license is\r
+ granted: 1) for any code that Contributor has deleted from the\r
+ Contributor Version; 2) separate from the Contributor Version;\r
+ 3) for infringements caused by: i) third party modifications of\r
+ Contributor Version or ii) the combination of Modifications made\r
+ by that Contributor with other software (except as part of the\r
+ Contributor Version) or other devices; or 4) under Patent Claims\r
+ infringed by Covered Code in the absence of Modifications made by\r
+ that Contributor.\r
+\r
+3. Distribution Obligations.\r
+\r
+ 3.1. Application of License.\r
+ The Modifications which You create or to which You contribute are\r
+ governed by the terms of this License, including without limitation\r
+ Section 2.2. The Source Code version of Covered Code may be\r
+ distributed only under the terms of this License or a future version\r
+ of this License released under Section 6.1, and You must include a\r
+ copy of this License with every copy of the Source Code You\r
+ distribute. You may not offer or impose any terms on any Source Code\r
+ version that alters or restricts the applicable version of this\r
+ License or the recipients' rights hereunder. However, You may include\r
+ an additional document offering the additional rights described in\r
+ Section 3.5.\r
+\r
+ 3.2. Availability of Source Code.\r
+ Any Modification which You create or to which You contribute must be\r
+ made available in Source Code form under the terms of this License\r
+ either on the same media as an Executable version or via an accepted\r
+ Electronic Distribution Mechanism to anyone to whom you made an\r
+ Executable version available; and if made available via Electronic\r
+ Distribution Mechanism, must remain available for at least twelve (12)\r
+ months after the date it initially became available, or at least six\r
+ (6) months after a subsequent version of that particular Modification\r
+ has been made available to such recipients. You are responsible for\r
+ ensuring that the Source Code version remains available even if the\r
+ Electronic Distribution Mechanism is maintained by a third party.\r
+\r
+ 3.3. Description of Modifications.\r
+ You must cause all Covered Code to which You contribute to contain a\r
+ file documenting the changes You made to create that Covered Code and\r
+ the date of any change. You must include a prominent statement that\r
+ the Modification is derived, directly or indirectly, from Original\r
+ Code provided by the Initial Developer and including the name of the\r
+ Initial Developer in (a) the Source Code, and (b) in any notice in an\r
+ Executable version or related documentation in which You describe the\r
+ origin or ownership of the Covered Code.\r
+\r
+ 3.4. Intellectual Property Matters\r
+ (a) Third Party Claims.\r
+ If Contributor has knowledge that a license under a third party's\r
+ intellectual property rights is required to exercise the rights\r
+ granted by such Contributor under Sections 2.1 or 2.2,\r
+ Contributor must include a text file with the Source Code\r
+ distribution titled "LEGAL" which describes the claim and the\r
+ party making the claim in sufficient detail that a recipient will\r
+ know whom to contact. If Contributor obtains such knowledge after\r
+ the Modification is made available as described in Section 3.2,\r
+ Contributor shall promptly modify the LEGAL file in all copies\r
+ Contributor makes available thereafter and shall take other steps\r
+ (such as notifying appropriate mailing lists or newsgroups)\r
+ reasonably calculated to inform those who received the Covered\r
+ Code that new knowledge has been obtained.\r
+\r
+ (b) Contributor APIs.\r
+ If Contributor's Modifications include an application programming\r
+ interface and Contributor has knowledge of patent licenses which\r
+ are reasonably necessary to implement that API, Contributor must\r
+ also include this information in the LEGAL file.\r
+\r
+ (c) Representations.\r
+ Contributor represents that, except as disclosed pursuant to\r
+ Section 3.4(a) above, Contributor believes that Contributor's\r
+ Modifications are Contributor's original creation(s) and/or\r
+ Contributor has sufficient rights to grant the rights conveyed by\r
+ this License.\r
+\r
+ 3.5. Required Notices.\r
+ You must duplicate the notice in Exhibit A in each file of the Source\r
+ Code. If it is not possible to put such notice in a particular Source\r
+ Code file due to its structure, then You must include such notice in a\r
+ location (such as a relevant directory) where a user would be likely\r
+ to look for such a notice. If You created one or more Modification(s)\r
+ You may add your name as a Contributor to the notice described in\r
+ Exhibit A. You must also duplicate this License in any documentation\r
+ for the Source Code where You describe recipients' rights or ownership\r
+ rights relating to Covered Code. You may choose to offer, and to\r
+ charge a fee for, warranty, support, indemnity or liability\r
+ obligations to one or more recipients of Covered Code. However, You\r
+ may do so only on Your own behalf, and not on behalf of the Initial\r
+ Developer or any Contributor. You must make it absolutely clear than\r
+ any such warranty, support, indemnity or liability obligation is\r
+ offered by You alone, and You hereby agree to indemnify the Initial\r
+ Developer and every Contributor for any liability incurred by the\r
+ Initial Developer or such Contributor as a result of warranty,\r
+ support, indemnity or liability terms You offer.\r
+\r
+ 3.6. Distribution of Executable Versions.\r
+ You may distribute Covered Code in Executable form only if the\r
+ requirements of Section 3.1-3.5 have been met for that Covered Code,\r
+ and if You include a notice stating that the Source Code version of\r
+ the Covered Code is available under the terms of this License,\r
+ including a description of how and where You have fulfilled the\r
+ obligations of Section 3.2. The notice must be conspicuously included\r
+ in any notice in an Executable version, related documentation or\r
+ collateral in which You describe recipients' rights relating to the\r
+ Covered Code. You may distribute the Executable version of Covered\r
+ Code or ownership rights under a license of Your choice, which may\r
+ contain terms different from this License, provided that You are in\r
+ compliance with the terms of this License and that the license for the\r
+ Executable version does not attempt to limit or alter the recipient's\r
+ rights in the Source Code version from the rights set forth in this\r
+ License. If You distribute the Executable version under a different\r
+ license You must make it absolutely clear that any terms which differ\r
+ from this License are offered by You alone, not by the Initial\r
+ Developer or any Contributor. You hereby agree to indemnify the\r
+ Initial Developer and every Contributor for any liability incurred by\r
+ the Initial Developer or such Contributor as a result of any such\r
+ terms You offer.\r
+\r
+ 3.7. Larger Works.\r
+ You may create a Larger Work by combining Covered Code with other code\r
+ not governed by the terms of this License and distribute the Larger\r
+ Work as a single product. In such a case, You must make sure the\r
+ requirements of this License are fulfilled for the Covered Code.\r
+\r
+4. Inability to Comply Due to Statute or Regulation.\r
+\r
+ If it is impossible for You to comply with any of the terms of this\r
+ License with respect to some or all of the Covered Code due to\r
+ statute, judicial order, or regulation then You must: (a) comply with\r
+ the terms of this License to the maximum extent possible; and (b)\r
+ describe the limitations and the code they affect. Such description\r
+ must be included in the LEGAL file described in Section 3.4 and must\r
+ be included with all distributions of the Source Code. Except to the\r
+ extent prohibited by statute or regulation, such description must be\r
+ sufficiently detailed for a recipient of ordinary skill to be able to\r
+ understand it.\r
+\r
+5. Application of this License.\r
+\r
+ This License applies to code to which the Initial Developer has\r
+ attached the notice in Exhibit A and to related Covered Code.\r
+\r
+6. Versions of the License.\r
+\r
+ 6.1. New Versions.\r
+ Netscape Communications Corporation ("Netscape") may publish revised\r
+ and/or new versions of the License from time to time. Each version\r
+ will be given a distinguishing version number.\r
+\r
+ 6.2. Effect of New Versions.\r
+ Once Covered Code has been published under a particular version of the\r
+ License, You may always continue to use it under the terms of that\r
+ version. You may also choose to use such Covered Code under the terms\r
+ of any subsequent version of the License published by Netscape. No one\r
+ other than Netscape has the right to modify the terms applicable to\r
+ Covered Code created under this License.\r
+\r
+ 6.3. Derivative Works.\r
+ If You create or use a modified version of this License (which you may\r
+ only do in order to apply it to code which is not already Covered Code\r
+ governed by this License), You must (a) rename Your license so that\r
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",\r
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your\r
+ license (except to note that your license differs from this License)\r
+ and (b) otherwise make it clear that Your version of the license\r
+ contains terms which differ from the Mozilla Public License and\r
+ Netscape Public License. (Filling in the name of the Initial\r
+ Developer, Original Code or Contributor in the notice described in\r
+ Exhibit A shall not of themselves be deemed to be modifications of\r
+ this License.)\r
+\r
+7. DISCLAIMER OF WARRANTY.\r
+\r
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,\r
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF\r
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.\r
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE\r
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,\r
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE\r
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER\r
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF\r
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.\r
+\r
+8. TERMINATION.\r
+\r
+ 8.1. This License and the rights granted hereunder will terminate\r
+ automatically if You fail to comply with terms herein and fail to cure\r
+ such breach within 30 days of becoming aware of the breach. All\r
+ sublicenses to the Covered Code which are properly granted shall\r
+ survive any termination of this License. Provisions which, by their\r
+ nature, must remain in effect beyond the termination of this License\r
+ shall survive.\r
+\r
+ 8.2. If You initiate litigation by asserting a patent infringement\r
+ claim (excluding declatory judgment actions) against Initial Developer\r
+ or a Contributor (the Initial Developer or Contributor against whom\r
+ You file such action is referred to as "Participant") alleging that:\r
+\r
+ (a) such Participant's Contributor Version directly or indirectly\r
+ infringes any patent, then any and all rights granted by such\r
+ Participant to You under Sections 2.1 and/or 2.2 of this License\r
+ shall, upon 60 days notice from Participant terminate prospectively,\r
+ unless if within 60 days after receipt of notice You either: (i)\r
+ agree in writing to pay Participant a mutually agreeable reasonable\r
+ royalty for Your past and future use of Modifications made by such\r
+ Participant, or (ii) withdraw Your litigation claim with respect to\r
+ the Contributor Version against such Participant. If within 60 days\r
+ of notice, a reasonable royalty and payment arrangement are not\r
+ mutually agreed upon in writing by the parties or the litigation claim\r
+ is not withdrawn, the rights granted by Participant to You under\r
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of\r
+ the 60 day notice period specified above.\r
+\r
+ (b) any software, hardware, or device, other than such Participant's\r
+ Contributor Version, directly or indirectly infringes any patent, then\r
+ any rights granted to You by such Participant under Sections 2.1(b)\r
+ and 2.2(b) are revoked effective as of the date You first made, used,\r
+ sold, distributed, or had made, Modifications made by that\r
+ Participant.\r
+\r
+ 8.3. If You assert a patent infringement claim against Participant\r
+ alleging that such Participant's Contributor Version directly or\r
+ indirectly infringes any patent where such claim is resolved (such as\r
+ by license or settlement) prior to the initiation of patent\r
+ infringement litigation, then the reasonable value of the licenses\r
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken\r
+ into account in determining the amount or value of any payment or\r
+ license.\r
+\r
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,\r
+ all end user license agreements (excluding distributors and resellers)\r
+ which have been validly granted by You or any distributor hereunder\r
+ prior to termination shall survive termination.\r
+\r
+9. LIMITATION OF LIABILITY.\r
+\r
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT\r
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL\r
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,\r
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR\r
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY\r
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,\r
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER\r
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN\r
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF\r
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY\r
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW\r
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE\r
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO\r
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.\r
+\r
+10. U.S. GOVERNMENT END USERS.\r
+\r
+ The Covered Code is a "commercial item," as that term is defined in\r
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer\r
+ software" and "commercial computer software documentation," as such\r
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48\r
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),\r
+ all U.S. Government End Users acquire Covered Code with only those\r
+ rights set forth herein.\r
+\r
+11. MISCELLANEOUS.\r
+\r
+ This License represents the complete agreement concerning subject\r
+ matter hereof. If any provision of this License is held to be\r
+ unenforceable, such provision shall be reformed only to the extent\r
+ necessary to make it enforceable. This License shall be governed by\r
+ California law provisions (except to the extent applicable law, if\r
+ any, provides otherwise), excluding its conflict-of-law provisions.\r
+ With respect to disputes in which at least one party is a citizen of,\r
+ or an entity chartered or registered to do business in the United\r
+ States of America, any litigation relating to this License shall be\r
+ subject to the jurisdiction of the Federal Courts of the Northern\r
+ District of California, with venue lying in Santa Clara County,\r
+ California, with the losing party responsible for costs, including\r
+ without limitation, court costs and reasonable attorneys' fees and\r
+ expenses. The application of the United Nations Convention on\r
+ Contracts for the International Sale of Goods is expressly excluded.\r
+ Any law or regulation which provides that the language of a contract\r
+ shall be construed against the drafter shall not apply to this\r
+ License.\r
+\r
+12. RESPONSIBILITY FOR CLAIMS.\r
+\r
+ As between Initial Developer and the Contributors, each party is\r
+ responsible for claims and damages arising, directly or indirectly,\r
+ out of its utilization of rights under this License and You agree to\r
+ work with Initial Developer and Contributors to distribute such\r
+ responsibility on an equitable basis. Nothing herein is intended or\r
+ shall be deemed to constitute any admission of liability.\r
+\r
+13. MULTIPLE-LICENSED CODE.\r
+\r
+ Initial Developer may designate portions of the Covered Code as\r
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial\r
+ Developer permits you to utilize portions of the Covered Code under\r
+ Your choice of the NPL or the alternative licenses, if any, specified\r
+ by the Initial Developer in the file described in Exhibit A.\r
+\r
+EXHIBIT A -Mozilla Public License.\r
+\r
+ ``The contents of this file are subject to the Mozilla Public License\r
+ Version 1.1 (the "License"); you may not use this file except in\r
+ compliance with the License. You may obtain a copy of the License at\r
+ http://www.mozilla.org/MPL/\r
+\r
+ Software distributed under the License is distributed on an "AS IS"\r
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
+ License for the specific language governing rights and limitations\r
+ under the License.\r
+\r
+ The Original Code is ______________________________________.\r
+\r
+ The Initial Developer of the Original Code is ________________________.\r
+ Portions created by ______________________ are Copyright (C) ______\r
+ _______________________. All Rights Reserved.\r
+\r
+ Contributor(s): ______________________________________.\r
+\r
+ Alternatively, the contents of this file may be used under the terms\r
+ of the _____ license (the "[___] License"), in which case the\r
+ provisions of [______] License are applicable instead of those\r
+ above. If you wish to allow use of your version of this file only\r
+ under the terms of the [____] License and not to allow others to use\r
+ your version of this file under the MPL, indicate your decision by\r
+ deleting the provisions above and replace them with the notice and\r
+ other provisions required by the [___] License. If you do not delete\r
+ the provisions above, a recipient may use your version of this file\r
+ under either the MPL or the [___] License."\r
+\r
+ [NOTE: The text of this Exhibit A may differ slightly from the text of\r
+ the notices in the Source Code files of the Original Code. You should\r
+ use the text of this Exhibit A rather than the text found in the\r
+ Original Code Source Code for Your Modifications.]\r
+ </license>\r
+\r
+ <plugin\r
+ id="com.lowagie.text"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.bouncycastle.bcmail-jdk14"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"/>\r
+\r
+ <plugin\r
+ id="org.bouncycastle.bcprov-jdk14"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"/>\r
+\r
+ <plugin\r
+ id="org.bouncycastle.bctsp-jdk14"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"/>\r
+\r
+</feature>\r
--- /dev/null
+/target/**\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.apache.lucene4.feature</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.FeatureBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.FeatureNature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+bin.includes = feature.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<feature\r
+ id="org.apache.lucene4"\r
+ label="Apache Lucene v4"\r
+ version="4.9.0"\r
+ provider-name="The Apache Software Foundation">\r
+\r
+ <description url="http://lucene.apache.org/java/">\r
+ Apache Lucene is a high-performance, full-featured text search engine library written entirely in Java. It is a technology suitable for nearly any application that requires full-text search, especially cross-platform.\r
+ </description>\r
+\r
+ <copyright url="http://lucene.apache.org/java/">\r
+ Copyright © 2006 The Apache Software Foundation.\r
+ </copyright>\r
+\r
+ <license url="http://www.apache.org/licenses/LICENSE-2.0">\r
+ Apache License\r
+ Version 2.0, January 2004\r
+ http://www.apache.org/licenses/\r
+\r
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+ 1. Definitions.\r
+\r
+ "License" shall mean the terms and conditions for use, reproduction,\r
+ and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+ "Licensor" shall mean the copyright owner or entity authorized by\r
+ the copyright owner that is granting the License.\r
+\r
+ "Legal Entity" shall mean the union of the acting entity and all\r
+ other entities that control, are controlled by, or are under common\r
+ control with that entity. For the purposes of this definition,\r
+ "control" means (i) the power, direct or indirect, to cause the\r
+ direction or management of such entity, whether by contract or\r
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+ outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+ "You" (or "Your") shall mean an individual or Legal Entity\r
+ exercising permissions granted by this License.\r
+\r
+ "Source" form shall mean the preferred form for making modifications,\r
+ including but not limited to software source code, documentation\r
+ source, and configuration files.\r
+\r
+ "Object" form shall mean any form resulting from mechanical\r
+ transformation or translation of a Source form, including but\r
+ not limited to compiled object code, generated documentation,\r
+ and conversions to other media types.\r
+\r
+ "Work" shall mean the work of authorship, whether in Source or\r
+ Object form, made available under the License, as indicated by a\r
+ copyright notice that is included in or attached to the work\r
+ (an example is provided in the Appendix below).\r
+\r
+ "Derivative Works" shall mean any work, whether in Source or Object\r
+ form, that is based on (or derived from) the Work and for which the\r
+ editorial revisions, annotations, elaborations, or other modifications\r
+ represent, as a whole, an original work of authorship. For the purposes\r
+ of this License, Derivative Works shall not include works that remain\r
+ separable from, or merely link (or bind by name) to the interfaces of,\r
+ the Work and Derivative Works thereof.\r
+\r
+ "Contribution" shall mean any work of authorship, including\r
+ the original version of the Work and any modifications or additions\r
+ to that Work or Derivative Works thereof, that is intentionally\r
+ submitted to Licensor for inclusion in the Work by the copyright owner\r
+ or by an individual or Legal Entity authorized to submit on behalf of\r
+ the copyright owner. For the purposes of this definition, "submitted"\r
+ means any form of electronic, verbal, or written communication sent\r
+ to the Licensor or its representatives, including but not limited to\r
+ communication on electronic mailing lists, source code control systems,\r
+ and issue tracking systems that are managed by, or on behalf of, the\r
+ Licensor for the purpose of discussing and improving the Work, but\r
+ excluding communication that is conspicuously marked or otherwise\r
+ designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+ "Contributor" shall mean Licensor and any individual or Legal Entity\r
+ on behalf of whom a Contribution has been received by Licensor and\r
+ subsequently incorporated within the Work.\r
+\r
+ 2. Grant of Copyright License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ copyright license to reproduce, prepare Derivative Works of,\r
+ publicly display, publicly perform, sublicense, and distribute the\r
+ Work and such Derivative Works in Source or Object form.\r
+\r
+ 3. Grant of Patent License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ (except as stated in this section) patent license to make, have made,\r
+ use, offer to sell, sell, import, and otherwise transfer the Work,\r
+ where such license applies only to those patent claims licensable\r
+ by such Contributor that are necessarily infringed by their\r
+ Contribution(s) alone or by combination of their Contribution(s)\r
+ with the Work to which such Contribution(s) was submitted. If You\r
+ institute patent litigation against any entity (including a\r
+ cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+ or a Contribution incorporated within the Work constitutes direct\r
+ or contributory patent infringement, then any patent licenses\r
+ granted to You under this License for that Work shall terminate\r
+ as of the date such litigation is filed.\r
+\r
+ 4. Redistribution. You may reproduce and distribute copies of the\r
+ Work or Derivative Works thereof in any medium, with or without\r
+ modifications, and in Source or Object form, provided that You\r
+ meet the following conditions:\r
+\r
+ (a) You must give any other recipients of the Work or\r
+ Derivative Works a copy of this License; and\r
+\r
+ (b) You must cause any modified files to carry prominent notices\r
+ stating that You changed the files; and\r
+\r
+ (c) You must retain, in the Source form of any Derivative Works\r
+ that You distribute, all copyright, patent, trademark, and\r
+ attribution notices from the Source form of the Work,\r
+ excluding those notices that do not pertain to any part of\r
+ the Derivative Works; and\r
+\r
+ (d) If the Work includes a "NOTICE" text file as part of its\r
+ distribution, then any Derivative Works that You distribute must\r
+ include a readable copy of the attribution notices contained\r
+ within such NOTICE file, excluding those notices that do not\r
+ pertain to any part of the Derivative Works, in at least one\r
+ of the following places: within a NOTICE text file distributed\r
+ as part of the Derivative Works; within the Source form or\r
+ documentation, if provided along with the Derivative Works; or,\r
+ within a display generated by the Derivative Works, if and\r
+ wherever such third-party notices normally appear. The contents\r
+ of the NOTICE file are for informational purposes only and\r
+ do not modify the License. You may add Your own attribution\r
+ notices within Derivative Works that You distribute, alongside\r
+ or as an addendum to the NOTICE text from the Work, provided\r
+ that such additional attribution notices cannot be construed\r
+ as modifying the License.\r
+\r
+ You may add Your own copyright statement to Your modifications and\r
+ may provide additional or different license terms and conditions\r
+ for use, reproduction, or distribution of Your modifications, or\r
+ for any such Derivative Works as a whole, provided Your use,\r
+ reproduction, and distribution of the Work otherwise complies with\r
+ the conditions stated in this License.\r
+\r
+ 5. Submission of Contributions. Unless You explicitly state otherwise,\r
+ any Contribution intentionally submitted for inclusion in the Work\r
+ by You to the Licensor shall be under the terms and conditions of\r
+ this License, without any additional terms or conditions.\r
+ Notwithstanding the above, nothing herein shall supersede or modify\r
+ the terms of any separate license agreement you may have executed\r
+ with Licensor regarding such Contributions.\r
+\r
+ 6. Trademarks. This License does not grant permission to use the trade\r
+ names, trademarks, service marks, or product names of the Licensor,\r
+ except as required for reasonable and customary use in describing the\r
+ origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+ 7. Disclaimer of Warranty. Unless required by applicable law or\r
+ agreed to in writing, Licensor provides the Work (and each\r
+ Contributor provides its Contributions) on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+ implied, including, without limitation, any warranties or conditions\r
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+ PARTICULAR PURPOSE. You are solely responsible for determining the\r
+ appropriateness of using or redistributing the Work and assume any\r
+ risks associated with Your exercise of permissions under this License.\r
+\r
+ 8. Limitation of Liability. In no event and under no legal theory,\r
+ whether in tort (including negligence), contract, or otherwise,\r
+ unless required by applicable law (such as deliberate and grossly\r
+ negligent acts) or agreed to in writing, shall any Contributor be\r
+ liable to You for damages, including any direct, indirect, special,\r
+ incidental, or consequential damages of any character arising as a\r
+ result of this License or out of the use or inability to use the\r
+ Work (including but not limited to damages for loss of goodwill,\r
+ work stoppage, computer failure or malfunction, or any and all\r
+ other commercial damages or losses), even if such Contributor\r
+ has been advised of the possibility of such damages.\r
+\r
+ 9. Accepting Warranty or Additional Liability. While redistributing\r
+ the Work or Derivative Works thereof, You may choose to offer,\r
+ and charge a fee for, acceptance of support, warranty, indemnity,\r
+ or other liability obligations and/or rights consistent with this\r
+ License. However, in accepting such obligations, You may act only\r
+ on Your own behalf and on Your sole responsibility, not on behalf\r
+ of any other Contributor, and only if You agree to indemnify,\r
+ defend, and hold each Contributor harmless for any liability\r
+ incurred by, or claims asserted against, such Contributor by reason\r
+ of your accepting any such warranty or additional liability.\r
+\r
+ END OF TERMS AND CONDITIONS\r
+\r
+ APPENDIX: How to apply the Apache License to your work.\r
+\r
+ To apply the Apache License to your work, attach the following\r
+ boilerplate notice, with the fields enclosed by brackets "[]"\r
+ replaced with your own identifying information. (Don't include\r
+ the brackets!) The text should be enclosed in the appropriate\r
+ comment syntax for the file format. We also recommend that a\r
+ file or class name and description of purpose be included on the\r
+ same "printed page" as the copyright notice for easier\r
+ identification within third-party archives.\r
+\r
+ Copyright [yyyy] [name of copyright owner]\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
+ </license>\r
+\r
+ <plugin\r
+ id="org.apache.lucene4.core"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.apache.lucene4.queries"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.apache.lucene4.sandbox"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.apache.lucene4.queryparser"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.apache.lucene4.analyzers-common"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+</feature>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.eclipsec.launcher.feature</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.FeatureBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.FeatureNature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+###############################################################################\r
+# Copyright (c) 2007, 2015 Association for Decentralized Information Management\r
+# in Industry THTH ry.\r
+# All rights reserved. This program and the accompanying materials\r
+# are made available under the terms of the Eclipse Public License v1.0\r
+# which accompanies this distribution, and is available at\r
+# http://www.eclipse.org/legal/epl-v10.html\r
+#\r
+# Contributors:\r
+# VTT Technical Research Centre of Finland - initial API and implementation\r
+# Semantum Oy - update to Eclipse Mars.1 (4.5.1)\r
+###############################################################################\r
+bin.includes=features.xml\r
+root.win32.win32.x86=bin/win32/win32/x86\r
+root.win32.win32.x86_64=bin/win32/win32/x86_64
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--
+ Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ in Industry THTH ry.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+
+ Contributors:
+ VTT Technical Research Centre of Finland - initial API and implementation
+ -->\r
+<feature\r
+ id="org.simantics.eclipsec.launcher"\r
+ label="eclipsec launcher includer"\r
+ version="3.6.200.v20150602-1417"\r
+ provider-name="VTT Technical Research Centre of Finland">\r
+\r
+ <description>\r
+ This is a build-time feature that only includes standard eclipsec launcher executables for platforms where available since the standard org.eclipse.equinox.launcher feature does not include these. The eclipsec executables are valuable for debugging purposes where native code crashes the whole program. With the normal launcher all your possible debug information will be lost forever. Using eclipsec you will see everything put in standard output and standard error in the same very console where you launched eclipsec.\r
+ </description>\r
+\r
+ <copyright url="http://www.example.com/copyright">\r
+ [Enter Copyright Description here.]\r
+ </copyright>\r
+\r
+ <license url="http://www.example.com/license">\r
+ [Enter License Description here.]\r
+ </license>\r
+\r
+</feature>\r
\r
<includes\r
id="org.simantics.eclipsec.launcher"\r
- version="0.0.0"\r
- optional="true"\r
- os="win32"\r
- ws="win32,wpf"\r
- arch="x86,x86_64"/>\r
+ version="0.0.0"/>\r
\r
<includes\r
id="org.simantics.help"\r
<requires>\r
<import feature="org.simantics.layer0" version="1.2.0" match="compatible"/>\r
<import feature="org.simantics.rcp" version="1.25.0" match="compatible"/>\r
- <import feature="org.simantics.platform.ui" version="1.25.0" match="compatible"/>\r
</requires>\r
\r
<plugin\r
</parent>\r
\r
<modules>\r
+ <module>com.lowagie.text.feature</module>\r
+ <module>org.apache.lucene4.feature</module>\r
<module>org.simantics.browsing.ui.feature</module>\r
<module>org.simantics.charts.feature</module>\r
<module>org.simantics.data.feature</module>\r
<module>org.simantics.document.base.feature</module>\r
<module>org.simantics.document.linking.feature</module>\r
<module>org.simantics.document.swt.feature</module>\r
+ <module>org.simantics.eclipsec.launcher.feature</module>\r
<module>org.simantics.event.feature</module>\r
<module>org.simantics.export.feature</module>\r
<module>org.simantics.g2d.feature</module>\r