IMHO, Let luajit support lua 5.2 is better :) My point is we don't need stay on lua 5.1 if luajit fully support lua 5.2. Anyone implement lua 4.0's tag methods with lua 5's metatable ? or still use lua 5.0 's vararg arg? 2012/10/26 Coda Highland <chighland@xxxxxxxxx>: > I never said they were equivalent. I also never said that setfenv() is > better. What I said was that you can implement setfenv() using _ENV in > order to make code that works in Lua 5.1, Lua 5.2, and LuaJIT. > > /s/ Adam > > On Thu, Oct 25, 2012 at 7:22 PM, 云风 <cloudwu@xxxxxxxxx> wrote: >> I think _ENV is better than setfenv , because it simplify the >> language . _ENV is only a syntactic sugar , so that we don't need the >> concept of global and environment in the language. >> >> setfenv is not equal to _ENV. For example, if we need to change the >> environment each call , we can pass the _ENV explicitly . >> >> function foobar(_ENV) >> a = 1 >> coroutine.yield() >> a = 2 >> end >> >> 2012/10/25 Coda Highland <chighland@xxxxxxxxx>: >>> On Thu, Oct 25, 2012 at 12:06 AM, 云风 <cloudwu@xxxxxxxxx> wrote: >>>> It looks like that Mike dislike _ENV ;) But I really need it to >>>> compatible my lua 5.2 code in luajit 2.0 . >>>> >>>> So I make a patch to support it. I guess someone would need it , too. >>>> >>>> Here it is: >>>> >>>> diff --git a/src/lib_base.c b/src/lib_base.c >>>> index 568216e..b58a5a4 100644 >>>> --- a/src/lib_base.c >>>> +++ b/src/lib_base.c >>>> @@ -363,6 +363,10 @@ static int load_aux(lua_State *L, int status, int >>>> envarg) >>>> GCtab *t = tabV(L->base+envarg-1); >>>> setgcref(fn->c.env, obj2gco(t)); >>>> lj_gc_objbarrier(L, fn, t); >>>> + if (LJ_52) { >>>> + lua_pushvalue(L, envarg); >>>> + lua_setupvalue(L, -2, 1); >>>> + } >>>> } >>>> return 1; >>>> } else { >>>> diff --git a/src/lj_lex.c b/src/lj_lex.c >>>> index b54d2a2..59b2b84 100644 >>>> --- a/src/lj_lex.c >>>> +++ b/src/lj_lex.c >>>> @@ -381,6 +381,7 @@ int lj_lex_setup(lua_State *L, LexState *ls) >>>> ls->lookahead = TK_eof; /* No look-ahead token. */ >>>> ls->linenumber = 1; >>>> ls->lastline = 1; >>>> + ls->env = NULL; >>>> lj_str_resizebuf(ls->L, &ls->sb, LJ_MIN_SBUF); >>>> next(ls); /* Read-ahead first char. */ >>>> if (ls->current == 0xef && ls->n >= 2 && char2int(ls->p[0]) == 0xbb && >>>> diff --git a/src/lj_lex.h b/src/lj_lex.h >>>> index d16461a..37c15eb 100644 >>>> --- a/src/lj_lex.h >>>> +++ b/src/lj_lex.h >>>> @@ -73,6 +73,7 @@ typedef struct LexState { >>>> BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */ >>>> MSize sizebcstack; /* Size of bytecode stack. */ >>>> uint32_t level; /* Syntactical nesting level. */ >>>> + GCstr *env; /* const _ENV */ >>>> } LexState; >>>> >>>> LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); >>>> diff --git a/src/lj_load.c b/src/lj_load.c >>>> index e30421e..5a389af 100644 >>>> --- a/src/lj_load.c >>>> +++ b/src/lj_load.c >>>> @@ -40,6 +40,9 @@ static TValue *cpparser(lua_State *L, lua_CFunction >>>> dummy, void *ud) >>>> } >>>> pt = bc ? lj_bcread(ls) : lj_parse(ls); >>>> fn = lj_func_newL_empty(L, pt, tabref(L->env)); >>>> + if (LJ_52) { >>>> + settabV(L, uvval(&gcref(fn->l.uvptr[0])->uv), tabref(L->env)); /* >>>> Set env table to upvalue 1 */ >>>> + } >>>> /* Don't combine above/below into one statement. */ >>>> setfuncV(L, L->top++, fn); >>>> return NULL; >>>> diff --git a/src/lj_parse.c b/src/lj_parse.c >>>> index 29def7b..2f435a5 100644 >>>> --- a/src/lj_parse.c >>>> +++ b/src/lj_parse.c >>>> @@ -1112,6 +1112,12 @@ static MSize var_lookup_(FuncState *fs, GCstr >>>> *name, ExpDesc *e, int first) >>>> fscope_uvmark(fs, reg); /* Scope now has an upvalue. */ >>>> return (MSize)(e->u.s.aux = (uint32_t)fs->varmap[reg]); >>>> } else { >>>> + if (LJ_52 && name == fs->ls->env && fs->prev == NULL) { >>>> + fscope_uvmark(fs,0); >>>> + expr_init(e, VUPVAL, 0); >>>> + e->u.s.aux = 0; >>>> + return 0; >>>> + } >>>> MSize vidx = var_lookup_(fs->prev, name, e, 0); /* Var in outer >>>> func? */ >>>> if ((int32_t)vidx >= 0) { /* Yes, make it an upvalue here. */ >>>> e->u.s.info = (uint8_t)var_lookup_uv(fs, vidx, e); >>>> @@ -1128,7 +1134,9 @@ static MSize var_lookup_(FuncState *fs, GCstr >>>> *name, ExpDesc *e, int first) >>>> >>>> /* Lookup variable name. */ >>>> #define var_lookup(ls, e) \ >>>> - var_lookup_((ls)->fs, lex_str(ls), (e), 1) >>>> + var_lookup_((ls)->fs, lex_str(ls), (e), 1); if (LJ_52 && (e)->k == >>>> VGLOBAL) var_global_((ls), (e)) >>>> + >>>> +static void var_global_(LexState *ls, ExpDesc *e); >>>> >>>> /* -- Goto an label handling >>>> ---------------------------------------------- */ >>>> >>>> @@ -1687,6 +1695,18 @@ static void expr_index(FuncState *fs, ExpDesc >>>> *t, ExpDesc *e) >>>> t->u.s.aux = expr_toanyreg(fs, e); /* 0..255: register */ >>>> } >>>> >>>> +/* Convert global to _ENV index. */ >>>> +static void var_global_(LexState *ls, ExpDesc *e) >>>> +{ >>>> + FuncState *fs = ls->fs; >>>> + ExpDesc key; >>>> + expr_init(&key, VKSTR, 0); >>>> + key.u.sval = e->u.sval; >>>> + var_lookup_(fs, ls->env, e, 1); >>>> + expr_toanyreg(fs, e); >>>> + expr_index(fs, e, &key); >>>> +} >>>> + >>>> /* Parse index expression with named field. */ >>>> static void expr_field(LexState *ls, ExpDesc *v) >>>> { >>>> @@ -2732,6 +2752,16 @@ GCproto *lj_parse(LexState *ls) >>>> fs.bcbase = NULL; >>>> fs.bclim = 0; >>>> fs.flags |= PROTO_VARARG; /* Main chunk is always a vararg func. */ >>>> + >>>> + if (LJ_52) { >>>> + /* Create upvalue named _ENV */ >>>> + ls->env = lj_parse_keepstr(ls, "_ENV", 4); /* Anchor _ENV >>>> string, 4 is sizeof _ENV */ >>>> + var_new(ls, 0, ls->env); >>>> + fs.uvmap[0] = 0; >>>> + fs.uvtmp[0] = 0; >>>> + fs.nuv = 1; >>>> + } >>>> + >>>> fscope_begin(&fs, &bl, 0); >>>> bcemit_AD(&fs, BC_FUNCV, 0, 0); /* Placeholder. */ >>>> lj_lex_next(ls); /* Read-ahead first token. */ >>>> >>>> >>>> -- >>>> http://blog.codingnow.com >>>> >>> >>> Most people just go the other way around -- it's not all that hard to >>> implement setfenv() in terms of _ENV to make Lua 5.2 capable of >>> running Lua 5.1 scripts. >>> >>> /s/ Adam >>> >> >> >> >> -- >> http://blog.codingnow.com >> > -- http://blog.codingnow.com