Inheritance: clojure.lang.CljCompiler.Ast.Expr
        public Expression GenCode(RHC rhc, ObjExpr objx, GenContext context)
        {
            //if (context.Mode == CompilerMode.Immediate)
            if (objx.FnMode == FnMode.Light)
            {
                // This will emit a plain Keyword reference, rather than a callsite.
                InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target));
                return(ie.GenCode(rhc, objx, context));
            }
            else
            {
                // pseudo-code:
                //  ILookupThunk thunk = objclass.ThunkField(i)
                //  object target = ...code...
                //  object val = thunk.get(target)
                //  if ( val != thunk )
                //     return val
                //  else
                //     KeywordLookupSite site = objclass.SiteField(i)
                //     thunk = site.fault(target)
                //     objclass.ThunkField(i) = thunk
                //     val = thunk.get(target)
                //     return val

                ParameterExpression thunkParam  = Expression.Parameter(typeof(ILookupThunk), "thunk");
                ParameterExpression targetParam = Expression.Parameter(typeof(object), "target");
                ParameterExpression valParam    = Expression.Parameter(typeof(Object), "val");
                ParameterExpression siteParam   = Expression.Parameter(typeof(KeywordLookupSite), "site");


                Expression assignThunkFromField = Expression.Assign(thunkParam, Expression.Field(null, objx.ThunkField(_siteIndex)));
                Expression assignThunkFromSite  = Expression.Assign(thunkParam, Expression.Call(siteParam, Compiler.Method_ILookupSite_fault, targetParam));
                Expression assignFieldFromThunk = Expression.Assign(Expression.Field(null, objx.ThunkField(_siteIndex)), thunkParam);
                Expression assignTarget         = Expression.Assign(targetParam, _target.GenCode(RHC.Expression, objx, context));
                Expression assignVal            = Expression.Assign(valParam, Expression.Call(thunkParam, Compiler.Method_ILookupThunk_get, targetParam));
                Expression assignSite           = Expression.Assign(siteParam, Expression.Field(null, objx.KeywordLookupSiteField(_siteIndex)));


                Expression block =
                    Expression.Block(typeof(Object), new ParameterExpression[] { thunkParam, valParam, targetParam },
                                     assignThunkFromField,
                                     assignTarget,
                                     assignVal,
                                     Expression.IfThen(
                                         Expression.Equal(valParam, thunkParam),
                                         Expression.Block(typeof(Object), new ParameterExpression[] { siteParam },
                                                          assignSite,
                                                          assignThunkFromSite,
                                                          assignFieldFromThunk,
                                                          assignVal)),
                                     valParam);

                block = Compiler.MaybeAddDebugInfo(block, _spanMap, context.IsDebuggable);
                return(block);
            }
        }
        public Expression GenCode(RHC rhc, ObjExpr objx, GenContext context)
        {
            //if (context.Mode == CompilerMode.Immediate)
            if (objx.FnMode == FnMode.Light )
            {
                // This will emit a plain Keyword reference, rather than a callsite.
                InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target));
                return ie.GenCode(rhc, objx, context);
            }
            else
            {
                // pseudo-code:
                //  ILookupThunk thunk = objclass.ThunkField(i)
                //  object target = ...code...
                //  object val = thunk.get(target)
                //  if ( val != thunk )
                //     return val
                //  else
                //     KeywordLookupSite site = objclass.SiteField(i)
                //     thunk = site.fault(target)
                //     objclass.ThunkField(i) = thunk
                //     val = thunk.get(target)
                //     return val

                ParameterExpression thunkParam = Expression.Parameter(typeof(ILookupThunk), "thunk");
                ParameterExpression targetParam = Expression.Parameter(typeof(object), "target");
                ParameterExpression valParam = Expression.Parameter(typeof(Object), "val");
                ParameterExpression siteParam = Expression.Parameter(typeof(KeywordLookupSite), "site");

                Expression assignThunkFromField = Expression.Assign(thunkParam, Expression.Field(null, objx.ThunkField(_siteIndex)));
                Expression assignThunkFromSite = Expression.Assign(thunkParam, Expression.Call(siteParam, Compiler.Method_ILookupSite_fault, targetParam));
                Expression assignFieldFromThunk = Expression.Assign(Expression.Field(null, objx.ThunkField(_siteIndex)), thunkParam);
                Expression assignTarget = Expression.Assign(targetParam,_target.GenCode(RHC.Expression, objx, context));
                Expression assignVal = Expression.Assign(valParam, Expression.Call(thunkParam, Compiler.Method_ILookupThunk_get,targetParam));
                Expression assignSite = Expression.Assign(siteParam, Expression.Field(null, objx.KeywordLookupSiteField(_siteIndex)));

                Expression block =
                    Expression.Block(typeof(Object), new ParameterExpression[] { thunkParam, valParam, targetParam },
                        assignThunkFromField,
                        assignTarget,
                        assignVal,
                        Expression.IfThen(
                            Expression.Equal(valParam, thunkParam),
                            Expression.Block(typeof(Object), new ParameterExpression[] { siteParam },
                                assignSite,
                                assignThunkFromSite,
                                assignFieldFromThunk,
                                assignVal)),
                        valParam);

                block = Compiler.MaybeAddDebugInfo(block, _spanMap, context.IsDebuggable);
                return block;
            }
        }
