private static bool SpecializeExpression(ILFunction f, ILExpression expr, AbstractEnvironment env, StringBuilder source, List<FunctionCallContainer> calls) { if (expr.Type == ILExpressionType.Assign) { var left = expr.LeftNode; var right = expr.RightNode; if (left.Type == ILExpressionType.VariableAccess) { var varName = left.Const.ToString(); try { var rightRed = right.AbstactReduce(varName, env, f.LocalTypes); if (rightRed is ILExpression) { var fcall = rightRed as ILExpression; SpecializeFunctionCall(f, fcall, varName, source, env, calls); //source.Append("<<FUNCTION_CALL>>"); } else if (env.IsDynamic(varName)) { //source.Append(varName); source.Append(" := "); if (rightRed is string) { source.Append("\t"); source.Append(varName); source.Append(" := "); source.Append((string)rightRed); source.Append(";"); source.Append(System.Environment.NewLine); } else { source.Append("\t"); source.Append(varName); source.Append(" := "); source.Append(RenderConst(rightRed)); source.Append(";"); source.Append(System.Environment.NewLine); } } else { object val = rightRed; System.Diagnostics.Debug.Assert(val is string == false); System.Diagnostics.Debug.Assert(val is ILExpression == false); env.SetValue(varName, val); } } catch (NullReferenceException) { source.Append("\t__spec_raise_null_ref_exception();"); source.Append(System.Environment.NewLine); } catch (IndexOutOfRangeException) { source.Append("\t__spec_raise_index_out_of_range_exception();"); source.Append(System.Environment.NewLine); } } else { System.Diagnostics.Debug.Assert(left.Type == ILExpressionType.ArrayAccess); try { var arrayName = left.LeftNode.Const.ToString(); object index = null; if (env.IsDynamic(left.RightNode.Const.ToString())) { index = left.RightNode.Const.ToString(); } else { index = env.GetValue(left.RightNode.Const.ToString()); } object rightVar = null; if (env.IsDynamic(right.Const.ToString())) { rightVar = right.Const.ToString(); } else { rightVar = env.GetValue(right.Const.ToString()); } if (env.IsDynamic(arrayName)) { source.Append("\t"); source.Append(arrayName); source.Append("["); source.Append(index); source.Append("] := "); source.Append(rightVar); source.Append(";"); source.Append(System.Environment.NewLine); } else { object[] a = (object[])env.GetValue(arrayName); a[Convert.ToInt32(index)] = rightVar; } } catch (NullReferenceException) { source.Append("\t__spec_raise_null_ref_exception();"); source.Append(System.Environment.NewLine); } catch (IndexOutOfRangeException) { source.Append("\t__spec_raise_index_out_of_range_exception();"); source.Append(System.Environment.NewLine); } } } else if (expr.Type == ILExpressionType.FunctionCall) { source.Append("\t"); source.Append(expr.Const.ToString()); source.Append("("); for (int i = 0; i < expr.VAList.Count; ++i) { string p = null; if (env.IsDynamic(expr.VAList[i].Const.ToString())) { p = expr.VAList[i].Const.ToString(); } else { p = RenderConst(env.GetValue(expr.VAList[i].Const.ToString())); } source.Append(p); if (i != expr.VAList.Count - 1) source.Append(", "); } source.Append(");"); source.Append(System.Environment.NewLine); } return false; }
private static void SpecializeFunctionCall(ILFunction context, ILExpression fcall, string resultVar, StringBuilder source, AbstractEnvironment env, List<FunctionCallContainer> calls) { var f = fcall.Function; //Stdlib function if (f.EmbeddedBody != null) { if (f.CanBeCalculatedWithoutRun && !fcall.VAList.Any(pexpr => env.IsDynamic(pexpr.Const.ToString()))) { var args = fcall.VAList.Select(ilexpr => ilexpr.Eval(env)) .Select(o => (o is Int32) ? o : ( (o is Boolean) ? o : L1Runtime.L1Runtime.GetArrayFromObjectArray((object[])o))).ToArray(); var result = f.EmbeddedBody.Invoke(null, args); if (env.IsDynamic(resultVar)) { source.Append("\t"); source.Append(resultVar); source.Append(" := "); RenderConst(result); source.Append(");"); source.Append(System.Environment.NewLine); } else { if (result is L1Runtime.L1Array<int>) { var l1arr = result as L1Runtime.L1Array<int>; var a = new object[l1arr.GetLength()]; for (int i = 0; i < a.Length; ++i) { a[i] = l1arr.GetValue(i); } result = a; } env.SetValue(resultVar, result); } } else { source.Append("\t"); source.Append(resultVar); source.Append(" := "); source.Append(f.Name); source.Append("("); for (int i = 0; i < fcall.VAList.Count; ++i) { var p = fcall.VAList[i].Const.ToString(); if (env.IsDynamic(p)) { source.Append(p); } else { source.Append(RenderConst(env.GetValue(p))); } if (i != fcall.VAList.Count - 1) source.Append(", "); } source.Append(");"); source.Append(System.Environment.NewLine); } } else { if (f.CanBeCalculatedWithoutRun && !fcall.VAList.Any(pexpr => env.IsDynamic(pexpr.Const.ToString()))) { var args = fcall.VAList.Select(ilexpr => ilexpr.Eval(env)).ToArray(); var res = f.Call(args); if (env.IsDynamic(resultVar)) { source.Append("\t").Append(resultVar).Append(" := ").Append(RenderConst(res)).Append(";").AppendLine(); } else { env.SetValue(resultVar, res); } } else { var functionCallRef = new FunctionCallContainer { Function = fcall.Function, SourceFunction = context, ResultVariable = resultVar, Parameters = fcall.VAList.Select(ilexpr => env.IsDynamic(ilexpr.Const.ToString()) ? ilexpr.Const.ToString() : env.GetValue(ilexpr.Const.ToString())).ToList() }; calls.Add(functionCallRef); source.Append("\t").Append(functionCallRef.ToString()).AppendLine(); } } }
private static ILExpression _constructVariableAccess(string accessTo) { var ilExpr = new ILExpression(); ilExpr.Type = ILExpressionType.VariableAccess; ilExpr.Const = accessTo; return ilExpr; }
//Simple expr contains dynamic variables? private static bool m_simpleExprContainsDynamicVariables(ILExpression expr, AbstractEnvironment env) { if (expr.Type == ILExpressionType.FunctionCall) { if (expr.Function.EmbeddedBody != null && !expr.Function.CanBeCalculatedWithoutRun) return true; foreach (var arg in expr.VAList) { if (env.IsDynamic(arg.Const.ToString())) return true; } if (expr.Function.CanBeCalculatedWithoutRun == false) { return true; } } else if (expr.Type == ILExpressionType.VariableAccess) { if (env.IsDynamic(expr.Const.ToString())) return true; } else { if (expr.LeftNode != null) { if (env.IsDynamic(expr.LeftNode.Const.ToString())) return true; } if (expr.RightNode != null) { if (env.IsDynamic(expr.RightNode.Const.ToString())) return true; } } return false; }
private static ILExpression _constructAssignExpressionToConst(string assignTo, object constant) { var assingExpr = new ILExpression(); assingExpr.Type = ILExpressionType.Assign; assingExpr.LeftNode = new ILExpression(); assingExpr.LeftNode.Type = ILExpressionType.VariableAccess; assingExpr.LeftNode.Const = assignTo; assingExpr.RightNode = new ILExpression(); assingExpr.RightNode.Type = ILExpressionType.Const; assingExpr.RightNode.Const = constant; return assingExpr; }
private static ILExpression _constructBinaryExpressionFromVars(string leftOp, string rightOp, OperationType opType) { var ilExpr = new ILExpression(); //+, -, *, /, mod, pow, xor if (opType == OperationType.Plus) ilExpr.Type = ILExpressionType.Plus; if (opType == OperationType.Minus) ilExpr.Type = ILExpressionType.Minus; if (opType == OperationType.Mult) ilExpr.Type = ILExpressionType.Mul; if (opType == OperationType.Div) ilExpr.Type = ILExpressionType.Div; if (opType == OperationType.Mod) ilExpr.Type = ILExpressionType.Mod; if (opType == OperationType.Power) ilExpr.Type = ILExpressionType.Pow; if (opType == OperationType.Xor) ilExpr.Type = ILExpressionType.Xor; //>,>=,<,<=,=,<> if (opType == OperationType.Gr) ilExpr.Type = ILExpressionType.Gr; if (opType == OperationType.Greq) ilExpr.Type = ILExpressionType.Greq; if (opType == OperationType.Le) ilExpr.Type = ILExpressionType.Le; if (opType == OperationType.Leeq) ilExpr.Type = ILExpressionType.Leeq; if (opType == OperationType.Equals) ilExpr.Type = ILExpressionType.Eq; if (opType == OperationType.NotEquals) ilExpr.Type = ILExpressionType.NotEq; //ArrayAccess if (opType == OperationType.ArrayAccess) ilExpr.Type = ILExpressionType.ArrayAccess; var left = new ILExpression(); left.Type = ILExpressionType.VariableAccess; left.Const = leftOp; ilExpr.LeftNode = left; if (opType == OperationType.UMinus || opType == OperationType.UNot) { if (opType == OperationType.UMinus) ilExpr.Type = ILExpressionType.Uminus; if (opType == OperationType.UNot) ilExpr.Type = ILExpressionType.Unot; ilExpr.RightNode = null; } else { var right = new ILExpression(); right.Type = ILExpressionType.VariableAccess; right.Const = rightOp; ilExpr.RightNode = right; } return ilExpr; }
private static ILExpression _constructAssignExpression(ILExpression left, string assignWhat) { var assingExpr = new ILExpression(); assingExpr.Type = ILExpressionType.Assign; assingExpr.LeftNode = left; assingExpr.RightNode = new ILExpression(); assingExpr.RightNode.Type = ILExpressionType.VariableAccess; assingExpr.RightNode.Const = assignWhat; return assingExpr; }
private static List<ILExpression> FindAllFunctionCallsInExpr(ILExpression expression) { if (expression == null) return new List<ILExpression>(); if (expression.Type == ILExpressionType.FunctionCall) return new List<ILExpression>(new ILExpression[]{expression}); else { var r = FindAllFunctionCallsInExpr(expression.LeftNode); r.AddRange(FindAllFunctionCallsInExpr(expression.RightNode)); return r; } }
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 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()); }
public static void EmitVariableDefinition(VariableDefinitionList vdl, List<ILInstuction> il) { foreach (var vd in vdl.Definitions) { ILExpression initExpr = new ILExpression(); initExpr.Type = ILExpressionType.Assign; ILExpression varAccess = new ILExpression(); varAccess.Type = ILExpressionType.VariableAccess; varAccess.Const = vd.Name; initExpr.LeftNode = varAccess; if (vd.InitExpression != null) initExpr.RightNode = ConstructILExpression(vd.InitExpression); else { initExpr.RightNode = new ILExpression(); initExpr.RightNode.Type = ILExpressionType.Const; if (vd.VariableType.Equals(VariableType.IntType)) initExpr.RightNode.Const = 0; else if (vd.VariableType.Equals(VariableType.BoolType)) initExpr.RightNode.Const = false; else initExpr.RightNode.Const = null; } initExpr.Line = GetLabel(); il.Add(initExpr); } }