public CycleStatement() { Step = new Expression(); Step.IntValue = 1; Step.IsLeaf = true; Step.LeafType = ExpressionLeafType.Constant; Step.ResultType = VariableType.IntType; Step.OpType = OperationType.None; DeclareVariable = String.Empty; }
private static ILExpression ConstructILExpression(Expression expr) { if (expr.OpType == OperationType.And || expr.OpType == OperationType.Or) throw new InvalidOperationException("And an Or doesn't supported yet"); if (expr == null) return null; //Binary ops if (expr.IsLeaf == false) { ILExpression ilExpr = new ILExpression(); ilExpr.LeftNode = ConstructILExpression(expr.LeftNode); ilExpr.RightNode = ConstructILExpression(expr.RightNode); //+, -, *, /, mod, pow, xor if (expr.OpType == OperationType.Plus) ilExpr.Type = ILExpressionType.Plus; if (expr.OpType == OperationType.Minus) ilExpr.Type = ILExpressionType.Minus; if (expr.OpType == OperationType.Mult) ilExpr.Type = ILExpressionType.Mul; if (expr.OpType == OperationType.Div) ilExpr.Type = ILExpressionType.Div; if (expr.OpType == OperationType.Mod) ilExpr.Type = ILExpressionType.Mod; if (expr.OpType == OperationType.Power) ilExpr.Type = ILExpressionType.Pow; if (expr.OpType == OperationType.Xor) ilExpr.Type = ILExpressionType.Xor; //>,>=,<,<=,=,<> if (expr.OpType == OperationType.Gr) ilExpr.Type = ILExpressionType.Gr; if (expr.OpType == OperationType.Greq) ilExpr.Type = ILExpressionType.Greq; if (expr.OpType == OperationType.Le) ilExpr.Type = ILExpressionType.Leeq; if (expr.OpType == OperationType.Equals) ilExpr.Type = ILExpressionType.Eq; if (expr.OpType == OperationType.NotEquals) ilExpr.Type = ILExpressionType.NotEq; //UNot, Uminus if (expr.OpType == OperationType.UNot) ilExpr.Type = ILExpressionType.Unot; if (expr.OpType == OperationType.UMinus) ilExpr.Type = ILExpressionType.Uminus; //ArrayAccess if (expr.OpType == OperationType.ArrayAccess) ilExpr.Type = ILExpressionType.ArrayAccess; //Assign if (expr.OpType == OperationType.Assign) ilExpr.Type = ILExpressionType.Assign; return ilExpr; } else { ILExpression ilExpr = new ILExpression(); if (expr.LeafType == ExpressionLeafType.Constant) { ilExpr.Type = ILExpressionType.Const; if (expr.ResultType == VariableType.IntType) ilExpr.Const = expr.IntValue; else if (expr.ResultType == VariableType.BoolType) ilExpr.Const = expr.BoolValue; else ilExpr.Const = expr.Value; } else if (expr.LeafType == ExpressionLeafType.VariableAccess) { ilExpr.Type = ILExpressionType.VariableAccess; ilExpr.Const = expr.Value; } else if (expr.LeafType == ExpressionLeafType.FunctionCall) { ilExpr.Type = ILExpressionType.FunctionCall; ilExpr.Const = expr.Value; ilExpr.VAList = new List<ILExpression>(); foreach (var expression in expr.VAList) ilExpr.VAList.Add(ConstructILExpression(expression)); ilExpr.Function = FindFunction((string)ilExpr.Const, expr.VAList); } else { ilExpr.LeftNode = ConstructILExpression(expr.LeftNode); if (expr.LeafType == ExpressionLeafType.ArrayLength) ilExpr.Type = ILExpressionType.ArrayLength; if (expr.LeafType == ExpressionLeafType.ArrayAlloc) ilExpr.Type = ILExpressionType.Alloc; } return ilExpr; } }
public static void EmitExpression(Expression expr, List<ILInstuction> il) { ILExpression ilExpr = ConstructILExpression(expr); ilExpr.Line = GetLabel(); il.Add(ilExpr); }
public static string _EmitExpression(Expression expr, List<ILInstuction> il) { if (expr.IsLeaf) { //Variable access if (expr.LeafType == ExpressionLeafType.VariableAccess) { CurrentFunction.AddLocal(expr.Value.ToString(), expr.ResultType); return expr.Value.ToString(); } else if (expr.LeafType == ExpressionLeafType.Constant) { var resultVariable = GetVariableName(); object c; if (expr.ResultType == VariableType.IntType) c = expr.IntValue; else if (expr.ResultType == VariableType.BoolType) c = expr.BoolValue; else c = expr.Value; var ilExpr = _constructAssignExpressionToConst(resultVariable, c); il.Add(ilExpr); //ilExpr.OriginalType = expr.ResultType; CurrentFunction.AddLocal(resultVariable, expr.ResultType); return resultVariable; } else if (expr.LeafType == ExpressionLeafType.FunctionCall) { var ilExpr = new ILExpression(); ilExpr.Type = ILExpressionType.FunctionCall; ilExpr.Const = expr.Value; ilExpr.VAList = new List<ILExpression>(); foreach (var expression in expr.VAList) { var parameterVariable = _EmitExpression(expression, il); ilExpr.VAList.Add(_constructVariableAccess(parameterVariable)); } ilExpr.Function = FindFunction((string)ilExpr.Const, expr.VAList); //TODO: Add support for void functions; //ilExpr.OriginalType = expr.ResultType; if (ilExpr.Function.IsVoidReturn) { il.Add(ilExpr); return "void"; } else { var resultVariable = GetVariableName(); var resultExpr = _constructAssignExpression(resultVariable, ilExpr); il.Add(resultExpr); CurrentFunction.AddLocal(resultVariable, expr.ResultType); return resultVariable; } } else if (expr.LeafType == ExpressionLeafType.ArrayLength) { var leftOp = _EmitExpression(expr.LeftNode, il); var ilExpr = new ILExpression(); ilExpr.Type = ILExpressionType.ArrayLength; ilExpr.LeftNode = _constructVariableAccess(leftOp); var resultVariable = GetVariableName(); var resultExpr = _constructAssignExpression(resultVariable, ilExpr); il.Add(resultExpr); //resultExpr.OriginalType = expr.ResultType; CurrentFunction.AddLocal(resultVariable, expr.ResultType); return resultVariable; } else if (expr.LeafType == ExpressionLeafType.ArrayAlloc) { var leftOp = _EmitExpression(expr.LeftNode, il); var ilExpr = new ILExpression(); ilExpr.Type = ILExpressionType.Alloc; ilExpr.OriginalType = expr.ResultType; ilExpr.LeftNode = _constructVariableAccess(leftOp); var resultVariable = GetVariableName(); var resultExpr = _constructAssignExpression(resultVariable, ilExpr); il.Add(resultExpr); CurrentFunction.AddLocal(resultVariable, expr.ResultType); return resultVariable; } } else { if (expr.OpType == OperationType.Assign) { var rightOp = _EmitExpression(expr.RightNode, il); if (expr.LeftNode.LeafType == ExpressionLeafType.VariableAccess) { var leftOp = _EmitExpression(expr.LeftNode, il); il.Add(_constructAssignExpression(leftOp, rightOp)); CurrentFunction.AddLocal(leftOp, expr.ResultType); return leftOp; } else if (expr.LeftNode.OpType == OperationType.ArrayAccess) { // Emit ( E1[E2] = E3) = // Emit (E3) --> R // Emit (E1) --> A // Emit (E2) --> I // A[I] = R // return R; var arrLeftOp = _EmitExpression(expr.LeftNode.LeftNode, il); var arrIndexOp = _EmitExpression(expr.LeftNode.RightNode, il); var arrAccess = _constructBinaryExpressionFromVars(arrLeftOp, arrIndexOp, OperationType.ArrayAccess); var assignExpr = _constructAssignExpression(arrAccess, rightOp); il.Add(assignExpr); // assignExprstring resultVar = GetVariableName(); // var secondAssignExpr = _constructAssignExpression(resultVar, arrAccess); // il.Add(secondAssignExpr); return rightOp; } else { throw new InvalidOperationException("Bad assign construction!"); } } else if (expr.OpType == OperationType.And) { var leftOp = _EmitExpression(expr.LeftNode, il); CurrentFunction.AddLocal(leftOp, expr.ResultType); var branch = new ILBranch(); branch.Line = GetLabel(); branch.Condition = _constructVariableAccess(leftOp); var succ = new ILDummy(); succ.Line = GetLabel(); var fail = new ILDummy(); fail.Line = GetLabel(); var end = new ILDummy(); end.Line = GetLabel(); var gotoEnd = new ILGoto(end.Line); branch.SuccessJump = succ.Line; branch.FailJump = fail.Line; var resultVariable = GetVariableName(); il.Add(branch); il.Add(succ); var rightOp = _EmitExpression(expr.RightNode, il); CurrentFunction.AddLocal(rightOp, expr.ResultType); il.Add(_constructAssignExpression(resultVariable, rightOp)); il.Add(gotoEnd); il.Add(fail); il.Add(_constructAssignExpressionToConst(resultVariable, false)); il.Add(end); CurrentFunction.AddLocal(resultVariable, expr.ResultType); return resultVariable; } else if (expr.OpType == OperationType.Or) { var leftOp = _EmitExpression(expr.LeftNode, il); CurrentFunction.AddLocal(leftOp, expr.ResultType); var branch = new ILBranch(); branch.Line = GetLabel(); branch.Condition = _constructVariableAccess(leftOp); var succ = new ILDummy(); succ.Line = GetLabel(); var fail = new ILDummy(); fail.Line = GetLabel(); var end = new ILDummy(); end.Line = GetLabel(); var gotoEnd = new ILGoto(end.Line); branch.SuccessJump = succ.Line; branch.FailJump = fail.Line; var resultVariable = GetVariableName(); il.Add(branch); il.Add(fail); var rightOp = _EmitExpression(expr.RightNode, il); CurrentFunction.AddLocal(rightOp, expr.ResultType); il.Add(_constructAssignExpression(resultVariable, rightOp)); il.Add(gotoEnd); il.Add(succ); il.Add(_constructAssignExpressionToConst(resultVariable, true)); il.Add(end); CurrentFunction.AddLocal(resultVariable, expr.ResultType); return resultVariable; } else if (expr.OpType == OperationType.UNot || expr.OpType == OperationType.UMinus) { var op1 = _EmitExpression(expr.LeftNode, il); string varName= GetVariableName(); var ilExpr = _constructBinaryExpressionFromVars(op1, "", expr.OpType); il.Add(_constructAssignExpression(varName, ilExpr)); CurrentFunction.AddLocal(varName, expr.ResultType); return varName; } else { var op1 = _EmitExpression(expr.LeftNode, il); var op2 = _EmitExpression(expr.RightNode, il); string varName = GetVariableName(); var ilExpr = _constructBinaryExpressionFromVars(op1, op2, expr.OpType); il.Add(_constructAssignExpression(varName, ilExpr)); CurrentFunction.AddLocal(varName, expr.ResultType); return varName; } } throw new InvalidOperationException("Bad expression! " + expr.ToString()); }
private static string m_renderConst(Expression expr) { if (expr.ResultType == VariableType.IntType) { return Convert.ToString(expr.IntValue); } if (expr.ResultType == VariableType.BoolType) { if (expr.BoolValue) { return "T"; } else { return "F"; } } if (expr.ResultType == VariableType.NullType) { return "NULL"; } if (expr.ResultType.Equals(VariableType.StrType)) { return "\"" + expr.Value.ToString() + "\""; } //TODO: Add array constants return "<<CONST>>"; }
//Prior(type) > Prior(subExpression.type), return false is subExpression is LEAF private static bool m_greaterPriority(OperationType type, Expression subExpression) { if (subExpression.IsLeaf) { return false; } else { int priorType = m_getPriority(type); int priorExpr = m_getPriority(subExpression.OpType); return priorType > priorExpr; } }
private static string m_getPreparedString(OperationType opType, Expression expr) { if (m_greaterPriority(opType, expr)) return "(" + expr.ToString() + ")"; else return expr.ToString(); }
public static void EmitUnaryExpression(Expression expr, SymbolTable table, ILGenerator ilGen) { System.Diagnostics.Debug.Assert(expr.IsLeaf); #region Const if (expr.LeafType == ExpressionLeafType.Constant) { if (expr.ResultType.TypeEnum == VariableTypeEnum.Integer) { ilGen.Emit(OpCodes.Ldc_I4, expr.IntValue); } if (expr.ResultType.TypeEnum == VariableTypeEnum.Char) { ilGen.Emit(OpCodes.Ldc_I4, (int)expr.CharValue); } if (expr.ResultType.TypeEnum == VariableTypeEnum.Bool) { ilGen.Emit(OpCodes.Ldc_I4, Convert.ToInt32(expr.BoolValue)); } if (expr.ResultType.TypeEnum == VariableTypeEnum.Array) { string s = expr.Value.ToString(); ilGen.Emit(OpCodes.Ldstr, s); ilGen.Emit(OpCodes.Call, GetStrArr()); } System.Diagnostics.Debug.Assert(expr.ResultType.TypeEnum != VariableTypeEnum.NULL); //System.Diagnostics.Debug.Assert(expr.ResultType.TypeEnum != VariableTypeEnum.Array); } #endregion #region Variable if (expr.LeafType == ExpressionLeafType.VariableAccess) { Symbol symbol = table.FindSymbol(expr.Value.ToString()); if (symbol.IsParameter) { ilGen.Emit(OpCodes.Ldarg, symbol.ParameterIndex); } else { ilGen.Emit(OpCodes.Ldloc, symbol.LocalBuilder); } } #endregion #region FunctionCall if (expr.LeafType == ExpressionLeafType.FunctionCall) { List<VariableType> argumentTypes = new List<VariableType>(); foreach (Expression e in expr.VAList) { Type t = GetTypeForCompilerType(e.ResultType); EmitExpression(e, table, ilGen); argumentTypes.Add(e.ResultType); } MethodInfo mi = GetMethodForFunctionNameAndArgumentTypes( expr.Value.ToString(), argumentTypes.ToArray(), expr.Location); ilGen.Emit(OpCodes.Call, mi); if (mi.ReturnType == typeof(void)) wasVoidFuncCalled = true; } #endregion #region New array if (expr.LeafType == ExpressionLeafType.ArrayAlloc) { Type arrayType = GetTypeForCompilerType(expr.ResultType); EmitExpression(expr.LeftNode, table, ilGen); ilGen.Emit(OpCodes.Newobj, GetArrayCtor(arrayType)); } #endregion #region Array length if (expr.LeafType == ExpressionLeafType.ArrayLength) { Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType); EmitExpression(expr.LeftNode, table, ilGen); ilGen.Emit(OpCodes.Call, GetArrayLengthGetter(arrayType)); } #endregion }
public static void EmitBinaryExpression(Expression expr, SymbolTable table, ILGenerator ilGen) { System.Diagnostics.Debug.Assert(!expr.IsLeaf); #region + if (expr.OpType == OperationType.Plus) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Add); if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char || expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ilGen.Emit(OpCodes.Conv_U2); } } #endregion #region - if (expr.OpType == OperationType.Minus) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Sub); if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.Char) { ilGen.Emit(OpCodes.Conv_U2); } } #endregion #region **, *, /, mod if (expr.OpType == OperationType.Power) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Call, GetDeg()); } if (expr.OpType == OperationType.Mult) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Mul); } if (expr.OpType == OperationType.Div) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Div); } if (expr.OpType == OperationType.Mod) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Rem); } #endregion #region unary - if (expr.OpType == OperationType.UMinus) { EmitExpression(expr.LeftNode, table, ilGen); ilGen.Emit(OpCodes.Neg); } #endregion #region unary not if (expr.OpType == OperationType.UNot) { EmitExpression(expr.LeftNode, table, ilGen); //ilGen.Emit(OpCodes.Not); ilGen.Emit(OpCodes.Ldc_I4_0); ilGen.Emit(OpCodes.Ceq); } #endregion #region and, or, xor if (expr.OpType == OperationType.And) { Label label = ilGen.DefineLabel(); EmitExpression(expr.LeftNode, table, ilGen); ilGen.Emit(OpCodes.Dup); ilGen.Emit(OpCodes.Brfalse, label); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.And); ilGen.MarkLabel(label); } if (expr.OpType == OperationType.Or) { Label label = ilGen.DefineLabel(); EmitExpression(expr.LeftNode, table, ilGen); ilGen.Emit(OpCodes.Dup); ilGen.Emit(OpCodes.Brtrue, label); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Or); ilGen.MarkLabel(label); } if (expr.OpType == OperationType.Xor) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Xor); } #endregion #region <, >, <=, >= if (expr.OpType == OperationType.Le) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Clt); } if (expr.OpType == OperationType.Leeq) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Cgt); ilGen.Emit(OpCodes.Ldc_I4_0); ilGen.Emit(OpCodes.Ceq); } if (expr.OpType == OperationType.Gr) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Cgt); } if (expr.OpType == OperationType.Greq) { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Clt); ilGen.Emit(OpCodes.Ldc_I4_0); ilGen.Emit(OpCodes.Ceq); } #endregion #region =, <> if (expr.OpType == OperationType.Equals) { if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL && expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { ilGen.Emit(OpCodes.Ldc_I4_1); } else if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { Type arrayType = GetTypeForCompilerType(expr.RightNode.ResultType); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType)); ilGen.Emit(OpCodes.Ceq); } else if (expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType); EmitExpression(expr.LeftNode, table, ilGen); ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType)); ilGen.Emit(OpCodes.Ceq); } else { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Ceq); } } if (expr.OpType == OperationType.NotEquals) { if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL && expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { ilGen.Emit(OpCodes.Ldc_I4_1); } else if (expr.LeftNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { Type arrayType = GetTypeForCompilerType(expr.RightNode.ResultType); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType)); ilGen.Emit(OpCodes.Ceq); } else if (expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType); EmitExpression(expr.LeftNode, table, ilGen); ilGen.Emit(OpCodes.Call, GetArrayNullGetter(arrayType)); ilGen.Emit(OpCodes.Ceq); } else { EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Ceq); } ilGen.Emit(OpCodes.Ldc_I4_0); ilGen.Emit(OpCodes.Ceq); } #endregion #region [] if (expr.OpType == OperationType.ArrayAccess) { Type arrayType = GetTypeForCompilerType(expr.LeftNode.ResultType); EmitExpression(expr.LeftNode, table, ilGen); EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Call, GetArrayGetter(arrayType)); } #endregion #region Assign if (expr.OpType == OperationType.Assign) { if (expr.LeftNode.OpType == OperationType.ArrayAccess) { Type arrayType = GetTypeForCompilerType(expr.LeftNode.LeftNode.ResultType); //Array EmitExpression(expr.LeftNode.LeftNode, table, ilGen); //Index EmitExpression(expr.LeftNode.RightNode, table, ilGen); //Value EmitExpression(expr.RightNode, table, ilGen); //Setter call ilGen.Emit(OpCodes.Call, GetArraySetter(arrayType)); //Banditism: after setter call - there is specified value on the stack's top } else if (expr.LeftNode.LeafType == ExpressionLeafType.VariableAccess) { Symbol symbol = table.FindSymbol(expr.LeftNode.Value.ToString()); //Reight part if (expr.RightNode.ResultType.TypeEnum == VariableTypeEnum.NULL) { ilGen.Emit(OpCodes.Call, GetArrayNullGetter(symbol.Type)); ilGen.Emit(OpCodes.Dup); } else { EmitExpression(expr.RightNode, table, ilGen); ilGen.Emit(OpCodes.Dup); } //Setter for variable if (symbol.IsParameter) { ilGen.Emit(OpCodes.Starg, symbol.ParameterIndex); } else { ilGen.Emit(OpCodes.Stloc, symbol.LocalBuilder); } } else { System.Diagnostics.Debug.Fail("Bad compiler error: bad assign construction"); } } #endregion }
public static void EmitExpression(Expression expr, SymbolTable table, ILGenerator ilGen) { if (expr.IsLeaf) { EmitUnaryExpression(expr, table, ilGen); } else { EmitBinaryExpression(expr, table, ilGen); } }