示例#3
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            if (objx.FnMode == FnMode.Light)
            {
                // This will emit a plain Keyword reference, rather than a callsite.
                InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target));
                ie.Emit(rhc, objx, ilg);
            }
            else
            {
                Label endLabel = ilg.DefineLabel();
                Label faultLabel = ilg.DefineLabel();

                GenContext.EmitDebugInfo(ilg, _spanMap);

                LocalBuilder thunkLoc = ilg.DeclareLocal(typeof(ILookupThunk));
                LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object));
                LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(thunkLoc, "thunk");
                GenContext.SetLocalName(targetLoc, "target");
                GenContext.SetLocalName(resultLoc, "result");

                // TODO: Debug info

                // pseudo-code:
                //  ILookupThunk thunk = objclass.ThunkField(i)
                //  object target = ...code...
                //  object val = thunk.get(target)
                //  if ( val != thunk )
                //     return val
                //  else
                //     KeywordLookupSite site = objclass.SiteField(i)
                //     thunk = site.fault(target)
                //     objclass.ThunkField(i) = thunk
                //     val = thunk.get(target)
                //     return val

                ilg.EmitFieldGet(objx.ThunkField(_siteIndex));                     // thunk
                ilg.Emit(OpCodes.Stloc, thunkLoc);                                  //  (thunkLoc <= thunk)

                _target.Emit(RHC.Expression, objx, ilg);                         // target
                ilg.Emit(OpCodes.Stloc, targetLoc);                                  //   (targetLoc <= target)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, targetLoc);
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result
                ilg.Emit(OpCodes.Stloc, resultLoc);                                 //    (resultLoc <= result)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, resultLoc);
                ilg.Emit(OpCodes.Beq, faultLabel);

                ilg.Emit(OpCodes.Ldloc, resultLoc);                                  // result
                ilg.Emit(OpCodes.Br, endLabel);

                ilg.MarkLabel(faultLabel);
                ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex));           // site
                ilg.Emit(OpCodes.Ldloc, targetLoc);                                  // site, target
                ilg.EmitCall(Compiler.Method_ILookupSite_fault);                    // new-thunk
                ilg.Emit(OpCodes.Dup);                                              // new-thunk, new-thunk
                ilg.EmitFieldSet(objx.ThunkField(_siteIndex));                      // new-thunk

                ilg.Emit(OpCodes.Ldloc, targetLoc);                                 // new-thunk, target
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result

                ilg.MarkLabel(endLabel);                                           // result
                if (rhc == RHC.Statement)
                    ilg.Emit(OpCodes.Pop);
            }
        }
