Exemplo n.º 1
0
        internal void Append(IExpression instruction)
        {
            if (this.Evaluation != null)
            {
                throw new Exception("Internal error");
            }

            this.instructions.Add(instruction);
            instruction.AttachTo(this);
        }
Exemplo n.º 2
0
        public static void TrapClosure(this ILambdaTransfer node, ComputationContext ctx, ref IExpression source)
        {
            if (TrapLambdaClosure(node, ctx, ref source))
            {
                return;
            }

            if (source is NameReference name_ref && name_ref.Binding.Match.Instance.Target is FunctionDefinition func)
            {
                if (func.Name.Arity > 0 && !name_ref.TemplateArguments.Any())
                {
                    ctx.AddError(ErrorCode.SelectingAmbiguousTemplateFunction, name_ref);
                }
                IExpression this_obj = name_ref.GetContext(func);
                // example scenario
                // f = my_object.my_square
                // f(4)

                // so we have to grab "my_object", make closure around it, and then put it instead of "my_object.my_square"

                name_ref.DetachFrom(node);
                if (name_ref.Prefix != null)
                {
                    name_ref.Prefix.DetachFrom(name_ref);
                    name_ref.Prefix.DereferencedCount_LEGACY = 0; // we have to clear it because we will reuse it
                }
                TypeDefinition closure_type = buildTypeOfReference(ctx, name_ref, this_obj);
                node.AddClosure(closure_type);

                if (this_obj != null)
                {
                    source = ExpressionFactory.HeapConstructor(closure_type.InstanceOf.NameOf,
                                                               FunctionArgument.Create(name_ref.Prefix));
                }
                else
                {
                    source = ExpressionFactory.HeapConstructor(closure_type.InstanceOf.NameOf);
                }
                source.AttachTo(node);

                closure_type.Surfed(ctx);
                closure_type.Evaluated(ctx, EvaluationCall.AdHocCrossJump);

                closure_type.InvokeFunctions().First().MetaThisParameter.Evaluated(ctx, EvaluationCall.AdHocCrossJump);
                source.Evaluated(ctx, EvaluationCall.Nested);
            }
        }
Exemplo n.º 3
0
        public static bool TrapLambdaClosure(this ILambdaTransfer node, ComputationContext ctx, ref IExpression source)
        {
            if (!(source is FunctionDefinition lambda))
            {
                return(false);
            }

            // example scenario
            // f = (x) => x*x
            // f(4)

            // we already have tracked all the variables used inside lambda (which are declared outside, locals are OK),
            // so all we have to do it is to remove it and put into closure type

            if (!lambda.IsComputed)
            {
                throw new Exception("Internal error");
            }

            lambda.DetachFrom(node);
            TypeDefinition closure_type = buildTypeOfLambda(ctx, lambda, lambda.LambdaTrap.Fields);

            node.AddClosure(closure_type);

            source = ExpressionFactory.HeapConstructor(closure_type.InstanceOf.NameOf,
                                                       lambda.LambdaTrap.Fields.Select(it => FunctionArgument.Create(NameReference.Create(it.Name.Name))).ToArray());
            source.AttachTo(node);

            lambda.LambdaTrap = null;

            // we have to manually evaluate this expression, because it is child of current node, and child nodes
            // are evaluated before their parents
            closure_type.Surfed(ctx);
            closure_type.Evaluated(ctx, EvaluationCall.AdHocCrossJump);

            // todo: this is ugly -- we are breaking into details of separate type
            // since the function is already computed, it won't evaluate meta this parameter
            lambda.MetaThisParameter.Evaluated(ctx, EvaluationCall.AdHocCrossJump);
            source.Evaluated(ctx, EvaluationCall.Nested);

            return(true);
        }
Exemplo n.º 4
0
        public static bool DataTransfer(this IEvaluable @this, ComputationContext ctx, ref IExpression source,
                                        IEntityInstance targetTypeName, bool ignoreMutability = false)
        {
            if (source == null)
            {
                return(true);
            }

            IEntityInstance src_type = source.Evaluation.Components;

            TypeMatch match = src_type.MatchesTarget(ctx, targetTypeName,
                                                     TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: false)
                                                     .WithIgnoredMutability(ignoreMutability)
                                                     .AllowedLifetimeChecking(true));

            if (match.HasFlag(TypeMatch.Attachment))
            {
                match ^= TypeMatch.Attachment;
            }

            if (match == TypeMatch.No)
            {
                ctx.ErrorManager.AddError(ErrorCode.TypeMismatch, source);
                return(false);
            }
            else if (match == TypeMatch.Lifetime)
            {
                ctx.ErrorManager.AddError(ErrorCode.EscapingReference, source);
                return(false);
            }
            else if (match == TypeMatch.InConversion)
            {
                source.DetachFrom(@this);
                source = ExpressionFactory.StackConstructor((targetTypeName as EntityInstance).NameOf, FunctionArgument.Create(source));
                source.AttachTo(@this);
                TypeMatch m = source.Evaluated(ctx, EvaluationCall.AdHocCrossJump).MatchesTarget(ctx, targetTypeName, TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: false));
                if (m != TypeMatch.Same && m != TypeMatch.Substitute)
                {
                    throw new Exception("Internal error");
                }
            }
            else if (match.HasFlag(TypeMatch.ImplicitReference))
            {
                match ^= TypeMatch.ImplicitReference;
                if (match != TypeMatch.Substitute && match != TypeMatch.Same)
                {
                    throw new NotImplementedException();
                }

                source.DetachFrom(@this);
                source = AddressOf.CreateReference(source);
                source.AttachTo(@this);
                IEntityInstance source_eval = source.Evaluated(ctx, EvaluationCall.AdHocCrossJump);
                TypeMatch       m           = source_eval.MatchesTarget(ctx, targetTypeName, TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping,
                                                                                                                 allowSlicing: true));
                if (m != TypeMatch.Same && m != TypeMatch.Substitute)
                {
                    throw new Exception($"Internal error: matching result {m}");
                }
            }
            else if (match == TypeMatch.OutConversion)
            {
                source.DetachFrom(@this);
                source = FunctionCall.ConvCall(source, (targetTypeName as EntityInstance).NameOf);
                source.AttachTo(@this);
                TypeMatch m = source.Evaluated(ctx, EvaluationCall.AdHocCrossJump).MatchesTarget(ctx, targetTypeName, TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: false));
                if (m != TypeMatch.Same && m != TypeMatch.Substitute)
                {
                    throw new Exception("Internal error");
                }
            }
            else if (match.HasFlag(TypeMatch.AutoDereference))
            {
                source.DereferencedCount_LEGACY = match.Dereferences;
                @this.Cast <IExpression>().DereferencingCount = match.Dereferences;

                match ^= TypeMatch.AutoDereference;
                if (match != TypeMatch.Substitute && match != TypeMatch.Same)
                {
                    throw new NotImplementedException();
                }
            }
            else if (match != TypeMatch.Same && match != TypeMatch.Substitute)
            {
                throw new NotImplementedException();
            }

            return(true);
        }