Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / codegen / CSharp / ooaCSharpInitVisitor.cs @ 3

1
/**
2
  *
3
  *                      OOAS Compiler (Deprecated)
4
  *
5
  * Copyright 2015, Institute for Software Technology, Graz University of
6
  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
7
  * of Technology. All rights reserved.
8
  *
9
  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
10
  *
11
  * Please notice that this version of the OOAS compiler is considered de-
12
  * precated. Only the Java version is maintained.
13
  *
14
  * Contributors:
15
  *               Willibald Krenn (TU Graz/AIT)
16
  *               Stefan Tiran (TU Graz/AIT)
17
  */
18

    
19
using System;
20
using System.Collections.Generic;
21
using System.Text;
22
using TUG.Mogentes;
23
using TUG.Mogentes.Codegen.CSharp;
24

    
25

    
26
namespace TUG.Mogentes.Codegen
27
{
28

    
29
    public sealed class OoaCSharpInitVisitor : OoaCompleteAstTraversalVisitor
30
    {
31
        private readonly string SimulationNameSpace = "TUG.Mogentes.Codegen.CSharp.Simulation";
32
        private OoaCodeEmitter emitter;
33
        private List<UlyssesType> hiddenTypesStillToEmit = new List<UlyssesType>();
34
        private StringBuilder helpers = new StringBuilder();
35
        private List<OoActionSystemType> autoConsList = new List<OoActionSystemType>();
36

    
37
        private int m_maxObjectNameLength = 0;
38
        private List<string> m_objectNames = new List<string>();
39
        private List<OoActionSystemInstance> m_initialObjectWorkingSet = new List<OoActionSystemInstance>();
40

    
41

    
42

    
43
        public int maxObjectNameLength { get { return m_maxObjectNameLength; } }
44
        public List<string> objectNames { get { return m_objectNames; } }
45
        public List<OoActionSystemInstance> initialObjectWorkingSet { get { return m_initialObjectWorkingSet; } }
46

    
47

    
48
        public void Error(int line, int pos, string p)
49
        {
50
            ParserError error = new ParserError(m_ParserState.filename, line, pos, p);
51
            m_ParserState.AddErrorMessage(error);
52
        }
53

    
54

    
55
        private void Error(OoActionSystemInstance id, string p)
56
        {
57
            int line = id.Type.identifier.line;
58
            int pos = id.Type.identifier.column;
59

    
60
            ParserError error = new ParserError(m_ParserState.filename, line, pos, p);
61
            m_ParserState.AddErrorMessage(error);
62
        }
63
        private void Warning(OoActionSystemType atype, string p)
64
        {
65
            ParserWarning warn = new ParserWarning(m_ParserState.filename, atype.identifier.line,
66
                atype.identifier.column, p);
67
            m_ParserState.AddWarningMessage(warn);
68
        }
69

    
70
        private string GetIdentifierString(string anIdentifier)
71
        {
72
            return CSharpIdentifier.GetIdentifierString(anIdentifier);
73
        }
74
        private List<OoActionSystemType> AstTypeLookup = new List<OoActionSystemType>();
75

    
76
        /// <summary>
77
        /// here we are called when a new object has been created
78
        /// </summary>
79
        internal void visit(TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass ulyssesActionSystemClass, int ConstrNum)
80
        {
81
            OoActionSystemType aParentType =
82
                ulyssesActionSystemClass.parent != null ?
83
                    AstTypeLookup[ulyssesActionSystemClass.parent._AstTypeLookupIndex] : null;
84
            OoActionSystemType atype = AstTypeLookup[ulyssesActionSystemClass._AstTypeLookupIndex];
85
            OoActionSystemInstance aParentInstance =
86
                ulyssesActionSystemClass.parent != null ?
87
                ulyssesActionSystemClass.parent.objectInstance : null;
88

    
89
            C5.HashSet<UlyssesType> seenTypes = new C5.HashSet<UlyssesType>();
90
            StringBuilder instantiationPath = new StringBuilder();
91
            if (aParentInstance != null)
92
            {
93
                OoActionSystemInstance tmp = aParentInstance;
94
                while (tmp != null)
95
                {
96
                    instantiationPath.Append(String.Format("<-{0}", tmp.Name));
97
                    seenTypes.Add(tmp.Type);
98
                    tmp = tmp.ParentObject;
99
                }
100
            }
101

    
102
            UlyssesType tmpType = atype;
103
            while (tmpType != null)
104
            {
105
                if (seenTypes.Contains(tmpType))
106
                {
107
                    throw new UlyssesCompileException(String.Format("Cycle in object creation. {0}", instantiationPath.ToString()));
108
                }
109
                else
110
                    tmpType = ((OoActionSystemType)tmpType).baseType;
111
            }
112

    
113
            ulyssesActionSystemClass.objectInstance =
114
                new OoActionSystemInstance(ulyssesActionSystemClass.objectName, atype, ulyssesActionSystemClass, aParentInstance);
115

    
116
            // update max length of object name
117
            m_maxObjectNameLength = ulyssesActionSystemClass.objectName.Length > m_maxObjectNameLength
118
                ? ulyssesActionSystemClass.objectName.Length : m_maxObjectNameLength;
119

    
120
            // add to list of object names
121
            m_objectNames.Add(ulyssesActionSystemClass.objectName);
122

    
123
            // add to global list of initial objects
124
            m_initialObjectWorkingSet.Add(ulyssesActionSystemClass.objectInstance);
125

    
126
            m_ParserState.AddMessage(new ParserMessage(m_ParserState.filename,
127
                atype.identifier.line, atype.identifier.column, String.Format("Creating object: {0}", ulyssesActionSystemClass.objectName)));
128

    
129
            atype.objects.Add(ulyssesActionSystemClass.objectInstance);
130
            // also add the object to the base types
131
            atype = atype.baseType;
132
            while (atype != null)
133
            {
134
                atype.derivedObjects.Add(ulyssesActionSystemClass.objectInstance);
135
                atype = atype.baseType;
136
            }
137
            atype = null;
138

    
139
            if (ConstrNum >= 0)
140
                CSharpExpression.constructors[ConstrNum].AddInstance(ulyssesActionSystemClass.objectInstance);
141
        }
142
        private string GetCSharpType(UlyssesType aType)
143
        {
144
            if (aType.isAnonymousType)
145
                hiddenTypesStillToEmit.Add(aType);
146

    
147
            CSharpType sharptype = new CSharpType();
148
            aType.Accept(sharptype);
149
            return sharptype.ToString();
150
        }
151
        private string GetCSharpExpression(Expression anExpression)
152
        {
153
            CSharpExpression sharpexpression = new CSharpExpression(helpers);
154
            anExpression.Accept(sharpexpression);
155
            return sharpexpression.ToString();
156
        }
157

    
158
        private void StartSimulation(string p)
159
        {
160
            try
161
            {
162
                // set reference
163
                TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass.objectInstantiator = this;
164
                // compile
165
                Uri path = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
166
                String[] RefAssemblies = { path.LocalPath };
167
                System.Reflection.Assembly simulationCode = CSharpCodeCompiler.BuildAssembly(new string[] { p }, RefAssemblies);
168
                // execute system initialization
169
                CSharpCodeCompiler.ExecuteCode(simulationCode, SimulationNameSpace + ".SimulationCore", "Main", "Start", new object[] { });
170
            }
171
            catch (UlyssesCompileException e)
172
            {
173
                ParserError error = new ParserError("ObjectInstantiationVisitor.cs", 0, 0, e.Message);
174
                m_ParserState.AddErrorMessage(error);
175
            }
176
        }
177

    
178
        /// <summary>
179
        /// generates C# code that describes initialization of the action systems
180
        /// this is used to determine the initial working set of classes.
181
        /// </summary>
182
        private void Emit(OoActionSystemType ooActionSystemType)
183
        {
184
            List<AttributeIdentifier> initializers = new List<AttributeIdentifier>();
185
            helpers = new StringBuilder();
186
            if (ooActionSystemType.baseType == null)
187
                emitter.AppendLineIncIndent(String.Format("public class {0} : TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass {{", GetIdentifierString(ooActionSystemType.identifier.tokenText)));
188
            else
189
                emitter.AppendLineIncIndent(String.Format("public class {0} : {1} {{", GetIdentifierString(ooActionSystemType.identifier.tokenText), GetIdentifierString(ooActionSystemType.baseType.identifier.tokenText)));
190

    
191
            foreach (var attr in ooActionSystemType.symbols.symbolList)
192
            {
193
                if (attr.kind == IdentifierKind.AttributeIdentifier)
194
                {
195
                    string staticdecl = ((AttributeIdentifier)attr).isStatic ? "static" : string.Empty;
196
                    emitter.AppendLine(String.Format("public {2} {0} {1};", GetCSharpType(attr.type), GetIdentifierString(attr.tokenText), staticdecl));
197
                    initializers.Add(((AttributeIdentifier)attr));
198
                }
199
            }
200

    
201
            // emit internal constructor that initializes object
202
            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)));
