From cae323e64b99d222ae55ac0f8cb64665ce0a34cf Mon Sep 17 00:00:00 2001 From: Marc Geilen Date: Sun, 8 May 2022 21:23:54 +0200 Subject: [PATCH] added generators --- .../build.gradle | 10 +- .../ComputationalModelingCompiler.java} | 8 +- .../lang/generator/DataflowGenerator.xtend | 21 +- .../generator/DataflowGeneratorGraphviz.xtend | 111 ++++++++ .../generator/DataflowGeneratorSDF3.xtend | 103 ++++++++ .../FiniteStateAutomataGenerator.xtend | 20 +- ...FiniteStateAutomataGeneratorGraphviz.xtend | 93 +++++++ .../LinearTemporalLogicGenerator.xtend | 17 +- .../LinearTemporalLogicGeneratorLaTeX.xtend | 170 ++++++++++++ .../generator/MarkovChainsGenerator.xtend | 20 +- .../MarkovChainsGeneratorGraphviz.xtend | 64 +++++ .../MarkovChainsGeneratorOctave.xtend | 243 ++++++++++++++++++ .../generator/MaxPlusMatrixGenerator.xtend | 17 +- .../MaxPlusMatrixGeneratorLaTeX.xtend | 155 +++++++++++ .../RegularExpressionsGenerator.xtend | 15 +- .../RegularExpressionsGeneratorLaTeX.xtend | 133 ++++++++++ src/readme.md | 2 + 17 files changed, 1164 insertions(+), 38 deletions(-) rename src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/src/main/java/{org/xtext/computationalmodelling/codegen/compiler/ComputationalModellingCompiler.java => info/computationalmodeling/codegen/compiler/ComputationalModelingCompiler.java} (94%) create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorGraphviz.xtend create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorSDF3.xtend create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGeneratorGraphviz.xtend create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGeneratorLaTeX.xtend create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorGraphviz.xtend create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorOctave.xtend create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MaxPlusMatrixGeneratorLaTeX.xtend create mode 100644 src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGeneratorLaTeX.xtend diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/build.gradle b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/build.gradle index ac46c8b..b20e2d2 100644 --- a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/build.gradle +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/build.gradle @@ -5,15 +5,15 @@ dependencies { api group: 'commons-io', name: 'commons-io', version: '2.0.1'} apply plugin: 'application' -mainClassName = "info.computationalmodeling.lang.codegen.compiler.ComputationalModellingCompiler" +mainClassName = "info.computationalmodeling.lang.codegen.compiler.ComputationalModelingCompiler" startScripts { - applicationName = 'computational-modelling-codegen' + applicationName = 'computational-modeling-codegen' } task standaloneStartScript(type: CreateStartScripts) { - mainClassName = 'info.computationalmodeling.lang.codegen.compiler.ComputationalModellingCompiler' - applicationName = 'computational-modelling-codegen' + mainClassName = 'info.computationalmodeling.lang.codegen.compiler.ComputationalModelingCompiler' + applicationName = 'computational-modeling-codegen' outputDir = new File(project.buildDir, 'scripts') classpath = jar.outputs.files + project.configurations.runtimeClasspath } @@ -27,7 +27,7 @@ jar { manifest { attributes 'Implementation-Title': '5XIE0 Code Generator', 'Implementation-Version': '1.0', - 'Main-Class': 'info.computationalmodeling.lang.codegen.compiler.ComputationalModellingCompiler' + 'Main-Class': 'info.computationalmodeling.lang.codegen.compiler.ComputationalModelingCompiler' } } diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/src/main/java/org/xtext/computationalmodelling/codegen/compiler/ComputationalModellingCompiler.java b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/src/main/java/info/computationalmodeling/codegen/compiler/ComputationalModelingCompiler.java similarity index 94% rename from src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/src/main/java/org/xtext/computationalmodelling/codegen/compiler/ComputationalModellingCompiler.java rename to src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/src/main/java/info/computationalmodeling/codegen/compiler/ComputationalModelingCompiler.java index d2694f0..48ad245 100644 --- a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/src/main/java/org/xtext/computationalmodelling/codegen/compiler/ComputationalModellingCompiler.java +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang.codegen.compiler/src/main/java/info/computationalmodeling/codegen/compiler/ComputationalModelingCompiler.java @@ -29,7 +29,7 @@ import com.google.inject.Inject; import com.google.inject.Provider; -public class ComputationalModellingCompiler { +public class ComputationalModelingCompiler { @Inject private Provider resourceSetProvider; @@ -47,7 +47,7 @@ private static void exitError(String msg) { private static void showUsage() { System.out.println("Usage:"); - System.out.println("computational-modelling-codegen "); + System.out.println("computational-modeling-codegen "); } public static void main(String[] args) { @@ -109,8 +109,10 @@ public static void main(String[] args) { } if (injector != null) { - ComputationalModellingCompiler comp = injector.getInstance(ComputationalModellingCompiler.class); + ComputationalModelingCompiler comp = injector.getInstance(ComputationalModelingCompiler.class); comp.runGenerator(filename, outputdir); + } else { + exitError("Failed to create injector."); } } diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGenerator.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGenerator.xtend index e43f865..2c49d33 100644 --- a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGenerator.xtend +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGenerator.xtend @@ -7,6 +7,8 @@ import org.eclipse.emf.ecore.resource.Resource import org.eclipse.xtext.generator.AbstractGenerator import org.eclipse.xtext.generator.IFileSystemAccess2 import org.eclipse.xtext.generator.IGeneratorContext +import info.computationalmodeling.lang.DataflowRuntimeModule +import com.google.inject.Guice /** * Generates code from your model files on save. @@ -15,11 +17,20 @@ import org.eclipse.xtext.generator.IGeneratorContext */ class DataflowGenerator extends AbstractGenerator { + com.google.inject.Injector injector = Guice.createInjector(new DataflowRuntimeModule()); + DataflowGeneratorGraphviz genA = new DataflowGeneratorGraphviz(); + DataflowGeneratorSDF3 genB = new DataflowGeneratorSDF3(); + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { -// fsa.generateFile('greetings.txt', 'People to greet: ' + -// resource.allContents -// .filter(Greeting) -// .map[name] -// .join(', ')) + + // generate both Graphviz and SDF3 files at the same time + + // first Graphviz + injector.injectMembers(genA); + genA.doGenerate(resource, fsa, context); + + // then SDF3 + injector.injectMembers(genB); + genB.doGenerate(resource, fsa, context); } } diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorGraphviz.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorGraphviz.xtend new file mode 100644 index 0000000..5c7040f --- /dev/null +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorGraphviz.xtend @@ -0,0 +1,111 @@ +/* + * generated by Xtext 2.19.0 + */ +package info.computationalmodeling.lang.generator + +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtext.generator.AbstractGenerator +import org.eclipse.xtext.generator.IFileSystemAccess2 +import org.eclipse.xtext.generator.IGeneratorContext +import com.google.inject.Inject +import org.eclipse.xtext.naming.IQualifiedNameProvider +import info.computationalmodeling.lang.dataflow.DataflowModel +import info.computationalmodeling.lang.dataflow.Edge +import info.computationalmodeling.lang.DataflowSupport + +/** + * Generates code from your model files on save. + * + * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation + */ +class DataflowGeneratorGraphviz extends AbstractGenerator { + + + @Inject extension IQualifiedNameProvider + + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { + + + for (m : resource.allContents.toIterable.filter(DataflowModel)) { + var ds = new DataflowSupport() + ds.getChannelNames(m) + ds.extractActorProperties(m) + ds.extractInputOutputNames(m) + ds.extractChannelProperties(m) + ds.determinePortNames(m) + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".dot", + m.compile(ds) + ) + } + } + + def compile(DataflowModel m, DataflowSupport ds) ''' + digraph «m.name» { + rankdir="LR"; + graph [bgcolor=transparent,overlap=false] + node [fontsize=20 fontname="Calibri" fillcolor="#FDF498" width=0.6 penwidth=2 style=filled shape=circle] + edge [fontsize=16 fontname="Calibri"] + «this.compileActors(m, ds)» + «this.compileInputs(m, ds)» + «this.compileOutputs(m, ds)» + «this.compileGraph(m, ds)» + } + ''' + + def compileActors(DataflowModel m, DataflowSupport ds) ''' + «FOR a: ds.setOfActors(m)» + «a» [label="«a»\n«ds.getExecutionTime(a)»"] + «ENDFOR» + + ''' + + def compileInputs(DataflowModel m, DataflowSupport ds) ''' + «FOR i:m.inputs» + «i.name» [shape=point, label="«i.name»", fillcolor="#000000" width=0.05 style=filled] + «ENDFOR» + + ''' + + def compileOutputs(DataflowModel m, DataflowSupport ds) ''' + «FOR o:m.outputs» + «o.name» [shape=point, label="«o.name»", fillcolor="#000000" width=0.05 style=filled] + «ENDFOR» + + ''' + + def compileGraph(DataflowModel m, DataflowSupport ds) ''' + «FOR e:m.edges» + «this.compileEdge(m, e, ds)» + «ENDFOR» + + ''' + + def String prodLabel(Edge e) { + } + + def compileInputEdge(Edge e, DataflowSupport ds) ''' + «e.srcact.name» -> «e.dstact.name» [minlen=1 len=1 xlabel="" headlabel="" taillabel="«e.srcact.name»"] + ''' + + def compileOutputEdge(Edge e, DataflowSupport ds) ''' + «e.srcact.name» -> «e.dstact.name» [minlen=1 len=1 xlabel="" headlabel="«e.dstact.name»" taillabel=""] + ''' + + def compileRegularEdge(Edge e, DataflowSupport ds) ''' + «e.srcact.name» -> «e.dstact.name» [minlen=3 len=3 xlabel="«ds.getInitialTokens(e).toString»" headlabel="«ds.getConsRate(e).toString»" taillabel="«ds.getProdRate(e).toString»"] + ''' + + + def compileEdge(DataflowModel m, Edge e, DataflowSupport ds) ''' + «IF ds.inputNames.contains(e.srcact.name)» + «compileInputEdge(e, ds)» + «ELSE» + «IF ds.outputNames.contains(e.dstact.name)» + «compileOutputEdge(e, ds)» + «ELSE» + «compileRegularEdge(e, ds)» + «ENDIF» + «ENDIF» + ''' +} diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorSDF3.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorSDF3.xtend new file mode 100644 index 0000000..e59e601 --- /dev/null +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/DataflowGeneratorSDF3.xtend @@ -0,0 +1,103 @@ +/* + * generated by Xtext 2.19.0 + */ +package info.computationalmodeling.lang.generator + +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtext.generator.AbstractGenerator +import org.eclipse.xtext.generator.IFileSystemAccess2 +import org.eclipse.xtext.generator.IGeneratorContext +import com.google.inject.Inject +import org.eclipse.xtext.naming.IQualifiedNameProvider +import info.computationalmodeling.lang.dataflow.DataflowModel +import info.computationalmodeling.lang.DataflowSupport +import java.util.Map + +/** + * Generates code from your model files on save. + * + * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation + */ +class DataflowGeneratorSDF3 extends AbstractGenerator { + + + @Inject extension IQualifiedNameProvider + + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { + + + for (m : resource.allContents.toIterable.filter(DataflowModel)) { + var ds = new DataflowSupport() + ds.getChannelNames(m) + ds.extractActorProperties(m) + ds.extractChannelProperties(m) + ds.determinePortNames(m) + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".sdfx", + m.compile(ds)) + } + } + + + + // Below the code generation methods + + def compile(DataflowModel m, DataflowSupport ds) ''' + + + + + «this.compileActorlist(m, ds)» + «this.compileChannellist(m, ds)» + + + «this.compileActorProperties(m, ds)» + «this.compileChannelProperties(m, ds)» + + + + ''' + + + def compileActorlist(DataflowModel m, DataflowSupport ds) ''' + «FOR a: ds.setOfActors(m)» + + «this.compilePortsOfActor(a, ds)» + + «ENDFOR» + ''' + + def compilePortsOfActor(String a, DataflowSupport ds) ''' + «FOR p: ds.getPortsOfActor(a).entrySet» + «this.compilePort(p)» + «ENDFOR» + ''' + + def compilePort(Map.Entry> p) ''' + + ''' + + def compileChannellist(DataflowModel m, DataflowSupport ds) ''' + «FOR e: m.edges» + + «ENDFOR» + ''' + + def compileActorProperties(DataflowModel m, DataflowSupport ds)''' + «FOR a: ds.setOfActors(m)» + + + + + + «ENDFOR» + ''' + + def compileChannelProperties(DataflowModel m, DataflowSupport ds)''' + «FOR e: m.edges» + + «ENDFOR» + ''' + + +} diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGenerator.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGenerator.xtend index 66e18bb..75a1743 100644 --- a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGenerator.xtend +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGenerator.xtend @@ -7,6 +7,8 @@ import org.eclipse.emf.ecore.resource.Resource import org.eclipse.xtext.generator.AbstractGenerator import org.eclipse.xtext.generator.IFileSystemAccess2 import org.eclipse.xtext.generator.IGeneratorContext +import info.computationalmodeling.lang.FiniteStateAutomataRuntimeModule +import com.google.inject.Guice /** * Generates code from your model files on save. @@ -15,11 +17,19 @@ import org.eclipse.xtext.generator.IGeneratorContext */ class FiniteStateAutomataGenerator extends AbstractGenerator { + com.google.inject.Injector injector = Guice.createInjector(new FiniteStateAutomataRuntimeModule()); + FiniteStateAutomataGeneratorGraphviz genA = new FiniteStateAutomataGeneratorGraphviz(); + //FiniteStateAutomataGeneratorB genB = new FiniteStateAutomataGeneratorB(); + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { -// fsa.generateFile('greetings.txt', 'People to greet: ' + -// resource.allContents -// .filter(Greeting) -// .map[name] -// .join(', ')) + + // generate graphviz image + injector.injectMembers(genA); + genA.doGenerate(resource, fsa, context); + + // then some other generator perhaps + // injector.injectMembers(genB); + //genB.doGenerate(resource, fsa, context); } + } diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGeneratorGraphviz.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGeneratorGraphviz.xtend new file mode 100644 index 0000000..3362834 --- /dev/null +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/FiniteStateAutomataGeneratorGraphviz.xtend @@ -0,0 +1,93 @@ +/* + * generated by Xtext 2.19.0 + */ +package info.computationalmodeling.lang.generator + +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtext.generator.AbstractGenerator +import org.eclipse.xtext.generator.IFileSystemAccess2 +import org.eclipse.xtext.generator.IGeneratorContext +import com.google.inject.Inject +import org.eclipse.xtext.naming.IQualifiedNameProvider +import info.computationalmodeling.lang.finitestateautomata.FiniteStateAutomatonModel +import info.computationalmodeling.lang.finitestateautomata.Edge +import info.computationalmodeling.lang.finitestateautomata.State +import info.computationalmodeling.lang.finitestateautomata.UndecoratedState +import info.computationalmodeling.lang.FiniteStateAutomataSupport +import org.eclipse.emf.common.util.EList + +/** + * Generates code from your model files on save. + * + * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation + */ +class FiniteStateAutomataGeneratorGraphviz extends AbstractGenerator { + + + @Inject extension IQualifiedNameProvider + + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { + + for (m : resource.allContents.toIterable.filter(FiniteStateAutomatonModel)) { + var ds = new FiniteStateAutomataSupport() + ds.extractProperties(m) + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".dot", + m.compile(ds) + ) + } + } + + def compile(FiniteStateAutomatonModel m, FiniteStateAutomataSupport ds) ''' + digraph «m.name» { + rankdir="LR"; + graph [bgcolor=transparent,overlap=false] + node [fontsize=20 fontname="Calibri" fillcolor="#98FDF4" width=0.6 penwidth=2 style=filled shape=circle] + edge[fontsize=16 fontname="Calibri"] + «this.compileGraph(m, ds)» + } + ''' + + def compileGraph(FiniteStateAutomatonModel m, FiniteStateAutomataSupport ds) ''' + «FOR s: ds.setOfStates» + «this.compileState(s, ds)» + «ENDFOR» + init [shape=point, label="", fillcolor="#000000" width=0.05 style=filled] + «FOR e:m.edges» + «this.compileEdge(e, ds)» + «ENDFOR» + «FOR s: ds.setOfStates» + «this.compileInitialEdge(s, ds)» + «ENDFOR» + + ''' + + def compileEdge(Edge e, FiniteStateAutomataSupport ds) ''' + "«stateName(e.srcstate)»" -> "«stateName(e.dststate)»" [minlen=3 len=3 xlabel="«ds.getEdgeLabel(e)»"] + ''' + + def stateName(State s) { + return stateName(s.ustate) + } + + def stateName(EList l) { + return l.map[UndecoratedState us | stateName(us)] + } + + def String stateName(UndecoratedState s) { + if (s.name !== null) return s.name + if (s.stateSet !== null) return '''{«String.join(',', stateName(s.stateSet.states))»}''' + if (s.stateTuple !== null) return '''(«String.join(',', stateName(s.stateTuple.states))»)''' + return "error!" + } + + + def compileState(String s, FiniteStateAutomataSupport ds) ''' + "«s»" [ «IF ds.stateProperties.get(s).contains('final')»peripheries = 2«ENDIF»«IF ds.stateToolTips.containsKey(s)» tooltip="«ds.stateToolTips.get(s)»"«ENDIF»] + ''' + + def compileInitialEdge(String s, FiniteStateAutomataSupport ds) ''' + «IF ds.stateProperties.get(s).contains('initial')»init -> "«s»" [minlen=2 len=2]«ENDIF» + ''' + +} diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGenerator.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGenerator.xtend index da4534f..981f315 100644 --- a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGenerator.xtend +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGenerator.xtend @@ -7,6 +7,9 @@ import org.eclipse.emf.ecore.resource.Resource import org.eclipse.xtext.generator.AbstractGenerator import org.eclipse.xtext.generator.IFileSystemAccess2 import org.eclipse.xtext.generator.IGeneratorContext +import info.computationalmodeling.lang.LinearTemporalLogicRuntimeModule +import com.google.inject.Guice + /** * Generates code from your model files on save. @@ -15,11 +18,15 @@ import org.eclipse.xtext.generator.IGeneratorContext */ class LinearTemporalLogicGenerator extends AbstractGenerator { + com.google.inject.Injector injector = Guice.createInjector(new LinearTemporalLogicRuntimeModule()); + LinearTemporalLogicGeneratorLaTeX genLaTeX = new LinearTemporalLogicGeneratorLaTeX(); + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { -// fsa.generateFile('greetings.txt', 'People to greet: ' + -// resource.allContents -// .filter(Greeting) -// .map[name] -// .join(', ')) + + + injector.injectMembers(genLaTeX); + genLaTeX.doGenerate(resource, fsa, context); + } + } diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGeneratorLaTeX.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGeneratorLaTeX.xtend new file mode 100644 index 0000000..ac22911 --- /dev/null +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/LinearTemporalLogicGeneratorLaTeX.xtend @@ -0,0 +1,170 @@ +/* + * generated by Xtext 2.19.0 + */ +package info.computationalmodeling.lang.generator + +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtext.generator.AbstractGenerator +import org.eclipse.xtext.generator.IFileSystemAccess2 +import org.eclipse.xtext.generator.IGeneratorContext +import com.google.inject.Inject +import org.eclipse.xtext.naming.IQualifiedNameProvider +import info.computationalmodeling.lang.lineartemporallogic.LTLModel +import info.computationalmodeling.lang.lineartemporallogic.LTLFormula +import java.util.List +import info.computationalmodeling.lang.lineartemporallogic.LTLFormula1 +import info.computationalmodeling.lang.lineartemporallogic.LTLFormula2 +import info.computationalmodeling.lang.lineartemporallogic.LTLFormula3 +import info.computationalmodeling.lang.lineartemporallogic.LTLFormula4 +import info.computationalmodeling.lang.lineartemporallogic.LTLFormula5 +import info.computationalmodeling.lang.lineartemporallogic.LTLFormula6 +import info.computationalmodeling.lang.lineartemporallogic.SetOfSymbols +import info.computationalmodeling.lang.lineartemporallogic.Definition + +/** + * Generates code from your model files on save. + * + * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation + */ +class LinearTemporalLogicGeneratorLaTeX extends AbstractGenerator { + + + @Inject extension IQualifiedNameProvider + + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { + + + for (m : resource.allContents.toIterable.filter(LTLModel)) { + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".LaTeX", + m.compileLaTeX) + } + } + + + def compileLaTeX(LTLModel m) ''' + \begin{array}{l} + «compileLTLFormula(m.formula)» \\ + «IF m.alphabet !== null» + \mathrm{alphabet} ~\{«compileSetOfSymbols(m.alphabet)»\} \\ + «ENDIF» + «IF m.definitions.length > 0» + \mathrm{where} \\ + \begin{align} + «compileDefinitions(m.definitions)» + \end{align}\\ + «ENDIF» + \end{array} + ''' + + def compileSetOfSymbols(SetOfSymbols ss) { + return ss.symbols.join(", ") + } + + def compileDefinitions(List defs) ''' + «FOR d: defs» + \mathit{«d.proposition»} & = \{«compileSetOfSymbols(d.symbols)»\} \\ + «ENDFOR» + ''' + + def CharSequence compileLTLFormula(LTLFormula re) { + if (re.alternatives.length>0) { + return compileLTLFormula1(re.formula) + compileOrTerms(re.alternatives) + } else { + return compileLTLFormula1(re.formula) + } + } + + def compileOrTerms(List alt) { + return " \\vee {" + (alt.map [a | a.compileLTLFormula1 ].join("} \\vee {")) + "}" + } + + def compileLTLFormula1(LTLFormula1 re) { + if (re.alternatives.length>0) { + return compileLTLFormula2(re.formula) + compileAndTerms(re.alternatives) + } else { + return compileLTLFormula2(re.formula) + } + } + + def compileAndTerms(List alt) { + return " \\wedge {" + (alt.map [a | a.compileLTLFormula2 ].join("} \\wedge {")) + "}" + } + + + def CharSequence compileLTLFormula2(LTLFormula2 re) { + // subexpression1 = LTLFormula3 ('U' subexpression2 = LTLFormula3)? + if (re.subexpression2 !== null) return compileUntilFormula(re.subexpression1, re.subexpression2) + return compileLTLFormula3(re.subexpression1) + } + + def compileUntilFormula(LTLFormula3 re1, LTLFormula2 re2) { + return compileLTLFormula3(re1) + " U " + compileLTLFormula2(re2) + } + + def CharSequence compileLTLFormula3(LTLFormula3 re) { + // subexpression1 = LTLFormula4 ('R' subexpression2 = LTLFormula4)? + if (re.subexpression2 !== null) return compileReleaseFormula(re.subexpression1, re.subexpression2) + return compileLTLFormula4(re.subexpression1) + } + + def compileReleaseFormula(LTLFormula4 re1, LTLFormula3 re2) { + return compileLTLFormula4(re1) + " R " + compileLTLFormula3(re2) + } + + def CharSequence compileLTLFormula4(LTLFormula4 re) { + if (re.consequence !== null) return compileLTLFormula5(re.subexpression) + compileImplicationFormula(re.consequence) + return compileLTLFormula5(re.subexpression) + } + + def CharSequence compileLTLFormula5(LTLFormula5 re) { + if (re.nextSubexpression !== null) return compileNextFormula(re.nextSubexpression) + if (re.eventuallySubexpression !== null) return compileEventuallyFormula(re.eventuallySubexpression) + if (re.alwaysSubexpression !== null) return compileAlwaysFormula(re.alwaysSubexpression) + if (re.notSubexpression !== null) return compileNotFormula(re.notSubexpression) + return compileLTLFormula6(re.subexpression) + } + + def compileNextFormula(LTLFormula5 re) { + return " X " + compileLTLFormula5(re) + } + def compileEventuallyFormula(LTLFormula5 re) { + return " F " + compileLTLFormula5(re) + } + def compileAlwaysFormula(LTLFormula5 re) { + return " G " + compileLTLFormula5(re) + } + + + def compileImplicationFormula(LTLFormula4 re) { + return " \\Rightarrow{} " + compileLTLFormula4(re) + } + + def compileNotFormula(LTLFormula5 re) { + return " \\neg " + compileLTLFormula5(re) + } + + def compileLTLFormula6(LTLFormula6 re) { + // propositionExpression = PropositionExpression | '(' expression = LTLFormula ')' + if (re.propositionExpression !== null) return compileProposition(re.propositionExpression) + if (re.trueExpression !== null) return "{\\mathrm{true}}" + if (re.falseExpression !== null) return "{\\mathrm{false}}" + return compileInParentheses(re.expression) + } + + def compileInParentheses(LTLFormula re) ''' + \left( {«re.compileLTLFormula»} \right) + ''' + + def compileProposition(String prop) { + if (prop.charAt(0) == '\'') { + return "\\mathit{"+prop.substring(1, prop.length-1)+"}" + } else { + return prop + } + } + + +} + + diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGenerator.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGenerator.xtend index 9d77fc1..b70e569 100644 --- a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGenerator.xtend +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGenerator.xtend @@ -7,6 +7,8 @@ import org.eclipse.emf.ecore.resource.Resource import org.eclipse.xtext.generator.AbstractGenerator import org.eclipse.xtext.generator.IFileSystemAccess2 import org.eclipse.xtext.generator.IGeneratorContext +import info.computationalmodeling.lang.MarkovChainsRuntimeModule +import com.google.inject.Guice /** * Generates code from your model files on save. @@ -15,11 +17,19 @@ import org.eclipse.xtext.generator.IGeneratorContext */ class MarkovChainsGenerator extends AbstractGenerator { + com.google.inject.Injector injector = Guice.createInjector(new MarkovChainsRuntimeModule()); + MarkovChainsGeneratorOctave genA = new MarkovChainsGeneratorOctave(); + MarkovChainsGeneratorGraphviz genB = new MarkovChainsGeneratorGraphviz(); + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { -// fsa.generateFile('greetings.txt', 'People to greet: ' + -// resource.allContents -// .filter(Greeting) -// .map[name] -// .join(', ')) + + // generate matrix description + injector.injectMembers(genA); + genA.doGenerate(resource, fsa, context); + + // generate graphviz description + injector.injectMembers(genB); + genB.doGenerate(resource, fsa, context); } + } diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorGraphviz.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorGraphviz.xtend new file mode 100644 index 0000000..35f40a9 --- /dev/null +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorGraphviz.xtend @@ -0,0 +1,64 @@ +/* + * generated by Xtext 2.19.0 + */ +package info.computationalmodeling.lang.generator + +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtext.generator.AbstractGenerator +import org.eclipse.xtext.generator.IFileSystemAccess2 +import org.eclipse.xtext.generator.IGeneratorContext +import com.google.inject.Inject +import org.eclipse.xtext.naming.IQualifiedNameProvider +import info.computationalmodeling.lang.markovchains.MarkovChainModel +import info.computationalmodeling.lang.MarkovChainSupport +import info.computationalmodeling.lang.markovchains.Edge + +/** + * Generates code from your model files on save. + * + * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation + */ +class MarkovChainsGeneratorGraphviz extends AbstractGenerator { + + + @Inject extension IQualifiedNameProvider + + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { + + for (m : resource.allContents.toIterable.filter(MarkovChainModel)) { + var ds = new MarkovChainSupport() + ds.extractProperties(m) + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".dot", + m.compile(ds)) + } + } + + + def compile(MarkovChainModel m, MarkovChainSupport ds) ''' + digraph «m.name» { + rankdir="LR"; + graph [bgcolor=transparent] + node [fontsize=20 fontname="Calibri" fillcolor="#F498FD" width=0.6 penwidth=2 style=filled shape=circle] + edge [fontsize=16 fontname="Calibri"] + «this.compileGraph(m, ds)» + } + ''' + + def compileGraph(MarkovChainModel m, MarkovChainSupport ds) ''' + «FOR e:m.edges» + «this.compileEdge(e, ds)» + «ENDFOR» + + ''' + + def compileEdge(Edge e, MarkovChainSupport ds) ''' + "«e.srcstate.name»" -> "«e.dststate.name»" [label="«MarkovChainSupport.probabilityLabel(e)»" ] + ''' + +// def compileEdge(Edge e, MarkovChainSupport ds) ''' +// "«ds.graphVizStateLabel(e.srcstate)»" -> "«ds.graphVizStateLabel(e.dststate)»" [label="«MarkovChainSupport.probabilityLabel(e)»" ] +// ''' + + +} diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorOctave.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorOctave.xtend new file mode 100644 index 0000000..bc6c9bf --- /dev/null +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/MarkovChainsGeneratorOctave.xtend @@ -0,0 +1,243 @@ +/* + * generated by Xtext 2.19.0 + */ +package info.computationalmodeling.lang.generator + +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtext.generator.AbstractGenerator +import org.eclipse.xtext.generator.IFileSystemAccess2 +import org.eclipse.xtext.generator.IGeneratorContext +import com.google.inject.Inject +import org.eclipse.xtext.naming.IQualifiedNameProvider +import info.computationalmodeling.lang.markovchains.MarkovChainModel +import info.computationalmodeling.lang.MarkovChainSupport +import java.math.BigInteger +import java.lang.Math +import org.apache.commons.math.fraction.BigFraction +/** + * Generates code from your model files on save. + * + * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation + */ +class MarkovChainsGeneratorOctave extends AbstractGenerator { + + + @Inject extension IQualifiedNameProvider + + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { + + + for (m : resource.allContents.toIterable.filter(MarkovChainModel)) { + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".mat", + m.compile) + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".LaTeX", + m.compileLaTeX) + } + } + + + + + def compile(MarkovChainModel m) { + val states = MarkovChainSupport.getStates(m) + val numbStates = states.length + val stateIndex = MarkovChainSupport.createStateIndex(states) + val trans = MarkovChainSupport.transitionProbabilities(m, states, stateIndex) + + val builder = new StringBuilder(); + builder.append("[").append("\n"); + var i = 0 + for (var r=0; r result + } + + // to be improved, give a nice representation of the double value, round to a close 'round' number, e.g., 0.1 instead of 0.10000002 + // perhaps even select a number of decimal place for the whole matrix + def prettyFmt(double d) { + return String.format("%.3f", d) + } + + def fractionLaTeXBuilder(BigFraction frac, int numbStates, BigInteger[] intTrans) { + val builder = new StringBuilder(); + builder.append("\\frac{").append(frac.numerator.toString).append("}{").append(frac.denominator.toString).append("}\\cdot\n"); + builder.append("\\begin{bmatrix}").append("\n"); + var i = 0 + for (var r=0; r result) result = exp ; + } + } + return result + } + + def minExponent(double[] numbers) { + var result = 100 + for (var i=0; i= 2) { + factor = Math.pow(10.0d, minExp) + factorStr = "10^{"+minExp.toString+"}" + } else { + if (maxExp <= -2) { + factor = Math.pow(10.0d, maxExp) + factorStr = "10^{"+minExp.toString+"}" + } + } + + val dblProbFact = multiplyArray(dblProb, factor) + + if (factor != 1.0d) { + builder.append(factorStr) + builder.append("\\cdot\n") + } + + builder.append("\\begin{bmatrix}").append("\n"); + var i = 0 + for (var r=0; r vectors) { + var res = new ArrayList>() + if (vectors.length == 0) { + return res + } + var j = 0 + for (v: vectors) { + var i = 0 + for (e: v.elements) { + if (res.length <= i) { + res.add(new ArrayList()) + while (res.get(i).size() < j){ + res.get(i).add("-inf") + } + } + res.get(i).add(e) + i += 1 + } + j += 1 + } + return res + } + + def compileRow(Row r) { + var res = "" + var i = 0 + for (e: r.elements) { + if (i > 0) { + res += " & " + } + i = i+1 + if (e == "-inf") { + res += " - \\infty{}" + } + else { + res += e + } + } + return res + } + + def compileRowOfStrings(ArrayList r) { + var res = "" + var i = 0 + for (e: r) { + if (i > 0) { + res += " & " + } + i = i+1 + if (e == "-inf") { + res += " - \\infty{}" + } + else { + res += e + } + } + return res + } + +} + + diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGenerator.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGenerator.xtend index c30a92c..7bed6d5 100644 --- a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGenerator.xtend +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGenerator.xtend @@ -7,6 +7,8 @@ import org.eclipse.emf.ecore.resource.Resource import org.eclipse.xtext.generator.AbstractGenerator import org.eclipse.xtext.generator.IFileSystemAccess2 import org.eclipse.xtext.generator.IGeneratorContext +import info.computationalmodeling.lang.RegularExpressionsRuntimeModule +import com.google.inject.Guice /** * Generates code from your model files on save. @@ -15,11 +17,14 @@ import org.eclipse.xtext.generator.IGeneratorContext */ class RegularExpressionsGenerator extends AbstractGenerator { + com.google.inject.Injector injector = Guice.createInjector(new RegularExpressionsRuntimeModule()); + RegularExpressionsGeneratorLaTeX genLaTeX = new RegularExpressionsGeneratorLaTeX(); + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { -// fsa.generateFile('greetings.txt', 'People to greet: ' + -// resource.allContents -// .filter(Greeting) -// .map[name] -// .join(', ')) + + // generate + injector.injectMembers(genLaTeX); + genLaTeX.doGenerate(resource, fsa, context); + } } diff --git a/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGeneratorLaTeX.xtend b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGeneratorLaTeX.xtend new file mode 100644 index 0000000..559c33e --- /dev/null +++ b/src/info.computationalmodeling.lang.codegen.parent/info.computationalmodeling.lang/src/main/java/info/computationalmodeling/lang/generator/RegularExpressionsGeneratorLaTeX.xtend @@ -0,0 +1,133 @@ +/* + * generated by Xtext 2.19.0 + */ +package info.computationalmodeling.lang.generator + +import org.eclipse.emf.ecore.resource.Resource +import org.eclipse.xtext.generator.AbstractGenerator +import org.eclipse.xtext.generator.IFileSystemAccess2 +import org.eclipse.xtext.generator.IGeneratorContext +import com.google.inject.Inject +import org.eclipse.xtext.naming.IQualifiedNameProvider +import info.computationalmodeling.lang.regularexpressions.RegExModel +import info.computationalmodeling.lang.regularexpressions.RegularExpression +import java.util.List +import info.computationalmodeling.lang.regularexpressions.RegularExpression1 +import info.computationalmodeling.lang.regularexpressions.RegularExpression2 +import info.computationalmodeling.lang.regularexpressions.RegularExpression3 +import info.computationalmodeling.lang.regularexpressions.ReferenceExpression +import info.computationalmodeling.lang.regularexpressions.Definition + +/** + * Generates code from your model files on save. + * + * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation + */ +class RegularExpressionsGeneratorLaTeX extends AbstractGenerator { + + + @Inject extension IQualifiedNameProvider + + override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { + + + for (m : resource.allContents.toIterable.filter(RegExModel)) { + fsa.generateFile( + m.fullyQualifiedName.toString("/") + ".LaTeX", + m.compileLaTeX) + } + } + + + def compileLaTeX(RegExModel m) ''' + \begin{array}{l} + «compileRegularExpression(m.expression)» \\ + «IF m.definitions.length > 0» + \mathrm{where} \\ + \begin{align} + «compileDefinitions(m.definitions)» + \end{align}\\ + «ENDIF» + \end{array} + ''' + + def compileDefinitions(List defs) ''' + «FOR d: defs» + «d.symbol» & = «compileRegularExpression(d.expression)» \\ + «ENDFOR» + ''' + + + def CharSequence compileRegularExpression(RegularExpression re) { + if (re.alternatives.length>0) { + return compileRegularExpression1(re.expression) + compileAlternatives(re.alternatives) + } else { + return compileRegularExpression1(re.expression) + } + } + + def compileAlternatives(List alt) { + return " + {" + (alt.map [a | a.compileRegularExpression1 ].join("} + {")) + "}" + } + + def compileRegularExpression1(RegularExpression1 re) { + if (re.concatenations.length>0) { + return "{" + compileRegularExpression2(re.expression) + "} \\cdot{} "+ compileConcatenations(re.concatenations) + } else { + return compileRegularExpression2(re.expression) + } + } + + def compileConcatenations(List concats) { + return "{" + (concats.map [c | c.compileRegularExpression2 ].join("} \\cdot{} {")) + "}" + } + + def compileRegularExpression2(RegularExpression2 re) { + if (re.kleene !== null) return compileKleene(re.subexpression) + if (re.omega !== null) return compileOmega(re.subexpression) + return compileRegularExpression3(re.subexpression) + } + + def compileInParentheses(RegularExpression re) ''' + \left( {«re.compileRegularExpression»} \right) + ''' + + def compileKleene(RegularExpression3 re) ''' + {«re.compileRegularExpression3»}^* + ''' + + def compileOmega(RegularExpression3 re) ''' + {«re.compileRegularExpression3»}^{\omega{}} + ''' + + def compileRegularExpression3(RegularExpression3 re) { + if (re.emptyLangExpression !== null) return compileEmptyLanguage() + if (re.emptyWordExpression !== null) return compileEmptyWord() + if (re.letterExpression !== null) return compileLetter(re.letterExpression) + if (re.referenceExpression !== null) return compileReference(re.referenceExpression) + return compileInParentheses(re.expression) + } + + def compileEmptyLanguage() ''' + \emptyset{} + ''' + + def compileEmptyWord() ''' + \epsilon{} + ''' + + def compileLetter(String letter) { + if (letter.charAt(0) == '\'') { + return "\\mathrm{"+letter.substring(1, letter.length-1)+"}" + } else { + return letter + } + } + + def compileReference(ReferenceExpression e) { + return "\\mathit{"+e.reference+"}" + } + +} + + diff --git a/src/readme.md b/src/readme.md index 111d461..52950fb 100644 --- a/src/readme.md +++ b/src/readme.md @@ -22,6 +22,8 @@ Run the image. The results are visible in the mounted volume `/output`. ### In Eclipse +TODO: update + - Open workspace in Eclipse - Import the parent project as an Existing Gradle Project - On project `org.xtext.computationalmodelling.parent`, right-click and select `Gradle`->`Refresh Gradle Project`. Wait for Eclipse to complete the process.