mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-25 23:02:27 +00:00
Bring Lua to 5.4.6. (#1214)
This essentially re-does the work of #875 on top of master. This is what I did to check that Cosmo's Lua extensions still worked: ``` $ build/bootstrap/make MODE=aarch64 o/aarch64/third_party/lua/lua $ ape o/aarch64/third_party/lua/lua >: 10 10 >: 010 8 >: 0b10 2 >: string.byte("\e") 27 >: "Hello, %s" % {"world"} Hello, world >: "*" * 3 *** ``` `luaL_traceback2` was used to show the stack trace with parameter values; it's used in `LuaCallWithTrace`, which is used in Redbean to run Lua code. You should be able to see the extended stack trace by running something like this: `redbean -e "function a(b)c()end a(2)"` (with "params" indicating the extended stack trace): ``` stack traceback: [string "function a(b)c()end a(2)"]:1: in function 'a', params: b = 2; [string "function a(b)c()end a(2)"]:1: in main chunk ``` @pkulchenko confirmed that I get the expected result with the updated code. This is what I did to check that Lua itself still worked: ``` $ cd third_party/lua/test/ $ ape ../../../o/aarch64/third_party/lua/lua all.lua ``` There's one test failure, in `files.lua`: ``` ***** FILE 'files.lua'***** testing i/o ../../../o/aarch64/third_party/lua/lua: files.lua:84: assertion failed! stack traceback: [C]: in function 'assert' files.lua:84: in main chunk (...tail calls...) all.lua:195: in main chunk [C]: in ? .>>> closing state <<< ``` That isn't a result of these changes; the same test is failing in master. The failure is here: ```lua if not _port then -- invalid seek local status, msg, code = io.stdin:seek("set", 1000) assert(not status and type(msg) == "string" and type(code) == "number") end ``` The test expects a seek to offset 1,000 on stdin to fail — but it doesn't. `status` ends up being the new offset rather than `nil`. If I comment out that one test, the remaining tests succeed.
This commit is contained in:
parent
3a599bfbe1
commit
0dbf01bf1d
90 changed files with 2741 additions and 1376 deletions
171
third_party/lua/lcode.c
vendored
171
third_party/lua/lcode.c
vendored
|
@ -3,7 +3,7 @@
|
|||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
│ │
|
||||
│ Lua │
|
||||
│ Copyright © 2004-2021 Lua.org, PUC-Rio. │
|
||||
│ Copyright © 2004-2023 Lua.org, PUC-Rio. │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining │
|
||||
│ a copy of this software and associated documentation files (the │
|
||||
|
@ -27,6 +27,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define lcode_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "third_party/lua/lcode.h"
|
||||
#include "third_party/lua/ldebug.h"
|
||||
|
@ -595,24 +596,41 @@ static int stringK (FuncState *fs, TString *s) {
|
|||
|
||||
/*
|
||||
** Add an integer to list of constants and return its index.
|
||||
** Integers use userdata as keys to avoid collision with floats with
|
||||
** same value; conversion to 'void*' is used only for hashing, so there
|
||||
** are no "precision" problems.
|
||||
*/
|
||||
static int luaK_intK (FuncState *fs, lua_Integer n) {
|
||||
TValue k, o;
|
||||
setpvalue(&k, cast_voidp(cast_sizet(n)));
|
||||
TValue o;
|
||||
setivalue(&o, n);
|
||||
return addk(fs, &k, &o);
|
||||
return addk(fs, &o, &o); /* use integer itself as key */
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a float to list of constants and return its index.
|
||||
** Add a float to list of constants and return its index. Floats
|
||||
** with integral values need a different key, to avoid collision
|
||||
** with actual integers. To that, we add to the number its smaller
|
||||
** power-of-two fraction that is still significant in its scale.
|
||||
** For doubles, that would be 1/2^52.
|
||||
** (This method is not bulletproof: there may be another float
|
||||
** with that value, and for floats larger than 2^53 the result is
|
||||
** still an integer. At worst, this only wastes an entry with
|
||||
** a duplicate.)
|
||||
*/
|
||||
static int luaK_numberK (FuncState *fs, lua_Number r) {
|
||||
TValue o;
|
||||
lua_Integer ik;
|
||||
setfltvalue(&o, r);
|
||||
if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */
|
||||
return addk(fs, &o, &o); /* use number itself as key */
|
||||
else { /* must build an alternative key */
|
||||
const int nbm = l_floatatt(MANT_DIG);
|
||||
const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1);
|
||||
const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */
|
||||
TValue kv;
|
||||
setfltvalue(&kv, k);
|
||||
/* result is not an integral value, unless value is too large */
|
||||
lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) ||
|
||||
l_mathop(fabs)(r) >= l_mathop(1e6));
|
||||
return addk(fs, &kv, &o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1348,6 +1366,35 @@ static int constfolding (FuncState *fs, int op, expdesc *e1,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a BinOpr to an OpCode (ORDER OPR - ORDER OP)
|
||||
*/
|
||||
l_sinline OpCode binopr2op (BinOpr opr, BinOpr baser, OpCode base) {
|
||||
lua_assert(baser <= opr &&
|
||||
((baser == OPR_ADD && opr <= OPR_SHR) ||
|
||||
(baser == OPR_LT && opr <= OPR_LE)));
|
||||
return cast(OpCode, (cast_int(opr) - cast_int(baser)) + cast_int(base));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a UnOpr to an OpCode (ORDER OPR - ORDER OP)
|
||||
*/
|
||||
l_sinline OpCode unopr2op (UnOpr opr) {
|
||||
return cast(OpCode, (cast_int(opr) - cast_int(OPR_MINUS)) +
|
||||
cast_int(OP_UNM));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a BinOpr to a tag method (ORDER OPR - ORDER TM)
|
||||
*/
|
||||
l_sinline TMS binopr2TM (BinOpr opr) {
|
||||
lua_assert(OPR_ADD <= opr && opr <= OPR_SHR);
|
||||
return cast(TMS, (cast_int(opr) - cast_int(OPR_ADD)) + cast_int(TM_ADD));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Emit code for unary expressions that "produce values"
|
||||
** (everything but 'not').
|
||||
|
@ -1386,12 +1433,15 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,
|
|||
** Emit code for binary expressions that "produce values" over
|
||||
** two registers.
|
||||
*/
|
||||
static void codebinexpval (FuncState *fs, OpCode op,
|
||||
static void codebinexpval (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int line) {
|
||||
int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */
|
||||
OpCode op = binopr2op(opr, OPR_ADD, OP_ADD);
|
||||
int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */
|
||||
/* 'e1' must be already in a register or it is a constant */
|
||||
lua_assert((VNIL <= e1->k && e1->k <= VKSTR) ||
|
||||
e1->k == VNONRELOC || e1->k == VRELOC);
|
||||
lua_assert(OP_ADD <= op && op <= OP_SHR);
|
||||
finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN,
|
||||
cast(TMS, (op - OP_ADD) + TM_ADD));
|
||||
finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, binopr2TM(opr));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1407,6 +1457,18 @@ static void codebini (FuncState *fs, OpCode op,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
** Code binary operators with K operand.
|
||||
*/
|
||||
static void codebinK (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int flip, int line) {
|
||||
TMS event = binopr2TM(opr);
|
||||
int v2 = e2->u.info; /* K index */
|
||||
OpCode op = binopr2op(opr, OPR_ADD, OP_ADDK);
|
||||
finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event);
|
||||
}
|
||||
|
||||
|
||||
/* Try to code a binary operator negating its second operand.
|
||||
** For the metamethod, 2nd operand must keep its original value.
|
||||
*/
|
||||
|
@ -1434,24 +1496,27 @@ static void swapexps (expdesc *e1, expdesc *e2) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
** Code binary operators with no constant operand.
|
||||
*/
|
||||
static void codebinNoK (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int flip, int line) {
|
||||
if (flip)
|
||||
swapexps(e1, e2); /* back to original order */
|
||||
codebinexpval(fs, opr, e1, e2, line); /* use standard operators */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Code arithmetic operators ('+', '-', ...). If second operand is a
|
||||
** constant in the proper range, use variant opcodes with K operands.
|
||||
*/
|
||||
static void codearith (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int flip, int line) {
|
||||
TMS event = cast(TMS, opr + TM_ADD);
|
||||
if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */
|
||||
int v2 = e2->u.info; /* K index */
|
||||
OpCode op = cast(OpCode, opr + OP_ADDK);
|
||||
finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event);
|
||||
}
|
||||
else { /* 'e2' is neither an immediate nor a K operand */
|
||||
OpCode op = cast(OpCode, opr + OP_ADD);
|
||||
if (flip)
|
||||
swapexps(e1, e2); /* back to original order */
|
||||
codebinexpval(fs, op, e1, e2, line); /* use standard operators */
|
||||
}
|
||||
if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) /* K operand? */
|
||||
codebinK(fs, opr, e1, e2, flip, line);
|
||||
else /* 'e2' is neither an immediate nor a K operand */
|
||||
codebinNoK(fs, opr, e1, e2, flip, line);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1468,35 +1533,27 @@ static void codecommutative (FuncState *fs, BinOpr op,
|
|||
flip = 1;
|
||||
}
|
||||
if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */
|
||||
codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD);
|
||||
codebini(fs, OP_ADDI, e1, e2, flip, line, TM_ADD);
|
||||
else
|
||||
codearith(fs, op, e1, e2, flip, line);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Code bitwise operations; they are all associative, so the function
|
||||
** Code bitwise operations; they are all commutative, so the function
|
||||
** tries to put an integer constant as the 2nd operand (a K operand).
|
||||
*/
|
||||
static void codebitwise (FuncState *fs, BinOpr opr,
|
||||
expdesc *e1, expdesc *e2, int line) {
|
||||
int flip = 0;
|
||||
int v2;
|
||||
OpCode op;
|
||||
if (e1->k == VKINT && luaK_exp2RK(fs, e1)) {
|
||||
if (e1->k == VKINT) {
|
||||
swapexps(e1, e2); /* 'e2' will be the constant operand */
|
||||
flip = 1;
|
||||
}
|
||||
else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */
|
||||
op = cast(OpCode, opr + OP_ADD);
|
||||
codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */
|
||||
return;
|
||||
}
|
||||
v2 = e2->u.info; /* index in K array */
|
||||
op = cast(OpCode, opr + OP_ADDK);
|
||||
lua_assert(ttisinteger(&fs->f->k[v2]));
|
||||
finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK,
|
||||
cast(TMS, opr + TM_ADD));
|
||||
if (e2->k == VKINT && luaK_exp2K(fs, e2)) /* K operand? */
|
||||
codebinK(fs, opr, e1, e2, flip, line);
|
||||
else /* no constants */
|
||||
codebinNoK(fs, opr, e1, e2, flip, line);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1504,25 +1561,27 @@ static void codebitwise (FuncState *fs, BinOpr opr,
|
|||
** Emit code for order comparisons. When using an immediate operand,
|
||||
** 'isfloat' tells whether the original value was a float.
|
||||
*/
|
||||
static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
|
||||
static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
|
||||
int r1, r2;
|
||||
int im;
|
||||
int isfloat = 0;
|
||||
OpCode op;
|
||||
if (isSCnumber(e2, &im, &isfloat)) {
|
||||
/* use immediate operand */
|
||||
r1 = luaK_exp2anyreg(fs, e1);
|
||||
r2 = im;
|
||||
op = cast(OpCode, (op - OP_LT) + OP_LTI);
|
||||
op = binopr2op(opr, OPR_LT, OP_LTI);
|
||||
}
|
||||
else if (isSCnumber(e1, &im, &isfloat)) {
|
||||
/* transform (A < B) to (B > A) and (A <= B) to (B >= A) */
|
||||
r1 = luaK_exp2anyreg(fs, e2);
|
||||
r2 = im;
|
||||
op = (op == OP_LT) ? OP_GTI : OP_GEI;
|
||||
op = binopr2op(opr, OPR_LT, OP_GTI);
|
||||
}
|
||||
else { /* regular case, compare two registers */
|
||||
r1 = luaK_exp2anyreg(fs, e1);
|
||||
r2 = luaK_exp2anyreg(fs, e2);
|
||||
op = binopr2op(opr, OPR_LT, OP_LT);
|
||||
}
|
||||
freeexps(fs, e1, e2);
|
||||
e1->u.info = condjump(fs, op, r1, r2, isfloat, 1);
|
||||
|
@ -1548,7 +1607,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
|
|||
op = OP_EQI;
|
||||
r2 = im; /* immediate operand */
|
||||
}
|
||||
else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */
|
||||
else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */
|
||||
op = OP_EQK;
|
||||
r2 = e2->u.info; /* constant index */
|
||||
}
|
||||
|
@ -1565,16 +1624,16 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
|
|||
/*
|
||||
** Apply prefix operation 'op' to expression 'e'.
|
||||
*/
|
||||
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
|
||||
void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) {
|
||||
static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP};
|
||||
luaK_dischargevars(fs, e);
|
||||
switch (op) {
|
||||
switch (opr) {
|
||||
case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */
|
||||
if (constfolding(fs, op + LUA_OPUNM, e, &ef))
|
||||
if (constfolding(fs, opr + LUA_OPUNM, e, &ef))
|
||||
break;
|
||||
/* else */ /* FALLTHROUGH */
|
||||
case OPR_LEN:
|
||||
codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line);
|
||||
codeunexpval(fs, unopr2op(opr), e, line);
|
||||
break;
|
||||
case OPR_NOT: codenot(fs, e); break;
|
||||
default: lua_assert(0);
|
||||
|
@ -1608,7 +1667,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
|
|||
case OPR_SHL: case OPR_SHR: {
|
||||
if (!tonumeral(v, NULL))
|
||||
luaK_exp2anyreg(fs, v);
|
||||
/* else keep numeral, which may be folded with 2nd operand */
|
||||
/* else keep numeral, which may be folded or used as an immediate
|
||||
operand */
|
||||
break;
|
||||
}
|
||||
case OPR_EQ: case OPR_NE: {
|
||||
|
@ -1703,30 +1763,27 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
|
|||
/* coded as (r1 >> -I) */;
|
||||
}
|
||||
else /* regular case (two registers) */
|
||||
codebinexpval(fs, OP_SHL, e1, e2, line);
|
||||
codebinexpval(fs, opr, e1, e2, line);
|
||||
break;
|
||||
}
|
||||
case OPR_SHR: {
|
||||
if (isSCint(e2))
|
||||
codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */
|
||||
else /* regular case (two registers) */
|
||||
codebinexpval(fs, OP_SHR, e1, e2, line);
|
||||
codebinexpval(fs, opr, e1, e2, line);
|
||||
break;
|
||||
}
|
||||
case OPR_EQ: case OPR_NE: {
|
||||
codeeq(fs, opr, e1, e2);
|
||||
break;
|
||||
}
|
||||
case OPR_LT: case OPR_LE: {
|
||||
OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ);
|
||||
codeorder(fs, op, e1, e2);
|
||||
break;
|
||||
}
|
||||
case OPR_GT: case OPR_GE: {
|
||||
/* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */
|
||||
OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ);
|
||||
swapexps(e1, e2);
|
||||
codeorder(fs, op, e1, e2);
|
||||
opr = cast(BinOpr, (opr - OPR_GT) + OPR_LT);
|
||||
} /* FALLTHROUGH */
|
||||
case OPR_LT: case OPR_LE: {
|
||||
codeorder(fs, opr, e1, e2);
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue