private void Inline([CanBeNull] List <Statement> tmp) { var statements = tmp ?? new List <Statement>(); // FEATURE #44 if (Receiver is LambdaExpression lambdaExpression) { if (lambdaExpression.Recur) { return; } var statementList = lambdaExpression.OptimizedStatementList; var s = statementList?.Statements.ToList() ?? lambdaExpression.Body.Statements.ToList(); var len = ArgsList.Count; // len = lambdaExpression.ParameterList.Count; // should equal for (var i = 0; i < len; i++) { var decl = lambdaExpression.ParameterList[i]; decl.Mutability = true; decl.Expression = ArgsList[i]; // decl.Type = ArgsList[i].GetExpressionType(); statements.Add(decl); } Expression ret = null; for (var i = s.Count - 1; i >= 0; i--) { if (s[i] is ReturnStatement returnStatement) { ret = returnStatement.Expression; s.RemoveAt(i); break; } } ret = ret ?? new NullExpression(MetaData); if (!(ret is AtomicExpression)) { var varName = $"retTmp{(ulong) ret.GetHashCode()}"; var expr = new VariableDeclaration(MetaData, varName, ret, type: ret.GetExpressionType()); s.Add(expr); var variableExpression = new VariableExpression(MetaData, varName) { Declaration = expr }; ret = variableExpression; } statements.AddRange(s); ConvertedResult = new ExpressionConvertedResult(statements, ret); } else { ConvertedResult = new ExpressionConvertedResult(statements, this); } }
public override void SurroundWith(Environment environment) { base.SurroundWith(environment); foreach (var expression in ArgsList) { expression.SurroundWith(environment); } Receiver.SurroundWith(Env); // FEATURE #33 if (Receiver is VariableExpression receiver) { var argsTypes = (from i in ArgsList select i.GetExpressionType()) .ToList(); var receiverDeclaration = Env.FindDeclarationSatisfies(declaration => string.Equals(declaration.Name, receiver.Name, Ordinal) && ((declaration is VariableDeclaration variableDeclaration && variableDeclaration.Type is LambdaType lambdaType && lambdaType.ParamsList.Count == ArgsList.Count && lambdaType.ParamsList.SequenceEqual(argsTypes)) || (declaration is ExternDeclaration externDeclaration && externDeclaration.Type is LambdaType lambdaType2 && lambdaType2.ParamsList.Count == ArgsList.Count && lambdaType2.ParamsList.SequenceEqual(argsTypes)))); if (null != receiverDeclaration) { // receiverDeclaration is obviously a variable declaraion / extern declaration // because it's one of the filter condition receiver.Declaration = receiverDeclaration; } else { Errors.Add($"{MetaData.GetErrorHeader()}unresolved reference: \"{receiver.Name}\""); } } LambdaType hisType; try { hisType = Receiver.GetExpressionType() as LambdaType; } catch (CompilerException) { if (Receiver is VariableExpression variable && string.Equals(variable.Name, "recur", Ordinal)) { throw new CompilerException( $"{MetaData.GetErrorHeader()}please specify lamdba return type when using `recur`"); } throw; } if (null != hisType) { _type = hisType.RetType; // FEATURE #32 for (var i = 0; i < ArgsList.Count; i++) { if (!Equals(ArgsList[i].GetExpressionType(), hisType.ParamsList[i])) { Errors.Add( $"{MetaData.GetErrorHeader()}type mismatch: expected {hisType.ParamsList[i]}, " + $"found {ArgsList[i].GetExpressionType()}"); } } } else { Errors.Add( $"{MetaData.GetErrorHeader()}the function call receiver shoule be a function," + $" not {Receiver.GetExpressionType()}."); } var tmp = Split(); // if keepall, don't inline anything if (Pragma.KeepAll) { if (null != tmp) { ConvertedResult = new ExpressionConvertedResult(tmp, this); } return; } Inline(tmp); }