/** * * OOAS Compiler (Deprecated) * * Copyright 2015, Institute for Software Technology, Graz University of * Technology. Portions are copyright 2015 by the AIT Austrian Institute * of Technology. All rights reserved. * * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED. * * Please notice that this version of the OOAS compiler is considered de- * precated. Only the Java version is maintained. * * Contributors: * Willibald Krenn (TU Graz/AIT) * Stefan Tiran (TU Graz/AIT) */ /* * Visitor that "compiles down" objects to normal action systems * Implementing the algorithm layed out in * Bonsangue, Kok, Sere: An Approach to Object-Orientation in Action Systems, In * MPC'98, LNCS 1422, pp. 68{95, 1998 * * Notes: * * WE DO OBJECT INSTANTIATION HERE: This means (more or less) that we will duplicate all the * classes found. In particular we will create one copy per object. In order to do that, we * need to know exactly how many objects of a certain type there will be. We also need to assign each of these * new action systems a particular name. Hence within this compilation step, we need to do * the following. * * -) need to count number of constructed objects per class (in order to be able to assign names) * => This is implemented by compiling the action system initialization to CSharp Code and * subsequently running the initialization step. * -) each action system (resembling an object now) gets a name that encodes the class name, and * information about which object created the new object. * => Per class: find root element, and do instantiation. Then iterate through all objects and * do instantiation for objects created in these.... (It makes sense to forbid creation of * objects of class A in class A...) * -) after the names are known, start instantiation (=copy) process and add necessary runtime * code (see the paper) * * */ using System; using System.Collections.Generic; using System.Text; using TUG.Mogentes.Codegen; using TUG.Mogentes.Codegen.CSharp; namespace TUG.Mogentes { internal sealed class OoaDummyCheckVisitor : OoaExpressionVisitor { public override void visit(AccessExpression accessExpression) { if (accessExpression.left.type == null) System.Console.WriteLine("outch"); base.visit(accessExpression); } public OoaDummyCheckVisitor() { } } public sealed class OoaObjectInstantiationVisitor : OoaCompleteAstTraversalVisitor { private OoaCSharpInitVisitor m_simulator; private ActionSystem m_actionSystem; private Identifier self; private Dictionary m_toReplace = new Dictionary(); /// /// for a given object and type, the method duplicates the attributes and adds them to the resulting /// instantiated action system. /// private void DuplicateAttribute(AttributeIdentifier attributeIdentifier, OoActionSystemInstance obj, OoActionSystemType aType, ActionSystem m_actionSystem) { AttributeIdentifier newAttribute = new AttributeIdentifier(attributeIdentifier); newAttribute.SetTokenText(String.Format("{0}_{1}", obj.Name, attributeIdentifier.tokenText)); m_toReplace.Add(attributeIdentifier, newAttribute); newAttribute.SetInitializer(newAttribute.initializer.Clone()); OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self); newAttribute.initializer.Accept(cloner); m_actionSystem.symbols.AddIdentifier(newAttribute); } private void DuplicateNamedAction(NamedActionIdentifier namedActionIdentifier, OoActionSystemInstance obj, OoActionSystemType aType, ActionSystem m_actionSystem) { NamedActionIdentifier newAction = new NamedActionIdentifier(namedActionIdentifier); newAction.SetTokenText(String.Format("{0}_{1}", obj.Name, namedActionIdentifier.tokenText)); m_toReplace.Add(namedActionIdentifier, newAction); OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self); newAction.Accept(cloner); m_actionSystem.symbols.AddIdentifier(newAction); } public static string GetInstanceFunctionName(OoActionSystemInstance obj, FunctionIdentifier afunction) { return String.Format("{0}_{1}", obj.Name, afunction.tokenText); } private void DuplicateMethod(MethodIdentifier methodIdentifier, OoActionSystemInstance obj, OoActionSystemType aType, ActionSystem m_actionSystem) { MethodIdentifier newMethod = new MethodIdentifier(methodIdentifier); newMethod.SetTokenText(GetInstanceFunctionName(obj, methodIdentifier)); m_toReplace.Add(methodIdentifier, newMethod); newMethod.SetBody((Block)newMethod.body.Clone()); OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self); newMethod.body.Accept(cloner); m_actionSystem.symbols.AddIdentifier(newMethod); } /*Duplicates the do-od block (incl. any do-od blocks of parent classes)*/ private void DuplicateDoOdBlock(OoActionSystemInstance obj, OoActionSystemType aType, ActionSystem m_actionSystem, Block result) { OoActionSystemType rootType = aType; Block block; while (aType != null) { block = aType.doOdBlock; if (block != null) { Block clone = (Block)block.Clone(); OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self); clone.Accept(cloner); result.AddStatement(clone); } aType = aType.baseType; } } Dictionary objectsdone = new Dictionary(); /// /// Generates an OoActionSystemType that is the instantiation of all the objects found in the System Assembling Block /// private void InstantiateObjects(ActionSystem m_actionSystem, MainModule mainModule, IdentifierList sysdescr, Block parent) { //C5.HashSet done = new C5.HashSet(); // Block newBlock; switch (sysdescr.listType) { case IdentifierListType.nondeterministic: newBlock = new NondetBlock(0, 0); break; case IdentifierListType.prioritized: newBlock = new PrioBlock(0, 0); break; case IdentifierListType.seqential: newBlock = new SeqBlock(0, 0); break; case IdentifierListType.normal: default: throw new NotImplementedException(); } if (parent == null) m_actionSystem.SetDoOdBlock(newBlock); else parent.AddStatement(newBlock); foreach (var id in sysdescr.identifiers) { Identifier ident = id; while (ident.kind == IdentifierKind.List && ((IdentifierList)ident).identifiers.Count == 1) { ident = ((IdentifierList)ident).identifiers.First.Value; } if (ident.kind == IdentifierKind.List) InstantiateObjects(m_actionSystem, mainModule, (IdentifierList)ident, newBlock); else { if (ident.kind == IdentifierKind.TypeIdentifier && ((TypeIdentifier)ident).type.kind == TypeKind.OoActionSystemType) { OoActionSystemType aType = (OoActionSystemType)((TypeIdentifier)ident).type; objectsdone.Add(aType, m_actionSystem); Block NondetBlock = null; // holds parallel comp of all objects if (aType.doOdBlock != null) { NondetBlock = new NondetBlock(0, 0); newBlock.AddStatement(NondetBlock); } foreach (var obj in aType.objects) { m_toReplace = new Dictionary(objectsdone); addParentClassMappings(m_toReplace, aType, m_actionSystem); self = new SelfTypeIdentifier(obj.Name, aType, null); SymbolTable table = aType.getAllSymbols(); foreach (var x in table.symbolList) { // resolve attributes first if (x.kind == IdentifierKind.AttributeIdentifier) DuplicateAttribute((AttributeIdentifier)x, obj, aType, m_actionSystem); } foreach (var x in table.symbolList) { // now do methods and other stuff if (x.kind == IdentifierKind.MethodIdentifier) DuplicateMethod((MethodIdentifier)x, obj, aType, m_actionSystem); else if (x.kind == IdentifierKind.NamedActionIdentifier) DuplicateNamedAction((NamedActionIdentifier)x, obj, aType, m_actionSystem); } // construct parallel composition of all the objects of one class. if (aType.doOdBlock != null) { DuplicateDoOdBlock(obj, aType, m_actionSystem, NondetBlock); } } // add an error, if a type does not get instantiated and the do-od block is filled.. // !!!!!!!!!!!!!!! note, if new is also allowed in normal actions, this needs to be disabled (or become a warning) !!!!!!!!!!!!!!!!!!!!!!!!!! if (aType.objects.Count == 0 && aType.doOdBlock != null) { m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column, String.Format("Type '{0}' is never instantiated but has a non-empty do-od block", aType.ToString()))); } } else throw new NotImplementedException(); } } } private void addParentClassMappings(Dictionary m_toReplace, OoActionSystemType aType, ActionSystem m_actionSystem) { while (aType != null) { if (!m_toReplace.ContainsKey(aType)) m_toReplace.Add(aType, m_actionSystem); // add base classes to mapping... aType = aType.baseType; } } /// /// Adds those objects of types that are not found in the SAB. /// private void InstantiatePassiveObjects(ActionSystem m_actionSystem, MainModule mainModule) { foreach (var x in mainModule.symbolTable.symbolList) { if (x.type.kind == TypeKind.OoActionSystemType && !objectsdone.ContainsKey(x.type)) if (((OoActionSystemType)x.type).autoConstruction) { OoActionSystemType aType = (OoActionSystemType)x.type; m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column, String.Format("Type '{0}' marked autocons but omitted in system description!", aType.ToString()))); } else { OoActionSystemType aType = (OoActionSystemType)x.type; foreach (var obj in aType.objects) { m_toReplace = new Dictionary(objectsdone); addParentClassMappings(m_toReplace, aType, m_actionSystem); self = new SelfTypeIdentifier(obj.Name, aType, null); SymbolTable table = aType.getAllSymbols(); foreach (var y in table.symbolList) { // resolve attributes first if (y.kind == IdentifierKind.AttributeIdentifier) DuplicateAttribute((AttributeIdentifier)y, obj, aType, m_actionSystem); } foreach (var y in table.symbolList) { // now do methods if (y.kind == IdentifierKind.MethodIdentifier) DuplicateMethod((MethodIdentifier)y, obj, aType, m_actionSystem); //else if (y.kind == IdentifierKind.NamedActionIdentifier) // m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column, // String.Format("Type '{0}' has named actions but was omitted in system description!", aType.ToString()))); } if (aType.doOdBlock != null) m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column, String.Format("Type '{0}' has do-od block but was omitted in system description!", aType.ToString()))); } } } } public override void visit(MainModule mainModule) { if (mainModule.systemDescription == null) return; /* determine names of objects */ mainModule.Accept(m_simulator); /* add information about all the objects to the AST */ //mainModule.SetObjects(m_simulator.initialObjectWorkingSet); m_actionSystem = new ActionSystem(); m_actionSystem.SetParentScope(mainModule); InstantiateObjects(m_actionSystem, mainModule, mainModule.systemDescription, m_actionSystem.doOdBlock); InstantiatePassiveObjects(m_actionSystem, mainModule); mainModule.SetInstance(m_actionSystem); } public override string ToString() { return m_simulator.ToString(); } public OoaObjectInstantiationVisitor(ParserState aState) : base(aState) { m_simulator = new OoaCSharpInitVisitor(aState); } } }