⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 generator.cs

📁 compiler programming, code something
💻 CS
📖 第 1 页 / 共 2 页
字号:
				else if(statement is Return)
				{
					if(((Return)statement).Value != null)
						EmitExpression(il,((Return)statement).Value,body.SymbolTable);
					il.Emit(OpCodes.Ret);
				}
				else if(statement is CallStatement)
				{
					CallStatement call = statement as CallStatement;
					Symbol symbol = body.SymbolTable.Find(call.Name,SymbolType.Function);
					EmitCallStatement(il,statement as CallStatement,body.SymbolTable);

					if(symbol != null)
					{
						if(((MethodBuilder)symbol.CodeObject).ReturnType != typeof(void))
							il.Emit(OpCodes.Pop);
					}
					else
					{
						if(call.Name == "Read")
							il.Emit(OpCodes.Pop);
					}
					
				}
				else if(statement is If)
				{
					//
					// Genereate if statement.
					//

					If ifStatement = statement as If;

					// Eval condition
					EmitExpression(il,ifStatement.Condition,body.SymbolTable);

					if(ifStatement.IfBody != null && ifStatement.ElseBody == null)
					{
						ifStatement.IfBody.SymbolTable = new SymbolTable(body.SymbolTable);
						Label exit = il.DefineLabel();
						il.Emit(OpCodes.Brfalse,exit);
						EmitBody(il,ifStatement.IfBody,false);
						il.MarkLabel(exit);
					}
					else if(ifStatement.IfBody != null && ifStatement.ElseBody != null)
					{
						ifStatement.IfBody.SymbolTable = new SymbolTable(body.SymbolTable);
						ifStatement.ElseBody.SymbolTable = new SymbolTable(body.SymbolTable);
						Label exit = il.DefineLabel();
						Label elseLabel = il.DefineLabel();
						il.Emit(OpCodes.Brfalse,elseLabel);
						EmitBody(il,ifStatement.IfBody,false);
						il.Emit(OpCodes.Br,exit);
						il.MarkLabel(elseLabel);
						EmitBody(il,ifStatement.ElseBody,false);
						il.MarkLabel(exit);
					}
				}

				else if(statement is While)
				{
					//
					// Generate while statement.
					//

					While whileStatement = statement as While;
					whileStatement.Body.SymbolTable = new SymbolTable(body.SymbolTable);
					Label begin = il.DefineLabel();
					Label exit = il.DefineLabel();
					il.MarkLabel(begin);
					// Eval condition
					EmitExpression(il,whileStatement.Condition,body.SymbolTable);
					il.Emit(OpCodes.Brfalse,exit);
					EmitBody(il,whileStatement.Body,false);
					il.Emit(OpCodes.Br,begin);
					il.MarkLabel(exit);

				}
				else if(statement is Do)
				{
					//
					// Generate do statement.
					//

					Do doStatement = statement as Do;
					doStatement.Body.SymbolTable = new SymbolTable(body.SymbolTable);
				
					Label loop = il.DefineLabel();
					il.MarkLabel(loop);
					EmitBody(il,doStatement.Body,false);
					EmitExpression(il,doStatement.Condition,body.SymbolTable);
					il.Emit(OpCodes.Brtrue,loop);
				}
				else if(statement is For)
				{
					//
					// Generate for statement.
					//

					For forStatement = statement as For;
					forStatement.Body.SymbolTable = new SymbolTable(body.SymbolTable);
				
					Label loop = il.DefineLabel();
					Label exit = il.DefineLabel();

					// Emit initializer
					EmitAssignment(il,forStatement.Initializer,body.SymbolTable);
					il.MarkLabel(loop);
					// Emit condition
					EmitExpression(il,forStatement.Condition,body.SymbolTable);
					il.Emit(OpCodes.Brfalse,exit);
					// Emit body
					EmitBody(il,forStatement.Body,false);
					// Emit counter
					EmitAssignment(il,forStatement.Counter,body.SymbolTable);
					il.Emit(OpCodes.Br,loop);
					il.MarkLabel(exit);
				}

			}
		}

		private void EmitAssignment(ILGenerator il, Assignment assignment, SymbolTable symbolTable)
		{
			Symbol variable = symbolTable.Find(assignment.Name,SymbolType.Variable);
			if(variable == null)
				Error("Assignment variable " + assignment.Name + " unknown.");

			// Non-indexed assignment
			if(assignment.Index == null)
			{
				if(variable.CodeObject is ParameterBuilder)
				{
					Parameter p = variable.SyntaxObject as Parameter;
					if(p.PassMethod == PassMethod.ByReference)
						il.Emit(OpCodes.Ldarg_S,((ParameterBuilder)variable.CodeObject).Position - 1);
				}

				// Load value
				EmitExpression(il,assignment.Value,symbolTable);

				// Store
				if(variable.CodeObject is LocalBuilder)
					il.Emit(OpCodes.Stloc,(LocalBuilder)variable.CodeObject);
				else if(variable.CodeObject is FieldBuilder)
					il.Emit(OpCodes.Stsfld,(FieldBuilder)variable.CodeObject);
				else if(variable.CodeObject is ParameterBuilder)
				{
					Parameter p = variable.SyntaxObject as Parameter;
					if(p.PassMethod == PassMethod.ByReference)
						il.Emit(OpCodes.Stind_I4);
					else
						il.Emit(OpCodes.Starg,((ParameterBuilder)variable.CodeObject).Position - 1);
				}		
			}
			else
			{
				// Load array.
				if(variable.CodeObject is LocalBuilder)
					il.Emit(OpCodes.Ldloc,(LocalBuilder)variable.CodeObject);
				else if(variable.CodeObject is FieldBuilder)
					il.Emit(OpCodes.Ldsfld,(FieldBuilder)variable.CodeObject);
				// Load index.
				EmitExpression(il,assignment.Index,symbolTable);
				// Load value.
				EmitExpression(il,assignment.Value,symbolTable);
				// Set
				il.Emit(OpCodes.Stelem_I4);
			}
		}

		private void EmitCall(ILGenerator il, Call call, SymbolTable symbolTable)
		{
			Symbol symbol = symbolTable.Find(call.Name,SymbolType.Function);
			
			if(symbol != null)
			{
				Function function = symbol.SyntaxObject as Function;

				//
				// Check arguments
				//

				if(call.Arguments == null && function.Parameters == null)
				{
					// Ugly hack.
					goto Hack;
				}
				else if(call.Arguments.Count != function.Parameters.Count)
				{
					Error("Argument mismatch [" + call.Name + "]");
				}
				else if(call.Arguments.Count != function.Parameters.Count)
				{
					Error("Argument mismatch [" + call.Name + "]");
				}
				else
				{
					for(int x = 0;x<call.Arguments.Count;x++)
					{
						if(call.Arguments[x].PassMethod != function.Parameters[x].PassMethod)
						{
							Error("Argument error [" + call.Name + "], argument [" + x + "] is wrong.");
						}
					}
				}

				if(call.Arguments != null)
				{
					foreach(Argument argument in call.Arguments)
					{
						if(argument.PassMethod == PassMethod.ByReference)
						{
							// Regular value
							if(argument.Value is Name)
							{
								Symbol variable = symbolTable.Find(((Name)argument.Value).Value,SymbolType.Variable);
								if(variable.CodeObject is LocalBuilder)
								{
									il.Emit(OpCodes.Ldloca,variable.CodeObject as LocalBuilder);
								}
								else if(variable.CodeObject is FieldBuilder)
								{
									il.Emit(OpCodes.Ldsflda,variable.CodeObject as FieldBuilder);
								}
								else if(variable.CodeObject is ParameterBuilder)
								{
									il.Emit(OpCodes.Ldarga_S,((ParameterBuilder) variable.CodeObject).Position - 1);
								}
							}
							else if(argument.Value is UnaryExpression && ((UnaryExpression)argument.Value).UnaryOperatorType == UnaryOperatorType.Indexer)
							{
								Symbol variable = symbolTable.Find(((Name)argument.Value).Value,SymbolType.Variable);
								if(variable.CodeObject is LocalBuilder)
								{
									if( ((Variable)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
										Error("ref cannot be applied to arrays");
									il.Emit(OpCodes.Ldloca,variable.CodeObject as LocalBuilder);
								}
								else if(variable.CodeObject is FieldBuilder)
								{
									if( ((Variable)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
										Error("ref cannot be applied to arrays");
									il.Emit(OpCodes.Ldsflda,variable.CodeObject as FieldBuilder);
								}
								else if(variable.CodeObject is ParameterBuilder)
								{
									if( ((Parameter)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
										Error("ref cannot be applied to arrays");
									il.Emit(OpCodes.Ldarga,((ParameterBuilder) variable.CodeObject).Position - 1);
								}

								EmitExpression(il,((UnaryExpression)argument.Value).Indexer,symbolTable);
								il.Emit(OpCodes.Ldelema);
							}
							else
							{
								Error("ref may only be applied to variables");
							}
						}
						else
						{
							EmitExpression(il,argument.Value,symbolTable);
						}
					}
				}

			Hack:
				il.Emit(OpCodes.Call,((MethodBuilder)symbol.CodeObject));
			}
			else
			{
				if(call.Name == "Read")
				{
					il.Emit(OpCodes.Ldstr,"Input > ");
					MethodInfo write = System.Type.GetType("System.Console").GetMethod("Write",new System.Type [] {typeof(string)});
					il.EmitCall(OpCodes.Call,write,null);

					MethodInfo read = System.Type.GetType("System.Console").GetMethod("ReadLine");
					MethodInfo parse = System.Type.GetType("System.Int32").GetMethod("Parse",new System.Type [] {typeof(string)});
					il.EmitCall(OpCodes.Call,read,null);
					il.EmitCall(OpCodes.Call,parse,null);
				}
				else if(call.Name == "Write")
				{
					EmitExpression(il,call.Arguments[0].Value,symbolTable);
					MethodInfo write = System.Type.GetType("System.Console").GetMethod("WriteLine",new System.Type [] {typeof(int)});
					il.EmitCall(OpCodes.Call,write,null);
				}
				else
				{
					Error("Unknown function name. [" + call.Name + "]");
				}
			}
		}


		private void EmitCallStatement(ILGenerator il, CallStatement call, SymbolTable symbolTable)
		{
			Symbol symbol = symbolTable.Find(call.Name,SymbolType.Function);
			
			if(symbol != null)
			{
				Function function = symbol.SyntaxObject as Function;

				//
				// Check arguments
				//
				if(call.Arguments == null && function.Parameters == null)
				{
					// Ugly hack.
					goto Hack;
				}
				else if(call.Arguments.Count != function.Parameters.Count)
				{
					Error("Argument mismatch [" + call.Name + "]");
				}
				else if(call.Arguments.Count != function.Parameters.Count)
				{
					Error("Argument mismatch [" + call.Name + "]");
				}
				else
				{
					for(int x = 0;x<call.Arguments.Count;x++)
					{
						if(call.Arguments[x].PassMethod != function.Parameters[x].PassMethod)
						{
							Error("Argument error [" + call.Name + "], argument [" + x + "] is wrong.");
						}
					}
				}

				if(call.Arguments != null)
				{
					foreach(Argument argument in call.Arguments)
					{
						if(argument.PassMethod == PassMethod.ByReference)
						{
							// Regular value
							if(argument.Value is Name)
							{
								Symbol variable = symbolTable.Find(((Name)argument.Value).Value,SymbolType.Variable);
								if(variable.CodeObject is LocalBuilder)
								{
									if( ((Variable)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
										Error("ref cannot be applied to arrays");
									il.Emit(OpCodes.Ldloca,variable.CodeObject as LocalBuilder);
								}
								else if(variable.CodeObject is FieldBuilder)
								{
									if( ((Variable)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
										Error("ref cannot be applied to arrays");
									il.Emit(OpCodes.Ldsflda,variable.CodeObject as FieldBuilder);
								}
								else if(variable.CodeObject is ParameterBuilder)
								{
									if( ((Parameter)variable.SyntaxObject).Type.VariableType == VariableType.PrimitiveArray)
										Error("ref cannot be applied to arrays");
									il.Emit(OpCodes.Ldarga,((ParameterBuilder) variable.CodeObject).Position - 1);
								}
							}
							else if(argument.Value is UnaryExpression && ((UnaryExpression)argument.Value).UnaryOperatorType == UnaryOperatorType.Indexer)
							{
								Symbol variable = symbolTable.Find(((Name)argument.Value).Value,SymbolType.Variable);
								if(variable.CodeObject is LocalBuilder)
								{
									il.Emit(OpCodes.Ldloc,variable.CodeObject as LocalBuilder);
								}
								else if(variable.CodeObject is FieldBuilder)
								{
									il.Emit(OpCodes.Ldsfld,variable.CodeObject as FieldBuilder);
								}
								else if(variable.CodeObject is ParameterBuilder)
								{
									il.Emit(OpCodes.Ldarga,((ParameterBuilder) variable.CodeObject).Position - 1);
								}

								EmitExpression(il,((UnaryExpression)argument.Value).Indexer,symbolTable);
								il.Emit(OpCodes.Ldelema);
							}
							else
							{
								Error("ref may only be applied to variables");
							}
						}
						else
						{
							EmitExpression(il,argument.Value,symbolTable);
						}
					}
				}

			Hack:
				il.Emit(OpCodes.Call,((MethodBuilder)symbol.CodeObject));
			}
			else
			{
				if(call.Name == "Read")
				{
					il.Emit(OpCodes.Ldstr,"Input > ");
					MethodInfo write = System.Type.GetType("System.Console").GetMethod("Write",new System.Type [] {typeof(string)});
					il.EmitCall(OpCodes.Call,write,null);

					MethodInfo read = System.Type.GetType("System.Console").GetMethod("ReadLine");
					MethodInfo parse = System.Type.GetType("System.Int32").GetMethod("Parse",new System.Type [] {typeof(string)});
					il.EmitCall(OpCodes.Call,read,null);
					il.EmitCall(OpCodes.Call,parse,null);

				}
				else if(call.Name == "Write")
				{
					EmitExpression(il,call.Arguments[0].Value,symbolTable);
					MethodInfo write = System.Type.GetType("System.Console").GetMethod("WriteLine",new System.Type [] {typeof(int)});
					il.EmitCall(OpCodes.Call,write,null);
				}
				else
				{
					Error("Unknown function name. [" + call.Name + "]");
				}
			}
		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -