private EvaluationResult EvaluateAmbientProperty(Context context, ModuleLiteral env, CallableValue property) { context.SetPropertyProvenance(env.Path, Location); try { using (var frame = EvaluationStackFrame.Empty()) { return(property.Apply(context, frame)); } } catch (EvaluationException e) { e.ReportError(context.Errors, env, Location, expression: this, context: context); } catch (OperationCanceledException) { return(EvaluationResult.Canceled); } catch (Exception exception) { context.Errors.ReportUnexpectedAmbientException(env, exception, Location); throw; } finally { context.UnsetPropertyProvenance(); } return(EvaluationResult.Error); }
private async Task <object> EvaluateResolverCallback(Context context, QualifierId qualifier, FilePosition filePosition, ResolvedEntry resolvedEntry) { var qualifierValue = QualifierValue.Create(qualifier, context.QualifierValueCache, context.FrontEndContext.QualifierTable, context.StringTable); var env = InstantiateFileModuleLiteral(context.ModuleRegistry, qualifierValue); using (var args = EvaluationStackFrame.Empty()) { return(await resolvedEntry.ResolverCallback(context, env, args)); } }
private EvaluationResult EvaluateWithNewNamedContextAndTemplate(ImmutableContextBase context, ref MutableContextFactory factory) { using (var frame = EvaluationStackFrame.Empty()) { return(Evaluate( context: context, env: factory.Module, args: frame, factory: ref factory)); } }
internal EvaluationStackFrame GetArgsForFrame(int frameIndex) { var entry = GetStackEntryForFrame(frameIndex); if (entry == null) { return(EvaluationStackFrame.Empty()); } return(entry.DebugInfo.Frame); }
/// <summary> /// Evaluates this thunk in a new named context /// </summary> /// <remarks> /// V2-specific. /// </remarks> public EvaluationResult EvaluateWithNewNamedContext(Context context, ModuleLiteral module, FullSymbol contextName, LineInfo location) { Contract.Assert(CapturedTemplateReference != null); // We evaluate the captured template that was captured for this thunk in the same way (context and module) the thunk will be using (var frame = EvaluationStackFrame.Empty()) { var templateValue = CapturedTemplateReference.Eval(context, module, frame); if (templateValue.IsErrorValue) { return(EvaluationResult.Error); } var factory = new MutableContextFactory(this, contextName, module, templateValue.Value, location); return(EvaluateWithNewNamedContextAndTemplate(context, ref factory)); } }
/// <summary> /// Evaluates given <paramref name="binding"/> that corresponds to field <paramref name="name"/> /// (<seealso cref="GetOrEvalField(Context, SymbolAtom, bool, ModuleLiteral, LineInfo)"/>) /// </summary> public EvaluationResult GetOrEvalFieldBinding(Context context, SymbolAtom name, ModuleBinding binding, LineInfo callingLocation) { object o = binding.Body; if (o is Thunk thunk) { return(GetOrEvalFieldBindingThunk(context, name, binding, thunk)); } if (o is Expression expr) { using (var frame = EvaluationStackFrame.Empty()) { return(expr.Eval(context, this, frame)); } } return(EvaluationResult.Create(o)); }
private ObjectInfo CallableValueInfo(EvaluationContext context, CallableValue cv) { if (cv.IsProperty) { return(GetObjectInfo(context, cv.Apply(context, EvaluationStackFrame.Empty()))); } var captures = EvaluationStackFrame.Empty(); var @null = UndefinedValue.Instance; Func <object> func = CreateFunc(); return(func != null ? FuncObjInfo(func, RenderCallableSignature(cv.CallableMember)) : new ObjectInfo("function(" + RenderCallableSignature(cv.CallableMember) + ")")); // Local functions Func <object> CreateFunc() { var undefined = EvaluationResult.Undefined; switch (cv.CallableMember.Kind) { case SyntaxKind.Function0: return(() => cv.Apply(context, captures).Value); case SyntaxKind.Function1 when cv.CallableMember.MinArity == 0: return(() => cv.Apply(context, undefined, captures).Value); case SyntaxKind.Function2 when cv.CallableMember.MinArity == 0: return(() => cv.Apply(context, undefined, undefined, captures).Value); case SyntaxKind.FunctionN when cv.CallableMember.MinArity == 0: return(() => cv.Apply(context, BuildXL.Utilities.Collections.CollectionUtilities.EmptyArray <EvaluationResult>(), captures).Value); } return(null); } }
/// <summary> /// Evaluates a resolved entry that is not a Thunk /// </summary> internal EvaluationResult EvaluateNonThunkedResolvedSymbol(Context context, ModuleLiteral module, ResolvedEntry resolvedEntry) { Contract.Assert(resolvedEntry.Thunk == null); if (resolvedEntry.ConstantExpression != null) { return(EvaluationResult.Create(resolvedEntry.ConstantExpression.Value)); } using (var empty = EvaluationStackFrame.Empty()) { if (resolvedEntry.Expression != null) { if (resolvedEntry.Expression is TypeOrNamespaceModuleLiteral namespaceExpression) { // If the resolved entry already evaluated to a namespace and the namespace // is already qualified, then there is no reason for instantiating it twice. Just reusing it. if (namespaceExpression.Qualifier.IsQualified()) { return(EvaluationResult.Create(namespaceExpression)); } return(EvaluationResult.Create(namespaceExpression.Instantiate(context.ModuleRegistry, GetFileQualifier()))); } return(resolvedEntry.Expression.Eval(context, module, empty)); } if (resolvedEntry.ResolverCallback != null) { return(resolvedEntry.ResolverCallback(context, module, empty).GetAwaiter().GetResult()); } Contract.Assert(resolvedEntry.Function != null); return(resolvedEntry.Function.Eval(context, module, empty)); } }
/// <inheritdoc /> protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame) { // There is some code duplication between this type and the CoerceQualifierTypeExpression. // But there is not clear how to reuse this because steps are 'slightly' different. var moduleCandidate = ModuleReference.Eval(context, env, frame); if (moduleCandidate.IsErrorValue || moduleCandidate.IsUndefined) { return(moduleCandidate); } // The type checker should make sure that 'this expression' evaluates to a module literal. var module = moduleCandidate.Value as ModuleLiteral; Contract.Assert( module != null, I($"The left hand-side of a withQualifier expression should evaluates to 'TypeOrNamespaceModuleLiteral' but got '{moduleCandidate.Value.GetType()}'")); Contract.Assert(module.CurrentFileModule != null, "module.CurrentFileModule != null"); // QualifierExpression can be an object literal or anything that ended up as an object literal. EvaluationResult objectQualifier; using (var emptyFrame = EvaluationStackFrame.Empty()) { objectQualifier = QualifierExpression.Eval(context, env, emptyFrame); } if (objectQualifier.IsErrorValue) { // Error has been reported. return(EvaluationResult.Error); } var qualifierLiteral = objectQualifier.Value as ObjectLiteral; Contract.Assert( qualifierLiteral != null, I($"The right hand-side of a withQualifier expression should evaluates to 'ObjectLiteral' but got '{objectQualifier.Value.GetType()}'")); if (!QualifierValue.TryCreate(context, env, qualifierLiteral, out QualifierValue qualifierValue, qualifierLiteral.Location)) { // Error has been reported. return(EvaluationResult.Error); } // Coercing qualifier with a given value if ( !QualifierUtilities.CoerceQualifierValueForV2( context, qualifierValue, SourceQualifierSpaceId, TargetQualifierSpaceId, referencingLocation: Location.AsUniversalLocation(env, context), referencedLocation: module.CurrentFileModule.Location.AsUniversalLocation(module.CurrentFileModule, context), coercedQualifierValue: out QualifierValue coercedQualifierValue)) { // Error has been reported return(EvaluationResult.Error); } var result = module.Instantiate(context.ModuleRegistry, coercedQualifierValue); return(EvaluationResult.Create(result)); }
private ObjectLiteral BuildExecuteOutputs(Context context, ModuleLiteral env, ProcessOutputs processOutputs, bool isService) { var entry = context.TopStack; using (var empty = EvaluationStackFrame.Empty()) { var getOutputFile = new Closure( env, FunctionLikeExpression.CreateAmbient(ExecuteResultGetOutputFile, m_getOutputFileSignature, GetOutputFile, m_getOutputFileStatistic), frame: empty); var getOutputDirectory = new Closure( env, FunctionLikeExpression.CreateAmbient(ExecuteResultGetOutputDirectory, m_getOutputDirectorySignature, GetOutputDirectory, m_getOutputDirectoryStatistic), frame: empty); var getOutputFiles = new Closure( env, FunctionLikeExpression.CreateAmbient(ExecuteResultGetOutputFiles, m_getOutputFilesSignature, GetOutputFiles, m_getOutputFilesStatistic), frame: empty); var getRequiredOutputFiles = new Closure( env, FunctionLikeExpression.CreateAmbient(ExecuteResultGetRequiredOutputFiles, m_getRequiredOutputFilesSignature, GetRequiredOutputFiles, m_getRequiredOutputFilesStatistic), frame: empty); var bindings = new List <Binding>(isService ? 6 : 5) { new Binding(ExecuteResultGetOutputFile, getOutputFile, location: default), new Binding(ExecuteResultGetOutputDirectory, getOutputDirectory, location: default), new Binding(ExecuteResultGetOutputFiles, getOutputFiles, location: default), new Binding(ExecuteResultGetRequiredOutputFiles, getRequiredOutputFiles, location: default), new Binding(ExecuteResultProcessOutputs, new EvaluationResult(processOutputs), location: default), }; if (isService) { bindings.Add(new Binding(CreateServiceResultServiceId, processOutputs.ProcessPipId, location: default)); } return(ObjectLiteral.Create(bindings, entry.InvocationLocation, entry.Path)); } // Local functions EvaluationResult GetOutputFile(Context contextArg, ModuleLiteral envArg, EvaluationStackFrame args) { var outputPath = Args.AsPathOrUndefined(args, 0, false); if (outputPath.IsValid && processOutputs.TryGetOutputFile(outputPath, out var file)) { return(EvaluationResult.Create(file)); } return(EvaluationResult.Undefined); } EvaluationResult GetOutputDirectory(Context contextArg, ModuleLiteral envArg, EvaluationStackFrame args) { var outputDir = Args.AsDirectory(args, 0); if (outputDir.IsValid && processOutputs.TryGetOutputDirectory(outputDir.Path, out var output)) { return(EvaluationResult.Create(output)); } return(EvaluationResult.Undefined); } EvaluationResult GetOutputFiles(Context contextArg, ModuleLiteral envArg, EvaluationStackFrame args) { var outputFiles = processOutputs.GetOutputFiles().Select(f => EvaluationResult.Create(f)).ToArray(); return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(outputFiles, entry.InvocationLocation, entry.Path))); } EvaluationResult GetRequiredOutputFiles(Context contextArg, ModuleLiteral envArg, EvaluationStackFrame args) { var outputFiles = processOutputs.GetRequiredOutputFiles().Select(f => EvaluationResult.Create(f)).ToArray(); return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(outputFiles, entry.InvocationLocation, entry.Path))); } }
/// <inheritdoc /> protected override EvaluationResult DoEval(Context context, ModuleLiteral env, EvaluationStackFrame frame) { // There is some code duplication between this type and the CoerceQualifierTypeExpression. // But there is not clear how to reuse this because steps are 'slightly' different. var moduleCandidate = ModuleReference.Eval(context, env, frame); if (moduleCandidate.IsErrorValue || moduleCandidate.IsUndefined) { return(moduleCandidate); } // The type checker should make sure that 'this expression' evaluates to a module literal. var module = moduleCandidate.Value as ModuleLiteral; Contract.Assert( module != null, I($"The left hand-side of a withQualifier expression should evaluates to 'TypeOrNamespaceModuleLiteral' but got '{moduleCandidate.Value.GetType()}'")); Contract.Assert(module.CurrentFileModule != null, "module.CurrentFileModule != null"); var currentQualifier = env.CurrentFileModule.Qualifier.Qualifier; // QualifierExpression can be an object literal or anything that ended up as an object literal. EvaluationResult objectQualifier; using (var emptyFrame = EvaluationStackFrame.Empty()) { objectQualifier = QualifierExpression.Eval(context, env, emptyFrame); } if (objectQualifier.IsErrorValue) { // Error has been reported. return(EvaluationResult.Error); } var requestedQualifier = objectQualifier.Value as ObjectLiteral; Contract.Assert( requestedQualifier != null, I($"The right hand-side of a withQualifier expression should evaluates to 'ObjectLiteral' but got '{objectQualifier.Value.GetType()}'")); // TODO: This can be made more efficient by talking with the qualifier table directly // and maintaining a global map of qualifier id to object literal rather than have many copies of // object literal floating around, but that would be more changes than warranted at the moment // since withqualifier is not used that heavily at the moment, when this starts showing up on profiles // we should consider improving the logic here. var qualifierBindings = new Dictionary <StringId, Binding>(); foreach (var member in currentQualifier.Members) { qualifierBindings[member.Key] = new Binding(member.Key, member.Value, requestedQualifier.Location); } foreach (var member in requestedQualifier.Members) { if (member.Value.IsUndefined) { // setting a value to undefined implies explicitly removing they qualifier key. qualifierBindings.Remove(member.Key); } else { qualifierBindings[member.Key] = new Binding(member.Key, member.Value, requestedQualifier.Location); } } var qualifierToUse = ObjectLiteral.Create(qualifierBindings.Values.ToArray()); if (!QualifierValue.TryCreate(context, env, qualifierToUse, out QualifierValue qualifierValue, requestedQualifier.Location)) { // Error has been reported. return(EvaluationResult.Error); } // Coercing qualifier with a given value if ( !QualifierUtilities.CoerceQualifierValueForV2( context, qualifierValue, SourceQualifierSpaceId, TargetQualifierSpaceId, referencingLocation: Location.AsUniversalLocation(env, context), referencedLocation: module.CurrentFileModule.Location.AsUniversalLocation(module.CurrentFileModule, context), coercedQualifierValue: out QualifierValue coercedQualifierValue)) { // Error has been reported return(EvaluationResult.Error); } var result = module.Instantiate(context.ModuleRegistry, coercedQualifierValue); return(EvaluationResult.Create(result)); }