/** * * 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) */ using System; using System.Collections.Generic; using System.Text; using TUG.Mogentes; using TUG.Mogentes.Codegen.CSharp; namespace TUG.Mogentes.Codegen { public sealed class OoaCSharpInitVisitor : OoaCompleteAstTraversalVisitor { private readonly string SimulationNameSpace = "TUG.Mogentes.Codegen.CSharp.Simulation"; private OoaCodeEmitter emitter; private List hiddenTypesStillToEmit = new List(); private StringBuilder helpers = new StringBuilder(); private List autoConsList = new List(); private int m_maxObjectNameLength = 0; private List m_objectNames = new List(); private List m_initialObjectWorkingSet = new List(); public int maxObjectNameLength { get { return m_maxObjectNameLength; } } public List objectNames { get { return m_objectNames; } } public List initialObjectWorkingSet { get { return m_initialObjectWorkingSet; } } public void Error(int line, int pos, string p) { ParserError error = new ParserError(m_ParserState.filename, line, pos, p); m_ParserState.AddErrorMessage(error); } private void Error(OoActionSystemInstance id, string p) { int line = id.Type.identifier.line; int pos = id.Type.identifier.column; ParserError error = new ParserError(m_ParserState.filename, line, pos, p); m_ParserState.AddErrorMessage(error); } private void Warning(OoActionSystemType atype, string p) { ParserWarning warn = new ParserWarning(m_ParserState.filename, atype.identifier.line, atype.identifier.column, p); m_ParserState.AddWarningMessage(warn); } private string GetIdentifierString(string anIdentifier) { return CSharpIdentifier.GetIdentifierString(anIdentifier); } private List AstTypeLookup = new List(); /// /// here we are called when a new object has been created /// internal void visit(TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass ulyssesActionSystemClass, int ConstrNum) { OoActionSystemType aParentType = ulyssesActionSystemClass.parent != null ? AstTypeLookup[ulyssesActionSystemClass.parent._AstTypeLookupIndex] : null; OoActionSystemType atype = AstTypeLookup[ulyssesActionSystemClass._AstTypeLookupIndex]; OoActionSystemInstance aParentInstance = ulyssesActionSystemClass.parent != null ? ulyssesActionSystemClass.parent.objectInstance : null; C5.HashSet seenTypes = new C5.HashSet(); StringBuilder instantiationPath = new StringBuilder(); if (aParentInstance != null) { OoActionSystemInstance tmp = aParentInstance; while (tmp != null) { instantiationPath.Append(String.Format("<-{0}", tmp.Name)); seenTypes.Add(tmp.Type); tmp = tmp.ParentObject; } } UlyssesType tmpType = atype; while (tmpType != null) { if (seenTypes.Contains(tmpType)) { throw new UlyssesCompileException(String.Format("Cycle in object creation. {0}", instantiationPath.ToString())); } else tmpType = ((OoActionSystemType)tmpType).baseType; } ulyssesActionSystemClass.objectInstance = new OoActionSystemInstance(ulyssesActionSystemClass.objectName, atype, ulyssesActionSystemClass, aParentInstance); // update max length of object name m_maxObjectNameLength = ulyssesActionSystemClass.objectName.Length > m_maxObjectNameLength ? ulyssesActionSystemClass.objectName.Length : m_maxObjectNameLength; // add to list of object names m_objectNames.Add(ulyssesActionSystemClass.objectName); // add to global list of initial objects m_initialObjectWorkingSet.Add(ulyssesActionSystemClass.objectInstance); m_ParserState.AddMessage(new ParserMessage(m_ParserState.filename, atype.identifier.line, atype.identifier.column, String.Format("Creating object: {0}", ulyssesActionSystemClass.objectName))); atype.objects.Add(ulyssesActionSystemClass.objectInstance); // also add the object to the base types atype = atype.baseType; while (atype != null) { atype.derivedObjects.Add(ulyssesActionSystemClass.objectInstance); atype = atype.baseType; } atype = null; if (ConstrNum >= 0) CSharpExpression.constructors[ConstrNum].AddInstance(ulyssesActionSystemClass.objectInstance); } private string GetCSharpType(UlyssesType aType) { if (aType.isAnonymousType) hiddenTypesStillToEmit.Add(aType); CSharpType sharptype = new CSharpType(); aType.Accept(sharptype); return sharptype.ToString(); } private string GetCSharpExpression(Expression anExpression) { CSharpExpression sharpexpression = new CSharpExpression(helpers); anExpression.Accept(sharpexpression); return sharpexpression.ToString(); } private void StartSimulation(string p) { try { // set reference TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass.objectInstantiator = this; // compile Uri path = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); String[] RefAssemblies = { path.LocalPath }; System.Reflection.Assembly simulationCode = CSharpCodeCompiler.BuildAssembly(new string[] { p }, RefAssemblies); // execute system initialization CSharpCodeCompiler.ExecuteCode(simulationCode, SimulationNameSpace + ".SimulationCore", "Main", "Start", new object[] { }); } catch (UlyssesCompileException e) { ParserError error = new ParserError("ObjectInstantiationVisitor.cs", 0, 0, e.Message); m_ParserState.AddErrorMessage(error); } } /// /// generates C# code that describes initialization of the action systems /// this is used to determine the initial working set of classes. /// private void Emit(OoActionSystemType ooActionSystemType) { List initializers = new List(); helpers = new StringBuilder(); if (ooActionSystemType.baseType == null) emitter.AppendLineIncIndent(String.Format("public class {0} : TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass {{", GetIdentifierString(ooActionSystemType.identifier.tokenText))); else emitter.AppendLineIncIndent(String.Format("public class {0} : {1} {{", GetIdentifierString(ooActionSystemType.identifier.tokenText), GetIdentifierString(ooActionSystemType.baseType.identifier.tokenText))); foreach (var attr in ooActionSystemType.symbols.symbolList) { if (attr.kind == IdentifierKind.AttributeIdentifier) { string staticdecl = ((AttributeIdentifier)attr).isStatic ? "static" : string.Empty; emitter.AppendLine(String.Format("public {2} {0} {1};", GetCSharpType(attr.type), GetIdentifierString(attr.tokenText), staticdecl)); initializers.Add(((AttributeIdentifier)attr)); } } // emit internal constructor that initializes object emitter.AppendLineIncIndent(String.Format("protected {0} (TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass parent, int constrNum, int LookupIndex, string aGivenName): base(parent, constrNum, LookupIndex, aGivenName) {{", GetIdentifierString(ooActionSystemType.identifier.tokenText))); foreach (var attr in initializers) emitter.AppendLine(String.Format("{0} = {1};", GetIdentifierString(attr.tokenText), GetCSharpExpression(attr.initializer))); emitter.AppendLineDecIndent("}"); // emit public constructor emitter.AppendLineIncIndent(String.Format("public {0} (TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass parent, int constrNum): this(parent, constrNum,{1}, String.Empty) {{}}", GetIdentifierString(ooActionSystemType.identifier.tokenText), AstTypeLookup.Count)); // emit public constructor with fixed name emitter.AppendLineIncIndent(String.Format("public {0} (TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass parent, int constrNum, string aName): this(parent, constrNum,{1}, aName) {{}}", GetIdentifierString(ooActionSystemType.identifier.tokenText), AstTypeLookup.Count)); AstTypeLookup.Add(ooActionSystemType); // emit helpers emitter.Append(helpers.ToString()); emitter.AppendLineDecIndent("}"); if (ooActionSystemType.autoConstruction) autoConsList.Add(ooActionSystemType); } /// /// Emits type definition for tuple /// private void Emit(TupleType atupleType) { emitter.AppendLineIncIndent(String.Format("public class {0} {{", GetIdentifierString(atupleType.identifier.tokenText))); int i = 0; foreach (var it in atupleType.innerTypes) { emitter.AppendLine(String.Format("public {0} elem_{1};", GetCSharpType(it), i.ToString())); i++; } emitter.AppendLine(" /*constr*/ "); emitter.Append(String.Format("public {0} (", GetIdentifierString(atupleType.identifier.tokenText))); i = 0; foreach (var it in atupleType.innerTypes) { if (i != 0) emitter.Append(","); emitter.Append(String.Format("{0} arg_{1}", GetCSharpType(it), i.ToString())); i++; } emitter.AppendLineIncIndent(") {"); i = 0; foreach (var it in atupleType.innerTypes) { emitter.AppendLine(String.Format("elem_{0} = arg_{0};", i.ToString())); i++; } emitter.AppendLineDecIndent("}"); emitter.AppendLineDecIndent("}"); } /// /// Emits type definition for enum /// private void Emit(EnumType anEnum) { emitter.Append(String.Format("public enum {0} {{", GetIdentifierString(anEnum.identifier.tokenText))); int i = 0; foreach (var it in anEnum.listOfEnumSymbols) { if (i != 0) emitter.Append(", "); else i++; emitter.Append(GetIdentifierString(it.tokenText)); } emitter.AppendLine("}"); } protected override void VisitAstElement(IAst element, IAst parent) { if (element.nodeType == AstNodeTypeEnum.type && ((UlyssesType)element).kind == TypeKind.OoActionSystemType) { OoActionSystemType asystem = (OoActionSystemType)element; /*if (asystem.autoConstruction) CheckForRecursiveNew(asystem);*/ Emit((OoActionSystemType)element); } else if (element.nodeType == AstNodeTypeEnum.type && ((UlyssesType)element).kind == TypeKind.TupleType) { Emit((TupleType)element); } else if (element.nodeType == AstNodeTypeEnum.type && ((UlyssesType)element).kind == TypeKind.EnumeratedType) { Emit((EnumType)element); } else base.VisitAstElement(element, parent); } public override void visit(MainModule mainModule) { CSharpExpression.constructors.Clear(); emitter.AppendLine("using System;"); emitter.AppendLine("using System.Collections.Generic;"); emitter.AppendLine("using System.Text;"); emitter.AppendLine("using TUG.Mogentes.Codegen.CSharp;"); emitter.AppendLine(""); emitter.AppendLineIncIndent(String.Format("namespace {0} {{", SimulationNameSpace)); base.visit(mainModule); emitter.AppendLine(" /* == anonymous types == */ "); foreach (var x in hiddenTypesStillToEmit) { // we only need to define tuples and enums.. if (x.kind == TypeKind.TupleType) Emit((TupleType)x); else if (x.kind == TypeKind.EnumeratedType) Emit((EnumType)x); } emitter.AppendLine(" /* == create autocons objects == */ "); emitter.AppendLineIncIndent("namespace SimulationCore {"); emitter.AppendLineIncIndent("public class Main {"); emitter.AppendLineIncIndent("public static void Start(){"); foreach (var x in autoConsList) emitter.AppendLine(String.Format("new {0}(null,-1 /*autocons*/);", GetIdentifierString(x.identifier.tokenText))); emitter.AppendLineDecIndent("}"); emitter.AppendLineDecIndent("}"); emitter.AppendLineDecIndent("}"); emitter.AppendLineDecIndent("}"); StartSimulation(emitter.ToString()); } public override string ToString() { return emitter.ToString(); } public OoaCSharpInitVisitor(ParserState state) : base(state) { emitter = new OoaCodeEmitter(); } } }