Ejemplo n.º 1
0
        /// <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));
        }
Ejemplo n.º 2
0
        /// <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));
        }