示例#1
0
        private static Expression CoalesceInternal(CodeBlock currentBlock, Expression left, Expression right, MethodInfo isTrue, bool isReverse)
        {
            Contract.RequiresNotNull(currentBlock, "currentBlock");
            Contract.RequiresNotNull(left, "left");
            Contract.RequiresNotNull(right, "right");

            // A bit too strict, but on a safe side.
            Contract.Requires(left.Type == right.Type, "Expression types must match");

            Variable tmp = currentBlock.CreateTemporaryVariable(SymbolTable.StringToId("tmp_left"), left.Type);

            Expression condition;

            if (isTrue != null)
            {
                Contract.Requires(isTrue.ReturnType == typeof(bool), "isTrue", "Predicate must return bool.");
                ParameterInfo[] parameters = isTrue.GetParameters();
                Contract.Requires(parameters.Length == 1, "isTrue", "Predicate must take one parameter.");
                Contract.Requires(isTrue.IsStatic && isTrue.IsPublic, "isTrue", "Predicate must be public and static.");

                Type pt = parameters[0].ParameterType;
                Contract.Requires(TypeUtils.CanAssign(pt, left.Type), "left", "Incorrect left expression type");
                condition = Call(isTrue, Assign(tmp, left));
            }
            else
            {
                Contract.Requires(TypeUtils.CanCompareToNull(left.Type), "left", "Incorrect left expression type");
                condition = Equal(Assign(tmp, left), Null(left.Type));
            }

            Expression t, f;

            if (isReverse)
            {
                t = Read(tmp);
                f = right;
            }
            else
            {
                t = right;
                f = Read(tmp);
            }

            return(Condition(condition, t, f));
        }
