Enso Integration with Ideal Graph Visualizer (#3533)

This PR adds sources for Enso language support in IGV (and NetBeans). The support is based on TextMate grammar shown in the editor and registration of the Enso language so IGV can find it. Then this PR adds new GitHub Actions workflow file to build the project using Maven.
This commit is contained in:
Jaroslav Tulach 2022-06-23 06:43:49 +02:00 committed by GitHub
parent 655793aa78
commit 479f74cc84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 630 additions and 14 deletions

41
.github/workflows/enso4igv.yml vendored Normal file
View File

@ -0,0 +1,41 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Enso Language Support for IGV
on:
push:
branches: [develop]
pull_request:
branches: [develop]
paths:
- "tools/enso4igv/**/*"
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
java: ["8"]
steps:
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v2
with:
distribution: "zulu"
java-version: ${{ matrix.java }}
cache: maven
- name: Update project version
working-directory: tools/enso4igv
run: |
mvn versions:set -DnewVersion=`mvn -q -DforceStdout help:evaluate -Dexpression=project.version | cut -f1 -d -`.$GITHUB_RUN_NUMBER
- name: Build with Maven
run: mvn -B package --file tools/enso4igv/pom.xml
- name: Archive NBM file
uses: actions/upload-artifact@v3
with:
name: Enso IGV Plugin
path: tools/enso4igv/target/*.nbm

View File

@ -248,6 +248,7 @@
builtins from method signatures][3454]
- [Avoid needless concatenations of warning/error messages][3465]
- [Added a full-blown DSL for builtins][3471]
- [Integration of Enso with Ideal Graph Visualizer][3533]
- [Lazy evaluation of RHS argument for || and &&][3492]
- [Drop Core implementation of IR][3512]
- [Replace `this` with `self`][3524]
@ -276,6 +277,7 @@
[3461]: https://github.com/enso-org/enso/pull/3461
[3465]: https://github.com/enso-org/enso/pull/3465
[3471]: https://github.com/enso-org/enso/pull/3471
[3533]: https://github.com/enso-org/enso/pull/3533
[3492]: https://github.com/enso-org/enso/pull/3492
[3493]: https://github.com/enso-org/enso/pull/3493
[3505]: https://github.com/enso-org/enso/pull/3505

View File

@ -1,3 +1,12 @@
COMP_PATH=$(dirname "$0")/../component
exec java -jar -Dtruffle.class.path.append="$COMP_PATH/runtime.jar" $JAVA_OPTS $COMP_PATH/runner.jar "$@"
EXTRA_OPTS="-Dgraal.PrintGraph=Network"
for opt in "$@"; do
if [ "$opt" = "--dump-graphs" ]; then
EXTRA_OPTS="$EXTRA_OPTS -Dgraal.Dump=:1"
fi
done
exec java -jar -Dtruffle.class.path.append="$COMP_PATH/runtime.jar" $EXTRA_OPTS $JAVA_OPTS $COMP_PATH/runner.jar "$@"
exit

View File

@ -1,3 +1,10 @@
@set comp-dir=%~dp0\..\component
@java -jar -Dtruffle.class.path.append=%comp-dir%\runtime.jar -Dpolyglot.engine.IterativePartialEscape=true %JAVA_OPTS% %comp-dir%\runner.jar %*
@exit /B %errorlevel%
@echo off
set comp-dir=%~dp0\..\component
set EXTRA_OPTS=-Dgraal.PrintGraph=Network
FOR %%A in (%*) DO (
if /I %%A==--dump-graphs (
set EXTRA_OPTS=%EXTRA_OPTS% -Dgraal.Dump=Truffle:1
)
)
java -jar -Dtruffle.class.path.append=%comp-dir%\runtime.jar -Dpolyglot.engine.IterativePartialEscape=true %EXTRA_OPTS% %JAVA_OPTS% %comp-dir%\runner.jar %*
exit /B %errorlevel%

View File

@ -50,7 +50,8 @@ order: 7
[IGV](https://www.graalvm.org/graalvm-as-a-platform/language-implementation-framework/Profiling/).
It's a horrible tool. It's clunky, ugly, and painful to use. It has also
saved us more times than we can count, definitely worth investing the time to
understand it. Use
understand it. Download
[Enso Language Support for IGV](../tools/enso4igv/README.md). Use
[this tutorial](https://shopify.engineering/understanding-programs-using-graphs)
(and
[the follow up post](https://chrisseaton.com/truffleruby/basic-truffle-graphs/))
@ -62,8 +63,9 @@ order: 7
debugging options.
3. Use [hsdis](https://github.com/liuzhengyang/hsdis/) for printing the
generated assembly you can often spot obvious problems with compilations.
That being said, IGV is usually the better tool, if you take a look at the
later compilation stages.
That being said, IGV (with
[Enso Language Support](../tools/enso4igv/README.md)) is usually the better
tool, if you take a look at the later compilation stages.
4. Pay attention to making things `final` and `@CompilationFinal`. This is the
most important way Graal does constant-folding. Whenever a loop bound can be
compilation final, take advantage (and use `@ExplodeLoop`).
@ -179,7 +181,8 @@ design choices. Here's a list with some explanations:
if any benchmark is more than 20% slower than the fastest recorded run. Don't
use your computer when running these. It is also worth noting that these can
be run through the `withDebug` utility, which allows you to test truffle
compilations (and e.g. watch the graphs in IGV).
compilations (and e.g. watch the graphs in IGV with
[Enso Language Support](../tools/enso4igv/README.md)).
8. **Tests**: There are scalatests that comprehensively test all of the language
semantics and compiler passes. These are run with `sbt runtime/test`. For
newer functionalities, we prefer adding tests to the `Tests` project in the

View File

@ -17,7 +17,7 @@ import org.graalvm.polyglot.PolyglotException
import java.io.File
import java.nio.file.{Path, Paths}
import java.util.{Collections, UUID}
import java.util.{HashMap, UUID}
import scala.Console.err
import scala.concurrent.duration._
@ -30,6 +30,7 @@ object Main {
private val RUN_OPTION = "run"
private val INSPECT_OPTION = "inspect"
private val DUMP_GRAPHS_OPTION = "dump-graphs"
private val HELP_OPTION = "help"
private val NEW_OPTION = "new"
private val PROJECT_NAME_OPTION = "new-project-name"
@ -99,6 +100,10 @@ object Main {
.longOpt(INSPECT_OPTION)
.desc("Start the Chrome inspector when --run is used.")
.build
val dumpGraphs = CliOption.builder
.longOpt(DUMP_GRAPHS_OPTION)
.desc("Dumps IGV graphs when --run is used.")
.build
val docs = CliOption.builder
.longOpt(DOCS_OPTION)
.desc("Runs the Enso documentation generator.")
@ -345,6 +350,7 @@ object Main {
.addOption(repl)
.addOption(run)
.addOption(inspect)
.addOption(dumpGraphs)
.addOption(docs)
.addOption(preinstall)
.addOption(newOpt)
@ -505,6 +511,7 @@ object Main {
* @param logMasking is the log masking enabled
* @param enableIrCaches are IR caches enabled
* @param inspect shall inspect option be enabled
* @param dump shall graphs be sent to the IGV
*/
private def run(
path: String,
@ -513,7 +520,8 @@ object Main {
logMasking: Boolean,
enableIrCaches: Boolean,
enableAutoParallelism: Boolean,
inspect: Boolean
inspect: Boolean,
dump: Boolean
): Unit = {
val file = new File(path)
if (!file.exists) {
@ -535,6 +543,14 @@ object Main {
}
file.getAbsolutePath
} else projectPath.getOrElse("")
val options = new HashMap[String, String]()
if (dump) {
options.put("engine.TraceCompilation", "true")
options.put("engine.MultiTier", "false")
}
if (inspect) {
options.put("inspect", "")
}
val context = new ContextFactory().create(
projectRoot,
System.in,
@ -545,9 +561,7 @@ object Main {
enableIrCaches,
strictErrors = true,
enableAutoParallelism = enableAutoParallelism,
options =
if (inspect) Collections.singletonMap("inspect", "")
else Collections.emptyMap
options = options
)
if (projectMode) {
PackageManager.Default.loadPackage(file) match {
@ -1013,7 +1027,8 @@ object Main {
logMasking,
shouldEnableIrCaches(line),
line.hasOption(AUTO_PARALLELISM_OPTION),
line.hasOption(INSPECT_OPTION)
line.hasOption(INSPECT_OPTION),
line.hasOption(DUMP_GRAPHS_OPTION)
)
}
if (line.hasOption(REPL_OPTION)) {

130
tools/enso4igv/README.md Normal file
View File

@ -0,0 +1,130 @@
# Enso Language Support for NetBeans & Ideal Graph Visualizer
[![Enso Language Support for IGV](https://github.com/enso-org/enso/actions/workflows/enso4igv.yml/badge.svg)](https://github.com/enso-org/enso/actions/workflows/enso4igv.yml)
[Enso language](http://enso.org) runtime engine is built on top of
[GraalVM](http://graalvm.org) and its _Truffle framework_. Enso, as a good
citizen of the GraalVM ecosystem, benefits from polyglot capabilities of GraalVM
as well as its rich tooling offering. One of such tools is _IGV_ - the _Ideal
Graph Visualizer_ - an excellent tool to get insights into behavior of Graal
compiler.
This document shows how to use _IGV_ with the _Enso language_. The command line
instructions format is Unix oriented. Use instructions appropriate for your
operating system to perform the same on different _OS_. _IGV_ itself as well as
the _Enso language_ support are platform neutral with launch scripts for all
major operating systems.
## Installation
Visit [GraalVM.org](http://graalvm.org) download page and continue towards
_enterprise edition_ option. There is an _Ideal Graph Visualizer_ option. After
clicking through the confirmation dialogs you should get a ZIP - I've just got
`idealgraphvisualizer-22.1.0.zip` and then:
```bash
$ unzip idealgraphvisualizer-22.1.0.zip
$ ./idealgraphvisualizer/bin/idealgraphvisualizer --userdir /tmp/emptyuserdir
```
launches the _IGV_ application. One doesn't have to use the `--userdir` option,
but doing so ensures the newly running _IGV_ process is isolated from any
settings left around by previous usage of _IGV_.
IGV understands Enso when
[Enso Language Support module](https://github.com/enso-org/enso/actions/workflows/enso4igv.yml)
is installed. Login to GitHub, follow the
[GitHub actions link](https://github.com/enso-org/enso/actions/workflows/enso4igv.yml)
and select a build. Unless you have some special needs choose the latest one.
The build summary page provides various information as well as list of artifacts
at the bottom. Download the _Enso IGV Plugin_ ZIP file (make sure you are logged
into GitHub - artifacts are only available to those logged in). Unzip it and get
`enso*.nbm` file. This file can be installed into _IGV_ (or any other
[NetBeans](http://netbeans.apache.org) based application). Go to
_Tools_/_Plugins_/_Downloaded_/_Add Plugins_ and select the NBM file.
![Tools/Plugins/Downloaded](https://user-images.githubusercontent.com/26887752/174608153-9f0b54fa-b507-45be-83de-d7911186d121.png)
Proceed by clicking _Install_. You may be asked to download _TextMate Lexer_ - a
necessary dependency of the _Enso support_ module. Continue through the wizard
to _finish_ the installation.
![Tools/Plugins/Downloaded](https://user-images.githubusercontent.com/26887752/174608219-1faf2728-0045-478b-a297-e3c06f691b19.png)
## Using the IGV
Get an instance of the Enso runtime engine (see
[Running Enso](../../docs/CONTRIBUTING.md#running-enso)) and then launch it with
special `--dump-graphs` option:
```bash
enso$ ./built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso --dump-graphs --run yourprogram.enso
```
When executed on [GraalVM 21.3.0](http://graalvm.org) these options instruct the
_Graal/Truffle compiler_ to dump files into `graal_dumps/_sometimestamp_`
directory. Generating these files takes a while - make sure `yourprogram.enso`
runs long enough for the system to warmup, compile the code and run at _full
speed_.
#### Sieve of Eratosthenes Example
As an example you can download
[sieve.enso](https://github.com/jtulach/sieve/blob/5b32450da35415322e683bb9769aa45f0d71f1df/enso/sieve.enso)
which computes hundred thousand of prime numbers repeatedly and measures time of
each round. Download the file and launch Enso with `--dump-graphs` argument:
```bash
enso$ ./built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso --dump-graphs --run sieve.enso
```
Bunch of files in `graal_dumps/*` subdirectory is going to be generated:
```bash
enso$ ls graal_dumps/*/Truffle* | tail -n5
graal_dumps/2022.06.20.06.18.21.733/TruffleHotSpotCompilation-9889[argument<2>].bgv
graal_dumps/2022.06.20.06.18.21.733/TruffleHotSpotCompilation-9896[IfThenElseMethodGen@3af870b9_<split-62b6b4f3>]_1.bgv
graal_dumps/2022.06.20.06.18.21.733/TruffleHotSpotCompilation-9896[IfThenElseMethodGen@3af870b9_<split-62b6b4f3>].bgv
graal_dumps/2022.06.20.06.18.21.733/TruffleHotSpotCompilation-9935[Primes.next_<split-717d5bdf>]_1.bgv
graal_dumps/2022.06.20.06.18.21.733/TruffleHotSpotCompilation-9935[Primes.next_<split-717d5bdf>].bgv
```
Let's launch IGV with Enso integration and let's open graph for one of the
top-most functions: `TruffleHotSpotCompilation*Primes*next*.bgv`. Choose
compilation phase _"Before lowering"_:
![Before Lowering Graph](https://user-images.githubusercontent.com/26887752/174608397-331a4438-1f12-40b0-9fcd-59eda5e53fb6.png)
Now you can inspect the _compiler graphs_ the regular _IGV_ way. Let's locate
for example `LoadField#FunctionSchema.isFullyApplied` node and let's check how
it got _inlined_(you can use search box in the top-right corner)
![Inlining Stacktrace](https://user-images.githubusercontent.com/26887752/174608478-e7002c43-d746-42c0-b61c-92ceb9d9f124.png)
The stack trace shows what methods of the Enso interpreter and Truffle runtime
are _"inlined on stack"_ when this node is being compiled. This is all regular
_IGV_ functionality, but now we can switch to _Enso view_:
![Enso Source](https://user-images.githubusercontent.com/26887752/174608595-4ce80b00-949a-4b28-84a7-60d5988bfc70.png)
By choosing the _Enso language icon_ in front of the stack trace combo, the
source code of our `.enso` program is opened and we can analyze what _compiler
nodes_ refer to what lines in the our _Enso_ program. Click _Navigate to Source_
icon in the _Stack View_ to get from graph node to source. Select a drop down
widget in the editor toolbar to show you what compiler nodes as associated with
currently selected line.
## Building
The plugin can be rebuilt using [Apache Maven](http://maven.apache.org). The
build is platform independent. The following instructions are for Unix like
environment. Switch to this directory and invoke:
```bash
enso/tools/enso4igv$ mvn clean install
enso/tools/enso4igv$ ls target/*.nbm
target/enso4igv-1.0-SNAPSHOT.nbm
```
an NBM file is generated which can be installed into IGV, NetBeans or any other
NetBeans based application.

111
tools/enso4igv/pom.xml Normal file
View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.enso.tools</groupId>
<artifactId>enso4igv</artifactId>
<packaging>nbm</packaging>
<name>Enso Language Support for NetBeans &amp; Ideal Graph Visualizer</name>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.netbeans.utilities</groupId>
<artifactId>nbm-maven-plugin</artifactId>
<extensions>true</extensions>
<version>4.7</version>
<configuration>
<useOSGiDependencies>true</useOSGiDependencies>
<author>Enso.org</author>
<licenseName>Apache 2.0</licenseName>
<licenseFile>../../LICENSE</licenseFile>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-netbeans-api-annotations-common</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-netbeans-modules-textmate-lexer</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-netbeans-api-templates</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-filesystems</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-loaders</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-nodes</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util-lookup</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util-ui</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-windows</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-text</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-netbeans-core-multiview</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-awt</artifactId>
<version>${netbeans.version}</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-dialogs</artifactId>
<version>${netbeans.version}</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<netbeans.version>RELEASE113</netbeans.version>
</properties>
</project>

View File

@ -0,0 +1,112 @@
package org.enso.tools.enso4igv;
import java.io.IOException;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.netbeans.core.spi.multiview.text.MultiViewEditorElement;
import org.netbeans.modules.textmate.lexer.api.GrammarRegistration;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.MIMEResolver;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectExistsException;
import org.openide.loaders.MultiDataObject;
import org.openide.loaders.MultiFileLoader;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.TopComponent;
@Messages({
"LBL_Enso_LOADER=Files of Enso"
})
@MIMEResolver.ExtensionRegistration(
displayName = "#LBL_Enso_LOADER",
mimeType = "application/x-enso",
extension = {"enso"}
)
@GrammarRegistration(mimeType = "application/x-enso", grammar = "enso.tmLanguage.json")
@DataObject.Registration(
mimeType = "application/x-enso",
iconBase = "org/enso/tools/enso4igv/enso.png",
displayName = "#LBL_Enso_LOADER",
position = 300
)
@ActionReferences({
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.OpenAction"),
position = 100,
separatorAfter = 200
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "Edit", id = "org.openide.actions.CutAction"),
position = 300
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "Edit", id = "org.openide.actions.CopyAction"),
position = 400,
separatorAfter = 500
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"),
position = 600
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.RenameAction"),
position = 700,
separatorAfter = 800
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"),
position = 900,
separatorAfter = 1000
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.FileSystemAction"),
position = 1100,
separatorAfter = 1200
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.ToolsAction"),
position = 1300
),
@ActionReference(
path = "Loaders/application/x-enso/Actions",
id = @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"),
position = 1400
)
})
public class EnsoDataObject extends MultiDataObject {
public EnsoDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
super(pf, loader);
registerEditor("application/x-enso", true);
}
@Override
protected int associateLookup() {
return 1;
}
@MultiViewElement.Registration(
displayName = "#LBL_Enso_EDITOR",
iconBase = "org/enso/tools/enso4igv/enso.png",
mimeType = "application/x-enso",
persistenceType = TopComponent.PERSISTENCE_ONLY_OPENED,
preferredID = "Enso",
position = 1000
)
@Messages("LBL_Enso_EDITOR=Source")
public static MultiViewEditorElement createEditor(Lookup lkp) {
return new MultiViewEditorElement(lkp);
}
}

View File

@ -0,0 +1,4 @@
@TemplateRegistration(folder = "Other", content = "EnsoTemplate.enso")
package org.enso.tools.enso4igv;
import org.netbeans.api.templates.TemplateRegistration;

View File

@ -0,0 +1,4 @@
Manifest-Version: 1.0
OpenIDE-Module-Layer: org/enso/tools/enso4igv/layer.xml
OpenIDE-Module-Localizing-Bundle: org/enso/tools/enso4igv/Bundle.properties

View File

@ -0,0 +1,7 @@
EnsoLanguage=Enso
OpenIDE-Module-Name=Enso for IGV
OpenIDE-Module-Short-Description=Enso language support for IGV
OpenIDE-Module-Long-Description=Provides Text Mate grammar for Enso language \
as well as integration with IGV to properly analyze IGV graphs generated \
for the Enso programs.
OpenIDE-Module-Display-Category=Editing

View File

@ -0,0 +1,10 @@
from Standard.Base import all
fac : Number -> Number
fac n =
facacc : Number -> Number -> Number
facacc n v = if n <= 1 then v else @Tail_Call facacc n-1 n*v
facacc n 1
main = IO.println (here.fac 6)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,148 @@
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "Enso",
"patterns": [{
"include": "#keywords"
},
{
"include": "#strings"
},
{
"include": "#entity"
},
{
"include": "#constant"
},
{
"include":"#comments"
}
],
"repository": {
"keywords": {
"patterns": [{
"name": "keyword.other",
"match": "\\b(here|this|type)\\b"
}, {
"name": "keyword.control",
"match": "\\b(case|of|if|then|else)\\b"
}, {
"name": "keyword.control.import",
"match": "\\b(import as|export as|from all hiding|polyglot java)\\b"
},
{
"name": "keyword.control.import",
"match": "^import\\s+.+(\\s+as.+)?$"
},
{
"name": "keyword.control.import",
"match": "^from\\s+.+(\\s+as.+)?\\s+import.+$"
},
{
"name": "keyword.control.import",
"match": "^export\\s+.+(\\s+as.+)?$"
},
{
"name": "keyword.control.import.enso",
"match": "^from\\s+.+(\\s+as.+)?\\s+export.+$"
},
{
"name": "keyword.control.import",
"match": "^polyglot\\s+java\\s+import\\s+.+(\\s+as.+)?$"
},
{
"name": "keyword.operator",
"match": "[-!$%&\\*\\+\/<=>\\?^|~:.]+|\\b_\\b"
},
{
"name": "keyword.operator",
"match": "="
}
]
},
"entity": {
"patterns": [{
"name": "entity.name.function",
"match": "\\b[a-z][a-z|_]*\\b"
},
{
"name": "entity.name.type",
"match": "\\b[A-Z][a-z|0-9]*(_|[A-Z|0-9]|[a-z|0-9]*)*\\b"
},
{
"name": "entity.name",
"match": "\\b[a-z|A-Z]\\w*\\b"
}
]
},
"strings": {
"name": "string.quoted.double",
"patterns": [{
"name": "string.quoted.double",
"begin": "\"",
"end": "\"",
"patterns": [{
"name": "constant.character.escape",
"matches": "\\\""
}]
},
{
"name": "string.quoted.single",
"begin": "\\'",
"end": "\\'",
"patterns": [{
"name": "constant.character.escape",
"matches": "\\\\'"
}]
}
]
},
"constant": {
"patterns": [{
"name": "constant.character",
"match": "\\\\u\\{[A-F|0-9]{1,8}\\}"
},
{
"name": "constant.character",
"match": "\\\\u\\{[A-F|0-9]{4}\\}"
},
{
"name": "constant.character",
"match": "\\\\U\\{[A-F|0-9]{8}\\}"
},
{
"name": "constant.character.escape",
"match": "\\\\"
},
{
"name": "constant.character.escape",
"match": "\\\""
},
{
"name": "constant.character.escape",
"match": "\\'"
},
{
"name": "constant.character.escape",
"match": "\\[abfnrtve]"
},
{
"name": "constant.character.numeric",
"match": "\\b[0-9]+(\\.[0-9]+)?"
}
]
},
"comments":{
"patterns": [{
"name": "comment.block.documentation",
"begin": "^(\\s*)##",
"end": "^(?!\\1\\s+)(?!\\s*$)"
},
{
"name":"comment.line.number-sign",
"begin": "#",
"end": "$"
}]
}
},
"scopeName": "source.enso"
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
<folder name="IGV">
<folder name="Languages">
<folder name="enso">
<attr name="displayName" bundlevalue="org.enso.tools.enso4igv.Bundle#EnsoLanguage"/>
<attr name="mimetype" stringvalue="application/x-enso"/>
<attr name="iconBase" stringvalue="org/enso/tools/enso4igv/enso.png"/>
</folder>
</folder>
</folder>
</filesystem>