From 0707e71c6ce9535c08dd3f64897a2987e5706548 Mon Sep 17 00:00:00 2001 From: gamax92 Date: Sun, 11 Aug 2019 12:14:21 +0200 Subject: [PATCH] Support __pairs and __ipairs Added PAIRS and IPAIRS constants to LuaValue Merged pairs and ipairs into one class with a dynamic constructor, this is similar to Lua's pairsmeta function. Check for and call it's specific metamethod if it's available. --- src/core/org/luaj/vm2/LuaValue.java | 10 +++++-- src/core/org/luaj/vm2/lib/BaseLib.java | 37 ++++++++++++++------------ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/core/org/luaj/vm2/LuaValue.java b/src/core/org/luaj/vm2/LuaValue.java index af249516..349044e6 100644 --- a/src/core/org/luaj/vm2/LuaValue.java +++ b/src/core/org/luaj/vm2/LuaValue.java @@ -99,7 +99,7 @@ package org.luaj.vm2; * {@link #INDEX}, {@link #NEWINDEX}, {@link #CALL}, {@link #MODE}, {@link #METATABLE}, * {@link #ADD}, {@link #SUB}, {@link #DIV}, {@link #MUL}, {@link #POW}, * {@link #MOD}, {@link #UNM}, {@link #LEN}, {@link #EQ}, {@link #LT}, - * {@link #LE}, {@link #TOSTRING}, and {@link #CONCAT}. + * {@link #LE}, {@link #TOSTRING}, {@link #CONCAT}, {@link PAIRS} and {@link IPAIRS}. * * @see org.luaj.vm2.lib.jse.JsePlatform * @see org.luaj.vm2.lib.jme.JmePlatform @@ -242,7 +242,13 @@ public class LuaValue extends Varargs { /** LuaString constant with value "__concat" for use as metatag */ public static final LuaString CONCAT = valueOf("__concat"); - + + /** LuaString constant with value "__pairs" for use as metatag */ + public static final LuaString PAIRS = valueOf("__pairs"); + + /** LuaString constant with value "__ipairs" for use as metatag */ + public static final LuaString IPAIRS = valueOf("__ipairs"); + /** LuaString constant with value "" */ public static final LuaString EMPTYSTRING = valueOf(""); diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index d0dbf6b3..cea359b6 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -113,8 +113,8 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { next next; env.set("next", next = new next()); - env.set("pairs", new pairs(next)); - env.set("ipairs", new ipairs()); + env.set("pairs", new pairsbase(PAIRS, NIL, next)); + env.set("ipairs", new pairsbase(IPAIRS, ZERO, new inext())); return env; } @@ -395,23 +395,26 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { } } } - - // "pairs" (t) -> iter-func, t, nil - static final class pairs extends VarArgFunction { - final next next; - pairs(next next) { - this.next = next; + + // pairsbase, // (t) -> iter-func, t, initial + static final class pairsbase extends VarArgFunction { + final LuaString method; + final LuaValue initial; + final VarArgFunction iter; + + pairsbase(LuaString method, LuaValue initial, VarArgFunction iter) { + this.method = method; + this.initial = initial; + this.iter = iter; } + public Varargs invoke(Varargs args) { - return varargsOf( next, args.checktable(1), NIL ); - } - } - - // // "ipairs", // (t) -> iter-func, t, 0 - static final class ipairs extends VarArgFunction { - inext inext = new inext(); - public Varargs invoke(Varargs args) { - return varargsOf( inext, args.checktable(1), ZERO ); + LuaValue arg = args.arg1(); + LuaValue t = arg.metatag(method); + if (!t.isnil()) + // TODO: This can return more than 3 results. + return t.invoke(args.isvalue(1) ? arg : t); + return varargsOf(iter, args.checktable(1), initial); } }