Added support for local variables to flexmi
diff --git a/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi b/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi
index 51b1544..a5d6a93 100644
--- a/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi
+++ b/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-limit-calculator.flexmi
@@ -2,7 +2,7 @@
<?import types.flexmi?>
<?import library.flexmi?>
<?render-egx comps.egx?>
-<comp name="SpeedLimitCalculator" :var="slc">
+<comp name="SpeedLimitCalculator" :local="slc">
<in name="location" type="geo"/>
<out name="speedLimit" type="float"/>
diff --git a/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-monitor.flexmi b/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-monitor.flexmi
index f4cf988..2c42156 100644
--- a/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-monitor.flexmi
+++ b/examples/org.eclipse.epsilon.examples.flexmi.comps/speed-monitor.flexmi
@@ -3,7 +3,7 @@
<?import library.flexmi?>
<?render-egx comps.egx?>
<_>
- <comp name="SpeedMonitor" :var="sm">
+ <comp name="SpeedMonitor" :local="sm">
<in name="speed" type="float"/>
<in name="location" type="geo"/>
<out name="warning" type="boolean"/>
@@ -13,11 +13,10 @@
<binary_operator name="Comparator" action="result = in1 > in2"
in="float" out="boolean" :var="comp"/>
- <con :from="sm.location" :to="slc.location"/>
+ <con :from="sm.location" :to="sm.SpeedLimitCalculator.location"/>
<con :from="sm.speed" :to="comp.in1"/>
- <con :from="slc.speedLimit" :to="comp.in2"/>
+ <con :from="sm.SpeedLimitCalculator.speedLimit" :to="comp.in2"/>
<con :from="comp.result" :to="sm.warning"/>
</comp>
-
</_>
\ No newline at end of file
diff --git a/examples/org.eclipse.epsilon.examples.flexmi.ecore/debug.flexmi b/examples/org.eclipse.epsilon.examples.flexmi.ecore/debug.flexmi
new file mode 100644
index 0000000..cb97e77
--- /dev/null
+++ b/examples/org.eclipse.epsilon.examples.flexmi.ecore/debug.flexmi
@@ -0,0 +1,9 @@
+<?nsuri http://www.eclipse.org/emf/2002/Ecore?>
+<_>
+ <class name="C1" :local="c">
+ <op :name="'create'+c.name" :type="c"/>
+ </class>
+
+ <class :name="c.name"/>
+
+</_>
\ No newline at end of file
diff --git a/examples/org.eclipse.epsilon.examples.flexmi.ecore/patterns.flexmi b/examples/org.eclipse.epsilon.examples.flexmi.ecore/patterns.flexmi
index d4eaaf1..ddab398 100644
--- a/examples/org.eclipse.epsilon.examples.flexmi.ecore/patterns.flexmi
+++ b/examples/org.eclipse.epsilon.examples.flexmi.ecore/patterns.flexmi
@@ -1,5 +1,5 @@
<?nsuri http://www.eclipse.org/emf/2002/Ecore?>
-<?render-graphviz-dot graphviz.egl?>
+<?render-egx ecore.egx?>
<_>
<singleton name="Log">
@@ -22,7 +22,7 @@
<:template name="singleton">
<content>
- <class :var="c">
+ <class :local="c">
<ref name="instance" :type="c"/>
<op name="getInstance" :type="c"/>
<:slot/>
diff --git a/examples/org.eclipse.epsilon.examples.flexmi.ecore/singleton.flexmi b/examples/org.eclipse.epsilon.examples.flexmi.ecore/singleton.flexmi
index ea7a12d..cdcd94c 100644
--- a/examples/org.eclipse.epsilon.examples.flexmi.ecore/singleton.flexmi
+++ b/examples/org.eclipse.epsilon.examples.flexmi.ecore/singleton.flexmi
@@ -1,14 +1,9 @@
<?nsuri http://www.eclipse.org/emf/2002/Ecore?>
<?render-egx ecore.egx?>
<_>
-
<singleton name="Log">
<attr name="level" type="int"/>
- </singleton>
-
- <singleton name="Log2">
- <attr name="level" type="int"/>
- </singleton>
+ </singleton>
<datatype name="int"/>
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java
index c1a9afd..0c3532c 100644
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/FlexmiResource.java
@@ -37,11 +37,15 @@
import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.epsilon.common.module.AbstractModuleElement;
+import org.eclipse.epsilon.common.module.ModuleElement;
import org.eclipse.epsilon.eol.execute.context.FrameStack;
import org.eclipse.epsilon.flexmi.actions.Action;
+import org.eclipse.epsilon.flexmi.actions.ActionMap;
import org.eclipse.epsilon.flexmi.actions.FeatureComputation;
import org.eclipse.epsilon.flexmi.actions.ObjectInitialization;
import org.eclipse.epsilon.flexmi.actions.VariableDeclaration;
+import org.eclipse.epsilon.flexmi.actions.VariableDeclaration.VariableDeclarationType;
import org.eclipse.epsilon.flexmi.templates.Template;
import org.eclipse.epsilon.flexmi.xml.Location;
import org.eclipse.epsilon.flexmi.xml.PseudoSAXParser;
@@ -63,7 +67,7 @@
protected List<ProcessingInstruction> processingInstructions = new ArrayList<ProcessingInstruction>();
protected EObjectTraceManager eObjectTraceManager = new EObjectTraceManager();
protected List<UnresolvedReference> unresolvedReferences = new ArrayList<UnresolvedReference>();
- protected List<Action> actions = new ArrayList<Action>();
+ // protected List<Action> actions = new ArrayList<Action>();
protected Stack<Object> objectStack = new Stack<Object>();
protected Node currentNode = null;
protected List<String> scripts = new ArrayList<String>();
@@ -75,7 +79,8 @@
protected List<Template> templates = new ArrayList<Template>();
protected BiMap<String, EObject> fullyQualifiedIDs = HashBiMap.create();
protected Map<EObject, String> localIDs = new HashMap<EObject, String>();
- protected Map<String, Object> variables = new HashMap<String, Object>();
+ protected FrameStack frameStack = new FrameStack();
+ protected ActionMap actionMap = new ActionMap();
public void startProcessingFragment(URI uri) {
parsedFragmentURIStack.push(uri);
@@ -240,7 +245,7 @@
EObject parent = (EObject) peek;
if (element.getNodeName().equalsIgnoreCase(Template.PREFIX + "init")) {
- actions.add(new ObjectInitialization(parent, element.getTextContent().trim(), getCurrentURI(), getLineNumber(element)));
+ actionMap.addAction(parent, new ObjectInitialization(parent, element.getTextContent().trim(), getCurrentURI(), getLineNumber(element)));
objectStack.push(null);
return;
}
@@ -356,7 +361,13 @@
@Override
public void endDocument(Document document) {
resolveReferences();
- performActions();
+
+ for (EObject content : getContents()) {
+ performNonLocalVariableDeclarations(content);
+ }
+ for (EObject content : getContents()) {
+ performActions(content);
+ }
}
public List<UnresolvedReference> getUnresolvedReferences() {
@@ -375,8 +386,16 @@
getWarnings().add(new FlexmiDiagnostic(message, uri, line));
}
- protected void performActions() {
- for (Action action : actions) {
+ protected void performActions(EObject eObject) {
+
+ ModuleElement entryPoint = null;
+
+ for (Action action : actionMap.getActions(eObject)) {
+
+ if (entryPoint == null && action instanceof VariableDeclaration && ((VariableDeclaration) action).getType() == VariableDeclarationType.LOCAL) {
+ entryPoint = new AbstractModuleElement() {};
+ ((VariableDeclaration) action).setEntryPoint(entryPoint);
+ }
try {
action.perform(this);
}
@@ -384,6 +403,32 @@
addParseWarning(ex.getMessage(), action.getUri(), action.getLineNumber());
}
}
+
+ for (EObject content : eObject.eContents()) {
+ performNonLocalVariableDeclarations(content);
+ }
+
+ for (EObject content : eObject.eContents()) {
+ performActions(content);
+ }
+
+ if (entryPoint != null) frameStack.leaveLocal(entryPoint);
+ }
+
+ protected void performNonLocalVariableDeclarations(EObject eObject) {
+ List<Action> actions = actionMap.getActions(eObject);
+ List<Action> performed = new ArrayList<Action>();
+ for (Action action : actions) {
+ if (action instanceof VariableDeclaration && ((VariableDeclaration) action).getType() != VariableDeclarationType.LOCAL) {
+ try {
+ action.perform(this);
+ performed.add(action);
+ } catch (Exception ex) {
+ addParseWarning(ex.getMessage(), action.getUri(), action.getLineNumber());
+ }
+ }
+ }
+ actions.removeAll(performed);
}
protected void resolveReferences() {
@@ -438,12 +483,12 @@
return 0;
}
- public void handleVarAttribute(String attribute, boolean collection, NamedNodeMap attributes, EObject eObject) {
+ public void handleVarAttribute(String attribute, VariableDeclarationType type, NamedNodeMap attributes, EObject eObject) {
// Find the _var attribute, create a variable declaration and remove it from the node
Node varAttribute = attributes.getNamedItem(Template.PREFIX + attribute);
if (varAttribute != null) {
for (String variable : varAttribute.getNodeValue().split(",")) {
- actions.add(new VariableDeclaration(eObject, variable.trim(), collection));
+ actionMap.addAction(eObject, new VariableDeclaration(eObject, variable.trim(), type));
}
attributes.removeNamedItem(varAttribute.getNodeName());
}
@@ -456,8 +501,9 @@
if (attributes.getLength() == 0 || eStructuralFeatures.size() == 0) return;
- handleVarAttribute("var", false, attributes, eObject);
- handleVarAttribute("col", true, attributes, eObject);
+ handleVarAttribute("var", VariableDeclarationType.REGULAR, attributes, eObject);
+ handleVarAttribute("local", VariableDeclarationType.LOCAL, attributes, eObject);
+ handleVarAttribute("global", VariableDeclarationType.GLOBAL, attributes, eObject);
Map<Node, EStructuralFeature> allocation = new AttributeStructuralFeatureAllocator().allocate(attributes, eStructuralFeatures);
@@ -468,7 +514,7 @@
EStructuralFeature sf = allocation.get(attribute);
if (name.startsWith(Template.PREFIX)) {
- actions.add(new FeatureComputation(eObject, sf, name, value, getCurrentURI(), getLineNumber(element)));
+ actionMap.addAction(eObject, new FeatureComputation(eObject, sf, name, value, getCurrentURI(), getLineNumber(element)));
}
else {
if (sf instanceof EAttribute) {
@@ -615,8 +661,8 @@
return objectStack.isEmpty() && Template.NODE_NAME.equals(element.getNodeName());
}
- public Map<String, Object> getVariables() {
- return variables;
+ public FrameStack getFrameStack() {
+ return frameStack;
}
public String getLocalId(EObject eObject) {
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/ActionMap.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/ActionMap.java
new file mode 100644
index 0000000..ee26b86
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/ActionMap.java
@@ -0,0 +1,28 @@
+package org.eclipse.epsilon.flexmi.actions;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.emf.ecore.EObject;
+
+public class ActionMap {
+
+ protected Map<EObject, List<Action>> map = new HashMap<EObject, List<Action>>();
+
+ public void addAction(EObject eObject, Action action) {
+ if (!map.containsKey(eObject)) {
+ map.put(eObject, new ArrayList<Action>());
+ }
+ map.get(eObject).add(action);
+ }
+
+ public List<Action> getActions(EObject eObject) {
+ if (!map.containsKey(eObject)) {
+ map.put(eObject, new ArrayList<Action>());
+ }
+ return map.get(eObject);
+ }
+
+}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/FeatureComputation.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/FeatureComputation.java
index 0245289..5682053 100644
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/FeatureComputation.java
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/FeatureComputation.java
@@ -27,15 +27,13 @@
}
public void compute(FlexmiResource resource) throws Exception {
+
InMemoryFlexmiModel model = new InMemoryFlexmiModel(resource);
EolModule module = new EolModule();
module.parse("return " + expression + ";");
if (module.getParseProblems().size() > 0) throw new Exception(module.getParseProblems().get(0).getReason());
- module.getContext().getFrameStack().putGlobal(Variable.createReadOnlyVariable("self", eObject));
module.getContext().getModelRepository().addModel(model);
- for (String variable : resource.getVariables().keySet()) {
- module.getContext().getFrameStack().put(Variable.createReadOnlyVariable(variable, resource.getVariables().get(variable)));
- }
+ module.getContext().setFrameStack(resource.getFrameStack());
eObject.eSet(eStructuralFeature, module.execute());
}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/ObjectInitialization.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/ObjectInitialization.java
index b6ac7d5..dac6b79 100644
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/ObjectInitialization.java
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/ObjectInitialization.java
@@ -4,7 +4,6 @@
import org.eclipse.emf.ecore.EObject;
import org.eclipse.epsilon.emc.emf.InMemoryEmfModel;
import org.eclipse.epsilon.eol.EolModule;
-import org.eclipse.epsilon.eol.execute.context.Variable;
import org.eclipse.epsilon.flexmi.FlexmiResource;
public class ObjectInitialization extends Computation {
@@ -22,11 +21,8 @@
EolModule module = new EolModule();
module.parse(expression);
if (module.getParseProblems().size() > 0) throw new Exception("Parse problem " + module.getParseProblems().get(0).getReason());
- module.getContext().getFrameStack().putGlobal(Variable.createReadOnlyVariable("self", eObject));
module.getContext().getModelRepository().addModel(model);
- for (String variable : resource.getVariables().keySet()) {
- module.getContext().getFrameStack().put(Variable.createReadOnlyVariable(variable, resource.getVariables().get(variable)));
- }
+ module.getContext().setFrameStack(resource.getFrameStack());
module.execute();
}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/VariableDeclaration.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/VariableDeclaration.java
index 04da356..8075d33 100644
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/VariableDeclaration.java
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/actions/VariableDeclaration.java
@@ -1,39 +1,52 @@
package org.eclipse.epsilon.flexmi.actions;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.epsilon.common.module.ModuleElement;
+import org.eclipse.epsilon.eol.execute.context.FrameType;
+import org.eclipse.epsilon.eol.execute.context.Variable;
import org.eclipse.epsilon.flexmi.FlexmiResource;
public class VariableDeclaration extends Action {
protected EObject eObject;
protected String name;
- protected boolean collection;
+ protected VariableDeclarationType type;
+ protected ModuleElement entryPoint;
- public VariableDeclaration(EObject eObject, String name, boolean collection) {
+ public VariableDeclaration(EObject eObject, String name, VariableDeclarationType type) {
super();
this.eObject = eObject;
this.name = name;
- this.collection = collection;
+ this.type = type;
}
@Override
public void perform(FlexmiResource resource) throws Exception {
- Map<String, Object> variables = resource.getVariables();
- if (collection) {
- if (variables.containsKey(name)) {
- ((Collection<Object>) variables.get(name)).add(eObject);
- }
- else {
- variables.put(name, new ArrayList<Object>(Arrays.asList(eObject)));
- }
+
+ Variable variable = Variable.createReadOnlyVariable(name, eObject);
+ if (type == VariableDeclarationType.GLOBAL) {
+ resource.getFrameStack().putGlobal(variable);
+ }
+ else if (type == VariableDeclarationType.REGULAR) {
+ resource.getFrameStack().put(variable);
}
else {
- variables.put(name, eObject);
+ resource.getFrameStack().enterLocal(FrameType.PROTECTED, entryPoint);
+ resource.getFrameStack().put(variable);
}
}
+
+ public VariableDeclarationType getType() {
+ return type;
+ }
+
+ public void setEntryPoint(ModuleElement entryPoint) {
+ this.entryPoint = entryPoint;
+ }
+
+ public enum VariableDeclarationType {
+ LOCAL,
+ GLOBAL,
+ REGULAR
+ }
}
diff --git a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/XmlTemplate.java b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/XmlTemplate.java
index cae5780..7d2899d 100644
--- a/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/XmlTemplate.java
+++ b/plugins/org.eclipse.epsilon.flexmi/src/org/eclipse/epsilon/flexmi/templates/XmlTemplate.java
@@ -21,12 +21,16 @@
List<Element> application = getApplication(call);
- for (Element applicationElement : application) {
+ if (!application.isEmpty()) {
+ Element firstElement = application.get(0);
for (String attributeName : Xml.getAttributeNames(call)) {
if (!getParameters().contains(attributeName)) {
- applicationElement.setAttribute(attributeName, call.getAttribute(attributeName));
+ firstElement.setAttribute(attributeName, call.getAttribute(attributeName));
}
}
+ }
+
+ for (Element applicationElement : application) {
replaceParameters(applicationElement, call);
}
diff --git a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/ActionTests.java b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/ActionTests.java
index 9735266..53545c3 100644
--- a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/ActionTests.java
+++ b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/ActionTests.java
@@ -1,26 +1,20 @@
package org.eclipse.epsilon.flexmi.test;
-import java.util.Arrays;
-
import org.junit.Test;
public class ActionTests extends FlexmiTests {
@Test
- public void testReferenceFeatures() throws Exception {
- assertEval("EReference.all.first().eType.name", "C1", "actions/model-with-actions.flexmi");
- assertEval("EReference.all.first().name", "r1", "actions/model-with-actions.flexmi");
- }
-
- @Test
- public void testClassFeatures() throws Exception {
- assertEval("EClass.all.first().isAbstract", true, "actions/model-with-actions.flexmi");
- }
-
- @Test
public void testVar() throws Exception {
- assertEval("EReference.all.second().eType.name", "C2", "actions/model-with-actions.flexmi");
- assertEval("EClass.all.third().eSuperTypes.name", Arrays.asList("C1", "C2"), "actions/model-with-actions.flexmi");
- assertEval("EClass.all.fourth().eSuperTypes.name", Arrays.asList("C1", "C2"), "actions/model-with-actions.flexmi");
+ assertEval("EOperation.all.first().name", "createC1", "actions/model-with-actions.flexmi");
+ assertEval("EOperation.all.second().name", "createC3", "actions/model-with-actions.flexmi");
+ assertEval("EOperation.all.first().eType.name", "C1", "actions/model-with-actions.flexmi");
+ assertEval("EOperation.all.second().eType.name", "C3", "actions/model-with-actions.flexmi");
+ assertEval("EClass.all.third().name", "C2Clone", "actions/model-with-actions.flexmi");
+
+ assertWarning("Undefined variable", 7, "actions/model-with-actions.flexmi");
}
+
+
+
}
diff --git a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/FlexmiTests.java b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/FlexmiTests.java
index c62117e..574551a 100644
--- a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/FlexmiTests.java
+++ b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/FlexmiTests.java
@@ -10,6 +10,7 @@
package org.eclipse.epsilon.flexmi.test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EcorePackage;
@@ -37,4 +38,9 @@
assertEquals(result, evaluator.evaluate(expression));
}
+ protected void assertWarning(String message, int line, String modelFileName) throws Exception {
+ assertTrue(loadResource(modelFileName).getWarnings().stream().
+ anyMatch(w -> w.getMessage().contains(message) && w.getLine() == line));
+ }
+
}
diff --git a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/models/actions/model-with-actions.flexmi b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/models/actions/model-with-actions.flexmi
index f62ddae..d1ac1a8 100644
--- a/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/models/actions/model-with-actions.flexmi
+++ b/tests/org.eclipse.epsilon.flexmi.test/src/org/eclipse/epsilon/flexmi/test/models/actions/model-with-actions.flexmi
@@ -1,18 +1,16 @@
<?nsuri http://www.eclipse.org/emf/2002/Ecore?>
<_>
- <class name="C1" :col="classes1, classes2">
- <ref :name="'r' + 1" :type="self.eContainer()"/>
- <:init>
- self.abstract = true;
- </:init>
+ <class name="C1" :local="c">
+ <op :name="'create'+c.name" :type="c"/>
</class>
- <class name="C2" :var="c" :col="classes1, classes2">
- <ref :type="c"/>
+ <class :name="c.name"/>
+
+ <class :name="c2.name + 'Clone'"/>
+
+ <class name="C2" :global="c2"/>
+
+ <class name="C3" :local="c">
+ <op :name="'create'+c.name" :type="c"/>
</class>
-
- <class name="C3" :super="classes1"/>
-
- <class name="C4" :super="classes2"/>
-
</_>
\ No newline at end of file