Skip to content

Commit

Permalink
Update to Lua 5.2
Browse files Browse the repository at this point in the history
Yes, I could do this in multiple commits. Or I could chuck it in one
horrifying mess!
  • Loading branch information
SquidDev committed Nov 1, 2023
1 parent dc245ed commit 9f03b7c
Show file tree
Hide file tree
Showing 91 changed files with 1,504 additions and 1,151 deletions.
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group = "org.squiddev"
version = "0.7.3"
version = "0.8.0-SNAPSHOT"

java {
toolchain {
Expand Down Expand Up @@ -120,7 +120,7 @@ publishing {

pom {
name.set("Cobalt")
description.set("A reentrant fork of LuaJ for Lua 5.1")
description.set("A reentrant fork of LuaJ for Lua 5.2")
url.set("https://github.com/SquidDev/Cobalt")

scm {
Expand Down
55 changes: 55 additions & 0 deletions src/main/java/cc/tweaked/cobalt/internal/LegacyEnv.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cc.tweaked.cobalt.internal;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.squiddev.cobalt.Constants;
import org.squiddev.cobalt.LuaTable;
import org.squiddev.cobalt.LuaValue;
import org.squiddev.cobalt.Prototype;
import org.squiddev.cobalt.debug.Upvalue;
import org.squiddev.cobalt.function.LuaClosure;

import java.util.Objects;

/**
* Utilities for working with Lua 5.1-style {@code getfenv}/{@code setfenv}.
* <p>
* These simply search for an {@link Constants#ENV _ENV} upvalue and set it.
*/
public final class LegacyEnv {
private LegacyEnv() {
}

private static int findEnv(Prototype prototype) {
for (int i = 0; i < prototype.upvalues(); i++) {
if (Objects.equals(prototype.getUpvalueName(i), Constants.ENV)) return i;
}

return -1;
}

public static @Nullable LuaTable getEnv(LuaClosure closure) {
int index = findEnv(closure.getPrototype());
return index >= 0 && closure.getUpvalue(index).getValue() instanceof LuaTable t ? t : null;
}

public static @Nullable LuaTable getEnv(LuaValue value) {
return value instanceof LuaClosure c ? getEnv(c) : null;
}

public static void setEnv(LuaClosure closure, LuaTable env) {
int index = findEnv(closure.getPrototype());
if (index >= 0) {
// Slightly odd to create a new upvalue here, but ensures that it only affects this function.
closure.setUpvalue(index, new Upvalue(env));
}
}

public static boolean setEnv(LuaValue value, LuaTable env) {
if (!(value instanceof LuaClosure c)) return false;

setEnv(c, env);
// We always return true on Lua closures, even if technically this won't do anything, as it ensures somewhat
// consistent behaviour.
return true;
}
}
5 changes: 5 additions & 0 deletions src/main/java/org/squiddev/cobalt/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ public class Constants {
*/
public static final LuaString LOADED = valueOf("_LOADED");

/**
* LuaString constant with value "_ENV" for use as metatag
*/
public static final LuaString ENV = valueOf("_ENV");

/**
* Constant limiting metatag loop processing
*/
Expand Down
137 changes: 73 additions & 64 deletions src/main/java/org/squiddev/cobalt/Lua.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,14 @@ public class Lua {
*/
public static final int LUA_MULTRET = -1;

/**
* Masks for new-style vararg
*/
public static final int VARARG_HASARG = 1;
public static final int VARARG_ISVARARG = 2;
public static final int VARARG_NEEDSARG = 4;

/*===========================================================================
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
`A' : 8 bits
`B' : 9 bits
`C' : 9 bits
'Ax' : 26 bits ('A', 'B', and 'C' together)
`Bx' : 18 bits (`B' and `C' together)
`sBx' : signed Bx
Expand All @@ -64,12 +58,14 @@ public class Lua {
public static final int iABC = 0;
public static final int iABx = 1;
public static final int iAsBx = 2;
public static final int iAx = 3;

// Size and position of opcode arguments.
public static final int SIZE_C = 9;
public static final int SIZE_B = 9;
public static final int SIZE_Bx = SIZE_C + SIZE_B;
public static final int SIZE_A = 8;
public static final int SIZE_Ax = SIZE_A + SIZE_B + SIZE_C;

public static final int SIZE_OP = 6;

Expand All @@ -78,20 +74,23 @@ public class Lua {
public static final int POS_C = POS_A + SIZE_A;
public static final int POS_B = POS_C + SIZE_C;
public static final int POS_Bx = POS_C;
public static final int POS_Ax = POS_A;

// Limits for opcode arguments.
public static final int MAX_OP = (1 << Lua.SIZE_OP) - 1;
public static final int MAXARG_A = (1 << Lua.SIZE_A) - 1;
public static final int MAXARG_B = (1 << Lua.SIZE_B) - 1;
public static final int MAXARG_C = (1 << Lua.SIZE_C) - 1;
public static final int MAXARG_Bx = (1 << Lua.SIZE_Bx) - 1;
public static final int MAX_OP = (1 << SIZE_OP) - 1;
public static final int MAXARG_A = (1 << SIZE_A) - 1;
public static final int MAXARG_B = (1 << SIZE_B) - 1;
public static final int MAXARG_C = (1 << SIZE_C) - 1;
public static final int MAXARG_Bx = (1 << SIZE_Bx) - 1;
public static final int MAXARG_sBx = MAXARG_Bx >> 1; // sBx' is signed
public static final int MAXARG_Ax = (1 << SIZE_Ax) - 1;

public static final int MASK_OP = ((1 << Lua.SIZE_OP) - 1) << Lua.POS_OP;
public static final int MASK_A = ((1 << Lua.SIZE_A) - 1) << Lua.POS_A;
public static final int MASK_B = ((1 << Lua.SIZE_B) - 1) << Lua.POS_B;
public static final int MASK_C = ((1 << Lua.SIZE_C) - 1) << Lua.POS_C;
public static final int MASK_Bx = ((1 << Lua.SIZE_Bx) - 1) << Lua.POS_Bx;
public static final int MASK_OP = ((1 << SIZE_OP) - 1) << POS_OP;
public static final int MASK_A = ((1 << SIZE_A) - 1) << POS_A;
public static final int MASK_B = ((1 << SIZE_B) - 1) << POS_B;
public static final int MASK_C = ((1 << SIZE_C) - 1) << POS_C;
public static final int MASK_Bx = ((1 << SIZE_Bx) - 1) << POS_Bx;
public static final int MASK_Ax = ((1 << SIZE_Ax) - 1) << POS_Ax;

// Utilities for reading instructions.

Expand Down Expand Up @@ -119,6 +118,9 @@ public static int GETARG_sBx(int i) {
return ((i >> POS_Bx) & MAXARG_Bx) - MAXARG_sBx;
}

public static int GETARG_Ax(int i) {
return (i >> POS_Ax) & MAXARG_Ax;
}

/**
* This bit 1 means constant (0 means register)
Expand Down Expand Up @@ -159,7 +161,7 @@ public static int RKASK(int x) {
/**
* Invalid register that fits in 8 bits
*/
public static final int NO_REG = Lua.MAXARG_A;
public static final int NO_REG = MAXARG_A;

/*
** R(x) - register
Expand All @@ -168,57 +170,60 @@ public static int RKASK(int x) {
*/
public static final int OP_MOVE = 0; // A B R(A) := R(B)
public static final int OP_LOADK = 1; // A Bx R(A) := Kst(Bx)
public static final int OP_LOADBOOL = 2; // A B C R(A) := (Bool)B; if (C) pc++
public static final int OP_LOADNIL = 3; // A B R(A) := ... := R(B) := nil
public static final int OP_GETUPVAL = 4; // A B R(A) := UpValue[B]
public static final int OP_LOADKX = 2; // A R(A) := Kst(extra arg)
public static final int OP_LOADBOOL = 3; // A B C R(A) := (Bool)B; if (C) pc++
public static final int OP_LOADNIL = 4; // A B R(A), R(A+1), ..., R(A+B) := nil
public static final int OP_GETUPVAL = 5; // A B R(A) := UpValue[B]

public static final int OP_GETTABUP = 6; // A B C R(A) := UpValue[B][RK(C)]
public static final int OP_GETTABLE = 7; // A B C R(A) := R(B)[RK(C)]

public static final int OP_GETGLOBAL = 5; // A Bx R(A) := Gbl[Kst(Bx)]
public static final int OP_GETTABLE = 6; // A B C R(A) := R(B)[RK(C)]
public static final int OP_SETTABUP = 8; // A B C UpValue[A][RK(B)] := RK(C)
public static final int OP_SETUPVAL = 9; // A B UpValue[B] := R(A)
public static final int OP_SETTABLE = 10; // A B C R(A)[RK(B)] := RK(C)

public static final int OP_SETGLOBAL = 7; // A Bx Gbl[Kst(Bx)] := R(A)
public static final int OP_SETUPVAL = 8; // A B UpValue[B] := R(A)
public static final int OP_SETTABLE = 9; // A B C R(A)[RK(B)] := RK(C)
public static final int OP_NEWTABLE = 11; // A B C R(A) := {} (size = B,C)

public static final int OP_NEWTABLE = 10; // A B C R(A) := {} (size = B,C)
public static final int OP_SELF = 12; // A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]

public static final int OP_SELF = 11; // A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]
public static final int OP_ADD = 13; // A B C R(A) := RK(B) + RK(C)
public static final int OP_SUB = 14; // A B C R(A) := RK(B) - RK(C)
public static final int OP_MUL = 15; // A B C R(A) := RK(B) * RK(C)
public static final int OP_DIV = 16; // A B C R(A) := RK(B) / RK(C)
public static final int OP_MOD = 17; // A B C R(A) := RK(B) % RK(C)
public static final int OP_POW = 18; // A B C R(A) := RK(B) ^ RK(C)
public static final int OP_UNM = 19; // A B R(A) := -R(B)
public static final int OP_NOT = 20; // A B R(A) := not R(B)
public static final int OP_LEN = 21; // A B R(A) := length of R(B)

public static final int OP_ADD = 12; // A B C R(A) := RK(B) + RK(C)
public static final int OP_SUB = 13; // A B C R(A) := RK(B) - RK(C)
public static final int OP_MUL = 14; // A B C R(A) := RK(B) * RK(C)
public static final int OP_DIV = 15; // A B C R(A) := RK(B) / RK(C)
public static final int OP_MOD = 16; // A B C R(A) := RK(B) % RK(C)
public static final int OP_POW = 17; // A B C R(A) := RK(B) ^ RK(C)
public static final int OP_UNM = 18; // A B R(A) := -R(B)
public static final int OP_NOT = 19; // A B R(A) := not R(B)
public static final int OP_LEN = 20; // A B R(A) := length of R(B)
public static final int OP_CONCAT = 22; // A B C R(A) := R(B).. ... ..R(C)

public static final int OP_CONCAT = 21; // A B C R(A) := R(B).. ... ..R(C)
public static final int OP_JMP = 23; // A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1)
public static final int OP_EQ = 24; // A B C if ((RK(B) == RK(C)) ~= A) then pc++
public static final int OP_LT = 25; // A B C if ((RK(B) < RK(C)) ~= A) then pc++
public static final int OP_LE = 26; // A B C if ((RK(B) <= RK(C)) ~= A) then pc++

public static final int OP_JMP = 22; // sBx pc+=sBx
public static final int OP_TEST = 27; // A C if not (R(A) <=> C) then pc++
public static final int OP_TESTSET = 28; // A B C if (R(B) <=> C) then R(A) := R(B) else pc++

public static final int OP_EQ = 23; // A B C if ((RK(B) == RK(C)) ~= A) then pc++
public static final int OP_LT = 24; // A B C if ((RK(B) < RK(C)) ~= A) then pc++
public static final int OP_LE = 25; // A B C if ((RK(B) <= RK(C)) ~= A) then pc++
public static final int OP_CALL = 29; // A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
public static final int OP_TAILCALL = 30; // A B C return R(A)(R(A+1), ... ,R(A+B-1))
public static final int OP_RETURN = 31; // A B return R(A), ... ,R(A+B-2) (see note)

public static final int OP_TEST = 26; // A C if not (R(A) <=> C) then pc++ *
public static final int OP_TESTSET = 27; // A B C if (R(B) <=> C) then R(A) := R(B) else pc++ *
public static final int OP_FORLOOP = 32; // A sBx R(A)+=R(A+2; if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
public static final int OP_FORPREP = 33; // A sBx R(A)-=R(A+2); pc+=sBx

public static final int OP_CALL = 28; // A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
public static final int OP_TAILCALL = 29; // A B C return R(A)(R(A+1), ... ,R(A+B-1))
public static final int OP_RETURN = 30; // A B return R(A), ... ,R(A+B-2) (see note)
public static final int OP_TFORCALL = 34; // A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
public static final int OP_TFORLOOP = 35; // A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }

public static final int OP_FORLOOP = 31; // A sBx R(A)+=R(A+2; if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
public static final int OP_FORPREP = 32; // A sBx R(A)-=R(A+2); pc+=sBx
public static final int OP_SETLIST = 36; // A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B

public static final int OP_TFORLOOP = 33; // A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
public static final int OP_SETLIST = 34; // A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
public static final int OP_CLOSURE = 37; // A Bx R(A) := closure(KPROTO[Bx])

public static final int OP_CLOSE = 35; // A close all variables in the stack up to (>=) R(A)
public static final int OP_CLOSURE = 36; // A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))
public static final int OP_VARARG = 38; // A B R(A), R(A+1), ..., R(A+B-2) = vararg

public static final int OP_VARARG = 37; // A B R(A), R(A+1), ..., R(A+B-1) = vararg
public static final int NUM_OPCODES = OP_VARARG + 1;
public static final int OP_EXTRAARG = 39; // Ax extra (larger) argument for previous opcode
public static final int NUM_OPCODES = OP_EXTRAARG + 1;

/*===========================================================================
Notes:
Expand Down Expand Up @@ -262,12 +267,13 @@ private static int opmode(int t, int a, int b, int c, int m) {
public static final int[] opmodes = {
opmode(0, 1, OpArgR, OpArgN, iABC), // OP_MOVE
opmode(0, 1, OpArgK, OpArgN, iABx), // OP_LOADK
opmode(0, 1, OpArgN, OpArgN, iABx), // OP_LOADKX
opmode(0, 1, OpArgU, OpArgU, iABC), // OP_LOADBOOL
opmode(0, 1, OpArgR, OpArgN, iABC), // OP_LOADNIL
opmode(0, 1, OpArgU, OpArgN, iABC), // OP_LOADNIL
opmode(0, 1, OpArgU, OpArgN, iABC), // OP_GETUPVAL
opmode(0, 1, OpArgK, OpArgN, iABx), // OP_GETGLOBAL
opmode(0, 1, OpArgU, OpArgK, iABC), // OP_GETTABUP
opmode(0, 1, OpArgR, OpArgK, iABC), // OP_GETTABLE
opmode(0, 0, OpArgK, OpArgN, iABx), // OP_SETGLOBAL
opmode(0, 0, OpArgK, OpArgK, iABC), // OP_SETTABUP
opmode(0, 0, OpArgU, OpArgN, iABC), // OP_SETUPVAL
opmode(0, 0, OpArgK, OpArgK, iABC), // OP_SETTABLE
opmode(0, 1, OpArgU, OpArgU, iABC), // OP_NEWTABLE
Expand All @@ -286,18 +292,19 @@ private static int opmode(int t, int a, int b, int c, int m) {
opmode(1, 0, OpArgK, OpArgK, iABC), // OP_EQ
opmode(1, 0, OpArgK, OpArgK, iABC), // OP_LT
opmode(1, 0, OpArgK, OpArgK, iABC), // OP_LE
opmode(1, 1, OpArgR, OpArgU, iABC), // OP_TEST
opmode(1, 0, OpArgN, OpArgU, iABC), // OP_TEST
opmode(1, 1, OpArgR, OpArgU, iABC), // OP_TESTSET
opmode(0, 1, OpArgU, OpArgU, iABC), // OP_CALL
opmode(0, 1, OpArgU, OpArgU, iABC), // OP_TAILCALL
opmode(0, 0, OpArgU, OpArgN, iABC), // OP_RETURN
opmode(0, 1, OpArgR, OpArgN, iAsBx), // OP_FORLOOP
opmode(0, 1, OpArgR, OpArgN, iAsBx), // OP_FORPREP
opmode(1, 0, OpArgN, OpArgU, iABC), // OP_TFORLOOP
opmode(0, 0, OpArgN, OpArgU, iABC), // OP_TFORCALL
opmode(0, 1, OpArgR, OpArgN, iAsBx), // OP_TFORLOOP
opmode(0, 0, OpArgU, OpArgU, iABC), // OP_SETLIST
opmode(0, 0, OpArgN, OpArgN, iABC), // OP_CLOSE
opmode(0, 1, OpArgU, OpArgN, iABx), // OP_CLOSURE
opmode(0, 1, OpArgU, OpArgN, iABC), // OP_VARARG
opmode(0, 0, OpArgU, OpArgU, iAx), // OP_EXTRAARG
};

public static int getOpMode(int m) {
Expand Down Expand Up @@ -328,12 +335,13 @@ public static boolean testTMode(int m) {
private static final String[] opcodeNames = {
"MOVE",
"LOADK",
"LOADKX",
"LOADBOOL",
"LOADNIL",
"GETUPVAL",
"GETGLOBAL",
"GETTABUP",
"GETTABLE",
"SETGLOBAL",
"SETTABUP",
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
Expand All @@ -359,11 +367,12 @@ public static boolean testTMode(int m) {
"RETURN",
"FORLOOP",
"FORPREP",
"TFORCALL",
"TFORLOOP",
"SETLIST",
"CLOSE",
"CLOSURE",
"VARARG",
"EXTRAARG",
};

public static String getOpName(int opcode) {
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/org/squiddev/cobalt/LuaState.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public final class LuaState {
*/
private final LuaThread mainThread;

private final LuaTable globals = new LuaTable();

/**
* Report an internal VM error.
*/
Expand All @@ -106,7 +108,16 @@ private LuaState(Builder builder) {
reportError = builder.reportError;
bytecodeFormat = builder.bytecodeFormat;

mainThread = currentThread = new LuaThread(this, new LuaTable());
mainThread = currentThread = new LuaThread(this);
}

/**
* Get the global environment.
*
* @return The global environment.
*/
public LuaTable globals() {
return globals;
}

/**
Expand Down
Loading

0 comments on commit 9f03b7c

Please sign in to comment.