public static void EmitVariableDefinition(VariableSymbol vSymbol, SymbolTable table, ILGenerator ilGen) { Type localType = GetTypeForCompilerType(vSymbol.VariableType); LocalBuilder localBuilder = ilGen.DeclareLocal(localType); if (vSymbol.InitExpression != null) { if (vSymbol.InitExpression.ResultType.TypeEnum == VariableTypeEnum.NULL) { Type arrayType = GetTypeForCompilerType(vSymbol.VariableType); ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType)); } else { EmitExpression(vSymbol.InitExpression, table, ilGen); } } else { if (vSymbol.VariableType.TypeEnum == VariableTypeEnum.Array) { MethodInfo mi = GetArrayNullGetter(localType); ilGen.Emit(OpCodes.Call, mi); } else { ilGen.Emit(OpCodes.Ldc_I4_0); } } ilGen.Emit(OpCodes.Stloc, localBuilder); table.AddSymbol(vSymbol.Name, localType, localBuilder); }
public static AssemblyBuilder GenerateAssembly(string name, L1Program program) { AssemblyName assemblyName = new AssemblyName(name); AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.ToString(), assemblyName + ".exe"); //Main method TypeBuilder mainTypeBuilder = moduleBuilder.DefineType("L1ProgramMain", TypeAttributes.Class | TypeAttributes.Public); MethodBuilder mainMethodBuilder = mainTypeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static); mainMethodBuilder.SetParameters(typeof(string[])); ILGenerator mainIlGenerator = mainMethodBuilder.GetILGenerator(); mainIlGenerator.Emit(OpCodes.Ldarg_0); mainIlGenerator.Emit(OpCodes.Call, f_mainRuntimeMethod); mainIlGenerator.Emit(OpCodes.Ret); //Program methods TypeBuilder functionsTypeBuilder = moduleBuilder.DefineType("L1ProgramFunctions", TypeAttributes.Class | TypeAttributes.Public); List<MethodBuilder> functionBuilders = new List<MethodBuilder>(); foreach (FunctionDefinition fDef in program.Functions) { if (fDef.IsEmbedded) continue; MethodBuilder functionBuilder = functionsTypeBuilder.DefineMethod(fDef.Header.FunctionName, MethodAttributes.Public | MethodAttributes.Static); if (fDef.Header.ReturnType != null) { Type t = GetTypeForCompilerType(fDef.Header.ReturnType); functionBuilder.SetReturnType(t); } else { functionBuilder.SetReturnType(typeof(void)); } List<Type> paramTypes = new List<Type>(); foreach (FunctionParameter parameter in fDef.Header.Parameters) { Type t = GetTypeForCompilerType(parameter.Type); paramTypes.Add(t); } functionBuilder.SetParameters(paramTypes.ToArray()); f_functions.Add(fDef.Header, functionBuilder); } foreach (FunctionDefinition fDef in program.Functions) { if (fDef.IsEmbedded) continue; MethodBuilder functionBuilder = (MethodBuilder)f_functions[fDef.Header]; ILGenerator ilGen = functionBuilder.GetILGenerator(); SymbolTable table = new SymbolTable(); int i = 0; foreach (FunctionParameter parameter in fDef.Header.Parameters) { Type t = GetTypeForCompilerType(parameter.Type); table.AddSymbol(parameter.Name, t, i++); } EmitFunction(fDef, table, ilGen); } //Завершение процесса генерации Type tMain = mainTypeBuilder.CreateType(); Type tFunctions = functionsTypeBuilder.CreateType(); moduleBuilder.CreateGlobalFunctions(); assemblyBuilder.SetEntryPoint(mainMethodBuilder, PEFileKinds.ConsoleApplication); return assemblyBuilder; }
public static void EmitStatementList(StatementList statements, SymbolTable table, ILGenerator ilGen) { foreach (Statement statement in statements) { #region MarkLabel if (!String.IsNullOrEmpty(statement.Label)) { ilGen.MarkLabel(f_contextLabels[statement.Label]); } #endregion #region GoTo if (statement is GotoStatement) { ilGen.Emit(OpCodes.Br, f_contextLabels[(statement as GotoStatement).GoTo]); } #endregion #region Expression if (statement is Expression) { Expression expr = (Expression)statement; EmitExpression(expr, table, ilGen); if (!wasVoidFuncCalled) { ilGen.Emit(OpCodes.Pop); } wasVoidFuncCalled = false; } #endregion #region VariableDefinitionList if (statement is VariableDefinitionList) { VariableDefinitionList vdList = (VariableDefinitionList)statement; foreach (VariableSymbol vSymbol in vdList.Definitions) { EmitVariableDefinition(vSymbol, table, ilGen); } } #endregion #region Return if (statement is ReturnStatement) { ReturnStatement returnStatement = (ReturnStatement)statement; EmitReturn(returnStatement, table, ilGen); } #endregion #region Assert if (statement is AssertStatement) { AssertStatement assertStatement = (AssertStatement)statement; EmitExpression(assertStatement.Expression, table, ilGen); ilGen.Emit(OpCodes.Ldc_I4, assertStatement.Expression.Location.eLin); ilGen.Emit(OpCodes.Call, GetAssert()); } #endregion #region WhileDo if (statement is WhileDoStatement) { WhileDoStatement wds = (WhileDoStatement)statement; SymbolTable newTable = new SymbolTable(table); Label condition = ilGen.DefineLabel(); Label endLoop = ilGen.DefineLabel(); ilGen.MarkLabel(condition); EmitExpression(wds.Condition, table, ilGen); ilGen.Emit(OpCodes.Brfalse, endLoop); EmitStatementList(wds.Statements, newTable, ilGen); ilGen.Emit(OpCodes.Br, condition); ilGen.MarkLabel(endLoop); } #endregion #region DoWhile if (statement is DoWhileStatement) { DoWhileStatement dws = (DoWhileStatement)statement; SymbolTable newTable = new SymbolTable(table); Label begin = ilGen.DefineLabel(); ilGen.MarkLabel(begin); EmitStatementList(dws.Statements, newTable, ilGen); EmitExpression(dws.Condition, table, ilGen); ilGen.Emit(OpCodes.Brtrue, begin); } #endregion #region If if (statement is IfStatement) { IfStatement ifStatement = (IfStatement)statement; Label end = ilGen.DefineLabel(); Label elseLabel = ilGen.DefineLabel(); List<Label> labels = new List<Label>(); labels.Add(new Label()); for (int i = 1; i < ifStatement.Clauses.Count; ++i) { labels.Add(ilGen.DefineLabel()); } labels.Add(elseLabel); for (int i = 0; i < ifStatement.Clauses.Count; ++i) { SymbolTable newTable = new SymbolTable(table); if (i != 0) ilGen.MarkLabel(labels[i]); EmitExpression(ifStatement.Clauses[i].Condition, table, ilGen); ilGen.Emit(OpCodes.Brfalse, labels[i + 1]); EmitStatementList(ifStatement.Clauses[i].Statements, newTable, ilGen); ilGen.Emit(OpCodes.Br, end); } ilGen.MarkLabel(elseLabel); if (ifStatement.AlternativeStatements != null) { SymbolTable newTable = new SymbolTable(table); EmitStatementList(ifStatement.AlternativeStatements, newTable, ilGen); } ilGen.MarkLabel(end); } #endregion #region СycleFor if (statement is CycleStatement) { CycleStatement cycle = (CycleStatement)statement; SymbolTable newTable = new SymbolTable(table); Symbol cycleIndex = null; if (cycle.DeclareVariable != String.Empty) { Type localType = GetTypeForCompilerType(cycle.VariableType); LocalBuilder indx = ilGen.DeclareLocal(localType); newTable.AddSymbol(cycle.DeclareVariable, localType, indx); cycleIndex = newTable.FindSymbol(cycle.DeclareVariable); } else { string indexName = cycle.Init.LeftNode.Value.ToString(); Symbol symbol = table.FindSymbol(indexName); cycleIndex = symbol; } LocalBuilder end = ilGen.DeclareLocal(typeof(int)); LocalBuilder step = ilGen.DeclareLocal(typeof(int)); Label loopLabel = ilGen.DefineLabel(); Label endLabel = ilGen.DefineLabel(); //Save cycle step and end condition to local variables EmitExpression(cycle.Step, table, ilGen); ilGen.Emit(OpCodes.Stloc, step); EmitExpression(cycle.EndValue, table, ilGen); ilGen.Emit(OpCodes.Stloc, end); //Init variable if (cycle.DeclareVariable == String.Empty) { EmitExpression(cycle.Init, table, ilGen); ilGen.Emit(OpCodes.Pop); } else { EmitExpression(cycle.Init, table, ilGen); ilGen.Emit(OpCodes.Stloc, cycleIndex.LocalBuilder); } ilGen.MarkLabel(loopLabel); //Check for cycle' condition if (cycleIndex.IsParameter) ilGen.Emit(OpCodes.Ldarg, cycleIndex.ParameterIndex); else ilGen.Emit(OpCodes.Ldloc, cycleIndex.LocalBuilder); ilGen.Emit(OpCodes.Ldloc, end); ilGen.Emit(OpCodes.Cgt); ilGen.Emit(OpCodes.Brtrue, endLabel); //Cycle body EmitStatementList(cycle.Statements, newTable, ilGen); //Increment if (cycleIndex.IsParameter) ilGen.Emit(OpCodes.Ldarg, cycleIndex.ParameterIndex); else ilGen.Emit(OpCodes.Ldloc, cycleIndex.LocalBuilder); ilGen.Emit(OpCodes.Ldloc, step); ilGen.Emit(OpCodes.Add); if (cycleIndex.Type == typeof(char)) ilGen.Emit(OpCodes.Conv_U2); if (cycleIndex.IsParameter) ilGen.Emit(OpCodes.Starg, cycleIndex.ParameterIndex); else ilGen.Emit(OpCodes.Stloc, cycleIndex.LocalBuilder); ilGen.Emit(OpCodes.Br, loopLabel); ilGen.MarkLabel(endLabel); } #endregion } }