示例#2
0
    protected internal static Expression GetAst(object args, CodeBlock cb, bool istailposition)
    {
      if (args is Annotation)
      {
        args = ((Annotation)args).stripped;
      }
      Cons c = args as Cons;
      if (c != null)
      {

        if (c.car is SymbolId)
        {
          SymbolId f = (SymbolId)c.car;

          Variable var = cb.Lookup(f);

          if (var != null && !assigns.ContainsKey(f))
          {
            var = null;
          }

          object m;

#if OPTIMIZATIONS

#if !BLAH
          CodeBlockExpression cbe;

          //// needs to do the same for overloads...
          if (SimpleGenerator.libraryglobals.TryGetValue(f, out cbe))
          {
            Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

            if (cbe.Block.ParameterCount < 9 && cbe.Block.ParameterCount == ppp.Length)
            {
              //inline here? we could for simple bodies, but we need to copy the entire structure
              if (!(cbe.Block.HasEnvironment || cbe.Block.IsClosure))
              {
                if (cbe.Block.Body is ReturnStatement)
                {
                  ReturnStatement rs = (ReturnStatement)cbe.Block.Body;

                  if (!ScriptDomainManager.Options.DebugMode && 
                    !ScriptDomainManager.Options.LightweightDebugging && 
                    !cb.IsGlobal && IsSimpleExpression(rs.Expression))
                  {
                    return InlineCall(cb, Ast.CodeBlockExpression(RewriteBody(cbe.Block), false, cbe.IsStronglyTyped), ppp);
                  }
                }
              }
              if (cbe.Block != cb.Parent && cbe.Block != cb) // do TCE later
              {
                return CallNormal(cbe, ppp);
              }
            }
          }

          // varargs
          if (SimpleGenerator.libraryglobalsX.TryGetValue(f, out cbe))
          {
            Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

            if (cbe.Block.ParameterCount < 9 && cbe.Block.ParameterCount - 1 <= ppp.Length)
            {
              //inline here?
              return CallVarArgs(cbe, ppp);
            }
          }

          // overloads
          CodeBlockDescriptor[] cbd;
          if (SimpleGenerator.libraryglobalsN.TryGetValue(f, out cbd))
          {
            Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

            foreach (CodeBlockDescriptor d in cbd)
            {
              if (d.codeblock.Block.ParameterCount < 9)
              {
                if (ppp.Length == d.arity || (d.varargs && ppp.Length > d.arity))
                {
                  if (d.varargs)
                  {
                    //inline here?
                    return CallVarArgs(d.codeblock, ppp);
                  }
                  else
                  {
                    //inline here?
                    //if (d.codeblock.Block != cb.Parent && d.codeblock.Block != cb) // do TCE later, not yet
                    {
                      return CallNormal(d.codeblock, ppp);
                    }
                  }
                }
              }
            }
          }
#endif

          //if (!ScriptDomainManager.Options.DebugMode)
          {

            if (f == SymbolTable.StringToId("call-with-values"))
            {
              Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);
              if (ppp.Length == 2 && ppp[1] is MethodCallExpression)
              {
                MethodCallExpression consumer = ppp[1] as MethodCallExpression;

                if (ppp[0] is MethodCallExpression)
                {
                  MethodCallExpression producer = ppp[0] as MethodCallExpression;
                  if (consumer.Method == Closure_Make && producer.Method == Closure_Make)
                  {
                    CodeBlockExpression ccbe = consumer.Arguments[0] as CodeBlockExpression;
                    CodeBlockExpression pcbe = producer.Arguments[0] as CodeBlockExpression;

                    pcbe.Block.Bind();
                    ccbe.Block.Bind();

                    if (ccbe.Block.ParameterCount == 0)
                    {
                      return InlineCall(cb, ccbe);
                    }
                    else if (ccbe.Block.ParameterCount == 1)
                    {
                      return InlineCall(cb, ccbe, Ast.SimpleCallHelper(typeof(Helpers).GetMethod("UnwrapValue"), InlineCall(cb, pcbe)));
                    }
                    else
                    {
                      Variable values = cb.CreateTemporaryVariable((SymbolId)Builtins.GenSym("values"), typeof(object[]));

                      Expression valuesarr = Ast.Read(values);

                      Expression[] pppp = new Expression[ccbe.Block.ParameterCount];

                      for (int i = 0; i < pppp.Length; i++)
                      {
                        pppp[i] = Ast.ArrayIndex(valuesarr, Ast.Constant(i));
                      }

                      return Ast.Comma(
                         Ast.Void(
                          Ast.Write(
                            values, 
                            Ast.ComplexCallHelper(
                              Ast.SimpleCallHelper(typeof(Helpers).GetMethod("WrapValue"), InlineCall(cb, pcbe)), 
                              typeof(MultipleValues).GetMethod("ToArray", new Type[] { typeof(int) }), 
                              Ast.Constant(pppp.Length)))), 
                          InlineCall(cb, ccbe, pppp));
                    }
                  }
                }
                if (consumer.Method == Closure_Make)
                {
                  CodeBlockExpression ccbe = consumer.Arguments[0] as CodeBlockExpression;
                  ccbe.Block.Bind();

                  Expression producer = ppp[0];

                  Expression exx = Ast.ConvertHelper(producer, typeof(Callable));

                  MethodInfo callx = GetCallable(0);

                  if (ccbe.Block.ParameterCount == 0)
                  {
                    return InlineCall(cb, ccbe);
                  }
                  else if (ccbe.Block.ParameterCount == 1)
                  {
                    return InlineCall(cb, ccbe, Ast.SimpleCallHelper(typeof(Helpers).GetMethod("UnwrapValue"), Ast.Call(exx, callx)));
                  }
                  else
                  {
                    Variable values = cb.CreateTemporaryVariable((SymbolId)Builtins.GenSym("values"), typeof(object[]));

                    Expression valuesarr = Ast.Read(values);

                    Expression[] pppp = new Expression[ccbe.Block.ParameterCount];

                    for (int i = 0; i < pppp.Length; i++)
                    {
                      pppp[i] = Ast.ArrayIndex(valuesarr, Ast.Constant(i));
                    }

                    return Ast.Comma(
                        Ast.Void(
                          Ast.Write(
                            values, 
                            Ast.ComplexCallHelper(
                              Ast.SimpleCallHelper(typeof(Helpers).GetMethod("WrapValue"),  
                                                   Ast.Call(exx, callx)), 
                              typeof(MultipleValues).GetMethod("ToArray", new Type[] { typeof(int) }), 
                              Ast.Constant(pppp.Length)))), 
                          InlineCall(cb, ccbe, pppp));
                  }
                }
              }
              else
              {
                ;
              }
            }
          }

#endif
          // this can be enabled once builtins are auto CPS'd.
          // ok I tried, but there are issues still, not sure what
#if OPTIMIZATIONS
          // check for inline emitter
          InlineEmitter ie;
          if (TryGetInlineEmitter(f, out ie))
          {
            Expression result = ie(GetAstList(c.cdr as Cons, cb));
            // if null is returned, the method cannot be inlined
            if (result != null)
            {
              if (spanhint.IsValid)
              {
                result.SetLoc(spanhint);
              }
              return result;
            }
          }
#endif

          if (Context.Scope.TryLookupName(f, out m))
          {
            if (var == null)
            {
              IGenerator gh = m as IGenerator;
              if (gh != null)
              {
                if (!Parser.sourcemap.TryGetValue(c, out spanhint))
                {
                  spanhint = SourceSpan.None;
                }
                return gh.Generate(c.cdr, cb);
              }

              BuiltinMethod bf = m as BuiltinMethod;
              if (bf != null)
              {
                MethodBinder mb = bf.Binder;
                Expression[] pars = Array.ConvertAll(GetAstList(c.cdr as Cons, cb), e => Unwrap(e));

                if (bf.AllowConstantFold && !ScriptDomainManager.Options.DebugMode)
                {
                  bool constant = Array.TrueForAll(pars, e => e is ConstantExpression && e.Type != typeof(BigInteger));

                  if (constant)
                  {
                    object[] cargs = Array.ConvertAll(pars, e => GetRuntimeConstant((ConstantExpression)e));
                    CallTarget0 disp = delegate
                    {
                      return bf.Call(cargs);
                    };
                    CallTarget1 handler = delegate(object e)
                    {
                      throw new CompileTimeEvaluationException();
                    };

                    try
                    {
                      object result = Runtime.R6RS.Exceptions.WithExceptionHandler(
                        Closure.Create(handler),
                        Closure.Create(disp));
                      var rrrr = GetCons(result, cb);
                      if (spanhint.IsValid)
                      {
                        rrrr.SetLoc(spanhint);
                      }
                      return rrrr;
                    }
                    catch (CompileTimeEvaluationException)
                    {
                    }
                  }
                }

                Type[] types = GetExpressionTypes(pars);
                MethodCandidate mc = mb.MakeBindingTarget(CallType.None, types);
                if (mc != null)
                {
                  if (mc.Target.NeedsContext)
                  {
                    pars = ArrayUtils.Insert<Expression>(Ast.CodeContext(), pars);
                  }
                  MethodBase meth = mc.Target.Method;

                  var rrrr = Ast.ComplexCallHelper(meth as MethodInfo, pars);
                  if (spanhint.IsValid)
                  {
                    rrrr.SetLoc(spanhint);
                  }
                  return rrrr;
                }
              }

              Closure clos = m as Closure;
              if (clos != null && !SetGenerator.IsAssigned(f))
              {

                // no provision for varargs
                MethodInfo[] mis = clos.Targets;
                if (mis.Length > 0)
                {
                  MethodBinder mb = MethodBinder.MakeBinder(binder, SymbolTable.IdToString(f), mis, BinderType.Normal);

                  Expression[] pars = Array.ConvertAll(GetAstList(c.cdr as Cons, cb), e => Unwrap(e));

                  if (clos.AllowConstantFold && !ScriptDomainManager.Options.DebugMode)
                  {
                    bool constant = Array.TrueForAll(pars, e => e is ConstantExpression && e.Type != typeof(BigInteger));

                    if (constant)
                    {
                      object[] cargs = Array.ConvertAll(pars, e => GetRuntimeConstant((ConstantExpression)e));

                      CallTarget0 disp = delegate
                      {
                        var rrrr = clos.Call(cargs);
                        return rrrr;
                      };

                      CallTarget1 handler = delegate (object e)
                      {
                        throw new CompileTimeEvaluationException();
                      };

                      try
                      {
                        object result = Runtime.R6RS.Exceptions.WithExceptionHandler(
                          Closure.Create(handler),
                          Closure.Create(disp));
                        var rrrr = GetCons(result, cb);
                        if (spanhint.IsValid)
                        {
                          rrrr.SetLoc(spanhint);
                        }
                        return rrrr;
                      }
                      catch (CompileTimeEvaluationException)
                      {
                      }
                    }
                  }

                  // exclude transient members if needed
                  if (!AllowTransientBinding)
                  {
                    mis = Array.FindAll(mis, x => !IsTransient(x.Module));
                  }

                  if (mis.Length > 0)
                  {
                    Type[] types = GetExpressionTypes(pars);
                    MethodCandidate mc = mb.MakeBindingTarget(CallType.None, types);
                    if (mc != null)
                    {
                      if (mc.Target.NeedsContext)
                      {
                        pars = ArrayUtils.Insert<Expression>(Ast.CodeContext(), pars);
                      }
                      MethodBase meth = mc.Target.Method;

                      var rrrr = Ast.ComplexCallHelper(meth as MethodInfo, pars);
                      if (spanhint.IsValid)
                      {
                        rrrr.SetLoc(spanhint);
                      }
                      return rrrr;
                    }
                  }
                }
                // check for overload thing
              }
            }
          }
        }

       
        Expression ex = Unwrap(GetAst(c.car, cb));

        // a 'let'
        if (ex is MethodCallExpression)
        {
          var ppp = GetAstList(c.cdr as Cons, cb);
          MethodCallExpression mcexpr = (MethodCallExpression)ex;
          if (mcexpr.Method == Closure_Make)
          {
            CodeBlockExpression cbe = mcexpr.Arguments[0] as CodeBlockExpression;

            if (ppp.Length < 9 && cbe.Block.ParameterCount == ppp.Length)
            {
              return InlineCall(cb, cbe, istailposition, ppp);
            }
          }

          // cater for varargs more efficiently, this does not seem to hit, probably needed somewhere else
          if (mcexpr.Method == Closure_MakeVarArgsX)
          {
            CodeBlockExpression cbe = mcexpr.Arguments[0] as CodeBlockExpression;

            if (ppp.Length < 9 && cbe.Block.ParameterCount <= ppp.Length)
            {
              return CallVarArgs(cbe, ppp);
            }
          }
        }

        if (ex is NewExpression && typeof(ITypedCallable).IsAssignableFrom(ex.Type))
        {
          NewExpression mcexpr = ex as NewExpression;
          CodeBlockExpression cbe = mcexpr.Arguments[0] as CodeBlockExpression;
          if (cbe == null && mcexpr.Arguments[0].Type == typeof(CodeContext) && mcexpr.Arguments[0] is ConstantExpression) // implies null
          {
            cbe = mcexpr.Arguments[1] as CodeBlockExpression;
          }
          if (cbe != null)
          {
            var ppp = GetAstListNoCast(c.cdr as Cons, cb);

            if (ppp.Length < 9 && cbe.Block.ParameterCount == ppp.Length)
            {
              return InlineCall(cb, cbe, istailposition, ppp);
            }
          }
        }

        if (ex is ConstantExpression)
        {
          Builtins.SyntaxError(SymbolTable.StringToObject("generator"), "expecting a procedure", c.car, c);
        }

        Expression r = null;

        if (ex.Type.Name.Contains("TypedClosure"))
        {
          Expression[] pp = GetAstListNoCast(c.cdr as Cons, cb);

          var m = ex.Type.GetMethod("Invoke");
          r = Ast.SimpleCallHelper(ex, m, pp);
        }
        else
        {
          Expression[] pp = GetAstList(c.cdr as Cons, cb);

          if (ex.Type != typeof(Callable))
          {
            ex = Ast.ConvertHelper(ex, typeof(Callable));
          }

          MethodInfo call = GetCallable(pp.Length);

          r = pp.Length > 8 ?
            Ast.Call(ex, call, Ast.NewArray(typeof(object[]), pp)) :
            Ast.Call(ex, call, pp);
        }

        if (spanhint.IsValid)
        {
          r.SetLoc(spanhint);
        }

        return r;
      }

      object[] v = args as object[];

      if (v != null)
      {
        return GetConsVector(v, cb);
      }
      else if (args is byte[])
      {
        Expression[] ba = Array.ConvertAll(args as byte[], b => Ast.Constant(b));
        return Ast.NewArray(typeof(byte[]), ba);
      }
      else
      {
        if (args is SymbolId)
        {
          SymbolId sym = (SymbolId)args;
          if (sym == SymbolTable.StringToId("uninitialized"))
          {
            return Ast.ReadField(null, typeof(Uninitialized), "Instance");
          }
          else
          {
            return Read(sym, cb, typeof(object));
          }
        }
        if (args == Builtins.Unspecified)
        {
          return Ast.ReadField(null, Unspecified);
        }
        if (args is Fraction)
        {
          Fraction f = (Fraction)args;
          return Ast.Constant( new FractionConstant(f));
        }
        if (args is ComplexFraction)
        {
          ComplexFraction f = (ComplexFraction)args;
          return Ast.Constant(new ComplexFractionConstant(f));
        }
        if (args != null && args.GetType().Name == "stx")
        {
          args = new SerializedConstant(args);
        }
        return Ast.Constant(args);
      }
    }
        private static Expression CoalesceInternal(CodeBlock currentBlock, Expression left, Expression right, MethodInfo isTrue, bool isReverse) {
            Contract.RequiresNotNull(currentBlock, "currentBlock");
            Contract.RequiresNotNull(left, "left");
            Contract.RequiresNotNull(right, "right");

            // A bit too strict, but on a safe side.
            Contract.Requires(left.Type == right.Type, "Expression types must match");

            Variable tmp = currentBlock.CreateTemporaryVariable(SymbolTable.StringToId("tmp_left"), left.Type);

            Expression condition;
            if (isTrue != null) {
                Contract.Requires(isTrue.ReturnType == typeof(bool), "isTrue", "Predicate must return bool.");
                ParameterInfo[] parameters = isTrue.GetParameters();
                Contract.Requires(parameters.Length == 1, "isTrue", "Predicate must take one parameter.");
                Contract.Requires(isTrue.IsStatic && isTrue.IsPublic, "isTrue", "Predicate must be public and static.");

                Type pt = parameters[0].ParameterType;
                Contract.Requires(TypeUtils.CanAssign(pt, left.Type), "left", "Incorrect left expression type");
                condition = Call(isTrue, Assign(tmp, left));
            } else {
                Contract.Requires(TypeUtils.CanCompareToNull(left.Type), "left", "Incorrect left expression type");
                condition = Equal(Assign(tmp, left), Null(left.Type));
            }

            Expression t, f;
            if (isReverse) {
                t = Read(tmp);
                f = right;
            } else {
                t = right;
                f = Read(tmp);
            }

            return Condition(condition, t, f);
        }
