public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Check children IdNode.CheckSemantics(scope, report); ExpressionNode.CheckSemantics(scope, report); if (!IdNode.IsOK || !ExpressionNode.IsOK) { return; } //Check use of variable name if (!scope.VariableNameAvailable(IdNode.Name)) { report.AddError(SemanticErrors.VariableNameAlreadyInUse(IdNode, IdNode.Name)); return; } //Check children types if (TigerType.AreOfSameType(ExpressionNode.TigerType, TigerType.Nil) || TigerType.AreOfSameType(ExpressionNode.TigerType, TigerType.Void)) { report.AddError(SemanticErrors.InvalidImplicitVariableDeclaration(ExpressionNode, ExpressionNode.TigerType)); return; } //Add variable to scope VariableInfo = scope.DefineVariable(IdNode.Name, ExpressionNode.TigerType, scope); IsOK = true; }
public void CheckBodySemantics(TigerScope scope, Report report) { //If CheckSemantics failed (FunctionInfo was not created) return if (!IsOK) { return; } IsOK = false; //Create function scope FunctionBodyNode.CheckSemantics(FunctionScope, report); if (!FunctionBodyNode.IsOK) { return; } IsOK = true; if (ReturnTypeNode != null && !ReturnTypeNode.TigerType.Assignable(FunctionBodyNode.TigerType)) { report.AddError(SemanticErrors.IncompatibleFunctionReturnTypeBody(FunctionBodyNode, ReturnTypeNode.TigerType, FunctionBodyNode.TigerType)); } else if (ReturnTypeNode == null && !TigerType.AreOfSameType(TigerType.Void, FunctionBodyNode.TigerType)) { report.AddError(SemanticErrors.IncompatibleFunctionReturnTypeBody(FunctionBodyNode, TigerType.Void, FunctionBodyNode.TigerType)); } }
public override void GenerateCode(ILGenerator generator) { var saveFields = ContainingScope.FieldsToFunctionDeclaration(FunctionInfo); foreach (var fieldBuilder in saveFields) { generator.Emit(OpCodes.Ldsfld, fieldBuilder); } foreach (var expressionNode in Arguments) { expressionNode.GenerateCode(generator); } var method = FunctionInfo.MethodBuilder; generator.Emit(OpCodes.Call, method); LocalBuilder methodResult = null; if (!TigerType.AreOfSameType(FunctionInfo.ReturnType, TigerType.Void)) { methodResult = generator.DeclareLocal(FunctionInfo.ReturnType.Type); generator.Emit(OpCodes.Stloc, methodResult); } foreach (var t in saveFields) { generator.Emit(OpCodes.Stsfld, t); } if (!TigerType.AreOfSameType(FunctionInfo.ReturnType, TigerType.Void)) { generator.Emit(OpCodes.Ldloc, methodResult); } }
public override void GenerateCode(ILGenerator generator) { if (InstructionNodes.Length == 0) { return; } for (var i = 0; i < InstructionNodes.Length - 1; i++) { InstructionNodes[i].GenerateCode(generator); if (!TigerType.AreOfSameType(InstructionNodes[i].TigerType, TigerType.Void)) { generator.Emit(OpCodes.Pop); } } InstructionNodes.Last().GenerateCode(generator); }
public override void CheckSemantics(TigerScope scope, Report report) { ContainingScope = scope; //Check children LeftOperandNode.CheckSemantics(scope, report); RightOperandNode.CheckSemantics(scope, report); if (!LeftOperandNode.IsOK || !RightOperandNode.IsOK) { return; } TigerType = TigerType.Int; //Check children types if (!TigerType.AreCompatible(LeftOperandNode.TigerType, RightOperandNode.TigerType) || (TigerType.AreOfSameType(LeftOperandNode.TigerType, TigerType.Nil) && TigerType.AreOfSameType(RightOperandNode.TigerType, TigerType.Nil))) { report.AddError(SemanticErrors.InvalidIdentityComparison(this, LeftOperandNode.TigerType, RightOperandNode.TigerType)); } }
private static int Main(string[] args) { Console.WriteLine("Tiger Compiler version 1.0"); Console.WriteLine(@"Copyright (C) 2015-2016 Laila González Fernández & Mario César Muñiz Jiménez"); //Creating report, parser and lexer var arg = args[0]; var report = new Report(); var characters = new ANTLRFileStream(arg); var lexer = new TigerLexer(report, characters); var tokens = new CommonTokenStream(lexer); var parser = new TigerParser(report, tokens) { TraceDestination = Console.Out, TreeAdaptor = new TreeAdaptor() }; //Syntactic analysis var ret = (ProgramNode)parser.program().Tree; if (!report.IsOk) { foreach (var message in report) { Console.WriteLine($"({message.Line}, {message.Column}): {message.Text}"); } return(1); } //Preparing assembly var name = Path.GetFileNameWithoutExtension(arg); var filename = name + ".exe"; var assemblyName = new AssemblyName(name); var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assembly.DefineDynamicModule(name, filename); var programType = moduleBuilder.DefineType(name + ".Program", TypeAttributes.Public); var mainMethod = programType.DefineMethod("Main", MethodAttributes.Static | MethodAttributes.Public, typeof(void), Type.EmptyTypes); var generator = mainMethod.GetILGenerator(); assembly.SetEntryPoint(mainMethod); ProgramNode.Module = moduleBuilder; ProgramNode.Program = programType; //Semantic analysis ret.CheckSemantics(new TigerScope(programType), report); if (!report.IsOk) { foreach (var message in report) { Console.WriteLine($"({message.Line}, {message.Column}): {message.Text}"); } return(1); } generator.BeginExceptionBlock(); //Code generation ret.GenerateCode(generator); if (!TigerType.AreOfSameType(ret.TigerType, TigerType.Void)) { generator.Emit(OpCodes.Pop); } generator.BeginCatchBlock(typeof(Exception)); generator.BeginScope(); LocalBuilder exception = generator.DeclareLocal(typeof(Exception)); MethodInfo writeLineSO = typeof(TextWriter).GetMethod("WriteLine", new Type[] { typeof(string), typeof(object) }); MethodInfo writeLineS = typeof(TextWriter).GetMethod("WriteLine", new Type[] { typeof(string) }); MethodInfo standardErrorOutput = typeof(Console).GetProperty("Error").GetGetMethod(); generator.Emit(OpCodes.Stloc, exception); generator.Emit(OpCodes.Call, standardErrorOutput); generator.Emit(OpCodes.Ldstr, "Exception of type '{0}' was thrown."); generator.Emit(OpCodes.Ldloc, exception); generator.Emit(OpCodes.Callvirt, typeof(Exception).GetMethod("GetType", Type.EmptyTypes)); generator.Emit(OpCodes.Callvirt, typeof(Type).GetProperty("Name").GetGetMethod()); generator.Emit(OpCodes.Callvirt, writeLineSO); generator.Emit(OpCodes.Call, standardErrorOutput); generator.Emit(OpCodes.Ldloc, exception); generator.Emit(OpCodes.Callvirt, typeof(Exception).GetProperty("Message").GetGetMethod()); generator.Emit(OpCodes.Callvirt, writeLineS); generator.EndScope(); generator.Emit(OpCodes.Ldc_I4_1); generator.Emit(OpCodes.Call, typeof(Environment).GetMethod("Exit")); generator.EndExceptionBlock(); generator.Emit(OpCodes.Ret); programType.CreateType(); assembly.Save(filename); return(0); }