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 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; }
//REDNER variable or it's value private object v(AbstractEnvironment env, string vname) { if (env.IsDynamic(vname)) return vname; else return rc(env.GetValue(vname)); }
//Reduce RIGHT part of il_expression public object AbstactReduce(string leftVariable, AbstractEnvironment state, Dictionary<string, VariableType> localTypeScope) { if (Type == ILExpressionType.Const) { if (Const is string) { var s = (string)Const; var a = new object[s.Length]; for (int i = 0; i < s.Length; ++i) { a[i] = (int)s[i]; } return a; } return Const; } //Only variable else if (Type == ILExpressionType.VariableAccess) { if (state.IsDynamic(Const.ToString())) return Const.ToString(); else return state.GetValue(Const.ToString()); } else if (Type == ILExpressionType.Alloc) { bool isDynamicLeftPart = state.IsDynamic(leftVariable); if (isDynamicLeftPart || state.IsDynamic(LeftNode.Const.ToString())) { return "new " + localTypeScope[leftVariable].NestedType.ToCompileableString() + "[" + v(state, LeftNode.Const.ToString()) + "]"; } else { int arraySize = (int)state.GetValue(LeftNode.Const.ToString()); var a = new object[arraySize]; object defElem = null; if (localTypeScope[leftVariable].NestedType.TypeEnum == VariableTypeEnum.Integer) { defElem = 0; } if (localTypeScope[leftVariable].NestedType.TypeEnum == VariableTypeEnum.Bool) { defElem = false; } for (int i = 0; i < arraySize; ++i) { a[i] = defElem; } return a; } } else if (Type == ILExpressionType.FunctionCall) { return this; } //Binary expression & unary else { object r = Eval(state); if (r == Dynamic.Value) return GetOp(LeftNode.Const.ToString(), (RightNode != null) ? RightNode.Const.ToString() : "", Type, state); else return r; } }
public object Eval(AbstractEnvironment state) { #region +, -, *, /, mod, pow if (Type == ILExpressionType.Plus) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left + (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Minus) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left - (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Mul) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left * (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Div) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left / (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Mod) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left % (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Pow) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return L1Runtime.L1Runtime.Deg((int)left, (int)right); else return Dynamic.Value; } #endregion #region [] if (Type == ILExpressionType.ArrayAccess) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return ((Array)left).GetValue((int)right); else return Dynamic.Value; } #endregion #region >, >=, <, <=, =, <> if (Type == ILExpressionType.Gr) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left > (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Greq) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left >= (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Le) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left < (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Leeq) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left <= (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.Eq) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left == (int)right; else return Dynamic.Value; } if (Type == ILExpressionType.NotEq) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (int)left != (int)right; else return Dynamic.Value; } #endregion #region Uminus, Unot if (Type == ILExpressionType.Uminus) { object left = LeftNode.Eval(state); if (left != Dynamic.Value) return - (int)left; else return Dynamic.Value; } if (Type == ILExpressionType.Unot) { object left = LeftNode.Eval(state); if (left != Dynamic.Value) return !(bool)left; else return Dynamic.Value; } #endregion #region And, Or, Xor if (Type == ILExpressionType.And) { throw new InvalidOperationException("And operator is not allowed in IL!"); } if (Type == ILExpressionType.Or) { throw new InvalidOperationException("Or operator is not allowed in IL!"); } if (Type == ILExpressionType.Xor) { object left = LeftNode.Eval(state); object right = RightNode.Eval(state); if (left != Dynamic.Value && right != Dynamic.Value) return (bool)left ^ (bool)right; else return Dynamic.Value; } #endregion #region Alloc, ArrayLength, VariableAccess, Const if (Type == ILExpressionType.Alloc) { object left = LeftNode.Eval(state); if (left != Dynamic.Value) { int size = (int)left; object[] r = new object[size]; if (OriginalType.NestedType == VariableType.IntType) { for (int i = 0; i < size; ++i) { r[i] = 0; } } if (OriginalType.NestedType == VariableType.BoolType) { for (int i = 0; i < size; ++i) { r[i] = false; } } return r; } else return Dynamic.Value; } if (Type == ILExpressionType.ArrayLength) { object left = LeftNode.Eval(state); if (left != Dynamic.Value) return ((Array)left).GetLength(0); else return Dynamic.Value; } if (Type == ILExpressionType.VariableAccess) { return state.GetValue((string)Const); } if (Type == ILExpressionType.Const) { if (Const is string) { var s = (string)Const; var a = new object[s.Length]; for (int i = 0; i < s.Length; ++i) { a[i] = (int)s[i]; } return a; } return Const; } #endregion #region Assign if (Type == ILExpressionType.Assign) { object right = RightNode.Eval(state); if (LeftNode.Type == ILExpressionType.VariableAccess) { state.SetValue((string)LeftNode.Const, right); return right; } else if (LeftNode.Type == ILExpressionType.ArrayAccess) { object array = LeftNode.LeftNode.Eval(state); object index = LeftNode.RightNode.Eval(state); if (array == Dynamic.Value) { return right; } else { if (index == Dynamic.Value) { //Set whole array as Dynamic state.SetArrayAsDynamic(array); } else { ((Array)array).SetValue(right, (int)index); } return right; } } else { throw new InvalidOperationException("Bad assign construction!"); } } #endregion #region FunctionCall if (Type == ILExpressionType.FunctionCall) { string functionName = (string)Const; var args = new List<object>(); bool isDynamic = false; foreach (ILExpression expr in VAList) { object arg = expr.Eval(state); args.Add(arg); if (arg == Dynamic.Value) isDynamic = true; } if (isDynamic) return Dynamic.Value; else return Function.Call(args.ToArray());; } #endregion throw new InvalidOperationException("Bad interpreter error! =("); }