aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-06-25 17:45:50 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-06-25 17:45:50 -0300
commitc1a63c45f8ec5932993c8cec40d3c5ec0743349c (patch)
treea61e8edb10b498c25e961cd7b2c7cb857e9db4c7 /ldo.c
parent4487c28ced3dcf47c3ee19b6f6eeb0089ec64ba5 (diff)
downloadlua-c1a63c45f8ec5932993c8cec40d3c5ec0743349c.tar.gz
lua-c1a63c45f8ec5932993c8cec40d3c5ec0743349c.tar.bz2
lua-c1a63c45f8ec5932993c8cec40d3c5ec0743349c.zip
'__call' metamethod can be any callable object
Removed the restriction that a '__call' metamethod must be an actual function.
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/ldo.c b/ldo.c
index 1a327ffd..288aef13 100644
--- a/ldo.c
+++ b/ldo.c
@@ -348,18 +348,18 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
348 348
349 349
350/* 350/*
351** Check whether __call metafield of 'func' is a function. If so, put 351** Check whether 'func' has a '__call' metafield. If so, put it in the
352** it in stack below original 'func' so that 'luaD_call' can call 352** stack, below original 'func', so that 'luaD_call' can call it. Raise
353** it. Raise an error if __call metafield is not a function. 353** an error if there is no '__call' metafield.
354*/ 354*/
355void luaD_tryfuncTM (lua_State *L, StkId func) { 355void luaD_tryfuncTM (lua_State *L, StkId func) {
356 const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); 356 const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL);
357 StkId p; 357 StkId p;
358 if (unlikely(!ttisfunction(tm))) 358 if (unlikely(ttisnil(tm)))
359 luaG_typeerror(L, s2v(func), "call"); 359 luaG_typeerror(L, s2v(func), "call"); /* nothing to call */
360 for (p = L->top; p > func; p--) 360 for (p = L->top; p > func; p--) /* open space for metamethod */
361 setobjs2s(L, p, p-1); 361 setobjs2s(L, p, p-1);
362 L->top++; /* assume EXTRA_STACK */ 362 L->top++; /* stack space pre-allocated by the caller */
363 setobj2s(L, func, tm); /* metamethod is the new function to be called */ 363 setobj2s(L, func, tm); /* metamethod is the new function to be called */
364} 364}
365 365
@@ -457,13 +457,13 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
457*/ 457*/
458void luaD_call (lua_State *L, StkId func, int nresults) { 458void luaD_call (lua_State *L, StkId func, int nresults) {
459 lua_CFunction f; 459 lua_CFunction f;
460 TValue *funcv = s2v(func); 460 retry:
461 switch (ttypetag(funcv)) { 461 switch (ttypetag(s2v(func))) {
462 case LUA_TCCL: /* C closure */ 462 case LUA_TCCL: /* C closure */
463 f = clCvalue(funcv)->f; 463 f = clCvalue(s2v(func))->f;
464 goto Cfunc; 464 goto Cfunc;
465 case LUA_TLCF: /* light C function */ 465 case LUA_TLCF: /* light C function */
466 f = fvalue(funcv); 466 f = fvalue(s2v(func));
467 Cfunc: { 467 Cfunc: {
468 int n; /* number of returns */ 468 int n; /* number of returns */
469 CallInfo *ci; 469 CallInfo *ci;
@@ -487,7 +487,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
487 } 487 }
488 case LUA_TLCL: { /* Lua function */ 488 case LUA_TLCL: { /* Lua function */
489 CallInfo *ci; 489 CallInfo *ci;
490 Proto *p = clLvalue(funcv)->p; 490 Proto *p = clLvalue(s2v(func))->p;
491 int narg = cast_int(L->top - func) - 1; /* number of real arguments */ 491 int narg = cast_int(L->top - func) - 1; /* number of real arguments */
492 int nfixparams = p->numparams; 492 int nfixparams = p->numparams;
493 int fsize = p->maxstacksize; /* frame size */ 493 int fsize = p->maxstacksize; /* frame size */
@@ -505,9 +505,9 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
505 break; 505 break;
506 } 506 }
507 default: { /* not a function */ 507 default: { /* not a function */
508 checkstackp(L, 1, func); /* space for metamethod */
508 luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ 509 luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
509 luaD_call(L, func, nresults); /* now it must be a function */ 510 goto retry; /* try again with metamethod */
510 break;
511 } 511 }
512 } 512 }
513} 513}