The StaDyn Programming Language
Source code documentation of StaDyn, a hybrid static and dynamic typing language.
Program.cs
Go to the documentation of this file.
1 // -------------------------------------------------------------------------- //
3 // Project rROTOR //
4 // -------------------------------------------------------------------------- //
5 // File: Program.cs //
6 // Authors: Cristina Gonzalez Muñoz - cristi.gm@gmail.com //
7 // Francisco Ortin - francisco.ortin@gmail.com //
8 // Co-author: Miguel Garcia - miguel.uniovi@gmail.com //
9 // Description: //
10 // Main class for the application. //
11 // -------------------------------------------------------------------------- //
12 // Create date: 23-01-2006 //
13 // Modification date: 23-02-2011 //
15 
16 using System;
17 using System.Diagnostics;
18 using System.Collections.Generic;
19 using System.IO;
20 using AST;
21 using CodeGeneration;
22 using Debugger;
23 using ErrorManagement;
24 using Inference.src.Core;
25 using Parser;
26 using Semantic;
27 using Semantic.SSAAlgorithm;
28 using antlr;
29 using TargetPlatforms;
30 
31 namespace Inference.Core
32 {
33  public class Program
34  {
35  #region Fields
36 
40  private List<SourceFile> astList;
41 
46  private static List<entryPointInfo> entryPointList = new List<entryPointInfo>();
47 
48  #region struct entryPointInfo
49 
50  private struct entryPointInfo
51  {
52  #region Fields
53 
54  Location location;
55  #endregion
56 
57  #region Properties
58  public Location Location {
59  get { return this.location; }
60  }
61 
62  #endregion
63 
64  #region Constructor
65 
72  public entryPointInfo(Location location)
73  {
74  this.location = location;
75  }
76 
77  #endregion
78  }
79 
80  #endregion
81 
82  #endregion
83 
84  #region SetEntryPointFound()
85 
92  public static void SetEntryPointFound(Location location)
93  {
94  entryPointList.Add(new entryPointInfo(location));
95  }
96 
97  #endregion
98 
99  #region Constructor
100 
104  public Program()
105  {
106  this.astList = new List<SourceFile>();
107  }
108 
109  #endregion
110 
111  #region LoadFile()
112 
119  public string LoadFile(FileInfo f, IDictionary<string, string> directories)
120  {
121  if (Directory.Exists(f.FullName))
122  {
123  string[] files = Directory.GetFileSystemEntries(f.FullName);
124  for (int i = 0; i < files.Length; i++)
125  {
126  LoadFile(new FileInfo(files[i]), directories);
127  directories[files[i]] = f.FullName;
128  }
129  }
130  if (f.Extension.Equals(".stadyn")||f.Extension.Equals(".cs")) {
131  parseFile(f, new FileStream(f.FullName, FileMode.Open, FileAccess.Read));
132  directories[f.Name] = f.Directory.FullName;
133  }
134  return null;
135 
136  }
137 
138  #endregion
139 
140  #region parseFile()
141 
147  private void parseFile(FileInfo f, Stream s)
148  {
149  CSharpParser parser;
150  TokenStreamHiddenTokenFilter filter;
151  try {
152  TokenStream lexer;
153 
154  // Create a scanner that reads from the input stream passed to us
155  CSharpLexer antlrLexer = new CSharpLexer(new StreamReader(s));
156 
157  // Define a selector that can switch from the C# codelexer to the C# preprocessor lexer
158  TokenStreamSelector selector = new TokenStreamSelector();
159  antlrLexer.Selector = selector;
160  antlrLexer.setFilename(f.Name);
161 
162  CSharpPreprocessorLexer preproLexer = new CSharpPreprocessorLexer(antlrLexer.getInputState());
163  preproLexer.Selector = selector;
164  CSharpPreprocessorHooverLexer hooverLexer = new CSharpPreprocessorHooverLexer(antlrLexer.getInputState());
165  hooverLexer.Selector = selector;
166 
167  // use the special token object class
168  antlrLexer.setTokenCreator(new CustomHiddenStreamToken.CustomHiddenStreamTokenCreator());
169  antlrLexer.setTabSize(1);
170  preproLexer.setTokenCreator(new CustomHiddenStreamToken.CustomHiddenStreamTokenCreator());
171  preproLexer.setTabSize(1);
172  hooverLexer.setTokenCreator(new CustomHiddenStreamToken.CustomHiddenStreamTokenCreator());
173  hooverLexer.setTabSize(1);
174 
175  // notify selector about various lexers; name them for convenient reference later
176  selector.addInputStream(antlrLexer, "codeLexer");
177  selector.addInputStream(preproLexer, "directivesLexer");
178  selector.addInputStream(hooverLexer, "hooverLexer");
179  selector.select("codeLexer"); // start with main the CSharp code lexer
180  lexer = selector;
181 
182  // create the stream filter; hide WS and SL_COMMENT
183  filter = new TokenStreamHiddenTokenFilter(lexer);
184  filter.hide(CSharpTokenTypes.WHITESPACE);
185  filter.hide(CSharpTokenTypes.NEWLINE);
186  filter.hide(CSharpTokenTypes.ML_COMMENT);
187  filter.hide(CSharpTokenTypes.SL_COMMENT);
188 
189  //------------------------------------------------------------------
190 
191  // Create a parser that reads from the scanner
192  parser = new CSharpParser(filter);
193  parser.setFilename(f.FullName);
194  //parser.setFilename(f.Name);
195 
196  // Start parsing at the compilationUnit rule
197  long startTime = DateTime.Now.Ticks;
198 
199  this.astList.Add(parser.compilationUnit());
200 
201 #if DEBUG
202  double elapsedTime = ((DateTime.Now.Ticks - startTime) / TimeSpan.TicksPerMillisecond) / 1000.0;
203  ConsoleColor previousColor = Console.ForegroundColor;
204  Console.ForegroundColor = ConsoleColor.DarkGray;
205  System.Console.Out.WriteLine("Parsed {0} in: {1} seconds.", f.Name, elapsedTime);
206  Console.ForegroundColor = previousColor;
207 #endif
208  }
209  catch (RecognitionException e)
210  {
211  ErrorManager.Instance.NotifyError(new ParserError(new Location(e.fileName, e.line, e.column), e.Message));
212  }
213  }
214 
215  #endregion
216 
217  #region Run()
218 
229  public void Run(IDictionary<string, string> directories, string outputFileName,
230  string debugFilePath, string ilasmFileName,string typeTableFileName, TargetPlatform targetPlatform, bool run, bool serverOptimization)
231  {
232  int previousNumberOfErrors = ErrorManager.Instance.ErrorCount;
233 
234  if (entryPointList.Count == 0)
235  ErrorManager.Instance.NotifyError(new EntryPointNotFoundError());
236  else
237  {
238  if (entryPointList.Count != 1)
239  {
240  for (int i = 0; i < entryPointList.Count; i++)
241  {
242  ErrorManager.Instance.NotifyError(new EntryPointFoundError(entryPointList[i].Location));
243  }
244  }
245  }
246 
247  for (int i = 0; i < this.astList.Count; i++)
248  {
249  this.astList[i].Accept(new VisitorSSA(), null);
250  }
251 
252  for (int i = 0; i < this.astList.Count; i++)
253  {
254  this.astList[i].Accept(new VisitorTypeLoad(), null);
255  }
256 
257  for (int i = 0; i < this.astList.Count; i++)
258  {
259  this.astList[i].Accept(new VisitorTypeDefinition(), null);
260  }
261 
262  for (int i = 0; i < this.astList.Count; i++)
263  {
264  this.astList[i].Accept(new VisitorSymbolIdentification(directories), null);
265  }
266 
267  VisitorTypeInference visitorTypeInference = new VisitorTypeInference();
268  for (int i = 0; i < this.astList.Count; i++)
269  // * The same visitor type inference should be used in the whole process
270  this.astList[i].Accept(visitorTypeInference, null);
271  //for (int i = 0; i < this.astList.Count; i++)
272  // this.astList[i].Accept(new VisitorDebug(new StreamWriter("debug.out")),0);
273 
274  // * Code is generated if no error has been found...
275  if (ErrorManager.Instance.ErrorCount == previousNumberOfErrors &&
276  // * ... and the output file and platform are not null
277  outputFileName != null)
278  {
279  if (entryPointList.Count == 1) {
280  // * The same visitor code generation should be used in the whole process
281  string ilFileName = Path.ChangeExtension(outputFileName, ".il");
282  VisitorCodeGenerationBase visitorCodeGeneration = createVisitorCodeGeneration(ilFileName, outputFileName, targetPlatform);
283  for (int i = 0; i < this.astList.Count; i++)
284  {
285  this.astList[i].Accept(visitorCodeGeneration, null);
286  }
287  visitorCodeGeneration.AddExceptionCode();
288  visitorCodeGeneration.Close();
289 
290  if (serverOptimization)
291  {
292  ConsoleColor previousColor = Console.ForegroundColor;
293  Console.ForegroundColor = ConsoleColor.DarkGray;
294  System.Console.Out.WriteLine("Server option founded, optimizing code...");
295  ServerOptimizer.OptimizeIlFile(ilFileName);
296  System.Console.Out.WriteLine("Code optimized.");
297  Console.ForegroundColor = previousColor;
298  }
299 
300  // * If no errors found, the executable file is generated
301  if (previousNumberOfErrors == ErrorManager.Instance.ErrorCount)
302  switch (targetPlatform)
303  {
304  case TargetPlatform.CLR:
305  assembleAndRun(ilFileName, outputFileName, ilasmFileName, run);
306  break;
307  case TargetPlatform.RRotor:
308  // TODO (assemble and run the IL code in the Rrotor platform)
309  break;
310  default:
311  System.Diagnostics.Debug.Assert(false, "Unknown target platform.");
312  break;
313  }
314  }
315  }
316 
317 
318 #if DEBUG
319  // * Dumps the types table
320  // debug(debugFilePath, typeTableFileName);
321 #endif
322 
323  ClearMemory();
324 
325  }
326 
327  #endregion
328 
329  #region ClearMemory()
330 
334  public static void ClearMemory()
335  {
336  // * Frees all the types in memory
337  TypeSystem.TypeTable.Instance.Clear();
338  // * Clear the list of entry points (main methods in C#)
339  Program.entryPointList.Clear();
340  }
341 
342  #endregion
343 
344  #region createVisitorCodeGeneration()
345  private VisitorCodeGenerationBase createVisitorCodeGeneration (string ilFileName, string outputFileName, TargetPlatform target)
352  {
353  switch (target)
354  {
355  case TargetPlatform.CLR:
356  return new VisitorCLRCodeGeneration<CLRCodeGenerator>(Path.GetFileNameWithoutExtension(outputFileName),
357  new CLRCodeGenerator(new StreamWriter(ilFileName)));
358  //new CLRCodeGenerator(Console.Out));
359  //case TargetPlatform.RRotor:
360  // return new VisitorRrotorCodeGeneration<RrotorCodeGenerator>(Path.GetFileNameWithoutExtension(outputFileName),
361  // new RrotorCodeGenerator(new StreamWriter(ilFileName)));
362  default:
363  System.Diagnostics.Debug.Assert(false, "Wrong target platform");
364  break;
365  }
366  return null;
367  }
368  #endregion
369 
370  #region assembleAndRun()
371  private void assembleAndRun(string ilFileName, string outputFileName, string ilasmFileName, bool run)
379  {
380  Process process = new Process();
381  process.StartInfo.UseShellExecute = false;
382  process.StartInfo.CreateNoWindow = true; //Uncomment this to execute large source code, but StandardOutput and StandardError will be not visible.
383  process.StartInfo.RedirectStandardOutput = false; //Set to false to execute large source code
384  process.StartInfo.RedirectStandardError = false; //Set to false to execute large source code
385 
386  process.StartInfo.FileName = ilasmFileName;
387  process.StartInfo.Arguments = "\"" + ilFileName + "\"" + " /output=" + "\"" + outputFileName + "\" /optimize";
388  process.Start();
389  process.WaitForExit();
390 
391  if (process.ExitCode != 0)
392  {
393  ErrorManager.Instance.NotifyError(new AssemblerError(ilFileName));
394  process.StartInfo.RedirectStandardOutput = false;
395  process.StartInfo.RedirectStandardError = false;
396  process.Start();
397  process.WaitForExit();
398  }
399  else if (run)
400  {
401  // * The compilation has successed
402  process.StartInfo.UseShellExecute = false;
403  process.StartInfo.RedirectStandardOutput = false;
404  process.StartInfo.RedirectStandardError = false;
405  process.StartInfo.FileName = outputFileName;
406  process.Start();
407  process.WaitForExit();
408  if (process.ExitCode != 0)
409  ErrorManager.Instance.NotifyError(new ExecutionError(outputFileName));
410  }
411  }
412  #endregion
413 
414  #region debug()
415  private void debug(string debugFilePath, string typeTableFileName) {
421 #if DEBUG
422  //TODO: OJO Si la carpeta Test no existe falla en tiempo de ejecución al menos en consola.
423  for (int i = 0; i < this.astList.Count; i++)
424  {
425  string debugFile = Path.Combine(debugFilePath, Path.ChangeExtension(this.astList[i].Location.FileName, ".out.txt"));
426  using (StreamWriter sw = new StreamWriter(debugFile.ToString()))
427  {
428  this.astList[i].Accept(new VisitorDebug(sw), 0);
429  sw.Close();
430  }
431  //this.astList[i].Accept(new VisitorDebug(Console.Out), 0);
432  }
433 
434  using (StreamWriter sw2 = new StreamWriter(typeTableFileName))
435  {
436  sw2.Write(TypeSystem.TypeTable.Instance.ToString());
437  sw2.Close();
438  }
439 #endif
440  }
441 
442  #endregion
443 
444  }
445 }
Represents a error produced when source code has not any entry point.
This class visits the AST to store the type of each declaration. Includes methods, fields and inheritance.
static void SetEntryPointFound(Location location)
Sets the information of entry point.
Definition: Program.cs:92
Class to allow the management of all different error types happened.
Definition: ErrorManager.cs:29
Represents the error occurred when compiled application has been executed.
This class encapsulates a location in a specific file. Implements an Inmutable pattern. So it can be used in any context, that is his internal fields never change.
Definition: Location.cs:24
This class walks the AST to to obtain intermediate code Thisis a layer adapter class and is the base ...
Program()
Constructor of Program
Definition: Program.cs:104
static void ClearMemory()
Frees information in memory
Definition: Program.cs:334
System.IO.FileInfo FileInfo
Definition: CSharpParser.cs:5
This class encapsulates the IL CLR code generator IL.
antlr.TokenStream TokenStream
Definition: CSharpLexer.cs:34
static ErrorManager Instance
Gets the unique instance of ErrorManager
Definition: ErrorManager.cs:69
Represents the error occurred while the source code is parsing.
Definition: ParserError.cs:23
void Run(IDictionary< string, string > directories, string outputFileName, string debugFilePath, string ilasmFileName, string typeTableFileName, TargetPlatform targetPlatform, bool run, bool serverOptimization)
Runs the application A filename : directoryname mapThe output file name. A null value means no execut...
Definition: Program.cs:229
antlr.RecognitionException RecognitionException
Definition: CSharpLexer.cs:31
Represents a error produced when source code has more the one entry point defined.
This class shows the information of the abstract syntax tree.
Definition: VisitorDebug.cs:34
This class visits the AST to make the type inference of all expressiones in the source code...
This class makes the static single assignment algorithm in which every variable is assigned exactly o...
Definition: VisitorSSA.cs:38
antlr.TokenStreamSelector TokenStreamSelector
Definition: CSharpLexer.cs:6
string LoadFile(FileInfo f, IDictionary< string, string > directories)
Starts the parsing process
Definition: Program.cs:119
Represents the error occurred when the assembler is not capable of assembling an IL file...
This class visits the AST to store the type of each defined class or inteface.
This class visits the AST to assign symbol information to identifier expression.
int ErrorCount
Returns the number of errors
System.IO.Stream Stream
Definition: CSharpLexer.cs:12