aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2008-10-28 14:53:16 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2008-10-28 14:53:16 -0200
commitf6978173e03fdbe5536887b08beb53884f7c1a18 (patch)
treebc31173c72e358649dda82a532c29066db352a70 /lvm.c
parente02483dbc031ca0cdba17cb511c1e674551f90c5 (diff)
downloadlua-f6978173e03fdbe5536887b08beb53884f7c1a18.tar.gz
lua-f6978173e03fdbe5536887b08beb53884f7c1a18.tar.bz2
lua-f6978173e03fdbe5536887b08beb53884f7c1a18.zip
yields accross metamethods and for iterators (except for __concat)
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c55
1 files changed, 25 insertions, 30 deletions
diff --git a/lvm.c b/lvm.c
index 44b159b6..65afc4a9 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.76 2008/08/26 13:27:42 roberto Exp roberto $ 2** $Id: lvm.c,v 2.77 2008/09/09 13:53:02 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -76,31 +76,24 @@ static void traceexec (lua_State *L) {
76} 76}
77 77
78 78
79static void callTMres (lua_State *L, StkId res, const TValue *f,
80 const TValue *p1, const TValue *p2) {
81 ptrdiff_t result = savestack(L, res);
82 setobj2s(L, L->top, f); /* push function */
83 setobj2s(L, L->top+1, p1); /* 1st argument */
84 setobj2s(L, L->top+2, p2); /* 2nd argument */
85 L->top += 3;
86 luaD_checkstack(L, 0);
87 luaD_call(L, L->top - 3, 1);
88 res = restorestack(L, result);
89 L->top--;
90 setobjs2s(L, res, L->top);
91}
92
93
94
95static void callTM (lua_State *L, const TValue *f, const TValue *p1, 79static void callTM (lua_State *L, const TValue *f, const TValue *p1,
96 const TValue *p2, const TValue *p3) { 80 const TValue *p2, TValue *p3, int hasres) {
97 setobj2s(L, L->top, f); /* push function */ 81 ptrdiff_t result = savestack(L, p3);
98 setobj2s(L, L->top+1, p1); /* 1st argument */ 82 int oldbase = L->baseCcalls;
99 setobj2s(L, L->top+2, p2); /* 2nd argument */ 83 setobj2s(L, L->top++, f); /* push function */
100 setobj2s(L, L->top+3, p3); /* 3th argument */ 84 setobj2s(L, L->top++, p1); /* 1st argument */
101 L->top += 4; 85 setobj2s(L, L->top++, p2); /* 2nd argument */
86 if (!hasres) /* no result? 'p3' is third argument */
87 setobj2s(L, L->top++, p3); /* 3th argument */
102 luaD_checkstack(L, 0); 88 luaD_checkstack(L, 0);
103 luaD_call(L, L->top - 4, 0); 89 if (isLua(L->ci)) /* metamethod invoked from a Lua function? */
90 L->baseCcalls++; /* allow it to yield */
91 luaD_call(L, L->top - (4 - hasres), hasres);
92 L->baseCcalls = oldbase;
93 if (hasres) { /* if has result, move it to its place */
94 p3 = restorestack(L, result);
95 setobjs2s(L, p3, --L->top);
96 }
104} 97}
105 98
106 99
@@ -121,7 +114,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
121 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) 114 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
122 luaG_typeerror(L, t, "index"); 115 luaG_typeerror(L, t, "index");
123 if (ttisfunction(tm)) { 116 if (ttisfunction(tm)) {
124 callTMres(L, val, tm, t, key); 117 callTM(L, tm, t, key, val, 1);
125 return; 118 return;
126 } 119 }
127 t = tm; /* else repeat with `tm' */ 120 t = tm; /* else repeat with `tm' */
@@ -148,7 +141,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
148 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) 141 else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
149 luaG_typeerror(L, t, "index"); 142 luaG_typeerror(L, t, "index");
150 if (ttisfunction(tm)) { 143 if (ttisfunction(tm)) {
151 callTM(L, tm, t, key, val); 144 callTM(L, tm, t, key, val, 0);
152 return; 145 return;
153 } 146 }
154 t = tm; /* else repeat with `tm' */ 147 t = tm; /* else repeat with `tm' */
@@ -163,7 +156,7 @@ static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
163 if (ttisnil(tm)) 156 if (ttisnil(tm))
164 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 157 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
165 if (ttisnil(tm)) return 0; 158 if (ttisnil(tm)) return 0;
166 callTMres(L, res, tm, p1, p2); 159 callTM(L, tm, p1, p2, res, 1);
167 return 1; 160 return 1;
168} 161}
169 162
@@ -190,7 +183,7 @@ static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
190 tm2 = luaT_gettmbyobj(L, p2, event); 183 tm2 = luaT_gettmbyobj(L, p2, event);
191 if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ 184 if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */
192 return -1; 185 return -1;
193 callTMres(L, L->top, tm1, p1, p2); 186 callTM(L, tm1, p1, p2, L->top, 1);
194 return !l_isfalse(L->top); 187 return !l_isfalse(L->top);
195} 188}
196 189
@@ -268,7 +261,7 @@ int luaV_equalval_ (lua_State *L, const TValue *t1, const TValue *t2) {
268 default: return gcvalue(t1) == gcvalue(t2); 261 default: return gcvalue(t1) == gcvalue(t2);
269 } 262 }
270 if (tm == NULL) return 0; /* no TM? */ 263 if (tm == NULL) return 0; /* no TM? */
271 callTMres(L, L->top, tm, t1, t2); /* call TM */ 264 callTM(L, tm, t1, t2, L->top, 1); /* call TM */
272 return !l_isfalse(L->top); 265 return !l_isfalse(L->top);
273} 266}
274 267
@@ -336,7 +329,7 @@ static void objlen (lua_State *L, StkId ra, const TValue *rb) {
336 break; 329 break;
337 } 330 }
338 } 331 }
339 callTMres(L, ra, tm, rb, luaO_nilobject); 332 callTM(L, tm, rb, luaO_nilobject, ra, 1);
340} 333}
341 334
342 335
@@ -680,7 +673,9 @@ void luaV_execute (lua_State *L) {
680 setobjs2s(L, cb+1, ra+1); 673 setobjs2s(L, cb+1, ra+1);
681 setobjs2s(L, cb, ra); 674 setobjs2s(L, cb, ra);
682 L->top = cb+3; /* func. + 2 args (state and index) */ 675 L->top = cb+3; /* func. + 2 args (state and index) */
676 L->baseCcalls++;
683 Protect(luaD_call(L, cb, GETARG_C(i))); 677 Protect(luaD_call(L, cb, GETARG_C(i)));
678 L->baseCcalls--;
684 L->top = L->ci->top; 679 L->top = L->ci->top;
685 cb = RA(i) + 3; /* previous call may change the stack */ 680 cb = RA(i) + 3; /* previous call may change the stack */
686 if (!ttisnil(cb)) { /* continue loop? */ 681 if (!ttisnil(cb)) { /* continue loop? */