Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rentz-Reichert2018-07-06 17:19:51 +0000
committerHenrik Rentz-Reichert2018-07-06 17:22:00 +0000
commit0509ac03bea494b08a92251e68e9efc92e415a20 (patch)
treed070ca8800c829827df8aff75c1b773fe1115908 /plugins/org.eclipse.etrice.dctools
parentc2dfdeabf15d7e367bcd92731e6ac8651ffb9cac (diff)
parentbed42b94fbf934db15e792b247ee747f0c37ebf4 (diff)
downloadorg.eclipse.etrice-0509ac03bea494b08a92251e68e9efc92e415a20.tar.gz
org.eclipse.etrice-0509ac03bea494b08a92251e68e9efc92e415a20.tar.xz
org.eclipse.etrice-0509ac03bea494b08a92251e68e9efc92e415a20.zip
Merge remote-tracking branch 'newfsmgen_finalize'
Conflicts: plugins/org.eclipse.etrice.ui.behavior.fsm/META-INF/MANIFEST.MF plugins/org.eclipse.etrice.ui.behavior/META-INF/MANIFEST.MF Change-Id: Icc81a851cdcdb35081b8eaa3d5b025c1f850de54
Diffstat (limited to 'plugins/org.eclipse.etrice.dctools')
-rw-r--r--plugins/org.eclipse.etrice.dctools/.classpath8
-rw-r--r--plugins/org.eclipse.etrice.dctools/.gitignore4
-rw-r--r--plugins/org.eclipse.etrice.dctools/.project34
-rw-r--r--plugins/org.eclipse.etrice.dctools/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--plugins/org.eclipse.etrice.dctools/META-INF/MANIFEST.MF23
-rw-r--r--plugins/org.eclipse.etrice.dctools/build.properties5
-rw-r--r--plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/GenModelAccess.xtend36
-rw-r--r--plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCLinker.xtend278
-rw-r--r--plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCTranslator.xtend84
-rw-r--r--plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCUtil.xtend148
-rw-r--r--plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/ITranslationProvider.xtend112
-rw-r--r--plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCProposalConfig.xtend98
-rw-r--r--plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCTranslatorVisitor.xtend246
13 files changed, 1083 insertions, 0 deletions
diff --git a/plugins/org.eclipse.etrice.dctools/.classpath b/plugins/org.eclipse.etrice.dctools/.classpath
new file mode 100644
index 000000000..428337e56
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/.classpath
@@ -0,0 +1,8 @@
+<?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.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="xtend-gen"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.etrice.dctools/.gitignore b/plugins/org.eclipse.etrice.dctools/.gitignore
new file mode 100644
index 000000000..1a7726dc2
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/.gitignore
@@ -0,0 +1,4 @@
+bin
+*._trace
+*.smap
+*.xtendbin
diff --git a/plugins/org.eclipse.etrice.dctools/.project b/plugins/org.eclipse.etrice.dctools/.project
new file mode 100644
index 000000000..af0ef944b
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.etrice.dctools</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <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>
+ <nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.etrice.dctools/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.etrice.dctools/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..0c68a61dc
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/plugins/org.eclipse.etrice.dctools/META-INF/MANIFEST.MF b/plugins/org.eclipse.etrice.dctools/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..9a9f24843
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/META-INF/MANIFEST.MF
@@ -0,0 +1,23 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Detail Code Tools
+Bundle-SymbolicName: org.eclipse.etrice.dctools
+Bundle-Version: 1.1.3.qualifier
+Bundle-Vendor: Eclipse eTrice
+Automatic-Module-Name: org.eclipse.etrice.dctools
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: com.google.guava,
+ org.eclipse.emf.ecore,
+ org.eclipse.jface.text,
+ org.eclipse.xtext.xbase.lib,
+ org.eclipse.xtend.lib,
+ org.eclipse.xtend.lib.macro,
+ org.eclipse.xtext.ui,
+ org.eclipse.etrice.core.fsm,
+ org.eclipse.etrice.core.room,
+ org.eclipse.etrice.dctools.fsm;visibility:=reexport,
+ org.eclipse.etrice.generator.fsm,
+ org.eclipse.etrice.core.genmodel.fsm
+Export-Package: org.eclipse.etrice.dctools,
+ org.eclipse.etrice.dctools.ast
+
diff --git a/plugins/org.eclipse.etrice.dctools/build.properties b/plugins/org.eclipse.etrice.dctools/build.properties
new file mode 100644
index 000000000..d8e2f0e92
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/build.properties
@@ -0,0 +1,5 @@
+source.. = src/,\
+ xtend-gen/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/GenModelAccess.xtend b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/GenModelAccess.xtend
new file mode 100644
index 000000000..340b069b8
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/GenModelAccess.xtend
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * 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:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools
+
+import java.util.Map
+import org.eclipse.etrice.core.RoomStandaloneSetup
+import org.eclipse.etrice.core.fsm.fSM.ModelComponent
+import org.eclipse.etrice.core.genmodel.fsm.ExtendedFsmGenBuilder
+import org.eclipse.etrice.core.genmodel.fsm.fsmgen.GraphContainer
+
+class GenModelAccess {
+
+ Map<ModelComponent, GraphContainer> cache = newHashMap
+
+ def public GraphContainer get(ModelComponent mc) {
+ if(!cache.containsKey(mc)) {
+ val injector = new RoomStandaloneSetup().createInjector
+ val builder = new ExtendedFsmGenBuilder(injector);
+ val gc = builder.createTransformedModel(mc)
+ builder.withCommonData(gc)
+ cache.put(mc, gc)
+ }
+
+ return cache.get(mc)
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCLinker.xtend b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCLinker.xtend
new file mode 100644
index 000000000..d703ea1ff
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCLinker.xtend
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * 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:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.ast
+
+import java.util.Deque
+import java.util.LinkedList
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.EReference
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.eclipse.etrice.core.fsm.fSM.StateGraphItem
+import org.eclipse.etrice.core.room.ActorClass
+import org.eclipse.etrice.core.room.Attribute
+import org.eclipse.etrice.core.room.DataClass
+import org.eclipse.etrice.core.room.EnumerationType
+import org.eclipse.etrice.core.room.InterfaceItem
+import org.eclipse.etrice.core.room.MessageData
+import org.eclipse.etrice.core.room.Operation
+import org.eclipse.etrice.core.room.Port
+import org.eclipse.etrice.core.room.PortClass
+import org.eclipse.etrice.core.room.RoomClass
+import org.eclipse.etrice.core.room.SAP
+import org.eclipse.etrice.core.room.VarDecl
+import org.eclipse.etrice.core.room.util.RoomHelpers
+import org.eclipse.etrice.dctools.fsm.ast.CandidateMap
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstArrayAccessNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstFeatureCallNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstIdentifierNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstOperationCallNode
+import org.eclipse.etrice.dctools.fsm.ast.util.IDCAstNodeVisitor
+
+import static org.eclipse.etrice.core.fsm.fSM.FSMPackage.Literals.*
+
+import static extension org.eclipse.xtext.EcoreUtil2.*
+import org.eclipse.etrice.core.fsm.fSM.DetailCode
+
+class DCLinker implements IDCAstNodeVisitor {
+
+ enum FeatureType {
+ SCALAR,
+ ARRAY,
+ OPERATION
+ }
+
+ EObject owner
+ EReference reference
+ MessageData transitionData
+
+ protected val extension RoomHelpers roomHelpers = new RoomHelpers
+
+ val Deque<EObject> contexts = new LinkedList
+
+ new(DetailCode dc) {
+ this(dc.eContainer, dc.eContainingFeature as EReference)
+ }
+
+ new(EObject owner, EReference reference) {
+ this(owner, reference, null)
+ }
+
+ new(DetailCode dc, MessageData transitionData) {
+ this(dc.eContainer, dc.eContainingFeature as EReference, transitionData)
+ }
+
+ new(EObject owner, EReference reference, MessageData transitionData) {
+ this.owner = owner
+ this.reference = reference
+ this.transitionData = transitionData
+ }
+
+ override visitBegin(DCAstNode node) {
+ switch node {
+ DCAstFeatureCallNode: {
+ // a feature call always starts in the global context
+ contexts.push(owner)
+ }
+ DCAstIdentifierNode case node.parent instanceof DCAstFeatureCallNode: link(node)
+ DCAstArrayAccessNode: link(node)
+ DCAstOperationCallNode: link(node)
+ }
+
+ return true
+ }
+
+ override visitEnd(DCAstNode node) {
+ switch node {
+ DCAstFeatureCallNode: contexts.pop
+ }
+ }
+
+ protected def dispatch void link(DCAstIdentifierNode node) {
+ node.doLink(FeatureType.SCALAR, node.id)
+ }
+
+ protected def dispatch void link(DCAstArrayAccessNode node) {
+ node.doLink(FeatureType.ARRAY, node.id)
+ }
+
+ protected def dispatch void link(DCAstOperationCallNode node) {
+ node.doLink(FeatureType.OPERATION, node.id)
+ }
+
+ protected def void doLink(DCAstNode node, FeatureType ft, String name) {
+ val candidates = getCandidates(ft)
+ node.linkedObject = candidates.get(name)
+ node.linkedData = candidates
+ replaceContext(node.linkedObject)
+ }
+
+ protected def replaceContext(EObject obj) {
+ contexts.pop
+ contexts.push(obj?.contextOf)
+ }
+
+ protected def dispatch getContextOf(EObject obj) {
+ null
+ }
+
+ protected def dispatch getContextOf(Port port) {
+ port
+ }
+
+ protected def dispatch getContextOf(Attribute att) {
+ att.type.type
+ }
+
+ protected def dispatch getContextOf(VarDecl vd) {
+ vd.refType.type
+ }
+
+ protected def dispatch getContextOf(MessageData md) {
+ md?.refType?.type
+ }
+
+ protected def dispatch getContextOf(Operation op) {
+ op?.returnType?.type
+ }
+
+ //http://git.eclipse.org/c/etrice/org.eclipse.etrice.git/tree/tests/org.eclipse.etrice.generator.common.tests/models/EnumTest.room?h=newfsmgen_finalize&id=79aa00b074c61bde5173d4859ce2b52e50b52dec#n117
+
+ protected def getCandidates(FeatureType type) {
+ val candidates = new CandidateMap
+
+ if (contexts.peek===owner) {
+ // this is the top level
+ topLevelCandidates(candidates, type)
+ }
+ else {
+ val current = contexts.peek
+ switch current {
+ DataClass: {
+ current.getCandidates(type, candidates)
+ }
+
+ InterfaceItem: {
+ current.getCandidates(candidates)
+ }
+
+ Attribute case current.type?.type instanceof DataClass: {
+ val dc = current.type.type as DataClass
+ dc.getCandidates(type, candidates)
+ }
+ MessageData case current.refType?.type instanceof DataClass: {
+ val dc = current.refType.type as DataClass
+ dc.getCandidates(type, candidates)
+ }
+ EnumerationType: {
+ // from descriptions, have to be resolved
+ var enumType = current
+ if (current.eIsProxy) {
+ val resolved = EcoreUtil.resolve(current, owner)
+ if (resolved instanceof EnumerationType)
+ enumType = resolved
+ }
+ enumType.literals.forEach[candidates.put(it.name, it)]
+ }
+ }
+ }
+
+ return candidates
+ }
+
+ protected def void topLevelCandidates(CandidateMap candidates, FeatureType type) {
+ // operation arguments
+ owner.getContainerOfType(Operation)?.arguments?.forEach[candidates.put(it.name, it)]
+
+ // TODO: compare with org.eclipse.etrice.expressions.detailcode.DetailExpressionProvider.initialFsmExpression(EObject, ActorClass, List<ExpressionFeature>)
+ if (!reference.name.contains('userCode')) {
+ val roomClass = owner.getContainerOfType(RoomClass)
+ switch roomClass {
+ ActorClass: {
+ if (transitionData!==null) {
+ candidates.put("transitionData", transitionData)
+ }
+ if (type==FeatureType.SCALAR) {
+ roomClass.allAttributes.forEach[candidates.put(it.name, it)]
+ }
+ if (type==FeatureType.ARRAY) {
+ roomClass.allAttributes.filter[size>1].forEach[candidates.put(it.name, it)]
+ }
+ if (type==FeatureType.OPERATION) {
+ roomClass.latestOperations.forEach[candidates.put(it.name, it)]
+ }
+ roomClass.allInterfaceItems.forEach[
+ switch it {
+ Port case type==FeatureType.SCALAR: candidates.put(it.name, it)
+ Port case type==FeatureType.ARRAY && it.replicated: candidates.put(it.name, it)
+ SAP case type==FeatureType.SCALAR: candidates.put(it.name, it)
+ }
+ ]
+ }
+
+ DataClass: {
+ roomClass.getCandidates(type, candidates)
+ }
+
+ case owner.getContainerOfType(PortClass)!==null: {
+ val portClass = owner.getContainerOfType(PortClass)
+ // TODO inheritance
+ portClass.operations.forEach[candidates.put(it.name, it)]
+ portClass.attributes.forEach[candidates.put(it.name, it)]
+ }
+ }
+ }
+ }
+
+ protected def void getCandidates(DataClass dataClass, FeatureType type, CandidateMap candidates) {
+ if (type==FeatureType.SCALAR) {
+ dataClass.allAttributes.forEach[candidates.put(it.name, it)]
+ }
+ if (type==FeatureType.ARRAY) {
+ dataClass.allAttributes.filter[size>1].forEach[candidates.put(it.name, it)]
+ }
+ if (type==FeatureType.OPERATION) {
+ dataClass.latestOperations.forEach[candidates.put(it.name, it)]
+ }
+ }
+
+ protected def void getCandidates(InterfaceItem ifItem, CandidateMap candidates) {
+ // operations
+ ifItem.protocol.getAllOperations(!ifItem.conjugated).forEach[candidates.put(it.name, it)]
+
+ // messages
+ switch reference {
+ case CP_BRANCH_TRANSITION__CONDITION,
+ case GUARDED_TRANSITION__GUARD,
+ case GUARD__GUARD: {
+ val pc = ifItem.protocol
+ switch pc?.commType {
+ case DATA_DRIVEN:
+ if (!ifItem.conjugated) pc.allIncomingMessages.forEach[candidates.put(it.name, it)]
+ case EVENT_DRIVEN: { /* no async message calls */}
+ case SYNCHRONOUS: {}
+ }
+ }
+ case owner.getContainerOfType(StateGraphItem)!==null: {
+ val pc = ifItem.protocol
+ switch pc?.commType {
+ case EVENT_DRIVEN:
+ pc.getAllMessages(ifItem.conjugated).forEach[candidates.put(it.name, it)]
+ case DATA_DRIVEN:
+ pc.allIncomingMessages.forEach[candidates.put(it.name, it)]
+ case SYNCHRONOUS: {}
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCTranslator.xtend b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCTranslator.xtend
new file mode 100644
index 000000000..7c72cd54b
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCTranslator.xtend
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2018 protos software gmbh (http://www.protos.de).
+ * 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:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.ast
+
+import org.eclipse.etrice.generator.fsm.generic.IDetailCodeTranslator
+import org.eclipse.etrice.core.fsm.fSM.DetailCode
+import org.eclipse.etrice.dctools.ast.internal.DCTranslatorVisitor
+import org.eclipse.etrice.core.room.util.RoomHelpers
+import org.eclipse.etrice.generator.fsm.base.IFSMTranslationProvider
+import org.eclipse.etrice.dctools.fsm.ast.DCLanguage
+import org.eclipse.etrice.dctools.fsm.ast.DCParser
+import org.eclipse.etrice.core.room.MessageData
+
+class DCTranslator implements IDetailCodeTranslator {
+
+ DCLanguage language
+ ITranslationProvider translationProvider
+
+ val extension RoomHelpers roomHelpers = new RoomHelpers
+
+ new(DCLanguage language, ITranslationProvider translationProvider) {
+ this.language = language
+ this.translationProvider = translationProvider
+ }
+
+ override getTranslatedCode(DetailCode dc) {
+ return getTranslatedCode(dc, null)
+ }
+
+ def getTranslatedCode(DetailCode dc, MessageData transitionData) {
+ var code = dc.detailCode
+
+ // before the actual parsing is done we translate tags
+ if (translationProvider.translateTags) {
+ code = translateTags(code, dc)
+ }
+
+ // parse
+ val parser = new DCParser(language)
+ val ast = parser.parse(code)
+
+ // link
+ val linker = new DCLinker(dc, transitionData)
+ ast.visit(linker)
+
+ // translate
+ val visitor = new DCTranslatorVisitor(translationProvider)
+ ast.visit(visitor)
+
+ return visitor.translatedCode
+ }
+
+ def translateTags(String text, DetailCode dc) {
+ val result = new StringBuilder
+
+ var int last = 0
+ var int next = text.indexOf(IFSMTranslationProvider.TAG_START, last)
+ while (next >= 0) {
+ result.append(text.substring(last, next))
+ last = next + IFSMTranslationProvider.TAG_START.length()
+ next = text.indexOf(IFSMTranslationProvider.TAG_END, last)
+ if (next >= 0) {
+ val String tag = text.substring(last, next)
+ result.append(translationProvider.translateTag(tag, dc))
+ last = next + IFSMTranslationProvider.TAG_END.length()
+ next = text.indexOf(IFSMTranslationProvider.TAG_START, last)
+ }
+ }
+ result.append(text.substring(last))
+
+ return result.toString
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCUtil.xtend b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCUtil.xtend
new file mode 100644
index 000000000..e2f580939
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/DCUtil.xtend
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * 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:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.ast
+
+import com.google.inject.Inject
+import java.util.List
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.etrice.core.converter.RoomValueConverterService
+import org.eclipse.etrice.core.fsm.fSM.DetailCode
+import org.eclipse.etrice.core.fsm.fSM.TransitionBase
+import org.eclipse.etrice.core.genmodel.fsm.FsmGenExtensions
+import org.eclipse.etrice.core.room.ActorClass
+import org.eclipse.etrice.core.room.MessageData
+import org.eclipse.etrice.core.room.RoomClass
+import org.eclipse.etrice.dctools.GenModelAccess
+import org.eclipse.etrice.dctools.ast.internal.DCProposalConfig
+import org.eclipse.etrice.dctools.fsm.ast.CandidateMap
+import org.eclipse.etrice.dctools.fsm.ast.DCLanguage
+import org.eclipse.etrice.dctools.fsm.ast.DCNodeAtOffset
+import org.eclipse.etrice.dctools.fsm.ast.DCParser
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstIdentifierNode
+import org.eclipse.jface.text.contentassist.ICompletionProposal
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.xtext.EcoreUtil2
+import org.eclipse.xtext.nodemodel.ILeafNode
+import org.eclipse.xtext.nodemodel.INode
+
+class DCUtil {
+
+ @Accessors
+ static class FindResult {
+ val EObject object
+ val int begin
+ val int length
+ }
+
+ @Inject RoomValueConverterService converterService
+ @Inject DCProposalConfig proposalConfig
+
+ val genModelAccess = new GenModelAccess
+ DCLanguage language = DCLanguage.C_LANGUAGE
+
+ new() {
+ }
+
+ def setLanguage(DCLanguage language) {
+ this.language = language
+ }
+
+ def FindResult findAtOffset(ILeafNode textNode, int offset) {
+ val ast = textNode.parseAndLink
+ val astNode = DCNodeAtOffset.find(ast, offset - textNode.delimiterAdjustedOffset)
+ if (astNode instanceof DCAstIdentifierNode) {
+ val object = getLinkedObject(astNode)
+ if (object !==null) {
+ return new FindResult(object, astNode.begin + converterService.CC_StringConverter.delim.length, astNode.end-astNode.begin)
+ }
+ }
+ return null
+ }
+
+ def getDelimiterAdjustedOffset(INode astNode) {
+ astNode.offset + converterService.CC_StringConverter.delim.length
+ }
+
+ def parseAndLink(INode astNode) {
+ val text = converterService.CC_StringConverter.stripDelim(astNode.getText());
+ val parser = new DCParser(language)
+ val ast = parser.parse(text)
+
+ if (astNode.parent.semanticElement instanceof DetailCode) {
+ val dc = astNode.parent.semanticElement as DetailCode
+
+ var DCLinker linker = null;
+
+ // lets check whether we have a transition and determine common data
+ val transition = EcoreUtil2.getContainerOfType(dc, TransitionBase)
+ if (transition!==null) {
+ val roomClass = EcoreUtil2.getContainerOfType(dc, RoomClass)
+ if (roomClass instanceof ActorClass) {
+ val gc = genModelAccess.get(roomClass)
+ val link = FsmGenExtensions.getLinkFor(gc, transition)
+ if (link!==null) {
+ linker = new DCLinker(dc, link.commonData as MessageData)
+ }
+ }
+ }
+
+ // if we have no common data we use a plain linker
+ if (linker===null) {
+ linker = new DCLinker(dc)
+ }
+
+ ast.visit(linker)
+
+ return ast
+ }
+ else {
+ return null
+ }
+ }
+
+ def List<ICompletionProposal> getProposals(INode textNode, int offset) {
+ val ast = textNode.parseAndLink
+ // note: we subtract 1 to get the token to the left of the caret
+ val astNode = DCNodeAtOffset.find(ast, offset - textNode.delimiterAdjustedOffset - 1)
+ if (astNode instanceof DCAstIdentifierNode) {
+ val candidates = astNode.candidates
+ if (candidates!==null) {
+ val begin = astNode.begin + converterService.CC_StringConverter.delim.length
+ val end = offset - textNode.offset
+ val prefix = textNode.text.substring(begin, end)
+ val matches = candidates.getMatches(prefix)
+ return matches.entrySet.map[match | proposalConfig.doCreateProposal(prefix, match.key, match.value, offset)].toList
+ }
+ }
+
+ newArrayList
+ }
+
+ static def EObject getLinkedObject(DCAstIdentifierNode astNode) {
+ if (astNode.linkedObject!==null) {
+ astNode.linkedObject
+ }
+ else if (astNode.parent!==null) {
+ astNode.parent.linkedObject
+ }
+ }
+
+ static def CandidateMap getCandidates(DCAstIdentifierNode astNode) {
+ if (astNode.linkedData instanceof CandidateMap) {
+ astNode.linkedData as CandidateMap
+ }
+ else if (astNode.parent!==null && astNode.parent.linkedData instanceof CandidateMap) {
+ astNode.parent.linkedData as CandidateMap
+ }
+ }
+}
diff --git a/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/ITranslationProvider.xtend b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/ITranslationProvider.xtend
new file mode 100644
index 000000000..2bb57091d
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/ITranslationProvider.xtend
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * 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:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.ast
+
+import org.eclipse.etrice.core.room.InterfaceItem
+import org.eclipse.etrice.core.fsm.fSM.AbstractInterfaceItem
+import org.eclipse.etrice.core.room.Attribute
+import org.eclipse.etrice.core.room.Message
+import org.eclipse.etrice.core.room.Operation
+import org.eclipse.etrice.core.room.PortOperation
+import org.eclipse.etrice.core.room.EnumLiteral
+import org.eclipse.etrice.dctools.fsm.ast.IFSMTranslationProvider
+
+/**
+ * This interface is used by the detail code translator to replace
+ * common constructs in detail level code with a target language specific
+ * piece of code.
+ * <p>
+ * The constructs that are replaced are
+ * <ul>
+ * <li>attributes</li>
+ * <li>operations</li>
+ * <li>port.message</li>
+ * <li>tags of the form <code><|tag|></code></li>
+ * </ul>
+ * </p>
+ * @see DCTranslator
+ * @author Henrik Rentz-Reichert
+ */
+interface ITranslationProvider extends IFSMTranslationProvider{
+
+ /**
+ * yield text to read an attribute (array index may be null). Is called whenever <i>attribute</i>
+ * or <i>attribute</i>[<i>index</i>] or is
+ * found in the detail code
+ * @param att the actor class attribute
+ * @param instance a pointer to the instance object
+ * @param index the index (should be null for scalars, !=null for arrays)
+ * @param orig the original text
+ * @return the translation
+ */
+ def String getAttributeGetter(Attribute att, String instance, String index, String orig)
+
+ /**
+ * yield text to write an attribute (array index may be null). Is called whenever <i>attribute</i>.set(<i>value</i>)
+ * or <i>attribute</i>[<i>index</i>].set(<i>value</i>) is
+ * found in the detail code
+ * @param att the actor class attribute
+ * @param instance a pointer to the instance object
+ * @param index the index (should be null for scalars, !=null for arrays)
+ * @param value to assign to the attribute
+ * @param orig the original text
+ * @return the translation
+ */
+ def String getAttributeSetter(Attribute att, String instance, String index, String value, String orig)
+
+ /**
+ * yield text for operation call. Is called whenever <i>operation</i>(<i>args</i>)
+ * is found in the detail code
+ * @param op operation to call
+ * @param instance a pointer to the defining class instance
+ * @param args the arguments to pass
+ * @param orig the original text
+ * @return the translation
+ */
+ def String getOperationText(Operation op, String instance, String args, String orig)
+
+ /**
+ * yields a sequence that reads data from a <b>data driven</b> port.
+ * Is called whenever <i>port</i>.<i>msg</i> or <i>port</i>[<i>index</i>].<i>msg</i>
+ * is found in the detail code
+ * @param item the interface item
+ * @param msg the message to read
+ * @param orig the original text
+ * @return the translation
+ */
+ def String getInterfaceItemMessageValue(InterfaceItem item, Message msg, String orig)
+
+ /**
+ * @return true if translations are provided for enumerations
+ */
+ def boolean translateEnums()
+
+ /**
+ * yields a replacement for &lt;enumtype>.&lt;literal>
+ * @param literal the enumeration literal to be translated
+ * @return the translated enumeration literal
+ */
+ def String getEnumText(EnumLiteral literal)
+
+ /**
+ * yields a call to an operation of an interface item
+ * @param item the interface item
+ * @param op the port class operation
+ * @param instance a pointer to the defining class instance
+ * @param args the argument list
+ * @param orig the original test
+ * @return the translation
+ */
+ def String getInterfaceItemOperationText(AbstractInterfaceItem item, PortOperation op, String instance, String args, String orig)
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCProposalConfig.xtend b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCProposalConfig.xtend
new file mode 100644
index 000000000..8f28887cd
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCProposalConfig.xtend
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * 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:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.ast.internal
+
+import com.google.inject.Singleton
+import com.google.inject.Inject
+import org.eclipse.jface.viewers.ILabelProvider
+import org.eclipse.etrice.core.room.util.RoomHelpers
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.jface.viewers.StyledString
+import org.eclipse.swt.graphics.Image
+import org.eclipse.xtext.ui.editor.contentassist.ConfigurableCompletionProposal
+import org.eclipse.xtext.ui.editor.contentassist.PrefixMatcher
+import org.eclipse.jface.text.contentassist.ICompletionProposal
+import org.eclipse.swt.graphics.Point
+import org.eclipse.etrice.core.room.Operation
+import org.eclipse.etrice.core.room.Message
+import org.eclipse.etrice.core.room.Attribute
+import org.eclipse.etrice.core.room.InterfaceItem
+import org.eclipse.etrice.core.room.Port
+
+@Singleton
+class DCProposalConfig {
+
+ @Inject
+ protected ILabelProvider labelProvider
+
+ @Inject
+ protected RoomHelpers roomHelpers
+
+ @Inject
+ protected PrefixMatcher prefixMatcher
+
+ def ICompletionProposal doCreateProposal(String prefix, String proposal, EObject object, int globalOffset) {
+ new ConfigurableCompletionProposal(proposal, globalOffset - prefix.length, prefix.length, proposal.length, object.image, object.displayString, null, null) => [
+ matcher = prefixMatcher
+ autoInsertable = false
+ // TODO adjust length to existing text
+ replaceContextLength = proposal.length
+ ]
+ }
+
+ def Pair<String, Point> getPostfixReplacement(EObject object) {
+ val brackets = switch object {
+ Operation,
+ Message:
+ #['(', ')']
+
+ Attribute case object.size>0,
+ Port case object.multiplicity>0:
+ #['[', ']']
+ }
+
+ if (brackets===null) {
+ return "" -> null
+ }
+
+ val replacement = switch object {
+ Operation:
+ object.arguments.map[name].join(', ')
+
+ Message case object.data !== null:
+ object.data.refType.type.name
+
+ Attribute, // fall through
+ InterfaceItem:
+ '0'
+
+ default:
+ ''
+ }
+
+ replacement.wrap(brackets.head, brackets.last)
+ }
+
+ private def Pair<String, Point> wrap(String text, String left, String right) {
+ val selection = if (!text.empty) new Point(1, text.length)
+ left + text + right -> selection
+ }
+
+ private def StyledString getDisplayString(EObject object) {
+
+ }
+
+ private def Image getImage(EObject object) {
+
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCTranslatorVisitor.xtend b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCTranslatorVisitor.xtend
new file mode 100644
index 000000000..c307273d1
--- /dev/null
+++ b/plugins/org.eclipse.etrice.dctools/src/org/eclipse/etrice/dctools/ast/internal/DCTranslatorVisitor.xtend
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * 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:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.ast.internal
+
+import org.eclipse.etrice.core.room.Attribute
+import org.eclipse.etrice.core.room.InterfaceItem
+import org.eclipse.etrice.core.room.Message
+import org.eclipse.etrice.core.room.Operation
+import org.eclipse.etrice.dctools.ast.ITranslationProvider
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstArrayAccessNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstBracketNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstBracketNode.BracketType
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstIdentifierNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstOperationCallNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstOtherNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstPeriodNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstWhitespaceNode
+import org.eclipse.etrice.dctools.fsm.ast.util.DCAstPrinter
+import org.eclipse.etrice.dctools.fsm.ast.util.IDCAstNodeVisitor
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstFeatureCallNode
+import org.eclipse.etrice.core.room.Port
+import org.eclipse.etrice.core.room.VarDecl
+
+class DCTranslatorVisitor implements IDCAstNodeVisitor {
+
+ ITranslationProvider translationProvider
+
+ val sb = new StringBuilder
+ var currentSB = sb
+
+ new(ITranslationProvider translationProvider) {
+ this.translationProvider = translationProvider
+ }
+
+ def String getTranslatedCode() {
+ sb.toString
+ }
+
+
+ override visitBegin(DCAstNode node) {
+
+ if (node instanceof DCAstBracketNode) {
+ if (node.shouldCollectArguments) {
+ currentSB = new StringBuilder
+ node.linkedData = currentSB
+ }
+ else {
+ currentSB.append(node.left)
+ }
+ }
+ else {
+ if (!node.skipOutput) {
+ switch node {
+ DCAstIdentifierNode: currentSB.append(node.id)
+ DCAstPeriodNode: currentSB.append(".")
+ DCAstWhitespaceNode: currentSB.append(node.text)
+ DCAstOtherNode: currentSB.append(node.text)
+ }
+ }
+ }
+
+ return true
+ }
+
+ override visitEnd(DCAstNode node) {
+ switch node {
+ DCAstBracketNode: {
+ if (node.linkedData!==null) {
+ // leave the nested StringBuilder and switch to the enclosing (or top) one
+ currentSB = node.enclosingSB
+ }
+ else if (node.closed) {
+ currentSB.append(node.right)
+ }
+ }
+
+ DCAstFeatureCallNode case node.canTranslate: node.translate
+ }
+ }
+
+ private def canTranslate(DCAstFeatureCallNode node) {
+ // if all even children are linked then we can translate the whole
+ for (var i=0; i<node.children.size; i=i+2) {
+ if (node.c(i).linkedObject===null) {
+ return false
+ }
+ }
+
+ // make sure the last child is not a period
+ val lastNode = node.children.last
+ if (lastNode instanceof DCAstPeriodNode) {
+ return false
+ }
+
+ return true
+ }
+
+ private def translate(DCAstFeatureCallNode node) {
+ val lastNode = node.children.last
+ var linkedObject = lastNode.linkedObject
+
+ // TODO: handle getter for data driven ports: port.message - i.e. no () after message
+
+ if (lastNode instanceof DCAstOperationCallNode) {
+ if (linkedObject instanceof Message) {
+ handleSendMessage(lastNode, linkedObject)
+ return
+ }
+ }
+
+ node.handleCallChain
+ }
+
+ def handleCallChain(DCAstFeatureCallNode node) {
+ var String instance = null
+ for (var i=0; i<node.children.size; i=i+2) {
+ val childNode = node.c(i)
+ val linkedObject = childNode.linkedObject
+ switch linkedObject {
+ Attribute: {
+ val index = if (childNode instanceof DCAstArrayAccessNode) {
+ (childNode.bracketNode.linkedData as StringBuilder).toString
+ }
+ instance = translationProvider.getAttributeGetter(linkedObject, instance, index, childNode.originalText)
+ }
+
+ VarDecl: {
+ instance = linkedObject.name
+ }
+
+ Operation: {
+ val args = if (childNode instanceof DCAstOperationCallNode) {
+ (childNode.bracketNode.linkedData as StringBuilder).toString
+ }
+ instance = translationProvider.getOperationText(linkedObject, instance, args, childNode.originalText)
+ }
+ }
+ }
+ currentSB.append(instance)
+ }
+
+ private def handleSendMessage(DCAstOperationCallNode msgNode, Message msg) {
+ val args = (msgNode.bracketNode.linkedData as StringBuilder).toString
+ // look back to interface item
+ val ifItemNode = msgNode.parent.c(0)
+ val ifItem = ifItemNode.linkedObject as InterfaceItem
+
+ val translated =
+ if (ifItemNode instanceof DCAstIdentifierNode) {
+ // accessed as scalar (means broadcast for replicated port)
+ val inst = ifItemNode.id
+ translationProvider.getInterfaceItemMessageText(ifItem, msg, inst, args, null, msgNode.originalText)
+ }
+ else if (ifItemNode instanceof DCAstArrayAccessNode) {
+ // accessed as array
+ val inst = ifItemNode.id
+ val index = (ifItemNode.bracketNode.linkedData as StringBuilder).toString
+ translationProvider.getInterfaceItemMessageText(ifItem, msg, inst, args, index, msgNode.originalText)
+ }
+ else {
+ // TODO: assert(false)
+ "internal translator error"
+ }
+ currentSB.append(translated)
+ }
+
+ private def skipOutput(DCAstNode node) {
+ val surroundingContext = node.getEnclosingBracketOrFeatureCall
+
+ // check whether we are inside a bracket without a feature call
+ if (surroundingContext instanceof DCAstBracketNode) {
+ return false
+ }
+
+ if (surroundingContext instanceof DCAstFeatureCallNode) {
+ return surroundingContext.canTranslate
+ }
+
+ return false
+ }
+
+ private def getEnclosingBracketOrFeatureCall(DCAstNode node) {
+ var parent = node.parent
+ while (parent!==null) {
+ if (parent instanceof DCAstFeatureCallNode || parent instanceof DCAstBracketNode) {
+ return parent
+ }
+ parent = parent.parent
+ }
+
+ return null
+ }
+
+ private def getOriginalText(DCAstNode node) {
+ val printer = new DCAstPrinter
+ node.visit(printer)
+ return printer.text
+ }
+
+ private def getEnclosingSB(DCAstBracketNode node) {
+ var parent = node.parent
+ while (parent!==null) {
+ if (parent instanceof DCAstBracketNode && parent.linkedData instanceof StringBuilder) {
+ return parent.linkedData as StringBuilder
+ }
+ parent = parent.parent
+ }
+
+ // return top level
+ return sb
+ }
+
+ private def shouldCollectArguments(DCAstBracketNode node) {
+ val linkedObject = node.parent.linkedObject
+
+ if (node.type==BracketType.CURLY) {
+ false
+ }
+ else if (linkedObject instanceof Operation) {
+ true
+ }
+ else if (linkedObject instanceof Message) {
+ true
+ }
+ else if (linkedObject instanceof Attribute) {
+ true
+ }
+ else if (linkedObject instanceof Port) {
+ true
+ }
+ else {
+ false
+ }
+ }
+} \ No newline at end of file

Back to the top