203
            foreach (var attr in initializers)
204
                emitter.AppendLine(String.Format("{0} = {1};", GetIdentifierString(attr.tokenText), GetCSharpExpression(attr.initializer)));
205
            emitter.AppendLineDecIndent("}");
206

    
207
            // emit public constructor
208
            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));
209

    
210
            // emit public constructor with fixed name
211
            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));
212

    
213

    
214
            AstTypeLookup.Add(ooActionSystemType);
215

    
216
            // emit helpers
217
            emitter.Append(helpers.ToString());
218

    
219
            emitter.AppendLineDecIndent("}");
220

    
221
            if (ooActionSystemType.autoConstruction)
222
                autoConsList.Add(ooActionSystemType);
223
        }
224

    
225
        /// <summary>
226
        /// Emits type definition for tuple 
227
        /// </summary>
228
        private void Emit(TupleType atupleType)
229
        {
230
            emitter.AppendLineIncIndent(String.Format("public class {0} {{", GetIdentifierString(atupleType.identifier.tokenText)));
231
            int i = 0;
232
            foreach (var it in atupleType.innerTypes)
233
            {
234
                emitter.AppendLine(String.Format("public {0} elem_{1};", GetCSharpType(it), i.ToString()));
235
                i++;
236
            }
237

    
238
            emitter.AppendLine(" /*constr*/ ");
239
            emitter.Append(String.Format("public {0} (", GetIdentifierString(atupleType.identifier.tokenText)));
240
            i = 0;
241
            foreach (var it in atupleType.innerTypes)
242
            {
243
                if (i != 0)
244
                    emitter.Append(",");
245
                emitter.Append(String.Format("{0} arg_{1}", GetCSharpType(it), i.ToString()));
246
                i++;
247
            }
248
            emitter.AppendLineIncIndent(") {");
249
            i = 0;
250
            foreach (var it in atupleType.innerTypes)
251
            {
252
                emitter.AppendLine(String.Format("elem_{0} = arg_{0};", i.ToString()));
253
                i++;
254
            }
255
            emitter.AppendLineDecIndent("}");
256

    
257
            emitter.AppendLineDecIndent("}");
258
        }