示例#4
0
        protected internal static Expression GetAst(object args, CodeBlock cb, bool istailposition)
        {
            if (args is Annotation)
            {
                args = ((Annotation)args).stripped;
            }
            Cons c = args as Cons;

            if (c != null)
            {
                if (c.car is SymbolId)
                {
                    SymbolId f = (SymbolId)c.car;

                    Variable var = cb.Lookup(f);

                    if (var != null && !assigns.ContainsKey(f))
                    {
                        var = null;
                    }

                    object m;

#if OPTIMIZATIONS
#if !BLAH
                    CodeBlockExpression cbe;

                    //// needs to do the same for overloads...
                    if (SimpleGenerator.libraryglobals.TryGetValue(f, out cbe))
                    {
                        Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        if (cbe.Block.ParameterCount < 9 && cbe.Block.ParameterCount == ppp.Length)
                        {
                            //inline here? we could for simple bodies, but we need to copy the entire structure
                            if (!(cbe.Block.HasEnvironment || cbe.Block.IsClosure))
                            {
                                if (cbe.Block.Body is ReturnStatement)
                                {
                                    ReturnStatement rs = (ReturnStatement)cbe.Block.Body;

                                    if (!ScriptDomainManager.Options.DebugMode &&
                                        !ScriptDomainManager.Options.LightweightDebugging &&
                                        !cb.IsGlobal && IsSimpleExpression(rs.Expression))
                                    {
                                        return(InlineCall(cb, Ast.CodeBlockExpression(RewriteBody(cbe.Block), false, cbe.IsStronglyTyped), ppp));
                                    }
                                }
                            }
                            if (cbe.Block != cb.Parent && cbe.Block != cb) // do TCE later
                            {
                                return(CallNormal(cbe, ppp));
                            }
                        }
                    }

                    // varargs
                    if (SimpleGenerator.libraryglobalsX.TryGetValue(f, out cbe))
                    {
                        Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        if (cbe.Block.ParameterCount < 9 && cbe.Block.ParameterCount - 1 <= ppp.Length)
                        {
                            //inline here?
                            return(CallVarArgs(cbe, ppp));
                        }
                    }

                    // overloads
                    CodeBlockDescriptor[] cbd;
                    if (SimpleGenerator.libraryglobalsN.TryGetValue(f, out cbd))
                    {
                        Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        foreach (CodeBlockDescriptor d in cbd)
                        {
                            if (d.codeblock.Block.ParameterCount < 9)
                            {
                                if (ppp.Length == d.arity || (d.varargs && ppp.Length > d.arity))
                                {
                                    if (d.varargs)
                                    {
                                        //inline here?
                                        return(CallVarArgs(d.codeblock, ppp));
                                    }
                                    else
                                    {
                                        //inline here?
                                        //if (d.codeblock.Block != cb.Parent && d.codeblock.Block != cb) // do TCE later, not yet
                                        {
                                            return(CallNormal(d.codeblock, ppp));
                                        }
                                    }
                                }
                            }
                        }
                    }
#endif

                    //if (!ScriptDomainManager.Options.DebugMode)
                    {
                        if (f == SymbolTable.StringToId("call-with-values"))
                        {
                            Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);
                            if (ppp.Length == 2 && ppp[1] is MethodCallExpression)
                            {
                                MethodCallExpression consumer = ppp[1] as MethodCallExpression;

                                if (ppp[0] is MethodCallExpression)
                                {
                                    MethodCallExpression producer = ppp[0] as MethodCallExpression;
                                    if (consumer.Method == Closure_Make && producer.Method == Closure_Make)
                                    {
                                        CodeBlockExpression ccbe = consumer.Arguments[0] as CodeBlockExpression;
                                        CodeBlockExpression pcbe = producer.Arguments[0] as CodeBlockExpression;

                                        pcbe.Block.Bind();
                                        ccbe.Block.Bind();

                                        if (ccbe.Block.ParameterCount == 0)
                                        {
                                            return(InlineCall(cb, ccbe));
                                        }
                                        else if (ccbe.Block.ParameterCount == 1)
                                        {
                                            return(InlineCall(cb, ccbe, Ast.SimpleCallHelper(typeof(Helpers).GetMethod("UnwrapValue"), InlineCall(cb, pcbe))));
                                        }
                                        else
                                        {
                                            Variable values = cb.CreateTemporaryVariable((SymbolId)Builtins.GenSym("values"), typeof(object[]));

                                            Expression valuesarr = Ast.Read(values);

                                            Expression[] pppp = new Expression[ccbe.Block.ParameterCount];

                                            for (int i = 0; i < pppp.Length; i++)
                                            {
                                                pppp[i] = Ast.ArrayIndex(valuesarr, Ast.Constant(i));
                                            }

                                            return(Ast.Comma(
                                                       Ast.Void(
                                                           Ast.Write(
                                                               values,
                                                               Ast.ComplexCallHelper(
                                                                   Ast.SimpleCallHelper(typeof(Helpers).GetMethod("WrapValue"), InlineCall(cb, pcbe)),
                                                                   typeof(MultipleValues).GetMethod("ToArray", new Type[] { typeof(int) }),
                                                                   Ast.Constant(pppp.Length)))),
                                                       InlineCall(cb, ccbe, pppp)));
                                        }
                                    }
                                }
                                if (consumer.Method == Closure_Make)
                                {
                                    CodeBlockExpression ccbe = consumer.Arguments[0] as CodeBlockExpression;
                                    ccbe.Block.Bind();

                                    Expression producer = ppp[0];

                                    Expression exx = Ast.ConvertHelper(producer, typeof(Callable));

                                    MethodInfo callx = GetCallable(0);

                                    if (ccbe.Block.ParameterCount == 0)
                                    {
                                        return(InlineCall(cb, ccbe));
                                    }
                                    else if (ccbe.Block.ParameterCount == 1)
                                    {
                                        return(InlineCall(cb, ccbe, Ast.SimpleCallHelper(typeof(Helpers).GetMethod("UnwrapValue"), Ast.Call(exx, callx))));
                                    }
                                    else
                                    {
                                        Variable values = cb.CreateTemporaryVariable((SymbolId)Builtins.GenSym("values"), typeof(object[]));

                                        Expression valuesarr = Ast.Read(values);

                                        Expression[] pppp = new Expression[ccbe.Block.ParameterCount];

                                        for (int i = 0; i < pppp.Length; i++)
                                        {
                                            pppp[i] = Ast.ArrayIndex(valuesarr, Ast.Constant(i));
                                        }

                                        return(Ast.Comma(
                                                   Ast.Void(
                                                       Ast.Write(
                                                           values,
                                                           Ast.ComplexCallHelper(
                                                               Ast.SimpleCallHelper(typeof(Helpers).GetMethod("WrapValue"),
                                                                                    Ast.Call(exx, callx)),
                                                               typeof(MultipleValues).GetMethod("ToArray", new Type[] { typeof(int) }),
                                                               Ast.Constant(pppp.Length)))),
                                                   InlineCall(cb, ccbe, pppp)));
                                    }
                                }
                            }
                            else
                            {
                                ;
                            }
                        }
                    }
#endif
                    // this can be enabled once builtins are auto CPS'd.
                    // ok I tried, but there are issues still, not sure what
#if OPTIMIZATIONS
                    // check for inline emitter
                    InlineEmitter ie;
                    if (TryGetInlineEmitter(f, out ie))
                    {
                        Expression result = ie(GetAstList(c.cdr as Cons, cb));
                        // if null is returned, the method cannot be inlined
                        if (result != null)
                        {
                            if (spanhint.IsValid)
                            {
                                result.SetLoc(spanhint);
                            }
                            return(result);
                        }
                    }
#endif

                    if (Context.Scope.TryLookupName(f, out m))
                    {
                        if (var == null)
                        {
                            IGenerator gh = m as IGenerator;
                            if (gh != null)
                            {
                                return(gh.Generate(c.cdr, cb));
                            }

                            BuiltinMethod bf = m as BuiltinMethod;
                            if (bf != null)
                            {
                                MethodBinder mb   = bf.Binder;
                                Expression[] pars = Array.ConvertAll(GetAstList(c.cdr as Cons, cb), e => Unwrap(e));

                                if (bf.AllowConstantFold && !ScriptDomainManager.Options.DebugMode)
                                {
                                    bool constant = Array.TrueForAll(pars, e => e is ConstantExpression && e.Type != typeof(BigInteger));

                                    if (constant)
                                    {
                                        object[]    cargs = Array.ConvertAll(pars, e => GetRuntimeConstant((ConstantExpression)e));
                                        CallTarget0 disp  = delegate
                                        {
                                            return(bf.Call(cargs));
                                        };
                                        CallTarget1 handler = delegate(object e)
                                        {
                                            throw new CompileTimeEvaluationException();
                                        };

                                        try
                                        {
                                            object result = Runtime.R6RS.Exceptions.WithExceptionHandler(
                                                Closure.Create(handler),
                                                Closure.Create(disp));
                                            var rrrr = GetCons(result, cb);
                                            if (spanhint.IsValid)
                                            {
                                                rrrr.SetLoc(spanhint);
                                            }
                                            return(rrrr);
                                        }
                                        catch (CompileTimeEvaluationException)
                                        {
                                        }
                                    }
                                }

                                Type[]          types = GetExpressionTypes(pars);
                                MethodCandidate mc    = mb.MakeBindingTarget(CallType.None, types);
                                if (mc != null)
                                {
                                    if (mc.Target.NeedsContext)
                                    {
                                        pars = ArrayUtils.Insert <Expression>(Ast.CodeContext(), pars);
                                    }
                                    MethodBase meth = mc.Target.Method;

                                    var rrrr = Ast.ComplexCallHelper(meth as MethodInfo, pars);
                                    if (spanhint.IsValid)
                                    {
                                        rrrr.SetLoc(spanhint);
                                    }
                                    return(rrrr);
                                }
                            }

                            Closure clos = m as Closure;
                            if (clos != null && !SetGenerator.IsAssigned(f))
                            {
                                // no provision for varargs
                                MethodInfo[] mis = clos.Targets;
                                if (mis.Length > 0)
                                {
                                    MethodBinder mb = MethodBinder.MakeBinder(binder, SymbolTable.IdToString(f), mis, BinderType.Normal);

                                    Expression[] pars = Array.ConvertAll(GetAstList(c.cdr as Cons, cb), e => Unwrap(e));

                                    if (clos.AllowConstantFold && !ScriptDomainManager.Options.DebugMode)
                                    {
                                        bool constant = Array.TrueForAll(pars, e => e is ConstantExpression && e.Type != typeof(BigInteger));

                                        if (constant)
                                        {
                                            object[] cargs = Array.ConvertAll(pars, e => GetRuntimeConstant((ConstantExpression)e));

                                            CallTarget0 disp = delegate
                                            {
                                                var rrrr = clos.Call(cargs);
                                                return(rrrr);
                                            };

                                            CallTarget1 handler = delegate(object e)
                                            {
                                                throw new CompileTimeEvaluationException();
                                            };

                                            try
                                            {
                                                object result = Runtime.R6RS.Exceptions.WithExceptionHandler(
                                                    Closure.Create(handler),
                                                    Closure.Create(disp));
                                                var rrrr = GetCons(result, cb);
                                                if (spanhint.IsValid)
                                                {
                                                    rrrr.SetLoc(spanhint);
                                                }
                                                return(rrrr);
                                            }
                                            catch (CompileTimeEvaluationException)
                                            {
                                            }
                                        }
                                    }

                                    // exclude transient members if needed
                                    if (!AllowTransientBinding)
                                    {
                                        mis = Array.FindAll(mis, x => !IsTransient(x.Module));
                                    }

                                    if (mis.Length > 0)
                                    {
                                        Type[]          types = GetExpressionTypes(pars);
                                        MethodCandidate mc    = mb.MakeBindingTarget(CallType.None, types);
                                        if (mc != null)
                                        {
                                            if (mc.Target.NeedsContext)
                                            {
                                                pars = ArrayUtils.Insert <Expression>(Ast.CodeContext(), pars);
                                            }
                                            MethodBase meth = mc.Target.Method;

                                            var rrrr = Ast.ComplexCallHelper(meth as MethodInfo, pars);
                                            if (spanhint.IsValid)
                                            {
                                                rrrr.SetLoc(spanhint);
                                            }
                                            return(rrrr);
                                        }
                                    }
                                }
                                // check for overload thing
                            }
                        }
                    }
                }


                Expression ex = Unwrap(GetAst(c.car, cb));

                // a 'let'
                if (ex is MethodCallExpression)
                {
                    var ppp = GetAstList(c.cdr as Cons, cb);
                    MethodCallExpression mcexpr = (MethodCallExpression)ex;
                    if (mcexpr.Method == Closure_Make)
                    {
                        CodeBlockExpression cbe = mcexpr.Arguments[0] as CodeBlockExpression;

                        if (ppp.Length < 9 && cbe.Block.ParameterCount == ppp.Length)
                        {
                            return(InlineCall(cb, cbe, istailposition, ppp));
                        }
                    }

                    // cater for varargs more efficiently, this does not seem to hit, probably needed somewhere else
                    if (mcexpr.Method == Closure_MakeVarArgsX)
                    {
                        CodeBlockExpression cbe = mcexpr.Arguments[0] as CodeBlockExpression;

                        if (ppp.Length < 9 && cbe.Block.ParameterCount <= ppp.Length)
                        {
                            return(CallVarArgs(cbe, ppp));
                        }
                    }
                }

                if (ex is NewExpression && typeof(ITypedCallable).IsAssignableFrom(ex.Type))
                {
                    NewExpression       mcexpr = ex as NewExpression;
                    CodeBlockExpression cbe    = mcexpr.Arguments[0] as CodeBlockExpression;
                    if (cbe == null && mcexpr.Arguments[0].Type == typeof(CodeContext) && mcexpr.Arguments[0] is ConstantExpression) // implies null
                    {
                        cbe = mcexpr.Arguments[1] as CodeBlockExpression;
                    }
                    if (cbe != null)
                    {
                        var ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        if (ppp.Length < 9 && cbe.Block.ParameterCount == ppp.Length)
                        {
                            return(InlineCall(cb, cbe, istailposition, ppp));
                        }
                    }
                }

                if (ex is ConstantExpression)
                {
                    Builtins.SyntaxError(SymbolTable.StringToObject("generator"), "expecting a procedure", c.car, c);
                }

                Expression r = null;

                if (ex.Type.Name.Contains("TypedClosure"))
                {
                    Expression[] pp = GetAstListNoCast(c.cdr as Cons, cb);

                    var m = ex.Type.GetMethod("Invoke");
                    r = Ast.SimpleCallHelper(ex, m, pp);
                }
                else
                {
                    Expression[] pp = GetAstList(c.cdr as Cons, cb);

                    if (ex.Type != typeof(Callable))
                    {
                        ex = Ast.ConvertHelper(ex, typeof(Callable));
                    }

                    MethodInfo call = GetCallable(pp.Length);

                    r = pp.Length > 8 ?
                        Ast.Call(ex, call, Ast.NewArray(typeof(object[]), pp)) :
                        Ast.Call(ex, call, pp);
                }

                if (spanhint.IsValid)
                {
                    r.SetLoc(spanhint);
                }

                return(r);
            }

            object[] v = args as object[];

            if (v != null)
            {
                return(GetConsVector(v, cb));
            }
            else if (args is byte[])
            {
                Expression[] ba = Array.ConvertAll(args as byte[], b => Ast.Constant(b));
                return(Ast.NewArray(typeof(byte[]), ba));
            }
            else
            {
                if (args is SymbolId)
                {
                    SymbolId sym = (SymbolId)args;
                    if (sym == SymbolTable.StringToId("uninitialized"))
                    {
                        return(Ast.ReadField(null, typeof(Uninitialized), "Instance"));
                    }
                    else
                    {
                        return(Read(sym, cb, typeof(object)));
                    }
                }
                if (args == Builtins.Unspecified)
                {
                    return(Ast.ReadField(null, Unspecified));
                }
                if (args is Fraction)
                {
                    Fraction f = (Fraction)args;
                    return(Ast.Constant(new FractionConstant(f)));
                }
                if (args is ComplexFraction)
                {
                    ComplexFraction f = (ComplexFraction)args;
                    return(Ast.Constant(new ComplexFractionConstant(f)));
                }
                if (args != null && args.GetType().Name == "stx")
                {
                    args = new SerializedConstant(args);
                }
                return(Ast.Constant(args));
            }
        }
示例#5
0
 protected internal override Variable MakeTemp(string name, Type type)
 {
     return(_block.CreateTemporaryVariable(SymbolTable.StringToId(name), type));
 }