예제 #1
0
 public ExprDotForgeEnumMethodEval(
     ExprDotForgeEnumMethodBase forge,
     EnumEval enumEval,
     int enumEvalNumRequiredEvents)
 {
     this.forge = forge;
     this.enumEval = enumEval;
     this.enumEvalNumRequiredEvents = enumEvalNumRequiredEvents;
 }
예제 #2
0
        public static CodegenExpression Codegen(
            ExprDotForgeEnumMethodBase forge,
            CodegenExpression inner,
            Type innerType,
            CodegenMethodScope codegenMethodScope,
            ExprForgeCodegenSymbol exprSymbol,
            CodegenClassScope codegenClassScope)
        {
            var returnType = EPTypeHelper.GetCodegenReturnType(forge.TypeInfo);
            var methodNode = codegenMethodScope
                .MakeChild(returnType, typeof(ExprDotForgeEnumMethodEval), codegenClassScope)
                .AddParam(innerType, "param");

            methodNode.Block.DebugStack();

            var refEPS = exprSymbol.GetAddEPS(methodNode);
            var refIsNewData = exprSymbol.GetAddIsNewData(methodNode);
            var refExprEvalCtx = exprSymbol.GetAddExprEvalCtx(methodNode);

            var forgeMember = codegenClassScope.AddDefaultFieldUnshared(
                true, typeof(object), NewInstance(typeof(object)));
            var block = methodNode.Block;

            //block.Debug("param: {0}", ExprDotMethod(Ref("param"), "RenderAny"));

            if (innerType == typeof(EventBean)) {
                block.DeclareVar<FlexCollection>("coll", FlexEvent(Ref("param")));
            }
            else if (innerType == typeof(object[])) {
                block.DeclareVar<FlexCollection>("coll", FlexWrap(Ref("param")));
            }
            else if (innerType.IsGenericCollection()) {
                block.DeclareVar(innerType, "coll", Ref("param"));
            }
            else {
                throw new IllegalStateException("invalid type presented for unwrapping");
            }

            block.DeclareVar<ExpressionResultCacheForEnumerationMethod>(
                "cache",
                ExprDotMethodChain(refExprEvalCtx)
                    .Get("ExpressionResultCacheService")
                    .Get("AllocateEnumerationMethod"));
            
            var premade = new EnumForgeCodegenParams(
                Ref("eventsLambda"),
                Ref("coll"),
                innerType,
                refIsNewData,
                refExprEvalCtx);
            
            if (forge.IsCache) {
                block
                    .DeclareVar<ExpressionResultCacheEntryLongArrayAndObj>(
                        "cacheValue",
                        ExprDotMethod(Ref("cache"), "GetEnumerationMethodLastValue", forgeMember))
                    .IfCondition(NotEqualsNull(Ref("cacheValue")))
                    .BlockReturn(Cast(returnType, ExprDotName(Ref("cacheValue"), "Result")))
                    .IfRefNullReturnNull("coll")
                    .DeclareVar<EventBean[]>(
                        "eventsLambda",
                        StaticMethod(
                            typeof(ExprDotForgeEnumMethodEval),
                            "AllocateCopyEventLambda",
                            refEPS,
                            Constant(forge.EnumEvalNumRequiredEvents)))
                    .DeclareVar(
                        EPTypeHelper.GetCodegenReturnType(forge.TypeInfo),
                        "result",
                        forge.EnumForge.Codegen(premade, methodNode, codegenClassScope))
                    .Expression(
                        ExprDotMethod(Ref("cache"), "SaveEnumerationMethodLastValue", forgeMember, Ref("result")))
                    .MethodReturn(Ref("result"));
            }
            else {
                var contextNumberMember = codegenClassScope.AddDefaultFieldUnshared(
                    true,
                    typeof(AtomicLong),
                    NewInstance(typeof(AtomicLong)));

                var returnInvocation = forge.EnumForge.Codegen(premade, methodNode, codegenClassScope);
                
                block
                    .DeclareVar<long>("contextNumber", ExprDotMethod(contextNumberMember, "GetAndIncrement"))
                    .TryCatch()
                    .Expression(ExprDotMethod(Ref("cache"), "PushContext", Ref("contextNumber")))
                    .IfRefNullReturnNull("coll")
                    .DeclareVar<EventBean[]>(
                        "eventsLambda",
                        StaticMethod(
                            typeof(ExprDotForgeEnumMethodEval),
                            "AllocateCopyEventLambda",
                            refEPS,
                            Constant(forge.EnumEvalNumRequiredEvents)))
                    .TryReturn(CodegenLegoCast.CastSafeFromObjectType(returnType, returnInvocation))
                    .TryFinally()
                    .Expression(ExprDotMethod(Ref("cache"), "PopContext"))
                    .BlockEnd()
                    .MethodEnd();
            }

            return LocalMethod(methodNode, inner);
        }