internal void Append(IExpression instruction) { if (this.Evaluation != null) { throw new Exception("Internal error"); } this.instructions.Add(instruction); instruction.AttachTo(this); }
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); } }
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); }
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); }