function $JsCallable(callable,parms,targs) {
    if (callable.getT$all === undefined) {
        callable.getT$all=Callable.getT$all;
    }
    var set_meta = callable.$crtmm$ === undefined;
    if (set_meta) {
        callable.$crtmm$={ps:[],mod:$CCMM$,d:['$','Callable']};
        if (parms !== undefined) {
            callable.$crtmm$['ps']=parms;
        }
    }
    if (targs !== undefined && callable.$$targs$$ === undefined) {
        callable.$$targs$$=targs;
        if (set_meta) {
            callable.$crtmm$['$t']=targs['Return'];
        }
    }
    return callable;
}
initExistingTypeProto($JsCallable, Function, 'ceylon.language::JsCallable', Callable);

function nop$() { return null; }

//This is used for plain method references
function JsCallable(o,f,targs) {
  if (o===null || o===undefined) return nop$;
  var f2 = function() {
    var arg=[].slice.call(arguments,0);
    //if we get only 1 arg and it's a tuple...
    if (arg.length===1 && is$(arg[0],{t:Tuple})) {
      //Possible spread
      var mm=getrtmm$$(f);
      //If f has only 1 param and it's not sequenced, get its type
      var a1t=mm && mm.ps && mm.ps.length===1 && mm.ps[0].seq===undefined ? mm.ps[0].$t : undefined;
      //If its type is a type param, get the type arg
      if (typeof(a1t)==='string')a1t=targs && targs[a1t];
      //If the tuple type matches the param type, it's NOT a spread
      if (!(a1t && is$(arg[0],a1t))) {
        var typecheck;
        if (a1t && arg[0].$$targs$$) {
          if (arg[0].$$targs$$.First$Tuple) {
            typecheck=arg[0].$$targs$$.First$Tuple;
          } else if (arg[0].$$targs$$.t==='T') {
            typecheck=arg[0].$$targs$$.l[0];
          }
        } else {
          typecheck={t:Iterable};
          if (arg[0].$$targs$$ && arg[0].$$targs$$.Element$Iterable)typecheck.a={Element$Iterable:arg[0].$$targs$$.Element$Iterable};
        }
        if (mm && mm.ps && (mm.ps.length>1 || (mm.ps.length===1
            && (mm.ps[0].seq || !extendsType(a1t, typecheck))))) {
          var a=arg[0].nativeArray ? arg[0].nativeArray():undefined;
          if (a===undefined) {
            a=[];
            for (var i=0;i<arg[0].size;i++)a.push(arg[0].$_get(i));
          }
          arg=a;
        }
      }
    }
    if (targs)arg.push(targs);
    return f.apply(o, arg);
  };
  f2.$crtmm$=f.$crtmm$===undefined?Callable.$crtmm$:f.$crtmm$;
  return f2;
}
JsCallable.$crtmm$=function(){return{ sts:[{t:Callable,a:{Return$Callable:'Return$Callable',Arguments$Callable:'Arguments$Callable'}}],
  tp:{Return$Callable:{dv:'out'}, Arguments$Callable:{dv:'in'}},pa:1,mod:$CCMM$,d:['$','Callable']};}

//This is used for spread method references
function JsCallableList(value,$mpt) {
    return function() {
        var a=arguments;
        if ($mpt) {
          a=[].slice.call(arguments,0);
          a.push($mpt);
        }
        var rval = Array(value.length);
        for (var i = 0; i < value.length; i++) {
            var c = value[i];
            rval[i] = c.f.apply(c.o, a);
        }
        return value.length===0?getEmpty():sequence(rval,{Element$sequence:{t:Callable},Absent$sequence:{t:Nothing}});
    };
}
JsCallableList.$crtmm$={tp:{Return$Callable:{dv:'out'}, Arguments$Callable:{dv:'in'}},pa:1,mod:$CCMM$,d:['$','Callable']};

ex$.JsCallableList=JsCallableList;
ex$.JsCallable=JsCallable;
ex$.$JsCallable=$JsCallable;

@@ -151,32 +151,35 @@
 _meta = 
-callable.$crtmm$
+getrtmm$$(callable)
  === und
@@ -337,14 +337,11 @@
 tmm$
-%5B'ps'%5D
+.ps
 =par
@@ -517,30 +517,33 @@
 tmm$
-%5B'$t'%5D
+.$t
 =targs
-%5B'
+.
 Return
-'%5D
+$Callable
 ;%0A  
@@ -724,14 +724,8 @@
 for 
-plain 
 meth
@@ -998,24 +998,45 @@
 sible spread
+, check the metamodel
 %0A      var m
@@ -1236,16 +1236,9 @@
 f it
-s type i
+'
 s a 
@@ -1265,16 +1265,21 @@
 type arg
+ument
 %0A      i
@@ -1397,16 +1397,92 @@
  spread%0A
+      //(it's just a regular 1-param func which happens to receive a tuple)%0A
       if
@@ -1634,32 +1634,43 @@
       typecheck=
+%7Bt:Tuple,a:
 arg%5B0%5D.$$targs$$
@@ -1669,28 +1669,17 @@
 $targs$$
-.First$Tuple
+%7D
 ;%0A      
@@ -1763,13 +1763,8 @@
 gs$$
-.l%5B0%5D
 ;%0A  
@@ -1776,157 +1776,88 @@
    %7D
-%0A        %7D else %7B%0A          typecheck=%7Bt:Iterable%7D;%0A          if (arg%5B0%5D.$$targs$$ && arg%5B0%5D.$$targs$$.Element$Iterable)typecheck.a=%7BElement$
+ else if (arg%5B0%5D.$$targs$$.Element$Iterable) %7B%0A            typecheck=%7Bt:
 Iterable
 :arg
@@ -1852,16 +1852,18 @@
 Iterable
+,a
 :arg%5B0%5D.
@@ -1891,16 +1891,28 @@
 rable%7D;%0A
+          %7D%0A
         

work on ceylon/ceylon-js#450