259

    
260
        /// <summary>
261
        /// Emits type definition for enum 
262
        /// </summary>
263
        private void Emit(EnumType anEnum)
264
        {
265
            emitter.Append(String.Format("public enum {0} {{", GetIdentifierString(anEnum.identifier.tokenText)));
266
            int i = 0;
267
            foreach (var it in anEnum.listOfEnumSymbols)
268
            {
269
                if (i != 0)
270
                    emitter.Append(", ");
271
                else
272
                    i++;
273
                emitter.Append(GetIdentifierString(it.tokenText));
274
            }
275
            emitter.AppendLine("}");
276
        }
277

    
278
        protected override void VisitAstElement(IAst element, IAst parent)
279
        {
280
            if (element.nodeType == AstNodeTypeEnum.type &&
281
                ((UlyssesType)element).kind == TypeKind.OoActionSystemType)
282
            {
283
                OoActionSystemType asystem = (OoActionSystemType)element;
284
                /*if (asystem.autoConstruction)
285
                    CheckForRecursiveNew(asystem);*/
286
                Emit((OoActionSystemType)element);
287
            }
288
            else if (element.nodeType == AstNodeTypeEnum.type &&
289
                ((UlyssesType)element).kind == TypeKind.TupleType)
290
            {
291
                Emit((TupleType)element);
292
            }
293
            else if (element.nodeType == AstNodeTypeEnum.type &&
294
                ((UlyssesType)element).kind == TypeKind.EnumeratedType)
295
            {
296
                Emit((EnumType)element);
297
            }
298
            else
299
                base.VisitAstElement(element, parent);
300
        }
301

    
302
        public override void visit(MainModule mainModule)
303
        {
304
            CSharpExpression.constructors.Clear(); 
305
            emitter.AppendLine("using System;");
306
            emitter.AppendLine("using System.Collections.Generic;");
307
            emitter.AppendLine("using System.Text;");
308
            emitter.AppendLine("using TUG.Mogentes.Codegen.CSharp;");
309
            emitter.AppendLine("");
310
            emitter.AppendLineIncIndent(String.Format("namespace {0} {{", SimulationNameSpace));
311

    
312
            base.visit(mainModule);
313

    
314
            emitter.AppendLine(" /* == anonymous types == */ ");
315
            foreach (var x in hiddenTypesStillToEmit)
316
            {
317
                // we only need to define tuples and enums..
318
                if (x.kind == TypeKind.TupleType)
319
                    Emit((TupleType)x);
320
                else if (x.kind == TypeKind.EnumeratedType)
321
                    Emit((EnumType)x);
322
            }
323

    
324
            emitter.AppendLine(" /* == create autocons objects == */ ");
325
            emitter.AppendLineIncIndent("namespace SimulationCore {");
326
            emitter.AppendLineIncIndent("public class Main {");
327
            emitter.AppendLineIncIndent("public static void Start(){");
328

    
329
            foreach (var x in autoConsList)
330
                emitter.AppendLine(String.Format("new {0}(null,-1 /*autocons*/);", GetIdentifierString(x.identifier.tokenText)));
331

    
332
            emitter.AppendLineDecIndent("}");
333
            emitter.AppendLineDecIndent("}");
334
            emitter.AppendLineDecIndent("}");
335

    
336
            emitter.AppendLineDecIndent("}");
337

    
338
            StartSimulation(emitter.ToString());
339
        }
340

    
341

    
342
        public override string ToString()
343
        {
344
            return emitter.ToString();
345
        }
346

    
347
        public OoaCSharpInitVisitor(ParserState state)
348
            : base(state)
349
        {
350
            emitter = new OoaCodeEmitter();
351
        }
352

    
353
    }
354
}