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

📄 generator.cs

📁 compiler programming, code something
💻 CS
📖 第 1 页 / 共 2 页
字号:
/*
Sharp Compiler
Copyright (C) 2003  Michael Bebenita

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections;

namespace Core.Compilation
{
	public class Generator
	{
		private Module m_Module = null;
		private SymbolTable m_Globals = null;

		public Generator(Module module)
		{
			m_Module = module;
		}

		public void Compile(string path)
		{
			AppDomain domain = System.Threading.Thread.GetDomain();
			AssemblyName name = new AssemblyName();
			name.Name = "Sharp Code Assembly";

			AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(name,AssemblyBuilderAccess.Save);
			ModuleBuilder moduleBuilder		= assemblyBuilder.DefineDynamicModule(m_Module.Name,m_Module.Name + ".exe",true);
			
			//
			// Create global variables.
			//

			TypeBuilder globalBuilder = moduleBuilder.DefineType("Global");
			m_Globals = new SymbolTable();
			foreach(Statement statement in m_Module.Body.Statements)
			{
				if(statement is Variable)
				{
					Variable variable = statement as Variable;
					System.Type type = variable.Type.ToSystemType();
					FieldBuilder field = globalBuilder.DefineField(variable.Name,type,FieldAttributes.Public | FieldAttributes.Static);
					m_Globals.Add(variable.Name,SymbolType.Variable,statement,field);
				}
			}

			globalBuilder.CreateType();
			
			//
			// Create functions.
			//

			m_Module.Body.SymbolTable = m_Globals;
			BuildFunctionStubs(m_Module.Body,moduleBuilder);

			foreach(Function function in m_Module.Body.Functions)
			{
				BuildFunction(function);
			}
	
			//
			// Create entry point.
			//

			MethodBuilder mainBuilder =  moduleBuilder.DefineGlobalMethod("Main",MethodAttributes.Public | MethodAttributes.Static,typeof(void),null);
			ILGenerator mainIL = mainBuilder.GetILGenerator();

			EmitBody(mainIL,m_Module.Body,true);

			moduleBuilder.CreateGlobalFunctions();
			assemblyBuilder.SetEntryPoint(mainBuilder.GetBaseDefinition());
			assemblyBuilder.Save(m_Module.Name + ".exe");

			System.IO.File.Move(m_Module.Name + ".exe",path);
			
		}

		private void FindFunction(Body body, ArrayList functions)
		{
			if(body != null && body.Functions != null)
			{
				foreach(Function function in body.Functions)
					FindFunction(function.Body,functions);
			}	
		}

		private void Error(string message)
		{
			throw new Exception(message);
		}
	
		private void EmitExpression(ILGenerator il, Expression expression, SymbolTable symbolTable)
		{
			if(expression is BinaryExpression)
			{
				EmitExpression(il,((BinaryExpression)expression).Left,symbolTable);
				EmitExpression(il,((BinaryExpression)expression).Right,symbolTable);
				
				switch( ((BinaryExpression)expression).BinaryOperatorType )
				{
					case BinaryOperatorType.Add:
						il.Emit(OpCodes.Add);
						break;
					case BinaryOperatorType.Subtract:
						il.Emit(OpCodes.Sub);
						break;
					case BinaryOperatorType.Multiply:
						il.Emit(OpCodes.Mul);
						break;
					case BinaryOperatorType.Divide:
						il.Emit(OpCodes.Div);
						break;
					case BinaryOperatorType.Modulo:
						il.Emit(OpCodes.Rem);
						break;
					case BinaryOperatorType.Equal:
						il.Emit(OpCodes.Ceq);
						break;
					case BinaryOperatorType.NotEqual:
						il.Emit(OpCodes.Ceq);
						il.Emit(OpCodes.Ldc_I4_0);
						il.Emit(OpCodes.Ceq);
						break;
					case BinaryOperatorType.GreaterThen:
						il.Emit(OpCodes.Cgt);
						break;
					case BinaryOperatorType.LessThen:
						il.Emit(OpCodes.Clt);
						break;
					case BinaryOperatorType.GraterOrEqualTo:
						il.Emit(OpCodes.Clt);
						il.Emit(OpCodes.Ldc_I4_0);
						il.Emit(OpCodes.Ceq);
						break;
					case BinaryOperatorType.LessOrEqualTo:
						il.Emit(OpCodes.Cgt);
						il.Emit(OpCodes.Ldc_I4_0);
						il.Emit(OpCodes.Ceq);
						break;
					case BinaryOperatorType.And:
						il.Emit(OpCodes.And);
						break;
					case BinaryOperatorType.Or:
						il.Emit(OpCodes.Or);
						break;
				}
			}
			else if(expression is UnaryExpression)
			{
				UnaryExpression unaryExpression = expression as UnaryExpression;

				switch(unaryExpression.UnaryOperatorType)
				{
					case UnaryOperatorType.Indexer:
						EmitExpression(il,unaryExpression.Value,symbolTable);
						EmitExpression(il,unaryExpression.Indexer,symbolTable);
						il.Emit(OpCodes.Ldelem_I4);
						break;
					case UnaryOperatorType.Negative:
						EmitExpression(il,unaryExpression.Value,symbolTable);
						il.Emit(OpCodes.Neg);
						break;
					case UnaryOperatorType.Not:
						EmitExpression(il,unaryExpression.Value,symbolTable);
						il.Emit(OpCodes.Not);
						break;

				}
			}
			else if(expression is Literal)
			{
				Literal literal = expression as Literal;

				switch(literal.LiteralType)
				{
					case LiteralType.Integer:
						il.Emit(OpCodes.Ldc_I4,Int32.Parse(literal.Value));
						break;
					case LiteralType.Real:
						il.Emit(OpCodes.Ldc_R4,float.Parse(literal.Value));
						break;
					case LiteralType.Character:
						il.Emit(OpCodes.Ldc_I4,char.GetNumericValue(literal.Value,0));
						break;
					case LiteralType.Boolean:
						if(literal.Value == "true")
							il.Emit(OpCodes.Ldc_I4,1);
						else if(literal.Value == "false")
							il.Emit(OpCodes.Ldc_I4,0);
						break;
				}
			}
			else if(expression is Name)
			{
				Name name = expression as Name;

				Symbol variable = symbolTable.Find(name.Value,SymbolType.Variable);
				if(variable == null)
					Error("Assignment variable " + name.Value + " unknown.");

				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);
				else if(variable.CodeObject is ParameterBuilder)
				{
					Parameter p = variable.SyntaxObject as Parameter;
					il.Emit(OpCodes.Ldarg_S,((ParameterBuilder)variable.CodeObject).Position - 1);
					if(p.PassMethod == PassMethod.ByReference)
						il.Emit(OpCodes.Ldind_I4);
				}

			}
			else if(expression is Call)
			{
				EmitCall(il,expression as Call,symbolTable);
			}
		}


		
		// Used to keep all function names unique.
		private SymbolTable m_Functions = new SymbolTable();
 
		private void BuildFunctionStubs(Body body, ModuleBuilder builder)
		{
			if(body == null || builder == null)
				throw new ArgumentNullException();

			SymbolTable sibillings = new SymbolTable(m_Globals);

			if(body != null && body.Functions != null)
			{
				foreach(Function function in body.Functions)
				{
					// Make child visible to sibillings
					function.Body.SymbolTable = sibillings;

					MethodBuilder method = BuildFunctionStub(function,builder);

					// Make child visible to parent.
					body.SymbolTable.Add(function.Name,SymbolType.Function,function,method);
					sibillings.Add(function.Name,SymbolType.Function,function,method);
					

					BuildFunctionStubs(function.Body,builder);
				}
			}
		}

		private MethodBuilder BuildFunctionStub(Function function, ModuleBuilder builder)
		{
			if(function == null || builder == null)
				throw new ArgumentNullException();
			//
			// Build function stub.
			//

			// Find an unique name.
			string functionName = function.Name;
			while(m_Functions.Find(functionName,SymbolType.Function) != null)
				functionName += "#";
	
			// Find return type.
			System.Type returnType = function.Type.ToSystemType();

			// Find parameters.
			System.Type [] parameters  = null;
			if(function.Parameters != null)
			{
				parameters = new System.Type[function.Parameters.Count];

				for(int x = 0; x < function.Parameters.Count; x++)
				{
					parameters[x] = function.Parameters[x].Type.ToSystemType();
				}
			}

			// Create method.
			MethodBuilder method = builder.DefineGlobalMethod(functionName,MethodAttributes.Public | MethodAttributes.Static,returnType, parameters);

			if(function.Parameters != null)
			{
				for(int x = 0; x < function.Parameters.Count; x++)
				{
					ParameterBuilder p = null;
					p = method.DefineParameter(x+1,ParameterAttributes.None,function.Parameters[x].Name);
					function.Body.SymbolTable.Add(p.Name,SymbolType.Variable,function.Parameters[x],p);
				}
			}
			
			function.Builder = method;
			m_Functions.Add(functionName,SymbolType.Function,function,method);
			return method;
		}

		private void BuildFunction(Function function)
		{
			if(function == null)
				throw new ArgumentNullException();

			//
			// Build child functions.
			//

			if(function.Body.Functions != null)
			{
				foreach(Function child in function.Body.Functions)
					BuildFunction(child);
			}

			//
			// Build function body.
			//
			
			ILGenerator il = function.Builder.GetILGenerator();

			EmitBody(il,function.Body,false);

			return;

		}

		private void EmitBody(ILGenerator il, Body body, bool root)
		{
			//
			// Declare local variables.
			//

			foreach(Statement statement in body.Statements)
			{
				if(statement is Variable)
				{
					Variable variable = statement as Variable;

					LocalBuilder local = null;
					FieldBuilder global = null;

					if(root)
					{
						global = (FieldBuilder)body.SymbolTable.Find(variable.Name,SymbolType.Variable).CodeObject;
					}
					else
					{
						local = il.DeclareLocal(variable.Type.ToSystemType());
						body.SymbolTable.Add(variable.Name,SymbolType.Variable,variable,local);
					}

					//
					// Initialize  variable.
					//

					if(variable.Type.VariableType == VariableType.Primitive)
					{
						if(variable.Value != null && variable.Value is Expression)
						{
							EmitExpression(il,(Expression)variable.Value,body.SymbolTable);
								
							if(root)
								il.Emit(OpCodes.Stsfld,global);
							else
								il.Emit(OpCodes.Stloc,local);	
						}
					}
					else if(variable.Type.VariableType == VariableType.PrimitiveArray)
					{
						// Empty array initialization.
						if(variable.Value != null && variable.Value is Expression)
						{
							EmitExpression(il,(Expression)variable.Value,body.SymbolTable);
							il.Emit(OpCodes.Newarr,variable.Type.ToSystemType());
							if(root)
								il.Emit(OpCodes.Stsfld,global);
							else
								il.Emit(OpCodes.Stloc,local);	
						}
						else if(variable.Value != null && variable.Value is ElementCollection)
						{
							ElementCollection elements = variable.Value as ElementCollection;
							
							il.Emit(OpCodes.Ldc_I4,elements.Count);
							il.Emit(OpCodes.Newarr,variable.Type.ToSystemType());
							if(root)
								il.Emit(OpCodes.Stsfld,global);
							else
								il.Emit(OpCodes.Stloc,local);

							for(int x = 0;x<elements.Count;x++)
							{
								// Load array
								if(root)
									il.Emit(OpCodes.Ldsfld,global);
								else
									il.Emit(OpCodes.Ldloc,local);
								// Load index
								il.Emit(OpCodes.Ldc_I4,x);
								// Load value
								EmitExpression(il,elements[x].Expression,body.SymbolTable);
								// Store
								il.Emit(OpCodes.Stelem_I4);
							}

						}

					}
				}
				else if(statement is Assignment)
				{
					EmitAssignment(il,statement as Assignment,body.SymbolTable);
				}

⌨️ 快捷键说明

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