示例#4
0
        public Expression GenCode(RHC rhc, ObjExpr objx, GenContext context)
        {
            //if (context.Mode == CompilerMode.Immediate)
            if (objx.FnMode == FnMode.Light )
            {
                // This will emit a plain Keyword reference, rather than a callsite.
                InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target));
                return ie.GenCode(rhc, objx, context);
            }
            else
            {

                ParameterExpression thunkParam = Expression.Parameter(typeof(ILookupThunk), "thunk");
                Expression assignThunk = Expression.Assign(thunkParam, Expression.Field(null, objx.ThunkField(_siteIndex)));

                ParameterExpression targetParam = Expression.Parameter(typeof(object), "target");
                Expression assignTarget = Expression.Assign(targetParam,_target.GenCode(RHC.Expression, objx, context));

                ParameterExpression valParam = Expression.Parameter(typeof(Object), "val");
                Expression assignVal = Expression.Assign(valParam, Expression.Call(thunkParam, Compiler.Method_ILookupThunk_get,targetParam));

                ParameterExpression siteParam = Expression.Parameter(typeof(KeywordLookupSite), "site");
                Expression assignSite = Expression.Assign(siteParam, Expression.Field(null, objx.KeywordLookupSiteField(_siteIndex)));

                Expression block =
                    Expression.Block(typeof(Object), new ParameterExpression[] { thunkParam, valParam, targetParam },
                        assignThunk,
                        assignTarget,
                        assignVal,
                        Expression.Condition(
                            Expression.NotEqual(valParam, thunkParam),
                            valParam,
                            Expression.Block(typeof(Object), new ParameterExpression[] { siteParam },
                                assignSite,
                                Expression.Call(siteParam, Compiler.Method_ILookupSite_fault, targetParam, objx.ThisParam)),
                            typeof(object)));

                block = Compiler.MaybeAddDebugInfo(block, _spanMap);
                return block;
            }
        }
示例#5
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            if (objx.FnMode == FnMode.Light)
            {
                // This will emit a plain Keyword reference, rather than a callsite.
                InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target));
                ie.Emit(rhc, objx, ilg);
            }
            else
            {
                Label endLabel   = ilg.DefineLabel();
                Label faultLabel = ilg.DefineLabel();

                GenContext.EmitDebugInfo(ilg, _spanMap);

                LocalBuilder thunkLoc  = ilg.DeclareLocal(typeof(ILookupThunk));
                LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object));
                LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(thunkLoc, "thunk");
                GenContext.SetLocalName(targetLoc, "target");
                GenContext.SetLocalName(resultLoc, "result");

                // TODO: Debug info

                // pseudo-code:
                //  ILookupThunk thunk = objclass.ThunkField(i)
                //  object target = ...code...
                //  object val = thunk.get(target)
                //  if ( val != thunk )
                //     return val
                //  else
                //     KeywordLookupSite site = objclass.SiteField(i)
                //     thunk = site.fault(target)
                //     objclass.ThunkField(i) = thunk
                //     val = thunk.get(target)
                //     return val

                ilg.EmitFieldGet(objx.ThunkField(_siteIndex));                   // thunk
                ilg.Emit(OpCodes.Stloc, thunkLoc);                               //  (thunkLoc <= thunk)

                _target.Emit(RHC.Expression, objx, ilg);                         // target
                ilg.Emit(OpCodes.Stloc, targetLoc);                              //   (targetLoc <= target)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, targetLoc);
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result
                ilg.Emit(OpCodes.Stloc, resultLoc);                                //    (resultLoc <= result)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, resultLoc);
                ilg.Emit(OpCodes.Beq, faultLabel);

                ilg.Emit(OpCodes.Ldloc, resultLoc);                                  // result
                ilg.Emit(OpCodes.Br, endLabel);

                ilg.MarkLabel(faultLabel);
                ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex));         // site
                ilg.Emit(OpCodes.Ldloc, targetLoc);                                // site, target
                ilg.EmitCall(Compiler.Method_ILookupSite_fault);                   // new-thunk
                ilg.Emit(OpCodes.Dup);                                             // new-thunk, new-thunk
                ilg.EmitFieldSet(objx.ThunkField(_siteIndex));                     // new-thunk

                ilg.Emit(OpCodes.Ldloc, targetLoc);                                // new-thunk, target
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result

                ilg.MarkLabel(endLabel);                                           // result
                if (rhc == RHC.Statement)
                {
                    ilg.Emit(OpCodes.Pop);
                }
            }
        }