示例#1
0
        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);
            }
        }
示例#2
0
        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);
        }