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); // // Создаем глобальные переменные // 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(); // // Строим функции // m_Module.Body.SymbolTable = m_Globals; BuildFunctionStubs(m_Module.Body, moduleBuilder); foreach (Function function in m_Module.Body.Functions) { BuildFunction(function); } // // Создаем точку входа (функция main) // MethodBuilder mainBuilder = moduleBuilder.DefineGlobalMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(void), null); ILGenerator mainIL = mainBuilder.GetILGenerator(); m_Module.Body.Statements.Add(new CallStatement(null, "main")); 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 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; case LiteralType.String: il.Emit(OpCodes.Ldstr, literal.Value); 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); } }
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; // // Проверка аргументов // if (call.Arguments == null && function.Parameters == null) { 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) { // Если параметр передан по ссылке 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 = null; if (call.Arguments[0].Value is Literal) { Literal temp = call.Arguments[0].Value as Literal; System.Type type = null; switch (temp.LiteralType) { case LiteralType.Boolean: type = typeof(bool); break; case LiteralType.Character: type = typeof(char); break; case LiteralType.Integer: type = typeof(int); break; case LiteralType.Real: type = typeof(double); break; case LiteralType.String: type = typeof(string); break; } write = System.Type.GetType("System.Console").GetMethod("WriteLine", new System.Type[] { type }); } else { 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 EmitAssignment(ILGenerator il, Assignment assignment, SymbolTable symbolTable) { Symbol variable = symbolTable.Find(assignment.Name, SymbolType.Variable); if (variable == null) Error("Assignment variable " + assignment.Name + " unknown."); // Не массив 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); } // Получаем значение EmitExpression(il, assignment.Value, symbolTable); // Сохраняем 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 { // Загружаем массив 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); // Индекс EmitExpression(il, assignment.Index, symbolTable); // Значение EmitExpression(il, assignment.Value, symbolTable); // Устанавливаем значение il.Emit(OpCodes.Stelem_I4); } }
public SymbolTable(SymbolTable parent) { m_Parent = parent; }
private void BuildSymbolTable(SymbolTable parent, Body body) { if (body.Structures != null) foreach (Structure structure in body.Structures) parent.Add(structure).SyntaxObject = structure; if (body.Functions != null) { foreach (Function function in body.Functions) { parent.Add(function).SyntaxObject = function; function.Body.SymbolTable = new SymbolTable(); BuildSymbolTable(function.Body.SymbolTable, function.Body); } } if (body.Statements != null) { foreach (Statement statement in body.Statements) { if (statement is Variable) parent.Add(statement as Variable).SyntaxObject = statement; } } }
public bool VerifyExpression(SymbolTable symbolTable, Expression expression) { // // Verify expression. // try { GetExpressionType(symbolTable, expression); return true; } catch (VerifierException x) { System.Diagnostics.Debug.WriteLine(x.Message); return false; } }
public Type GetExpressionType(SymbolTable symbolTable, Expression expression) { if (expression is UnaryExpression) { UnaryExpression unary = (UnaryExpression)expression; return FindType(GetExpressionType(symbolTable, unary.Value), unary.UnaryOperatorType); } else if (expression is BinaryExpression) { BinaryExpression binary = (BinaryExpression)expression; return FindType(GetExpressionType(symbolTable, binary.Left), GetExpressionType(symbolTable, binary.Right), binary.BinaryOperatorType); } else if (expression is Literal) { Literal literal = expression as Literal; if (literal.LiteralType == LiteralType.Boolean) return new Type(PrimitiveType.Boolean); if (literal.LiteralType == LiteralType.Character) return new Type(PrimitiveType.Character); if (literal.LiteralType == LiteralType.Integer) return new Type(PrimitiveType.Integer); if (literal.LiteralType == LiteralType.Real) return new Type(PrimitiveType.Real); if (literal.LiteralType == LiteralType.String) return new Type(PrimitiveType.Void); } else if (expression is Name) { return ((Variable)symbolTable.Find(((Name)expression).Value, SymbolType.Variable).SyntaxObject).Type; } else if (expression is Call) { return ((Call)expression).Type; } return null; }