From f40e89e19c7001ef8b0f4aefb16cfe3bfb00e883 Mon Sep 17 00:00:00 2001 From: UnlegitDqrk Date: Sun, 1 Mar 2026 12:39:42 +0100 Subject: [PATCH] Implemented Support of Java 21 VirtualThread --- .classpath | 19 - .idea/.gitignore | 10 + .idea/compiler.xml | 16 + .idea/discord.xml | 7 + .idea/encodings.xml | 13 + .idea/jarRepositories.xml | 25 + .idea/luaj.iml | 9 + .idea/misc.xml | 18 + .idea/vcs.xml | 6 + .project | 17 - README.md | 11 - build-app.xml | 108 -- build-applet.xml | 116 -- build-coverage.xml | 119 -- build-libs.xml | 56 - build-maven.xml | 176 -- build-midlet.xml | 113 -- build-perf.xml | 68 - build.xml | 212 --- core/pom.xml | 36 + .../src/main/java}/org/luaj/vm2/Buffer.java | 0 .../src/main/java}/org/luaj/vm2/Globals.java | 0 .../main/java}/org/luaj/vm2/LoadState.java | 0 .../src/main/java}/org/luaj/vm2/LocVars.java | 0 .../src/main/java}/org/luaj/vm2/Lua.java | 0 .../main/java}/org/luaj/vm2/LuaBoolean.java | 0 .../main/java}/org/luaj/vm2/LuaClosure.java | 4 +- .../main/java}/org/luaj/vm2/LuaDouble.java | 0 .../src/main/java}/org/luaj/vm2/LuaError.java | 0 .../main/java}/org/luaj/vm2/LuaFunction.java | 0 .../main/java}/org/luaj/vm2/LuaInteger.java | 0 .../src/main/java}/org/luaj/vm2/LuaNil.java | 0 .../main/java}/org/luaj/vm2/LuaNumber.java | 0 .../main/java}/org/luaj/vm2/LuaString.java | 0 .../src/main/java}/org/luaj/vm2/LuaTable.java | 0 .../src/main/java/org/luaj/vm2/LuaThread.java | 309 ++++ .../main/java}/org/luaj/vm2/LuaUserdata.java | 0 .../src/main/java}/org/luaj/vm2/LuaValue.java | 30 +- .../main/java}/org/luaj/vm2/Metatable.java | 0 .../java}/org/luaj/vm2/NonTableMetatable.java | 0 .../java}/org/luaj/vm2/OrphanedThread.java | 2 +- .../src/main/java}/org/luaj/vm2/Print.java | 0 .../main/java}/org/luaj/vm2/Prototype.java | 0 .../java}/org/luaj/vm2/TailcallVarargs.java | 0 .../src/main/java}/org/luaj/vm2/UpValue.java | 0 .../main/java}/org/luaj/vm2/Upvaldesc.java | 0 .../src/main/java}/org/luaj/vm2/Varargs.java | 2 +- .../main/java}/org/luaj/vm2/WeakTable.java | 0 .../org/luaj/vm2/compiler/Constants.java | 0 .../org/luaj/vm2/compiler/DumpState.java | 2 +- .../org/luaj/vm2/compiler/FuncState.java | 764 ++++---- .../org/luaj/vm2/compiler/InstructionPtr.java | 0 .../java}/org/luaj/vm2/compiler/IntPtr.java | 0 .../java}/org/luaj/vm2/compiler/LexState.java | 1530 ++++++++--------- .../java}/org/luaj/vm2/compiler/LuaC.java | 2 +- .../buildOutputCleanup.lock | Bin 0 -> 17 bytes .../buildOutputCleanup/cache.properties | 2 + .../android/.gradle/vcs-1/gc.properties | 0 examples/maven/pom.xml | 21 +- jme/pom.xml | 122 ++ .../openautonomousconnection/luaj/Main.java | 17 + jse/pom.xml | 134 ++ {src/jse => jse/src/main/java}/lua.java | 0 {src/jse => jse/src/main/java}/luac.java | 0 {src/jse => jse/src/main/java}/luajc.java | 0 .../main/java}/org/luaj/vm2/ast/Block.java | 0 .../main/java}/org/luaj/vm2/ast/Chunk.java | 0 .../src/main/java}/org/luaj/vm2/ast/Exp.java | 0 .../main/java}/org/luaj/vm2/ast/FuncArgs.java | 0 .../main/java}/org/luaj/vm2/ast/FuncBody.java | 0 .../main/java}/org/luaj/vm2/ast/FuncName.java | 0 .../src/main/java}/org/luaj/vm2/ast/Name.java | 0 .../java}/org/luaj/vm2/ast/NameResolver.java | 0 .../java}/org/luaj/vm2/ast/NameScope.java | 0 .../main/java}/org/luaj/vm2/ast/ParList.java | 0 .../src/main/java}/org/luaj/vm2/ast/Stat.java | 0 .../src/main/java}/org/luaj/vm2/ast/Str.java | 0 .../java}/org/luaj/vm2/ast/SyntaxElement.java | 0 .../org/luaj/vm2/ast/TableConstructor.java | 0 .../java}/org/luaj/vm2/ast/TableField.java | 0 .../main/java}/org/luaj/vm2/ast/Variable.java | 0 .../main/java}/org/luaj/vm2/ast/Visitor.java | 2 +- .../java}/org/luaj/vm2/luajc/BasicBlock.java | 0 .../java}/org/luaj/vm2/luajc/JavaBuilder.java | 0 .../java}/org/luaj/vm2/luajc/JavaGen.java | 0 .../java}/org/luaj/vm2/luajc/JavaLoader.java | 0 .../main/java}/org/luaj/vm2/luajc/LuaJC.java | 4 +- .../java}/org/luaj/vm2/luajc/ProtoInfo.java | 0 .../java}/org/luaj/vm2/luajc/UpvalInfo.java | 0 .../java}/org/luaj/vm2/luajc/VarInfo.java | 0 .../java}/org/luaj/vm2/parser/LuaParser.java | 6 +- .../luaj/vm2/parser/LuaParserConstants.java | 0 .../vm2/parser/LuaParserTokenManager.java | 0 .../org/luaj/vm2/parser/ParseException.java | 0 .../org/luaj/vm2/parser/SimpleCharStream.java | 0 .../main/java}/org/luaj/vm2/parser/Token.java | 0 .../org/luaj/vm2/parser/TokenMgrError.java | 0 .../org/luaj/vm2/script/LuaScriptEngine.java | 182 +- .../vm2/script/LuaScriptEngineFactory.java | 0 .../org/luaj/vm2/script/LuajContext.java | 0 .../org/luaj/vm2/server/DefaultLauncher.java | 0 .../java}/org/luaj/vm2/server/Launcher.java | 0 .../org/luaj/vm2/server/LuajClassLoader.java | 0 .../services/javax.script.ScriptEngineFactory | 0 .../java/org/luaj/luajc/SampleMainChunk.java | 0 .../test}/java/org/luaj/luajc/TestLuaJ.java | 0 .../test}/java/org/luaj/luajc/TestLuaJC.java | 0 .../src/test/java}/org/luaj/vm2/AllTests.java | 0 .../org/luaj/vm2/BufferedStreamTest.java | 0 .../java}/org/luaj/vm2/CompatibiltyTest.java | 6 +- .../test/java}/org/luaj/vm2/ErrorsTest.java | 2 +- .../java}/org/luaj/vm2/FragmentsTest.java | 0 .../java}/org/luaj/vm2/LoadOrderTest.java | 0 .../java}/org/luaj/vm2/LuaOperationsTest.java | 0 .../test/java}/org/luaj/vm2/MathLibTest.java | 0 .../java}/org/luaj/vm2/MetatableTest.java | 0 .../org/luaj/vm2/OrphanedThreadTest.java | 0 .../java}/org/luaj/vm2/RequireClassTest.java | 0 .../java}/org/luaj/vm2/ScriptDrivenTest.java | 0 .../test/java}/org/luaj/vm2/StringTest.java | 0 .../java}/org/luaj/vm2/TableHashTest.java | 0 .../test/java}/org/luaj/vm2/TableTest.java | 4 +- .../src/test/java}/org/luaj/vm2/TypeTest.java | 0 .../java}/org/luaj/vm2/UTF8StreamTest.java | 0 .../luaj/vm2/UnaryBinaryOperatorsTest.java | 0 .../test/java}/org/luaj/vm2/VarargsTest.java | 0 .../java}/org/luaj/vm2/WeakTableTest.java | 0 .../luaj/vm2/compiler/AbstractUnitTests.java | 16 +- .../luaj/vm2/compiler/CompilerUnitTests.java | 0 .../vm2/compiler/DumpLoadEndianIntTest.java | 20 +- .../org/luaj/vm2/compiler/LuaParserTests.java | 7 +- .../luaj/vm2/compiler/RegressionTests.java | 0 .../org/luaj/vm2/compiler/SimpleTests.java | 1 - .../require/RequireSampleClassCastExcep.java | 0 .../require/RequireSampleLoadLuaError.java | 0 .../RequireSampleLoadRuntimeExcep.java | 0 .../vm2/require/RequireSampleSuccess.java | 0 .../luaj/vm2/script/ScriptEngineTests.java | 0 pom.xml | 149 ++ src/core/org/luaj/vm2/LuaThread.java | 260 --- src/core/org/luaj/vm2/lib/BaseLib.java | 485 ------ src/core/org/luaj/vm2/lib/Bit32Lib.java | 224 --- src/core/org/luaj/vm2/lib/CoroutineLib.java | 144 -- src/core/org/luaj/vm2/lib/DebugLib.java | 899 ---------- src/core/org/luaj/vm2/lib/IoLib.java | 684 -------- src/core/org/luaj/vm2/lib/LibFunction.java | 222 --- src/core/org/luaj/vm2/lib/MathLib.java | 306 ---- src/core/org/luaj/vm2/lib/OneArgFunction.java | 72 - src/core/org/luaj/vm2/lib/OsLib.java | 524 ------ src/core/org/luaj/vm2/lib/PackageLib.java | 381 ---- src/core/org/luaj/vm2/lib/ResourceFinder.java | 59 - src/core/org/luaj/vm2/lib/StringLib.java | 1223 ------------- src/core/org/luaj/vm2/lib/TableLib.java | 158 -- .../org/luaj/vm2/lib/TableLibFunction.java | 9 - .../org/luaj/vm2/lib/ThreeArgFunction.java | 73 - src/core/org/luaj/vm2/lib/TwoArgFunction.java | 73 - src/core/org/luaj/vm2/lib/VarArgFunction.java | 83 - .../org/luaj/vm2/lib/ZeroArgFunction.java | 70 - src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java | 230 --- src/jme/org/luaj/vm2/lib/jme/JmePlatform.java | 135 -- .../org/luaj/vm2/lib/jse/CoerceJavaToLua.java | 196 --- .../org/luaj/vm2/lib/jse/CoerceLuaToJava.java | 372 ---- src/jse/org/luaj/vm2/lib/jse/JavaArray.java | 86 - src/jse/org/luaj/vm2/lib/jse/JavaClass.java | 153 -- .../org/luaj/vm2/lib/jse/JavaConstructor.java | 116 -- .../org/luaj/vm2/lib/jse/JavaInstance.java | 82 - src/jse/org/luaj/vm2/lib/jse/JavaMember.java | 84 - src/jse/org/luaj/vm2/lib/jse/JavaMethod.java | 163 -- src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java | 116 -- src/jse/org/luaj/vm2/lib/jse/JseIoLib.java | 343 ---- src/jse/org/luaj/vm2/lib/jse/JseMathLib.java | 120 -- src/jse/org/luaj/vm2/lib/jse/JseOsLib.java | 135 -- src/jse/org/luaj/vm2/lib/jse/JsePlatform.java | 143 -- src/jse/org/luaj/vm2/lib/jse/JseProcess.java | 132 -- .../org/luaj/vm2/lib/jse/JseStringLib.java | 39 - src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java | 214 --- .../org/luaj/vm2/lib/jse/JsePlatformTest.java | 21 - .../luaj/vm2/lib/jse/LuaJavaCoercionTest.java | 446 ----- .../lib/jse/LuajavaAccessibleMembersTest.java | 68 - .../vm2/lib/jse/LuajavaClassMembersTest.java | 238 --- .../junit/org/luaj/vm2/lib/jse/OsLibTest.java | 78 - .../junit/org/luaj/vm2/lib/jse/TestClass.java | 22 - .../org/luaj/vm2/lib/jse/TestInterface.java | 5 - test/lua/baselib.lua | 277 --- test/lua/coroutinelib.lua | 126 -- test/lua/debuglib.lua | 280 --- test/lua/errors.lua | 137 -- test/lua/errors/args.lua | 198 --- test/lua/errors/baselibargs.lua | 145 -- test/lua/errors/coroutinelibargs.lua | 47 - test/lua/errors/debuglibargs.lua | 150 -- test/lua/errors/iolibargs.lua | 85 - test/lua/errors/mathlibargs.lua | 112 -- test/lua/errors/modulelibargs.lua | 21 - test/lua/errors/operators.lua | 157 -- test/lua/errors/stringlibargs.lua | 120 -- test/lua/errors/tablelibargs.lua | 70 - test/lua/functions.lua | 74 - test/lua/iolib.lua | 153 -- test/lua/luaj3.0-tests.zip | Bin 323550 -> 0 bytes test/lua/manyupvals.lua | 37 - test/lua/mathlib.lua | 239 --- test/lua/metatags.lua | 286 --- test/lua/oslib.lua | 60 - test/lua/perf/binarytrees.lua | 50 - test/lua/perf/fannkuch.lua | 51 - test/lua/perf/nbody.lua | 123 -- test/lua/perf/nsieve.lua | 35 - test/lua/repack.sh | 39 - test/lua/stringlib.lua | 192 --- test/lua/tablelib.lua | 284 --- test/lua/tailcalls.lua | 153 -- test/lua/upvalues.lua | 97 -- test/lua/vm.lua | 250 --- version.properties | 1 - wtk.xml | 25 - 216 files changed, 2172 insertions(+), 16083 deletions(-) delete mode 100644 .classpath create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/discord.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/luaj.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml delete mode 100644 .project delete mode 100644 build-app.xml delete mode 100644 build-applet.xml delete mode 100644 build-coverage.xml delete mode 100644 build-libs.xml delete mode 100644 build-maven.xml delete mode 100644 build-midlet.xml delete mode 100644 build-perf.xml delete mode 100644 build.xml create mode 100644 core/pom.xml rename {src/core => core/src/main/java}/org/luaj/vm2/Buffer.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/Globals.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LoadState.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LocVars.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/Lua.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaBoolean.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaClosure.java (99%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaDouble.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaError.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaFunction.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaInteger.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaNil.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaNumber.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaString.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaTable.java (100%) create mode 100644 core/src/main/java/org/luaj/vm2/LuaThread.java rename {src/core => core/src/main/java}/org/luaj/vm2/LuaUserdata.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/LuaValue.java (99%) rename {src/core => core/src/main/java}/org/luaj/vm2/Metatable.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/NonTableMetatable.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/OrphanedThread.java (96%) rename {src/core => core/src/main/java}/org/luaj/vm2/Print.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/Prototype.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/TailcallVarargs.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/UpValue.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/Upvaldesc.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/Varargs.java (99%) rename {src/core => core/src/main/java}/org/luaj/vm2/WeakTable.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/compiler/Constants.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/compiler/DumpState.java (99%) rename {src/core => core/src/main/java}/org/luaj/vm2/compiler/FuncState.java (66%) rename {src/core => core/src/main/java}/org/luaj/vm2/compiler/InstructionPtr.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/compiler/IntPtr.java (100%) rename {src/core => core/src/main/java}/org/luaj/vm2/compiler/LexState.java (64%) rename {src/core => core/src/main/java}/org/luaj/vm2/compiler/LuaC.java (98%) create mode 100644 examples/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock create mode 100644 examples/android/.gradle/buildOutputCleanup/cache.properties rename test/lua/errors/abc.txt => examples/android/.gradle/vcs-1/gc.properties (100%) create mode 100644 jme/pom.xml create mode 100644 jme/src/main/java/org/openautonomousconnection/luaj/Main.java create mode 100644 jse/pom.xml rename {src/jse => jse/src/main/java}/lua.java (100%) rename {src/jse => jse/src/main/java}/luac.java (100%) rename {src/jse => jse/src/main/java}/luajc.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Block.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Chunk.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Exp.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/FuncArgs.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/FuncBody.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/FuncName.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Name.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/NameResolver.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/NameScope.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/ParList.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Stat.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Str.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/SyntaxElement.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/TableConstructor.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/TableField.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Variable.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/ast/Visitor.java (99%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/BasicBlock.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/JavaBuilder.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/JavaGen.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/JavaLoader.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/LuaJC.java (97%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/ProtoInfo.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/UpvalInfo.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/luajc/VarInfo.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/parser/LuaParser.java (99%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/parser/LuaParserConstants.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/parser/LuaParserTokenManager.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/parser/ParseException.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/parser/SimpleCharStream.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/parser/Token.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/parser/TokenMgrError.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/script/LuaScriptEngine.java (54%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/script/LuaScriptEngineFactory.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/script/LuajContext.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/server/DefaultLauncher.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/server/Launcher.java (100%) rename {src/jse => jse/src/main/java}/org/luaj/vm2/server/LuajClassLoader.java (100%) rename {src/jse => jse/src/main/resources}/META-INF/services/javax.script.ScriptEngineFactory (100%) rename {test => jse/src/test}/java/org/luaj/luajc/SampleMainChunk.java (100%) rename {test => jse/src/test}/java/org/luaj/luajc/TestLuaJ.java (100%) rename {test => jse/src/test}/java/org/luaj/luajc/TestLuaJC.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/AllTests.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/BufferedStreamTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/CompatibiltyTest.java (96%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/ErrorsTest.java (98%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/FragmentsTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/LoadOrderTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/LuaOperationsTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/MathLibTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/MetatableTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/OrphanedThreadTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/RequireClassTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/ScriptDrivenTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/StringTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/TableHashTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/TableTest.java (98%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/TypeTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/UTF8StreamTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/UnaryBinaryOperatorsTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/VarargsTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/WeakTableTest.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/compiler/AbstractUnitTests.java (94%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/compiler/CompilerUnitTests.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java (93%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/compiler/LuaParserTests.java (93%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/compiler/RegressionTests.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/compiler/SimpleTests.java (99%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/require/RequireSampleClassCastExcep.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/require/RequireSampleLoadLuaError.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/require/RequireSampleSuccess.java (100%) rename {test/junit => jse/src/test/java}/org/luaj/vm2/script/ScriptEngineTests.java (100%) create mode 100644 pom.xml delete mode 100644 src/core/org/luaj/vm2/LuaThread.java delete mode 100644 src/core/org/luaj/vm2/lib/BaseLib.java delete mode 100644 src/core/org/luaj/vm2/lib/Bit32Lib.java delete mode 100644 src/core/org/luaj/vm2/lib/CoroutineLib.java delete mode 100644 src/core/org/luaj/vm2/lib/DebugLib.java delete mode 100644 src/core/org/luaj/vm2/lib/IoLib.java delete mode 100644 src/core/org/luaj/vm2/lib/LibFunction.java delete mode 100644 src/core/org/luaj/vm2/lib/MathLib.java delete mode 100644 src/core/org/luaj/vm2/lib/OneArgFunction.java delete mode 100644 src/core/org/luaj/vm2/lib/OsLib.java delete mode 100644 src/core/org/luaj/vm2/lib/PackageLib.java delete mode 100644 src/core/org/luaj/vm2/lib/ResourceFinder.java delete mode 100644 src/core/org/luaj/vm2/lib/StringLib.java delete mode 100644 src/core/org/luaj/vm2/lib/TableLib.java delete mode 100644 src/core/org/luaj/vm2/lib/TableLibFunction.java delete mode 100644 src/core/org/luaj/vm2/lib/ThreeArgFunction.java delete mode 100644 src/core/org/luaj/vm2/lib/TwoArgFunction.java delete mode 100644 src/core/org/luaj/vm2/lib/VarArgFunction.java delete mode 100644 src/core/org/luaj/vm2/lib/ZeroArgFunction.java delete mode 100644 src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java delete mode 100644 src/jme/org/luaj/vm2/lib/jme/JmePlatform.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/CoerceJavaToLua.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JavaArray.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JavaClass.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JavaConstructor.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JavaInstance.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JavaMember.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JavaMethod.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JseBaseLib.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JseIoLib.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JseMathLib.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JseOsLib.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JsePlatform.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JseProcess.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/JseStringLib.java delete mode 100644 src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java delete mode 100644 test/junit/org/luaj/vm2/lib/jse/JsePlatformTest.java delete mode 100644 test/junit/org/luaj/vm2/lib/jse/LuaJavaCoercionTest.java delete mode 100644 test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java delete mode 100644 test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java delete mode 100644 test/junit/org/luaj/vm2/lib/jse/OsLibTest.java delete mode 100644 test/junit/org/luaj/vm2/lib/jse/TestClass.java delete mode 100644 test/junit/org/luaj/vm2/lib/jse/TestInterface.java delete mode 100644 test/lua/baselib.lua delete mode 100644 test/lua/coroutinelib.lua delete mode 100644 test/lua/debuglib.lua delete mode 100644 test/lua/errors.lua delete mode 100644 test/lua/errors/args.lua delete mode 100644 test/lua/errors/baselibargs.lua delete mode 100644 test/lua/errors/coroutinelibargs.lua delete mode 100644 test/lua/errors/debuglibargs.lua delete mode 100644 test/lua/errors/iolibargs.lua delete mode 100644 test/lua/errors/mathlibargs.lua delete mode 100644 test/lua/errors/modulelibargs.lua delete mode 100644 test/lua/errors/operators.lua delete mode 100644 test/lua/errors/stringlibargs.lua delete mode 100644 test/lua/errors/tablelibargs.lua delete mode 100644 test/lua/functions.lua delete mode 100644 test/lua/iolib.lua delete mode 100644 test/lua/luaj3.0-tests.zip delete mode 100644 test/lua/manyupvals.lua delete mode 100644 test/lua/mathlib.lua delete mode 100644 test/lua/metatags.lua delete mode 100644 test/lua/oslib.lua delete mode 100644 test/lua/perf/binarytrees.lua delete mode 100644 test/lua/perf/fannkuch.lua delete mode 100644 test/lua/perf/nbody.lua delete mode 100644 test/lua/perf/nsieve.lua delete mode 100644 test/lua/repack.sh delete mode 100644 test/lua/stringlib.lua delete mode 100644 test/lua/tablelib.lua delete mode 100644 test/lua/tailcalls.lua delete mode 100644 test/lua/upvalues.lua delete mode 100644 test/lua/vm.lua delete mode 100644 version.properties delete mode 100644 wtk.xml diff --git a/.classpath b/.classpath deleted file mode 100644 index eded28b8..00000000 --- a/.classpath +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..ab1f4164 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 00000000..85067693 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 00000000..d8e95616 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 00000000..a72ee6d0 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 00000000..50664c82 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/luaj.iml b/.idea/luaj.iml new file mode 100644 index 00000000..d6ebd480 --- /dev/null +++ b/.idea/luaj.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..a8069d15 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.project b/.project deleted file mode 100644 index 15180d11..00000000 --- a/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - luaj-vm - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/README.md b/README.md index 75363ae9..86848e6c 100644 --- a/README.md +++ b/README.md @@ -317,10 +317,6 @@ A simple example may be found in You must include the library luaj-jme-3.0.2.jar in your midlet jar.

-An ant script to build and run the midlet is in -

-	build-midlet.xml
-

You must install the wireless toolkit and define WTK_HOME for this script to work. @@ -428,7 +424,6 @@ Applets in browsers should use the JsePlatform. The permissions model in applet highly restrictive, so a specialization of the Luajava library must be used that uses default class loading. This is illustrated in the sample Applet examples/jse/SampleApplet.java, -which can be built using build-applet.xml.

JmePlatform

@@ -447,7 +442,6 @@ In particular Globals.finder is overridden to load as resources, so scripts shou colocated with class files in the MIDlet jar file. Luajava cannot be used. Camples code is in examples/jme/SampleMIDlet.java, -which can be built using build-midlet.xml.

Thread Safety

@@ -889,10 +883,6 @@ Unit test scripts can be found in these locations

Code coverage

-A build script for running unit tests and producing code coverage statistics is in -

-	build-coverage.xml
-
It relies on the cobertura code coverage library. @@ -951,7 +941,6 @@ and at http://luaj.sour
  • Add explicit Globals object to manage global state, especially to imrpove thread safety
  • Drop support for lua source to java surce (lua2java) in favor of direct java bytecode output (luajc)
  • Remove compatibility functions like table.getn(), table.maxn(), table.foreach(), and math.log10()
  • -
  • Add ability to create runnable jar file from lua script with sample build file build-app.xml
  • Supply environment as second argument to LibFunction when loading via require()
  • Fix bug 3597515 memory leak due to string caching by simplifying caching logic.
  • Fix bug 3565008 so that short substrings are backed by short arrays.
  • diff --git a/build-app.xml b/build-app.xml deleted file mode 100644 index a3985c9d..00000000 --- a/build-app.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - ------ @{cmd} - - - - - - - - - - - - - =========== @{srcdir}/@{luaprog} ============= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build-applet.xml b/build-applet.xml deleted file mode 100644 index d27b4420..00000000 --- a/build-applet.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -injars ${build.dir}/${script.name}-unobfuscated.jar - -outjars ${build.dir}/${script.name}.jar - -libraryjars ${java.home}/lib/rt.jar - -overloadaggressively - -repackageclasses '' - -allowaccessmodification - -printmapping ${build.dir}/mapping.txt - - -keep public class * extends java.applet.Applet - - -target 1.4 - - - - - - - - - - - Luaj Sample Applet - -

    Luaj Sample Applet

    - Requires browser that supports applets. - ${script.name} - - - - - - -
    -
    - - - - - - - - - - - - -
    diff --git a/build-coverage.xml b/build-coverage.xml deleted file mode 100644 index 8a491f8c..00000000 --- a/build-coverage.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build-libs.xml b/build-libs.xml deleted file mode 100644 index 872c5bb8..00000000 --- a/build-libs.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build-maven.xml b/build-maven.xml deleted file mode 100644 index 33e2211d..00000000 --- a/build-maven.xml +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - 4.0.0 - org.luaj - luaj-]]>@{platform} - ]]>${version}@{snapshot} - jar - luaj-]]>@{platform} - Luaj ]]>${version}@{platform} - http://sourceforge.net/projects/luaj/ - - - MIT License - http://luaj.sourceforge.net/license.txt - repo - - - - - jrosebor - James Roseborough - jim.roseborough@luaj.org - -8 - - - - ifarmer - Ian Farmer - ian.farmer@luaj.org - -8 - - - - - http://luaj.cvs.sourceforge.net/viewvc/luaj/luaj-vm/ - - -]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Luaj API]]> - Copyright © 2007-2015 Luaj.org. All Rights Reserved.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Usage: ant [-Dversion=${version}] -f build-maven.xml [install | shapshot | deploy] - - diff --git a/build-midlet.xml b/build-midlet.xml deleted file mode 100644 index 89457961..00000000 --- a/build-midlet.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -injars build/sample-plain.jar - -outjars build/sample.jar - -libraryjars lib/midpapi20.jar - -libraryjars lib/cldcapi11.jar - -overloadaggressively - -repackageclasses '' - -microedition - - -keep public class SampleMIDlet - -keep public class * extends org.luaj.vm2.LuaValue - - - - - - Jar file length is ${sample.jar.length} - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build-perf.xml b/build-perf.xml deleted file mode 100644 index 63007823..00000000 --- a/build-perf.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ------ @{program} @{luaprog} - - - - - - - - - - - - =========== @{luaprog} ============= - - - - - - - - - - - - - - - - diff --git a/build.xml b/build.xml deleted file mode 100644 index e0ea7f0d..00000000 --- a/build.xml +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Luaj API]]> - Copyright © 2007-2015 Luaj.org. All Rights Reserved.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 00000000..ba62cddd --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + + org.openautonomousconnection.luaj + parent + 3.0.2 + + + core + jar + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + jar + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 21 + 21 + + + + + \ No newline at end of file diff --git a/src/core/org/luaj/vm2/Buffer.java b/core/src/main/java/org/luaj/vm2/Buffer.java similarity index 100% rename from src/core/org/luaj/vm2/Buffer.java rename to core/src/main/java/org/luaj/vm2/Buffer.java diff --git a/src/core/org/luaj/vm2/Globals.java b/core/src/main/java/org/luaj/vm2/Globals.java similarity index 100% rename from src/core/org/luaj/vm2/Globals.java rename to core/src/main/java/org/luaj/vm2/Globals.java diff --git a/src/core/org/luaj/vm2/LoadState.java b/core/src/main/java/org/luaj/vm2/LoadState.java similarity index 100% rename from src/core/org/luaj/vm2/LoadState.java rename to core/src/main/java/org/luaj/vm2/LoadState.java diff --git a/src/core/org/luaj/vm2/LocVars.java b/core/src/main/java/org/luaj/vm2/LocVars.java similarity index 100% rename from src/core/org/luaj/vm2/LocVars.java rename to core/src/main/java/org/luaj/vm2/LocVars.java diff --git a/src/core/org/luaj/vm2/Lua.java b/core/src/main/java/org/luaj/vm2/Lua.java similarity index 100% rename from src/core/org/luaj/vm2/Lua.java rename to core/src/main/java/org/luaj/vm2/Lua.java diff --git a/src/core/org/luaj/vm2/LuaBoolean.java b/core/src/main/java/org/luaj/vm2/LuaBoolean.java similarity index 100% rename from src/core/org/luaj/vm2/LuaBoolean.java rename to core/src/main/java/org/luaj/vm2/LuaBoolean.java diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/core/src/main/java/org/luaj/vm2/LuaClosure.java similarity index 99% rename from src/core/org/luaj/vm2/LuaClosure.java rename to core/src/main/java/org/luaj/vm2/LuaClosure.java index 46a3556f..a1c1c078 100644 --- a/src/core/org/luaj/vm2/LuaClosure.java +++ b/core/src/main/java/org/luaj/vm2/LuaClosure.java @@ -502,10 +502,10 @@ public class LuaClosure extends LuaFunction { continue; case Lua.OP_EXTRAARG: - throw new java.lang.IllegalArgumentException("Uexecutable opcode: OP_EXTRAARG"); + throw new IllegalArgumentException("Uexecutable opcode: OP_EXTRAARG"); default: - throw new java.lang.IllegalArgumentException("Illegal opcode: " + (i & 0x3f)); + throw new IllegalArgumentException("Illegal opcode: " + (i & 0x3f)); } } } catch ( LuaError le ) { diff --git a/src/core/org/luaj/vm2/LuaDouble.java b/core/src/main/java/org/luaj/vm2/LuaDouble.java similarity index 100% rename from src/core/org/luaj/vm2/LuaDouble.java rename to core/src/main/java/org/luaj/vm2/LuaDouble.java diff --git a/src/core/org/luaj/vm2/LuaError.java b/core/src/main/java/org/luaj/vm2/LuaError.java similarity index 100% rename from src/core/org/luaj/vm2/LuaError.java rename to core/src/main/java/org/luaj/vm2/LuaError.java diff --git a/src/core/org/luaj/vm2/LuaFunction.java b/core/src/main/java/org/luaj/vm2/LuaFunction.java similarity index 100% rename from src/core/org/luaj/vm2/LuaFunction.java rename to core/src/main/java/org/luaj/vm2/LuaFunction.java diff --git a/src/core/org/luaj/vm2/LuaInteger.java b/core/src/main/java/org/luaj/vm2/LuaInteger.java similarity index 100% rename from src/core/org/luaj/vm2/LuaInteger.java rename to core/src/main/java/org/luaj/vm2/LuaInteger.java diff --git a/src/core/org/luaj/vm2/LuaNil.java b/core/src/main/java/org/luaj/vm2/LuaNil.java similarity index 100% rename from src/core/org/luaj/vm2/LuaNil.java rename to core/src/main/java/org/luaj/vm2/LuaNil.java diff --git a/src/core/org/luaj/vm2/LuaNumber.java b/core/src/main/java/org/luaj/vm2/LuaNumber.java similarity index 100% rename from src/core/org/luaj/vm2/LuaNumber.java rename to core/src/main/java/org/luaj/vm2/LuaNumber.java diff --git a/src/core/org/luaj/vm2/LuaString.java b/core/src/main/java/org/luaj/vm2/LuaString.java similarity index 100% rename from src/core/org/luaj/vm2/LuaString.java rename to core/src/main/java/org/luaj/vm2/LuaString.java diff --git a/src/core/org/luaj/vm2/LuaTable.java b/core/src/main/java/org/luaj/vm2/LuaTable.java similarity index 100% rename from src/core/org/luaj/vm2/LuaTable.java rename to core/src/main/java/org/luaj/vm2/LuaTable.java diff --git a/core/src/main/java/org/luaj/vm2/LuaThread.java b/core/src/main/java/org/luaj/vm2/LuaThread.java new file mode 100644 index 00000000..a210d4c7 --- /dev/null +++ b/core/src/main/java/org/luaj/vm2/LuaThread.java @@ -0,0 +1,309 @@ +/******************************************************************************* + * Copyright (c) 2007-2012 LuaJ. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ +package org.luaj.vm2; + + +import java.lang.ref.WeakReference; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Subclass of {@link LuaValue} that implements + * a lua coroutine thread using Java Threads. + *

    + * A LuaThread is typically created in response to a scripted call to + * {@code coroutine.create()} + *

    + * The threads must be initialized with the globals, so that + * the global environment may be passed along according to rules of lua. + * This is done via the constructor arguments {@link #LuaThread(Globals)} or + * {@link #LuaThread(Globals, LuaValue)}. + *

    + * The utility classes {@link org.luaj.vm2.lib.jse.JsePlatform} and + * {@link org.luaj.vm2.lib.jme.JmePlatform} + * see to it that this {@link Globals} are initialized properly. + *

    + * The behavior of coroutine threads matches closely the behavior + * of C coroutine library. However, because of the use of Java threads + * to manage call state, it is possible to yield from anywhere in luaj. + *

    + * Each Java thread wakes up at regular intervals and checks a weak reference + * to determine if it can ever be resumed. If not, it throws + * {@link OrphanedThread} which is an {@link java.lang.Error}. + * Applications should not catch {@link OrphanedThread}, because it can break + * the thread safety of luaj. The value controlling the polling interval + * is {@link #thread_orphan_check_interval} and may be set by the user. + *

    + * There are two main ways to abandon a coroutine. The first is to call + * {@code yield()} from lua, or equivalently {@link Globals#yield(Varargs)}, + * and arrange to have it never resumed possibly by values passed to yield. + * The second is to throw {@link OrphanedThread}, which should put the thread + * in a dead state. In either case all references to the thread must be + * dropped, and the garbage collector must run for the thread to be + * garbage collected. + * + * + * @see LuaValue + * @see org.luaj.vm2.lib.jse.JsePlatform + * @see org.luaj.vm2.lib.jme.JmePlatform + * @see org.luaj.vm2.lib.CoroutineLib + */ +public class LuaThread extends LuaValue { + + /** Shared metatable for lua threads. */ + public static LuaValue s_metatable; + + /** The current number of coroutines. Should not be set. */ + public static int coroutine_count = 0; + + /** Polling interval, in milliseconds, which each thread uses while waiting to + * return from a yielded state to check if the lua threads is no longer + * referenced and therefore should be garbage collected. + * A short polling interval for many threads will consume server resources. + * Orphaned threads cannot be detected and collected unless garbage + * collection is run. This can be changed by Java startup code if desired. + */ + public static long thread_orphan_check_interval = 5000; + + public static final String USE_PLATFORM_THREAD = "USE_PLATFORM_THREAD"; + + private static boolean SUPPORT_VIRTUAL_THREAD = false; + + static { + try { + Thread.class.getMethod("ofVirtual"); + SUPPORT_VIRTUAL_THREAD = true; + } catch (Exception e) { + //e.printStackTrace(); + } + } + + public static final int STATUS_INITIAL = 0; + public static final int STATUS_SUSPENDED = 1; + public static final int STATUS_RUNNING = 2; + public static final int STATUS_NORMAL = 3; + public static final int STATUS_DEAD = 4; + public static final String[] STATUS_NAMES = { + "suspended", + "suspended", + "running", + "normal", + "dead",}; + + public final State state; + + public static final int MAX_CALLSTACK = 256; + + /** Thread-local used by DebugLib to store debugging state. + * This is an opaque value that should not be modified by applications. */ + public Object callstack; + + public final Globals globals; + + /** Error message handler for this thread, if any. */ + public LuaValue errorfunc; + + /** Private constructor for main thread only */ + public LuaThread(Globals globals) { + state = new State(globals, this, null); + state.status = STATUS_RUNNING; + this.globals = globals; + } + + /** + * Create a LuaThread around a function and environment + * @param func The function to execute + */ + public LuaThread(Globals globals, LuaValue func) { + LuaValue.assert_(func != null, "function cannot be null"); + state = new State(globals, this, func); + this.globals = globals; + } + + public int type() { + return LuaValue.TTHREAD; + } + + public String typename() { + return "thread"; + } + + public boolean isthread() { + return true; + } + + public LuaThread optthread(LuaThread defval) { + return this; + } + + public LuaThread checkthread() { + return this; + } + + public LuaValue getmetatable() { + return s_metatable; + } + + public String getStatus() { + return STATUS_NAMES[state.status]; + } + + public boolean isMainThread() { + return this.state.function == null; + } + + public Varargs resume(Varargs args) { + final LuaThread.State s = this.state; + if (s.status > LuaThread.STATUS_SUSPENDED) + return LuaValue.varargsOf(LuaValue.FALSE, + LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine")); + return s.lua_resume(this, args); + } + + public static class State implements Runnable { + private final Globals globals; + final WeakReference lua_thread; + public final LuaValue function; + Varargs args = LuaValue.NONE; + Varargs result = LuaValue.NONE; + String error = null; + + /** Hook function control state used by debug lib. */ + public LuaValue hookfunc; + + public boolean hookline; + public boolean hookcall; + public boolean hookrtrn; + public int hookcount; + public boolean inhook; + public int lastline; + public int bytecodes; + + public int status = LuaThread.STATUS_INITIAL; + private Lock locker = new ReentrantLock(); + private Condition cond = locker.newCondition(); + + State(Globals globals, LuaThread lua_thread, LuaValue function) { + this.globals = globals; + this.lua_thread = new WeakReference(lua_thread); + this.function = function; + } + + public void run() { + locker.lock(); + try { + try { + Varargs a = this.args; + this.args = LuaValue.NONE; + this.result = function.invoke(a); + } catch (Throwable t) { + this.error = t.getMessage(); + } finally { + this.status = LuaThread.STATUS_DEAD; + cond.signal(); + } + } finally { + locker.unlock(); + } + } + + public Varargs lua_resume(LuaThread new_thread, Varargs args) { + locker.lock(); + try { + LuaThread previous_thread = globals.running; + try { + globals.running = new_thread; + this.args = args; + if (this.status == STATUS_INITIAL) { + this.status = STATUS_RUNNING; + Thread t = null; + if(SUPPORT_VIRTUAL_THREAD) { + LuaValue setting = globals.get(USE_PLATFORM_THREAD); + if(setting.isnil()) {//default + if(Thread.currentThread().isVirtual()) { + t = Thread.ofVirtual().name("Coroutine-"+(++coroutine_count)).start(this); + } + } else { + if(!setting.toboolean()) { + t = Thread.ofVirtual().name("Coroutine-"+(++coroutine_count)).start(this); + } + } + } + if (t == null){ + new Thread(this, "Coroutine-"+(++coroutine_count)).start(); + } + } else { + cond.signal(); + } + if (previous_thread != null) + previous_thread.state.status = STATUS_NORMAL; + this.status = STATUS_RUNNING; + cond.await(); + return (this.error != null? + LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)): + LuaValue.varargsOf(LuaValue.TRUE, this.result)); + } catch (InterruptedException ie) { + throw new OrphanedThread(); + } finally { + this.args = LuaValue.NONE; + this.result = LuaValue.NONE; + this.error = null; + globals.running = previous_thread; + if (previous_thread != null) + globals.running.state.status =STATUS_RUNNING; + } + } finally { + locker.unlock(); + } + } + + public Varargs lua_yield(Varargs args) { + locker.lock(); + try { + try { + this.result = args; + this.status = STATUS_SUSPENDED; + cond.signal(); + do { + cond.await(thread_orphan_check_interval,TimeUnit.MILLISECONDS); + if (this.lua_thread.get() == null) { + this.status = STATUS_DEAD; + throw new OrphanedThread(); + } + } while (this.status == STATUS_SUSPENDED); + return this.args; + } catch (InterruptedException ie) { + this.status = STATUS_DEAD; + throw new OrphanedThread(); + } finally { + this.args = LuaValue.NONE; + this.result = LuaValue.NONE; + } + } finally { + locker.unlock(); + } + } + } + +} \ No newline at end of file diff --git a/src/core/org/luaj/vm2/LuaUserdata.java b/core/src/main/java/org/luaj/vm2/LuaUserdata.java similarity index 100% rename from src/core/org/luaj/vm2/LuaUserdata.java rename to core/src/main/java/org/luaj/vm2/LuaUserdata.java diff --git a/src/core/org/luaj/vm2/LuaValue.java b/core/src/main/java/org/luaj/vm2/LuaValue.java similarity index 99% rename from src/core/org/luaj/vm2/LuaValue.java rename to core/src/main/java/org/luaj/vm2/LuaValue.java index 9d3af18d..34913cb3 100644 --- a/src/core/org/luaj/vm2/LuaValue.java +++ b/core/src/main/java/org/luaj/vm2/LuaValue.java @@ -3402,8 +3402,8 @@ public class LuaValue extends Varargs { switch ( v.length ) { case 0: return NONE; case 1: return v[0]; - case 2: return new Varargs.PairVarargs(v[0],v[1]); - default: return new Varargs.ArrayVarargs(v,NONE); + case 2: return new PairVarargs(v[0],v[1]); + default: return new ArrayVarargs(v,NONE); } } @@ -3419,12 +3419,12 @@ public class LuaValue extends Varargs { switch ( v.length ) { case 0: return r; case 1: return r.narg()>0? - (Varargs) new Varargs.PairVarargs(v[0],r): + (Varargs) new PairVarargs(v[0],r): (Varargs) v[0]; case 2: return r.narg()>0? - (Varargs) new Varargs.ArrayVarargs(v,r): - (Varargs) new Varargs.PairVarargs(v[0],v[1]); - default: return new Varargs.ArrayVarargs(v,r); + (Varargs) new ArrayVarargs(v,r): + (Varargs) new PairVarargs(v[0],v[1]); + default: return new ArrayVarargs(v,r); } } @@ -3441,8 +3441,8 @@ public class LuaValue extends Varargs { switch ( length ) { case 0: return NONE; case 1: return v[offset]; - case 2: return new Varargs.PairVarargs(v[offset+0],v[offset+1]); - default: return new Varargs.ArrayPartVarargs(v, offset, length, NONE); + case 2: return new PairVarargs(v[offset+0],v[offset+1]); + default: return new ArrayPartVarargs(v, offset, length, NONE); } } @@ -3463,12 +3463,12 @@ public class LuaValue extends Varargs { switch ( length ) { case 0: return more; case 1: return more.narg()>0? - (Varargs) new Varargs.PairVarargs(v[offset],more): + (Varargs) new PairVarargs(v[offset],more): (Varargs) v[offset]; case 2: return more.narg()>0? - (Varargs) new Varargs.ArrayPartVarargs(v,offset,length,more): - (Varargs) new Varargs.PairVarargs(v[offset],v[offset+1]); - default: return new Varargs.ArrayPartVarargs(v,offset,length,more); + (Varargs) new ArrayPartVarargs(v,offset,length,more): + (Varargs) new PairVarargs(v[offset],v[offset+1]); + default: return new ArrayPartVarargs(v,offset,length,more); } } @@ -3485,7 +3485,7 @@ public class LuaValue extends Varargs { public static Varargs varargsOf(LuaValue v, Varargs r) { switch ( r.narg() ) { case 0: return v; - default: return new Varargs.PairVarargs(v,r); + default: return new PairVarargs(v,r); } } @@ -3502,8 +3502,8 @@ public class LuaValue extends Varargs { */ public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) { switch ( v3.narg() ) { - case 0: return new Varargs.PairVarargs(v1,v2); - default: return new Varargs.ArrayPartVarargs(new LuaValue[]{v1,v2}, 0, 2, v3); + case 0: return new PairVarargs(v1,v2); + default: return new ArrayPartVarargs(new LuaValue[]{v1,v2}, 0, 2, v3); } } diff --git a/src/core/org/luaj/vm2/Metatable.java b/core/src/main/java/org/luaj/vm2/Metatable.java similarity index 100% rename from src/core/org/luaj/vm2/Metatable.java rename to core/src/main/java/org/luaj/vm2/Metatable.java diff --git a/src/core/org/luaj/vm2/NonTableMetatable.java b/core/src/main/java/org/luaj/vm2/NonTableMetatable.java similarity index 100% rename from src/core/org/luaj/vm2/NonTableMetatable.java rename to core/src/main/java/org/luaj/vm2/NonTableMetatable.java diff --git a/src/core/org/luaj/vm2/OrphanedThread.java b/core/src/main/java/org/luaj/vm2/OrphanedThread.java similarity index 96% rename from src/core/org/luaj/vm2/OrphanedThread.java rename to core/src/main/java/org/luaj/vm2/OrphanedThread.java index b3c931f1..5e2eba8d 100644 --- a/src/core/org/luaj/vm2/OrphanedThread.java +++ b/core/src/main/java/org/luaj/vm2/OrphanedThread.java @@ -22,7 +22,7 @@ package org.luaj.vm2; /** - * {@link java.lang.Error} sublcass that indicates a lua thread that is no + * {@link Error} sublcass that indicates a lua thread that is no * longer referenced has been detected. *

    * The java thread in which this is thrown should correspond to a diff --git a/src/core/org/luaj/vm2/Print.java b/core/src/main/java/org/luaj/vm2/Print.java similarity index 100% rename from src/core/org/luaj/vm2/Print.java rename to core/src/main/java/org/luaj/vm2/Print.java diff --git a/src/core/org/luaj/vm2/Prototype.java b/core/src/main/java/org/luaj/vm2/Prototype.java similarity index 100% rename from src/core/org/luaj/vm2/Prototype.java rename to core/src/main/java/org/luaj/vm2/Prototype.java diff --git a/src/core/org/luaj/vm2/TailcallVarargs.java b/core/src/main/java/org/luaj/vm2/TailcallVarargs.java similarity index 100% rename from src/core/org/luaj/vm2/TailcallVarargs.java rename to core/src/main/java/org/luaj/vm2/TailcallVarargs.java diff --git a/src/core/org/luaj/vm2/UpValue.java b/core/src/main/java/org/luaj/vm2/UpValue.java similarity index 100% rename from src/core/org/luaj/vm2/UpValue.java rename to core/src/main/java/org/luaj/vm2/UpValue.java diff --git a/src/core/org/luaj/vm2/Upvaldesc.java b/core/src/main/java/org/luaj/vm2/Upvaldesc.java similarity index 100% rename from src/core/org/luaj/vm2/Upvaldesc.java rename to core/src/main/java/org/luaj/vm2/Upvaldesc.java diff --git a/src/core/org/luaj/vm2/Varargs.java b/core/src/main/java/org/luaj/vm2/Varargs.java similarity index 99% rename from src/core/org/luaj/vm2/Varargs.java rename to core/src/main/java/org/luaj/vm2/Varargs.java index e56d8dcf..04cf60d8 100644 --- a/src/core/org/luaj/vm2/Varargs.java +++ b/core/src/main/java/org/luaj/vm2/Varargs.java @@ -537,7 +537,7 @@ public abstract class Varargs { if (newstart == this.end) return v.arg(this.end); if (newstart == this.end-1) - return new Varargs.PairVarargs(v.arg(this.end-1), v.arg(this.end)); + return new PairVarargs(v.arg(this.end-1), v.arg(this.end)); return new SubVarargs(v, newstart, this.end); } return new SubVarargs(v, newstart, this.end); diff --git a/src/core/org/luaj/vm2/WeakTable.java b/core/src/main/java/org/luaj/vm2/WeakTable.java similarity index 100% rename from src/core/org/luaj/vm2/WeakTable.java rename to core/src/main/java/org/luaj/vm2/WeakTable.java diff --git a/src/core/org/luaj/vm2/compiler/Constants.java b/core/src/main/java/org/luaj/vm2/compiler/Constants.java similarity index 100% rename from src/core/org/luaj/vm2/compiler/Constants.java rename to core/src/main/java/org/luaj/vm2/compiler/Constants.java diff --git a/src/core/org/luaj/vm2/compiler/DumpState.java b/core/src/main/java/org/luaj/vm2/compiler/DumpState.java similarity index 99% rename from src/core/org/luaj/vm2/compiler/DumpState.java rename to core/src/main/java/org/luaj/vm2/compiler/DumpState.java index 3f92ba63..f53a3ea2 100644 --- a/src/core/org/luaj/vm2/compiler/DumpState.java +++ b/core/src/main/java/org/luaj/vm2/compiler/DumpState.java @@ -168,7 +168,7 @@ public class DumpState { break; case NUMBER_FORMAT_INTS_ONLY: if ( ! ALLOW_INTEGER_CASTING && ! o.isint() ) - throw new java.lang.IllegalArgumentException("not an integer: "+o); + throw new IllegalArgumentException("not an integer: "+o); writer.write(LuaValue.TNUMBER); dumpInt(o.toint()); break; diff --git a/src/core/org/luaj/vm2/compiler/FuncState.java b/core/src/main/java/org/luaj/vm2/compiler/FuncState.java similarity index 66% rename from src/core/org/luaj/vm2/compiler/FuncState.java rename to core/src/main/java/org/luaj/vm2/compiler/FuncState.java index 70e0f885..4c56a206 100644 --- a/src/core/org/luaj/vm2/compiler/FuncState.java +++ b/core/src/main/java/org/luaj/vm2/compiler/FuncState.java @@ -1,24 +1,24 @@ /******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ + * Copyright (c) 2009 Luaj.org. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ package org.luaj.vm2.compiler; import java.util.Hashtable; @@ -45,7 +45,7 @@ public class FuncState extends Constants { boolean upval; /* true if some variable in the block is an upvalue */ boolean isloop; /* true if `block' is a loop */ }; - + Prototype f; /* current function header */ Hashtable h; /* table to find (and reuse) elements in `k' */ FuncState prev; /* enclosing function */ @@ -64,8 +64,8 @@ public class FuncState extends Constants { FuncState() { } - - + + // ============================================================= // from lcode.h // ============================================================= @@ -86,7 +86,7 @@ public class FuncState extends Constants { setreturns(e, LUA_MULTRET); } - + // ============================================================= // from lparser.c // ============================================================= @@ -97,7 +97,7 @@ public class FuncState extends Constants { for (i = bl.firstlabel; i < ll_n; i++) { if (label.eq_b(ll[i].name)) { String msg = ls.L.pushfstring( - "label '" + label + " already defined on line " + ll[i].line); + "label '" + label + " already defined on line " + ll[i].line); ls.semerror(msg); } } @@ -108,13 +108,13 @@ public class FuncState extends Constants { if ( v > l ) errorlimit( l, msg ); } - + void errorlimit (int limit, String what) { // TODO: report message logic. - String msg = (f.linedefined == 0) ? - ls.L.pushfstring("main function has more than "+limit+" "+what) : - ls.L.pushfstring("function at line "+f.linedefined+" has more than "+limit+" "+what); - ls.lexerror(msg, 0); + String msg = (f.linedefined == 0) ? + ls.L.pushfstring("main function has more than "+limit+" "+what) : + ls.L.pushfstring("function at line "+f.linedefined+" has more than "+limit+" "+what); + ls.lexerror(msg, 0); } LocVars getlocvar(int i) { @@ -124,19 +124,19 @@ public class FuncState extends Constants { } void removevars (int tolevel) { - ls.dyd.n_actvar -= (nactvar - tolevel); - while (nactvar > tolevel) - getlocvar(--nactvar).endpc = pc; + ls.dyd.n_actvar -= (nactvar - tolevel); + while (nactvar > tolevel) + getlocvar(--nactvar).endpc = pc; } int searchupvalue (LuaString name) { - int i; - Upvaldesc[] up = f.upvalues; - for (i = 0; i < nups; i++) - if (up[i].name.eq_b(name)) - return i; - return -1; /* not found */ + int i; + Upvaldesc[] up = f.upvalues; + for (i = 0; i < nups; i++) + if (up[i].name.eq_b(name)) + return i; + return -1; /* not found */ } int newupvalue (LuaString name, expdesc v) { @@ -144,9 +144,9 @@ public class FuncState extends Constants { if (f.upvalues == null || nups + 1 > f.upvalues.length) f.upvalues = realloc( f.upvalues, nups > 0 ? nups*2 : 1 ); f.upvalues[nups] = new Upvaldesc(name, v.k == LexState.VLOCAL, v.u.info); - return nups++; + return nups++; } - + int searchvar(LuaString n) { int i; for (i = nactvar - 1; i >= 0; i--) { @@ -155,14 +155,14 @@ public class FuncState extends Constants { } return -1; /* not found */ } - + void markupval(int level) { BlockCnt bl = this.bl; while (bl.nactvar > level) bl = bl.previous; bl.upval = true; } - + static int singlevaraux(FuncState fs, LuaString n, expdesc var, int base) { if (fs == null) /* no more levels? */ return LexState.VVOID; /* default is global */ @@ -173,24 +173,24 @@ public class FuncState extends Constants { fs.markupval(v); /* local will be used as an upval */ return LexState.VLOCAL; } else { /* not found at current level; try upvalues */ - int idx = fs.searchupvalue(n); /* try existing upvalues */ - if (idx < 0) { /* not found? */ - if (singlevaraux(fs.prev, n, var, 0) == LexState.VVOID) /* try upper levels */ - return LexState.VVOID; /* not found; is a global */ - /* else was LOCAL or UPVAL */ - idx = fs.newupvalue(n, var); /* will be a new upvalue */ - } - var.init(LexState.VUPVAL, idx); - return LexState.VUPVAL; + int idx = fs.searchupvalue(n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + if (singlevaraux(fs.prev, n, var, 0) == LexState.VVOID) /* try upper levels */ + return LexState.VVOID; /* not found; is a global */ + /* else was LOCAL or UPVAL */ + idx = fs.newupvalue(n, var); /* will be a new upvalue */ + } + var.init(LexState.VUPVAL, idx); + return LexState.VUPVAL; } } /* - ** "export" pending gotos to outer level, to check them against - ** outer labels; if the block being exited has upvalues, and - ** the goto exits the scope of any variable (which can be the - ** upvalue), close those variables being exited. - */ + ** "export" pending gotos to outer level, to check them against + ** outer labels; if the block being exited has upvalues, and + ** the goto exits the scope of any variable (which can be the + ** upvalue), close those variables being exited. + */ void movegotosout(BlockCnt bl) { int i = bl.firstgoto; final LexState.Labeldesc[] gl = ls.dyd.gt; @@ -207,37 +207,37 @@ public class FuncState extends Constants { i++; /* move to next one */ } } - + void enterblock (BlockCnt bl, boolean isloop) { - bl.isloop = isloop; - bl.nactvar = nactvar; - bl.firstlabel = (short) ls.dyd.n_label; - bl.firstgoto = (short) ls.dyd.n_gt; - bl.upval = false; - bl.previous = this.bl; - this.bl = bl; - _assert(this.freereg == this.nactvar); + bl.isloop = isloop; + bl.nactvar = nactvar; + bl.firstlabel = (short) ls.dyd.n_label; + bl.firstgoto = (short) ls.dyd.n_gt; + bl.upval = false; + bl.previous = this.bl; + this.bl = bl; + _assert(this.freereg == this.nactvar); } void leaveblock() { BlockCnt bl = this.bl; if (bl.previous != null && bl.upval) { - /* create a 'jump to here' to close upvalues */ - int j = this.jump(); - this.patchclose(j, bl.nactvar); - this.patchtohere(j); + /* create a 'jump to here' to close upvalues */ + int j = this.jump(); + this.patchclose(j, bl.nactvar); + this.patchtohere(j); } if (bl.isloop) - ls.breaklabel(); /* close pending breaks */ + ls.breaklabel(); /* close pending breaks */ this.bl = bl.previous; this.removevars(bl.nactvar); _assert(bl.nactvar == this.nactvar); this.freereg = this.nactvar; /* free registers */ ls.dyd.n_label = bl.firstlabel; /* remove local labels */ if (bl.previous != null) /* inner block? */ - this.movegotosout(bl); /* update pending gotos to outer block */ + this.movegotosout(bl); /* update pending gotos to outer block */ else if (bl.firstgoto < ls.dyd.n_gt) /* pending gotos in outer block? */ - ls.undefgoto(ls.dyd.gt[bl.firstgoto]); /* error */ + ls.undefgoto(ls.dyd.gt[bl.firstgoto]); /* error */ } void closelistfield(ConsControl cc) { @@ -258,19 +258,19 @@ public class FuncState extends Constants { void lastlistfield (ConsControl cc) { if (cc.tostore == 0) return; if (hasmultret(cc.v.k)) { - this.setmultret(cc.v); - this.setlist(cc.t.u.info, cc.na, LUA_MULTRET); - cc.na--; /** do not count last expression (unknown number of elements) */ + this.setmultret(cc.v); + this.setlist(cc.t.u.info, cc.na, LUA_MULTRET); + cc.na--; /** do not count last expression (unknown number of elements) */ } else { - if (cc.v.k != LexState.VVOID) - this.exp2nextreg(cc.v); - this.setlist(cc.t.u.info, cc.na, cc.tostore); + if (cc.v.k != LexState.VVOID) + this.exp2nextreg(cc.v); + this.setlist(cc.t.u.info, cc.na, cc.tostore); } } - - - + + + // ============================================================= // from lcode.c // ============================================================= @@ -479,7 +479,7 @@ public class FuncState extends Constants { return ((Integer) h.get(v)).intValue(); } final int idx = this.nk; - this.h.put(v, new Integer(idx)); + this.h.put(v, idx); final Prototype f = this.f; if (f.k == null || nk + 1 >= f.k.length) f.k = realloc( f.k, nk*2 + 1 ); @@ -531,33 +531,33 @@ public class FuncState extends Constants { void dischargevars(expdesc e) { switch (e.k) { - case LexState.VLOCAL: { - e.k = LexState.VNONRELOC; - break; - } - case LexState.VUPVAL: { - e.u.info = this.codeABC(OP_GETUPVAL, 0, e.u.info, 0); - e.k = LexState.VRELOCABLE; - break; - } - case LexState.VINDEXED: { - int op = OP_GETTABUP; /* assume 't' is in an upvalue */ - this.freereg(e.u.ind_idx); - if (e.u.ind_vt == LexState.VLOCAL) { /* 't' is in a register? */ - this.freereg(e.u.ind_t); - op = OP_GETTABLE; + case LexState.VLOCAL: { + e.k = LexState.VNONRELOC; + break; } - e.u.info = this.codeABC(op, 0, e.u.ind_t, e.u.ind_idx); - e.k = LexState.VRELOCABLE; - break; - } - case LexState.VVARARG: - case LexState.VCALL: { - this.setoneret(e); - break; - } - default: - break; /* there is one value available (somewhere) */ + case LexState.VUPVAL: { + e.u.info = this.codeABC(OP_GETUPVAL, 0, e.u.info, 0); + e.k = LexState.VRELOCABLE; + break; + } + case LexState.VINDEXED: { + int op = OP_GETTABUP; /* assume 't' is in an upvalue */ + this.freereg(e.u.ind_idx); + if (e.u.ind_vt == LexState.VLOCAL) { /* 't' is in a register? */ + this.freereg(e.u.ind_t); + op = OP_GETTABLE; + } + e.u.info = this.codeABC(op, 0, e.u.ind_t, e.u.ind_idx); + e.k = LexState.VRELOCABLE; + break; + } + case LexState.VVARARG: + case LexState.VCALL: { + this.setoneret(e); + break; + } + default: + break; /* there is one value available (somewhere) */ } } @@ -569,38 +569,38 @@ public class FuncState extends Constants { void discharge2reg(expdesc e, int reg) { this.dischargevars(e); switch (e.k) { - case LexState.VNIL: { - this.nil(reg, 1); - break; - } - case LexState.VFALSE: - case LexState.VTRUE: { - this.codeABC(OP_LOADBOOL, reg, (e.k == LexState.VTRUE ? 1 : 0), - 0); - break; - } - case LexState.VK: { - this.codeK(reg, e.u.info); - break; - } - case LexState.VKNUM: { - this.codeK(reg, this.numberK(e.u.nval())); - break; - } - case LexState.VRELOCABLE: { - InstructionPtr pc = this.getcodePtr(e); - SETARG_A(pc, reg); - break; - } - case LexState.VNONRELOC: { - if (reg != e.u.info) - this.codeABC(OP_MOVE, reg, e.u.info, 0); - break; - } - default: { - _assert (e.k == LexState.VVOID || e.k == LexState.VJMP); - return; /* nothing to do... */ - } + case LexState.VNIL: { + this.nil(reg, 1); + break; + } + case LexState.VFALSE: + case LexState.VTRUE: { + this.codeABC(OP_LOADBOOL, reg, (e.k == LexState.VTRUE ? 1 : 0), + 0); + break; + } + case LexState.VK: { + this.codeK(reg, e.u.info); + break; + } + case LexState.VKNUM: { + this.codeK(reg, this.numberK(e.u.nval())); + break; + } + case LexState.VRELOCABLE: { + InstructionPtr pc = this.getcodePtr(e); + SETARG_A(pc, reg); + break; + } + case LexState.VNONRELOC: { + if (reg != e.u.info) + this.codeABC(OP_MOVE, reg, e.u.info, 0); + break; + } + default: { + _assert (e.k == LexState.VVOID || e.k == LexState.VJMP); + return; /* nothing to do... */ + } } e.u.info = reg; e.k = LexState.VNONRELOC; @@ -673,57 +673,57 @@ public class FuncState extends Constants { int exp2RK(expdesc e) { this.exp2val(e); switch (e.k) { - case LexState.VTRUE: - case LexState.VFALSE: - case LexState.VNIL: { - if (this.nk <= MAXINDEXRK) { /* constant fit in RK operand? */ - e.u.info = (e.k == LexState.VNIL) ? this.nilK() - : this.boolK((e.k == LexState.VTRUE)); + case LexState.VTRUE: + case LexState.VFALSE: + case LexState.VNIL: { + if (this.nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e.u.info = (e.k == LexState.VNIL) ? this.nilK() + : this.boolK((e.k == LexState.VTRUE)); + e.k = LexState.VK; + return RKASK(e.u.info); + } else + break; + } + case LexState.VKNUM: { + e.u.info = this.numberK(e.u.nval()); e.k = LexState.VK; - return RKASK(e.u.info); - } else + /* go through */ + } + case LexState.VK: { + if (e.u.info <= MAXINDEXRK) /* constant fit in argC? */ + return RKASK(e.u.info); + else + break; + } + default: break; } - case LexState.VKNUM: { - e.u.info = this.numberK(e.u.nval()); - e.k = LexState.VK; - /* go through */ - } - case LexState.VK: { - if (e.u.info <= MAXINDEXRK) /* constant fit in argC? */ - return RKASK(e.u.info); - else - break; - } - default: - break; - } /* not a constant in the right range: put it in a register */ return this.exp2anyreg(e); } void storevar(expdesc var, expdesc ex) { switch (var.k) { - case LexState.VLOCAL: { - this.freeexp(ex); - this.exp2reg(ex, var.u.info); - return; - } - case LexState.VUPVAL: { - int e = this.exp2anyreg(ex); - this.codeABC(OP_SETUPVAL, e, var.u.info, 0); - break; - } - case LexState.VINDEXED: { - int op = (var.u.ind_vt == LexState.VLOCAL) ? OP_SETTABLE : OP_SETTABUP; - int e = this.exp2RK(ex); - this.codeABC(op, var.u.ind_t, var.u.ind_idx, e); - break; - } - default: { - _assert (false); /* invalid var kind to store */ - break; - } + case LexState.VLOCAL: { + this.freeexp(ex); + this.exp2reg(ex, var.u.info); + return; + } + case LexState.VUPVAL: { + int e = this.exp2anyreg(ex); + this.codeABC(OP_SETUPVAL, e, var.u.info, 0); + break; + } + case LexState.VINDEXED: { + int op = (var.u.ind_vt == LexState.VLOCAL) ? OP_SETTABLE : OP_SETTABUP; + int e = this.exp2RK(ex); + this.codeABC(op, var.u.ind_t, var.u.ind_idx, e); + break; + } + default: { + _assert (false); /* invalid var kind to store */ + break; + } } this.freeexp(ex); } @@ -769,21 +769,21 @@ public class FuncState extends Constants { int pc; /* pc of last jump */ this.dischargevars(e); switch (e.k) { - case LexState.VJMP: { - this.invertjump(e); - pc = e.u.info; - break; - } - case LexState.VK: - case LexState.VKNUM: - case LexState.VTRUE: { - pc = LexState.NO_JUMP; /* always true; do nothing */ - break; - } - default: { - pc = this.jumponcond(e, 0); - break; - } + case LexState.VJMP: { + this.invertjump(e); + pc = e.u.info; + break; + } + case LexState.VK: + case LexState.VKNUM: + case LexState.VTRUE: { + pc = LexState.NO_JUMP; /* always true; do nothing */ + break; + } + default: { + pc = this.jumponcond(e, 0); + break; + } } this.concat(e.f, pc); /* insert last jump in `f' list */ this.patchtohere(e.t.i); @@ -794,19 +794,19 @@ public class FuncState extends Constants { int pc; /* pc of last jump */ this.dischargevars(e); switch (e.k) { - case LexState.VJMP: { - pc = e.u.info; - break; - } - case LexState.VNIL: - case LexState.VFALSE: { - pc = LexState.NO_JUMP; /* always false; do nothing */ - break; - } - default: { - pc = this.jumponcond(e, 1); - break; - } + case LexState.VJMP: { + pc = e.u.info; + break; + } + case LexState.VNIL: + case LexState.VFALSE: { + pc = LexState.NO_JUMP; /* always false; do nothing */ + break; + } + default: { + pc = this.jumponcond(e, 1); + break; + } } this.concat(e.t, pc); /* insert last jump in `t' list */ this.patchtohere(e.f.i); @@ -816,33 +816,33 @@ public class FuncState extends Constants { void codenot(expdesc e) { this.dischargevars(e); switch (e.k) { - case LexState.VNIL: - case LexState.VFALSE: { - e.k = LexState.VTRUE; - break; - } - case LexState.VK: - case LexState.VKNUM: - case LexState.VTRUE: { - e.k = LexState.VFALSE; - break; - } - case LexState.VJMP: { - this.invertjump(e); - break; - } - case LexState.VRELOCABLE: - case LexState.VNONRELOC: { - this.discharge2anyreg(e); - this.freeexp(e); - e.u.info = this.codeABC(OP_NOT, 0, e.u.info, 0); - e.k = LexState.VRELOCABLE; - break; - } - default: { - _assert (false); /* cannot happen */ - break; - } + case LexState.VNIL: + case LexState.VFALSE: { + e.k = LexState.VTRUE; + break; + } + case LexState.VK: + case LexState.VKNUM: + case LexState.VTRUE: { + e.k = LexState.VFALSE; + break; + } + case LexState.VJMP: { + this.invertjump(e); + break; + } + case LexState.VRELOCABLE: + case LexState.VNONRELOC: { + this.discharge2anyreg(e); + this.freeexp(e); + e.u.info = this.codeABC(OP_NOT, 0, e.u.info, 0); + e.k = LexState.VRELOCABLE; + break; + } + default: { + _assert (false); /* cannot happen */ + break; + } } /* interchange true and false lists */ { @@ -871,39 +871,39 @@ public class FuncState extends Constants { if (!e1.isnumeral() || !e2.isnumeral()) return false; if ((op == OP_DIV || op == OP_MOD) && e2.u.nval().eq_b(LuaValue.ZERO)) - return false; /* do not attempt to divide by 0 */ + return false; /* do not attempt to divide by 0 */ v1 = e1.u.nval(); v2 = e2.u.nval(); switch (op) { - case OP_ADD: - r = v1.add(v2); - break; - case OP_SUB: - r = v1.sub(v2); - break; - case OP_MUL: - r = v1.mul(v2); - break; - case OP_DIV: - r = v1.div(v2); - break; - case OP_MOD: - r = v1.mod(v2); - break; - case OP_POW: - r = v1.pow(v2); - break; - case OP_UNM: - r = v1.neg(); - break; - case OP_LEN: - // r = v1.len(); - // break; - return false; /* no constant folding for 'len' */ - default: - _assert (false); - r = null; - break; + case OP_ADD: + r = v1.add(v2); + break; + case OP_SUB: + r = v1.sub(v2); + break; + case OP_MUL: + r = v1.mul(v2); + break; + case OP_DIV: + r = v1.div(v2); + break; + case OP_MOD: + r = v1.mod(v2); + break; + case OP_POW: + r = v1.pow(v2); + break; + case OP_UNM: + r = v1.neg(); + break; + case OP_LEN: + // r = v1.len(); + // break; + return false; /* no constant folding for 'len' */ + default: + _assert (false); + r = null; + break; } if ( Double.isNaN(r.todouble()) ) return false; /* do not attempt to produce NaN */ @@ -951,131 +951,131 @@ public class FuncState extends Constants { expdesc e2 = new expdesc(); e2.init(LexState.VKNUM, 0); switch (op) { - case LexState.OPR_MINUS: { - if (e.isnumeral()) /* minus constant? */ - e.u.setNval(e.u.nval().neg()); /* fold it */ - else { - this.exp2anyreg(e); - this.codearith(OP_UNM, e, e2, line); - } - break; - } - case LexState.OPR_NOT: - this.codenot(e); - break; - case LexState.OPR_LEN: { - this.exp2anyreg(e); /* cannot operate on constants */ - this.codearith(OP_LEN, e, e2, line); - break; - } - default: - _assert (false); + case LexState.OPR_MINUS: { + if (e.isnumeral()) /* minus constant? */ + e.u.setNval(e.u.nval().neg()); /* fold it */ + else { + this.exp2anyreg(e); + this.codearith(OP_UNM, e, e2, line); + } + break; + } + case LexState.OPR_NOT: + this.codenot(e); + break; + case LexState.OPR_LEN: { + this.exp2anyreg(e); /* cannot operate on constants */ + this.codearith(OP_LEN, e, e2, line); + break; + } + default: + _assert (false); } } void infix(int /* BinOpr */op, expdesc v) { switch (op) { - case LexState.OPR_AND: { - this.goiftrue(v); - break; - } - case LexState.OPR_OR: { - this.goiffalse(v); - break; - } - case LexState.OPR_CONCAT: { - this.exp2nextreg(v); /* operand must be on the `stack' */ - break; - } - case LexState.OPR_ADD: - case LexState.OPR_SUB: - case LexState.OPR_MUL: - case LexState.OPR_DIV: - case LexState.OPR_MOD: - case LexState.OPR_POW: { - if (!v.isnumeral()) + case LexState.OPR_AND: { + this.goiftrue(v); + break; + } + case LexState.OPR_OR: { + this.goiffalse(v); + break; + } + case LexState.OPR_CONCAT: { + this.exp2nextreg(v); /* operand must be on the `stack' */ + break; + } + case LexState.OPR_ADD: + case LexState.OPR_SUB: + case LexState.OPR_MUL: + case LexState.OPR_DIV: + case LexState.OPR_MOD: + case LexState.OPR_POW: { + if (!v.isnumeral()) + this.exp2RK(v); + break; + } + default: { this.exp2RK(v); - break; - } - default: { - this.exp2RK(v); - break; - } + break; + } } } void posfix(int op, expdesc e1, expdesc e2, int line) { switch (op) { - case LexState.OPR_AND: { - _assert (e1.t.i == LexState.NO_JUMP); /* list must be closed */ - this.dischargevars(e2); - this.concat(e2.f, e1.f.i); - // *e1 = *e2; - e1.setvalue(e2); - break; - } - case LexState.OPR_OR: { - _assert (e1.f.i == LexState.NO_JUMP); /* list must be closed */ - this.dischargevars(e2); - this.concat(e2.t, e1.t.i); - // *e1 = *e2; - e1.setvalue(e2); - break; - } - case LexState.OPR_CONCAT: { - this.exp2val(e2); - if (e2.k == LexState.VRELOCABLE - && GET_OPCODE(this.getcode(e2)) == OP_CONCAT) { - _assert (e1.u.info == GETARG_B(this.getcode(e2)) - 1); - this.freeexp(e1); - SETARG_B(this.getcodePtr(e2), e1.u.info); - e1.k = LexState.VRELOCABLE; - e1.u.info = e2.u.info; - } else { - this.exp2nextreg(e2); /* operand must be on the 'stack' */ - this.codearith(OP_CONCAT, e1, e2, line); + case LexState.OPR_AND: { + _assert (e1.t.i == LexState.NO_JUMP); /* list must be closed */ + this.dischargevars(e2); + this.concat(e2.f, e1.f.i); + // *e1 = *e2; + e1.setvalue(e2); + break; } - break; - } - case LexState.OPR_ADD: - this.codearith(OP_ADD, e1, e2, line); - break; - case LexState.OPR_SUB: - this.codearith(OP_SUB, e1, e2, line); - break; - case LexState.OPR_MUL: - this.codearith(OP_MUL, e1, e2, line); - break; - case LexState.OPR_DIV: - this.codearith(OP_DIV, e1, e2, line); - break; - case LexState.OPR_MOD: - this.codearith(OP_MOD, e1, e2, line); - break; - case LexState.OPR_POW: - this.codearith(OP_POW, e1, e2, line); - break; - case LexState.OPR_EQ: - this.codecomp(OP_EQ, 1, e1, e2); - break; - case LexState.OPR_NE: - this.codecomp(OP_EQ, 0, e1, e2); - break; - case LexState.OPR_LT: - this.codecomp(OP_LT, 1, e1, e2); - break; - case LexState.OPR_LE: - this.codecomp(OP_LE, 1, e1, e2); - break; - case LexState.OPR_GT: - this.codecomp(OP_LT, 0, e1, e2); - break; - case LexState.OPR_GE: - this.codecomp(OP_LE, 0, e1, e2); - break; - default: - _assert (false); + case LexState.OPR_OR: { + _assert (e1.f.i == LexState.NO_JUMP); /* list must be closed */ + this.dischargevars(e2); + this.concat(e2.t, e1.t.i); + // *e1 = *e2; + e1.setvalue(e2); + break; + } + case LexState.OPR_CONCAT: { + this.exp2val(e2); + if (e2.k == LexState.VRELOCABLE + && GET_OPCODE(this.getcode(e2)) == OP_CONCAT) { + _assert (e1.u.info == GETARG_B(this.getcode(e2)) - 1); + this.freeexp(e1); + SETARG_B(this.getcodePtr(e2), e1.u.info); + e1.k = LexState.VRELOCABLE; + e1.u.info = e2.u.info; + } else { + this.exp2nextreg(e2); /* operand must be on the 'stack' */ + this.codearith(OP_CONCAT, e1, e2, line); + } + break; + } + case LexState.OPR_ADD: + this.codearith(OP_ADD, e1, e2, line); + break; + case LexState.OPR_SUB: + this.codearith(OP_SUB, e1, e2, line); + break; + case LexState.OPR_MUL: + this.codearith(OP_MUL, e1, e2, line); + break; + case LexState.OPR_DIV: + this.codearith(OP_DIV, e1, e2, line); + break; + case LexState.OPR_MOD: + this.codearith(OP_MOD, e1, e2, line); + break; + case LexState.OPR_POW: + this.codearith(OP_POW, e1, e2, line); + break; + case LexState.OPR_EQ: + this.codecomp(OP_EQ, 1, e1, e2); + break; + case LexState.OPR_NE: + this.codecomp(OP_EQ, 0, e1, e2); + break; + case LexState.OPR_LT: + this.codecomp(OP_LT, 1, e1, e2); + break; + case LexState.OPR_LE: + this.codecomp(OP_LE, 1, e1, e2); + break; + case LexState.OPR_GT: + this.codecomp(OP_LT, 0, e1, e2); + break; + case LexState.OPR_GE: + this.codecomp(OP_LE, 0, e1, e2); + break; + default: + _assert (false); } } @@ -1143,5 +1143,5 @@ public class FuncState extends Constants { } this.freereg = (short) (base + 1); /* free registers with list values */ } - -} + +} \ No newline at end of file diff --git a/src/core/org/luaj/vm2/compiler/InstructionPtr.java b/core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java similarity index 100% rename from src/core/org/luaj/vm2/compiler/InstructionPtr.java rename to core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java diff --git a/src/core/org/luaj/vm2/compiler/IntPtr.java b/core/src/main/java/org/luaj/vm2/compiler/IntPtr.java similarity index 100% rename from src/core/org/luaj/vm2/compiler/IntPtr.java rename to core/src/main/java/org/luaj/vm2/compiler/IntPtr.java diff --git a/src/core/org/luaj/vm2/compiler/LexState.java b/core/src/main/java/org/luaj/vm2/compiler/LexState.java similarity index 64% rename from src/core/org/luaj/vm2/compiler/LexState.java rename to core/src/main/java/org/luaj/vm2/compiler/LexState.java index 0192de05..e889514e 100644 --- a/src/core/org/luaj/vm2/compiler/LexState.java +++ b/core/src/main/java/org/luaj/vm2/compiler/LexState.java @@ -1,24 +1,24 @@ /******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ + * Copyright (c) 2009 Luaj.org. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ package org.luaj.vm2.compiler; import java.io.IOException; @@ -37,81 +37,81 @@ import org.luaj.vm2.lib.MathLib; public class LexState extends Constants { - + protected static final String RESERVED_LOCAL_VAR_FOR_CONTROL = "(for control)"; - protected static final String RESERVED_LOCAL_VAR_FOR_STATE = "(for state)"; - protected static final String RESERVED_LOCAL_VAR_FOR_GENERATOR = "(for generator)"; - protected static final String RESERVED_LOCAL_VAR_FOR_STEP = "(for step)"; - protected static final String RESERVED_LOCAL_VAR_FOR_LIMIT = "(for limit)"; - protected static final String RESERVED_LOCAL_VAR_FOR_INDEX = "(for index)"; - - // keywords array - protected static final String[] RESERVED_LOCAL_VAR_KEYWORDS = new String[] { - RESERVED_LOCAL_VAR_FOR_CONTROL, - RESERVED_LOCAL_VAR_FOR_GENERATOR, - RESERVED_LOCAL_VAR_FOR_INDEX, - RESERVED_LOCAL_VAR_FOR_LIMIT, - RESERVED_LOCAL_VAR_FOR_STATE, - RESERVED_LOCAL_VAR_FOR_STEP - }; - private static final Hashtable RESERVED_LOCAL_VAR_KEYWORDS_TABLE = new Hashtable(); - static { - for ( int i=0; i=", "<=", "~=", - "::", "", "", "", "", "", + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", + "::", "", "", "", "", "", }; final static int - /* terminal symbols denoted by reserved words */ - TK_AND=257, TK_BREAK=258, TK_DO=259, TK_ELSE=260, TK_ELSEIF=261, - TK_END=262, TK_FALSE=263, TK_FOR=264, TK_FUNCTION=265, TK_GOTO=266, TK_IF=267, - TK_IN=268, TK_LOCAL=269, TK_NIL=270, TK_NOT=271, TK_OR=272, TK_REPEAT=273, - TK_RETURN=274, TK_THEN=275, TK_TRUE=276, TK_UNTIL=277, TK_WHILE=278, - /* other terminal symbols */ - TK_CONCAT=279, TK_DOTS=280, TK_EQ=281, TK_GE=282, TK_LE=283, TK_NE=284, - TK_DBCOLON=285, TK_EOS=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289; - + /* terminal symbols denoted by reserved words */ + TK_AND=257, TK_BREAK=258, TK_DO=259, TK_ELSE=260, TK_ELSEIF=261, + TK_END=262, TK_FALSE=263, TK_FOR=264, TK_FUNCTION=265, TK_GOTO=266, TK_IF=267, + TK_IN=268, TK_LOCAL=269, TK_NIL=270, TK_NOT=271, TK_OR=272, TK_REPEAT=273, + TK_RETURN=274, TK_THEN=275, TK_TRUE=276, TK_UNTIL=277, TK_WHILE=278, + /* other terminal symbols */ + TK_CONCAT=279, TK_DOTS=280, TK_EQ=281, TK_GE=282, TK_LE=283, TK_NE=284, + TK_DBCOLON=285, TK_EOS=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289; + final static int FIRST_RESERVED = TK_AND; final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED; - + final static Hashtable RESERVED = new Hashtable(); static { for ( int i=0; i= '0' && c <= '9') - || (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c == '_'); + || (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c == '_'); // return Character.isLetterOrDigit(c); } - + private boolean isalpha(int c) { return (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z'); + || (c >= 'A' && c <= 'Z'); } - + private boolean isdigit(int c) { return (c >= '0' && c <= '9'); } - + private boolean isxdigit(int c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } - + private boolean isspace(int c) { return (c >= 0 && c <= ' '); } - - + + public LexState(LuaC.CompileState state, InputStream stream) { this.z = stream; this.buff = new char[32]; @@ -210,7 +210,7 @@ public class LexState extends Constants { void nextChar() { try { - current = z.read(); + current = z.read(); } catch ( IOException e ) { e.printStackTrace(); current = EOZ; @@ -249,12 +249,12 @@ public class LexState extends Constants { String txtToken(int token) { switch ( token ) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: - return new String( buff, 0, nbuff ); - default: - return token2str( token ); + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + return new String( buff, 0, nbuff ); + default: + return token2str( token ); } } @@ -303,20 +303,20 @@ public class LexState extends Constants { this.current = firstByte; /* read first char */ this.skipShebang(); } - + private void skipShebang() { if ( current == '#' ) while (!currIsNewline() && current != EOZ) nextChar(); } - + /* - ** ======================================================= - ** LEXICAL ANALYZER - ** ======================================================= - */ + ** ======================================================= + ** LEXICAL ANALYZER + ** ======================================================= + */ boolean check_next(String set) { @@ -382,7 +382,7 @@ public class LexState extends Constants { } return LuaValue.valueOf(sgn * m * MathLib.dpow_d(2.0, e)); } - + boolean str2d(String str, SemInfo seminfo) { if (str.indexOf('n')>=0 || str.indexOf('N')>=0) seminfo.r = LuaValue.ZERO; @@ -436,47 +436,47 @@ public class LexState extends Constants { inclinenumber(); /* skip it */ for (boolean endloop = false; !endloop;) { switch (current) { - case EOZ: - lexerror((seminfo != null) ? "unfinished long string" - : "unfinished long comment", TK_EOS); - break; /* to avoid warnings */ - case '[': { - if (skip_sep() == sep) { - save_and_next(); /* skip 2nd `[' */ - cont++; - if (LUA_COMPAT_LSTR == 1) { - if (sep == 0) - lexerror("nesting of [[...]] is deprecated", '['); + case EOZ: + lexerror((seminfo != null) ? "unfinished long string" + : "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ + case '[': { + if (skip_sep() == sep) { + save_and_next(); /* skip 2nd `[' */ + cont++; + if (LUA_COMPAT_LSTR == 1) { + if (sep == 0) + lexerror("nesting of [[...]] is deprecated", '['); + } } + break; } - break; - } - case ']': { - if (skip_sep() == sep) { - save_and_next(); /* skip 2nd `]' */ - if (LUA_COMPAT_LSTR == 2) { - cont--; - if (sep == 0 && cont >= 0) - break; + case ']': { + if (skip_sep() == sep) { + save_and_next(); /* skip 2nd `]' */ + if (LUA_COMPAT_LSTR == 2) { + cont--; + if (sep == 0 && cont >= 0) + break; + } + endloop = true; } - endloop = true; + break; + } + case '\n': + case '\r': { + save('\n'); + inclinenumber(); + if (seminfo == null) + nbuff = 0; /* avoid wasting space */ + break; + } + default: { + if (seminfo != null) + save_and_next(); + else + nextChar(); } - break; - } - case '\n': - case '\r': { - save('\n'); - inclinenumber(); - if (seminfo == null) - nbuff = 0; /* avoid wasting space */ - break; - } - default: { - if (seminfo != null) - save_and_next(); - else - nextChar(); - } } } if (seminfo != null) @@ -501,79 +501,79 @@ public class LexState extends Constants { save_and_next(); while (current != del) { switch (current) { - case EOZ: - lexerror("unfinished string", TK_EOS); - continue; /* to avoid warnings */ - case '\n': - case '\r': - lexerror("unfinished string", TK_STRING); - continue; /* to avoid warnings */ - case '\\': { - int c; - nextChar(); /* do not save the `\' */ - switch (current) { - case 'a': /* bell */ - c = '\u0007'; - break; - case 'b': /* backspace */ - c = '\b'; - break; - case 'f': /* form feed */ - c = '\f'; - break; - case 'n': /* newline */ - c = '\n'; - break; - case 'r': /* carriage return */ - c = '\r'; - break; - case 't': /* tab */ - c = '\t'; - break; - case 'v': /* vertical tab */ - c = '\u000B'; - break; - case 'x': - c = readhexaesc(); - break; - case '\n': /* go through */ - case '\r': - save('\n'); - inclinenumber(); - continue; case EOZ: - continue; /* will raise an error next loop */ - case 'z': { /* zap following span of spaces */ - nextChar(); /* skip the 'z' */ - while (isspace(current)) { - if (currIsNewline()) inclinenumber(); - else nextChar(); - } - continue; - } - default: { - if (!isdigit(current)) - save_and_next(); /* handles \\, \", \', and \? */ - else { /* \xxx */ - int i = 0; - c = 0; - do { - c = 10 * c + (current - '0'); - nextChar(); - } while (++i < 3 && isdigit(current)); - if (c > UCHAR_MAX) - lexerror("escape sequence too large", TK_STRING); - save(c); + lexerror("unfinished string", TK_EOS); + continue; /* to avoid warnings */ + case '\n': + case '\r': + lexerror("unfinished string", TK_STRING); + continue; /* to avoid warnings */ + case '\\': { + int c; + nextChar(); /* do not save the `\' */ + switch (current) { + case 'a': /* bell */ + c = '\u0007'; + break; + case 'b': /* backspace */ + c = '\b'; + break; + case 'f': /* form feed */ + c = '\f'; + break; + case 'n': /* newline */ + c = '\n'; + break; + case 'r': /* carriage return */ + c = '\r'; + break; + case 't': /* tab */ + c = '\t'; + break; + case 'v': /* vertical tab */ + c = '\u000B'; + break; + case 'x': + c = readhexaesc(); + break; + case '\n': /* go through */ + case '\r': + save('\n'); + inclinenumber(); + continue; + case EOZ: + continue; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + nextChar(); /* skip the 'z' */ + while (isspace(current)) { + if (currIsNewline()) inclinenumber(); + else nextChar(); + } + continue; + } + default: { + if (!isdigit(current)) + save_and_next(); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int i = 0; + c = 0; + do { + c = 10 * c + (current - '0'); + nextChar(); + } while (++i < 3 && isdigit(current)); + if (c > UCHAR_MAX) + lexerror("escape sequence too large", TK_STRING); + save(c); + } + continue; + } } + save(c); + nextChar(); continue; } - } - save(c); - nextChar(); - continue; - } - default: - save_and_next(); + default: + save_and_next(); } } save_and_next(); /* skip delimiter */ @@ -584,140 +584,140 @@ public class LexState extends Constants { nbuff = 0; while (true) { switch (current) { - case '\n': - case '\r': { - inclinenumber(); - continue; - } - case ' ': - case '\f': - case '\t': - case 0x0B: /* \v */ { - nextChar(); - continue; - } - case '-': { - nextChar(); - if (current != '-') - return '-'; - /* else is a comment */ - nextChar(); - if (current == '[') { + case '\n': + case '\r': { + inclinenumber(); + continue; + } + case ' ': + case '\f': + case '\t': + case 0x0B: /* \v */ { + nextChar(); + continue; + } + case '-': { + nextChar(); + if (current != '-') + return '-'; + /* else is a comment */ + nextChar(); + if (current == '[') { + int sep = skip_sep(); + nbuff = 0; /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(null, sep); /* long comment */ + nbuff = 0; + continue; + } + } + /* else short comment */ + while (!currIsNewline() && current != EOZ) + nextChar(); + continue; + } + case '[': { int sep = skip_sep(); - nbuff = 0; /* `skip_sep' may dirty the buffer */ if (sep >= 0) { - read_long_string(null, sep); /* long comment */ - nbuff = 0; - continue; + read_long_string(seminfo, sep); + return TK_STRING; + } else if (sep == -1) + return '['; + else + lexerror("invalid long string delimiter", TK_STRING); + } + case '=': { + nextChar(); + if (current != '=') + return '='; + else { + nextChar(); + return TK_EQ; } } - /* else short comment */ - while (!currIsNewline() && current != EOZ) + case '<': { nextChar(); - continue; - } - case '[': { - int sep = skip_sep(); - if (sep >= 0) { - read_long_string(seminfo, sep); + if (current != '=') + return '<'; + else { + nextChar(); + return TK_LE; + } + } + case '>': { + nextChar(); + if (current != '=') + return '>'; + else { + nextChar(); + return TK_GE; + } + } + case '~': { + nextChar(); + if (current != '=') + return '~'; + else { + nextChar(); + return TK_NE; + } + } + case ':': { + nextChar(); + if (current != ':') + return ':'; + else { + nextChar(); + return TK_DBCOLON; + } + } + case '"': + case '\'': { + read_string(current, seminfo); return TK_STRING; - } else if (sep == -1) - return '['; - else - lexerror("invalid long string delimiter", TK_STRING); - } - case '=': { - nextChar(); - if (current != '=') - return '='; - else { - nextChar(); - return TK_EQ; } - } - case '<': { - nextChar(); - if (current != '=') - return '<'; - else { - nextChar(); - return TK_LE; + case '.': { + save_and_next(); + if (check_next(".")) { + if (check_next(".")) + return TK_DOTS; /* ... */ + else + return TK_CONCAT; /* .. */ + } else if (!isdigit(current)) + return '.'; + else { + read_numeral(seminfo); + return TK_NUMBER; + } } - } - case '>': { - nextChar(); - if (current != '=') - return '>'; - else { - nextChar(); - return TK_GE; - } - } - case '~': { - nextChar(); - if (current != '=') - return '~'; - else { - nextChar(); - return TK_NE; - } - } - case ':': { - nextChar(); - if (current != ':') - return ':'; - else { - nextChar(); - return TK_DBCOLON; - } - } - case '"': - case '\'': { - read_string(current, seminfo); - return TK_STRING; - } - case '.': { - save_and_next(); - if (check_next(".")) { - if (check_next(".")) - return TK_DOTS; /* ... */ - else - return TK_CONCAT; /* .. */ - } else if (!isdigit(current)) - return '.'; - else { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { read_numeral(seminfo); return TK_NUMBER; } - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - read_numeral(seminfo); - return TK_NUMBER; - } - case EOZ: { - return TK_EOS; - } - default: { - if (isalpha(current) || current == '_') { - /* identifier or reserved word */ - LuaString ts; - do { - save_and_next(); - } while (isalnum(current)); - ts = newstring(buff, 0, nbuff); - if ( RESERVED.containsKey(ts) ) - return ((Integer)RESERVED.get(ts)).intValue(); - else { - seminfo.ts = ts; - return TK_NAME; - } - } else { - int c = current; - nextChar(); - return c; /* single-char tokens (+ - / ...) */ + case EOZ: { + return TK_EOS; + } + default: { + if (isalpha(current) || current == '_') { + /* identifier or reserved word */ + LuaString ts; + do { + save_and_next(); + } while (isalnum(current)); + ts = newstring(buff, 0, nbuff); + if ( RESERVED.containsKey(ts) ) + return ((Integer)RESERVED.get(ts)).intValue(); + else { + seminfo.ts = ts; + return TK_NAME; + } + } else { + int c = current; + nextChar(); + return c; /* single-char tokens (+ - / ...) */ + } } - } } } } @@ -739,8 +739,8 @@ public class LexState extends Constants { // ============================================================= // from lcode.h // ============================================================= - - + + // ============================================================= // from lparser.c // ============================================================= @@ -832,8 +832,8 @@ public class LexState extends Constants { Labeldesc[] label; /* list of active labels */ int n_label = 0; }; - - + + boolean hasmultret(int k) { return ((k) == VCALL || (k) == VVARARG); } @@ -841,7 +841,7 @@ public class LexState extends Constants { /*---------------------------------------------------------------------- name args description ------------------------------------------------------------------------*/ - + void anchor_token () { /* last token from outer function must be EOS */ _assert(fs != null || t.token == TK_EOS); @@ -876,8 +876,8 @@ public class LexState extends Constants { } void checknext (int c) { - check(c); - next(); + check(c); + next(); } void check_condition(boolean c, String msg) { @@ -905,7 +905,7 @@ public class LexState extends Constants { next(); return ts; } - + void codestring(expdesc e, LuaString s) { e.init(VK, fs.stringK(s)); } @@ -914,7 +914,7 @@ public class LexState extends Constants { codestring(e, str_checkname()); } - + int registerlocalvar(LuaString varname) { FuncState fs = this.fs; Prototype f = fs.f; @@ -923,7 +923,7 @@ public class LexState extends Constants { f.locvars[fs.nlocvars] = new LocVars(varname,0,0); return fs.nlocvars++; } - + void new_localvar(LuaString name) { int reg = registerlocalvar(name); fs.checklimit(dyd.n_actvar + 1, FuncState.LUAI_MAXVARS, "local variables"); @@ -950,19 +950,19 @@ public class LexState extends Constants { while (fs.nactvar > tolevel) fs.getlocvar(--fs.nactvar).endpc = fs.pc; } - + void singlevar(expdesc var) { LuaString varname = this.str_checkname(); FuncState fs = this.fs; if (FuncState.singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ expdesc key = new expdesc(); - FuncState.singlevaraux(fs, this.envn, var, 1); /* get environment variable */ - _assert(var.k == VLOCAL || var.k == VUPVAL); - this.codestring(key, varname); /* key is variable name */ - fs.indexed(var, key); /* env[varname] */ + FuncState.singlevaraux(fs, this.envn, var, 1); /* get environment variable */ + _assert(var.k == VLOCAL || var.k == VUPVAL); + this.codestring(key, varname); /* key is variable name */ + fs.indexed(var, key); /* env[varname] */ } } - + void adjust_assign(int nvars, int nexps, expdesc e) { FuncState fs = this.fs; int extra = nvars - nexps; @@ -986,12 +986,12 @@ public class LexState extends Constants { } } } - + void enterlevel() { if (++L.nCcalls > LUAI_MAXCCALLS) lexerror("chunk has too many syntax levels", 0); } - + void leavelevel() { L.nCcalls--; } @@ -1056,11 +1056,11 @@ public class LexState extends Constants { i++; } } - + /* - ** create a label named "break" to resolve break statements - */ + ** create a label named "break" to resolve break statements + */ void breaklabel () { LuaString n = LuaString.valueOf("break"); int l = newlabelentry(dyd.label=grow(dyd.label, dyd.n_label+1), dyd.n_label++, n, 0, fs.pc); @@ -1068,50 +1068,50 @@ public class LexState extends Constants { } /* - ** generates an error for an undefined 'goto'; choose appropriate - ** message when label name is a reserved word (which can only be 'break') - */ + ** generates an error for an undefined 'goto'; choose appropriate + ** message when label name is a reserved word (which can only be 'break') + */ void undefgoto (Labeldesc gt) { - String msg = L.pushfstring(isReservedKeyword(gt.name.tojstring()) - ? "<"+gt.name+"> at line "+gt.line+" not inside a loop" - : "no visible label '"+gt.name+"' for at line "+gt.line); - semerror(msg); + String msg = L.pushfstring(isReservedKeyword(gt.name.tojstring()) + ? "<"+gt.name+"> at line "+gt.line+" not inside a loop" + : "no visible label '"+gt.name+"' for at line "+gt.line); + semerror(msg); } Prototype addprototype () { - Prototype clp; - Prototype f = fs.f; /* prototype of current function */ - if (f.p == null || fs.np >= f.p.length) { - f.p = realloc(f.p, Math.max(1, fs.np * 2)); - } - f.p[fs.np++] = clp = new Prototype(); - return clp; + Prototype clp; + Prototype f = fs.f; /* prototype of current function */ + if (f.p == null || fs.np >= f.p.length) { + f.p = realloc(f.p, Math.max(1, fs.np * 2)); + } + f.p[fs.np++] = clp = new Prototype(); + return clp; } void codeclosure (expdesc v) { - FuncState fs = this.fs.prev; - v.init(VRELOCABLE, fs.codeABx(OP_CLOSURE, 0, fs.np - 1)); - fs.exp2nextreg(v); /* fix it at stack top (for GC) */ + FuncState fs = this.fs.prev; + v.init(VRELOCABLE, fs.codeABx(OP_CLOSURE, 0, fs.np - 1)); + fs.exp2nextreg(v); /* fix it at stack top (for GC) */ } void open_func (FuncState fs, BlockCnt bl) { - fs.prev = this.fs; /* linked list of funcstates */ - fs.ls = this; - this.fs = fs; - fs.pc = 0; - fs.lasttarget = -1; - fs.jpc = new IntPtr( NO_JUMP ); - fs.freereg = 0; - fs.nk = 0; - fs.np = 0; - fs.nups = 0; - fs.nlocvars = 0; - fs.nactvar = 0; - fs.firstlocal = dyd.n_actvar; - fs.bl = null; - fs.f.source = this.source; - fs.f.maxstacksize = 2; /* registers 0/1 are always valid */ - fs.enterblock(bl, false); + fs.prev = this.fs; /* linked list of funcstates */ + fs.ls = this; + this.fs = fs; + fs.pc = 0; + fs.lasttarget = -1; + fs.jpc = new IntPtr( NO_JUMP ); + fs.freereg = 0; + fs.nk = 0; + fs.np = 0; + fs.nups = 0; + fs.nlocvars = 0; + fs.nactvar = 0; + fs.firstlocal = dyd.n_actvar; + fs.bl = null; + fs.f.source = this.source; + fs.f.maxstacksize = 2; /* registers 0/1 are always valid */ + fs.enterblock(bl, false); } void close_func() { @@ -1144,7 +1144,7 @@ public class LexState extends Constants { this.checkname(key); fs.indexed(v, key); } - + void yindex(expdesc v) { /* index -> '[' expr ']' */ this.next(); /* skip the '[' */ @@ -1154,11 +1154,11 @@ public class LexState extends Constants { } - /* - ** {====================================================================== - ** Rules for Constructors - ** ======================================================================= - */ + /* + ** {====================================================================== + ** Rules for Constructors + ** ======================================================================= + */ static class ConsControl { @@ -1192,10 +1192,10 @@ public class LexState extends Constants { } void listfield (ConsControl cc) { - this.expr(cc.v); - fs.checklimit(cc.na, MAX_INT, "items in a constructor"); - cc.na++; - cc.tostore++; + this.expr(cc.v); + fs.checklimit(cc.na, MAX_INT, "items in a constructor"); + cc.na++; + cc.tostore++; } @@ -1217,22 +1217,22 @@ public class LexState extends Constants { break; fs.closelistfield(cc); switch (this.t.token) { - case TK_NAME: { /* may be listfields or recfields */ - this.lookahead(); - if (this.lookahead.token != '=') /* expression? */ - this.listfield(cc); - else + case TK_NAME: { /* may be listfields or recfields */ + this.lookahead(); + if (this.lookahead.token != '=') /* expression? */ + this.listfield(cc); + else + this.recfield(cc); + break; + } + case '[': { /* constructor_item -> recfield */ this.recfield(cc); - break; - } - case '[': { /* constructor_item -> recfield */ - this.recfield(cc); - break; - } - default: { /* constructor_part -> listfield */ - this.listfield(cc); - break; - } + break; + } + default: { /* constructor_part -> listfield */ + this.listfield(cc); + break; + } } } while (this.testnext(',') || this.testnext(';')); this.check_match('}', '{', line); @@ -1241,51 +1241,51 @@ public class LexState extends Constants { SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */ SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */ } - + /* - ** converts an integer to a "floating point byte", represented as - ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if - ** eeeee != 0 and (xxx) otherwise. - */ + ** converts an integer to a "floating point byte", represented as + ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if + ** eeeee != 0 and (xxx) otherwise. + */ static int luaO_int2fb (int x) { - int e = 0; /* expoent */ - while (x >= 16) { - x = (x+1) >> 1; - e++; - } - if (x < 8) return x; - else return ((e+1) << 3) | (((int)x) - 8); + int e = 0; /* expoent */ + while (x >= 16) { + x = (x+1) >> 1; + e++; + } + if (x < 8) return x; + else return ((e+1) << 3) | (((int)x) - 8); } /* }====================================================================== */ void parlist () { - /* parlist -> [ param { `,' param } ] */ - FuncState fs = this.fs; - Prototype f = fs.f; - int nparams = 0; - f.is_vararg = 0; - if (this.t.token != ')') { /* is `parlist' not empty? */ - do { - switch (this.t.token) { - case TK_NAME: { /* param . NAME */ - this.new_localvar(this.str_checkname()); - ++nparams; - break; - } - case TK_DOTS: { /* param . `...' */ - this.next(); - f.is_vararg = 1; - break; - } - default: this.syntaxerror(" or " + LUA_QL("...") + " expected"); - } - } while ((f.is_vararg==0) && this.testnext(',')); - } - this.adjustlocalvars(nparams); - f.numparams = fs.nactvar; - fs.reserveregs(fs.nactvar); /* reserve register for parameters */ + /* parlist -> [ param { `,' param } ] */ + FuncState fs = this.fs; + Prototype f = fs.f; + int nparams = 0; + f.is_vararg = 0; + if (this.t.token != ')') { /* is `parlist' not empty? */ + do { + switch (this.t.token) { + case TK_NAME: { /* param . NAME */ + this.new_localvar(this.str_checkname()); + ++nparams; + break; + } + case TK_DOTS: { /* param . `...' */ + this.next(); + f.is_vararg = 1; + break; + } + default: this.syntaxerror(" or " + LUA_QL("...") + " expected"); + } + } while ((f.is_vararg==0) && this.testnext(',')); + } + this.adjustlocalvars(nparams); + f.numparams = fs.nactvar; + fs.reserveregs(fs.nactvar); /* reserve register for parameters */ } @@ -1309,7 +1309,7 @@ public class LexState extends Constants { this.codeclosure(e); this.close_func(); } - + int explist(expdesc v) { /* explist1 -> expr { `,' expr } */ int n = 1; /* at least one expression */ @@ -1328,30 +1328,30 @@ public class LexState extends Constants { expdesc args = new expdesc(); int base, nparams; switch (this.t.token) { - case '(': { /* funcargs -> `(' [ explist1 ] `)' */ - this.next(); - if (this.t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - this.explist(args); - fs.setmultret(args); + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + this.next(); + if (this.t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + this.explist(args); + fs.setmultret(args); + } + this.check_match(')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + this.constructor(args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + this.codestring(args, this.t.seminfo.ts); + this.next(); /* must use `seminfo' before `next' */ + break; + } + default: { + this.syntaxerror("function arguments expected"); + return; } - this.check_match(')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - this.constructor(args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - this.codestring(args, this.t.seminfo.ts); - this.next(); /* must use `seminfo' before `next' */ - break; - } - default: { - this.syntaxerror("function arguments expected"); - return; - } } _assert (f.k == VNONRELOC); base = f.u.info; /* base register for call */ @@ -1365,35 +1365,35 @@ public class LexState extends Constants { f.init(VCALL, fs.codeABC(Lua.OP_CALL, base, nparams + 1, 2)); fs.fixline(line); fs.freereg = (short)(base+1); /* call remove function and arguments and leaves - * (unless changed) one result */ + * (unless changed) one result */ } /* - ** {====================================================================== - ** Expression parsing - ** ======================================================================= - */ + ** {====================================================================== + ** Expression parsing + ** ======================================================================= + */ void primaryexp (expdesc v) { /* primaryexp -> NAME | '(' expr ')' */ switch (t.token) { - case '(': { - int line = linenumber; - this.next(); - this.expr(v); - this.check_match(')', '(', line); - fs.dischargevars(v); - return; - } - case TK_NAME: { - singlevar(v); - return; - } - default: { - this.syntaxerror("unexpected symbol " + t.token + " (" + ((char) t.token) + ")"); - return; - } + case '(': { + int line = linenumber; + this.next(); + this.expr(v); + this.check_match(')', '(', line); + fs.dischargevars(v); + return; + } + case TK_NAME: { + singlevar(v); + return; + } + default: { + this.syntaxerror("unexpected symbol " + t.token + " (" + ((char) t.token) + ")"); + return; + } } } @@ -1405,37 +1405,37 @@ public class LexState extends Constants { primaryexp(v); for (;;) { switch (t.token) { - case '.': { /* fieldsel */ - this.fieldsel(v); - break; - } - case '[': { /* `[' exp1 `]' */ - expdesc key = new expdesc(); - fs.exp2anyregup(v); - this.yindex(key); - fs.indexed(v, key); - break; - } - case ':': { /* `:' NAME funcargs */ - expdesc key = new expdesc(); - this.next(); - this.checkname(key); - fs.self(v, key); - this.funcargs(v, line); - break; - } - case '(': - case TK_STRING: - case '{': { /* funcargs */ - fs.exp2nextreg(v); - this.funcargs(v, line); - break; - } - default: - return; + case '.': { /* fieldsel */ + this.fieldsel(v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key = new expdesc(); + fs.exp2anyregup(v); + this.yindex(key); + fs.indexed(v, key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key = new expdesc(); + this.next(); + this.checkname(key); + fs.self(v, key); + this.funcargs(v, line); + break; + } + case '(': + case TK_STRING: + case '{': { /* funcargs */ + fs.exp2nextreg(v); + this.funcargs(v, line); + break; + } + default: + return; } } - } + } void simpleexp(expdesc v) { @@ -1444,47 +1444,47 @@ public class LexState extends Constants { * FUNCTION body | primaryexp */ switch (this.t.token) { - case TK_NUMBER: { - v.init(VKNUM, 0); - v.u.setNval(this.t.seminfo.r); - break; - } - case TK_STRING: { - this.codestring(v, this.t.seminfo.ts); - break; - } - case TK_NIL: { - v.init(VNIL, 0); - break; - } - case TK_TRUE: { - v.init(VTRUE, 0); - break; - } - case TK_FALSE: { - v.init(VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState fs = this.fs; - this.check_condition(fs.f.is_vararg!=0, "cannot use " + LUA_QL("...") - + " outside a vararg function"); - v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0)); - break; - } - case '{': { /* constructor */ - this.constructor(v); - return; - } - case TK_FUNCTION: { - this.next(); - this.body(v, false, this.linenumber); - return; - } - default: { - this.suffixedexp(v); - return; - } + case TK_NUMBER: { + v.init(VKNUM, 0); + v.u.setNval(this.t.seminfo.r); + break; + } + case TK_STRING: { + this.codestring(v, this.t.seminfo.ts); + break; + } + case TK_NIL: { + v.init(VNIL, 0); + break; + } + case TK_TRUE: { + v.init(VTRUE, 0); + break; + } + case TK_FALSE: { + v.init(VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState fs = this.fs; + this.check_condition(fs.f.is_vararg!=0, "cannot use " + LUA_QL("...") + + " outside a vararg function"); + v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + this.constructor(v); + return; + } + case TK_FUNCTION: { + this.next(); + this.body(v, false, this.linenumber); + return; + } + default: { + this.suffixedexp(v); + return; + } } this.next(); } @@ -1492,52 +1492,52 @@ public class LexState extends Constants { int getunopr(int op) { switch (op) { - case TK_NOT: - return OPR_NOT; - case '-': - return OPR_MINUS; - case '#': - return OPR_LEN; - default: - return OPR_NOUNOPR; + case TK_NOT: + return OPR_NOT; + case '-': + return OPR_MINUS; + case '#': + return OPR_LEN; + default: + return OPR_NOUNOPR; } } int getbinopr(int op) { switch (op) { - case '+': - return OPR_ADD; - case '-': - return OPR_SUB; - case '*': - return OPR_MUL; - case '/': - return OPR_DIV; - case '%': - return OPR_MOD; - case '^': - return OPR_POW; - case TK_CONCAT: - return OPR_CONCAT; - case TK_NE: - return OPR_NE; - case TK_EQ: - return OPR_EQ; - case '<': - return OPR_LT; - case TK_LE: - return OPR_LE; - case '>': - return OPR_GT; - case TK_GE: - return OPR_GE; - case TK_AND: - return OPR_AND; - case TK_OR: - return OPR_OR; - default: - return OPR_NOBINOPR; + case '+': + return OPR_ADD; + case '-': + return OPR_SUB; + case '*': + return OPR_MUL; + case '/': + return OPR_DIV; + case '%': + return OPR_MOD; + case '^': + return OPR_POW; + case TK_CONCAT: + return OPR_CONCAT; + case TK_NE: + return OPR_NE; + case TK_EQ: + return OPR_EQ; + case '<': + return OPR_LT; + case TK_LE: + return OPR_LE; + case '>': + return OPR_GT; + case TK_GE: + return OPR_GE; + case TK_AND: + return OPR_AND; + case TK_OR: + return OPR_OR; + default: + return OPR_NOBINOPR; } } @@ -1551,29 +1551,29 @@ public class LexState extends Constants { right = (byte) j; } }; - + static Priority[] priority = { /* ORDER OPR */ - new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7), new Priority(7, 7), /* `+' `-' `/' `%' */ - new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */ - new Priority(3, 3), new Priority(3, 3), /* equality and inequality */ - new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */ - new Priority(2, 2), new Priority(1, 1) /* logical (and/or) */ + new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7), new Priority(7, 7), /* `+' `-' `/' `%' */ + new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */ + new Priority(3, 3), new Priority(3, 3), /* equality and inequality */ + new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */ + new Priority(2, 2), new Priority(1, 1) /* logical (and/or) */ }; static final int UNARY_PRIORITY = 8; /* priority for unary operators */ /* - ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } - ** where `binop' is any binary operator with a priority higher than `limit' - */ + ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } + ** where `binop' is any binary operator with a priority higher than `limit' + */ int subexpr(expdesc v, int limit) { int op; int uop; this.enterlevel(); uop = getunopr(this.t.token); if (uop != OPR_NOUNOPR) { - int line = linenumber; + int line = linenumber; this.next(); this.subexpr(v, UNARY_PRIORITY); fs.prefix(uop, v, line); @@ -1604,37 +1604,37 @@ public class LexState extends Constants { /* - ** {====================================================================== - ** Rules for Statements - ** ======================================================================= - */ + ** {====================================================================== + ** Rules for Statements + ** ======================================================================= + */ boolean block_follow (boolean withuntil) { switch (t.token) { - case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOS: - return true; + case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOS: + return true; case TK_UNTIL: - return withuntil; - default: return false; + return withuntil; + default: return false; } } void block () { - /* block -> chunk */ - FuncState fs = this.fs; - BlockCnt bl = new BlockCnt(); - fs.enterblock(bl, false); - this.statlist(); - fs.leaveblock(); + /* block -> chunk */ + FuncState fs = this.fs; + BlockCnt bl = new BlockCnt(); + fs.enterblock(bl, false); + this.statlist(); + fs.leaveblock(); } /* - ** structure to chain all variables in the left-hand side of an - ** assignment - */ + ** structure to chain all variables in the left-hand side of an + ** assignment + */ static class LHS_assign { LHS_assign prev; /* variable (global, local, upvalue, or indexed) */ @@ -1643,11 +1643,11 @@ public class LexState extends Constants { /* - ** check whether, in an assignment to a local variable, the local variable - ** is needed in a previous assignment (to a table). If so, save original - ** local value in a safe place and use this safe copy in the previous - ** assignment. - */ + ** check whether, in an assignment to a local variable, the local variable + ** is needed in a previous assignment (to a table). If so, save original + ** local value in a safe place and use this safe copy in the previous + ** assignment. + */ void check_conflict (LHS_assign lh, expdesc v) { FuncState fs = this.fs; short extra = (short) fs.freereg; /* eventual position to save local variable */ @@ -1668,10 +1668,10 @@ public class LexState extends Constants { } } if (conflict) { - /* copy upvalue/local value to a temporary (in position 'extra') */ - int op = (v.k == VLOCAL) ? Lua.OP_MOVE : Lua.OP_GETUPVAL; - fs.codeABC(op, extra, v.u.info, 0); - fs.reserveregs(1); + /* copy upvalue/local value to a temporary (in position 'extra') */ + int op = (v.k == VLOCAL) ? Lua.OP_MOVE : Lua.OP_GETUPVAL; + fs.codeABC(op, extra, v.u.info, 0); + fs.reserveregs(1); } } @@ -1679,32 +1679,32 @@ public class LexState extends Constants { void assignment (LHS_assign lh, int nvars) { expdesc e = new expdesc(); this.check_condition(VLOCAL <= lh.v.k && lh.v.k <= VINDEXED, - "syntax error"); + "syntax error"); if (this.testnext(',')) { /* assignment -> `,' primaryexp assignment */ - LHS_assign nv = new LHS_assign(); - nv.prev = lh; - this.suffixedexp(nv.v); - if (nv.v.k != VINDEXED) - this.check_conflict(lh, nv.v); - this.assignment(nv, nvars+1); + LHS_assign nv = new LHS_assign(); + nv.prev = lh; + this.suffixedexp(nv.v); + if (nv.v.k != VINDEXED) + this.check_conflict(lh, nv.v); + this.assignment(nv, nvars+1); } else { /* assignment . `=' explist1 */ - int nexps; - this.checknext('='); - nexps = this.explist(e); - if (nexps != nvars) { - this.adjust_assign(nvars, nexps, e); - if (nexps > nvars) - this.fs.freereg -= nexps - nvars; /* remove extra values */ - } - else { - fs.setoneret(e); /* close last expression */ - fs.storevar(lh.v, e); - return; /* avoid default */ - } - } - e.init(VNONRELOC, this.fs.freereg-1); /* default assignment */ - fs.storevar(lh.v, e); + int nexps; + this.checknext('='); + nexps = this.explist(e); + if (nexps != nvars) { + this.adjust_assign(nvars, nexps, e); + if (nexps > nvars) + this.fs.freereg -= nexps - nvars; /* remove extra values */ + } + else { + fs.setoneret(e); /* close last expression */ + fs.storevar(lh.v, e); + return; /* avoid default */ + } + } + e.init(VNONRELOC, this.fs.freereg-1); /* default assignment */ + fs.storevar(lh.v, e); } @@ -1755,9 +1755,9 @@ public class LexState extends Constants { dyd.label[l].nactvar = fs.bl.nactvar; } findgotos(dyd.label[l]); -} + } + - void whilestat (int line) { /* whilestat -> WHILE cond DO block END */ FuncState fs = this.fs; @@ -1790,7 +1790,7 @@ public class LexState extends Constants { this.check_match(TK_UNTIL, TK_REPEAT, line); condexit = this.cond(); /* read condition (inside scope block) */ if (bl2.upval) { /* upvalues? */ - fs.patchclose(condexit, bl2.nactvar); + fs.patchclose(condexit, bl2.nactvar); } fs.leaveblock(); /* finish scope */ fs.patchlist(condexit, repeat_init); /* close the loop */ @@ -1890,15 +1890,15 @@ public class LexState extends Constants { this.next(); /* skip `for' */ varname = this.str_checkname(); /* first variable name */ switch (this.t.token) { - case '=': - this.fornum(varname, line); - break; - case ',': - case TK_IN: - this.forlist(varname); - break; - default: - this.syntaxerror(LUA_QL("=") + " or " + LUA_QL("in") + " expected"); + case '=': + this.fornum(varname, line); + break; + case ',': + case TK_IN: + this.forlist(varname); + break; + default: + this.syntaxerror(LUA_QL("=") + " or " + LUA_QL("in") + " expected"); } this.check_match(TK_END, TK_FOR, line); fs.leaveblock(); /* loop scope (`break' jumps to this point) */ @@ -1941,9 +1941,9 @@ public class LexState extends Constants { IntPtr escapelist = new IntPtr(NO_JUMP); /* exit list for finished parts */ test_then_block(escapelist); /* IF cond THEN block */ while (t.token == TK_ELSEIF) - test_then_block(escapelist); /* ELSEIF cond THEN block */ + test_then_block(escapelist); /* ELSEIF cond THEN block */ if (testnext(TK_ELSE)) - block(); /* `else' part */ + block(); /* `else' part */ check_match(TK_END, TK_IF, line); fs.patchtohere(escapelist.i); /* patch escape list to 'if' end */ } @@ -2056,63 +2056,63 @@ public class LexState extends Constants { int line = this.linenumber; /* may be needed for error messages */ enterlevel(); switch (this.t.token) { - case ';': { /* stat -> ';' (empty statement) */ - next(); /* skip ';' */ - break; - } - case TK_IF: { /* stat -> ifstat */ - this.ifstat(line); - break; - } - case TK_WHILE: { /* stat -> whilestat */ - this.whilestat(line); - break; - } - case TK_DO: { /* stat -> DO block END */ - this.next(); /* skip DO */ - this.block(); - this.check_match(TK_END, TK_DO, line); - break; - } - case TK_FOR: { /* stat -> forstat */ - this.forstat(line); - break; - } - case TK_REPEAT: { /* stat -> repeatstat */ - this.repeatstat(line); - break; - } - case TK_FUNCTION: { - this.funcstat(line); /* stat -> funcstat */ - break; - } - case TK_LOCAL: { /* stat -> localstat */ - this.next(); /* skip LOCAL */ - if (this.testnext(TK_FUNCTION)) /* local function? */ - this.localfunc(); - else - this.localstat(); - break; - } - case TK_DBCOLON: { /* stat -> label */ - next(); /* skip double colon */ - labelstat(str_checkname(), line); - break; - } - case TK_RETURN: { /* stat -> retstat */ - next(); /* skip RETURN */ - this.retstat(); - break; - } - case TK_BREAK: - case TK_GOTO: { /* stat -> breakstat */ - this.gotostat(fs.jump()); - break; - } - default: { - this.exprstat(); - break; - } + case ';': { /* stat -> ';' (empty statement) */ + next(); /* skip ';' */ + break; + } + case TK_IF: { /* stat -> ifstat */ + this.ifstat(line); + break; + } + case TK_WHILE: { /* stat -> whilestat */ + this.whilestat(line); + break; + } + case TK_DO: { /* stat -> DO block END */ + this.next(); /* skip DO */ + this.block(); + this.check_match(TK_END, TK_DO, line); + break; + } + case TK_FOR: { /* stat -> forstat */ + this.forstat(line); + break; + } + case TK_REPEAT: { /* stat -> repeatstat */ + this.repeatstat(line); + break; + } + case TK_FUNCTION: { + this.funcstat(line); /* stat -> funcstat */ + break; + } + case TK_LOCAL: { /* stat -> localstat */ + this.next(); /* skip LOCAL */ + if (this.testnext(TK_FUNCTION)) /* local function? */ + this.localfunc(); + else + this.localstat(); + break; + } + case TK_DBCOLON: { /* stat -> label */ + next(); /* skip double colon */ + labelstat(str_checkname(), line); + break; + } + case TK_RETURN: { /* stat -> retstat */ + next(); /* skip RETURN */ + this.retstat(); + break; + } + case TK_BREAK: + case TK_GOTO: { /* stat -> breakstat */ + this.gotostat(fs.jump()); + break; + } + default: { + this.exprstat(); + break; + } } _assert(fs.f.maxstacksize >= fs.freereg && fs.freereg >= fs.nactvar); @@ -2132,22 +2132,22 @@ public class LexState extends Constants { } /* - ** compiles the main function, which is a regular vararg function with an - ** upvalue named LUA_ENV - */ + ** compiles the main function, which is a regular vararg function with an + ** upvalue named LUA_ENV + */ public void mainfunc(FuncState funcstate) { - BlockCnt bl = new BlockCnt(); - open_func(funcstate, bl); - fs.f.is_vararg = 1; /* main function is always vararg */ - expdesc v = new expdesc(); - v.init(VLOCAL, 0); /* create and... */ - fs.newupvalue(envn, v); /* ...set environment upvalue */ - next(); /* read first token */ - statlist(); /* parse main body */ - check(TK_EOS); - close_func(); + BlockCnt bl = new BlockCnt(); + open_func(funcstate, bl); + fs.f.is_vararg = 1; /* main function is always vararg */ + expdesc v = new expdesc(); + v.init(VLOCAL, 0); /* create and... */ + fs.newupvalue(envn, v); /* ...set environment upvalue */ + next(); /* read first token */ + statlist(); /* parse main body */ + check(TK_EOS); + close_func(); } - + /* }====================================================================== */ - -} + +} \ No newline at end of file diff --git a/src/core/org/luaj/vm2/compiler/LuaC.java b/core/src/main/java/org/luaj/vm2/compiler/LuaC.java similarity index 98% rename from src/core/org/luaj/vm2/compiler/LuaC.java rename to core/src/main/java/org/luaj/vm2/compiler/LuaC.java index 1e53636d..6d41ce08 100644 --- a/src/core/org/luaj/vm2/compiler/LuaC.java +++ b/core/src/main/java/org/luaj/vm2/compiler/LuaC.java @@ -43,7 +43,7 @@ import org.luaj.vm2.lib.BaseLib; * using a user-supplied environment. * *

    - * Implements the {@link org.luaj.vm2.Globals.Compiler} interface for loading + * Implements the {@link Globals.Compiler} interface for loading * initialized chunks, which is an interface common to * lua bytecode compiling and java bytecode compiling. * diff --git a/examples/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/examples/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000000000000000000000000000000000000..70daf29cb6b0fb0cde17c35eeb768907338758b3 GIT binary patch literal 17 UcmZSHv!HXq)fVM=1_)pT06Aa;WdHyG literal 0 HcmV?d00001 diff --git a/examples/android/.gradle/buildOutputCleanup/cache.properties b/examples/android/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 00000000..2598ceb3 --- /dev/null +++ b/examples/android/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sun Mar 01 11:42:21 CET 2026 +gradle.version=9.0.0 diff --git a/test/lua/errors/abc.txt b/examples/android/.gradle/vcs-1/gc.properties similarity index 100% rename from test/lua/errors/abc.txt rename to examples/android/.gradle/vcs-1/gc.properties diff --git a/examples/maven/pom.xml b/examples/maven/pom.xml index 85025c43..be00baae 100644 --- a/examples/maven/pom.xml +++ b/examples/maven/pom.xml @@ -7,16 +7,25 @@ 1.0-SNAPSHOT maven-example http://maven.apache.org + + + oac + https://repo.open-autonomous-connection.org/api/packages/open-autonomous-connection/maven + + true + + + - - org.luaj - luaj-jse - 3.0.1 - + junit junit - 3.8.1 + 4.13.2 test diff --git a/jme/pom.xml b/jme/pom.xml new file mode 100644 index 00000000..c0b7eef7 --- /dev/null +++ b/jme/pom.xml @@ -0,0 +1,122 @@ + + + 4.0.0 + + + org.openautonomousconnection.luaj + parent + 3.0.2 + + + jme + jar + + + + org.openautonomousconnection.luaj + core + ${project.version} + + + + + + jme + + + env.WTK_HOME + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + copy-sources + generate-sources + copy-resources + + ${project.build.directory}/generated-sources/luaj-jme + + + ${project.basedir}/../luaj-core/src/main/java + **/*.java + + + ${project.basedir}/src/main/java + **/*.java + + + + + + + + + com.google.code.maven-replacer-plugin + replacer + + + rewrite-branding + generate-sources + replace + + ${project.build.directory}/generated-sources/luaj-jme + **/*.java + + + "Luaj 0.0" + "${luaj.brand.jme}" + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-generated-sources + generate-sources + add-source + + + ${project.build.directory}/generated-sources/luaj-jme + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + + -bootclasspath + ${env.WTK_HOME}/lib/cldcapi11.jar${path.separator}${env.WTK_HOME}/lib/midpapi20.jar${path.separator}${env.WTK_HOME}/lib/mmapi.jar + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + jar + + + + + + + + \ No newline at end of file diff --git a/jme/src/main/java/org/openautonomousconnection/luaj/Main.java b/jme/src/main/java/org/openautonomousconnection/luaj/Main.java new file mode 100644 index 00000000..eaac0957 --- /dev/null +++ b/jme/src/main/java/org/openautonomousconnection/luaj/Main.java @@ -0,0 +1,17 @@ +package org.openautonomousconnection.luaj; + +//TIP To Run code, press or +// click the icon in the gutter. +public class Main { + static void main() { + //TIP Press with your caret at the highlighted text + // to see how IntelliJ IDEA suggests fixing it. + IO.println(String.format("Hello and welcome!")); + + for (int i = 1; i <= 5; i++) { + //TIP Press to start debugging your code. We have set one breakpoint + // for you, but you can always add more by pressing . + IO.println("i = " + i); + } + } +} diff --git a/jse/pom.xml b/jse/pom.xml new file mode 100644 index 00000000..75bd7b4c --- /dev/null +++ b/jse/pom.xml @@ -0,0 +1,134 @@ + + + 4.0.0 + + + org.openautonomousconnection.luaj + parent + 3.0.2 + + + jse + jar + + + + org.openautonomousconnection.luaj + core + ${project.version} + + + org.apache.bcel + bcel + 6.12.0 + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + copy-sources + generate-sources + copy-resources + + ${project.build.directory}/generated-sources/luaj-jse + + + ${project.basedir}/../luaj-core/src/main/java + **/*.java + + + ${project.basedir}/src/main/java + **/*.java + + + + + + + + com.google.code.maven-replacer-plugin + replacer + + + rewrite-branding-and-cleanup + generate-sources + replace + + ${project.build.directory}/generated-sources/luaj-jse + + **/*.java + + + + "Luaj 0.0" + "${luaj.brand.jse}" + + <String> + <Stat> + <Exp> + <Name> + <Block> + <TableField> + <VarExp> + <Exp.VarExp> + <Object,String> + <Double,String> + <Integer,Integer> + <Integer,LocalVariableGen> + <Exp,Integer> + <String,byte[]> + <String,Variable> + <LuaValue,String> + <LuaString,String> + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-generated-sources + generate-sources + add-source + + + ${project.build.directory}/generated-sources/luaj-jse + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + **/* + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + jar + + + + + + + \ No newline at end of file diff --git a/src/jse/lua.java b/jse/src/main/java/lua.java similarity index 100% rename from src/jse/lua.java rename to jse/src/main/java/lua.java diff --git a/src/jse/luac.java b/jse/src/main/java/luac.java similarity index 100% rename from src/jse/luac.java rename to jse/src/main/java/luac.java diff --git a/src/jse/luajc.java b/jse/src/main/java/luajc.java similarity index 100% rename from src/jse/luajc.java rename to jse/src/main/java/luajc.java diff --git a/src/jse/org/luaj/vm2/ast/Block.java b/jse/src/main/java/org/luaj/vm2/ast/Block.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/Block.java rename to jse/src/main/java/org/luaj/vm2/ast/Block.java diff --git a/src/jse/org/luaj/vm2/ast/Chunk.java b/jse/src/main/java/org/luaj/vm2/ast/Chunk.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/Chunk.java rename to jse/src/main/java/org/luaj/vm2/ast/Chunk.java diff --git a/src/jse/org/luaj/vm2/ast/Exp.java b/jse/src/main/java/org/luaj/vm2/ast/Exp.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/Exp.java rename to jse/src/main/java/org/luaj/vm2/ast/Exp.java diff --git a/src/jse/org/luaj/vm2/ast/FuncArgs.java b/jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/FuncArgs.java rename to jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java diff --git a/src/jse/org/luaj/vm2/ast/FuncBody.java b/jse/src/main/java/org/luaj/vm2/ast/FuncBody.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/FuncBody.java rename to jse/src/main/java/org/luaj/vm2/ast/FuncBody.java diff --git a/src/jse/org/luaj/vm2/ast/FuncName.java b/jse/src/main/java/org/luaj/vm2/ast/FuncName.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/FuncName.java rename to jse/src/main/java/org/luaj/vm2/ast/FuncName.java diff --git a/src/jse/org/luaj/vm2/ast/Name.java b/jse/src/main/java/org/luaj/vm2/ast/Name.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/Name.java rename to jse/src/main/java/org/luaj/vm2/ast/Name.java diff --git a/src/jse/org/luaj/vm2/ast/NameResolver.java b/jse/src/main/java/org/luaj/vm2/ast/NameResolver.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/NameResolver.java rename to jse/src/main/java/org/luaj/vm2/ast/NameResolver.java diff --git a/src/jse/org/luaj/vm2/ast/NameScope.java b/jse/src/main/java/org/luaj/vm2/ast/NameScope.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/NameScope.java rename to jse/src/main/java/org/luaj/vm2/ast/NameScope.java diff --git a/src/jse/org/luaj/vm2/ast/ParList.java b/jse/src/main/java/org/luaj/vm2/ast/ParList.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/ParList.java rename to jse/src/main/java/org/luaj/vm2/ast/ParList.java diff --git a/src/jse/org/luaj/vm2/ast/Stat.java b/jse/src/main/java/org/luaj/vm2/ast/Stat.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/Stat.java rename to jse/src/main/java/org/luaj/vm2/ast/Stat.java diff --git a/src/jse/org/luaj/vm2/ast/Str.java b/jse/src/main/java/org/luaj/vm2/ast/Str.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/Str.java rename to jse/src/main/java/org/luaj/vm2/ast/Str.java diff --git a/src/jse/org/luaj/vm2/ast/SyntaxElement.java b/jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/SyntaxElement.java rename to jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java diff --git a/src/jse/org/luaj/vm2/ast/TableConstructor.java b/jse/src/main/java/org/luaj/vm2/ast/TableConstructor.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/TableConstructor.java rename to jse/src/main/java/org/luaj/vm2/ast/TableConstructor.java diff --git a/src/jse/org/luaj/vm2/ast/TableField.java b/jse/src/main/java/org/luaj/vm2/ast/TableField.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/TableField.java rename to jse/src/main/java/org/luaj/vm2/ast/TableField.java diff --git a/src/jse/org/luaj/vm2/ast/Variable.java b/jse/src/main/java/org/luaj/vm2/ast/Variable.java similarity index 100% rename from src/jse/org/luaj/vm2/ast/Variable.java rename to jse/src/main/java/org/luaj/vm2/ast/Variable.java diff --git a/src/jse/org/luaj/vm2/ast/Visitor.java b/jse/src/main/java/org/luaj/vm2/ast/Visitor.java similarity index 99% rename from src/jse/org/luaj/vm2/ast/Visitor.java rename to jse/src/main/java/org/luaj/vm2/ast/Visitor.java index 8f49a566..ec1444ef 100644 --- a/src/jse/org/luaj/vm2/ast/Visitor.java +++ b/jse/src/main/java/org/luaj/vm2/ast/Visitor.java @@ -155,7 +155,7 @@ abstract public class Visitor { public void visitVars(List vars) { if ( vars != null ) for ( int i=0, n=vars.size(); i exps) { if ( exps != null ) diff --git a/src/jse/org/luaj/vm2/luajc/BasicBlock.java b/jse/src/main/java/org/luaj/vm2/luajc/BasicBlock.java similarity index 100% rename from src/jse/org/luaj/vm2/luajc/BasicBlock.java rename to jse/src/main/java/org/luaj/vm2/luajc/BasicBlock.java diff --git a/src/jse/org/luaj/vm2/luajc/JavaBuilder.java b/jse/src/main/java/org/luaj/vm2/luajc/JavaBuilder.java similarity index 100% rename from src/jse/org/luaj/vm2/luajc/JavaBuilder.java rename to jse/src/main/java/org/luaj/vm2/luajc/JavaBuilder.java diff --git a/src/jse/org/luaj/vm2/luajc/JavaGen.java b/jse/src/main/java/org/luaj/vm2/luajc/JavaGen.java similarity index 100% rename from src/jse/org/luaj/vm2/luajc/JavaGen.java rename to jse/src/main/java/org/luaj/vm2/luajc/JavaGen.java diff --git a/src/jse/org/luaj/vm2/luajc/JavaLoader.java b/jse/src/main/java/org/luaj/vm2/luajc/JavaLoader.java similarity index 100% rename from src/jse/org/luaj/vm2/luajc/JavaLoader.java rename to jse/src/main/java/org/luaj/vm2/luajc/JavaLoader.java diff --git a/src/jse/org/luaj/vm2/luajc/LuaJC.java b/jse/src/main/java/org/luaj/vm2/luajc/LuaJC.java similarity index 97% rename from src/jse/org/luaj/vm2/luajc/LuaJC.java rename to jse/src/main/java/org/luaj/vm2/luajc/LuaJC.java index 4b74ef4f..53117478 100644 --- a/src/jse/org/luaj/vm2/luajc/LuaJC.java +++ b/jse/src/main/java/org/luaj/vm2/luajc/LuaJC.java @@ -34,7 +34,7 @@ import org.luaj.vm2.Prototype; import org.luaj.vm2.compiler.LuaC; /** - * Implementation of {@link org.luaj.vm2.Globals.Compiler} which does direct + * Implementation of {@link Globals.Compiler} which does direct * lua-to-java-bytecode compiling. *

    * By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or @@ -59,7 +59,7 @@ import org.luaj.vm2.compiler.LuaC; * * @see Globals#compiler * @see #install(Globals) - * @see org.luaj.vm2.compiler.LuaC + * @see LuaC * @see LuaValue */ public class LuaJC implements Globals.Loader { diff --git a/src/jse/org/luaj/vm2/luajc/ProtoInfo.java b/jse/src/main/java/org/luaj/vm2/luajc/ProtoInfo.java similarity index 100% rename from src/jse/org/luaj/vm2/luajc/ProtoInfo.java rename to jse/src/main/java/org/luaj/vm2/luajc/ProtoInfo.java diff --git a/src/jse/org/luaj/vm2/luajc/UpvalInfo.java b/jse/src/main/java/org/luaj/vm2/luajc/UpvalInfo.java similarity index 100% rename from src/jse/org/luaj/vm2/luajc/UpvalInfo.java rename to jse/src/main/java/org/luaj/vm2/luajc/UpvalInfo.java diff --git a/src/jse/org/luaj/vm2/luajc/VarInfo.java b/jse/src/main/java/org/luaj/vm2/luajc/VarInfo.java similarity index 100% rename from src/jse/org/luaj/vm2/luajc/VarInfo.java rename to jse/src/main/java/org/luaj/vm2/luajc/VarInfo.java diff --git a/src/jse/org/luaj/vm2/parser/LuaParser.java b/jse/src/main/java/org/luaj/vm2/parser/LuaParser.java similarity index 99% rename from src/jse/org/luaj/vm2/parser/LuaParser.java rename to jse/src/main/java/org/luaj/vm2/parser/LuaParser.java index d7e254fd..c85664f3 100644 --- a/src/jse/org/luaj/vm2/parser/LuaParser.java +++ b/jse/src/main/java/org/luaj/vm2/parser/LuaParser.java @@ -1741,7 +1741,7 @@ public class LuaParser implements LuaParserConstants { throw generateParseException(); } - static private final class LookaheadSuccess extends java.lang.Error { } + static private final class LookaheadSuccess extends Error { } final private LookaheadSuccess jj_ls = new LookaheadSuccess(); private boolean jj_scan_token(int kind) { if (jj_scanpos == jj_lastpos) { @@ -1791,7 +1791,7 @@ public class LuaParser implements LuaParserConstants { return (jj_ntk = jj_nt.kind); } - private java.util.List jj_expentries = new java.util.ArrayList(); + private List jj_expentries = new ArrayList(); private int[] jj_expentry; private int jj_kind = -1; private int[] jj_lasttokens = new int[100]; @@ -1806,7 +1806,7 @@ public class LuaParser implements LuaParserConstants { for (int i = 0; i < jj_endpos; i++) { jj_expentry[i] = jj_lasttokens[i]; } - jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) { + jj_entries_loop: for (Iterator it = jj_expentries.iterator(); it.hasNext();) { int[] oldentry = (int[])(it.next()); if (oldentry.length == jj_expentry.length) { for (int i = 0; i < jj_expentry.length; i++) { diff --git a/src/jse/org/luaj/vm2/parser/LuaParserConstants.java b/jse/src/main/java/org/luaj/vm2/parser/LuaParserConstants.java similarity index 100% rename from src/jse/org/luaj/vm2/parser/LuaParserConstants.java rename to jse/src/main/java/org/luaj/vm2/parser/LuaParserConstants.java diff --git a/src/jse/org/luaj/vm2/parser/LuaParserTokenManager.java b/jse/src/main/java/org/luaj/vm2/parser/LuaParserTokenManager.java similarity index 100% rename from src/jse/org/luaj/vm2/parser/LuaParserTokenManager.java rename to jse/src/main/java/org/luaj/vm2/parser/LuaParserTokenManager.java diff --git a/src/jse/org/luaj/vm2/parser/ParseException.java b/jse/src/main/java/org/luaj/vm2/parser/ParseException.java similarity index 100% rename from src/jse/org/luaj/vm2/parser/ParseException.java rename to jse/src/main/java/org/luaj/vm2/parser/ParseException.java diff --git a/src/jse/org/luaj/vm2/parser/SimpleCharStream.java b/jse/src/main/java/org/luaj/vm2/parser/SimpleCharStream.java similarity index 100% rename from src/jse/org/luaj/vm2/parser/SimpleCharStream.java rename to jse/src/main/java/org/luaj/vm2/parser/SimpleCharStream.java diff --git a/src/jse/org/luaj/vm2/parser/Token.java b/jse/src/main/java/org/luaj/vm2/parser/Token.java similarity index 100% rename from src/jse/org/luaj/vm2/parser/Token.java rename to jse/src/main/java/org/luaj/vm2/parser/Token.java diff --git a/src/jse/org/luaj/vm2/parser/TokenMgrError.java b/jse/src/main/java/org/luaj/vm2/parser/TokenMgrError.java similarity index 100% rename from src/jse/org/luaj/vm2/parser/TokenMgrError.java rename to jse/src/main/java/org/luaj/vm2/parser/TokenMgrError.java diff --git a/src/jse/org/luaj/vm2/script/LuaScriptEngine.java b/jse/src/main/java/org/luaj/vm2/script/LuaScriptEngine.java similarity index 54% rename from src/jse/org/luaj/vm2/script/LuaScriptEngine.java rename to jse/src/main/java/org/luaj/vm2/script/LuaScriptEngine.java index 415c885c..7c85a6e0 100644 --- a/src/jse/org/luaj/vm2/script/LuaScriptEngine.java +++ b/jse/src/main/java/org/luaj/vm2/script/LuaScriptEngine.java @@ -1,24 +1,24 @@ /******************************************************************************* -* Copyright (c) 2008-2013 LuaJ. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ + * Copyright (c) 2008-2013 LuaJ. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ package org.luaj.vm2.script; import java.io.*; @@ -33,7 +33,7 @@ import org.luaj.vm2.lib.jse.CoerceJavaToLua; /** * Implementation of the ScriptEngine interface which can compile and execute * scripts using luaj. - * + * *

    * This engine requires the types of the Bindings and ScriptContext to be * compatible with the engine. For creating new client context use @@ -42,35 +42,35 @@ import org.luaj.vm2.lib.jse.CoerceJavaToLua; * construct a {@link LuajBindings} directly. */ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngine, Compilable { - - private static final String __ENGINE_VERSION__ = Lua._VERSION; - private static final String __NAME__ = "Luaj"; - private static final String __SHORT_NAME__ = "Luaj"; - private static final String __LANGUAGE__ = "lua"; - private static final String __LANGUAGE_VERSION__ = "5.2"; - private static final String __ARGV__ = "arg"; - private static final String __FILENAME__ = "?"; - - private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory(); - - private LuajContext context; - public LuaScriptEngine() { - // set up context - context = new LuajContext(); - context.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE); - setContext(context); - - // set special values - put(LANGUAGE_VERSION, __LANGUAGE_VERSION__); - put(LANGUAGE, __LANGUAGE__); - put(ENGINE, __NAME__); - put(ENGINE_VERSION, __ENGINE_VERSION__); - put(ARGV, __ARGV__); - put(FILENAME, __FILENAME__); - put(NAME, __SHORT_NAME__); - put("THREADING", null); - } + private static final String __ENGINE_VERSION__ = Lua._VERSION; + private static final String __NAME__ = "Luaj"; + private static final String __SHORT_NAME__ = "Luaj"; + private static final String __LANGUAGE__ = "lua"; + private static final String __LANGUAGE_VERSION__ = "5.2"; + private static final String __ARGV__ = "arg"; + private static final String __FILENAME__ = "?"; + + private static final ScriptEngineFactory myFactory = new LuaScriptEngineFactory(); + + private LuajContext context; + + public LuaScriptEngine() { + // set up context + context = new LuajContext(); + context.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE); + setContext(context); + + // set special values + put(LANGUAGE_VERSION, __LANGUAGE_VERSION__); + put(LANGUAGE, __LANGUAGE__); + put(ENGINE, __NAME__); + put(ENGINE_VERSION, __ENGINE_VERSION__); + put(ARGV, __ARGV__); + put(FILENAME, __FILENAME__); + put(NAME, __SHORT_NAME__); + put("THREADING", null); + } @Override public CompiledScript compile(String script) throws ScriptException { @@ -80,14 +80,14 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin @Override public CompiledScript compile(Reader script) throws ScriptException { try { - InputStream is = new Utf8Encoder(script); - try { - final Globals g = context.globals; - final LuaFunction f = g.load(script, "script").checkfunction(); - return new LuajCompiledScript(f, g); + InputStream is = new Utf8Encoder(script); + try { + final Globals g = context.globals; + final LuaFunction f = g.load(script, "script").checkfunction(); + return new LuajCompiledScript(f, g); } catch ( LuaError lee ) { throw new ScriptException(lee.getMessage() ); - } finally { + } finally { is.close(); } } catch ( Exception e ) { @@ -124,7 +124,7 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin @Override public Object eval(Reader reader, ScriptContext context) throws ScriptException { - return compile(reader).eval(context); + return compile(reader).eval(context); } @Override @@ -145,20 +145,20 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin return LuaScriptEngine.this; } - public Object eval() throws ScriptException { - return eval(getContext()); - } - - public Object eval(Bindings bindings) throws ScriptException { - return eval(((LuajContext) getContext()).globals, bindings); - } - - public Object eval(ScriptContext context) throws ScriptException { - return eval(((LuajContext) context).globals, context.getBindings(ScriptContext.ENGINE_SCOPE)); + public Object eval() throws ScriptException { + return eval(getContext()); } - - Object eval(Globals g, Bindings b) throws ScriptException { - g.setmetatable(new BindingsMetatable(b)); + + public Object eval(Bindings bindings) throws ScriptException { + return eval(((LuajContext) getContext()).globals, bindings); + } + + public Object eval(ScriptContext context) throws ScriptException { + return eval(((LuajContext) context).globals, context.getBindings(ScriptContext.ENGINE_SCOPE)); + } + + Object eval(Globals g, Bindings b) throws ScriptException { + g.setmetatable(new BindingsMetatable(b)); LuaFunction f = function; if (f.isclosure()) f = new LuaClosure(f.checkclosure().p, g); @@ -193,22 +193,22 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin return c; n = 0; if ( c < 0x800 ) { - buf[n++] = (0x80 | ( c & 0x3f)); + buf[n++] = (0x80 | ( c & 0x3f)); return (0xC0 | ((c>>6) & 0x1f)); } else { - buf[n++] = (0x80 | ( c & 0x3f)); + buf[n++] = (0x80 | ( c & 0x3f)); buf[n++] = (0x80 | ((c>>6) & 0x3f)); return (0xE0 | ((c>>12) & 0x0f)); } } } - + static class BindingsMetatable extends LuaTable { BindingsMetatable(final Bindings bindings) { this.rawset(LuaValue.INDEX, new TwoArgFunction() { public LuaValue call(LuaValue table, LuaValue key) { - if (key.isstring()) + if (key.isstring()) return toLua(bindings.get(key.tojstring())); else return this.rawget(key); @@ -231,36 +231,36 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin }); } } - + static private LuaValue toLua(Object javaValue) { return javaValue == null? LuaValue.NIL: - javaValue instanceof LuaValue? (LuaValue) javaValue: - CoerceJavaToLua.coerce(javaValue); + javaValue instanceof LuaValue? (LuaValue) javaValue: + CoerceJavaToLua.coerce(javaValue); } static private Object toJava(LuaValue luajValue) { switch ( luajValue.type() ) { - case LuaValue.TNIL: return null; - case LuaValue.TSTRING: return luajValue.tojstring(); - case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class); - case LuaValue.TNUMBER: return luajValue.isinttype()? - (Object) new Integer(luajValue.toint()): - (Object) new Double(luajValue.todouble()); - default: return luajValue; + case LuaValue.TNIL: return null; + case LuaValue.TSTRING: return luajValue.tojstring(); + case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class); + case LuaValue.TNUMBER: return luajValue.isinttype()? + luajValue.toint(): + luajValue.todouble(); + default: return luajValue; } } static private Object toJava(Varargs v) { final int n = v.narg(); switch (n) { - case 0: return null; - case 1: return toJava(v.arg1()); - default: - Object[] o = new Object[n]; - for (int i=0; i expected = new java.util.ArrayList(); + java.util.List expected = new ArrayList(); Varargs n; int i; for (n = t.next(LuaValue.NIL), i = 0; !n.arg1().isnil(); n = t.next(n.arg1()), ++i) { @@ -410,7 +410,7 @@ public class TableTest extends TestCase { t.set(n.arg1(), LuaValue.NIL); } // Iterate over remaining table, and form list of entries still in table. - java.util.List actual = new java.util.ArrayList(); + java.util.List actual = new ArrayList(); for (n = t.next(LuaValue.NIL); !n.arg1().isnil(); n = t.next(n.arg1())) { actual.add(n.arg1() + "=" + n.arg(2)); } diff --git a/test/junit/org/luaj/vm2/TypeTest.java b/jse/src/test/java/org/luaj/vm2/TypeTest.java similarity index 100% rename from test/junit/org/luaj/vm2/TypeTest.java rename to jse/src/test/java/org/luaj/vm2/TypeTest.java diff --git a/test/junit/org/luaj/vm2/UTF8StreamTest.java b/jse/src/test/java/org/luaj/vm2/UTF8StreamTest.java similarity index 100% rename from test/junit/org/luaj/vm2/UTF8StreamTest.java rename to jse/src/test/java/org/luaj/vm2/UTF8StreamTest.java diff --git a/test/junit/org/luaj/vm2/UnaryBinaryOperatorsTest.java b/jse/src/test/java/org/luaj/vm2/UnaryBinaryOperatorsTest.java similarity index 100% rename from test/junit/org/luaj/vm2/UnaryBinaryOperatorsTest.java rename to jse/src/test/java/org/luaj/vm2/UnaryBinaryOperatorsTest.java diff --git a/test/junit/org/luaj/vm2/VarargsTest.java b/jse/src/test/java/org/luaj/vm2/VarargsTest.java similarity index 100% rename from test/junit/org/luaj/vm2/VarargsTest.java rename to jse/src/test/java/org/luaj/vm2/VarargsTest.java diff --git a/test/junit/org/luaj/vm2/WeakTableTest.java b/jse/src/test/java/org/luaj/vm2/WeakTableTest.java similarity index 100% rename from test/junit/org/luaj/vm2/WeakTableTest.java rename to jse/src/test/java/org/luaj/vm2/WeakTableTest.java diff --git a/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java b/jse/src/test/java/org/luaj/vm2/compiler/AbstractUnitTests.java similarity index 94% rename from test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java rename to jse/src/test/java/org/luaj/vm2/compiler/AbstractUnitTests.java index dd29a9cb..5e4fb3a4 100644 --- a/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java +++ b/jse/src/test/java/org/luaj/vm2/compiler/AbstractUnitTests.java @@ -1,22 +1,16 @@ package org.luaj.vm2.compiler; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.net.MalformedURLException; -import java.net.URL; - import junit.framework.TestCase; - import org.luaj.vm2.Globals; -import org.luaj.vm2.LoadState; import org.luaj.vm2.Print; import org.luaj.vm2.Prototype; +import org.luaj.vm2.compiler.DumpState; import org.luaj.vm2.lib.jse.JsePlatform; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; + abstract public class AbstractUnitTests extends TestCase { private final String dir; diff --git a/test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java b/jse/src/test/java/org/luaj/vm2/compiler/CompilerUnitTests.java similarity index 100% rename from test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java rename to jse/src/test/java/org/luaj/vm2/compiler/CompilerUnitTests.java diff --git a/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java b/jse/src/test/java/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java similarity index 93% rename from test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java rename to jse/src/test/java/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java index 69437a58..066af4c9 100644 --- a/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java +++ b/jse/src/test/java/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java @@ -1,24 +1,12 @@ package org.luaj.vm2.compiler; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; - import junit.framework.TestCase; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LoadState; -import org.luaj.vm2.LuaClosure; -import org.luaj.vm2.LuaFunction; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Prototype; +import org.luaj.vm2.*; +import org.luaj.vm2.compiler.DumpState; import org.luaj.vm2.lib.jse.JsePlatform; +import java.io.*; + public class DumpLoadEndianIntTest extends TestCase { private static final String SAVECHUNKS = "SAVECHUNKS"; diff --git a/test/junit/org/luaj/vm2/compiler/LuaParserTests.java b/jse/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java similarity index 93% rename from test/junit/org/luaj/vm2/compiler/LuaParserTests.java rename to jse/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java index 3c9c9d21..834e2674 100644 --- a/test/junit/org/luaj/vm2/compiler/LuaParserTests.java +++ b/jse/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java @@ -1,12 +1,13 @@ package org.luaj.vm2.compiler; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.compiler.CompilerUnitTests; +import org.luaj.vm2.parser.LuaParser; + import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.parser.LuaParser; - public class LuaParserTests extends CompilerUnitTests { protected void setUp() throws Exception { diff --git a/test/junit/org/luaj/vm2/compiler/RegressionTests.java b/jse/src/test/java/org/luaj/vm2/compiler/RegressionTests.java similarity index 100% rename from test/junit/org/luaj/vm2/compiler/RegressionTests.java rename to jse/src/test/java/org/luaj/vm2/compiler/RegressionTests.java diff --git a/test/junit/org/luaj/vm2/compiler/SimpleTests.java b/jse/src/test/java/org/luaj/vm2/compiler/SimpleTests.java similarity index 99% rename from test/junit/org/luaj/vm2/compiler/SimpleTests.java rename to jse/src/test/java/org/luaj/vm2/compiler/SimpleTests.java index 993a9861..3055d281 100644 --- a/test/junit/org/luaj/vm2/compiler/SimpleTests.java +++ b/jse/src/test/java/org/luaj/vm2/compiler/SimpleTests.java @@ -1,7 +1,6 @@ package org.luaj.vm2.compiler; import junit.framework.TestCase; - import org.luaj.vm2.Globals; import org.luaj.vm2.LuaDouble; import org.luaj.vm2.LuaInteger; diff --git a/test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java b/jse/src/test/java/org/luaj/vm2/require/RequireSampleClassCastExcep.java similarity index 100% rename from test/junit/org/luaj/vm2/require/RequireSampleClassCastExcep.java rename to jse/src/test/java/org/luaj/vm2/require/RequireSampleClassCastExcep.java diff --git a/test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java b/jse/src/test/java/org/luaj/vm2/require/RequireSampleLoadLuaError.java similarity index 100% rename from test/junit/org/luaj/vm2/require/RequireSampleLoadLuaError.java rename to jse/src/test/java/org/luaj/vm2/require/RequireSampleLoadLuaError.java diff --git a/test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java b/jse/src/test/java/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java similarity index 100% rename from test/junit/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java rename to jse/src/test/java/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java diff --git a/test/junit/org/luaj/vm2/require/RequireSampleSuccess.java b/jse/src/test/java/org/luaj/vm2/require/RequireSampleSuccess.java similarity index 100% rename from test/junit/org/luaj/vm2/require/RequireSampleSuccess.java rename to jse/src/test/java/org/luaj/vm2/require/RequireSampleSuccess.java diff --git a/test/junit/org/luaj/vm2/script/ScriptEngineTests.java b/jse/src/test/java/org/luaj/vm2/script/ScriptEngineTests.java similarity index 100% rename from test/junit/org/luaj/vm2/script/ScriptEngineTests.java rename to jse/src/test/java/org/luaj/vm2/script/ScriptEngineTests.java diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..e242bf3b --- /dev/null +++ b/pom.xml @@ -0,0 +1,149 @@ + + + 4.0.0 + + org.openautonomousconnection.luaj + parent + 3.0.2 + pom + + + core + jse + jme + + + + UTF-8 + 8 + jse ${project.version} + jme ${project.version} + + + + + MIT License + https://opensource.org/license/mit + The license is readable in the LICENSE-File + + + + + + Enby + https://github.com/Enyby + LuaJ + https://github.com/luaj + + + Benjamin P. Jung + https://github.com/headcr4sh + LuaJ + https://github.com/luaj + + + Lorenzo Stanco + https://github.com/lorenzos + LuaJ + https://github.com/luaj + + + Mikhael-Danilov + https://github.com/Mikhael-Danilov + LuaJ + https://github.com/luaj + + + zaoqi + https://github.com/zaoqi + LuaJ + https://github.com/luaj + + + James Roseborough + + + Ian Farmer + + + Open Autonomous Connection + https://open-autonomous-connection.org/ + Open Autonomous Connection + https://open-autonomous-connection.org/ + + + + + Issue Tracker + https://repo.open-autonomous-connection.org/open-autonomous-connection/luaj/issues + + + + + oac + LuaJ + https://repo.open-autonomous-connection.org/api/packages/open-autonomous-connection/maven + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.3 + + false + false + none + en_US + UTF-8 + UTF-8 + UTF-8 + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + ${maven.compiler.release} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.8.0 + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + + + \ No newline at end of file diff --git a/src/core/org/luaj/vm2/LuaThread.java b/src/core/org/luaj/vm2/LuaThread.java deleted file mode 100644 index a085abee..00000000 --- a/src/core/org/luaj/vm2/LuaThread.java +++ /dev/null @@ -1,260 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2007-2012 LuaJ. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2; - - -import java.lang.ref.WeakReference; - -/** - * Subclass of {@link LuaValue} that implements - * a lua coroutine thread using Java Threads. - *

    - * A LuaThread is typically created in response to a scripted call to - * {@code coroutine.create()} - *

    - * The threads must be initialized with the globals, so that - * the global environment may be passed along according to rules of lua. - * This is done via the constructor arguments {@link #LuaThread(Globals)} or - * {@link #LuaThread(Globals, LuaValue)}. - *

    - * The utility classes {@link org.luaj.vm2.lib.jse.JsePlatform} and - * {@link org.luaj.vm2.lib.jme.JmePlatform} - * see to it that this {@link Globals} are initialized properly. - *

    - * The behavior of coroutine threads matches closely the behavior - * of C coroutine library. However, because of the use of Java threads - * to manage call state, it is possible to yield from anywhere in luaj. - *

    - * Each Java thread wakes up at regular intervals and checks a weak reference - * to determine if it can ever be resumed. If not, it throws - * {@link OrphanedThread} which is an {@link java.lang.Error}. - * Applications should not catch {@link OrphanedThread}, because it can break - * the thread safety of luaj. The value controlling the polling interval - * is {@link #thread_orphan_check_interval} and may be set by the user. - *

    - * There are two main ways to abandon a coroutine. The first is to call - * {@code yield()} from lua, or equivalently {@link Globals#yield(Varargs)}, - * and arrange to have it never resumed possibly by values passed to yield. - * The second is to throw {@link OrphanedThread}, which should put the thread - * in a dead state. In either case all references to the thread must be - * dropped, and the garbage collector must run for the thread to be - * garbage collected. - * - * - * @see LuaValue - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see org.luaj.vm2.lib.CoroutineLib - */ -public class LuaThread extends LuaValue { - - /** Shared metatable for lua threads. */ - public static LuaValue s_metatable; - - /** The current number of coroutines. Should not be set. */ - public static int coroutine_count = 0; - - /** Polling interval, in milliseconds, which each thread uses while waiting to - * return from a yielded state to check if the lua threads is no longer - * referenced and therefore should be garbage collected. - * A short polling interval for many threads will consume server resources. - * Orphaned threads cannot be detected and collected unless garbage - * collection is run. This can be changed by Java startup code if desired. - */ - public static long thread_orphan_check_interval = 5000; - - public static final int STATUS_INITIAL = 0; - public static final int STATUS_SUSPENDED = 1; - public static final int STATUS_RUNNING = 2; - public static final int STATUS_NORMAL = 3; - public static final int STATUS_DEAD = 4; - public static final String[] STATUS_NAMES = { - "suspended", - "suspended", - "running", - "normal", - "dead",}; - - public final State state; - - public static final int MAX_CALLSTACK = 256; - - /** Thread-local used by DebugLib to store debugging state. - * This is an opaque value that should not be modified by applications. */ - public Object callstack; - - public final Globals globals; - - /** Error message handler for this thread, if any. */ - public LuaValue errorfunc; - - /** Private constructor for main thread only */ - public LuaThread(Globals globals) { - state = new State(globals, this, null); - state.status = STATUS_RUNNING; - this.globals = globals; - } - - /** - * Create a LuaThread around a function and environment - * @param func The function to execute - */ - public LuaThread(Globals globals, LuaValue func) { - LuaValue.assert_(func != null, "function cannot be null"); - state = new State(globals, this, func); - this.globals = globals; - } - - public int type() { - return LuaValue.TTHREAD; - } - - public String typename() { - return "thread"; - } - - public boolean isthread() { - return true; - } - - public LuaThread optthread(LuaThread defval) { - return this; - } - - public LuaThread checkthread() { - return this; - } - - public LuaValue getmetatable() { - return s_metatable; - } - - public String getStatus() { - return STATUS_NAMES[state.status]; - } - - public boolean isMainThread() { - return this.state.function == null; - } - - public Varargs resume(Varargs args) { - final LuaThread.State s = this.state; - if (s.status > LuaThread.STATUS_SUSPENDED) - return LuaValue.varargsOf(LuaValue.FALSE, - LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine")); - return s.lua_resume(this, args); - } - - public static class State implements Runnable { - private final Globals globals; - final WeakReference lua_thread; - public final LuaValue function; - Varargs args = LuaValue.NONE; - Varargs result = LuaValue.NONE; - String error = null; - - /** Hook function control state used by debug lib. */ - public LuaValue hookfunc; - - public boolean hookline; - public boolean hookcall; - public boolean hookrtrn; - public int hookcount; - public boolean inhook; - public int lastline; - public int bytecodes; - - public int status = LuaThread.STATUS_INITIAL; - - State(Globals globals, LuaThread lua_thread, LuaValue function) { - this.globals = globals; - this.lua_thread = new WeakReference(lua_thread); - this.function = function; - } - - public synchronized void run() { - try { - Varargs a = this.args; - this.args = LuaValue.NONE; - this.result = function.invoke(a); - } catch (Throwable t) { - this.error = t.getMessage(); - } finally { - this.status = LuaThread.STATUS_DEAD; - this.notify(); - } - } - - public synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) { - LuaThread previous_thread = globals.running; - try { - globals.running = new_thread; - this.args = args; - if (this.status == STATUS_INITIAL) { - this.status = STATUS_RUNNING; - new Thread(this, "Coroutine-"+(++coroutine_count)).start(); - } else { - this.notify(); - } - if (previous_thread != null) - previous_thread.state.status = STATUS_NORMAL; - this.status = STATUS_RUNNING; - this.wait(); - return (this.error != null? - LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)): - LuaValue.varargsOf(LuaValue.TRUE, this.result)); - } catch (InterruptedException ie) { - throw new OrphanedThread(); - } finally { - this.args = LuaValue.NONE; - this.result = LuaValue.NONE; - this.error = null; - globals.running = previous_thread; - if (previous_thread != null) - globals.running.state.status =STATUS_RUNNING; - } - } - - public synchronized Varargs lua_yield(Varargs args) { - try { - this.result = args; - this.status = STATUS_SUSPENDED; - this.notify(); - do { - this.wait(thread_orphan_check_interval); - if (this.lua_thread.get() == null) { - this.status = STATUS_DEAD; - throw new OrphanedThread(); - } - } while (this.status == STATUS_SUSPENDED); - return this.args; - } catch (InterruptedException ie) { - this.status = STATUS_DEAD; - throw new OrphanedThread(); - } finally { - this.args = LuaValue.NONE; - this.result = LuaValue.NONE; - } - } - } - -} diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java deleted file mode 100644 index fb86825b..00000000 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ /dev/null @@ -1,485 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import java.io.IOException; -import java.io.InputStream; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.Lua; -import org.luaj.vm2.LuaError; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaThread; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Subclass of {@link LibFunction} which implements the lua basic library functions. - *

    - * This contains all library functions listed as "basic functions" in the lua documentation for JME. - * The functions dofile and loadfile use the - * {@link Globals#finder} instance to find resource files. - * Since JME has no file system by default, {@link BaseLib} implements - * {@link ResourceFinder} using {@link Class#getResource(String)}, - * which is the closest equivalent on JME. - * The default loader chain in {@link PackageLib} will use these as well. - *

    - * To use basic library functions that include a {@link ResourceFinder} based on - * directory lookup, use {@link org.luaj.vm2.lib.jse.JseBaseLib} instead. - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or - * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * globals.get("print").call(LuaValue.valueOf("hello, world"));
    - * } 
    - *

    - * For special cases where the smallest possible footprint is desired, - * a minimal set of libraries could be loaded - * directly via {@link Globals#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.get("print").call(LuaValue.valueOf("hello, world"));
    - * } 
    - * Doing so will ensure the library is properly initialized - * and loaded into the globals table. - *

    - * This is a direct port of the corresponding library in C. - * @see org.luaj.vm2.lib.jse.JseBaseLib - * @see ResourceFinder - * @see Globals#finder - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 Base Lib Reference - */ -public class BaseLib extends TwoArgFunction implements ResourceFinder { - - Globals globals; - - - /** Perform one-time initialization on the library by adding base functions - * to the supplied environment, and returning it as the return value. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, which must be a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - globals = env.checkglobals(); - globals.finder = this; - globals.baselib = this; - env.set( "_G", env ); - env.set( "_VERSION", Lua._VERSION ); - env.set("assert", new _assert()); - env.set("collectgarbage", new collectgarbage()); - env.set("dofile", new dofile()); - env.set("error", new error()); - env.set("getmetatable", new getmetatable()); - env.set("load", new load()); - env.set("loadfile", new loadfile()); - env.set("pcall", new pcall()); - env.set("print", new print(this)); - env.set("rawequal", new rawequal()); - env.set("rawget", new rawget()); - env.set("rawlen", new rawlen()); - env.set("rawset", new rawset()); - env.set("select", new select()); - env.set("setmetatable", new setmetatable()); - env.set("tonumber", new tonumber()); - env.set("tostring", new tostring()); - env.set("type", new type()); - env.set("xpcall", new xpcall()); - - next next; - env.set("next", next = new next()); - env.set("pairs", new pairs(next)); - env.set("ipairs", new ipairs()); - - return env; - } - - /** ResourceFinder implementation - * - * Tries to open the file as a resource, which can work for JSE and JME. - */ - public InputStream findResource(String filename) { - return getClass().getResourceAsStream(filename.startsWith("/")? filename: "/"+filename); - } - - - // "assert", // ( v [,message] ) -> v, message | ERR - static final class _assert extends VarArgFunction { - public Varargs invoke(Varargs args) { - if ( !args.arg1().toboolean() ) - error( args.narg()>1? args.optjstring(2,"assertion failed!"): "assertion failed!" ); - return args; - } - } - - // "collectgarbage", // ( opt [,arg] ) -> value - static final class collectgarbage extends VarArgFunction { - public Varargs invoke(Varargs args) { - String s = args.optjstring(1, "collect"); - if ( "collect".equals(s) ) { - System.gc(); - return ZERO; - } else if ( "count".equals(s) ) { - Runtime rt = Runtime.getRuntime(); - long used = rt.totalMemory() - rt.freeMemory(); - return varargsOf(valueOf(used/1024.), valueOf(used%1024)); - } else if ( "step".equals(s) ) { - System.gc(); - return LuaValue.TRUE; - } else { - argerror(1, "invalid option '" + s + "'"); - } - return NIL; - } - } - - // "dofile", // ( filename ) -> result1, ... - final class dofile extends VarArgFunction { - public Varargs invoke(Varargs args) { - args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil"); - String filename = args.isstring(1)? args.tojstring(1): null; - Varargs v = filename == null? - loadStream( globals.STDIN, "=stdin", "bt", globals ): - loadFile( args.checkjstring(1), "bt", globals ); - return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke(); - } - } - - // "error", // ( message [,level] ) -> ERR - static final class error extends TwoArgFunction { - public LuaValue call(LuaValue arg1, LuaValue arg2) { - if (arg1.isnil()) throw new LuaError(NIL); - if (!arg1.isstring() || arg2.optint(1) == 0) throw new LuaError(arg1); - throw new LuaError(arg1.tojstring(), arg2.optint(1)); - } - } - - // "getmetatable", // ( object ) -> table - static final class getmetatable extends LibFunction { - public LuaValue call() { - return argerror(1, "value expected"); - } - public LuaValue call(LuaValue arg) { - LuaValue mt = arg.getmetatable(); - return mt!=null? mt.rawget(METATABLE).optvalue(mt): NIL; - } - } - // "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg - final class load extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue ld = args.arg1(); - if (!ld.isstring() && !ld.isfunction()) { - throw new LuaError("bad argument #1 to 'load' (string or function expected, got " + ld.typename() + ")"); - } - String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)"); - String mode = args.optjstring(3, "bt"); - LuaValue env = args.optvalue(4, globals); - return loadStream(ld.isstring()? ld.strvalue().toInputStream(): - new StringInputStream(ld.checkfunction()), source, mode, env); - } - } - - // "loadfile", // ( [filename [, mode [, env]]] ) -> chunk | nil, msg - final class loadfile extends VarArgFunction { - public Varargs invoke(Varargs args) { - args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil"); - String filename = args.isstring(1)? args.tojstring(1): null; - String mode = args.optjstring(2, "bt"); - LuaValue env = args.optvalue(3, globals); - return filename == null? - loadStream( globals.STDIN, "=stdin", mode, env ): - loadFile( filename, mode, env ); - } - } - - // "pcall", // (f, arg1, ...) -> status, result1, ... - final class pcall extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue func = args.checkvalue(1); - if (globals != null && globals.debuglib != null) - globals.debuglib.onCall(this); - try { - return varargsOf(TRUE, func.invoke(args.subargs(2))); - } catch ( LuaError le ) { - final LuaValue m = le.getMessageObject(); - return varargsOf(FALSE, m!=null? m: NIL); - } catch ( Exception e ) { - final String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); - } finally { - if (globals != null && globals.debuglib != null) - globals.debuglib.onReturn(); - } - } - } - - // "print", // (...) -> void - final class print extends VarArgFunction { - final BaseLib baselib; - print(BaseLib baselib) { - this.baselib = baselib; - } - public Varargs invoke(Varargs args) { - LuaValue tostring = globals.get("tostring"); - for ( int i=1, n=args.narg(); i<=n; i++ ) { - if ( i>1 ) globals.STDOUT.print( '\t' ); - LuaString s = tostring.call( args.arg(i) ).strvalue(); - globals.STDOUT.print(s.tojstring()); - } - globals.STDOUT.print('\n'); - return NONE; - } - } - - - // "rawequal", // (v1, v2) -> boolean - static final class rawequal extends LibFunction { - public LuaValue call() { - return argerror(1, "value expected"); - } - public LuaValue call(LuaValue arg) { - return argerror(2, "value expected"); - } - public LuaValue call(LuaValue arg1, LuaValue arg2) { - return valueOf(arg1.raweq(arg2)); - } - } - - // "rawget", // (table, index) -> value - static final class rawget extends TableLibFunction { - public LuaValue call(LuaValue arg) { - return argerror(2, "value expected"); - } - public LuaValue call(LuaValue arg1, LuaValue arg2) { - return arg1.checktable().rawget(arg2); - } - } - - - // "rawlen", // (v) -> value - static final class rawlen extends LibFunction { - public LuaValue call(LuaValue arg) { - return valueOf(arg.rawlen()); - } - } - - // "rawset", // (table, index, value) -> table - static final class rawset extends TableLibFunction { - public LuaValue call(LuaValue table) { - return argerror(2,"value expected"); - } - public LuaValue call(LuaValue table, LuaValue index) { - return argerror(3,"value expected"); - } - public LuaValue call(LuaValue table, LuaValue index, LuaValue value) { - LuaTable t = table.checktable(); - if (!index.isvalidkey()) argerror(2, "table index is nil"); - t.rawset(index, value); - return t; - } - } - - // "select", // (f, ...) -> value1, ... - static final class select extends VarArgFunction { - public Varargs invoke(Varargs args) { - int n = args.narg()-1; - if ( args.arg1().equals(valueOf("#")) ) - return valueOf(n); - int i = args.checkint(1); - if ( i == 0 || i < -n ) - argerror(1,"index out of range"); - return args.subargs(i<0? n+i+2: i+1); - } - } - - // "setmetatable", // (table, metatable) -> table - static final class setmetatable extends TableLibFunction { - public LuaValue call(LuaValue table) { - return argerror(2,"nil or table expected"); - } - public LuaValue call(LuaValue table, LuaValue metatable) { - final LuaValue mt0 = table.checktable().getmetatable(); - if ( mt0!=null && !mt0.rawget(METATABLE).isnil() ) - error("cannot change a protected metatable"); - return table.setmetatable(metatable.isnil()? null: metatable.checktable()); - } - } - - // "tonumber", // (e [,base]) -> value - static final class tonumber extends LibFunction { - public LuaValue call(LuaValue e) { - return e.tonumber(); - } - public LuaValue call(LuaValue e, LuaValue base) { - if (base.isnil()) - return e.tonumber(); - final int b = base.checkint(); - if ( b < 2 || b > 36 ) - argerror(2, "base out of range"); - return e.checkstring().tonumber(b); - } - } - - // "tostring", // (e) -> value - static final class tostring extends LibFunction { - public LuaValue call(LuaValue arg) { - LuaValue h = arg.metatag(TOSTRING); - if ( ! h.isnil() ) - return h.call(arg); - LuaValue v = arg.tostring(); - if ( ! v.isnil() ) - return v; - return valueOf(arg.tojstring()); - } - } - - // "type", // (v) -> value - static final class type extends LibFunction { - public LuaValue call(LuaValue arg) { - return valueOf(arg.typename()); - } - } - - // "xpcall", // (f, err) -> result1, ... - final class xpcall extends VarArgFunction { - public Varargs invoke(Varargs args) { - final LuaThread t = globals.running; - final LuaValue preverror = t.errorfunc; - t.errorfunc = args.checkvalue(2); - try { - if (globals != null && globals.debuglib != null) - globals.debuglib.onCall(this); - try { - return varargsOf(TRUE, args.arg1().invoke(args.subargs(3))); - } catch ( LuaError le ) { - final LuaValue m = le.getMessageObject(); - return varargsOf(FALSE, m!=null? m: NIL); - } catch ( Exception e ) { - final String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); - } finally { - if (globals != null && globals.debuglib != null) - globals.debuglib.onReturn(); - } - } finally { - t.errorfunc = preverror; - } - } - } - - // "pairs" (t) -> iter-func, t, nil - static final class pairs extends VarArgFunction { - final next next; - pairs(next next) { - this.next = next; - } - 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 ); - } - } - - // "next" ( table, [index] ) -> next-index, next-value - static final class next extends VarArgFunction { - public Varargs invoke(Varargs args) { - return args.checktable(1).next(args.arg(2)); - } - } - - // "inext" ( table, [int-index] ) -> next-index, next-value - static final class inext extends VarArgFunction { - public Varargs invoke(Varargs args) { - return args.checktable(1).inext(args.arg(2)); - } - } - - /** - * Load from a named file, returning the chunk or nil,error of can't load - * @param env - * @param mode - * @return Varargs containing chunk, or NIL,error-text on error - */ - public Varargs loadFile(String filename, String mode, LuaValue env) { - InputStream is = globals.finder.findResource(filename); - if ( is == null ) - return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory")); - try { - return loadStream(is, "@"+filename, mode, env); - } finally { - try { - is.close(); - } catch ( Exception e ) { - e.printStackTrace(); - } - } - } - - public Varargs loadStream(InputStream is, String chunkname, String mode, LuaValue env) { - try { - if ( is == null ) - return varargsOf(NIL, valueOf("not found: "+chunkname)); - return globals.load(is, chunkname, mode, env); - } catch (Exception e) { - return varargsOf(NIL, valueOf(e.getMessage())); - } - } - - - private static class StringInputStream extends InputStream { - final LuaValue func; - byte[] bytes; - int offset, remaining = 0; - StringInputStream(LuaValue func) { - this.func = func; - } - public int read() throws IOException { - if ( remaining < 0 ) - return -1; - if ( remaining == 0 ) { - LuaValue s = func.call(); - if ( s.isnil() ) - return remaining = -1; - LuaString ls = s.strvalue(); - bytes = ls.m_bytes; - offset = ls.m_offset; - remaining = ls.m_length; - if (remaining <= 0) - return -1; - } - --remaining; - return 0xFF&bytes[offset++]; - } - } -} diff --git a/src/core/org/luaj/vm2/lib/Bit32Lib.java b/src/core/org/luaj/vm2/lib/Bit32Lib.java deleted file mode 100644 index 699c6945..00000000 --- a/src/core/org/luaj/vm2/lib/Bit32Lib.java +++ /dev/null @@ -1,224 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2012 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Subclass of LibFunction that implements the Lua standard {@code bit32} library. - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("bit32").get("bnot").call( LuaValue.valueOf(2) ) );
    - * } 
    - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new Bit32Lib());
    - * System.out.println( globals.get("bit32").get("bnot").call( LuaValue.valueOf(2) ) );
    - * } 
    - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 Bitwise Operation Lib Reference - */ -public class Bit32Lib extends TwoArgFunction { - - public Bit32Lib() { - } - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, which must be a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - LuaTable t = new LuaTable(); - bind(t, Bit32LibV.class, new String[] { - "band", "bnot", "bor", "btest", "bxor", "extract", "replace" - }); - bind(t, Bit32Lib2.class, new String[] { - "arshift", "lrotate", "lshift", "rrotate", "rshift" - }); - env.set("bit32", t); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("bit32", t); - return t; - } - - static final class Bit32LibV extends VarArgFunction { - public Varargs invoke(Varargs args) { - switch ( opcode ) { - case 0: return Bit32Lib.band( args ); - case 1: return Bit32Lib.bnot( args ); - case 2: return Bit32Lib.bor( args ); - case 3: return Bit32Lib.btest( args ); - case 4: return Bit32Lib.bxor( args ); - case 5: - return Bit32Lib.extract( args.checkint(1), args.checkint(2), args.optint(3, 1) ); - case 6: - return Bit32Lib.replace( args.checkint(1), args.checkint(2), - args.checkint(3), args.optint(4, 1) ); - } - return NIL; - } - } - - static final class Bit32Lib2 extends TwoArgFunction { - - public LuaValue call(LuaValue arg1, LuaValue arg2) { - switch ( opcode ) { - case 0: return Bit32Lib.arshift(arg1.checkint(), arg2.checkint()); - case 1: return Bit32Lib.lrotate(arg1.checkint(), arg2.checkint()); - case 2: return Bit32Lib.lshift(arg1.checkint(), arg2.checkint()); - case 3: return Bit32Lib.rrotate(arg1.checkint(), arg2.checkint()); - case 4: return Bit32Lib.rshift(arg1.checkint(), arg2.checkint()); - } - return NIL; - } - - } - - static LuaValue arshift(int x, int disp) { - if (disp >= 0) { - return bitsToValue(x >> disp); - } else { - return bitsToValue(x << -disp); - } - } - - static LuaValue rshift(int x, int disp) { - if (disp >= 32 || disp <= -32) { - return ZERO; - } else if (disp >= 0) { - return bitsToValue(x >>> disp); - } else { - return bitsToValue(x << -disp); - } - } - - static LuaValue lshift(int x, int disp) { - if (disp >= 32 || disp <= -32) { - return ZERO; - } else if (disp >= 0) { - return bitsToValue(x << disp); - } else { - return bitsToValue(x >>> -disp); - } - } - - static Varargs band( Varargs args ) { - int result = -1; - for ( int i = 1; i <= args.narg(); i++ ) { - result &= args.checkint(i); - } - return bitsToValue( result ); - } - - static Varargs bnot( Varargs args ) { - return bitsToValue( ~args.checkint(1) ); - } - - static Varargs bor( Varargs args ) { - int result = 0; - for ( int i = 1; i <= args.narg(); i++ ) { - result |= args.checkint(i); - } - return bitsToValue( result ); - } - - static Varargs btest( Varargs args ) { - int bits = -1; - for ( int i = 1; i <= args.narg(); i++ ) { - bits &= args.checkint(i); - } - return valueOf( bits != 0 ); - } - - static Varargs bxor( Varargs args ) { - int result = 0; - for ( int i = 1; i <= args.narg(); i++ ) { - result ^= args.checkint(i); - } - return bitsToValue( result ); - } - - static LuaValue lrotate(int x, int disp) { - if (disp < 0) { - return rrotate(x, -disp); - } else { - disp = disp & 31; - return bitsToValue((x << disp) | (x >>> (32 - disp))); - } - } - - static LuaValue rrotate(int x, int disp) { - if (disp < 0) { - return lrotate(x, -disp); - } else { - disp = disp & 31; - return bitsToValue((x >>> disp) | (x << (32 - disp))); - } - } - - static LuaValue extract(int n, int field, int width) { - if (field < 0) { - argerror(2, "field cannot be negative"); - } - if (width < 0) { - argerror(3, "width must be postive"); - } - if (field + width > 32) { - error("trying to access non-existent bits"); - } - return bitsToValue((n >>> field) & (-1 >>> (32 - width))); - } - - static LuaValue replace(int n, int v, int field, int width) { - if (field < 0) { - argerror(3, "field cannot be negative"); - } - if (width < 0) { - argerror(4, "width must be postive"); - } - if (field + width > 32) { - error("trying to access non-existent bits"); - } - int mask = (-1 >>> (32 - width)) << field; - n = (n & ~mask) | ((v << field) & mask); - return bitsToValue(n); - } - - private static LuaValue bitsToValue( int x ) { - return ( x < 0 ) ? valueOf((double) ((long) x & 0xFFFFFFFFL)) : valueOf(x); - } -} diff --git a/src/core/org/luaj/vm2/lib/CoroutineLib.java b/src/core/org/luaj/vm2/lib/CoroutineLib.java deleted file mode 100644 index 28cb246b..00000000 --- a/src/core/org/luaj/vm2/lib/CoroutineLib.java +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2007-2011 LuaJ. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaThread; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Subclass of {@link LibFunction} which implements the lua standard {@code coroutine} - * library. - *

    - * The coroutine library in luaj has the same behavior as the - * coroutine library in C, but is implemented using Java Threads to maintain - * the call state between invocations. Therefore it can be yielded from anywhere, - * similar to the "Coco" yield-from-anywhere patch available for C-based lua. - * However, coroutines that are yielded but never resumed to complete their execution - * may not be collected by the garbage collector. - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("coroutine").get("running").call() );
    - * } 
    - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new CoroutineLib());
    - * System.out.println( globals.get("coroutine").get("running").call() );
    - * } 
    - *

    - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 Coroutine Lib Reference - */ -public class CoroutineLib extends TwoArgFunction { - - static int coroutine_count = 0; - - Globals globals; - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, which must be a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - globals = env.checkglobals(); - LuaTable coroutine = new LuaTable(); - coroutine.set("create", new create()); - coroutine.set("resume", new resume()); - coroutine.set("running", new running()); - coroutine.set("status", new status()); - coroutine.set("yield", new yield()); - coroutine.set("wrap", new wrap()); - env.set("coroutine", coroutine); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("coroutine", coroutine); - return coroutine; - } - - final class create extends LibFunction { - public LuaValue call(LuaValue f) { - return new LuaThread(globals, f.checkfunction()); - } - } - - static final class resume extends VarArgFunction { - public Varargs invoke(Varargs args) { - final LuaThread t = args.checkthread(1); - return t.resume( args.subargs(2) ); - } - } - - final class running extends VarArgFunction { - public Varargs invoke(Varargs args) { - final LuaThread r = globals.running; - return varargsOf(r, valueOf(r.isMainThread())); - } - } - - static final class status extends LibFunction { - public LuaValue call(LuaValue t) { - LuaThread lt = t.checkthread(); - return valueOf( lt.getStatus() ); - } - } - - final class yield extends VarArgFunction { - public Varargs invoke(Varargs args) { - return globals.yield( args ); - } - } - - final class wrap extends LibFunction { - public LuaValue call(LuaValue f) { - final LuaValue func = f.checkfunction(); - final LuaThread thread = new LuaThread(globals, func); - return new wrapper(thread); - } - } - - static final class wrapper extends VarArgFunction { - final LuaThread luathread; - wrapper(LuaThread luathread) { - this.luathread = luathread; - } - public Varargs invoke(Varargs args) { - final Varargs result = luathread.resume(args); - if ( result.arg1().toboolean() ) { - return result.subargs(2); - } else { - return error( result.arg(2).tojstring() ); - } - } - } -} diff --git a/src/core/org/luaj/vm2/lib/DebugLib.java b/src/core/org/luaj/vm2/lib/DebugLib.java deleted file mode 100644 index 167ea36c..00000000 --- a/src/core/org/luaj/vm2/lib/DebugLib.java +++ /dev/null @@ -1,899 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.Lua; -import org.luaj.vm2.LuaBoolean; -import org.luaj.vm2.LuaClosure; -import org.luaj.vm2.LuaError; -import org.luaj.vm2.LuaFunction; -import org.luaj.vm2.LuaNil; -import org.luaj.vm2.LuaNumber; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaThread; -import org.luaj.vm2.LuaUserdata; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Print; -import org.luaj.vm2.Prototype; -import org.luaj.vm2.Varargs; - -/** - * Subclass of {@link LibFunction} which implements the lua standard {@code debug} - * library. - *

    - * The debug library in luaj tries to emulate the behavior of the corresponding C-based lua library. - * To do this, it must maintain a separate stack of calls to {@link LuaClosure} and {@link LibFunction} - * instances. - * Especially when lua-to-java bytecode compiling is being used - * via a {@link org.luaj.vm2.Globals.Compiler} such as {@link org.luaj.vm2.luajc.LuaJC}, - * this cannot be done in all cases. - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#debugGlobals()} or - * {@link org.luaj.vm2.lib.jme.JmePlatform#debugGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.debugGlobals();
    - * System.out.println( globals.get("debug").get("traceback").call() );
    - * } 
    - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new DebugLib());
    - * System.out.println( globals.get("debug").get("traceback").call() );
    - * } 
    - *

    - * This library exposes the entire state of lua code, and provides method to see and modify - * all underlying lua values within a Java VM so should not be exposed to client code - * in a shared server environment. - * - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 Debug Lib Reference - */ -public class DebugLib extends TwoArgFunction { - public static boolean CALLS; - public static boolean TRACE; - static { - try { CALLS = (null != System.getProperty("CALLS")); } catch (Exception e) {} - try { TRACE = (null != System.getProperty("TRACE")); } catch (Exception e) {} - } - - static final LuaString LUA = valueOf("Lua"); - private static final LuaString QMARK = valueOf("?"); - private static final LuaString CALL = valueOf("call"); - private static final LuaString LINE = valueOf("line"); - private static final LuaString COUNT = valueOf("count"); - private static final LuaString RETURN = valueOf("return"); - - static final LuaString FUNC = valueOf("func"); - static final LuaString ISTAILCALL = valueOf("istailcall"); - static final LuaString ISVARARG = valueOf("isvararg"); - static final LuaString NUPS = valueOf("nups"); - static final LuaString NPARAMS = valueOf("nparams"); - static final LuaString NAME = valueOf("name"); - static final LuaString NAMEWHAT = valueOf("namewhat"); - static final LuaString WHAT = valueOf("what"); - static final LuaString SOURCE = valueOf("source"); - static final LuaString SHORT_SRC = valueOf("short_src"); - static final LuaString LINEDEFINED = valueOf("linedefined"); - static final LuaString LASTLINEDEFINED = valueOf("lastlinedefined"); - static final LuaString CURRENTLINE = valueOf("currentline"); - static final LuaString ACTIVELINES = valueOf("activelines"); - - Globals globals; - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, which must be a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - globals = env.checkglobals(); - globals.debuglib = this; - LuaTable debug = new LuaTable(); - debug.set("debug", new debug()); - debug.set("gethook", new gethook()); - debug.set("getinfo", new getinfo()); - debug.set("getlocal", new getlocal()); - debug.set("getmetatable", new getmetatable()); - debug.set("getregistry", new getregistry()); - debug.set("getupvalue", new getupvalue()); - debug.set("getuservalue", new getuservalue()); - debug.set("sethook", new sethook()); - debug.set("setlocal", new setlocal()); - debug.set("setmetatable", new setmetatable()); - debug.set("setupvalue", new setupvalue()); - debug.set("setuservalue", new setuservalue()); - debug.set("traceback", new traceback()); - debug.set("upvalueid", new upvalueid()); - debug.set("upvaluejoin", new upvaluejoin()); - env.set("debug", debug); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("debug", debug); - return debug; - } - - // debug.debug() - static final class debug extends ZeroArgFunction { - public LuaValue call() { - return NONE; - } - } - - // debug.gethook ([thread]) - final class gethook extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaThread t = args.narg() > 0 ? args.checkthread(1): globals.running; - LuaThread.State s = t.state; - return varargsOf( - s.hookfunc != null? s.hookfunc: NIL, - valueOf((s.hookcall?"c":"")+(s.hookline?"l":"")+(s.hookrtrn?"r":"")), - valueOf(s.hookcount)); - } - } - - // debug.getinfo ([thread,] f [, what]) - final class getinfo extends VarArgFunction { - public Varargs invoke(Varargs args) { - int a=1; - LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running; - LuaValue func = args.arg(a++); - String what = args.optjstring(a++, "flnStu"); - DebugLib.CallStack callstack = callstack(thread); - - // find the stack info - DebugLib.CallFrame frame; - if ( func.isnumber() ) { - frame = callstack.getCallFrame(func.toint()); - if (frame == null) - return NONE; - func = frame.f; - } else if ( func.isfunction() ) { - frame = callstack.findCallFrame(func); - } else { - return argerror(a-2, "function or level"); - } - - // start a table - DebugInfo ar = callstack.auxgetinfo(what, (LuaFunction) func, frame); - LuaTable info = new LuaTable(); - if (what.indexOf('S') >= 0) { - info.set(WHAT, LUA); - info.set(SOURCE, valueOf(ar.source)); - info.set(SHORT_SRC, valueOf(ar.short_src)); - info.set(LINEDEFINED, valueOf(ar.linedefined)); - info.set(LASTLINEDEFINED, valueOf(ar.lastlinedefined)); - } - if (what.indexOf('l') >= 0) { - info.set( CURRENTLINE, valueOf(ar.currentline) ); - } - if (what.indexOf('u') >= 0) { - info.set(NUPS, valueOf(ar.nups)); - info.set(NPARAMS, valueOf(ar.nparams)); - info.set(ISVARARG, ar.isvararg? ONE: ZERO); - } - if (what.indexOf('n') >= 0) { - info.set(NAME, LuaValue.valueOf(ar.name!=null? ar.name: "?")); - info.set(NAMEWHAT, LuaValue.valueOf(ar.namewhat)); - } - if (what.indexOf('t') >= 0) { - info.set(ISTAILCALL, ZERO); - } - if (what.indexOf('L') >= 0) { - LuaTable lines = new LuaTable(); - info.set(ACTIVELINES, lines); - DebugLib.CallFrame cf; - for (int l = 1; (cf=callstack.getCallFrame(l)) != null; ++l) - if (cf.f == func) - lines.insert(-1, valueOf(cf.currentline())); - } - if (what.indexOf('f') >= 0) { - if (func != null) - info.set( FUNC, func ); - } - return info; - } - } - - // debug.getlocal ([thread,] f, local) - final class getlocal extends VarArgFunction { - public Varargs invoke(Varargs args) { - int a=1; - LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running; - int level = args.checkint(a++); - int local = args.checkint(a++); - CallFrame f = callstack(thread).getCallFrame(level); - return f != null? f.getLocal(local): NONE; - } - } - - // debug.getmetatable (value) - static final class getmetatable extends LibFunction { - public LuaValue call(LuaValue v) { - LuaValue mt = v.getmetatable(); - return mt != null? mt: NIL; - } - } - - // debug.getregistry () - final class getregistry extends ZeroArgFunction { - public LuaValue call() { - return globals; - } - } - - // debug.getupvalue (f, up) - static final class getupvalue extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue func = args.checkfunction(1); - int up = args.checkint(2); - if ( func instanceof LuaClosure ) { - LuaClosure c = (LuaClosure) func; - LuaString name = findupvalue(c, up); - if ( name != null ) { - return varargsOf(name, c.upValues[up-1].getValue() ); - } - } - return NIL; - } - } - - // debug.getuservalue (u) - static final class getuservalue extends LibFunction { - public LuaValue call(LuaValue u) { - return u.isuserdata()? u: NIL; - } - } - - - // debug.sethook ([thread,] hook, mask [, count]) - final class sethook extends VarArgFunction { - public Varargs invoke(Varargs args) { - int a=1; - LuaThread t = args.isthread(a)? args.checkthread(a++): globals.running; - LuaValue func = args.optfunction(a++, null); - String str = args.optjstring(a++,""); - int count = args.optint(a++,0); - boolean call=false,line=false,rtrn=false; - for ( int i=0; i 0 && up <= c.upValues.length ) { - return valueOf(c.upValues[up-1].hashCode()); - } - } - return NIL; - } - } - - // debug.upvaluejoin (f1, n1, f2, n2) - static final class upvaluejoin extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaClosure f1 = args.checkclosure(1); - int n1 = args.checkint(2); - LuaClosure f2 = args.checkclosure(3); - int n2 = args.checkint(4); - if (n1 < 1 || n1 > f1.upValues.length) - argerror("index out of range"); - if (n2 < 1 || n2 > f2.upValues.length) - argerror("index out of range"); - f1.upValues[n1-1] = f2.upValues[n2-1]; - return NONE; - } - } - - public void onCall(LuaFunction f) { - LuaThread.State s = globals.running.state; - if (s.inhook) return; - callstack().onCall(f); - if (s.hookcall) callHook(s, CALL, NIL); - } - - public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) { - LuaThread.State s = globals.running.state; - if (s.inhook) return; - callstack().onCall(c, varargs, stack); - if (s.hookcall) callHook(s, CALL, NIL); - } - - public void onInstruction(int pc, Varargs v, int top) { - LuaThread.State s = globals.running.state; - if (s.inhook) return; - callstack().onInstruction(pc, v, top); - if (s.hookfunc == null) return; - if (s.hookcount > 0) - if (++s.bytecodes % s.hookcount == 0) - callHook(s, COUNT, NIL); - if (s.hookline) { - int newline = callstack().currentline(); - if ( newline != s.lastline ) { - s.lastline = newline; - callHook(s, LINE, LuaValue.valueOf(newline)); - } - } - } - - public void onReturn() { - LuaThread.State s = globals.running.state; - if (s.inhook) return; - callstack().onReturn(); - if (s.hookrtrn) callHook(s, RETURN, NIL); - } - - public String traceback(int level) { - return callstack().traceback(level); - } - - public CallFrame getCallFrame(int level) { - return callstack().getCallFrame(level); - } - - void callHook(LuaThread.State s, LuaValue type, LuaValue arg) { - if (s.inhook || s.hookfunc == null) return; - s.inhook = true; - try { - s.hookfunc.call(type, arg); - } catch (LuaError e) { - throw e; - } catch (RuntimeException e) { - throw new LuaError(e); - } finally { - s.inhook = false; - } - } - - CallStack callstack() { - return callstack(globals.running); - } - - CallStack callstack(LuaThread t) { - if (t.callstack == null) - t.callstack = new CallStack(); - return (CallStack) t.callstack; - } - - static class DebugInfo { - String name; /* (n) */ - String namewhat; /* (n) 'global', 'local', 'field', 'method' */ - String what; /* (S) 'Lua', 'C', 'main', 'tail' */ - String source; /* (S) */ - int currentline; /* (l) */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - short nups; /* (u) number of upvalues */ - short nparams;/* (u) number of parameters */ - boolean isvararg; /* (u) */ - boolean istailcall; /* (t) */ - String short_src; /* (S) */ - CallFrame cf; /* active function */ - - public void funcinfo(LuaFunction f) { - if (f.isclosure()) { - Prototype p = f.checkclosure().p; - this.source = p.source != null ? p.source.tojstring() : "=?"; - this.linedefined = p.linedefined; - this.lastlinedefined = p.lastlinedefined; - this.what = (this.linedefined == 0) ? "main" : "Lua"; - this.short_src = p.shortsource(); - } else { - this.source = "=[Java]"; - this.linedefined = -1; - this.lastlinedefined = -1; - this.what = "Java"; - this.short_src = f.name(); - } - } - } - - public static class CallStack { - final static CallFrame[] EMPTY = {}; - CallFrame[] frame = EMPTY; - int calls = 0; - - CallStack() {} - - synchronized int currentline() { - return calls > 0? frame[calls-1].currentline(): -1; - } - - private synchronized CallFrame pushcall() { - if (calls >= frame.length) { - int n = Math.max(4, frame.length * 3 / 2); - CallFrame[] f = new CallFrame[n]; - System.arraycopy(frame, 0, f, 0, frame.length); - for (int i = frame.length; i < n; ++i) - f[i] = new CallFrame(); - frame = f; - for (int i = 1; i < n; ++i) - f[i].previous = f[i-1]; - } - return frame[calls++]; - } - - final synchronized void onCall(LuaFunction function) { - pushcall().set(function); - } - - final synchronized void onCall(LuaClosure function, Varargs varargs, LuaValue[] stack) { - pushcall().set(function, varargs, stack); - } - - final synchronized void onReturn() { - if (calls > 0) - frame[--calls].reset(); - } - - final synchronized void onInstruction(int pc, Varargs v, int top) { - if (calls > 0) - frame[calls-1].instr(pc, v, top); - } - - /** - * Get the traceback starting at a specific level. - * @param level - * @return String containing the traceback. - */ - synchronized String traceback(int level) { - StringBuffer sb = new StringBuffer(); - sb.append( "stack traceback:" ); - for (DebugLib.CallFrame c; (c = getCallFrame(level++)) != null; ) { - sb.append("\n\t"); - sb.append( c.shortsource() ); - sb.append( ':' ); - if (c.currentline() > 0) - sb.append( c.currentline()+":" ); - sb.append( " in " ); - DebugInfo ar = auxgetinfo("n", c.f, c); - if (c.linedefined() == 0) - sb.append("main chunk"); - else if ( ar.name != null ) { - sb.append( "function '" ); - sb.append( ar.name ); - sb.append( '\'' ); - } else { - sb.append( "function <" ); - sb.append( c.shortsource() ); - sb.append( ':' ); - sb.append( c.linedefined() ); - sb.append( '>' ); - } - } - sb.append("\n\t[Java]: in ?"); - return sb.toString(); - } - - synchronized DebugLib.CallFrame getCallFrame(int level) { - if (level < 1 || level > calls) - return null; - return frame[calls-level]; - } - - synchronized DebugLib.CallFrame findCallFrame(LuaValue func) { - for (int i = 1; i <= calls; ++i) - if (frame[calls-i].f == func) - return frame[i]; - return null; - } - - - synchronized DebugInfo auxgetinfo(String what, LuaFunction f, CallFrame ci) { - DebugInfo ar = new DebugInfo(); - for (int i = 0, n = what.length(); i < n; ++i) { - switch (what.charAt(i)) { - case 'S': - ar.funcinfo(f); - break; - case 'l': - ar.currentline = ci != null && ci.f.isclosure()? ci.currentline(): -1; - break; - case 'u': - if (f != null && f.isclosure()) { - Prototype p = f.checkclosure().p; - ar.nups = (short) p.upvalues.length; - ar.nparams = (short) p.numparams; - ar.isvararg = p.is_vararg != 0; - } else { - ar.nups = 0; - ar.isvararg = true; - ar.nparams = 0; - } - break; - case 't': - ar.istailcall = false; - break; - case 'n': { - /* calling function is a known Lua function? */ - if (ci != null && ci.previous != null) { - if (ci.previous.f.isclosure()) { - NameWhat nw = getfuncname(ci.previous); - if (nw != null) { - ar.name = nw.name; - ar.namewhat = nw.namewhat; - } - } - } - if (ar.namewhat == null) { - ar.namewhat = ""; /* not found */ - ar.name = null; - } - break; - } - case 'L': - case 'f': - break; - default: - // TODO: return bad status. - break; - } - } - return ar; - } - - } - - public static class CallFrame { - LuaFunction f; - int pc; - int top; - Varargs v; - LuaValue[] stack; - CallFrame previous; - void set(LuaClosure function, Varargs varargs, LuaValue[] stack) { - this.f = function; - this.v = varargs; - this.stack = stack; - } - public String shortsource() { - return f.isclosure()? f.checkclosure().p.shortsource(): "[Java]"; - } - void set(LuaFunction function) { - this.f = function; - } - void reset() { - this.f = null; - this.v = null; - this.stack = null; - } - void instr(int pc, Varargs v, int top) { - this.pc = pc; - this.v = v; - this.top = top; - if (TRACE) - Print.printState(f.checkclosure(), pc, stack, top, v); - } - Varargs getLocal(int i) { - LuaString name = getlocalname(i); - if ( i >= 1 && i <= stack.length && stack[i-1] != null ) - return varargsOf( name == null ? NIL : name, stack[i-1] ); - else - return NIL; - } - Varargs setLocal(int i, LuaValue value) { - LuaString name = getlocalname(i); - if ( i >= 1 && i <= stack.length && stack[i-1] != null ) { - stack[i-1] = value; - return name == null ? NIL : name; - } else { - return NIL; - } - } - public int currentline() { - if ( !f.isclosure() ) return -1; - int[] li = f.checkclosure().p.lineinfo; - return li==null || pc<0 || pc>=li.length? -1: li[pc]; - } - String sourceline() { - if ( !f.isclosure() ) return f.tojstring(); - return f.checkclosure().p.shortsource() + ":" + currentline(); - } - int linedefined() { - return f.isclosure()? f.checkclosure().p.linedefined: -1; - } - LuaString getlocalname(int index) { - if ( !f.isclosure() ) return null; - return f.checkclosure().p.getlocalname(index, pc); - } - } - - static LuaString findupvalue(LuaClosure c, int up) { - if ( c.upValues != null && up > 0 && up <= c.upValues.length ) { - if ( c.p.upvalues != null && up <= c.p.upvalues.length ) - return c.p.upvalues[up-1].name; - else - return LuaString.valueOf( "."+up ); - } - return null; - } - - static void lua_assert(boolean x) { - if (!x) throw new RuntimeException("lua_assert failed"); - } - - static class NameWhat { - final String name; - final String namewhat; - NameWhat(String name, String namewhat) { - this.name = name; - this.namewhat = namewhat; - } - } - - // Return the name info if found, or null if no useful information could be found. - static NameWhat getfuncname(DebugLib.CallFrame frame) { - if (!frame.f.isclosure()) - return new NameWhat(frame.f.classnamestub(), "Java"); - Prototype p = frame.f.checkclosure().p; - int pc = frame.pc; - int i = p.code[pc]; /* calling instruction */ - LuaString tm; - switch (Lua.GET_OPCODE(i)) { - case Lua.OP_CALL: - case Lua.OP_TAILCALL: /* get function name */ - return getobjname(p, pc, Lua.GETARG_A(i)); - case Lua.OP_TFORCALL: /* for iterator */ - return new NameWhat("(for iterator)", "(for iterator"); - /* all other instructions can call only through metamethods */ - case Lua.OP_SELF: - case Lua.OP_GETTABUP: - case Lua.OP_GETTABLE: tm = LuaValue.INDEX; break; - case Lua.OP_SETTABUP: - case Lua.OP_SETTABLE: tm = LuaValue.NEWINDEX; break; - case Lua.OP_EQ: tm = LuaValue.EQ; break; - case Lua.OP_ADD: tm = LuaValue.ADD; break; - case Lua.OP_SUB: tm = LuaValue.SUB; break; - case Lua.OP_MUL: tm = LuaValue.MUL; break; - case Lua.OP_DIV: tm = LuaValue.DIV; break; - case Lua.OP_MOD: tm = LuaValue.MOD; break; - case Lua.OP_POW: tm = LuaValue.POW; break; - case Lua.OP_UNM: tm = LuaValue.UNM; break; - case Lua.OP_LEN: tm = LuaValue.LEN; break; - case Lua.OP_LT: tm = LuaValue.LT; break; - case Lua.OP_LE: tm = LuaValue.LE; break; - case Lua.OP_CONCAT: tm = LuaValue.CONCAT; break; - default: - return null; /* else no useful name can be found */ - } - return new NameWhat( tm.tojstring(), "metamethod" ); - } - - // return NameWhat if found, null if not - public static NameWhat getobjname(Prototype p, int lastpc, int reg) { - int pc = lastpc; // currentpc(L, ci); - LuaString name = p.getlocalname(reg + 1, pc); - if (name != null) /* is a local? */ - return new NameWhat( name.tojstring(), "local" ); - - /* else try symbolic execution */ - pc = findsetreg(p, lastpc, reg); - if (pc != -1) { /* could find instruction? */ - int i = p.code[pc]; - switch (Lua.GET_OPCODE(i)) { - case Lua.OP_MOVE: { - int a = Lua.GETARG_A(i); - int b = Lua.GETARG_B(i); /* move from `b' to `a' */ - if (b < a) - return getobjname(p, pc, b); /* get name for `b' */ - break; - } - case Lua.OP_GETTABUP: - case Lua.OP_GETTABLE: { - int k = Lua.GETARG_C(i); /* key index */ - int t = Lua.GETARG_B(i); /* table index */ - LuaString vn = (Lua.GET_OPCODE(i) == Lua.OP_GETTABLE) /* name of indexed variable */ - ? p.getlocalname(t + 1, pc) - : (t < p.upvalues.length ? p.upvalues[t].name : QMARK); - String jname = kname(p, pc, k); - return new NameWhat( jname, vn != null && vn.eq_b(ENV)? "global": "field" ); - } - case Lua.OP_GETUPVAL: { - int u = Lua.GETARG_B(i); /* upvalue index */ - name = u < p.upvalues.length ? p.upvalues[u].name : QMARK; - return name == null ? null : new NameWhat( name.tojstring(), "upvalue" ); - } - case Lua.OP_LOADK: - case Lua.OP_LOADKX: { - int b = (Lua.GET_OPCODE(i) == Lua.OP_LOADK) ? Lua.GETARG_Bx(i) - : Lua.GETARG_Ax(p.code[pc + 1]); - if (p.k[b].isstring()) { - name = p.k[b].strvalue(); - return new NameWhat( name.tojstring(), "constant" ); - } - break; - } - case Lua.OP_SELF: { - int k = Lua.GETARG_C(i); /* key index */ - String jname = kname(p, pc, k); - return new NameWhat( jname, "method" ); - } - default: - break; - } - } - return null; /* no useful name found */ - } - - static String kname(Prototype p, int pc, int c) { - if (Lua.ISK(c)) { /* is 'c' a constant? */ - LuaValue k = p.k[Lua.INDEXK(c)]; - if (k.isstring()) { /* literal constant? */ - return k.tojstring(); /* it is its own name */ - } /* else no reasonable name found */ - } else { /* 'c' is a register */ - NameWhat what = getobjname(p, pc, c); /* search for 'c' */ - if (what != null && "constant".equals(what.namewhat)) { /* found a constant name? */ - return what.name; /* 'name' already filled */ - } - /* else no reasonable name found */ - } - return "?"; /* no reasonable name found */ - } - - /* - ** try to find last instruction before 'lastpc' that modified register 'reg' - */ - static int findsetreg (Prototype p, int lastpc, int reg) { - int pc; - int setreg = -1; /* keep last instruction that changed 'reg' */ - for (pc = 0; pc < lastpc; pc++) { - int i = p.code[pc]; - int op = Lua.GET_OPCODE(i); - int a = Lua.GETARG_A(i); - switch (op) { - case Lua.OP_LOADNIL: { - int b = Lua.GETARG_B(i); - if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ - setreg = pc; - break; - } - case Lua.OP_TFORCALL: { - if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ - break; - } - case Lua.OP_CALL: - case Lua.OP_TAILCALL: { - if (reg >= a) setreg = pc; /* affect all registers above base */ - break; - } - case Lua.OP_JMP: { - int b = Lua.GETARG_sBx(i); - int dest = pc + 1 + b; - /* jump is forward and do not skip `lastpc'? */ - if (pc < dest && dest <= lastpc) - pc += b; /* do the jump */ - break; - } - case Lua.OP_TEST: { - if (reg == a) setreg = pc; /* jumped code can change 'a' */ - break; - } - case Lua.OP_SETLIST: { // Lua.testAMode(Lua.OP_SETLIST) == false - if ( ((i>>14)&0x1ff) == 0 ) pc++; // if c == 0 then c stored in next op -> skip - break; - } - default: - if (Lua.testAMode(op) && reg == a) /* any instruction that set A */ - setreg = pc; - break; - } - } - return setreg; - } -} diff --git a/src/core/org/luaj/vm2/lib/IoLib.java b/src/core/org/luaj/vm2/lib/IoLib.java deleted file mode 100644 index 13f6f986..00000000 --- a/src/core/org/luaj/vm2/lib/IoLib.java +++ /dev/null @@ -1,684 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.IOException; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Abstract base class extending {@link LibFunction} which implements the - * core of the lua standard {@code io} library. - *

    - * It contains the implementation of the io library support that is common to - * the JSE and JME platforms. - * In practice on of the concrete IOLib subclasses is chosen: - * {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and - * {@link org.luaj.vm2.lib.jme.JmeIoLib} for the JME platform. - *

    - * The JSE implementation conforms almost completely to the C-based lua library, - * while the JME implementation follows closely except in the area of random-access files, - * which are difficult to support properly on JME. - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
    - * } 
    - * In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseIoLib} library will be loaded, which will include - * the base functionality provided by this class, whereas the {@link org.luaj.vm2.lib.jse.JsePlatform} would load the - * {@link org.luaj.vm2.lib.jse.JseIoLib}. - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new OsLib());
    - * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
    - * } 
    - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see org.luaj.vm2.lib.jse.JseIoLib - * @see org.luaj.vm2.lib.jme.JmeIoLib - * @see http://www.lua.org/manual/5.1/manual.html#5.7 - */ -abstract -public class IoLib extends TwoArgFunction { - - abstract - protected class File extends LuaValue{ - abstract public void write( LuaString string ) throws IOException; - abstract public void flush() throws IOException; - abstract public boolean isstdfile(); - abstract public void close() throws IOException; - abstract public boolean isclosed(); - // returns new position - abstract public int seek(String option, int bytecount) throws IOException; - abstract public void setvbuf(String mode, int size); - // get length remaining to read - abstract public int remaining() throws IOException; - // peek ahead one character - abstract public int peek() throws IOException, EOFException; - // return char if read, -1 if eof, throw IOException on other exception - abstract public int read() throws IOException, EOFException; - // return number of bytes read if positive, false if eof, throw IOException on other exception - abstract public int read(byte[] bytes, int offset, int length) throws IOException; - - public boolean eof() throws IOException { - try { - return peek() < 0; - } catch (EOFException e) { return true; } - } - - // delegate method access to file methods table - public LuaValue get( LuaValue key ) { - return filemethods.get(key); - } - - // essentially a userdata instance - public int type() { - return LuaValue.TUSERDATA; - } - public String typename() { - return "userdata"; - } - - // displays as "file" type - public String tojstring() { - return "file: " + Integer.toHexString(hashCode()); - } - - public void finalize() { - if (!isclosed()) { - try { - close(); - } catch (IOException ignore) {} - } - } - } - - /** Enumerated value representing stdin */ - protected static final int FTYPE_STDIN = 0; - /** Enumerated value representing stdout */ - protected static final int FTYPE_STDOUT = 1; - /** Enumerated value representing stderr */ - protected static final int FTYPE_STDERR = 2; - /** Enumerated value representing a file type for a named file */ - protected static final int FTYPE_NAMED = 3; - - /** - * Wrap the standard input. - * @return File - * @throws IOException - */ - abstract protected File wrapStdin() throws IOException; - - /** - * Wrap the standard output. - * @return File - * @throws IOException - */ - abstract protected File wrapStdout() throws IOException; - - /** - * Wrap the standard error output. - * @return File - * @throws IOException - */ - abstract protected File wrapStderr() throws IOException; - - /** - * Open a file in a particular mode. - * @param filename - * @param readMode true if opening in read mode - * @param appendMode true if opening in append mode - * @param updateMode true if opening in update mode - * @param binaryMode true if opening in binary mode - * @return File object if successful - * @throws IOException if could not be opened - */ - abstract protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException; - - /** - * Open a temporary file. - * @return File object if successful - * @throws IOException if could not be opened - */ - abstract protected File tmpFile() throws IOException; - - /** - * Start a new process and return a file for input or output - * @param prog the program to execute - * @param mode "r" to read, "w" to write - * @return File to read to or write from - * @throws IOException if an i/o exception occurs - */ - abstract protected File openProgram(String prog, String mode) throws IOException; - - private File infile = null; - private File outfile = null; - private File errfile = null; - - private static final LuaValue STDIN = valueOf("stdin"); - private static final LuaValue STDOUT = valueOf("stdout"); - private static final LuaValue STDERR = valueOf("stderr"); - private static final LuaValue FILE = valueOf("file"); - private static final LuaValue CLOSED_FILE = valueOf("closed file"); - - private static final int IO_CLOSE = 0; - private static final int IO_FLUSH = 1; - private static final int IO_INPUT = 2; - private static final int IO_LINES = 3; - private static final int IO_OPEN = 4; - private static final int IO_OUTPUT = 5; - private static final int IO_POPEN = 6; - private static final int IO_READ = 7; - private static final int IO_TMPFILE = 8; - private static final int IO_TYPE = 9; - private static final int IO_WRITE = 10; - - private static final int FILE_CLOSE = 11; - private static final int FILE_FLUSH = 12; - private static final int FILE_LINES = 13; - private static final int FILE_READ = 14; - private static final int FILE_SEEK = 15; - private static final int FILE_SETVBUF = 16; - private static final int FILE_WRITE = 17; - - private static final int IO_INDEX = 18; - private static final int LINES_ITER = 19; - - public static final String[] IO_NAMES = { - "close", - "flush", - "input", - "lines", - "open", - "output", - "popen", - "read", - "tmpfile", - "type", - "write", - }; - - public static final String[] FILE_NAMES = { - "close", - "flush", - "lines", - "read", - "seek", - "setvbuf", - "write", - }; - - LuaTable filemethods; - - protected Globals globals; - - public LuaValue call(LuaValue modname, LuaValue env) { - globals = env.checkglobals(); - - // io lib functions - LuaTable t = new LuaTable(); - bind(t, IoLibV.class, IO_NAMES ); - - // create file methods table - filemethods = new LuaTable(); - bind(filemethods, IoLibV.class, FILE_NAMES, FILE_CLOSE ); - - // set up file metatable - LuaTable mt = new LuaTable(); - bind(mt, IoLibV.class, new String[] { "__index" }, IO_INDEX ); - t.setmetatable( mt ); - - // all functions link to library instance - setLibInstance( t ); - setLibInstance( filemethods ); - setLibInstance( mt ); - - // return the table - env.set("io", t); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("io", t); - return t; - } - - private void setLibInstance(LuaTable t) { - LuaValue[] k = t.keys(); - for ( int i=0, n=k.length; i bool - public Varargs _io_flush() throws IOException { - checkopen(output()); - outfile.flush(); - return LuaValue.TRUE; - } - - // io.tmpfile() -> file - public Varargs _io_tmpfile() throws IOException { - return tmpFile(); - } - - // io.close([file]) -> void - public Varargs _io_close(LuaValue file) throws IOException { - File f = file.isnil()? output(): checkfile(file); - checkopen(f); - return ioclose(f); - } - - // io.input([file]) -> file - public Varargs _io_input(LuaValue file) { - infile = file.isnil()? input(): - file.isstring()? ioopenfile(FTYPE_NAMED, file.checkjstring(),"r"): - checkfile(file); - return infile; - } - - // io.output(filename) -> file - public Varargs _io_output(LuaValue filename) { - outfile = filename.isnil()? output(): - filename.isstring()? ioopenfile(FTYPE_NAMED, filename.checkjstring(),"w"): - checkfile(filename); - return outfile; - } - - // io.type(obj) -> "file" | "closed file" | nil - public Varargs _io_type(LuaValue obj) { - File f = optfile(obj); - return f!=null? - f.isclosed()? CLOSED_FILE: FILE: - NIL; - } - - // io.popen(prog, [mode]) -> file - public Varargs _io_popen(String prog, String mode) throws IOException { - if (!"r".equals(mode) && !"w".equals(mode)) argerror(2, "invalid value: '" + mode + "'; must be one of 'r' or 'w'"); - return openProgram(prog, mode); - } - - // io.open(filename, [mode]) -> file | nil,err - public Varargs _io_open(String filename, String mode) throws IOException { - return rawopenfile(FTYPE_NAMED, filename, mode); - } - - // io.lines(filename, ...) -> iterator - public Varargs _io_lines(Varargs args) { - String filename = args.optjstring(1, null); - File infile = filename==null? input(): ioopenfile(FTYPE_NAMED, filename,"r"); - checkopen(infile); - return lines(infile, filename != null, args.subargs(2)); - } - - // io.read(...) -> (...) - public Varargs _io_read(Varargs args) throws IOException { - checkopen(input()); - return ioread(infile,args); - } - - // io.write(...) -> void - public Varargs _io_write(Varargs args) throws IOException { - checkopen(output()); - return iowrite(outfile,args); - } - - // file:close() -> void - public Varargs _file_close(LuaValue file) throws IOException { - return ioclose(checkfile(file)); - } - - // file:flush() -> void - public Varargs _file_flush(LuaValue file) throws IOException { - checkfile(file).flush(); - return LuaValue.TRUE; - } - - // file:setvbuf(mode,[size]) -> void - public Varargs _file_setvbuf(LuaValue file, String mode, int size) { - if ("no".equals(mode)) { - } else if ("full".equals(mode)) { - } else if ("line".equals(mode)) { - } else { - argerror(1, "invalid value: '" + mode + "'; must be one of 'no', 'full' or 'line'"); - } - checkfile(file).setvbuf(mode,size); - return LuaValue.TRUE; - } - - // file:lines(...) -> iterator - public Varargs _file_lines(Varargs args) { - return lines(checkfile(args.arg1()), false, args.subargs(2)); - } - - // file:read(...) -> (...) - public Varargs _file_read(LuaValue file, Varargs subargs) throws IOException { - return ioread(checkfile(file),subargs); - } - - // file:seek([whence][,offset]) -> pos | nil,error - public Varargs _file_seek(LuaValue file, String whence, int offset) throws IOException { - if ("set".equals(whence)) { - } else if ("end".equals(whence)) { - } else if ("cur".equals(whence)) { - } else { - argerror(1, "invalid value: '" + whence + "'; must be one of 'set', 'cur' or 'end'"); - } - return valueOf( checkfile(file).seek(whence,offset) ); - } - - // file:write(...) -> void - public Varargs _file_write(LuaValue file, Varargs subargs) throws IOException { - return iowrite(checkfile(file),subargs); - } - - // __index, returns a field - public Varargs _io_index(LuaValue v) { - return v.equals(STDOUT)?output(): - v.equals(STDIN)? input(): - v.equals(STDERR)? errput(): NIL; - } - - // lines iterator(s,var) -> var' - public Varargs _lines_iter(LuaValue file, boolean toclose, Varargs args) throws IOException { - File f = optfile(file); - if ( f == null ) argerror(1, "not a file: " + file); - if ( f.isclosed() ) error("file is already closed"); - Varargs ret = ioread(f, args); - if (toclose && ret.isnil(1) && f.eof()) f.close(); - return ret; - } - - private File output() { - return outfile!=null? outfile: (outfile=ioopenfile(FTYPE_STDOUT,"-","w")); - } - - private File errput() { - return errfile!=null? errfile: (errfile=ioopenfile(FTYPE_STDERR,"-","w")); - } - - private File ioopenfile(int filetype, String filename, String mode) { - try { - return rawopenfile(filetype, filename, mode); - } catch ( Exception e ) { - error("io error: "+e.getMessage()); - return null; - } - } - - private static Varargs ioclose(File f) throws IOException { - if ( f.isstdfile() ) - return errorresult("cannot close standard file"); - else { - f.close(); - return successresult(); - } - } - - private static Varargs successresult() { - return LuaValue.TRUE; - } - - static Varargs errorresult(Exception ioe) { - String s = ioe.getMessage(); - return errorresult("io error: "+(s!=null? s: ioe.toString())); - } - - private static Varargs errorresult(String errortext) { - return varargsOf(NIL, valueOf(errortext)); - } - - private Varargs lines(final File f, boolean toclose, Varargs args) { - try { - return new IoLibV(f,"lnext",LINES_ITER,this,toclose,args); - } catch ( Exception e ) { - return error("lines: "+e); - } - } - - private static Varargs iowrite(File f, Varargs args) throws IOException { - for ( int i=1, n=args.narg(); i<=n; i++ ) - f.write( args.checkstring(i) ); - return f; - } - - private Varargs ioread(File f, Varargs args) throws IOException { - int i,n=args.narg(); - if (n == 0) return freadline(f,false); - LuaValue[] v = new LuaValue[n]; - LuaValue ai,vi; - LuaString fmt; - for ( i=0; i= 2 && fmt.m_bytes[fmt.m_offset] == '*' ) { - switch ( fmt.m_bytes[fmt.m_offset+1] ) { - case 'n': vi = freadnumber(f); break item; - case 'l': vi = freadline(f,false); break item; - case 'L': vi = freadline(f,true); break item; - case 'a': vi = freadall(f); break item; - } - } - default: - return argerror( i+1, "(invalid format)" ); - } - if ( (v[i++] = vi).isnil() ) - break; - } - return i==0? NIL: varargsOf(v, 0, i); - } - - private static File checkfile(LuaValue val) { - File f = optfile(val); - if ( f == null ) - argerror(1,"file"); - checkopen( f ); - return f; - } - - private static File optfile(LuaValue val) { - return (val instanceof File)? (File) val: null; - } - - private static File checkopen(File file) { - if ( file.isclosed() ) - error("attempt to use a closed file"); - return file; - } - - private File rawopenfile(int filetype, String filename, String mode) throws IOException { - int len = mode.length(); - for (int i = 0; i < len; i++) { // [rwa][+]?b* - char ch = mode.charAt(i); - if (i == 0 && "rwa".indexOf(ch) >= 0) continue; - if (i == 1 && ch == '+') continue; - if (i >= 1 && ch == 'b') continue; - len = -1; - break; - } - if (len <= 0) argerror(2, "invalid mode: '" + mode + "'"); - - switch (filetype) { - case FTYPE_STDIN: return wrapStdin(); - case FTYPE_STDOUT: return wrapStdout(); - case FTYPE_STDERR: return wrapStderr(); - } - boolean isreadmode = mode.startsWith("r"); - boolean isappend = mode.startsWith("a"); - boolean isupdate = mode.indexOf('+') > 0; - boolean isbinary = mode.endsWith("b"); - return openFile( filename, isreadmode, isappend, isupdate, isbinary ); - } - - - // ------------- file reading utilitied ------------------ - - public static LuaValue freadbytes(File f, int count) throws IOException { - if (count == 0) return f.eof() ? NIL : EMPTYSTRING; - byte[] b = new byte[count]; - int r; - if ( ( r = f.read(b,0,b.length) ) < 0 ) - return NIL; - return LuaString.valueUsing(b, 0, r); - } - public static LuaValue freaduntil(File f,boolean lineonly,boolean withend) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int c; - try { - if ( lineonly ) { - loop: while ( (c = f.read()) >= 0 ) { - switch ( c ) { - case '\r': if (withend) baos.write(c); break; - case '\n': if (withend) baos.write(c); break loop; - default: baos.write(c); break; - } - } - } else { - while ( (c = f.read()) >= 0 ) - baos.write(c); - } - } catch ( EOFException e ) { - c = -1; - } - return ( c < 0 && baos.size() == 0 )? - (LuaValue) NIL: - (LuaValue) LuaString.valueUsing(baos.toByteArray()); - } - public static LuaValue freadline(File f,boolean withend) throws IOException { - return freaduntil(f,true,withend); - } - public static LuaValue freadall(File f) throws IOException { - int n = f.remaining(); - if ( n >= 0 ) { - return n == 0 ? EMPTYSTRING : freadbytes(f, n); - } else { - return freaduntil(f,false,false); - } - } - public static LuaValue freadnumber(File f) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - freadchars(f," \t\r\n",null); - freadchars(f,"-+",baos); - //freadchars(f,"0",baos); - //freadchars(f,"xX",baos); - freadchars(f,"0123456789",baos); - freadchars(f,".",baos); - freadchars(f,"0123456789",baos); - //freadchars(f,"eEfFgG",baos); - // freadchars(f,"+-",baos); - //freadchars(f,"0123456789",baos); - String s = baos.toString(); - return s.length()>0? valueOf( Double.parseDouble(s) ): NIL; - } - private static void freadchars(File f, String chars, ByteArrayOutputStream baos) throws IOException { - int c; - while ( true ) { - c = f.peek(); - if ( chars.indexOf(c) < 0 ) { - return; - } - f.read(); - if ( baos != null ) - baos.write( c ); - } - } - - - -} diff --git a/src/core/org/luaj/vm2/lib/LibFunction.java b/src/core/org/luaj/vm2/lib/LibFunction.java deleted file mode 100644 index eba56072..00000000 --- a/src/core/org/luaj/vm2/lib/LibFunction.java +++ /dev/null @@ -1,222 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaError; -import org.luaj.vm2.LuaFunction; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Subclass of {@link LuaFunction} common to Java functions exposed to lua. - *

    - * To provide for common implementations in JME and JSE, - * library functions are typically grouped on one or more library classes - * and an opcode per library function is defined and used to key the switch - * to the correct function within the library. - *

    - * Since lua functions can be called with too few or too many arguments, - * and there are overloaded {@link LuaValue#call()} functions with varying - * number of arguments, a Java function exposed in lua needs to handle the - * argument fixup when a function is called with a number of arguments - * differs from that expected. - *

    - * To simplify the creation of library functions, - * there are 5 direct subclasses to handle common cases based on number of - * argument values and number of return return values. - *

    - *

    - * To be a Java library that can be loaded via {@code require}, it should have - * a public constructor that returns a {@link LuaValue} that, when executed, - * initializes the library. - *

    - * For example, the following code will implement a library called "hyperbolic" - * with two functions, "sinh", and "cosh": -

     {@code
    - * import org.luaj.vm2.LuaValue;
    - * import org.luaj.vm2.lib.*;
    - * 
    - * public class hyperbolic extends TwoArgFunction {
    - *
    - *	public hyperbolic() {}
    - *
    - *	public LuaValue call(LuaValue modname, LuaValue env) {
    - *		LuaValue library = tableOf();
    - *		library.set( "sinh", new sinh() );
    - *		library.set( "cosh", new cosh() );
    - *		env.set( "hyperbolic", library );
    - *		return library;
    - *	}
    - *
    - *	static class sinh extends OneArgFunction {
    - *		public LuaValue call(LuaValue x) {
    - *			return LuaValue.valueOf(Math.sinh(x.checkdouble()));
    - *		}
    - *	}
    - *	
    - *	static class cosh extends OneArgFunction {
    - *		public LuaValue call(LuaValue x) {
    - *			return LuaValue.valueOf(Math.cosh(x.checkdouble()));
    - *		}
    - *	}
    - *}
    - *}
    - * The default constructor is used to instantiate the library - * in response to {@code require 'hyperbolic'} statement, - * provided it is on Java"s class path. - * This instance is then invoked with 2 arguments: the name supplied to require(), - * and the environment for this function. The library may ignore these, or use - * them to leave side effects in the global environment, for example. - * In the previous example, two functions are created, 'sinh', and 'cosh', and placed - * into a global table called 'hyperbolic' using the supplied 'env' argument. - *

    - * To test it, a script such as this can be used: - *

     {@code
    - * local t = require('hyperbolic')
    - * print( 't', t )
    - * print( 'hyperbolic', hyperbolic )
    - * for k,v in pairs(t) do
    - * 	print( 'k,v', k,v )
    - * end
    - * print( 'sinh(.5)', hyperbolic.sinh(.5) )
    - * print( 'cosh(.5)', hyperbolic.cosh(.5) )
    - * }
    - *

    - * It should produce something like: - *

     {@code
    - * t	table: 3dbbd23f
    - * hyperbolic	table: 3dbbd23f
    - * k,v	cosh	function: 3dbbd128
    - * k,v	sinh	function: 3dbbd242
    - * sinh(.5)	0.5210953
    - * cosh(.5)	1.127626
    - * }
    - *

    - * See the source code in any of the library functions - * such as {@link BaseLib} or {@link TableLib} for other examples. - */ -abstract public class LibFunction extends LuaFunction { - - /** User-defined opcode to differentiate between instances of the library function class. - *

    - * Subclass will typicall switch on this value to provide the specific behavior for each function. - */ - protected int opcode; - - /** The common name for this function, useful for debugging. - *

    - * Binding functions initialize this to the name to which it is bound. - */ - protected String name; - - /** Default constructor for use by subclasses */ - protected LibFunction() { - } - - public String tojstring() { - return name != null ? "function: " + name : super.tojstring(); - } - - /** - * Bind a set of library functions. - *

    - * An array of names is provided, and the first name is bound - * with opcode = 0, second with 1, etc. - * @param env The environment to apply to each bound function - * @param factory the Class to instantiate for each bound function - * @param names array of String names, one for each function. - * @see #bind(LuaValue, Class, String[], int) - */ - protected void bind(LuaValue env, Class factory, String[] names ) { - bind( env, factory, names, 0 ); - } - - /** - * Bind a set of library functions, with an offset - *

    - * An array of names is provided, and the first name is bound - * with opcode = {@code firstopcode}, second with {@code firstopcode+1}, etc. - * @param env The environment to apply to each bound function - * @param factory the Class to instantiate for each bound function - * @param names array of String names, one for each function. - * @param firstopcode the first opcode to use - * @see #bind(LuaValue, Class, String[]) - */ - protected void bind(LuaValue env, Class factory, String[] names, int firstopcode ) { - try { - for ( int i=0, n=names.length; i - * It contains only the math library support that is possible on JME. - * For a more complete implementation based on math functions specific to JSE - * use {@link org.luaj.vm2.lib.jse.JseMathLib}. - * In Particular the following math functions are not implemented by this library: - *

    - *

    - * The implementations of {@code exp()} and {@code pow()} are constructed by - * hand for JME, so will be slower and less accurate than when executed on the JSE platform. - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or - * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
    - * } 
    - * When using {@link org.luaj.vm2.lib.jse.JsePlatform} as in this example, - * the subclass {@link org.luaj.vm2.lib.jse.JseMathLib} will - * be included, which also includes this base functionality. - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new MathLib());
    - * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
    - * } 
    - * Doing so will ensure the library is properly initialized - * and loaded into the globals table. - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see org.luaj.vm2.lib.jse.JseMathLib - * @see Lua 5.2 Math Lib Reference - */ -public class MathLib extends TwoArgFunction { - - /** Pointer to the latest MathLib instance, used only to dispatch - * math.exp to tha correct platform math library. - */ - public static MathLib MATHLIB = null; - - /** Construct a MathLib, which can be initialized by calling it with a - * modname string, and a global environment table as arguments using - * {@link #call(LuaValue, LuaValue)}. */ - public MathLib() { - MATHLIB = this; - } - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, typically a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - LuaTable math = new LuaTable(0,30); - math.set("abs", new abs()); - math.set("ceil", new ceil()); - math.set("cos", new cos()); - math.set("deg", new deg()); - math.set("exp", new exp(this)); - math.set("floor", new floor()); - math.set("fmod", new fmod()); - math.set("frexp", new frexp()); - math.set("huge", LuaDouble.POSINF ); - math.set("ldexp", new ldexp()); - math.set("max", new max()); - math.set("min", new min()); - math.set("modf", new modf()); - math.set("pi", Math.PI ); - math.set("pow", new pow()); - random r; - math.set("random", r = new random()); - math.set("randomseed", new randomseed(r)); - math.set("rad", new rad()); - math.set("sin", new sin()); - math.set("sqrt", new sqrt()); - math.set("tan", new tan()); - env.set("math", math); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("math", math); - return math; - } - - abstract protected static class UnaryOp extends OneArgFunction { - public LuaValue call(LuaValue arg) { - return valueOf(call(arg.checkdouble())); - } - abstract protected double call(double d); - } - - abstract protected static class BinaryOp extends TwoArgFunction { - public LuaValue call(LuaValue x, LuaValue y) { - return valueOf(call(x.checkdouble(), y.checkdouble())); - } - abstract protected double call(double x, double y); - } - - static final class abs extends UnaryOp { protected double call(double d) { return Math.abs(d); } } - static final class ceil extends UnaryOp { protected double call(double d) { return Math.ceil(d); } } - static final class cos extends UnaryOp { protected double call(double d) { return Math.cos(d); } } - static final class deg extends UnaryOp { protected double call(double d) { return Math.toDegrees(d); } } - static final class floor extends UnaryOp { protected double call(double d) { return Math.floor(d); } } - static final class rad extends UnaryOp { protected double call(double d) { return Math.toRadians(d); } } - static final class sin extends UnaryOp { protected double call(double d) { return Math.sin(d); } } - static final class sqrt extends UnaryOp { protected double call(double d) { return Math.sqrt(d); } } - static final class tan extends UnaryOp { protected double call(double d) { return Math.tan(d); } } - - static final class exp extends UnaryOp { - final MathLib mathlib; - exp(MathLib mathlib) { - this.mathlib = mathlib; - } - protected double call(double d) { - return mathlib.dpow_lib(Math.E,d); - } - } - - static final class fmod extends TwoArgFunction { - public LuaValue call(LuaValue xv, LuaValue yv) { - if (xv.islong() && yv.islong()) { - return valueOf(xv.tolong() % yv.tolong()); - } - return valueOf(xv.checkdouble() % yv.checkdouble()); - } - } - static final class ldexp extends BinaryOp { - protected double call(double x, double y) { - // This is the behavior on os-x, windows differs in rounding behavior. - return x * Double.longBitsToDouble((((long) y) + 1023) << 52); - } - } - static final class pow extends BinaryOp { - protected double call(double x, double y) { - return MathLib.dpow_default(x, y); - } - } - - static class frexp extends VarArgFunction { - public Varargs invoke(Varargs args) { - double x = args.checkdouble(1); - if ( x == 0 ) return varargsOf(ZERO,ZERO); - long bits = Double.doubleToLongBits( x ); - double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))); - double e = (((int) (bits >> 52)) & 0x7ff) - 1022; - return varargsOf( valueOf(m), valueOf(e) ); - } - } - - static class max extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue m = args.checkvalue(1); - for ( int i=2,n=args.narg(); i<=n; ++i ) { - LuaValue v = args.checkvalue(i); - if (m.lt_b(v)) m = v; - } - return m; - } - } - - static class min extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue m = args.checkvalue(1); - for ( int i=2,n=args.narg(); i<=n; ++i ) { - LuaValue v = args.checkvalue(i); - if (v.lt_b(m)) m = v; - } - return m; - } - } - - static class modf extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue n = args.arg1(); - /* number is its own integer part, no fractional part */ - if (n.islong()) return varargsOf(n, valueOf(0.0)); - double x = n.checkdouble(); - /* integer part (rounds toward zero) */ - double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x ); - /* fractional part (test needed for inf/-inf) */ - double fracPart = x == intPart ? 0.0 : x - intPart; - return varargsOf( valueOf(intPart), valueOf(fracPart) ); - } - } - - static class random extends LibFunction { - Random random = new Random(); - public LuaValue call() { - return valueOf( random.nextDouble() ); - } - public LuaValue call(LuaValue a) { - int m = a.checkint(); - if (m<1) argerror(1, "interval is empty"); - return valueOf( 1 + random.nextInt(m) ); - } - public LuaValue call(LuaValue a, LuaValue b) { - int m = a.checkint(); - int n = b.checkint(); - if (n 0; whole>>=1, v*=v ) - if ( (whole & 1) != 0 ) - p *= v; - if ( (b -= whole) > 0 ) { - int frac = (int) (0x10000 * b); - for ( ; (frac&0xffff)!=0; frac<<=1 ) { - a = Math.sqrt(a); - if ( (frac & 0x8000) != 0 ) - p *= a; - } - } - return p; - } - -} diff --git a/src/core/org/luaj/vm2/lib/OneArgFunction.java b/src/core/org/luaj/vm2/lib/OneArgFunction.java deleted file mode 100644 index 3db6a321..00000000 --- a/src/core/org/luaj/vm2/lib/OneArgFunction.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** Abstract base class for Java function implementations that take one argument and - * return one value. - *

    - * Subclasses need only implement {@link LuaValue#call(LuaValue)} to complete this class, - * simplifying development. - * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc, - * are routed through this method by this class, - * dropping or extending arguments with {@code nil} values as required. - *

    - * If more than one argument are required, or no arguments are required, - * or variable argument or variable return values, - * then use one of the related function - * {@link ZeroArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. - *

    - * See {@link LibFunction} for more information on implementation libraries and library functions. - * @see #call(LuaValue) - * @see LibFunction - * @see ZeroArgFunction - * @see TwoArgFunction - * @see ThreeArgFunction - * @see VarArgFunction - */ -abstract public class OneArgFunction extends LibFunction { - - abstract public LuaValue call(LuaValue arg); - - /** Default constructor */ - public OneArgFunction() { - } - - public final LuaValue call() { - return call(NIL); - } - - public final LuaValue call(LuaValue arg1, LuaValue arg2) { - return call(arg1); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { - return call(arg1); - } - - public Varargs invoke(Varargs varargs) { - return call(varargs.arg1()); - } -} diff --git a/src/core/org/luaj/vm2/lib/OsLib.java b/src/core/org/luaj/vm2/lib/OsLib.java deleted file mode 100644 index 85b8677e..00000000 --- a/src/core/org/luaj/vm2/lib/OsLib.java +++ /dev/null @@ -1,524 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import java.io.IOException; -import java.util.Calendar; -import java.util.Date; - -import org.luaj.vm2.Buffer; -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Subclass of {@link LibFunction} which implements the standard lua {@code os} library. - *

    - * It is a usable base with simplified stub functions - * for library functions that cannot be implemented uniformly - * on Jse and Jme. - *

    - * This can be installed as-is on either platform, or extended - * and refined to be used in a complete Jse implementation. - *

    - * Because the nature of the {@code os} library is to encapsulate - * os-specific features, the behavior of these functions varies considerably - * from their counterparts in the C platform. - *

    - * The following functions have limited implementations of features - * that are not supported well on Jme: - *

    - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("os").get("time").call() );
    - * } 
    - * In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseOsLib} library will be loaded, which will include - * the base functionality provided by this class. - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new OsLib());
    - * System.out.println( globals.get("os").get("time").call() );
    - * } 
    - *

    - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JseOsLib - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see http://www.lua.org/manual/5.1/manual.html#5.8 - */ -public class OsLib extends TwoArgFunction { - public static final String TMP_PREFIX = ".luaj"; - public static final String TMP_SUFFIX = "tmp"; - - private static final int CLOCK = 0; - private static final int DATE = 1; - private static final int DIFFTIME = 2; - private static final int EXECUTE = 3; - private static final int EXIT = 4; - private static final int GETENV = 5; - private static final int REMOVE = 6; - private static final int RENAME = 7; - private static final int SETLOCALE = 8; - private static final int TIME = 9; - private static final int TMPNAME = 10; - - private static final String[] NAMES = { - "clock", - "date", - "difftime", - "execute", - "exit", - "getenv", - "remove", - "rename", - "setlocale", - "time", - "tmpname", - }; - - private static final long t0 = System.currentTimeMillis(); - private static long tmpnames = t0; - - protected Globals globals; - - /** - * Create and OsLib instance. - */ - public OsLib() { - } - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, typically a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - globals = env.checkglobals(); - LuaTable os = new LuaTable(); - for (int i = 0; i < NAMES.length; ++i) - os.set(NAMES[i], new OsLibFunc(i, NAMES[i])); - env.set("os", os); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("os", os); - return os; - } - - class OsLibFunc extends VarArgFunction { - public OsLibFunc(int opcode, String name) { - this.opcode = opcode; - this.name = name; - } - public Varargs invoke(Varargs args) { - try { - switch ( opcode ) { - case CLOCK: - return valueOf(clock()); - case DATE: { - String s = args.optjstring(1, "%c"); - double t = args.isnumber(2)? args.todouble(2): time(null); - if (s.equals("*t")) { - Calendar d = Calendar.getInstance(); - d.setTime(new Date((long)(t*1000))); - LuaTable tbl = LuaValue.tableOf(); - tbl.set("year", LuaValue.valueOf(d.get(Calendar.YEAR))); - tbl.set("month", LuaValue.valueOf(d.get(Calendar.MONTH)+1)); - tbl.set("day", LuaValue.valueOf(d.get(Calendar.DAY_OF_MONTH))); - tbl.set("hour", LuaValue.valueOf(d.get(Calendar.HOUR_OF_DAY))); - tbl.set("min", LuaValue.valueOf(d.get(Calendar.MINUTE))); - tbl.set("sec", LuaValue.valueOf(d.get(Calendar.SECOND))); - tbl.set("wday", LuaValue.valueOf(d.get(Calendar.DAY_OF_WEEK))); - tbl.set("yday", LuaValue.valueOf(d.get(0x6))); // Day of year - tbl.set("isdst", LuaValue.valueOf(isDaylightSavingsTime(d))); - return tbl; - } - return valueOf( date(s, t==-1? time(null): t) ); - } - case DIFFTIME: - return valueOf(difftime(args.checkdouble(1),args.checkdouble(2))); - case EXECUTE: - return execute(args.optjstring(1, null)); - case EXIT: - exit(args.optint(1, 0)); - return NONE; - case GETENV: { - final String val = getenv(args.checkjstring(1)); - return val!=null? valueOf(val): NIL; - } - case REMOVE: - remove(args.checkjstring(1)); - return LuaValue.TRUE; - case RENAME: - rename(args.checkjstring(1), args.checkjstring(2)); - return LuaValue.TRUE; - case SETLOCALE: { - String s = setlocale(args.optjstring(1,null), args.optjstring(2, "all")); - return s!=null? valueOf(s): NIL; - } - case TIME: - return valueOf(time(args.opttable(1, null))); - case TMPNAME: - return valueOf(tmpname()); - } - return NONE; - } catch ( IOException e ) { - return varargsOf(NIL, valueOf(e.getMessage())); - } - } - } - - /** - * @return an approximation of the amount in seconds of CPU time used by - * the program. For luaj this simple returns the elapsed time since the - * OsLib class was loaded. - */ - protected double clock() { - return (System.currentTimeMillis()-t0) / 1000.; - } - - /** - * Returns the number of seconds from time t1 to time t2. - * In POSIX, Windows, and some other systems, this value is exactly t2-t1. - * @param t2 - * @param t1 - * @return diffeence in time values, in seconds - */ - protected double difftime(double t2, double t1) { - return t2 - t1; - } - - /** - * If the time argument is present, this is the time to be formatted - * (see the os.time function for a description of this value). - * Otherwise, date formats the current time. - * - * Date returns the date as a string, - * formatted according to the same rules as ANSII strftime, but without - * support for %g, %G, or %V. - * - * When called without arguments, date returns a reasonable date and - * time representation that depends on the host system and on the - * current locale (that is, os.date() is equivalent to os.date("%c")). - * - * @param format - * @param time time since epoch, or -1 if not supplied - * @return a LString or a LTable containing date and time, - * formatted according to the given string format. - */ - public String date(String format, double time) { - Calendar d = Calendar.getInstance(); - d.setTime(new Date((long)(time*1000))); - if (format.startsWith("!")) { - time -= timeZoneOffset(d); - d.setTime(new Date((long)(time*1000))); - format = format.substring(1); - } - byte[] fmt = format.getBytes(); - final int n = fmt.length; - Buffer result = new Buffer(n); - byte c; - for ( int i = 0; i < n; ) { - switch ( c = fmt[i++ ] ) { - case '\n': - result.append( "\n" ); - break; - default: - result.append( c ); - break; - case '%': - if (i >= n) break; - switch ( c = fmt[i++ ] ) { - default: - LuaValue.argerror(1, "invalid conversion specifier '%"+c+"'"); - break; - case '%': - result.append( (byte)'%' ); - break; - case 'a': - result.append(WeekdayNameAbbrev[d.get(Calendar.DAY_OF_WEEK)-1]); - break; - case 'A': - result.append(WeekdayName[d.get(Calendar.DAY_OF_WEEK)-1]); - break; - case 'b': - result.append(MonthNameAbbrev[d.get(Calendar.MONTH)]); - break; - case 'B': - result.append(MonthName[d.get(Calendar.MONTH)]); - break; - case 'c': - result.append(date("%a %b %d %H:%M:%S %Y", time)); - break; - case 'd': - result.append(String.valueOf(100+d.get(Calendar.DAY_OF_MONTH)).substring(1)); - break; - case 'H': - result.append(String.valueOf(100+d.get(Calendar.HOUR_OF_DAY)).substring(1)); - break; - case 'I': - result.append(String.valueOf(100+(d.get(Calendar.HOUR_OF_DAY)%12)).substring(1)); - break; - case 'j': { // day of year. - Calendar y0 = beginningOfYear(d); - int dayOfYear = (int) ((d.getTime().getTime() - y0.getTime().getTime()) / (24 * 3600L * 1000L)); - result.append(String.valueOf(1001+dayOfYear).substring(1)); - break; - } - case 'm': - result.append(String.valueOf(101+d.get(Calendar.MONTH)).substring(1)); - break; - case 'M': - result.append(String.valueOf(100+d.get(Calendar.MINUTE)).substring(1)); - break; - case 'p': - result.append(d.get(Calendar.HOUR_OF_DAY) < 12? "AM": "PM"); - break; - case 'S': - result.append(String.valueOf(100+d.get(Calendar.SECOND)).substring(1)); - break; - case 'U': - result.append(String.valueOf(weekNumber(d, 0))); - break; - case 'w': - result.append(String.valueOf((d.get(Calendar.DAY_OF_WEEK)+6)%7)); - break; - case 'W': - result.append(String.valueOf(weekNumber(d, 1))); - break; - case 'x': - result.append(date("%m/%d/%y", time)); - break; - case 'X': - result.append(date("%H:%M:%S", time)); - break; - case 'y': - result.append(String.valueOf(d.get(Calendar.YEAR)).substring(2)); - break; - case 'Y': - result.append(String.valueOf(d.get(Calendar.YEAR))); - break; - case 'z': { - final int tzo = timeZoneOffset(d) / 60; - final int a = Math.abs(tzo); - final String h = String.valueOf(100 + a / 60).substring(1); - final String m = String.valueOf(100 + a % 60).substring(1); - result.append((tzo>=0? "+": "-") + h + m); - break; - } - } - } - } - return result.tojstring(); - } - - private static final String[] WeekdayNameAbbrev = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - private static final String[] WeekdayName = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; - private static final String[] MonthNameAbbrev = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - private static final String[] MonthName = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; - - private Calendar beginningOfYear(Calendar d) { - Calendar y0 = Calendar.getInstance(); - y0.setTime(d.getTime()); - y0.set(Calendar.MONTH, 0); - y0.set(Calendar.DAY_OF_MONTH, 1); - y0.set(Calendar.HOUR_OF_DAY, 0); - y0.set(Calendar.MINUTE, 0); - y0.set(Calendar.SECOND, 0); - y0.set(Calendar.MILLISECOND, 0); - return y0; - } - - private int weekNumber(Calendar d, int startDay) { - Calendar y0 = beginningOfYear(d); - y0.set(Calendar.DAY_OF_MONTH, 1 + (startDay + 8 - y0.get(Calendar.DAY_OF_WEEK)) % 7); - if (y0.after(d)) { - y0.set(Calendar.YEAR, y0.get(Calendar.YEAR) - 1); - y0.set(Calendar.DAY_OF_MONTH, 1 + (startDay + 8 - y0.get(Calendar.DAY_OF_WEEK)) % 7); - } - long dt = d.getTime().getTime() - y0.getTime().getTime(); - return 1 + (int) (dt / (7L * 24L * 3600L * 1000L)); - } - - private int timeZoneOffset(Calendar d) { - int localStandarTimeMillis = ( - d.get(Calendar.HOUR_OF_DAY) * 3600 + - d.get(Calendar.MINUTE) * 60 + - d.get(Calendar.SECOND)) * 1000; - return d.getTimeZone().getOffset( - 1, - d.get(Calendar.YEAR), - d.get(Calendar.MONTH), - d.get(Calendar.DAY_OF_MONTH), - d.get(Calendar.DAY_OF_WEEK), - localStandarTimeMillis) / 1000; - } - - private boolean isDaylightSavingsTime(Calendar d) { - return timeZoneOffset(d) != d.getTimeZone().getRawOffset() / 1000; - } - - /** - * This function is equivalent to the C function system. - * It passes command to be executed by an operating system shell. - * It returns a status code, which is system-dependent. - * If command is absent, then it returns nonzero if a shell - * is available and zero otherwise. - * @param command command to pass to the system - */ - protected Varargs execute(String command) { - return varargsOf(NIL, valueOf("exit"), ONE); - } - - /** - * Calls the C function exit, with an optional code, to terminate the host program. - * @param code - */ - protected void exit(int code) { - System.exit(code); - } - - /** - * Returns the value of the process environment variable varname, - * or the System property value for varname, - * or null if the variable is not defined in either environment. - * - * The default implementation, which is used by the JmePlatform, - * only queryies System.getProperty(). - * - * The JsePlatform overrides this behavior and returns the - * environment variable value using System.getenv() if it exists, - * or the System property value if it does not. - * - * A SecurityException may be thrown if access is not allowed - * for 'varname'. - * @param varname - * @return String value, or null if not defined - */ - protected String getenv(String varname) { - return System.getProperty(varname); - } - - /** - * Deletes the file or directory with the given name. - * Directories must be empty to be removed. - * If this function fails, it throws and IOException - * - * @param filename - * @throws IOException if it fails - */ - protected void remove(String filename) throws IOException { - throw new IOException( "not implemented" ); - } - - /** - * Renames file or directory named oldname to newname. - * If this function fails,it throws and IOException - * - * @param oldname old file name - * @param newname new file name - * @throws IOException if it fails - */ - protected void rename(String oldname, String newname) throws IOException { - throw new IOException( "not implemented" ); - } - - /** - * Sets the current locale of the program. locale is a string specifying - * a locale; category is an optional string describing which category to change: - * "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category - * is "all". - * - * If locale is the empty string, the current locale is set to an implementation- - * defined native locale. If locale is the string "C", the current locale is set - * to the standard C locale. - * - * When called with null as the first argument, this function only returns the - * name of the current locale for the given category. - * - * @param locale - * @param category - * @return the name of the new locale, or null if the request - * cannot be honored. - */ - protected String setlocale(String locale, String category) { - return "C"; - } - - /** - * Returns the current time when called without arguments, - * or a time representing the date and time specified by the given table. - * This table must have fields year, month, and day, - * and may have fields hour, min, sec, and isdst - * (for a description of these fields, see the os.date function). - * @param table - * @return long value for the time - */ - protected double time(LuaTable table) { - java.util.Date d; - if (table == null) { - d = new java.util.Date(); - } else { - Calendar c = Calendar.getInstance(); - c.set(Calendar.YEAR, table.get("year").checkint()); - c.set(Calendar.MONTH, table.get("month").checkint()-1); - c.set(Calendar.DAY_OF_MONTH, table.get("day").checkint()); - c.set(Calendar.HOUR_OF_DAY, table.get("hour").optint(12)); - c.set(Calendar.MINUTE, table.get("min").optint(0)); - c.set(Calendar.SECOND, table.get("sec").optint(0)); - c.set(Calendar.MILLISECOND, 0); - d = c.getTime(); - } - return d.getTime() / 1000.; - } - - /** - * Returns a string with a file name that can be used for a temporary file. - * The file must be explicitly opened before its use and explicitly removed - * when no longer needed. - * - * On some systems (POSIX), this function also creates a file with that name, - * to avoid security risks. (Someone else might create the file with wrong - * permissions in the time between getting the name and creating the file.) - * You still have to open the file to use it and to remove it (even if you - * do not use it). - * - * @return String filename to use - */ - protected String tmpname() { - synchronized ( OsLib.class ) { - return TMP_PREFIX+(tmpnames++)+TMP_SUFFIX; - } - } -} diff --git a/src/core/org/luaj/vm2/lib/PackageLib.java b/src/core/org/luaj/vm2/lib/PackageLib.java deleted file mode 100644 index 4c2147c9..00000000 --- a/src/core/org/luaj/vm2/lib/PackageLib.java +++ /dev/null @@ -1,381 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2010-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import java.io.InputStream; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaFunction; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Subclass of {@link LibFunction} which implements the lua standard package and module - * library functions. - * - *

    Lua Environment Variables

    - * The following variables are available to lua scrips when this library has been loaded: - * - * - *

    Java Environment Variables

    - * These Java environment variables affect the library behavior: - * - * - *

    Loading

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *
     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("require").call"foo") );
    - * } 
    - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * System.out.println( globals.get("require").call("foo") );
    - * } 
    - *

    Limitations

    - * This library has been implemented to match as closely as possible the behavior in the corresponding library in C. - * However, the default filesystem search semantics are different and delegated to the bas library - * as outlined in the {@link BaseLib} and {@link org.luaj.vm2.lib.jse.JseBaseLib} documentation. - *

    - * @see LibFunction - * @see BaseLib - * @see org.luaj.vm2.lib.jse.JseBaseLib - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 Package Lib Reference - */ -public class PackageLib extends TwoArgFunction { - - /** The default value to use for package.path. This can be set with the system property - * "luaj.package.path", and is "?.lua" by default. */ - public static final String DEFAULT_LUA_PATH; - static { - String path = null; - try { - path = System.getProperty("luaj.package.path"); - } catch (Exception e) { - System.out.println(e.toString()); - } - if (path == null) { - path = "?.lua"; - } - DEFAULT_LUA_PATH = path; - } - - static final LuaString _LOADED = valueOf("loaded"); - private static final LuaString _LOADLIB = valueOf("loadlib"); - static final LuaString _PRELOAD = valueOf("preload"); - static final LuaString _PATH = valueOf("path"); - static final LuaString _SEARCHPATH = valueOf("searchpath"); - static final LuaString _SEARCHERS = valueOf("searchers"); - - /** The globals that were used to load this library. */ - Globals globals; - - /** The table for this package. */ - LuaTable package_; - - /** Loader that loads from {@code preload} table if found there */ - public preload_searcher preload_searcher; - - /** Loader that loads as a lua script using the lua path currently in {@link path} */ - public lua_searcher lua_searcher; - - /** Loader that loads as a Java class. Class must have public constructor and be a LuaValue. */ - public java_searcher java_searcher; - - private static final LuaString _SENTINEL = valueOf("\u0001"); - - private static final String FILE_SEP = System.getProperty("file.separator"); - - public PackageLib() {} - - /** Perform one-time initialization on the library by adding package functions - * to the supplied environment, and returning it as the return value. - * It also creates the package.preload and package.loaded tables for use by - * other libraries. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, typically a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - globals = env.checkglobals(); - globals.set("require", new require()); - package_ = new LuaTable(); - package_.set(_LOADED, new LuaTable()); - package_.set(_PRELOAD, new LuaTable()); - package_.set(_PATH, LuaValue.valueOf(DEFAULT_LUA_PATH)); - package_.set(_LOADLIB, new loadlib()); - package_.set(_SEARCHPATH, new searchpath()); - LuaTable searchers = new LuaTable(); - searchers.set(1, preload_searcher = new preload_searcher()); - searchers.set(2, lua_searcher = new lua_searcher()); - searchers.set(3, java_searcher = new java_searcher()); - package_.set(_SEARCHERS, searchers); - package_.set("config", FILE_SEP + "\n;\n?\n!\n-\n"); - package_.get(_LOADED).set("package", package_); - env.set("package", package_); - globals.package_ = this; - return env; - } - - /** Allow packages to mark themselves as loaded */ - public void setIsLoaded(String name, LuaTable value) { - package_.get(_LOADED).set(name, value); - } - - - /** Set the lua path used by this library instance to a new value. - * Merely sets the value of {@link path} to be used in subsequent searches. */ - public void setLuaPath( String newLuaPath ) { - package_.set(_PATH, LuaValue.valueOf(newLuaPath)); - } - - public String tojstring() { - return "package"; - } - - // ======================== Package loading ============================= - - /** - * require (modname) - * - * Loads the given module. The function starts by looking into the package.loaded table - * to determine whether modname is already loaded. If it is, then require returns the value - * stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module. - * - * To find a loader, require is guided by the package.searchers sequence. - * By changing this sequence, we can change how require looks for a module. - * The following explanation is based on the default configuration for package.searchers. - * - * First require queries package.preload[modname]. If it has a value, this value - * (which should be a function) is the loader. Otherwise require searches for a Lua loader using - * the path stored in package.path. If that also fails, it searches for a Java loader using - * the classpath, using the public default constructor, and casting the instance to LuaFunction. - * - * Once a loader is found, require calls the loader with two arguments: modname and an extra value - * dependent on how it got the loader. If the loader came from a file, this extra value is the file name. - * If the loader is a Java instance of LuaFunction, this extra value is the environment. - * If the loader returns any non-nil value, require assigns the returned value to package.loaded[modname]. - * If the loader does not return a non-nil value and has not assigned any value to package.loaded[modname], - * then require assigns true to this entry. - * In any case, require returns the final value of package.loaded[modname]. - * - * If there is any error loading or running the module, or if it cannot find any loader for the module, - * then require raises an error. - */ - public class require extends OneArgFunction { - public LuaValue call( LuaValue arg ) { - LuaString name = arg.checkstring(); - LuaValue loaded = package_.get(_LOADED); - LuaValue result = loaded.get(name); - if ( result.toboolean() ) { - if ( result == _SENTINEL ) - error("loop or previous error loading module '"+name+"'"); - return result; - } - - /* else must load it; iterate over available loaders */ - LuaTable tbl = package_.get(_SEARCHERS).checktable(); - StringBuffer sb = new StringBuffer(); - Varargs loader = null; - for ( int i=1; true; i++ ) { - LuaValue searcher = tbl.get(i); - if ( searcher.isnil() ) { - error( "module '"+name+"' not found: "+name+sb ); - } - - /* call loader with module name as argument */ - loader = searcher.invoke(name); - if ( loader.isfunction(1) ) - break; - if ( loader.isstring(1) ) - sb.append( loader.tojstring(1) ); - } - - // load the module using the loader - loaded.set(name, _SENTINEL); - result = loader.arg1().call(name, loader.arg(2)); - if ( ! result.isnil() ) - loaded.set( name, result ); - else if ( (result = loaded.get(name)) == _SENTINEL ) - loaded.set( name, result = LuaValue.TRUE ); - return result; - } - } - - public static class loadlib extends VarArgFunction { - public Varargs invoke( Varargs args ) { - args.checkstring(1); - return varargsOf(NIL, valueOf("dynamic libraries not enabled"), valueOf("absent")); - } - } - - public class preload_searcher extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaString name = args.checkstring(1); - LuaValue val = package_.get(_PRELOAD).get(name); - return val.isnil()? - valueOf("\n\tno field package.preload['"+name+"']"): - val; - } - } - - public class lua_searcher extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaString name = args.checkstring(1); - - // get package path - LuaValue path = package_.get(_PATH); - if ( ! path.isstring() ) - return valueOf("package.path is not a string"); - - // get the searchpath function. - Varargs v = package_.get(_SEARCHPATH).invoke(varargsOf(name, path)); - - // Did we get a result? - if (!v.isstring(1)) - return v.arg(2).tostring(); - LuaString filename = v.arg1().strvalue(); - - // Try to load the file. - v = globals.loadfile(filename.tojstring()); - if ( v.arg1().isfunction() ) - return LuaValue.varargsOf(v.arg1(), filename); - - // report error - return varargsOf(NIL, valueOf("'"+filename+"': "+v.arg(2).tojstring())); - } - } - - public class searchpath extends VarArgFunction { - public Varargs invoke(Varargs args) { - String name = args.checkjstring(1); - String path = args.checkjstring(2); - String sep = args.optjstring(3, "."); - String rep = args.optjstring(4, FILE_SEP); - - // check the path elements - int e = -1; - int n = path.length(); - StringBuffer sb = null; - name = name.replace(sep.charAt(0), rep.charAt(0)); - while ( e < n ) { - - // find next template - int b = e+1; - e = path.indexOf(';',b); - if ( e < 0 ) - e = path.length(); - String template = path.substring(b,e); - - // create filename - int q = template.indexOf('?'); - String filename = template; - if ( q >= 0 ) { - filename = template.substring(0,q) + name + template.substring(q+1); - } - - // try opening the file - InputStream is = globals.finder.findResource(filename); - if (is != null) { - try { is.close(); } catch ( java.io.IOException ioe ) {} - return valueOf(filename); - } - - // report error - if ( sb == null ) - sb = new StringBuffer(); - sb.append( "\n\t"+filename ); - } - return varargsOf(NIL, valueOf(sb.toString())); - } - } - - public class java_searcher extends VarArgFunction { - public Varargs invoke(Varargs args) { - String name = args.checkjstring(1); - String classname = toClassname( name ); - Class c = null; - LuaValue v = null; - try { - c = Class.forName(classname); - v = (LuaValue) c.newInstance(); - if (v.isfunction()) - ((LuaFunction)v).initupvalue1(globals); - return varargsOf(v, globals); - } catch ( ClassNotFoundException cnfe ) { - return valueOf("\n\tno class '"+classname+"'" ); - } catch ( Exception e ) { - return valueOf("\n\tjava load failed on '"+classname+"', "+e ); - } - } - } - - /** Convert lua filename to valid class name */ - public static final String toClassname( String filename ) { - int n=filename.length(); - int j=n; - if ( filename.endsWith(".lua") ) - j -= 4; - for ( int k=0; k='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') ) - return true; - switch ( c ) { - case '.': - case '$': - case '_': - return true; - default: - return false; - } - } -} diff --git a/src/core/org/luaj/vm2/lib/ResourceFinder.java b/src/core/org/luaj/vm2/lib/ResourceFinder.java deleted file mode 100644 index 3a7b38a6..00000000 --- a/src/core/org/luaj/vm2/lib/ResourceFinder.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009-2011 Luaj.org. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - ******************************************************************************/ -package org.luaj.vm2.lib; - -import java.io.InputStream; - -import org.luaj.vm2.Globals; - -/** - * Interface for opening application resource files such as scripts sources. - *

    - * This is used by required to load files that are part of - * the application, and implemented by BaseLib - * for both the Jme and Jse platforms. - *

    - * The Jme version of base lib {@link BaseLib} - * implements {@link Globals#finder} via {@link Class#getResourceAsStream(String)}, - * while the Jse version {@link org.luaj.vm2.lib.jse.JseBaseLib} implements it using {@link java.io.File#File(String)}. - *

    - * The io library does not use this API for file manipulation. - *

    - * @see BaseLib - * @see Globals#finder - * @see org.luaj.vm2.lib.jse.JseBaseLib - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see org.luaj.vm2.lib.jse.JsePlatform - */ -public interface ResourceFinder { - - /** - * Try to open a file, or return null if not found. - * - * @see org.luaj.vm2.lib.BaseLib - * @see org.luaj.vm2.lib.jse.JseBaseLib - * - * @param filename - * @return InputStream, or null if not found. - */ - public InputStream findResource( String filename ); -} \ No newline at end of file diff --git a/src/core/org/luaj/vm2/lib/StringLib.java b/src/core/org/luaj/vm2/lib/StringLib.java deleted file mode 100644 index 8011459a..00000000 --- a/src/core/org/luaj/vm2/lib/StringLib.java +++ /dev/null @@ -1,1223 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import org.luaj.vm2.Buffer; -import org.luaj.vm2.LuaClosure; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; -import org.luaj.vm2.compiler.DumpState; - -/** - * Subclass of {@link LibFunction} which implements the lua standard {@code string} - * library. - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
    - * } 
    - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new JseStringLib());
    - * System.out.println( globals.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
    - * } 
    - *

    - * This is a direct port of the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 String Lib Reference - */ -public class StringLib extends TwoArgFunction { - - /** Construct a StringLib, which can be initialized by calling it with a - * modname string, and a global environment table as arguments using - * {@link #call(LuaValue, LuaValue)}. */ - public StringLib() { - } - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - * Creates a metatable that uses __INDEX to fall back on itself to support string - * method operations. - * If the shared strings metatable instance is null, will set the metatable as - * the global shared metatable for strings. - *

    - * All tables and metatables are read-write by default so if this will be used in - * a server environment, sandboxing should be used. In particular, the - * {@link LuaString#s_metatable} table should probably be made read-only. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, typically a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - LuaTable string = new LuaTable(); - string.set("byte", new _byte()); - string.set("char", new _char()); - string.set("dump", new dump()); - string.set("find", new find()); - string.set("format", new format()); - string.set("gmatch", new gmatch()); - string.set("gsub", new gsub()); - string.set("len", new len()); - string.set("lower", new lower()); - string.set("match", new match()); - string.set("rep", new rep()); - string.set("reverse", new reverse()); - string.set("sub", new sub()); - string.set("upper", new upper()); - - env.set("string", string); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("string", string); - if (LuaString.s_metatable == null) { - LuaString.s_metatable = LuaValue.tableOf(new LuaValue[] { INDEX, string }); - } - return string; - } - - /** - * string.byte (s [, i [, j]]) - * - * Returns the internal numerical codes of the - * characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the - * default value for j is i. - * - * Note that numerical codes are not necessarily portable across platforms. - * - * @param args the calling args - */ - static final class _byte extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaString s = args.checkstring(1); - int l = s.m_length; - int posi = posrelat( args.optint(2,1), l ); - int pose = posrelat( args.optint(3,posi), l ); - int n,i; - if (posi <= 0) posi = 1; - if (pose > l) pose = l; - if (posi > pose) return NONE; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* overflow? */ - error("string slice too long"); - LuaValue[] v = new LuaValue[n]; - for (i=0; i=256) argerror(a, "invalid value for string.char [0; 255]: " + c); - bytes[i] = (byte) c; - } - return LuaString.valueUsing( bytes ); - } - } - - /** - * string.dump (function[, stripDebug]) - * - * Returns a string containing a binary representation of the given function, - * so that a later loadstring on this string returns a copy of the function. - * function must be a Lua function without upvalues. - * Boolean param stripDebug - true to strip debugging info, false otherwise. - * The default value for stripDebug is true. - * - * TODO: port dumping code as optional add-on - */ - static final class dump extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue f = args.checkfunction(1); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - DumpState.dump( ((LuaClosure)f).p, baos, args.optboolean(2, true) ); - return LuaString.valueUsing(baos.toByteArray()); - } catch (IOException e) { - return error( e.getMessage() ); - } - } - } - - /** - * string.find (s, pattern [, init [, plain]]) - * - * Looks for the first match of pattern in the string s. - * If it finds a match, then find returns the indices of s - * where this occurrence starts and ends; otherwise, it returns nil. - * A third, optional numerical argument init specifies where to start the search; - * its default value is 1 and may be negative. A value of true as a fourth, - * optional argument plain turns off the pattern matching facilities, - * so the function does a plain "find substring" operation, - * with no characters in pattern being considered "magic". - * Note that if plain is given, then init must be given as well. - * - * If the pattern has captures, then in a successful match the captured values - * are also returned, after the two indices. - */ - static final class find extends VarArgFunction { - public Varargs invoke(Varargs args) { - return str_find_aux( args, true ); - } - } - - /** - * string.format (formatstring, ...) - * - * Returns a formatted version of its variable number of arguments following - * the description given in its first argument (which must be a string). - * The format string follows the same rules as the printf family of standard C functions. - * The only differences are that the options/modifiers *, l, L, n, p, and h are not supported - * and that there is an extra option, q. The q option formats a string in a form suitable - * to be safely read back by the Lua interpreter: the string is written between double quotes, - * and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly - * escaped when written. For instance, the call - * string.format('%q', 'a string with "quotes" and \n new line') - * - * will produce the string: - * "a string with \"quotes\" and \ - * new line" - * - * The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, - * whereas q and s expect a string. - * - * This function does not accept string values containing embedded zeros, - * except as arguments to the q option. - */ - final class format extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaString fmt = args.checkstring( 1 ); - final int n = fmt.length(); - Buffer result = new Buffer(n); - int arg = 1; - int c; - - for ( int i = 0; i < n; ) { - switch ( c = fmt.luaByte( i++ ) ) { - case '\n': - result.append( "\n" ); - break; - default: - result.append( (byte) c ); - break; - case L_ESC: - if ( i < n ) { - if ( ( c = fmt.luaByte( i ) ) == L_ESC ) { - ++i; - result.append( (byte)L_ESC ); - } else { - arg++; - FormatDesc fdsc = new FormatDesc(args, fmt, i ); - i += fdsc.length; - switch ( fdsc.conversion ) { - case 'c': - fdsc.format( result, (byte)args.checkint( arg ) ); - break; - case 'i': - case 'd': - fdsc.format( result, args.checklong( arg ) ); - break; - case 'o': - case 'u': - case 'x': - case 'X': - fdsc.format( result, args.checklong( arg ) ); - break; - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - fdsc.format( result, args.checkdouble( arg ) ); - break; - case 'q': - addquoted( result, args.checkstring( arg ) ); - break; - case 's': { - LuaString s = args.checkstring( arg ); - if ( fdsc.precision == -1 && s.length() >= 100 ) { - result.append( s ); - } else { - fdsc.format( result, s ); - } - } break; - default: - error("invalid option '%"+(char)fdsc.conversion+"' to 'format'"); - break; - } - } - } - } - } - - return result.tostring(); - } - } - - static void addquoted(Buffer buf, LuaString s) { - int c; - buf.append( (byte) '"' ); - for ( int i = 0, n = s.length(); i < n; i++ ) { - switch ( c = s.luaByte( i ) ) { - case '"': case '\\': case '\n': - buf.append( (byte)'\\' ); - buf.append( (byte)c ); - break; - default: - if (c <= 0x1F || c == 0x7F) { - buf.append( (byte) '\\' ); - if (i+1 == n || s.luaByte(i+1) < '0' || s.luaByte(i+1) > '9') { - buf.append(Integer.toString(c)); - } else { - buf.append( (byte) '0' ); - buf.append( (byte) (char) ('0' + c / 10) ); - buf.append( (byte) (char) ('0' + c % 10) ); - } - } else { - buf.append((byte) c); - } - break; - } - } - buf.append( (byte) '"' ); - } - - private static final String FLAGS = "-+ #0"; - - class FormatDesc { - - private boolean leftAdjust; - private boolean zeroPad; - private boolean explicitPlus; - private boolean space; - private boolean alternateForm; - private static final int MAX_FLAGS = 5; - - private int width; - int precision; - - public final int conversion; - public final int length; - - public final String src; - - public FormatDesc(Varargs args, LuaString strfrmt, final int start) { - int p = start, n = strfrmt.length(); - int c = 0; - - boolean moreFlags = true; - while ( moreFlags ) { - switch ( c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ) ) { - case '-': leftAdjust = true; break; - case '+': explicitPlus = true; break; - case ' ': space = true; break; - case '#': alternateForm = true; break; - case '0': zeroPad = true; break; - default: moreFlags = false; break; - } - } - if ( p - start > MAX_FLAGS ) - error("invalid format (repeated flags)"); - - width = -1; - if ( Character.isDigit( (char)c ) ) { - width = c - '0'; - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - if ( Character.isDigit( (char) c ) ) { - width = width * 10 + (c - '0'); - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - } - } - - precision = -1; - if ( c == '.' ) { - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - if ( Character.isDigit( (char) c ) ) { - precision = c - '0'; - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - if ( Character.isDigit( (char) c ) ) { - precision = precision * 10 + (c - '0'); - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - } - } - } - - if ( Character.isDigit( (char) c ) ) - error("invalid format (width or precision too long)"); - - zeroPad &= !leftAdjust; // '-' overrides '0' - conversion = c; - length = p - start; - src = strfrmt.substring(start - 1, p).tojstring(); - } - - public void format(Buffer buf, byte c) { - // TODO: not clear that any of width, precision, or flags apply here. - buf.append(c); - } - - public void format(Buffer buf, long number) { - String digits; - - if ( number == 0 && precision == 0 ) { - digits = ""; - } else { - int radix; - switch ( conversion ) { - case 'x': - case 'X': - radix = 16; - break; - case 'o': - radix = 8; - break; - default: - radix = 10; - break; - } - digits = Long.toString( number, radix ); - if ( conversion == 'X' ) - digits = digits.toUpperCase(); - } - - int minwidth = digits.length(); - int ndigits = minwidth; - int nzeros; - - if ( number < 0 ) { - ndigits--; - } else if ( explicitPlus || space ) { - minwidth++; - } - - if ( precision > ndigits ) - nzeros = precision - ndigits; - else if ( precision == -1 && zeroPad && width > minwidth ) - nzeros = width - minwidth; - else - nzeros = 0; - - minwidth += nzeros; - int nspaces = width > minwidth ? width - minwidth : 0; - - if ( !leftAdjust ) - pad( buf, ' ', nspaces ); - - if ( number < 0 ) { - if ( nzeros > 0 ) { - buf.append( (byte)'-' ); - digits = digits.substring( 1 ); - } - } else if ( explicitPlus ) { - buf.append( (byte)'+' ); - } else if ( space ) { - buf.append( (byte)' ' ); - } - - if ( nzeros > 0 ) - pad( buf, '0', nzeros ); - - buf.append( digits ); - - if ( leftAdjust ) - pad( buf, ' ', nspaces ); - } - - public void format(Buffer buf, double x) { - buf.append( StringLib.this.format(src, x) ); - } - - public void format(Buffer buf, LuaString s) { - int nullindex = s.indexOf( (byte)'\0', 0 ); - if ( nullindex != -1 ) - s = s.substring( 0, nullindex ); - buf.append(s); - } - - public final void pad(Buffer buf, char c, int n) { - byte b = (byte)c; - while ( n-- > 0 ) - buf.append(b); - } - } - - protected String format(String src, double x) { - return String.valueOf(x); - } - - /** - * string.gmatch (s, pattern) - * - * Returns an iterator function that, each time it is called, returns the next captures - * from pattern over string s. If pattern specifies no captures, then the - * whole match is produced in each call. - * - * As an example, the following loop - * s = "hello world from Lua" - * for w in string.gmatch(s, "%a+") do - * print(w) - * end - * - * will iterate over all the words from string s, printing one per line. - * The next example collects all pairs key=value from the given string into a table: - * t = {} - * s = "from=world, to=Lua" - * for k, v in string.gmatch(s, "(%w+)=(%w+)") do - * t[k] = v - * end - * - * For this function, a '^' at the start of a pattern does not work as an anchor, - * as this would prevent the iteration. - */ - static final class gmatch extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaString src = args.checkstring( 1 ); - LuaString pat = args.checkstring( 2 ); - return new GMatchAux(args, src, pat); - } - } - - static class GMatchAux extends VarArgFunction { - private final int srclen; - private final MatchState ms; - private int soffset; - private int lastmatch; - public GMatchAux(Varargs args, LuaString src, LuaString pat) { - this.srclen = src.length(); - this.ms = new MatchState(args, src, pat); - this.soffset = 0; - this.lastmatch = -1; - } - public Varargs invoke(Varargs args) { - for ( ; soffset<=srclen; soffset++ ) { - ms.reset(); - int res = ms.match(soffset, 0); - if ( res >=0 && res != lastmatch ) { - int soff = soffset; - lastmatch = soffset = res; - return ms.push_captures( true, soff, res ); - } - } - return NIL; - } - } - - - /** - * string.gsub (s, pattern, repl [, n]) - * Returns a copy of s in which all (or the first n, if given) occurrences of the - * pattern have been replaced by a replacement string specified by repl, which - * may be a string, a table, or a function. gsub also returns, as its second value, - * the total number of matches that occurred. - * - * If repl is a string, then its value is used for replacement. - * The character % works as an escape character: any sequence in repl of the form %n, - * with n between 1 and 9, stands for the value of the n-th captured substring (see below). - * The sequence %0 stands for the whole match. The sequence %% stands for a single %. - * - * If repl is a table, then the table is queried for every match, using the first capture - * as the key; if the pattern specifies no captures, then the whole match is used as the key. - * - * If repl is a function, then this function is called every time a match occurs, - * with all captured substrings passed as arguments, in order; if the pattern specifies - * no captures, then the whole match is passed as a sole argument. - * - * If the value returned by the table query or by the function call is a string or a number, - * then it is used as the replacement string; otherwise, if it is false or nil, - * then there is no replacement (that is, the original match is kept in the string). - * - * Here are some examples: - * x = string.gsub("hello world", "(%w+)", "%1 %1") - * --> x="hello hello world world" - * - * x = string.gsub("hello world", "%w+", "%0 %0", 1) - * --> x="hello hello world" - * - * x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") - * --> x="world hello Lua from" - * - * x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) - * --> x="home = /home/roberto, user = roberto" - * - * x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) - * return loadstring(s)() - * end) - * --> x="4+5 = 9" - * - * local t = {name="lua", version="5.1"} - * x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) - * --> x="lua-5.1.tar.gz" - */ - static final class gsub extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaString src = args.checkstring( 1 ); - final int srclen = src.length(); - LuaString p = args.checkstring( 2 ); - int lastmatch = -1; /* end of last match */ - LuaValue repl = args.arg( 3 ); - int max_s = args.optint( 4, srclen + 1 ); - final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^'; - - Buffer lbuf = new Buffer( srclen ); - MatchState ms = new MatchState( args, src, p ); - - int soffset = 0; - int n = 0; - while ( n < max_s ) { - ms.reset(); - int res = ms.match( soffset, anchor ? 1 : 0 ); - if ( res != -1 && res != lastmatch ) { /* match? */ - n++; - ms.add_value( lbuf, soffset, res, repl ); /* add replacement to buffer */ - soffset = lastmatch = res; - } - else if ( soffset < srclen ) /* otherwise, skip one character */ - lbuf.append( (byte) src.luaByte( soffset++ ) ); - else break; /* end of subject */ - if ( anchor ) break; - } - lbuf.append( src.substring( soffset, srclen ) ); - return varargsOf(lbuf.tostring(), valueOf(n)); - } - } - - /** - * string.len (s) - * - * Receives a string and returns its length. The empty string "" has length 0. - * Embedded zeros are counted, so "a\000bc\000" has length 5. - */ - static final class len extends OneArgFunction { - public LuaValue call(LuaValue arg) { - return arg.checkstring().len(); - } - } - - /** - * string.lower (s) - * - * Receives a string and returns a copy of this string with all uppercase letters - * changed to lowercase. All other characters are left unchanged. - * The definition of what an uppercase letter is depends on the current locale. - */ - static final class lower extends OneArgFunction { - public LuaValue call(LuaValue arg) { - return valueOf( arg.checkjstring().toLowerCase() ); - } - } - - /** - * string.match (s, pattern [, init]) - * - * Looks for the first match of pattern in the string s. If it finds one, - * then match returns the captures from the pattern; otherwise it returns - * nil. If pattern specifies no captures, then the whole match is returned. - * A third, optional numerical argument init specifies where to start the - * search; its default value is 1 and may be negative. - */ - static final class match extends VarArgFunction { - public Varargs invoke(Varargs args) { - return str_find_aux( args, false ); - } - } - - /** - * string.rep (s, n) - * - * Returns a string that is the concatenation of n copies of the string s. - */ - static final class rep extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaString s = args.checkstring( 1 ); - int n = args.checkint( 2 ); - final byte[] bytes = new byte[ s.length() * n ]; - int len = s.length(); - for ( int offset = 0; offset < bytes.length; offset += len ) { - s.copyInto( 0, bytes, offset, len ); - } - return LuaString.valueUsing( bytes ); - } - } - - /** - * string.reverse (s) - * - * Returns a string that is the string s reversed. - */ - static final class reverse extends OneArgFunction { - public LuaValue call(LuaValue arg) { - LuaString s = arg.checkstring(); - int n = s.length(); - byte[] b = new byte[n]; - for ( int i=0, j=n-1; i l ) - end = l; - - if ( start <= end ) { - return s.substring( start-1 , end ); - } else { - return EMPTYSTRING; - } - } - } - - /** - * string.upper (s) - * - * Receives a string and returns a copy of this string with all lowercase letters - * changed to uppercase. All other characters are left unchanged. - * The definition of what a lowercase letter is depends on the current locale. - */ - static final class upper extends OneArgFunction { - public LuaValue call(LuaValue arg) { - return valueOf(arg.checkjstring().toUpperCase()); - } - } - - /** - * This utility method implements both string.find and string.match. - */ - static Varargs str_find_aux( Varargs args, boolean find ) { - LuaString s = args.checkstring( 1 ); - LuaString pat = args.checkstring( 2 ); - int init = args.optint( 3, 1 ); - - if ( init > 0 ) { - init = Math.min( init - 1, s.length() ); - } else if ( init < 0 ) { - init = Math.max( 0, s.length() + init ); - } - - boolean fastMatch = find && ( args.arg(4).toboolean() || pat.indexOfAny( SPECIALS ) == -1 ); - - if ( fastMatch ) { - int result = s.indexOf( pat, init ); - if ( result != -1 ) { - return varargsOf( valueOf(result+1), valueOf(result+pat.length()) ); - } - } else { - MatchState ms = new MatchState( args, s, pat ); - - boolean anchor = false; - int poff = 0; - if ( pat.length() > 0 && pat.luaByte( 0 ) == '^' ) { - anchor = true; - poff = 1; - } - - int soff = init; - do { - int res; - ms.reset(); - if ( ( res = ms.match( soff, poff ) ) != -1 ) { - if ( find ) { - return varargsOf( valueOf(soff+1), valueOf(res), ms.push_captures( false, soff, res )); - } else { - return ms.push_captures( true, soff, res ); - } - } - } while ( soff++ < s.length() && !anchor ); - } - return NIL; - } - - static int posrelat( int pos, int len ) { - return ( pos >= 0 ) ? pos : len + pos + 1; - } - - // Pattern matching implementation - - private static final int L_ESC = '%'; - private static final LuaString SPECIALS = valueOf("^$*+?.([%-"); - private static final int MAX_CAPTURES = 32; - - private static final int MAXCCALLS = 200; - - private static final int CAP_UNFINISHED = -1; - private static final int CAP_POSITION = -2; - - private static final byte MASK_ALPHA = 0x01; - private static final byte MASK_LOWERCASE = 0x02; - private static final byte MASK_UPPERCASE = 0x04; - private static final byte MASK_DIGIT = 0x08; - private static final byte MASK_PUNCT = 0x10; - private static final byte MASK_SPACE = 0x20; - private static final byte MASK_CONTROL = 0x40; - private static final byte MASK_HEXDIGIT = (byte)0x80; - - static final byte[] CHAR_TABLE; - - static { - CHAR_TABLE = new byte[256]; - - for ( int i = 0; i < 128; ++i ) { - final char c = (char) i; - CHAR_TABLE[i] = (byte)( ( Character.isDigit( c ) ? MASK_DIGIT : 0 ) | - ( Character.isLowerCase( c ) ? MASK_LOWERCASE : 0 ) | - ( Character.isUpperCase( c ) ? MASK_UPPERCASE : 0 ) | - ( ( c < ' ' || c == 0x7F ) ? MASK_CONTROL : 0 ) ); - if ( ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) || ( c >= '0' && c <= '9' ) ) { - CHAR_TABLE[i] |= MASK_HEXDIGIT; - } - if ( ( c >= '!' && c <= '/' ) || ( c >= ':' && c <= '@' ) || ( c >= '[' && c <= '`' ) || ( c >= '{' && c <= '~' ) ) { - CHAR_TABLE[i] |= MASK_PUNCT; - } - if ( ( CHAR_TABLE[i] & ( MASK_LOWERCASE | MASK_UPPERCASE ) ) != 0 ) { - CHAR_TABLE[i] |= MASK_ALPHA; - } - } - - CHAR_TABLE[' '] = MASK_SPACE; - CHAR_TABLE['\r'] |= MASK_SPACE; - CHAR_TABLE['\n'] |= MASK_SPACE; - CHAR_TABLE['\t'] |= MASK_SPACE; - CHAR_TABLE[0x0B /* '\v' */ ] |= MASK_SPACE; - CHAR_TABLE['\f'] |= MASK_SPACE; - }; - - static class MatchState { - int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ - final LuaString s; - final LuaString p; - final Varargs args; - int level; - int[] cinit; - int[] clen; - - MatchState( Varargs args, LuaString s, LuaString pattern ) { - this.s = s; - this.p = pattern; - this.args = args; - this.level = 0; - this.cinit = new int[ MAX_CAPTURES ]; - this.clen = new int[ MAX_CAPTURES ]; - this.matchdepth = MAXCCALLS; - } - - void reset() { - level = 0; - this.matchdepth = MAXCCALLS; - } - - private void add_s( Buffer lbuf, LuaString news, int soff, int e ) { - int l = news.length(); - for ( int i = 0; i < l; ++i ) { - byte b = (byte) news.luaByte( i ); - if ( b != L_ESC ) { - lbuf.append( (byte) b ); - } else { - ++i; // skip ESC - b = (byte)(i < l ? news.luaByte( i ) : 0); - if ( !Character.isDigit( (char) b ) ) { - if (b != L_ESC) error( "invalid use of '" + (char)L_ESC + - "' in replacement string: after '" + (char)L_ESC + - "' must be '0'-'9' or '" + (char)L_ESC + - "', but found " + (i < l ? "symbol '" + (char)b + "' with code " + b + - " at pos " + (i + 1) : - "end of string")); - lbuf.append( b ); - } else if ( b == '0' ) { - lbuf.append( s.substring( soff, e ) ); - } else { - lbuf.append( push_onecapture( b - '1', soff, e ).strvalue() ); - } - } - } - } - - public void add_value( Buffer lbuf, int soffset, int end, LuaValue repl ) { - switch ( repl.type() ) { - case LuaValue.TSTRING: - case LuaValue.TNUMBER: - add_s( lbuf, repl.strvalue(), soffset, end ); - return; - - case LuaValue.TFUNCTION: - repl = repl.invoke( push_captures( true, soffset, end ) ).arg1(); - break; - - case LuaValue.TTABLE: - // Need to call push_onecapture here for the error checking - repl = repl.get( push_onecapture( 0, soffset, end ) ); - break; - - default: - error( "bad argument: string/function/table expected" ); - return; - } - - if ( !repl.toboolean() ) { - repl = s.substring( soffset, end ); - } else if ( ! repl.isstring() ) { - error( "invalid replacement value (a "+repl.typename()+")" ); - } - lbuf.append( repl.strvalue() ); - } - - Varargs push_captures( boolean wholeMatch, int soff, int end ) { - int nlevels = ( this.level == 0 && wholeMatch ) ? 1 : this.level; - switch ( nlevels ) { - case 0: return NONE; - case 1: return push_onecapture( 0, soff, end ); - } - LuaValue[] v = new LuaValue[nlevels]; - for ( int i = 0; i < nlevels; ++i ) - v[i] = push_onecapture( i, soff, end ); - return varargsOf(v); - } - - private LuaValue push_onecapture( int i, int soff, int end ) { - if ( i >= this.level ) { - if ( i == 0 ) { - return s.substring( soff, end ); - } else { - return error( "invalid capture index %" + (i + 1) ); - } - } else { - int l = clen[i]; - if ( l == CAP_UNFINISHED ) { - return error( "unfinished capture" ); - } - if ( l == CAP_POSITION ) { - return valueOf( cinit[i] + 1 ); - } else { - int begin = cinit[i]; - return s.substring( begin, begin + l ); - } - } - } - - private int check_capture( int l ) { - l -= '1'; - if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) { - error("invalid capture index %" + (l + 1)); - } - return l; - } - - private int capture_to_close() { - int level = this.level; - for ( level--; level >= 0; level-- ) - if ( clen[level] == CAP_UNFINISHED ) - return level; - error("invalid pattern capture"); - return 0; - } - - int classend( int poffset ) { - switch ( p.luaByte( poffset++ ) ) { - case L_ESC: - if ( poffset == p.length() ) { - error( "malformed pattern (ends with '%')" ); - } - return poffset + 1; - - case '[': - if ( poffset != p.length() && p.luaByte( poffset ) == '^' ) poffset++; - do { - if ( poffset == p.length() ) { - error( "malformed pattern (missing ']')" ); - } - if ( p.luaByte( poffset++ ) == L_ESC && poffset < p.length() ) - poffset++; /* skip escapes (e.g. '%]') */ - } while ( poffset == p.length() || p.luaByte( poffset ) != ']' ); - return poffset + 1; - default: - return poffset; - } - } - - static boolean match_class( int c, int cl ) { - final char lcl = Character.toLowerCase( (char) cl ); - int cdata = CHAR_TABLE[c]; - - boolean res; - switch ( lcl ) { - case 'a': res = ( cdata & MASK_ALPHA ) != 0; break; - case 'd': res = ( cdata & MASK_DIGIT ) != 0; break; - case 'l': res = ( cdata & MASK_LOWERCASE ) != 0; break; - case 'u': res = ( cdata & MASK_UPPERCASE ) != 0; break; - case 'c': res = ( cdata & MASK_CONTROL ) != 0; break; - case 'p': res = ( cdata & MASK_PUNCT ) != 0; break; - case 's': res = ( cdata & MASK_SPACE ) != 0; break; - case 'g': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT | MASK_PUNCT ) ) != 0; break; - case 'w': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT ) ) != 0; break; - case 'x': res = ( cdata & MASK_HEXDIGIT ) != 0; break; - case 'z': res = ( c == 0 ); break; /* deprecated option */ - default: return cl == c; - } - return ( lcl == cl ) ? res : !res; - } - - boolean matchbracketclass( int c, int poff, int ec ) { - boolean sig = true; - if ( p.luaByte( poff + 1 ) == '^' ) { - sig = false; - poff++; - } - while ( ++poff < ec ) { - if ( p.luaByte( poff ) == L_ESC ) { - poff++; - if ( match_class( c, p.luaByte( poff ) ) ) - return sig; - } - else if ( ( p.luaByte( poff + 1 ) == '-' ) && ( poff + 2 < ec ) ) { - poff += 2; - if ( p.luaByte( poff - 2 ) <= c && c <= p.luaByte( poff ) ) - return sig; - } - else if ( p.luaByte( poff ) == c ) return sig; - } - return !sig; - } - - boolean singlematch( int c, int poff, int ep ) { - switch ( p.luaByte( poff ) ) { - case '.': return true; - case L_ESC: return match_class( c, p.luaByte( poff + 1 ) ); - case '[': return matchbracketclass( c, poff, ep - 1 ); - default: return p.luaByte( poff ) == c; - } - } - - /** - * Perform pattern matching. If there is a match, returns offset into s - * where match ends, otherwise returns -1. - */ - int match( int soffset, int poffset ) { - if (matchdepth-- == 0) error("pattern too complex"); - try { - while ( true ) { - // Check if we are at the end of the pattern - - // equivalent to the '\0' case in the C version, but our pattern - // string is not NUL-terminated. - if ( poffset == p.length() ) - return soffset; - switch ( p.luaByte( poffset ) ) { - case '(': - if ( ++poffset < p.length() && p.luaByte( poffset ) == ')' ) - return start_capture( soffset, poffset + 1, CAP_POSITION ); - else - return start_capture( soffset, poffset, CAP_UNFINISHED ); - case ')': - return end_capture( soffset, poffset + 1 ); - case L_ESC: - if ( poffset + 1 == p.length() ) - error("malformed pattern (ends with '%')"); - switch ( p.luaByte( poffset + 1 ) ) { - case 'b': - soffset = matchbalance( soffset, poffset + 2 ); - if ( soffset == -1 ) return -1; - poffset += 4; - continue; - case 'f': { - poffset += 2; - if ( poffset == p.length() || p.luaByte( poffset ) != '[' ) { - error("missing '[' after '%f' in pattern"); - } - int ep = classend( poffset ); - int previous = ( soffset == 0 ) ? '\0' : s.luaByte( soffset - 1 ); - int next = ( soffset == s.length() ) ? '\0' : s.luaByte( soffset ); - if ( matchbracketclass( previous, poffset, ep - 1 ) || - !matchbracketclass( next, poffset, ep - 1 ) ) - return -1; - poffset = ep; - continue; - } - default: { - int c = p.luaByte( poffset + 1 ); - if ( Character.isDigit( (char) c ) ) { - soffset = match_capture( soffset, c ); - if ( soffset == -1 ) - return -1; - return match( soffset, poffset + 2 ); - } - } - } - case '$': - if ( poffset + 1 == p.length() ) - return ( soffset == s.length() ) ? soffset : -1; - } - int ep = classend( poffset ); - boolean m = soffset < s.length() && singlematch( s.luaByte( soffset ), poffset, ep ); - int pc = ( ep < p.length() ) ? p.luaByte( ep ) : '\0'; - - switch ( pc ) { - case '?': - int res; - if ( m && ( ( res = match( soffset + 1, ep + 1 ) ) != -1 ) ) - return res; - poffset = ep + 1; - continue; - case '*': - return max_expand( soffset, poffset, ep ); - case '+': - return ( m ? max_expand( soffset + 1, poffset, ep ) : -1 ); - case '-': - return min_expand( soffset, poffset, ep ); - default: - if ( !m ) - return -1; - soffset++; - poffset = ep; - continue; - } - } - } finally { - matchdepth++; - } - } - - int max_expand( int soff, int poff, int ep ) { - int i = 0; - while ( soff + i < s.length() && - singlematch( s.luaByte( soff + i ), poff, ep ) ) - i++; - while ( i >= 0 ) { - int res = match( soff + i, ep + 1 ); - if ( res != -1 ) - return res; - i--; - } - return -1; - } - - int min_expand( int soff, int poff, int ep ) { - for ( ;; ) { - int res = match( soff, ep + 1 ); - if ( res != -1 ) - return res; - else if ( soff < s.length() && singlematch( s.luaByte( soff ), poff, ep ) ) - soff++; - else return -1; - } - } - - int start_capture( int soff, int poff, int what ) { - int res; - int level = this.level; - if ( level >= MAX_CAPTURES ) { - error( "too many captures" ); - } - cinit[ level ] = soff; - clen[ level ] = what; - this.level = level + 1; - if ( ( res = match( soff, poff ) ) == -1 ) - this.level--; - return res; - } - - int end_capture( int soff, int poff ) { - int l = capture_to_close(); - int res; - clen[l] = soff - cinit[l]; - if ( ( res = match( soff, poff ) ) == -1 ) - clen[l] = CAP_UNFINISHED; - return res; - } - - int match_capture( int soff, int l ) { - l = check_capture( l ); - int len = clen[ l ]; - if ( ( s.length() - soff ) >= len && - LuaString.equals( s, cinit[l], s, soff, len ) ) - return soff + len; - else - return -1; - } - - int matchbalance( int soff, int poff ) { - final int plen = p.length(); - if ( poff == plen || poff + 1 == plen ) { - error( "malformed pattern (missing arguments to '%b')" ); - } - final int slen = s.length(); - if ( soff >= slen ) - return -1; - final int b = p.luaByte( poff ); - if ( s.luaByte( soff ) != b ) - return -1; - final int e = p.luaByte( poff + 1 ); - int cont = 1; - while ( ++soff < slen ) { - if ( s.luaByte( soff ) == e ) { - if ( --cont == 0 ) return soff + 1; - } - else if ( s.luaByte( soff ) == b ) cont++; - } - return -1; - } - } -} diff --git a/src/core/org/luaj/vm2/lib/TableLib.java b/src/core/org/luaj/vm2/lib/TableLib.java deleted file mode 100644 index 64959277..00000000 --- a/src/core/org/luaj/vm2/lib/TableLib.java +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** - * Subclass of {@link LibFunction} which implements the lua standard {@code table} - * library. - * - *

    - * Typically, this library is included as part of a call to either - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("table").get("length").call( LuaValue.tableOf() ) );
    - * } 
    - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new TableLib());
    - * System.out.println( globals.get("table").get("length").call( LuaValue.tableOf() ) );
    - * } 
    - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 Table Lib Reference - */ -public class TableLib extends TwoArgFunction { - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, typically a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - LuaTable table = new LuaTable(); - table.set("concat", new concat()); - table.set("insert", new insert()); - table.set("pack", new pack()); - table.set("remove", new remove()); - table.set("sort", new sort()); - table.set("unpack", new unpack()); - env.set("table", table); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("table", table); - return NIL; - } - - // "concat" (table [, sep [, i [, j]]]) -> string - static class concat extends TableLibFunction { - public LuaValue call(LuaValue list) { - return list.checktable().concat(EMPTYSTRING,1,list.length()); - } - public LuaValue call(LuaValue list, LuaValue sep) { - return list.checktable().concat(sep.checkstring(),1,list.length()); - } - public LuaValue call(LuaValue list, LuaValue sep, LuaValue i) { - return list.checktable().concat(sep.checkstring(),i.checkint(),list.length()); - } - public LuaValue call(LuaValue list, LuaValue sep, LuaValue i, LuaValue j) { - return list.checktable().concat(sep.checkstring(),i.checkint(),j.checkint()); - } - } - - // "insert" (table, [pos,] value) - static class insert extends VarArgFunction { - public Varargs invoke(Varargs args) { - switch (args.narg()) { - case 2: { - LuaTable table = args.checktable(1); - table.insert(table.length()+1,args.arg(2)); - return NONE; - } - case 3: { - LuaTable table = args.checktable(1); - int pos = args.checkint(2); - int max = table.length() + 1; - if (pos < 1 || pos > max) argerror(2, "position out of bounds: " + pos + " not between 1 and " + max); - table.insert(pos, args.arg(3)); - return NONE; - } - default: { - return error("wrong number of arguments to 'table.insert': " + args.narg() + " (must be 2 or 3)"); - } - } - } - } - - // "pack" (...) -> table - static class pack extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaValue t = tableOf(args, 1); - t.set("n", args.narg()); - return t; - } - } - - // "remove" (table [, pos]) -> removed-ele - static class remove extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaTable table = args.checktable(1); - int size = table.length(); - int pos = args.optint(2, size); - if (pos != size && (pos < 1 || pos > size + 1)) { - argerror(2, "position out of bounds: " + pos + " not between 1 and " + (size + 1)); - } - return table.remove(pos); - } - } - - // "sort" (table [, comp]) - static class sort extends VarArgFunction { - public Varargs invoke(Varargs args) { - args.checktable(1).sort( - args.isnil(2)? NIL: args.checkfunction(2)); - return NONE; - } - } - - - // "unpack", // (list [,i [,j]]) -> result1, ... - static class unpack extends VarArgFunction { - public Varargs invoke(Varargs args) { - LuaTable t = args.checktable(1); - // do not waste resource for calc rawlen if arg3 is not nil - int len = args.arg(3).isnil() ? t.length() : 0; - return t.unpack(args.optint(2, 1), args.optint(3, len)); - } - } -} diff --git a/src/core/org/luaj/vm2/lib/TableLibFunction.java b/src/core/org/luaj/vm2/lib/TableLibFunction.java deleted file mode 100644 index 5fabef7e..00000000 --- a/src/core/org/luaj/vm2/lib/TableLibFunction.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaValue; - -class TableLibFunction extends LibFunction { - public LuaValue call() { - return argerror(1, "table expected, got no value"); - } -} diff --git a/src/core/org/luaj/vm2/lib/ThreeArgFunction.java b/src/core/org/luaj/vm2/lib/ThreeArgFunction.java deleted file mode 100644 index 68ceb243..00000000 --- a/src/core/org/luaj/vm2/lib/ThreeArgFunction.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** Abstract base class for Java function implementations that take two arguments and - * return one value. - *

    - * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue,LuaValue)} to complete this class, - * simplifying development. - * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc, - * are routed through this method by this class, - * dropping or extending arguments with {@code nil} values as required. - *

    - * If more or less than three arguments are required, - * or variable argument or variable return values, - * then use one of the related function - * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link VarArgFunction}. - *

    - * See {@link LibFunction} for more information on implementation libraries and library functions. - * @see #call(LuaValue,LuaValue,LuaValue) - * @see LibFunction - * @see ZeroArgFunction - * @see OneArgFunction - * @see TwoArgFunction - * @see VarArgFunction - */ -abstract public class ThreeArgFunction extends LibFunction { - - abstract public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3); - - /** Default constructor */ - public ThreeArgFunction() { - } - - public final LuaValue call() { - return call(NIL, NIL, NIL); - } - - public final LuaValue call(LuaValue arg) { - return call(arg, NIL, NIL); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2) { - return call(arg1, arg2, NIL); - } - - public Varargs invoke(Varargs varargs) { - return call(varargs.arg1(),varargs.arg(2),varargs.arg(3)); - } - -} diff --git a/src/core/org/luaj/vm2/lib/TwoArgFunction.java b/src/core/org/luaj/vm2/lib/TwoArgFunction.java deleted file mode 100644 index 8a97f6fb..00000000 --- a/src/core/org/luaj/vm2/lib/TwoArgFunction.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** Abstract base class for Java function implementations that take two arguments and - * return one value. - *

    - * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue)} to complete this class, - * simplifying development. - * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc, - * are routed through this method by this class, - * dropping or extending arguments with {@code nil} values as required. - *

    - * If more or less than two arguments are required, - * or variable argument or variable return values, - * then use one of the related function - * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. - *

    - * See {@link LibFunction} for more information on implementation libraries and library functions. - * @see #call(LuaValue,LuaValue) - * @see LibFunction - * @see ZeroArgFunction - * @see OneArgFunction - * @see ThreeArgFunction - * @see VarArgFunction - */ -abstract public class TwoArgFunction extends LibFunction { - - abstract public LuaValue call(LuaValue arg1, LuaValue arg2); - - /** Default constructor */ - public TwoArgFunction() { - } - - public final LuaValue call() { - return call(NIL, NIL); - } - - public final LuaValue call(LuaValue arg) { - return call(arg, NIL); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { - return call(arg1, arg2); - } - - public Varargs invoke(Varargs varargs) { - return call(varargs.arg1(),varargs.arg(2)); - } - -} diff --git a/src/core/org/luaj/vm2/lib/VarArgFunction.java b/src/core/org/luaj/vm2/lib/VarArgFunction.java deleted file mode 100644 index 8e2bd614..00000000 --- a/src/core/org/luaj/vm2/lib/VarArgFunction.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** Abstract base class for Java function implementations that takes varaiable arguments and - * returns multiple return values. - *

    - * Subclasses need only implement {@link LuaValue#invoke(Varargs)} to complete this class, - * simplifying development. - * All other uses of {@link #call(LuaValue)}, {@link #invoke()},etc, - * are routed through this method by this class, - * converting arguments to {@link Varargs} and - * dropping or extending return values with {@code nil} values as required. - *

    - * If between one and three arguments are required, and only one return value is returned, - * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link ThreeArgFunction}. - *

    - * See {@link LibFunction} for more information on implementation libraries and library functions. - * @see #invoke(Varargs) - * @see LibFunction - * @see ZeroArgFunction - * @see OneArgFunction - * @see TwoArgFunction - * @see ThreeArgFunction - */ -abstract public class VarArgFunction extends LibFunction { - - public VarArgFunction() { - } - - public LuaValue call() { - return invoke(NONE).arg1(); - } - - public LuaValue call(LuaValue arg) { - return invoke(arg).arg1(); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2) { - return invoke(varargsOf(arg1,arg2)).arg1(); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { - return invoke(varargsOf(arg1,arg2,arg3)).arg1(); - } - - /** - * Subclass responsibility. - * May not have expected behavior for tail calls. - * Should not be used if: - * - function has a possibility of returning a TailcallVarargs - * @param args the arguments to the function call. - */ - public Varargs invoke(Varargs args) { - return onInvoke(args).eval(); - } - - public Varargs onInvoke(Varargs args) { - return invoke(args); - } -} diff --git a/src/core/org/luaj/vm2/lib/ZeroArgFunction.java b/src/core/org/luaj/vm2/lib/ZeroArgFunction.java deleted file mode 100644 index 06169d74..00000000 --- a/src/core/org/luaj/vm2/lib/ZeroArgFunction.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib; - -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; - -/** Abstract base class for Java function implementations that take no arguments and - * return one value. - *

    - * Subclasses need only implement {@link LuaValue#call()} to complete this class, - * simplifying development. - * All other uses of {@link #call(LuaValue)}, {@link #invoke(Varargs)},etc, - * are routed through this method by this class. - *

    - * If one or more arguments are required, or variable argument or variable return values, - * then use one of the related function - * {@link OneArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. - *

    - * See {@link LibFunction} for more information on implementation libraries and library functions. - * @see #call() - * @see LibFunction - * @see OneArgFunction - * @see TwoArgFunction - * @see ThreeArgFunction - * @see VarArgFunction - */ -abstract public class ZeroArgFunction extends LibFunction { - - abstract public LuaValue call(); - - /** Default constructor */ - public ZeroArgFunction() { - } - - public LuaValue call(LuaValue arg) { - return call(); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2) { - return call(); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { - return call(); - } - - public Varargs invoke(Varargs varargs) { - return call(); - } -} diff --git a/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java b/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java deleted file mode 100644 index e7cbd3c1..00000000 --- a/src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jme; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import javax.microedition.io.Connector; -import javax.microedition.io.StreamConnection; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.IoLib; -import org.luaj.vm2.lib.LibFunction; - -/** - * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io} - * library for the JSE platform. - *

    - * The implementation of the is based on CLDC 1.0 and StreamConnection. - * However, seek is not supported. - *

    - * Typically, this library is included as part of a call to - * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JmePlatform.standardGlobals();
    - * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
    - * } 
    - *

    - * For special cases where the smallest possible footprint is desired, - * a minimal set of libraries could be loaded - * directly via {@link Globals#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JmeBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new JmeIoLib());
    - * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
    - * } 
    - *

    However, other libraries such as MathLib are not loaded in this case. - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see IoLib - * @see org.luaj.vm2.lib.jse.JseIoLib - * @see Lua 5.2 I/O Lib Reference - */ -public class JmeIoLib extends IoLib { - - protected File wrapStdin() throws IOException { - return new FileImpl(globals.STDIN); - } - - protected File wrapStdout() throws IOException { - return new FileImpl(globals.STDOUT); - } - - protected File wrapStderr() throws IOException { - return new FileImpl(globals.STDERR); - } - - protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { - String url = "file:///" + filename; - int mode = readMode? Connector.READ: Connector.READ_WRITE; - StreamConnection conn = (StreamConnection) Connector.open( url, mode ); - File f = readMode? - new FileImpl(conn, conn.openInputStream(), null): - new FileImpl(conn, conn.openInputStream(), conn.openOutputStream()); - /* - if ( appendMode ) { - f.seek("end",0); - } else { - if ( ! readMode ) - conn.truncate(0); - } - */ - return f; - } - - private static void notimplemented() throws IOException { - throw new IOException("not implemented"); - } - - protected File openProgram(String prog, String mode) throws IOException { - notimplemented(); - return null; - } - - protected File tmpFile() throws IOException { - notimplemented(); - return null; - } - - private final class FileImpl extends File { - private final StreamConnection conn; - private final InputStream is; - private final OutputStream os; - private boolean closed = false; - private boolean nobuffer = false; - private int lookahead = -1; - private FileImpl( StreamConnection conn, InputStream is, OutputStream os ) { - this.conn = conn; - this.is = is; - this.os = os; - } - private FileImpl( InputStream i ) { - this( null, i, null ); - } - private FileImpl( OutputStream o ) { - this( null, null, o ); - } - public String tojstring() { - return "file ("+this.hashCode()+")"; - } - public boolean isstdfile() { - return conn == null; - } - public void close() throws IOException { - closed = true; - if ( conn != null ) { - conn.close(); - } - } - public void flush() throws IOException { - if ( os != null ) - os.flush(); - } - public void write(LuaString s) throws IOException { - if ( os != null ) - os.write( s.m_bytes, s.m_offset, s.m_length ); - else - notimplemented(); - if ( nobuffer ) - flush(); - } - public boolean isclosed() { - return closed; - } - public int seek(String option, int pos) throws IOException { - /* - if ( conn != null ) { - if ( "set".equals(option) ) { - conn.seek(pos); - return (int) conn.getFilePointer(); - } else if ( "end".equals(option) ) { - conn.seek(conn.length()+1+pos); - return (int) conn.length()+1; - } else { - conn.seek(conn.getFilePointer()+pos); - return (int) conn.getFilePointer(); - } - } - */ - notimplemented(); - return 0; - } - public void setvbuf(String mode, int size) { - nobuffer = "no".equals(mode); - } - - // get length remaining to read - public int remaining() throws IOException { - return -1; - } - - // peek ahead one character - public int peek() throws IOException { - if ( lookahead < 0 ) - lookahead = is.read(); - return lookahead; - } - - // return char if read, -1 if eof, throw IOException on other exception - public int read() throws IOException { - if ( lookahead >= 0 ) { - int c = lookahead; - lookahead = -1; - return c; - } - if ( is != null ) - return is.read(); - notimplemented(); - return 0; - } - - // return number of bytes read if positive, -1 if eof, throws IOException - public int read(byte[] bytes, int offset, int length) throws IOException { - int n,i=0; - if (is!=null) { - if ( length > 0 && lookahead >= 0 ) { - bytes[offset] = (byte) lookahead; - lookahead = -1; - i += 1; - } - for ( ; i 0 ? i : -1 ); - i += n; - } - } else { - notimplemented(); - } - return length; - } - } -} diff --git a/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java b/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java deleted file mode 100644 index c7c8bb66..00000000 --- a/src/jme/org/luaj/vm2/lib/jme/JmePlatform.java +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009 Luaj.org. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - ******************************************************************************/ -package org.luaj.vm2.lib.jme; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LoadState; -import org.luaj.vm2.LuaThread; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.compiler.LuaC; -import org.luaj.vm2.lib.BaseLib; -import org.luaj.vm2.lib.Bit32Lib; -import org.luaj.vm2.lib.CoroutineLib; -import org.luaj.vm2.lib.DebugLib; -import org.luaj.vm2.lib.MathLib; -import org.luaj.vm2.lib.OsLib; -import org.luaj.vm2.lib.PackageLib; -import org.luaj.vm2.lib.ResourceFinder; -import org.luaj.vm2.lib.StringLib; -import org.luaj.vm2.lib.TableLib; - -/** The {@link org.luaj.vm2.lib.jme.JmePlatform} class is a convenience class to standardize - * how globals tables are initialized for the JME platform. - *

    - * The JME platform, being limited, cannot implement all libraries in all aspects. The main limitations are - *

    - *

    - * It is used to allocate either a set of standard globals using - * {@link #standardGlobals()} or debug globals using {@link #debugGlobals()} - *

    - * A simple example of initializing globals and using them from Java is: - *

     {@code
    - * Globals global = JmePlatform.standardGlobals();
    - * global.get("print").call(LuaValue.valueOf("hello, world"));
    - * } 
    - *

    - * Once globals are created, a simple way to load and run a script is: - *

     {@code
    - * LoadState.load( getClass().getResourceAsStream("main.lua"), "main.lua", globals ).call();
    - * } 
    - *

    - * although {@code require} could also be used: - *

     {@code
    - * globals.get("require").call(LuaValue.valueOf("main"));
    - * } 
    - * For this to succeed, the file "main.lua" must be a resource in the class path. - * See {@link BaseLib} for details on finding scripts using {@link ResourceFinder}. - *

    - * The standard globals will contain all standard libraries in their JME flavors: - *

    - * In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form. - *

    - * The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}. - *

    - *

    - * The class ensures that initialization is done in the correct order. - * - * @see Globals - * @see org.luaj.vm2.lib.jse.JsePlatform - */ -public class JmePlatform { - - /** - * Create a standard set of globals for JME including all the libraries. - * - * @return Table of globals initialized with the standard JME libraries - * @see #debugGlobals() - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - */ - public static Globals standardGlobals() { - Globals globals = new Globals(); - globals.load(new BaseLib()); - globals.load(new PackageLib()); - globals.load(new Bit32Lib()); - globals.load(new OsLib()); - globals.load(new MathLib()); - globals.load(new TableLib()); - globals.load(new StringLib()); - globals.load(new CoroutineLib()); - globals.load(new JmeIoLib()); - LoadState.install(globals); - LuaC.install(globals); - return globals; - } - - /** Create standard globals including the {@link DebugLib} library. - * - * @return Table of globals initialized with the standard JSE and debug libraries - * @see #standardGlobals() - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see DebugLib - */ - public static Globals debugGlobals() { - Globals globals = standardGlobals(); - globals.load(new DebugLib()); - return globals; - } -} diff --git a/src/jse/org/luaj/vm2/lib/jse/CoerceJavaToLua.java b/src/jse/org/luaj/vm2/lib/jse/CoerceJavaToLua.java deleted file mode 100644 index 177f9acf..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/CoerceJavaToLua.java +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.luaj.vm2.LuaDouble; -import org.luaj.vm2.LuaInteger; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaUserdata; -import org.luaj.vm2.LuaValue; - -/** - * Helper class to coerce values from Java to lua within the luajava library. - *

    - * This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib}, - * but can also be used directly when working with Java/lua bindings. - *

    - * To coerce scalar types, the various, generally the {@code valueOf(type)} methods - * on {@link LuaValue} may be used: - *

    - *

    - * To coerce arrays of objects and lists, the {@code listOf(..)} and {@code tableOf(...)} methods - * on {@link LuaValue} may be used: - *

    - * The method {@link CoerceJavaToLua#coerce(Object)} looks as the type and dimesioning - * of the argument and tries to guess the best fit for corrsponding lua scalar, - * table, or table of tables. - * - * @see CoerceJavaToLua#coerce(Object) - * @see org.luaj.vm2.lib.jse.LuajavaLib - */ -public class CoerceJavaToLua { - - static interface Coercion { - public LuaValue coerce( Object javaValue ); - }; - - private static final class BoolCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - Boolean b = (Boolean) javaValue; - return b.booleanValue()? LuaValue.TRUE: LuaValue.FALSE; - } - } - - private static final class IntCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - Number n = (Number) javaValue; - return LuaInteger.valueOf( n.intValue() ); - } - } - - private static final class CharCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - Character c = (Character) javaValue; - return LuaInteger.valueOf( c.charValue() ); - } - } - - private static final class DoubleCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - Number n = (Number) javaValue; - return LuaDouble.valueOf( n.doubleValue() ); - } - } - - private static final class StringCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - return LuaString.valueOf( javaValue.toString() ); - } - } - - private static final class BytesCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - return LuaValue.valueOf((byte[]) javaValue); - } - } - - private static final class ClassCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - return JavaClass.forClass((Class) javaValue); - } - } - - private static final class InstanceCoercion implements Coercion { - public LuaValue coerce(Object javaValue) { - return new JavaInstance(javaValue); - } - } - - private static final class ArrayCoercion implements Coercion { - public LuaValue coerce(Object javaValue) { - // should be userdata? - return new JavaArray(javaValue); - } - } - - private static final class LuaCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { - return (LuaValue) javaValue; - } - } - - - static final Map COERCIONS = Collections.synchronizedMap(new HashMap()); - - static { - Coercion boolCoercion = new BoolCoercion() ; - Coercion intCoercion = new IntCoercion() ; - Coercion charCoercion = new CharCoercion() ; - Coercion doubleCoercion = new DoubleCoercion() ; - Coercion stringCoercion = new StringCoercion() ; - Coercion bytesCoercion = new BytesCoercion() ; - Coercion classCoercion = new ClassCoercion() ; - COERCIONS.put( Boolean.class, boolCoercion ); - COERCIONS.put( Byte.class, intCoercion ); - COERCIONS.put( Character.class, charCoercion ); - COERCIONS.put( Short.class, intCoercion ); - COERCIONS.put( Integer.class, intCoercion ); - COERCIONS.put( Long.class, doubleCoercion ); - COERCIONS.put( Float.class, doubleCoercion ); - COERCIONS.put( Double.class, doubleCoercion ); - COERCIONS.put( String.class, stringCoercion ); - COERCIONS.put( byte[].class, bytesCoercion ); - COERCIONS.put( Class.class, classCoercion ); - } - - /** - * Coerse a Java object to a corresponding lua value. - *

    - * Integral types {@code boolean}, {@code byte}, {@code char}, and {@code int} - * will become {@link LuaInteger}; - * {@code long}, {@code float}, and {@code double} will become {@link LuaDouble}; - * {@code String} and {@code byte[]} will become {@link LuaString}; - * types inheriting from {@link LuaValue} will be returned without coercion; - * other types will become {@link LuaUserdata}. - * @param o Java object needing conversion - * @return {@link LuaValue} corresponding to the supplied Java value. - * @see LuaValue - * @see LuaInteger - * @see LuaDouble - * @see LuaString - * @see LuaUserdata - */ - public static LuaValue coerce(Object o) { - if ( o == null ) - return LuaValue.NIL; - Class clazz = o.getClass(); - Coercion c = (Coercion) COERCIONS.get( clazz ); - if ( c == null ) { - c = clazz.isArray()? arrayCoercion: - o instanceof LuaValue ? luaCoercion: - instanceCoercion; - COERCIONS.put( clazz, c ); - } - return c.coerce(o); - } - - static final Coercion instanceCoercion = new InstanceCoercion(); - - static final Coercion arrayCoercion = new ArrayCoercion(); - - static final Coercion luaCoercion = new LuaCoercion() ; -} diff --git a/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java b/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java deleted file mode 100644 index c658aacc..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/CoerceLuaToJava.java +++ /dev/null @@ -1,372 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import java.lang.reflect.Array; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; - -/** - * Helper class to coerce values from lua to Java within the luajava library. - *

    - * This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib}, - * but can also be used directly when working with Java/lua bindings. - *

    - * To coerce to specific Java values, generally the {@code toType()} methods - * on {@link LuaValue} may be used: - *

    - *

    - * For data in lua tables, the various methods on {@link LuaTable} can be used directly - * to convert data to something more useful. - * - * @see org.luaj.vm2.lib.jse.LuajavaLib - * @see CoerceJavaToLua - */ -public class CoerceLuaToJava { - - static int SCORE_NULL_VALUE = 0x10; - static int SCORE_WRONG_TYPE = 0x100; - static int SCORE_UNCOERCIBLE = 0x10000; - - static interface Coercion { - public int score( LuaValue value ); - public Object coerce( LuaValue value ); - }; - - /** - * Coerce a LuaValue value to a specified java class - * @param value LuaValue to coerce - * @param clazz Class to coerce into - * @return Object of type clazz (or a subclass) with the corresponding value. - */ - public static Object coerce(LuaValue value, Class clazz) { - return getCoercion(clazz).coerce(value); - } - - static final Map COERCIONS = Collections.synchronizedMap(new HashMap()); - - static final class BoolCoercion implements Coercion { - public String toString() { - return "BoolCoercion()"; - } - public int score( LuaValue value ) { - switch ( value.type() ) { - case LuaValue.TBOOLEAN: - return 0; - } - return 1; - } - - public Object coerce(LuaValue value) { - return value.toboolean()? Boolean.TRUE: Boolean.FALSE; - } - } - - static final class NumericCoercion implements Coercion { - static final int TARGET_TYPE_BYTE = 0; - static final int TARGET_TYPE_CHAR = 1; - static final int TARGET_TYPE_SHORT = 2; - static final int TARGET_TYPE_INT = 3; - static final int TARGET_TYPE_LONG = 4; - static final int TARGET_TYPE_FLOAT = 5; - static final int TARGET_TYPE_DOUBLE = 6; - static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" }; - final int targetType; - public String toString() { - return "NumericCoercion("+TYPE_NAMES[targetType]+")"; - } - NumericCoercion(int targetType) { - this.targetType = targetType; - } - public int score( LuaValue value ) { - int fromStringPenalty = 0; - if ( value.type() == LuaValue.TSTRING ) { - value = value.tonumber(); - if ( value.isnil() ) { - return SCORE_UNCOERCIBLE; - } - fromStringPenalty = 4; - } - if ( value.isint() ) { - switch ( targetType ) { - case TARGET_TYPE_BYTE: { - int i = value.toint(); - return fromStringPenalty + ((i==(byte)i)? 0: SCORE_WRONG_TYPE); - } - case TARGET_TYPE_CHAR: { - int i = value.toint(); - return fromStringPenalty + ((i==(byte)i)? 1: (i==(char)i)? 0: SCORE_WRONG_TYPE); - } - case TARGET_TYPE_SHORT: { - int i = value.toint(); - return fromStringPenalty + - ((i==(byte)i)? 1: (i==(short)i)? 0: SCORE_WRONG_TYPE); - } - case TARGET_TYPE_INT: { - int i = value.toint(); - return fromStringPenalty + - ((i==(byte)i)? 2: ((i==(char)i) || (i==(short)i))? 1: 0); - } - case TARGET_TYPE_FLOAT: return fromStringPenalty + 1; - case TARGET_TYPE_LONG: return fromStringPenalty + 1; - case TARGET_TYPE_DOUBLE: return fromStringPenalty + 2; - default: return SCORE_WRONG_TYPE; - } - } else if ( value.isnumber() ) { - switch ( targetType ) { - case TARGET_TYPE_BYTE: return SCORE_WRONG_TYPE; - case TARGET_TYPE_CHAR: return SCORE_WRONG_TYPE; - case TARGET_TYPE_SHORT: return SCORE_WRONG_TYPE; - case TARGET_TYPE_INT: return SCORE_WRONG_TYPE; - case TARGET_TYPE_LONG: { - double d = value.todouble(); - return fromStringPenalty + ((d==(long)d)? 0: SCORE_WRONG_TYPE); - } - case TARGET_TYPE_FLOAT: { - double d = value.todouble(); - return fromStringPenalty + ((d==(float)d)? 0: SCORE_WRONG_TYPE); - } - case TARGET_TYPE_DOUBLE: { - double d = value.todouble(); - return fromStringPenalty + (((d==(long)d) || (d==(float)d))? 1: 0); - } - default: return SCORE_WRONG_TYPE; - } - } else { - return SCORE_UNCOERCIBLE; - } - } - - public Object coerce(LuaValue value) { - switch ( targetType ) { - case TARGET_TYPE_BYTE: return new Byte( (byte) value.toint() ); - case TARGET_TYPE_CHAR: return new Character( (char) value.toint() ); - case TARGET_TYPE_SHORT: return new Short( (short) value.toint() ); - case TARGET_TYPE_INT: return new Integer( (int) value.toint() ); - case TARGET_TYPE_LONG: return new Long( (long) value.todouble() ); - case TARGET_TYPE_FLOAT: return new Float( (float) value.todouble() ); - case TARGET_TYPE_DOUBLE: return new Double( (double) value.todouble() ); - default: return null; - } - } - } - - static final class StringCoercion implements Coercion { - public static final int TARGET_TYPE_STRING = 0; - public static final int TARGET_TYPE_BYTES = 1; - final int targetType; - public StringCoercion(int targetType) { - this.targetType = targetType; - } - public String toString() { - return "StringCoercion("+(targetType==TARGET_TYPE_STRING? "String": "byte[]")+")"; - } - public int score(LuaValue value) { - switch ( value.type() ) { - case LuaValue.TSTRING: - return value.checkstring().isValidUtf8()? - (targetType==TARGET_TYPE_STRING? 0: 1): - (targetType==TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE); - case LuaValue.TNIL: - return SCORE_NULL_VALUE; - default: - return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE; - } - } - public Object coerce(LuaValue value) { - if ( value.isnil() ) - return null; - if ( targetType == TARGET_TYPE_STRING ) - return value.tojstring(); - LuaString s = value.checkstring(); - byte[] b = new byte[s.m_length]; - s.copyInto(0, b, 0, b.length); - return b; - } - } - - static final class ArrayCoercion implements Coercion { - final Class componentType; - final Coercion componentCoercion; - public ArrayCoercion(Class componentType) { - this.componentType = componentType; - this.componentCoercion = getCoercion(componentType); - } - public String toString() { - return "ArrayCoercion("+componentType.getName()+")"; - } - public int score(LuaValue value) { - switch ( value.type() ) { - case LuaValue.TTABLE: - return value.length()==0? 0: componentCoercion.score( value.get(1) ); - case LuaValue.TUSERDATA: - return inheritanceLevels( componentType, value.touserdata().getClass().getComponentType() ); - case LuaValue.TNIL: - return SCORE_NULL_VALUE; - default: - return SCORE_UNCOERCIBLE; - } - } - public Object coerce(LuaValue value) { - switch ( value.type() ) { - case LuaValue.TTABLE: { - int n = value.length(); - Object a = Array.newInstance(componentType, n); - for ( int i=0; i - * Can get elements by their integer key index, as well as the length. - *

    - * This class is not used directly. - * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)} - * when an array is supplied. - * @see CoerceJavaToLua - * @see CoerceLuaToJava - */ -class JavaArray extends LuaUserdata { - - private static final class LenFunction extends OneArgFunction { - public LuaValue call(LuaValue u) { - return LuaValue.valueOf(Array.getLength(((LuaUserdata)u).m_instance)); - } - } - - static final LuaValue LENGTH = valueOf("length"); - - static final LuaTable array_metatable; - static { - array_metatable = new LuaTable(); - array_metatable.rawset(LuaValue.LEN, new LenFunction()); - } - - JavaArray(Object instance) { - super(instance); - setmetatable(array_metatable); - } - - public LuaValue get(LuaValue key) { - if ( key.equals(LENGTH) ) - return valueOf(Array.getLength(m_instance)); - if ( key.isint() ) { - int i = key.toint() - 1; - return i>=0 && i=0 && i - * Will respond to get() and set() by returning field values, or java methods. - *

    - * This class is not used directly. - * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)} - * when a Class is supplied. - * @see CoerceJavaToLua - * @see CoerceLuaToJava - */ -class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion { - - static final Map classes = Collections.synchronizedMap(new HashMap()); - - static final LuaValue NEW = valueOf("new"); - - Map fields; - Map methods; - Map innerclasses; - - static JavaClass forClass(Class c) { - JavaClass j = (JavaClass) classes.get(c); - if ( j == null ) - classes.put( c, j = new JavaClass(c) ); - return j; - } - - JavaClass(Class c) { - super(c); - this.jclass = this; - } - - public LuaValue coerce(Object javaValue) { - return this; - } - - Field getField(LuaValue key) { - if ( fields == null ) { - Map m = new HashMap(); - Field[] f = ((Class)m_instance).getFields(); - for ( int i=0; i - * May be called with arguments to return a JavaInstance - * created by calling the constructor. - *

    - * This class is not used directly. - * It is returned by calls to {@link JavaClass#new(LuaValue key)} - * when the value of key is "new". - * @see CoerceJavaToLua - * @see CoerceLuaToJava - */ -class JavaConstructor extends JavaMember { - - static final Map constructors = Collections.synchronizedMap(new HashMap()); - - static JavaConstructor forConstructor(Constructor c) { - JavaConstructor j = (JavaConstructor) constructors.get(c); - if ( j == null ) - constructors.put( c, j = new JavaConstructor(c) ); - return j; - } - - public static LuaValue forConstructors(JavaConstructor[] array) { - return new Overload(array); - } - - final Constructor constructor; - - private JavaConstructor(Constructor c) { - super( c.getParameterTypes(), c.getModifiers() ); - this.constructor = c; - } - - public Varargs invoke(Varargs args) { - Object[] a = convertArgs(args); - try { - return CoerceJavaToLua.coerce( constructor.newInstance(a) ); - } catch (InvocationTargetException e) { - throw new LuaError(e.getTargetException()); - } catch (Exception e) { - return LuaValue.error("coercion error "+e); - } - } - - /** - * LuaValue that represents an overloaded Java constructor. - *

    - * On invocation, will pick the best method from the list, and invoke it. - *

    - * This class is not used directly. - * It is returned by calls to calls to {@link JavaClass#get(LuaValue key)} - * when key is "new" and there is more than one public constructor. - */ - static class Overload extends VarArgFunction { - final JavaConstructor[] constructors; - public Overload(JavaConstructor[] c) { - this.constructors = c; - } - - public Varargs invoke(Varargs args) { - JavaConstructor best = null; - int score = CoerceLuaToJava.SCORE_UNCOERCIBLE; - for ( int i=0; i - * Will respond to get() and set() by returning field values or methods. - *

    - * This class is not used directly. - * It is returned by calls to {@link CoerceJavaToLua#coerce(Object)} - * when a subclass of Object is supplied. - * @see CoerceJavaToLua - * @see CoerceLuaToJava - */ -class JavaInstance extends LuaUserdata { - - JavaClass jclass; - - JavaInstance(Object instance) { - super(instance); - } - - public LuaValue get(LuaValue key) { - if ( jclass == null ) - jclass = JavaClass.forClass(m_instance.getClass()); - Field f = jclass.getField(key); - if ( f != null ) - try { - return CoerceJavaToLua.coerce(f.get(m_instance)); - } catch (Exception e) { - throw new LuaError(e); - } - LuaValue m = jclass.getMethod(key); - if ( m != null ) - return m; - Class c = jclass.getInnerClass(key); - if ( c != null ) - return JavaClass.forClass(c); - return super.get(key); - } - - public void set(LuaValue key, LuaValue value) { - if ( jclass == null ) - jclass = JavaClass.forClass(m_instance.getClass()); - Field f = jclass.getField(key); - if ( f != null ) - try { - f.set(m_instance, CoerceLuaToJava.coerce(value, f.getType())); - return; - } catch (Exception e) { - throw new LuaError(e); - } - super.set(key, value); - } - -} diff --git a/src/jse/org/luaj/vm2/lib/jse/JavaMember.java b/src/jse/org/luaj/vm2/lib/jse/JavaMember.java deleted file mode 100644 index e4e9b7ed..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/JavaMember.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import org.luaj.vm2.Varargs; -import org.luaj.vm2.lib.VarArgFunction; -import org.luaj.vm2.lib.jse.CoerceLuaToJava.Coercion; - -/** - * Java method or constructor. - *

    - * Primarily handles argument coercion for parameter lists including scoring of compatibility and - * java varargs handling. - *

    - * This class is not used directly. - * It is an abstract base class for {@link JavaConstructor} and {@link JavaMethod}. - * @see JavaConstructor - * @see JavaMethod - * @see CoerceJavaToLua - * @see CoerceLuaToJava - */ -abstract -class JavaMember extends VarArgFunction { - - static final int METHOD_MODIFIERS_VARARGS = 0x80; - - final Coercion[] fixedargs; - final Coercion varargs; - - protected JavaMember(Class[] params, int modifiers) { - boolean isvarargs = ((modifiers & METHOD_MODIFIERS_VARARGS) != 0); - fixedargs = new CoerceLuaToJava.Coercion[isvarargs? params.length-1: params.length]; - for ( int i=0; ifixedargs.length? CoerceLuaToJava.SCORE_WRONG_TYPE * (n-fixedargs.length): 0; - for ( int j=0; j - * Can be invoked via call(LuaValue...) and related methods. - *

    - * This class is not used directly. - * It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)} - * when a method is named. - * @see CoerceJavaToLua - * @see CoerceLuaToJava - */ -class JavaMethod extends JavaMember { - - static final Map methods = Collections.synchronizedMap(new HashMap()); - - static JavaMethod forMethod(Method m) { - JavaMethod j = (JavaMethod) methods.get(m); - if ( j == null ) - methods.put( m, j = new JavaMethod(m) ); - return j; - } - - static LuaFunction forMethods(JavaMethod[] m) { - return new Overload(m); - } - - final Method method; - - private JavaMethod(Method m) { - super( m.getParameterTypes(), m.getModifiers() ); - this.method = m; - try { - if (!m.isAccessible()) - m.setAccessible(true); - } catch (SecurityException s) { - } - } - - public LuaValue call() { - return error("method cannot be called without instance"); - } - - public LuaValue call(LuaValue arg) { - return invokeMethod(arg.checkuserdata(), LuaValue.NONE); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2) { - return invokeMethod(arg1.checkuserdata(), arg2); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { - return invokeMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3)); - } - - public Varargs invoke(Varargs args) { - return invokeMethod(args.checkuserdata(1), args.subargs(2)); - } - - LuaValue invokeMethod(Object instance, Varargs args) { - Object[] a = convertArgs(args); - try { - return CoerceJavaToLua.coerce( method.invoke(instance, a) ); - } catch (InvocationTargetException e) { - throw new LuaError(e.getTargetException()); - } catch (Exception e) { - return LuaValue.error("coercion error "+e); - } - } - - /** - * LuaValue that represents an overloaded Java method. - *

    - * On invocation, will pick the best method from the list, and invoke it. - *

    - * This class is not used directly. - * It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)} - * when an overloaded method is named. - */ - static class Overload extends LuaFunction { - - final JavaMethod[] methods; - - Overload(JavaMethod[] methods) { - this.methods = methods; - } - - public LuaValue call() { - return error("method cannot be called without instance"); - } - - public LuaValue call(LuaValue arg) { - return invokeBestMethod(arg.checkuserdata(), LuaValue.NONE); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2) { - return invokeBestMethod(arg1.checkuserdata(), arg2); - } - - public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { - return invokeBestMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3)); - } - - public Varargs invoke(Varargs args) { - return invokeBestMethod(args.checkuserdata(1), args.subargs(2)); - } - - private LuaValue invokeBestMethod(Object instance, Varargs args) { - JavaMethod best = null; - int score = CoerceLuaToJava.SCORE_UNCOERCIBLE; - for ( int i=0; i - * Since JME has no file system by default, {@link BaseLib} implements - * {@link ResourceFinder} using {@link Class#getResource(String)}. - * The {@link org.luaj.vm2.lib.jse.JseBaseLib} implements {@link Globals#finder} by scanning the current directory - * first, then falling back to {@link Class#getResource(String)} if that fails. - * Otherwise, the behavior is the same as that of {@link BaseLib}. - *

    - * Typically, this library is included as part of a call to - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * globals.get("print").call(LuaValue.valueOf("hello, world"));
    - * } 
    - *

    - * For special cases where the smallest possible footprint is desired, - * a minimal set of libraries could be loaded - * directly via {@link Globals#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.get("print").call(LuaValue.valueOf("hello, world"));
    - * } 
    - *

    However, other libraries such as PackageLib are not loaded in this case. - *

    - * This is a direct port of the corresponding library in C. - * @see Globals - * @see BaseLib - * @see ResourceFinder - * @see Globals#finder - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 Base Lib Reference - */ - -public class JseBaseLib extends org.luaj.vm2.lib.BaseLib { - - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - *

    Specifically, extend the library loading to set the default value for {@link Globals#STDIN} - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, which must be a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - super.call(modname, env); - env.checkglobals().STDIN = System.in; - return env; - } - - - /** - * Try to open a file in the current working directory, - * or fall back to base opener if not found. - * - * This implementation attempts to open the file using new File(filename). - * It falls back to the base implementation that looks it up as a resource - * in the class path if not found as a plain file. - * - * @see org.luaj.vm2.lib.BaseLib - * @see org.luaj.vm2.lib.ResourceFinder - * - * @param filename - * @return InputStream, or null if not found. - */ - public InputStream findResource(String filename) { - File f = new File(filename); - if ( ! f.exists() ) - return super.findResource(filename); - try { - return new BufferedInputStream(new FileInputStream(f)); - } catch ( IOException ioe ) { - return null; - } - } -} - diff --git a/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java b/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java deleted file mode 100644 index cfaf6f4a..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/JseIoLib.java +++ /dev/null @@ -1,343 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import java.io.BufferedInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.RandomAccessFile; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaError; -import org.luaj.vm2.LuaString; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.IoLib; -import org.luaj.vm2.lib.LibFunction; - -/** - * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io} - * library for the JSE platform. - *

    - * It uses RandomAccessFile to implement seek on files. - *

    - * Typically, this library is included as part of a call to - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
    - * } 
    - *

    - * For special cases where the smallest possible footprint is desired, - * a minimal set of libraries could be loaded - * directly via {@link Globals#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new JseIoLib());
    - * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
    - * } 
    - *

    However, other libraries such as MathLib are not loaded in this case. - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see IoLib - * @see org.luaj.vm2.lib.jme.JmeIoLib - * @see Lua 5.2 I/O Lib Reference - */ -public class JseIoLib extends IoLib { - - protected File wrapStdin() throws IOException { - return new StdinFile(); - } - - protected File wrapStdout() throws IOException { - return new StdoutFile(FTYPE_STDOUT); - } - - protected File wrapStderr() throws IOException { - return new StdoutFile(FTYPE_STDERR); - } - - protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { - RandomAccessFile f = new RandomAccessFile(filename,readMode? "r": "rw"); - if ( appendMode ) { - f.seek(f.length()); - } else { - if ( ! readMode ) - f.setLength(0); - } - return new FileImpl( f ); - } - - protected File openProgram(String prog, String mode) throws IOException { - final Process p = Runtime.getRuntime().exec(prog); - return "w".equals(mode)? - new FileImpl( p.getOutputStream() ): - new FileImpl( p.getInputStream() ); - } - - protected File tmpFile() throws IOException { - java.io.File f = java.io.File.createTempFile(".luaj","bin"); - f.deleteOnExit(); - return new FileImpl( new RandomAccessFile(f,"rw") ); - } - - private static void notimplemented() { - throw new LuaError("not implemented"); - } - - - private final class FileImpl extends File { - private final RandomAccessFile file; - private final InputStream is; - private final OutputStream os; - private boolean closed = false; - private boolean nobuffer = false; - private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) { - this.file = file; - this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null; - this.os = os; - } - private FileImpl( RandomAccessFile f ) { - this( f, null, null ); - } - private FileImpl( InputStream i ) { - this( null, i, null ); - } - private FileImpl( OutputStream o ) { - this( null, null, o ); - } - public String tojstring() { - return "file (" + (this.closed ? "closed" : String.valueOf(this.hashCode())) + ")"; - } - public boolean isstdfile() { - return file == null; - } - public void close() throws IOException { - closed = true; - if ( file != null ) { - file.close(); - } - } - public void flush() throws IOException { - if ( os != null ) - os.flush(); - } - public void write(LuaString s) throws IOException { - if ( os != null ) - os.write( s.m_bytes, s.m_offset, s.m_length ); - else if ( file != null ) - file.write( s.m_bytes, s.m_offset, s.m_length ); - else - notimplemented(); - if ( nobuffer ) - flush(); - } - public boolean isclosed() { - return closed; - } - public int seek(String option, int pos) throws IOException { - if ( file != null ) { - if ( "set".equals(option) ) { - file.seek(pos); - } else if ( "end".equals(option) ) { - file.seek(file.length()+pos); - } else { - file.seek(file.getFilePointer()+pos); - } - return (int) file.getFilePointer(); - } - notimplemented(); - return 0; - } - public void setvbuf(String mode, int size) { - nobuffer = "no".equals(mode); - } - - // get length remaining to read - public int remaining() throws IOException { - return file!=null? (int) (file.length()-file.getFilePointer()): -1; - } - - // peek ahead one character - public int peek() throws IOException { - if ( is != null ) { - is.mark(1); - int c = is.read(); - is.reset(); - return c; - } else if ( file != null ) { - long fp = file.getFilePointer(); - int c = file.read(); - file.seek(fp); - return c; - } - notimplemented(); - return 0; - } - - // return char if read, -1 if eof, throw IOException on other exception - public int read() throws IOException { - if ( is != null ) - return is.read(); - else if ( file != null ) { - return file.read(); - } - notimplemented(); - return 0; - } - - // return number of bytes read if positive, -1 if eof, throws IOException - public int read(byte[] bytes, int offset, int length) throws IOException { - if (file!=null) { - return file.read(bytes, offset, length); - } else if (is!=null) { - return is.read(bytes, offset, length); - } else { - notimplemented(); - } - return length; - } - } - - private final class StdoutFile extends File { - private final int file_type; - - private StdoutFile(int file_type) { - this.file_type = file_type; - } - - public String tojstring() { - return "file ("+this.hashCode()+")"; - } - - private final PrintStream getPrintStream() { - return file_type == FTYPE_STDERR? - globals.STDERR: - globals.STDOUT; - } - - public void write(LuaString string) throws IOException { - getPrintStream().write(string.m_bytes, string.m_offset, string.m_length); - } - - public void flush() throws IOException { - getPrintStream().flush(); - } - - public boolean isstdfile() { - return true; - } - - public void close() throws IOException { - // do not close std files. - } - - public boolean isclosed() { - return false; - } - - public int seek(String option, int bytecount) throws IOException { - return 0; - } - - public void setvbuf(String mode, int size) { - } - - public int remaining() throws IOException { - return 0; - } - - public int peek() throws IOException, EOFException { - return 0; - } - - public int read() throws IOException, EOFException { - return 0; - } - - public int read(byte[] bytes, int offset, int length) - throws IOException { - return 0; - } - } - - private final class StdinFile extends File { - private StdinFile() { - } - - public String tojstring() { - return "file ("+this.hashCode()+")"; - } - - public void write(LuaString string) throws IOException { - } - - public void flush() throws IOException { - } - - public boolean isstdfile() { - return true; - } - - public void close() throws IOException { - // do not close std files. - } - - public boolean isclosed() { - return false; - } - - public int seek(String option, int bytecount) throws IOException { - return 0; - } - - public void setvbuf(String mode, int size) { - } - - public int remaining() throws IOException { - return -1; - } - - public int peek() throws IOException, EOFException { - globals.STDIN.mark(1); - int c = globals.STDIN.read(); - globals.STDIN.reset(); - return c; - } - - public int read() throws IOException, EOFException { - return globals.STDIN.read(); - } - - public int read(byte[] bytes, int offset, int length) - throws IOException { - return globals.STDIN.read(bytes, offset, length); - } - } -} diff --git a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java b/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java deleted file mode 100644 index 87f133a1..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/JseMathLib.java +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009-2011 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.LibFunction; -import org.luaj.vm2.lib.TwoArgFunction; - -/** - * Subclass of {@link LibFunction} which implements the lua standard {@code math} - * library. - *

    - * It contains all lua math functions, including those not available on the JME platform. - * See {@link org.luaj.vm2.lib.MathLib} for the exception list. - *

    - * Typically, this library is included as part of a call to - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
    - * } 
    - *

    - * For special cases where the smallest possible footprint is desired, - * a minimal set of libraries could be loaded - * directly via {@link Globals#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new JseMathLib());
    - * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
    - * } 
    - *

    However, other libraries such as CoroutineLib are not loaded in this case. - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see org.luaj.vm2.lib.jse.JseMathLib - * @see Lua 5.2 Math Lib Reference - */ -public class JseMathLib extends org.luaj.vm2.lib.MathLib { - - public JseMathLib() {} - - - /** Perform one-time initialization on the library by creating a table - * containing the library functions, adding that table to the supplied environment, - * adding the table to package.loaded, and returning table as the return value. - *

    Specifically, adds all library functions that can be implemented directly - * in JSE but not JME: acos, asin, atan, atan2, cosh, exp, log, pow, sinh, and tanh. - * @param modname the module name supplied if this is loaded via 'require'. - * @param env the environment to load into, which must be a Globals instance. - */ - public LuaValue call(LuaValue modname, LuaValue env) { - super.call(modname, env); - LuaValue math = env.get("math"); - math.set("acos", new acos()); - math.set("asin", new asin()); - LuaValue atan = new atan2(); - math.set("atan", atan); - math.set("atan2", atan); - math.set("cosh", new cosh()); - math.set("exp", new exp()); - math.set("log", new log()); - math.set("pow", new pow()); - math.set("sinh", new sinh()); - math.set("tanh", new tanh()); - return math; - } - - static final class acos extends UnaryOp { protected double call(double d) { return Math.acos(d); } } - static final class asin extends UnaryOp { protected double call(double d) { return Math.asin(d); } } - static final class atan2 extends TwoArgFunction { - public LuaValue call(LuaValue x, LuaValue y) { - return valueOf(Math.atan2(x.checkdouble(), y.optdouble(1))); - } - } - static final class cosh extends UnaryOp { protected double call(double d) { return Math.cosh(d); } } - static final class exp extends UnaryOp { protected double call(double d) { return Math.exp(d); } } - static final class log extends TwoArgFunction { - public LuaValue call(LuaValue x, LuaValue base) { - double nat = Math.log(x.checkdouble()); - double b = base.optdouble(Math.E); - if (b != Math.E) nat /= Math.log(b); - return valueOf(nat); - } - } - static final class pow extends BinaryOp { protected double call(double x, double y) { return Math.pow(x, y); } } - static final class sinh extends UnaryOp { protected double call(double d) { return Math.sinh(d); } } - static final class tanh extends UnaryOp { protected double call(double d) { return Math.tanh(d); } } - - /** Faster, better version of pow() used by arithmetic operator ^ */ - public double dpow_lib(double a, double b) { - return Math.pow(a, b); - } - - -} - diff --git a/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java b/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java deleted file mode 100644 index af63c8af..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/JseOsLib.java +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import java.io.File; -import java.io.IOException; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; -import org.luaj.vm2.lib.LibFunction; -import org.luaj.vm2.lib.OsLib; - -/** - * Subclass of {@link LibFunction} which implements the standard lua {@code os} library. - *

    - * This contains more complete implementations of the following functions - * using features that are specific to JSE: - *

    - *

    - * Because the nature of the {@code os} library is to encapsulate - * os-specific features, the behavior of these functions varies considerably - * from their counterparts in the C platform. - *

    - * Typically, this library is included as part of a call to - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("os").get("time").call() );
    - * } 
    - *

    - * For special cases where the smallest possible footprint is desired, - * a minimal set of libraries could be loaded - * directly via {@link Globals#load(LuaValue)} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new JseOsLib());
    - * System.out.println( globals.get("os").get("time").call() );
    - * } 
    - *

    However, other libraries such as MathLib are not loaded in this case. - *

    - * @see LibFunction - * @see OsLib - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see Lua 5.2 OS Lib Reference - */ -public class JseOsLib extends org.luaj.vm2.lib.OsLib { - - /** return code indicating the execute() threw an I/O exception */ - public static final int EXEC_IOEXCEPTION = 1; - - /** return code indicating the execute() was interrupted */ - public static final int EXEC_INTERRUPTED = -2; - - /** return code indicating the execute() threw an unknown exception */ - public static final int EXEC_ERROR = -3; - - /** public constructor */ - public JseOsLib() { - } - - protected String getenv(String varname) { - String s = System.getenv(varname); - return s != null? s : System.getProperty(varname); - } - - protected Varargs execute(String command) { - int exitValue; - try { - exitValue = new JseProcess(command, null, globals.STDOUT, globals.STDERR).waitFor(); - } catch (IOException ioe) { - exitValue = EXEC_IOEXCEPTION; - } catch (InterruptedException e) { - exitValue = EXEC_INTERRUPTED; - } catch (Throwable t) { - exitValue = EXEC_ERROR; - } - if (exitValue == 0) - return varargsOf(TRUE, valueOf("exit"), ZERO); - return varargsOf(NIL, valueOf("signal"), valueOf(exitValue)); - } - - protected void remove(String filename) throws IOException { - File f = new File(filename); - if ( ! f.exists() ) - throw new IOException("No such file or directory"); - if ( ! f.delete() ) - throw new IOException("Failed to delete"); - } - - protected void rename(String oldname, String newname) throws IOException { - File f = new File(oldname); - if ( ! f.exists() ) - throw new IOException("No such file or directory"); - if ( ! f.renameTo(new File(newname)) ) - throw new IOException("Failed to rename"); - } - - protected String tmpname() { - try { - java.io.File f = java.io.File.createTempFile(TMP_PREFIX ,TMP_SUFFIX); - return f.getAbsolutePath(); - } catch ( IOException ioe ) { - return super.tmpname(); - } - } - -} diff --git a/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java b/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java deleted file mode 100644 index 00575aaf..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/JsePlatform.java +++ /dev/null @@ -1,143 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009-2011 Luaj.org. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - ******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LoadState; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; -import org.luaj.vm2.compiler.LuaC; -import org.luaj.vm2.lib.Bit32Lib; -import org.luaj.vm2.lib.CoroutineLib; -import org.luaj.vm2.lib.DebugLib; -import org.luaj.vm2.lib.PackageLib; -import org.luaj.vm2.lib.ResourceFinder; -import org.luaj.vm2.lib.StringLib; -import org.luaj.vm2.lib.TableLib; - -/** The {@link org.luaj.vm2.lib.jse.JsePlatform} class is a convenience class to standardize - * how globals tables are initialized for the JSE platform. - *

    - * It is used to allocate either a set of standard globals using - * {@link #standardGlobals()} or debug globals using {@link #debugGlobals()} - *

    - * A simple example of initializing globals and using them from Java is: - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * globals.get("print").call(LuaValue.valueOf("hello, world"));
    - * } 
    - *

    - * Once globals are created, a simple way to load and run a script is: - *

     {@code
    - * globals.load( new FileInputStream("main.lua"), "main.lua" ).call();
    - * } 
    - *

    - * although {@code require} could also be used: - *

     {@code
    - * globals.get("require").call(LuaValue.valueOf("main"));
    - * } 
    - * For this to succeed, the file "main.lua" must be in the current directory or a resource. - * See {@link org.luaj.vm2.lib.jse.JseBaseLib} for details on finding scripts using {@link ResourceFinder}. - *

    - * The standard globals will contain all standard libraries plus {@code luajava}: - *

    - * In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form. - *

    - * The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}. - *

    - * The class ensures that initialization is done in the correct order. - * - * @see Globals - * @see org.luaj.vm2.lib.jme.JmePlatform - */ -public class JsePlatform { - - /** - * Create a standard set of globals for JSE including all the libraries. - * - * @return Table of globals initialized with the standard JSE libraries - * @see #debugGlobals() - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - */ - public static Globals standardGlobals() { - Globals globals = new Globals(); - globals.load(new JseBaseLib()); - globals.load(new PackageLib()); - globals.load(new Bit32Lib()); - globals.load(new TableLib()); - globals.load(new JseStringLib()); - globals.load(new CoroutineLib()); - globals.load(new JseMathLib()); - globals.load(new JseIoLib()); - globals.load(new JseOsLib()); - globals.load(new LuajavaLib()); - LoadState.install(globals); - LuaC.install(globals); - return globals; - } - - /** Create standard globals including the {@link DebugLib} library. - * - * @return Table of globals initialized with the standard JSE and debug libraries - * @see #standardGlobals() - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see DebugLib - */ - public static Globals debugGlobals() { - Globals globals = standardGlobals(); - globals.load(new DebugLib()); - return globals; - } - - - /** Simple wrapper for invoking a lua function with command line arguments. - * The supplied function is first given a new Globals object as its environment - * then the program is run with arguments. - * @return {@link Varargs} containing any values returned by mainChunk. - */ - public static Varargs luaMain(LuaValue mainChunk, String[] args) { - Globals g = standardGlobals(); - int n = args.length; - LuaValue[] vargs = new LuaValue[args.length]; - for (int i = 0; i < n; ++i) - vargs[i] = LuaValue.valueOf(args[i]); - LuaValue arg = LuaValue.listOf(vargs); - arg.set("n", n); - g.set("arg", arg); - mainChunk.initupvalue1(g); - return mainChunk.invoke(LuaValue.varargsOf(vargs)); - } -} diff --git a/src/jse/org/luaj/vm2/lib/jse/JseProcess.java b/src/jse/org/luaj/vm2/lib/jse/JseProcess.java deleted file mode 100644 index 3fcd79f1..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/JseProcess.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2012 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** Analog of Process that pipes input and output to client-specified streams. - */ -public class JseProcess { - - final Process process; - final Thread input,output,error; - - /** Construct a process around a command, with specified streams to redirect input and output to. - * - * @param cmd The command to execute, including arguments, if any - * @param stdin Optional InputStream to read from as process input, or null if input is not needed. - * @param stdout Optional OutputStream to copy process output to, or null if output is ignored. - * @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored. - * @throws IOException If the system process could not be created. - * @see Process - */ - public JseProcess(String[] cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException { - this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr); - } - - /** Construct a process around a command, with specified streams to redirect input and output to. - * - * @param cmd The command to execute, including arguments, if any - * @param stdin Optional InputStream to read from as process input, or null if input is not needed. - * @param stdout Optional OutputStream to copy process output to, or null if output is ignored. - * @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored. - * @throws IOException If the system process could not be created. - * @see Process - */ - public JseProcess(String cmd, InputStream stdin, OutputStream stdout, OutputStream stderr) throws IOException { - this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr); - } - - private JseProcess(Process process, InputStream stdin, OutputStream stdout, OutputStream stderr) { - this.process = process; - input = stdin == null? null: copyBytes(stdin, process.getOutputStream(), null, process.getOutputStream()); - output = stdout == null? null: copyBytes(process.getInputStream(), stdout, process.getInputStream(), null); - error = stderr == null? null: copyBytes(process.getErrorStream(), stderr, process.getErrorStream(), null); - } - - /** Get the exit value of the process. */ - public int exitValue() { - return process.exitValue(); - } - - /** Wait for the process to complete, and all pending output to finish. - * @return The exit status. - * @throws InterruptedException - */ - public int waitFor() throws InterruptedException { - int r = process.waitFor(); - if (input != null) - input.join(); - if (output != null) - output.join(); - if (error != null) - error.join(); - process.destroy(); - return r; - } - - /** Create a thread to copy bytes from input to output. */ - private Thread copyBytes(final InputStream input, - final OutputStream output, final InputStream ownedInput, - final OutputStream ownedOutput) { - Thread t = (new CopyThread(output, ownedOutput, ownedInput, input)); - t.start(); - return t; - } - - private static final class CopyThread extends Thread { - private final OutputStream output; - private final OutputStream ownedOutput; - private final InputStream ownedInput; - private final InputStream input; - - private CopyThread(OutputStream output, OutputStream ownedOutput, - InputStream ownedInput, InputStream input) { - this.output = output; - this.ownedOutput = ownedOutput; - this.ownedInput = ownedInput; - this.input = input; - } - - public void run() { - try { - byte[] buf = new byte[1024]; - int r; - try { - while ((r = input.read(buf)) >= 0) { - output.write(buf, 0, r); - } - } finally { - if (ownedInput != null) - ownedInput.close(); - if (ownedOutput != null) - ownedOutput.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } - -} diff --git a/src/jse/org/luaj/vm2/lib/jse/JseStringLib.java b/src/jse/org/luaj/vm2/lib/jse/JseStringLib.java deleted file mode 100644 index 41177787..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/JseStringLib.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - -public class JseStringLib extends org.luaj.vm2.lib.StringLib { - - /** public constructor */ - public JseStringLib() { - } - - protected String format(String src, double x) { - String out; - try { - out = String.format(src, new Object[] {Double.valueOf(x)}); - } catch (Throwable e) { - out = super.format(src, x); - } - return out; - } -} diff --git a/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java b/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java deleted file mode 100644 index 35f1f850..00000000 --- a/src/jse/org/luaj/vm2/lib/jse/LuajavaLib.java +++ /dev/null @@ -1,214 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Luaj.org. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -******************************************************************************/ -package org.luaj.vm2.lib.jse; - - -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaError; -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.Varargs; -import org.luaj.vm2.compiler.LuaC; -import org.luaj.vm2.lib.LibFunction; -import org.luaj.vm2.lib.VarArgFunction; - -/** - * Subclass of {@link LibFunction} which implements the features of the luajava package. - *

    - * Luajava is an approach to mixing lua and java using simple functions that bind - * java classes and methods to lua dynamically. The API is documented on the - * luajava documentation pages. - * - *

    - * Typically, this library is included as part of a call to - * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} - *

     {@code
    - * Globals globals = JsePlatform.standardGlobals();
    - * System.out.println( globals.get("luajava").get("bindClass").call( LuaValue.valueOf("java.lang.System") ).invokeMethod("currentTimeMillis") );
    - * } 
    - *

    - * To instantiate and use it directly, - * link it into your globals table via {@link Globals#load} using code such as: - *

     {@code
    - * Globals globals = new Globals();
    - * globals.load(new JseBaseLib());
    - * globals.load(new PackageLib());
    - * globals.load(new LuajavaLib());
    - * globals.load(
    - *      "sys = luajava.bindClass('java.lang.System')\n"+
    - *      "print ( sys:currentTimeMillis() )\n", "main.lua" ).call();
    - * } 
    - *

    - * - * The {@code luajava} library is available - * on all JSE platforms via the call to {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} - * and the luajava api's are simply invoked from lua. - * Because it makes extensive use of Java's reflection API, it is not available - * on JME, but can be used in Android applications. - *

    - * This has been implemented to match as closely as possible the behavior in the corresponding library in C. - * - * @see LibFunction - * @see org.luaj.vm2.lib.jse.JsePlatform - * @see org.luaj.vm2.lib.jme.JmePlatform - * @see LuaC - * @see CoerceJavaToLua - * @see CoerceLuaToJava - * @see http://www.keplerproject.org/luajava/manual.html#luareference - */ -public class LuajavaLib extends VarArgFunction { - - static final int INIT = 0; - static final int BINDCLASS = 1; - static final int NEWINSTANCE = 2; - static final int NEW = 3; - static final int CREATEPROXY = 4; - static final int LOADLIB = 5; - - static final String[] NAMES = { - "bindClass", - "newInstance", - "new", - "createProxy", - "loadLib", - }; - - static final int METHOD_MODIFIERS_VARARGS = 0x80; - - public LuajavaLib() { - } - - public Varargs invoke(Varargs args) { - try { - switch ( opcode ) { - case INIT: { - // LuaValue modname = args.arg1(); - LuaValue env = args.arg(2); - LuaTable t = new LuaTable(); - bind( t, this.getClass(), NAMES, BINDCLASS ); - env.set("luajava", t); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("luajava", t); - return t; - } - case BINDCLASS: { - final Class clazz = classForName(args.checkjstring(1)); - return JavaClass.forClass(clazz); - } - case NEWINSTANCE: - case NEW: { - // get constructor - final LuaValue c = args.checkvalue(1); - final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class)); - final Varargs consargs = args.subargs(2); - return JavaClass.forClass(clazz).getConstructor().invoke(consargs); - } - - case CREATEPROXY: { - final int niface = args.narg()-1; - if ( niface <= 0 ) - throw new LuaError("no interfaces"); - final LuaValue lobj = args.checktable(niface+1); - - // get the interfaces - final Class[] ifaces = new Class[niface]; - for ( int i=0; i=0 ); - } - - public void testLuaErrorCause() { - String script = "luajava.bindClass( \""+SomeClass.class.getName()+"\"):someMethod()"; - LuaValue chunk = globals.get("load").call(LuaValue.valueOf(script)); - try { - chunk.invoke(LuaValue.NONE); - fail( "call should not have succeeded" ); - } catch ( LuaError lee ) { - Throwable c = lee.getCause(); - assertEquals( SomeException.class, c.getClass() ); - } - } - - public interface VarArgsInterface { - public String varargsMethod( String a, String ... v ); - public String arrayargsMethod( String a, String[] v ); - } - - public void testVarArgsProxy() { - String script = "return luajava.createProxy( \""+VarArgsInterface.class.getName()+"\", \n"+ - "{\n" + - " varargsMethod = function(a,...)\n" + - " return table.concat({a,...},'-')\n" + - " end,\n" + - " arrayargsMethod = function(a,array)\n" + - " return tostring(a)..(array and \n" + - " ('-'..tostring(array.length)\n" + - " ..'-'..tostring(array[1])\n" + - " ..'-'..tostring(array[2])\n" + - " ) or '-nil')\n" + - " end,\n" + - "} )\n"; - Varargs chunk = globals.get("load").call(LuaValue.valueOf(script)); - if ( ! chunk.arg1().toboolean() ) - fail( chunk.arg(2).toString() ); - LuaValue result = chunk.arg1().call(); - Object u = result.touserdata(); - VarArgsInterface v = (VarArgsInterface) u; - assertEquals( "foo", v.varargsMethod("foo") ); - assertEquals( "foo-bar", v.varargsMethod("foo", "bar") ); - assertEquals( "foo-bar-etc", v.varargsMethod("foo", "bar", "etc") ); - assertEquals( "foo-0-nil-nil", v.arrayargsMethod("foo", new String[0]) ); - assertEquals( "foo-1-bar-nil", v.arrayargsMethod("foo", new String[] {"bar"}) ); - assertEquals( "foo-2-bar-etc", v.arrayargsMethod("foo", new String[] {"bar","etc"}) ); - assertEquals( "foo-3-bar-etc", v.arrayargsMethod("foo", new String[] {"bar","etc","etc"}) ); - assertEquals( "foo-nil", v.arrayargsMethod("foo", null) ); - } - - public void testBigNum() { - String script = - "bigNumA = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n" + - "bigNumB = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n" + - "bigNumC = bigNumA:multiply(bigNumB);\n" + - //"print(bigNumA:toString())\n" + - //"print(bigNumB:toString())\n" + - //"print(bigNumC:toString())\n" + - "return bigNumA:toString(), bigNumB:toString(), bigNumC:toString()"; - Varargs chunk = globals.get("load").call(LuaValue.valueOf(script)); - if ( ! chunk.arg1().toboolean() ) - fail( chunk.arg(2).toString() ); - Varargs results = chunk.arg1().invoke(); - int nresults = results.narg(); - String sa = results.tojstring(1); - String sb = results.tojstring(2); - String sc = results.tojstring(3); - assertEquals( 3, nresults ); - assertEquals( "12345678901234567890", sa ); - assertEquals( "12345678901234567890", sb ); - assertEquals( "152415787532388367501905199875019052100", sc ); - } - - public interface IA {} - public interface IB extends IA {} - public interface IC extends IB {} - - public static class A implements IA { - } - public static class B extends A implements IB { - public String set( Object x ) { return "set(Object) "; } - public String set( String x ) { return "set(String) "+x; } - public String set( A x ) { return "set(A) "; } - public String set( B x ) { return "set(B) "; } - public String set( C x ) { return "set(C) "; } - public String set( byte x ) { return "set(byte) "+x; } - public String set( char x ) { return "set(char) "+(int)x; } - public String set( short x ) { return "set(short) "+x; } - public String set( int x ) { return "set(int) "+x; } - public String set( long x ) { return "set(long) "+x; } - public String set( float x ) { return "set(float) "+x; } - public String set( double x ) { return "set(double) "+x; } - - public String setr( double x ) { return "setr(double) "+x; } - public String setr( float x ) { return "setr(float) "+x; } - public String setr( long x ) { return "setr(long) "+x; } - public String setr( int x ) { return "setr(int) "+x; } - public String setr( short x ) { return "setr(short) "+x; } - public String setr( char x ) { return "setr(char) "+(int)x; } - public String setr( byte x ) { return "setr(byte) "+x; } - public String setr( C x ) { return "setr(C) "; } - public String setr( B x ) { return "setr(B) "; } - public String setr( A x ) { return "setr(A) "; } - public String setr( String x ) { return "setr(String) "+x; } - public String setr( Object x ) { return "setr(Object) "; } - - public Object getObject() { return new Object(); } - public String getString() { return "abc"; } - public byte[] getbytearray() { return new byte[] { 1, 2, 3 }; } - public A getA() { return new A(); } - public B getB() { return new B(); } - public C getC() { return new C(); } - public byte getbyte() { return 1; } - public char getchar() { return 65000; } - public short getshort() { return -32000; } - public int getint() { return 100000; } - public long getlong() { return 50000000000L; } - public float getfloat() { return 6.5f; } - public double getdouble() { return Math.PI; } - } - public static class C extends B implements IC { - } - public static class D extends C implements IA { - } - - public void testOverloadedJavaMethodObject() { doOverloadedMethodTest( "Object", "" ); } - public void testOverloadedJavaMethodString() { doOverloadedMethodTest( "String", "abc" ); } - public void testOverloadedJavaMethodA() { doOverloadedMethodTest( "A", "" ); } - public void testOverloadedJavaMethodB() { doOverloadedMethodTest( "B", "" ); } - public void testOverloadedJavaMethodC() { doOverloadedMethodTest( "C", "" ); } - public void testOverloadedJavaMethodByte() { doOverloadedMethodTest( "byte", "1" ); } - public void testOverloadedJavaMethodChar() { doOverloadedMethodTest( "char", "65000" ); } - public void testOverloadedJavaMethodShort() { doOverloadedMethodTest( "short", "-32000" ); } - public void testOverloadedJavaMethodInt() { doOverloadedMethodTest( "int", "100000" ); } - public void testOverloadedJavaMethodLong() { doOverloadedMethodTest( "long", "50000000000" ); } - public void testOverloadedJavaMethodFloat() { doOverloadedMethodTest( "float", "6.5" ); } - public void testOverloadedJavaMethodDouble() { doOverloadedMethodTest( "double", "3.141592653589793" ); } - - private void doOverloadedMethodTest( String typename, String value ) { - String script = - "local a = luajava.newInstance('"+B.class.getName()+"');\n" + - "local b = a:set(a:get"+typename+"())\n" + - "local c = a:setr(a:get"+typename+"())\n" + - "return b,c"; - Varargs chunk = globals.get("load").call(LuaValue.valueOf(script)); - if ( ! chunk.arg1().toboolean() ) - fail( chunk.arg(2).toString() ); - Varargs results = chunk.arg1().invoke(); - int nresults = results.narg(); - assertEquals( 2, nresults ); - LuaValue b = results.arg(1); - LuaValue c = results.arg(2); - String sb = b.tojstring(); - String sc = c.tojstring(); - assertEquals( "set("+typename+") "+value, sb ); - assertEquals( "setr("+typename+") "+value, sc ); - } - - public void testClassInheritanceLevels() { - assertEquals( 0, CoerceLuaToJava.inheritanceLevels(Object.class, Object.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, String.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(Object.class, A.class) ); - assertEquals( 2, CoerceLuaToJava.inheritanceLevels(Object.class, B.class) ); - assertEquals( 3, CoerceLuaToJava.inheritanceLevels(Object.class, C.class) ); - - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, Object.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, String.class) ); - assertEquals( 0, CoerceLuaToJava.inheritanceLevels(A.class, A.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(A.class, B.class) ); - assertEquals( 2, CoerceLuaToJava.inheritanceLevels(A.class, C.class) ); - - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, Object.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, String.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, A.class) ); - assertEquals( 0, CoerceLuaToJava.inheritanceLevels(B.class, B.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(B.class, C.class) ); - - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, Object.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, String.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, A.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, B.class) ); - assertEquals( 0, CoerceLuaToJava.inheritanceLevels(C.class, C.class) ); - } - - public void testInterfaceInheritanceLevels() { - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, A.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IB.class, B.class) ); - assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IA.class, B.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IC.class, C.class) ); - assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IB.class, C.class) ); - assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IA.class, C.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, D.class) ); - assertEquals( 2, CoerceLuaToJava.inheritanceLevels(IC.class, D.class) ); - assertEquals( 3, CoerceLuaToJava.inheritanceLevels(IB.class, D.class) ); - - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, A.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, A.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, B.class) ); - assertEquals( CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, IA.class) ); - assertEquals( 1, CoerceLuaToJava.inheritanceLevels(IA.class, IB.class) ); - } - - public void testCoerceJavaToLuaLuaValue() { - assertSame(LuaValue.NIL, CoerceJavaToLua.coerce(LuaValue.NIL)); - assertSame(LuaValue.ZERO, CoerceJavaToLua.coerce(LuaValue.ZERO)); - assertSame(LuaValue.ONE, CoerceJavaToLua.coerce(LuaValue.ONE)); - assertSame(LuaValue.INDEX, CoerceJavaToLua.coerce(LuaValue.INDEX)); - LuaTable table = LuaValue.tableOf(); - assertSame(table, CoerceJavaToLua.coerce(table)); - } - - public void testCoerceJavaToLuaByeArray() { - byte[] bytes = "abcd".getBytes(); - LuaValue value = CoerceJavaToLua.coerce(bytes); - assertEquals(LuaString.class, value.getClass()); - assertEquals(LuaValue.valueOf("abcd"), value); - } -} - diff --git a/test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java b/test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java deleted file mode 100644 index 3a86a8e6..00000000 --- a/test/junit/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.luaj.vm2.lib.jse; - -import junit.framework.TestCase; - -import org.luaj.vm2.Globals; -import org.luaj.vm2.LuaValue; - -public class LuajavaAccessibleMembersTest extends TestCase { - - private Globals globals; - - protected void setUp() throws Exception { - super.setUp(); - globals = JsePlatform.standardGlobals(); - } - - private String invokeScript(String script) { - try { - LuaValue c = globals.load(script, "script"); - return c.call().tojstring(); - } catch ( Exception e ) { - fail("exception: "+e ); - return "failed"; - } - } - - public void testAccessFromPrivateClassImplementedMethod() { - assertEquals("privateImpl-aaa-interface_method(bar)", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "a = b:create_PrivateImpl('aaa');" + - "return a:interface_method('bar');")); - } - - public void testAccessFromPrivateClassPublicMethod() { - assertEquals("privateImpl-aaa-public_method", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "a = b:create_PrivateImpl('aaa');" + - "return a:public_method();")); - } - - public void testAccessFromPrivateClassGetPublicField() { - assertEquals("aaa", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "a = b:create_PrivateImpl('aaa');" + - "return a.public_field;")); - } - - public void testAccessFromPrivateClassSetPublicField() { - assertEquals("foo", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "a = b:create_PrivateImpl('aaa');" + - "a.public_field = 'foo';" + - "return a.public_field;")); - } - - public void testAccessFromPrivateClassPublicConstructor() { - assertEquals("privateImpl-constructor", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "c = b:get_PrivateImplClass();" + - "return luajava.new(c);")); - } - - public void testAccessPublicEnum() { - assertEquals("class org.luaj.vm2.lib.jse.TestClass$SomeEnum", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "return b.SomeEnum")); - } -} diff --git a/test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java b/test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java deleted file mode 100644 index 496adffe..00000000 --- a/test/junit/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java +++ /dev/null @@ -1,238 +0,0 @@ -package org.luaj.vm2.lib.jse; - -import junit.framework.TestCase; - -import org.luaj.vm2.LuaError; -import org.luaj.vm2.LuaValue; - -public class LuajavaClassMembersTest extends TestCase { - public static class A { - protected A() {} - } - public static class B extends A { - public byte m_byte_field; - public int m_int_field; - public double m_double_field; - public String m_string_field; - - protected B() {} - public B(int i) { m_int_field = i; } - - public String setString( String x ) { return "setString(String) "+x; } - public String getString() { return "abc"; } - public int getint() { return 100000; } - - public String uniq() { return "uniq()"; } - public String uniqs(String s) { return "uniqs(string:"+s+")"; } - public String uniqi(int i) { return "uniqi(int:"+i+")"; } - public String uniqsi(String s, int i) { return "uniqsi(string:"+s+",int:"+i+")"; } - public String uniqis(int i, String s) { return "uniqis(int:"+i+",string:"+s+")"; } - - public String pick() { return "pick()"; } - public String pick(String s) { return "pick(string:"+s+")"; } - public String pick(int i) { return "pick(int:"+i+")"; } - public String pick(String s, int i) { return "pick(string:"+s+",int:"+i+")"; } - public String pick(int i, String s) { return "pick(int:"+i+",string:"+s+")"; } - - public static String staticpick() { return "static-pick()"; } - public static String staticpick(String s) { return "static-pick(string:"+s+")"; } - public static String staticpick(int i) { return "static-pick(int:"+i+")"; } - public static String staticpick(String s, int i) { return "static-pick(string:"+s+",int:"+i+")"; } - public static String staticpick(int i, String s) { return "static-pick(int:"+i+",string:"+s+")"; } - } - public static class C extends B { - public C() {} - public C(String s) { m_string_field = s; } - public C(int i) { m_int_field = i; } - public C(String s, int i) { m_string_field = s; m_int_field = i; } - public int getint() { return 200000; } - - public String pick(String s) { return "class-c-pick(string:"+s+")"; } - public String pick(int i) { return "class-c-pick(int:"+i+")"; } - public static class D { - public static String name() { return "name-of-D"; } - } - } - - static LuaValue ZERO = LuaValue.ZERO; - static LuaValue ONE = LuaValue.ONE; - static LuaValue PI = LuaValue.valueOf(Math.PI); - static LuaValue THREE = LuaValue.valueOf(3); - static LuaValue NUMS = LuaValue.valueOf(123); - static LuaValue ABC = LuaValue.valueOf("abc"); - static LuaValue SOMEA = CoerceJavaToLua.coerce(new A()); - static LuaValue SOMEB = CoerceJavaToLua.coerce(new B()); - static LuaValue SOMEC = CoerceJavaToLua.coerce(new C()); - - public void testSetByteField() { - B b = new B(); - JavaInstance i = new JavaInstance(b); - i.set("m_byte_field", ONE ); assertEquals( 1, b.m_byte_field ); assertEquals( ONE, i.get("m_byte_field") ); - i.set("m_byte_field", PI ); assertEquals( 3, b.m_byte_field ); assertEquals( THREE, i.get("m_byte_field") ); - i.set("m_byte_field", ABC ); assertEquals( 0, b.m_byte_field ); assertEquals( ZERO, i.get("m_byte_field") ); - } - public void testSetDoubleField() { - B b = new B(); - JavaInstance i = new JavaInstance(b); - i.set("m_double_field", ONE ); assertEquals( 1., b.m_double_field ); assertEquals( ONE, i.get("m_double_field") ); - i.set("m_double_field", PI ); assertEquals( Math.PI, b.m_double_field ); assertEquals( PI, i.get("m_double_field") ); - i.set("m_double_field", ABC ); assertEquals( 0., b.m_double_field ); assertEquals( ZERO, i.get("m_double_field") ); - } - public void testNoFactory() { - JavaClass c = JavaClass.forClass(A.class); - try { - c.call(); - fail( "did not throw lua error as expected" ); - } catch ( LuaError e ) { - } - } - public void testUniqueFactoryCoercible() { - JavaClass c = JavaClass.forClass(B.class); - assertEquals( JavaClass.class, c.getClass() ); - LuaValue constr = c.get("new"); - assertEquals( JavaConstructor.class, constr.getClass() ); - LuaValue v = constr.call(NUMS); - Object b = v.touserdata(); - assertEquals( B.class, b.getClass() ); - assertEquals( 123, ((B)b).m_int_field ); - Object b0 = constr.call().touserdata(); - assertEquals( B.class, b0.getClass() ); - assertEquals( 0, ((B)b0).m_int_field ); - } - public void testUniqueFactoryUncoercible() { - JavaClass f = JavaClass.forClass(B.class); - LuaValue constr = f.get("new"); - assertEquals( JavaConstructor.class, constr.getClass() ); - try { - LuaValue v = constr.call(LuaValue.userdataOf(new Object())); - Object b = v.touserdata(); - // fail( "did not throw lua error as expected" ); - assertEquals( 0, ((B)b).m_int_field ); - } catch ( LuaError e ) { - } - } - public void testOverloadedFactoryCoercible() { - JavaClass f = JavaClass.forClass(C.class); - LuaValue constr = f.get("new"); - assertEquals( JavaConstructor.Overload.class, constr.getClass() ); - Object c = constr.call().touserdata(); - Object ci = constr.call(LuaValue.valueOf(123)).touserdata(); - Object cs = constr.call(LuaValue.valueOf("abc")).touserdata(); - Object csi = constr.call( LuaValue.valueOf("def"), LuaValue.valueOf(456) ).touserdata(); - assertEquals( C.class, c.getClass() ); - assertEquals( C.class, ci.getClass() ); - assertEquals( C.class, cs.getClass() ); - assertEquals( C.class, csi.getClass() ); - assertEquals( null, ((C)c).m_string_field ); - assertEquals( 0, ((C)c).m_int_field ); - assertEquals( "abc", ((C)cs).m_string_field ); - assertEquals( 0, ((C)cs).m_int_field ); - assertEquals( null, ((C)ci).m_string_field ); - assertEquals( 123, ((C)ci).m_int_field ); - assertEquals( "def", ((C)csi).m_string_field ); - assertEquals( 456, ((C)csi).m_int_field ); - } - public void testOverloadedFactoryUncoercible() { - JavaClass f = JavaClass.forClass(C.class); - try { - Object c = f.call(LuaValue.userdataOf(new Object())); - // fail( "did not throw lua error as expected" ); - assertEquals( 0, ((C)c).m_int_field ); - assertEquals( null, ((C)c).m_string_field ); - } catch ( LuaError e ) { - } - } - - public void testNoAttribute() { - JavaClass f = JavaClass.forClass(A.class); - LuaValue v = f.get("bogus"); - assertEquals( v, LuaValue.NIL ); - try { - f.set("bogus",ONE); - fail( "did not throw lua error as expected" ); - } catch ( LuaError e ) {} - } - public void testFieldAttributeCoercible() { - JavaInstance i = new JavaInstance(new B()); - i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() ); - i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() ); - i = new JavaInstance(new C()); - i.set("m_int_field", ONE ); assertEquals( 1, i.get("m_int_field").toint() ); - i.set("m_int_field", THREE ); assertEquals( 3, i.get("m_int_field").toint() ); - } - public void testUniqueMethodAttributeCoercible() { - B b = new B(); - JavaInstance ib = new JavaInstance(b); - LuaValue b_getString = ib.get("getString"); - LuaValue b_getint = ib.get("getint"); - assertEquals( JavaMethod.class, b_getString.getClass() ); - assertEquals( JavaMethod.class, b_getint.getClass() ); - assertEquals( "abc", b_getString.call(SOMEB).tojstring() ); - assertEquals( 100000, b_getint.call(SOMEB).toint()); - assertEquals( "abc", b_getString.call(SOMEC).tojstring() ); - assertEquals( 200000, b_getint.call(SOMEC).toint()); - } - public void testUniqueMethodAttributeArgsCoercible() { - B b = new B(); - JavaInstance ib = new JavaInstance(b); - LuaValue uniq = ib.get("uniq"); - LuaValue uniqs = ib.get("uniqs"); - LuaValue uniqi = ib.get("uniqi"); - LuaValue uniqsi = ib.get("uniqsi"); - LuaValue uniqis = ib.get("uniqis"); - assertEquals( JavaMethod.class, uniq.getClass() ); - assertEquals( JavaMethod.class, uniqs.getClass() ); - assertEquals( JavaMethod.class, uniqi.getClass() ); - assertEquals( JavaMethod.class, uniqsi.getClass() ); - assertEquals( JavaMethod.class, uniqis.getClass() ); - assertEquals( "uniq()", uniq.call(SOMEB).tojstring() ); - assertEquals( "uniqs(string:abc)", uniqs.call(SOMEB,ABC).tojstring() ); - assertEquals( "uniqi(int:1)", uniqi.call(SOMEB,ONE).tojstring() ); - assertEquals( "uniqsi(string:abc,int:1)", uniqsi.call(SOMEB,ABC,ONE).tojstring() ); - assertEquals( "uniqis(int:1,string:abc)", uniqis.call(SOMEB,ONE,ABC).tojstring() ); - assertEquals( "uniqis(int:1,string:abc)", uniqis.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() ); - } - public void testOverloadedMethodAttributeCoercible() { - B b = new B(); - JavaInstance ib = new JavaInstance(b); - LuaValue p = ib.get("pick"); - assertEquals( "pick()", p.call(SOMEB).tojstring() ); - assertEquals( "pick(string:abc)", p.call(SOMEB,ABC).tojstring() ); - assertEquals( "pick(int:1)", p.call(SOMEB,ONE).tojstring() ); - assertEquals( "pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() ); - assertEquals( "pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() ); - assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() ); - } - public void testUnboundOverloadedMethodAttributeCoercible() { - B b = new B(); - JavaInstance ib = new JavaInstance(b); - LuaValue p = ib.get("pick"); - assertEquals( JavaMethod.Overload.class, p.getClass() ); - assertEquals( "pick()", p.call(SOMEC).tojstring() ); - assertEquals( "class-c-pick(string:abc)", p.call(SOMEC,ABC).tojstring() ); - assertEquals( "class-c-pick(int:1)", p.call(SOMEC,ONE).tojstring() ); - assertEquals( "pick(string:abc,int:1)", p.call(SOMEC,ABC,ONE).tojstring() ); - assertEquals( "pick(int:1,string:abc)", p.call(SOMEC,ONE,ABC).tojstring() ); - assertEquals( "pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEC,ONE,ABC,ONE})).arg1().tojstring() ); - } - public void testOverloadedStaticMethodAttributeCoercible() { - B b = new B(); - JavaInstance ib = new JavaInstance(b); - LuaValue p = ib.get("staticpick"); - assertEquals( "static-pick()", p.call(SOMEB).tojstring() ); - assertEquals( "static-pick(string:abc)", p.call(SOMEB,ABC).tojstring() ); - assertEquals( "static-pick(int:1)", p.call(SOMEB,ONE).tojstring() ); - assertEquals( "static-pick(string:abc,int:1)", p.call(SOMEB,ABC,ONE).tojstring() ); - assertEquals( "static-pick(int:1,string:abc)", p.call(SOMEB,ONE,ABC).tojstring() ); - assertEquals( "static-pick(int:1,string:abc)", p.invoke(LuaValue.varargsOf(new LuaValue[] {SOMEB,ONE,ABC,ONE})).arg1().tojstring() ); - } - public void testGetInnerClass() { - C c = new C(); - JavaInstance ic = new JavaInstance(c); - LuaValue d = ic.get("D"); - assertFalse(d.isnil()); - assertSame(d, JavaClass.forClass(C.D.class)); - LuaValue e = ic.get("E"); - assertTrue(e.isnil()); - } -} diff --git a/test/junit/org/luaj/vm2/lib/jse/OsLibTest.java b/test/junit/org/luaj/vm2/lib/jse/OsLibTest.java deleted file mode 100644 index 6c698acc..00000000 --- a/test/junit/org/luaj/vm2/lib/jse/OsLibTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.luaj.vm2.lib.jse; - -import org.luaj.vm2.LuaValue; -import org.luaj.vm2.lib.OsLib; -import org.luaj.vm2.lib.jme.JmePlatform; - -import junit.framework.TestCase; - -public class OsLibTest extends TestCase { - - LuaValue jme_lib; - LuaValue jse_lib; - double time; - - public void setUp() { - jse_lib = JsePlatform.standardGlobals().get("os");; - jme_lib = JmePlatform.standardGlobals().get("os");; - time = new java.util.Date(2001-1900, 7, 23, 14, 55, 02).getTime() / 1000.0; - } - - void t(String format, String expected) { - String actual = jme_lib.get("date").call(LuaValue.valueOf(format), LuaValue.valueOf(time)).tojstring(); - assertEquals(expected, actual); - } - - public void testStringDateChars() { t("foo", "foo"); } - public void testStringDate_a() { t("%a", "Thu"); } - public void testStringDate_A() { t("%A", "Thursday"); } - public void testStringDate_b() { t("%b", "Aug"); } - public void testStringDate_B() { t("%B", "August"); } - public void testStringDate_c() { t("%c", "Thu Aug 23 14:55:02 2001"); } - public void testStringDate_d() { t("%d", "23"); } - public void testStringDate_H() { t("%H", "14"); } - public void testStringDate_I() { t("%I", "02"); } - public void testStringDate_j() { t("%j", "235"); } - public void testStringDate_m() { t("%m", "08"); } - public void testStringDate_M() { t("%M", "55"); } - public void testStringDate_p() { t("%p", "PM"); } - public void testStringDate_S() { t("%S", "02"); } - public void testStringDate_U() { t("%U", "33"); } - public void testStringDate_w() { t("%w", "4"); } - public void testStringDate_W() { t("%W", "34"); } - public void testStringDate_x() { t("%x", "08/23/01"); } - public void testStringDate_X() { t("%X", "14:55:02"); } - public void testStringDate_y() { t("%y", "01"); } - public void testStringDate_Y() { t("%Y", "2001"); } - public void testStringDate_Pct() { t("%%", "%"); } - - static final double DAY = 24. * 3600.; - public void testStringDate_UW_neg4() { time-=4*DAY; t("%c %U %W", "Sun Aug 19 14:55:02 2001 33 33"); } - public void testStringDate_UW_neg3() { time-=3*DAY; t("%c %U %W", "Mon Aug 20 14:55:02 2001 33 34"); } - public void testStringDate_UW_neg2() { time-=2*DAY; t("%c %U %W", "Tue Aug 21 14:55:02 2001 33 34"); } - public void testStringDate_UW_neg1() { time-=DAY; t("%c %U %W", "Wed Aug 22 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos0() { time+=0; t("%c %U %W", "Thu Aug 23 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos1() { time+=DAY; t("%c %U %W", "Fri Aug 24 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos2() { time+=2*DAY; t("%c %U %W", "Sat Aug 25 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos3() { time+=3*DAY; t("%c %U %W", "Sun Aug 26 14:55:02 2001 34 34"); } - public void testStringDate_UW_pos4() { time+=4*DAY; t("%c %U %W", "Mon Aug 27 14:55:02 2001 34 35"); } - - public void testJseOsGetenvForEnvVariables() { - LuaValue USER = LuaValue.valueOf("USER"); - LuaValue jse_user = jse_lib.get("getenv").call(USER); - LuaValue jme_user = jme_lib.get("getenv").call(USER); - assertFalse(jse_user.isnil()); - assertTrue(jme_user.isnil()); - System.out.println("User: " + jse_user); - } - - public void testJseOsGetenvForSystemProperties() { - System.setProperty("test.key.foo", "test.value.bar"); - LuaValue key = LuaValue.valueOf("test.key.foo"); - LuaValue value = LuaValue.valueOf("test.value.bar"); - LuaValue jse_value = jse_lib.get("getenv").call(key); - LuaValue jme_value = jme_lib.get("getenv").call(key); - assertEquals(value, jse_value); - assertEquals(value, jme_value); - } -} diff --git a/test/junit/org/luaj/vm2/lib/jse/TestClass.java b/test/junit/org/luaj/vm2/lib/jse/TestClass.java deleted file mode 100644 index dc57bc4b..00000000 --- a/test/junit/org/luaj/vm2/lib/jse/TestClass.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.luaj.vm2.lib.jse; - -public class TestClass { - private static class PrivateImpl implements TestInterface { - public String public_field; - public PrivateImpl() { - this.public_field = "privateImpl-constructor"; - } - PrivateImpl(String f) { - this.public_field = f; - } - public String public_method() { return "privateImpl-"+public_field+"-public_method"; } - public String interface_method(String x) { return "privateImpl-"+public_field+"-interface_method("+x+")"; } - public String toString() { return public_field; } - } - public TestInterface create_PrivateImpl(String f) { return new PrivateImpl(f); } - public Class get_PrivateImplClass() { return PrivateImpl.class; } - public enum SomeEnum { - ValueOne, - ValueTwo, - } -} \ No newline at end of file diff --git a/test/junit/org/luaj/vm2/lib/jse/TestInterface.java b/test/junit/org/luaj/vm2/lib/jse/TestInterface.java deleted file mode 100644 index 1b58a0a5..00000000 --- a/test/junit/org/luaj/vm2/lib/jse/TestInterface.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.luaj.vm2.lib.jse; - -public interface TestInterface { - String interface_method(String x); -} \ No newline at end of file diff --git a/test/lua/baselib.lua b/test/lua/baselib.lua deleted file mode 100644 index 96c50ce8..00000000 --- a/test/lua/baselib.lua +++ /dev/null @@ -1,277 +0,0 @@ - --- tostring replacement that assigns ids -local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} -tostring = function(x) - if not x or not types[type(x)] then return ts(x) end - if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end - return id[x] -end - --- wrap pcall to return one result --- error message are tested elsewhere -local pc = pcall -local pcall = function(...) - local s,e = pc(...) - if s then return e end - return false, type(e) -end - --- print -print() -print(11) -print("abc",123,nil,"pqr") -print( nil and 'T' or 'F' ) -print( false and 'T' or 'F' ) -print( 0 and 'T' or 'F' ) - --- assert -print( 'assert(true)', assert(true) ) -print( 'pcall(assert,true)', pcall(assert,true) ) -print( 'pcall(assert,false)', pcall(assert,false) ) -print( 'pcall(assert,nil)', pcall(assert,nil) ) -print( 'pcall(assert,true,"msg")', pcall(assert,true,"msg") ) -print( 'pcall(assert,false,"msg")', pcall(assert,false,"msg") ) -print( 'pcall(assert,nil,"msg")', pcall(assert,nil,"msg") ) -print( 'pcall(assert,false,"msg","msg2")', pcall(assert,false,"msg","msg2") ) - --- collectgarbage (not supported) -print( 'collectgarbage("count")', type(collectgarbage("count"))) -print( 'collectgarbage("collect")', type(collectgarbage("collect"))) -print( 'collectgarbage("count")', type(collectgarbage("count"))) - --- dofile (not supported) --- ipairs -print( 'pcall(ipairs)', pcall(ipairs) ) -print( 'pcall(ipairs,nil)', pcall(ipairs,nil) ) -print( 'pcall(ipairs,"a")', pcall(ipairs,"a") ) -print( 'pcall(ipairs,1)', pcall(ipairs,1) ) -for k,v in ipairs({}) do print('ipairs1',k,v)end -for k,v in ipairs({'one','two'}) do print('ipairs2',k,v)end -for k,v in ipairs({aa='aaa',bb='bbb'}) do print('ipairs3',k,v)end -for k,v in ipairs({aa='aaa',bb='bbb','one','two'}) do print('ipairs4',k,v)end -for k,v in ipairs({[30]='30',[20]='20'}) do print('ipairs5',k,v)end - --- load -t = { "print ", "'table ", "loaded'", "", " print'after empty string'" } -i = 0 -f = function() i = i + 1; return t[i]; end -c,e = load(f) -if c then print('load: ', pcall(c)) else print('load failed:', e) end - --- loadfile --- load -local lst = "print(3+4); return 8" -local chunk, err = load( lst ) -print( 'load("'..lst..'")', chunk, err ) -print( 'load("'..lst..'")()', chunk() ) - --- pairs -print( 'pcall(pairs)', pcall(pairs) ) -print( 'pcall(pairs,nil)', pcall(pairs,nil) ) -print( 'pcall(pairs,"a")', pcall(pairs,"a") ) -print( 'pcall(pairs,1)', pcall(pairs,1) ) -for k,v in pairs({}) do print('pairs1',k,v)end -for k,v in pairs({'one','two'}) do print('pairs2',k,v)end -for k,v in pairs({aa='aaa'}) do print('pairs3',k,v)end -for k,v in pairs({aa='aaa','one','two'}) do print('pairs4',k,v)end -for k,v in pairs({[20]='30',[30]='20'}) do print('pairs5',k,v)end - --- _G -print( '_G["abc"] (before)', _G["abc"] ) -abc='def' -print( '_G["abc"] (after)', _G["abc"] ) - --- type -print( 'type(nil)', type(nil) ) -print( 'type("a")', type("a") ) -print( 'type(1)', type(1) ) -print( 'type(1.5)', type(1.5) ) -print( 'type(function() end)', type(function() end) ) -print( 'type({})', type({}) ) -print( 'type(true)', type(true) ) -print( 'type(false)', type(false) ) -print( 'pcall(type,type)', pcall(type,type) ) -print( 'pcall(type)', pcall(type) ) -print( '(function() return pcall(type) end)()', (function() return pcall(type) end)() ) -local function la() return pcall(type) end -print( 'la()', la() ) -function ga() return pcall(type) end -print( 'ga()', ga() ) - --- getmetatable, setmetatable -ta = { aa1="aaa1", aa2="aaa2" } -tb = { bb1="bbb1", bb2="bbb2" } -print( 'getmetatable(ta)', getmetatable(ta) ) -print( 'getmetatable(tb)', getmetatable(tb) ) -print( 'setmetatable(ta),{cc1="ccc1"}', type( setmetatable(ta,{cc1="ccc1"}) ) ) -print( 'setmetatable(tb),{dd1="ddd1"}', type( setmetatable(tb,{dd1="ddd1"}) ) ) -print( 'getmetatable(ta)["cc1"]', getmetatable(ta)["cc1"] ) -print( 'getmetatable(tb)["dd1"]', getmetatable(tb)["dd1"] ) -print( 'getmetatable(1)', getmetatable(1) ) -print( 'pcall(setmetatable,1)', pcall(setmetatable,1) ) -print( 'pcall(setmetatable,nil)', pcall(setmetatable,nil) ) -print( 'pcall(setmetatable,"ABC")', pcall(setmetatable,"ABC") ) -print( 'pcall(setmetatable,function() end)', pcall(setmetatable,function() end) ) - --- rawget,rawset -local mt = {aa="aaa", bb="bbb"} -mt.__index = mt -mt.__newindex = mt -local s = {cc="ccc", dd="ddd", } -local t = {cc="ccc", dd="ddd"} -setmetatable(t,mt) -print( 'pcall(rawget)', pcall(rawget)) -print( 'pcall(rawget,"a")', pcall(rawget,"a")) -print( 'pcall(rawget,s)', pcall(rawget,s)) -print( 'pcall(rawget,t)', pcall(rawget,t)) - -function printtables() - function printtable(name,t) - print( ' '..name, t["aa"], t["bb"], t["cc"], t["dd"], t["ee"], t["ff"], t["gg"] ) - print( ' '..name, - rawget(t,"aa"), - rawget(t,"bb"), - rawget(t,"cc"), - rawget(t,"dd"), - rawget(t,"ee"), - rawget(t,"ff"), - rawget(t,"gg") ) - end - printtable( 's', s ) - printtable( 't', t ) - printtable( 'mt', mt ) -end -printtables() -print( 'pcall(rawset,s,"aa","www")', rawset(s,"aa","www")) -printtables() -print( 'pcall(rawset,s,"cc","xxx")', rawset(s,"cc","xxx")) -printtables() -print( 'pcall(rawset,t,"aa","yyy")', rawset(t,"aa","yyy")) -printtables() -print( 'pcall(rawset,t,"dd","zzz")', rawset(t,"dd","zzz")) -printtables() - --- rawlen -print( 'pcall(rawlen, {})', pcall(rawlen, {})) -print( 'pcall(rawlen, {"a"})', pcall(rawlen, {'a'})) -print( 'pcall(rawlen, {"a","b"})', pcall(rawlen, {'a','b'})) -print( 'pcall(rawlen, "")', pcall(rawlen, "")) -print( 'pcall(rawlen, "a")', pcall(rawlen, 'a')) -print( 'pcall(rawlen, "ab")', pcall(rawlen, 'ab')) -print( 'pcall(rawlen, 1)', pcall(rawlen, 1)) -print( 'pcall(rawlen, nil)', pcall(rawlen, nil)) -print( 'pcall(rawlen)', pcall(rawlen)) - -printtables() -print( 's["ee"]="ppp"' ); s["ee"]="ppp" -printtables() -print( 's["cc"]="qqq"' ); s["cc"]="qqq" -printtables() -print( 't["ff"]="rrr"' ); t["ff"]="rrr" -printtables() -print( 't["dd"]="sss"' ); t["dd"]="sss" -printtables() -print( 'mt["gg"]="ttt"' ); mt["gg"]="ttt" -printtables() - - --- select -print( 'pcall(select)', pcall(select) ) -print( 'select(1,11,22,33,44,55)', select(1,11,22,33,44,55) ) -print( 'select(2,11,22,33,44,55)', select(2,11,22,33,44,55) ) -print( 'select(3,11,22,33,44,55)', select(3,11,22,33,44,55) ) -print( 'select(4,11,22,33,44,55)', select(4,11,22,33,44,55) ) -print( 'pcall(select,5,11,22,33,44,55)', pcall(select,5,11,22,33,44,55) ) -print( 'pcall(select,6,11,22,33,44,55)', pcall(select,6,11,22,33,44,55) ) -print( 'pcall(select,7,11,22,33,44,55)', pcall(select,7,11,22,33,44,55) ) -print( 'pcall(select,0,11,22,33,44,55)', pcall(select,0,11,22,33,44,55) ) -print( 'pcall(select,-1,11,22,33,44,55)', pcall(select,-1,11,22,33,44,55) ) -print( 'pcall(select,-2,11,22,33,44,55)', pcall(select,-2,11,22,33,44,55) ) -print( 'pcall(select,-4,11,22,33,44,55)', pcall(select,-4,11,22,33,44,55) ) -print( 'pcall(select,-5,11,22,33,44,55)', pcall(select,-5,11,22,33,44,55) ) -print( 'pcall(select,-6,11,22,33,44,55)', pcall(select,-6,11,22,33,44,55) ) -print( 'pcall(select,1)', pcall(select,1) ) -print( 'pcall(select,select)', pcall(select,select) ) -print( 'pcall(select,{})', pcall(select,{}) ) -print( 'pcall(select,"2",11,22,33)', pcall(select,"2",11,22,33) ) -print( 'pcall(select,"abc",11,22,33)', pcall(select,"abc",11,22,33) ) - - --- tonumber -print( 'pcall(tonumber)', pcall(tostring) ) -print( 'pcall(tonumber,nil)', pcall(tonumber,nil) ) -print( 'pcall(tonumber,"abc")', pcall(tonumber,"abc") ) -print( 'pcall(tonumber,"123")', pcall(tonumber,"123") ) -print( 'pcall(tonumber,"123",10)', pcall(tonumber,"123", 10) ) -print( 'pcall(tonumber,"123",8)', pcall(tonumber,"123", 8) ) -print( 'pcall(tonumber,"123",6)', pcall(tonumber,"123", 6) ) -print( 'pcall(tonumber,"10101",4)', pcall(tonumber,"10101", 4) ) -print( 'pcall(tonumber,"10101",3)', pcall(tonumber,"10101", 3) ) -print( 'pcall(tonumber,"10101",2)', pcall(tonumber,"10101", 2) ) -print( 'pcall(tonumber,"1a1",16)', pcall(tonumber,"1a1", 16) ) -print( 'pcall(tonumber,"1a1",32)', pcall(tonumber,"1a1", 32) ) -print( 'pcall(tonumber,"1a1",54)', pcall(tonumber,"1a1", 54) ) -print( 'pcall(tonumber,"1a1",1)', pcall(tonumber,"1a1", 1) ) -print( 'pcall(tonumber,"1a1",0)', pcall(tonumber,"1a1", 0) ) -print( 'pcall(tonumber,"1a1",-1)', pcall(tonumber,"1a1", -1) ) -print( 'pcall(tonumber,"1a1","32")', pcall(tonumber,"1a1", "32") ) -print( 'pcall(tonumber,"123","456")', pcall(tonumber,"123","456") ) -print( 'pcall(tonumber,"1a1",10)', pcall(tonumber,"1a1", 10) ) -print( 'pcall(tonumber,"151",4)', pcall(tonumber,"151", 4) ) -print( 'pcall(tonumber,"151",3)', pcall(tonumber,"151", 3) ) -print( 'pcall(tonumber,"151",2)', pcall(tonumber,"151", 2) ) -print( 'pcall(tonumber,"123",8,8)', pcall(tonumber,"123", 8, 8) ) -print( 'pcall(tonumber,123)', pcall(tonumber,123) ) -print( 'pcall(tonumber,true)', pcall(tonumber,true) ) -print( 'pcall(tonumber,false)', pcall(tonumber,false) ) -print( 'pcall(tonumber,tonumber)', pcall(tonumber,tonumber) ) -print( 'pcall(tonumber,function() end)', pcall(tonumber,function() end) ) -print( 'pcall(tonumber,{"one","two",a="aa",b="bb"})', pcall(tonumber,{"one","two",a="aa",b="bb"}) ) -print( 'pcall(tonumber,"123.456")', pcall(tonumber,"123.456") ) -print( 'pcall(tonumber," 123.456")', pcall(tonumber," 123.456") ) -print( 'pcall(tonumber," 234qwer")', pcall(tonumber," 234qwer") ) -print( 'pcall(tonumber,"0x20")', pcall(tonumber,"0x20") ) -print( 'pcall(tonumber," 0x20")', pcall(tonumber," 0x20") ) -print( 'pcall(tonumber,"0x20 ")', pcall(tonumber,"0x20 ") ) -print( 'pcall(tonumber," 0x20 ")', pcall(tonumber," 0x20 ") ) -print( 'pcall(tonumber,"0X20")', pcall(tonumber,"0X20") ) -print( 'pcall(tonumber," 0X20")', pcall(tonumber," 0X20") ) -print( 'pcall(tonumber,"0X20 ")', pcall(tonumber,"0X20 ") ) -print( 'pcall(tonumber," 0X20 ")', pcall(tonumber," 0X20 ") ) -print( 'pcall(tonumber,"0x20",10)', pcall(tonumber,"0x20",10) ) -print( 'pcall(tonumber,"0x20",16)', pcall(tonumber,"0x20",16) ) -print( 'pcall(tonumber,"0x20",8)', pcall(tonumber,"0x20",8) ) - --- tostring -print( 'pcall(tostring)', pcall(tostring) ) -print( 'pcall(tostring,nil)', pcall(tostring,nil) ) -print( 'pcall(tostring,"abc")', pcall(tostring,"abc") ) -print( 'pcall(tostring,"abc","def")', pcall(tostring,"abc","def") ) -print( 'pcall(tostring,123)', pcall(tostring,123) ) -print( 'pcall(tostring,true)', pcall(tostring,true) ) -print( 'pcall(tostring,false)', pcall(tostring,false) ) -print( 'tostring(tostring)', type(tostring(tostring)) ) -print( 'tostring(function() end)', type(tostring(function() end)) ) -print( 'tostring({"one","two",a="aa",b="bb"})', type(tostring({"one","two",a="aa",b="bb"})) ) - --- _VERSION -print( '_VERSION', type(_VERSION) ) - --- xpcall -local errfunc = function( detail ) - print( ' in errfunc', type(detail) ) - return 'response-from-xpcall' -end -local badfunc = function() error( 'error-from-badfunc' ) end -local wrappedbad = function() pcall( badfunc ) end -print( 'pcall(badfunc)', pcall(badfunc) ) -print( 'pcall(badfunc,errfunc)', pcall(badfunc,errfunc) ) -print( 'pcall(badfunc,badfunc)', pcall(badfunc,badfunc) ) -print( 'pcall(wrappedbad)', pcall(wrappedbad) ) -print( 'pcall(wrappedbad,errfunc)', pcall(wrappedbad,errfunc) ) -print( 'pcall(xpcall(badfunc))', pcall(xpcall,badfunc) ) -print( 'pcall(xpcall(badfunc,errfunc))', pcall(xpcall,badfunc,errfunc) ) -print( 'pcall(xpcall(badfunc,badfunc))', pcall(xpcall,badfunc,badfunc) ) -print( 'pcall(xpcall(wrappedbad))', pcall(xpcall,wrappedbad) ) -print( 'xpcall(wrappedbad,errfunc)', xpcall(wrappedbad,errfunc) ) - diff --git a/test/lua/coroutinelib.lua b/test/lua/coroutinelib.lua deleted file mode 100644 index 468dc1f7..00000000 --- a/test/lua/coroutinelib.lua +++ /dev/null @@ -1,126 +0,0 @@ -function printrunning() - if coroutine.running() == nil then - print("running is nil"); - else - print("running is not nil") - end -end - -function foo (a) - print("foo", a) - return coroutine.yield(2*a) -end - -co = coroutine.create(function (a,b) - print("co-body", a, b) - local r = foo(a+1) - print("co-body", r) - local r, s = coroutine.yield(a+b, a-b) - print("co-body", r, s) - - printrunning() - print("co.status.inside",coroutine.status(co)); - local co2 = coroutine.create(function() - print("co.status.inside2",coroutine.status(co)); - end) - print("co.status.inside",coroutine.status(co)); - coroutine.resume(co2); - - return b, "end" -end) - -function exercise() - printrunning() - print("co.status",coroutine.status(co)); - print("main", coroutine.resume(co, 1, 10)) - print("co.status",coroutine.status(co)); - print("main", coroutine.resume(co, "r")) - print("co.status",coroutine.status(co)); - print("main", coroutine.resume(co, "x", "y")) - print("co.status",coroutine.status(co)); - print("main", coroutine.resume(co, "x", "y")) - print("co.status",coroutine.status(co)); -end - -exercise(); - -co = coroutine.create(function (a,b) - print("co-body", a, b) --- TODO: make java and C behave the same for yielding in pcalls --- local status,r = pcall( foo, a+1 ) -foo(a+1) - print("co-body", status,r) - local r, s = coroutine.yield(a+b, a-b) - print("co-body", r, s) - return b, "end" -end) - -exercise(); - - --- wrap test -local g = coroutine.wrap(function (a,b) - print("co-body", a, b) - local r = foo(a+1) - print("co-body", r) - local r, s = coroutine.yield(a+b, a-b) - print("co-body", r, s) - return b, "end" -end ) - -print("g", g(1, 10)) -print("g", g("r")) -print("g", g("x", "y")) -local s,e = pcall( g, "x", "y" ) -print("g", string.match(e,'cannot resume dead coroutine') or 'badmessage: '..tostring(e)) - --- varargs passing -local echo = function(msg,...) - print( msg, ...) - return ... -end -local echocr = function(...) - local arg = table.pack(...) - echo('(echocr) first args', table.unpack(arg,1,arg.n)) - local a = arg - while true do - a = { echo( '(echoch) yield returns', coroutine.yield( table.unpack(a) ) ) } - end -end -local c = coroutine.create( echocr ) -local step = function(...) - echo( '(main) resume returns', - coroutine.resume(c, echo('(main) sending args', ...)) ) -end -step(111,222,333) -step() -step(111) -step(111,222,333) - --- test loops in resume calls -b = coroutine.create( function( arg ) - while ( true ) do - print( ' b-resumed', arg, b == coroutine.running() ) - print( ' b-b', coroutine.status(b) ) - print( ' b-c', coroutine.status(c) ) - print( ' b-resume-b',coroutine.resume( b, 'b-arg-for-b' ) ) - print( ' b-resume-c',coroutine.resume( c, 'b-arg-for-c' ) ) - arg = coroutine.yield( 'b-rslt' ) - end -end ) -c = coroutine.create( function( arg ) - for i=1,3 do - print( ' c-resumed', arg, c == coroutine.running() ) - print( ' c-b', coroutine.status(b) ) - print( ' c-c', coroutine.status(c) ) - print( ' c-resume-b',coroutine.resume( b, 'b-arg-for-b' ) ) - print( ' c-resume-c',coroutine.resume( c, 'b-arg-for-c' ) ) - arg = coroutine.yield( 'c-rslt' ) - end -end ) -for i=1,3 do - print( 'main-b', coroutine.status(b) ) - print( 'main-c', coroutine.status(c) ) - print( 'main-resume-b',coroutine.resume( b, 'main-arg-for-b' ) ) - print( 'main-resume-c',coroutine.resume( c, 'main-arg-for-c' ) ) -end diff --git a/test/lua/debuglib.lua b/test/lua/debuglib.lua deleted file mode 100644 index 11894486..00000000 --- a/test/lua/debuglib.lua +++ /dev/null @@ -1,280 +0,0 @@ - -local print,tostring,_G,pcall,ipairs,isnumber = print,tostring,_G,pcall,ipairs,isnumber -local e,f,g,h,s -print( 'has debug', debug~=nil ) -if not debug then error( 'no debug' ) end - - -print( '----- debug.getlocal, debug.setlocal' ) -h = function(v,i,n) - s = 'h-'..v..'-'..i - local x1,y1 = debug.getlocal(v,i) - local x2,y2 = debug.setlocal(v,i,n) - local x3,y3 = debug.getlocal(v,i) - return s..' -> '..v..'-'..i..' '.. - 'get='..tostring(x1)..','..tostring(y1)..' '.. - 'set='..tostring(x2)..','..tostring(y2)..' '.. - 'get='..tostring(x3)..','..tostring(y3)..' ' -end -g = function(...) - local p,q,r=7,8,9 - local t = h(...) - local b = table.concat({...},',') - return t..'\tg locals='..p..','..q..','..r..' tbl={'..b..'}' -end -f = function(a,b,c) - local d,e,f = 4,5,6 - local t = g(a,b,c) - return t..'\tf locals='..','..a..','..b..','..c..','..d..','..e..','..f -end -for lvl=3,2,-1 do - for lcl=0,7 do - print( pcall( f, lvl, lcl, '#' ) ) - end -end -for lvl=1,1 do - for lcl=3,7 do - print( pcall( f, lvl, lcl, '#' ) ) - end -end - - -print( '----- debug.getupvalue, debug.setupvalue' ) -local m,n,o = 101,102,103 -f = function(p,q,r) - local p,q,r = 104,105,106 - local g = function(s,t,u) - local v,w,x = 107,108,109 - return function() - return m,n,o,p,q,r,v,w,x - end - end - return g -end -g = f() -h = g() -local callh = function() - local t = {} - for i,v in ipairs( { pcall(h) } ) do - t[i] = tostring(v) - end - return table.concat(t,',') -end -print( 'h', h() ) -local funs = { f, g, h } -local names = { 'f', 'g', 'h' } -for i=1,3 do - local fun,name = funs[i],names[i] - for index=0,10 do - local s1,x1,y1 = pcall( debug.getupvalue, fun, index ) - local s2,x2,y2 = pcall( debug.setupvalue, fun, index, 666000+i*111000+index ) - local s3,x3,y3 = pcall( debug.getupvalue, fun, index ) - print( name..' -> '..i..'-'..index..' '.. - 'get='..tostring(s1)..','..tostring(x1)..','..tostring(y1)..' '.. - 'set='..tostring(s2)..','..tostring(x2)..','..tostring(y2)..' '.. - 'get='..tostring(s3)..','..tostring(x3)..','..tostring(y3)..' '.. - 'tbl='..callh() ) - end -end - -print( '----- debug.setmetatable, debug.getmetatable' ) -local a = {a='bbb'} -local b = {} -local mt = {__index={b='ccc'}} -print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) -local s1,x1,y1 = pcall( debug.getmetatable, a ) -local s2,x2,y2 = pcall( debug.setmetatable, a, mt ) -print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) -local s3,x3,y3 = pcall( debug.getmetatable, a ) print(type(s3), type(x3), type(y3), type(getmetatable(a))) -local s4,x4,y4 = pcall( debug.getmetatable, b ) print(type(s4), type(x4), type(y4), type(getmetatable(b))) -local s5,x5,y5 = pcall( debug.setmetatable, a, nil ) print(type(s5), type(x5), type(y5), type(getmetatable(a))) -print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b)) -local s6,x6,y6 = pcall( debug.getmetatable, a ) print(type(s6), type(x6), type(y6), type(getmetatable(a))) -if not s1 then print( 's1 error', x1 ) end -if not s2 then print( 's2 error', x2 ) end -if not s3 then print( 's3 error', x3 ) end -if not s4 then print( 's4 error', x4 ) end -if not s5 then print( 's5 error', x5 ) end -if not s6 then print( 's6 error', x6 ) end -print( 'get='..tostring(s1)..','..tostring(x1==nil)..','..tostring(y1) ) -print( 'set='..tostring(s2)..','..tostring(x2==a)..','..tostring(y2) ) -print( 'get='..tostring(s3)..','..tostring(x3==mt)..','..tostring(y3) ) -print( 'get='..tostring(s4)..','..tostring(x4==nil)..','..tostring(y4) ) -print( 'set='..tostring(s5)..','..tostring(x5==a)..','..tostring(y5) ) -print( 'get='..tostring(s6)..','..tostring(x6==nil)..','..tostring(y6) ) -print( pcall( debug.getmetatable, 1 ) ) -print( pcall( debug.setmetatable, 1, {} ) ) -print( pcall( debug.setmetatable, 1, nil ) ) - -print( '----- debug.getinfo' ) -local printfield = function(tbl, field) - local x = tbl[field] - if x == nil then return end - local typ = type(x) - if typ=='table' then - x = '{'..table.concat(x,',')..'}' - elseif typ=='function' then - x = typ - end - print( ' '..field..': '..tostring(x) ) -end -local fields = { 'source', 'short_src', 'what', - 'currentline', 'linedefined', 'lastlinedefined', - 'nups', 'func', 'activelines' } -local printinfo = function(...) - for i,a in ipairs({...}) do - if type(a) == 'table' then - for j,field in ipairs(fields) do - printfield( a, field) - end - else - print( tostring(a) ) - end - end -end -function test() - local x = 5 - function f() - x = x + 1 - return x - end - function g() - x = x - 1 - print( '---' ) - printinfo( 'debug.getinfo(1)', debug.getinfo(1) ) - printinfo( 'debug.getinfo(1,"")', debug.getinfo(1, "") ) - printinfo( 'debug.getinfo(1,"l")', debug.getinfo(1, "l") ) - printinfo( 'debug.getinfo(1,"fL")', debug.getinfo(1, "fL") ) - printinfo( 'debug.getinfo(2)', debug.getinfo(2) ) - printinfo( 'debug.getinfo(2,"l")', debug.getinfo(2, "l") ) - printinfo( 'debug.getinfo(2,"fL")', debug.getinfo(2, "fL") ) - printinfo( 'debug.getinfo(10,"")', pcall( debug.getinfo, 10, "" ) ) - printinfo( 'debug.getinfo(-10,"")', pcall( debug.getinfo, -10, "" ) ) - print( '---' ) - return x - end - print(f()) - print(g()) - return f, g -end - -local options = "nSlufL" -local e,f,g = pcall( test ) -print( 'e,f,g', e, type(f), type(g) ) -printinfo( 'debug.getinfo(f)', pcall(debug.getinfo, f) ) -printinfo( 'debug.getinfo(f,"'..options..'")', pcall(debug.getinfo, f, options) ) -for j=1,6 do - local opts = options:sub(j,j) - printinfo( 'debug.getinfo(f,"'..opts..'")', pcall(debug.getinfo, f, opts) ) -end -printinfo( 'debug.getinfo(g)', pcall(debug.getinfo, g) ) -printinfo( 'debug.getinfo(test)', pcall(debug.getinfo, test) ) - -print( '----- debug.sethook, debug.gethook' ) -f = function(x) - g = function(y) - return math.min(x,h) - end - local a = g(x) - return a + a -end -local hook = function(...) - print( ' ... in hook', ... ) - local info = debug.getinfo(2,"Sl") - if info then - print( ' info[2]='..tostring(info.short_src)..','..tostring(info.currentline) ) - end -end -local tryfunc = function(hook,mask,func,arg) - local x,f,h,m - pcall( function() - debug.sethook(hook,mask) - x = func(arg) - f,h,m = debug.gethook() - end ) - debug.sethook() - return x,f,h,m -end - -local tryhooks = function(mask) - local s1,a1,b1,c1,d1 = pcall( tryfunc, hook, mask, f, 333 ) - print( 'hook = '..mask..' -> '.. - 'result='..tostring(s1)..','..tostring(a1)..','.. - type(b1)..','..type(c1)..','.. - tostring(b1==f)..','..tostring(c1==hook)..','.. - tostring(d1)..' ' ) -end - -tryhooks("c") -tryhooks("r") -tryhooks("l") -tryhooks("crl") - -print( '----- debug.traceback' ) -function test() - function a(msg) - print((string.gsub(debug.traceback(msg), "%[Java]", "[C]"))) - end - local function b(msg) - pcall(a,msg) - end - c = function(i) - if i <= 0 then b('hi') return end - return c(i-1) - end - d = setmetatable({},{__index=function(t,k) v = c(k) return v end}) - local e = function() - return d[0] - end - local f = { - g = function() - e() - end - } - h = function() - f.g() - end - local i = h - i() -end -pcall(test) - - -print( '----- debug.upvalueid' ) -local x,y = 100,200 -function a(b,c) - local z,w = b,c - return function() - x,y,z,w = x+1,y+1,z+1,w+1 - return x,y,z,w - end -end -a1 = a(300,400) -a2 = a(500,600) -print('debug.getupvalue(a1,1)', debug.getupvalue(a1,1)) -print('debug.getupvalue(a1,2)', debug.getupvalue(a1,2)) -print('debug.getupvalue(a2,1)', debug.getupvalue(a2,1)) -print('debug.getupvalue(a2,2)', debug.getupvalue(a2,2)) -print('debug.upvalueid(a1,1) == debug.upvalueid(a1,1)', debug.upvalueid(a1,1) == debug.upvalueid(a1,1)) -print('debug.upvalueid(a1,1) == debug.upvalueid(a2,1)', debug.upvalueid(a1,1) == debug.upvalueid(a2,1)) -print('debug.upvalueid(a1,1) == debug.upvalueid(a1,2)', debug.upvalueid(a1,1) == debug.upvalueid(a1,2)) - -print( '----- debug.upvaluejoin' ) -print('a1',a1()) -print('a2',a2()) -print('debug.upvaluejoin(a1,1,a2,2)', debug.upvaluejoin(a1,1,a2,2)) -print('debug.upvaluejoin(a1,3,a2,4)', debug.upvaluejoin(a1,3,a2,4)) -print('a1',a1()) -print('a2',a2()) -print('a1',a1()) -print('a2',a2()) -for i = 1,4 do - print('debug.getupvalue(a1,'..i..')', debug.getupvalue(a1,i)) - print('debug.getupvalue(a2,'..i..')', debug.getupvalue(a2,i)) - for j = 1,4 do - print('debug.upvalueid(a1,'..i..') == debug.upvalueid(a1,'..j..')', debug.upvalueid(a1,i) == debug.upvalueid(a1,j)) - print('debug.upvalueid(a1,'..i..') == debug.upvalueid(a2,'..j..')', debug.upvalueid(a1,i) == debug.upvalueid(a2,j)) - print('debug.upvalueid(a2,'..i..') == debug.upvalueid(a1,'..j..')', debug.upvalueid(a2,i) == debug.upvalueid(a1,j)) - print('debug.upvalueid(a2,'..i..') == debug.upvalueid(a2,'..j..')', debug.upvalueid(a2,i) == debug.upvalueid(a2,j)) - end -end diff --git a/test/lua/errors.lua b/test/lua/errors.lua deleted file mode 100644 index 3ed06c2e..00000000 --- a/test/lua/errors.lua +++ /dev/null @@ -1,137 +0,0 @@ --- tostring replacement that assigns ids -local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} -tostring = function(x) - if not x or not types[type(x)] then return ts(x) end - if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end - return id[x] -end - --- test of common types of errors --- local function c(f,...) return f(...) end --- local function b(...) return c(...) end ---local function a(...) return (pcall(b,...)) end -local function a(...) local s,e=pcall(...) if s then return s,e else return false,type(e) end end -s = 'some string' -local t = {} --- error message tests -print( 'a(error)', a(error) ) -print( 'a(error,"msg")', a(error,"msg") ) -print( 'a(error,"msg",0)', a(error,"msg",0) ) -print( 'a(error,"msg",1)', a(error,"msg",1) ) -print( 'a(error,"msg",2)', a(error,"msg",2) ) -print( 'a(error,"msg",3)', a(error,"msg",3) ) -print( 'a(error,"msg",4)', a(error,"msg",4) ) -print( 'a(error,"msg",5)', a(error,"msg",5) ) -print( 'a(error,"msg",6)', a(error,"msg",6) ) - --- call errors -print( 'a(nil())', a(function() return n() end) ) -print( 'a(t()) ', a(function() return t() end) ) -print( 'a(s()) ', a(function() return s() end) ) -print( 'a(true())', a(function() local b = true; return b() end) ) - --- arithmetic errors -print( 'a(nil+1)', a(function() return nil+1 end) ) -print( 'a(a+1) ', a(function() return a+1 end) ) -print( 'a(s+1) ', a(function() return s+1 end) ) -print( 'a(true+1)', a(function() local b = true; return b+1 end) ) - --- table errors -print( 'a(nil.x)', a(function() return n.x end) ) -print( 'a(a.x) ', a(function() return a.x end) ) -print( 'a(s.x) ', a(function() return s.x end) ) -print( 'a(true.x)', a(function() local b = true; return b.x end) ) -print( 'a(nil.x=5)', a(function() n.x=5 end) ) -print( 'a(a.x=5) ', a(function() a.x=5 end) ) -print( 'a(s.x=5) ', a(function() s.x=5 end) ) -print( 'a(true.x=5)', a(function() local b = true; b.x=5 end) ) - --- len operator -print( 'a(#nil) ', a(function() return #n end) ) -print( 'a(#t) ', a(function() return #t end) ) -print( 'a(#s) ', a(function() return #s end) ) -print( 'a(#a) ', a(function() return #a end) ) -print( 'a(#true)', a(function() local b = true; return #b end) ) - --- comparison errors -print( 'a(nil>1)', a(function() return nil>1 end) ) -print( 'a(a>1) ', a(function() return a>1 end) ) -print( 'a(s>1) ', a(function() return s>1 end) ) -print( 'a(true>1)', a(function() local b = true; return b>1 end) ) - --- unary minus errors -print( 'a(-nil)', a(function() return -n end) ) -print( 'a(-a) ', a(function() return -a end) ) -print( 'a(-s) ', a(function() return -s end) ) -print( 'a(-true)', a(function() local b = true; return -b end) ) - --- string concatenation -local function concatsuite(comparefunc) - print( '"a".."b"', comparefunc("a","b") ) - print( '"a"..nil', comparefunc("a",nil) ) - print( 'nil.."b"', comparefunc(nil,"b") ) - print( '"a"..{}', comparefunc("a",{}) ) - print( '{}.."b"', comparefunc({},"b") ) - print( '"a"..2', comparefunc("a",2) ) - print( '2.."b"', comparefunc(2,"b") ) - print( '"a"..print', comparefunc("a",print) ) - print( 'print.."b"', comparefunc(print,"b") ) - print( '"a"..true', comparefunc("a",true) ) - print( 'true.."b"', comparefunc(true,"b") ) - print( 'nil..true', comparefunc(nil,true) ) - print( '"a"..3.5', comparefunc("a",3.5) ) - print( '3.5.."b"', comparefunc(3.5,"b") ) -end -local function strconcat(a,b) - return (pcall( function() return a..b end) ) -end -local function tblconcat(a,b) - local t={a,b} - return (pcall( function() return table.concat(t,'-',1,2) end )) -end - -print( '-------- string concatenation' ) -concatsuite(strconcat) -print( '-------- table concatenation' ) -concatsuite(tblconcat) - --- pairs -print( '-------- pairs tests' ) -print( 'a(pairs(nil))', a(function() return pairs(nil,{}) end) ) -print( 'a(pairs(a)) ', a(function() return pairs(a,{}) end) ) -print( 'a(pairs(s)) ', a(function() return pairs(s,{}) end) ) -print( 'a(pairs(t)) ', a(function() return pairs(t,{}) end) ) -print( 'a(pairs(true))', a(function() local b = true; return pairs(b,{}) end) ) - --- setmetatable -print( '-------- setmetatable tests' ) -function sm(...) - return tostring(setmetatable(...)) -end -print( 'a(setmetatable(nil))', a(function() return sm(nil,{}) end) ) -print( 'a(setmetatable(a)) ', a(function() return sm(a,{}) end) ) -print( 'a(setmetatable(s)) ', a(function() return sm(s,{}) end) ) -print( 'a(setmetatable(true))', a(function() local b = true; return sm(b,{}) end) ) -print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) -print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) -print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable={}}) end) ) -print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) -print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) -print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) -t = {} -print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) -print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) -print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable='some string'}) end) ) -print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) -print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) ) -print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) ) -print( 'a(setmetatable(t,nil)) ', a(function() return sm(t,nil) end) ) -print( 'a(setmetatable(t)) ', a(function() return sm(t) end) ) -print( 'a(setmetatable({},"abc")) ', a(function() return sm({},'abc') end) ) - --- bad args to error! -print( 'error("msg","arg")', a(function() error('some message', 'some bad arg') end) ) - --- loadfile, dofile on missing files -print( 'loadfile("bogus.txt")', a(function() return loadfile("bogus.txt") end) ) -print( 'dofile("bogus.txt")', a(function() return dofile("bogus.txt") end) ) diff --git a/test/lua/errors/args.lua b/test/lua/errors/args.lua deleted file mode 100644 index f74e48fa..00000000 --- a/test/lua/errors/args.lua +++ /dev/null @@ -1,198 +0,0 @@ --- utilities to check that args of various types pass or fail --- argument type checking -local ok = '-\t' -local fail = 'fail ' -local needcheck = 'needcheck ' -local badmsg = 'badmsg ' - -akey = 'aa' -astring = 'abc' -astrnum = '789' -anumber = 1.25 -ainteger = 345 -adouble = 12.75 -aboolean = true -atable = {[akey]=456} -afunction = function() end -anil = nil -athread = coroutine.create(afunction) - -anylua = { nil, astring, anumber, aboolean, atable, afunction, athread } - -somestring = { astring, anumber } -somenumber = { anumber, astrnum } -someboolean = { aboolean } -sometable = { atable } -somefunction = { afunction } -somenil = { anil } -somekey = { akey } -notakey = { astring, anumber, aboolean, atable, afunction } - -notastring = { nil, aboolean, atable, afunction, athread } -notanumber = { nil, astring, aboolean, atable, afunction, athread } -notaboolean = { nil, astring, anumber, atable, afunction, athread } -notatable = { nil, astring, anumber, aboolean, afunction, athread } -notafunction = { nil, astring, anumber, aboolean, atable, athread } -notathread = { nil, astring, anumber, aboolean, atable, afunction } -notanil = { astring, anumber, aboolean, atable, afunction, athread } - -nonstring = { aboolean, atable, afunction, athread } -nonnumber = { astring, aboolean, atable, afunction, athread } -nonboolean = { astring, anumber, atable, afunction, athread } -nontable = { astring, anumber, aboolean, afunction, athread } -nonfunction = { astring, anumber, aboolean, atable, athread } -nonthread = { astring, anumber, aboolean, atable, afunction } -nonkey = { astring, anumber, aboolean, atable, afunction } - -local structtypes = { - ['table']='', - ['function']='', - ['thread']='', - ['userdata']='', -} - -local function bracket(v) - return "<"..type(v)..">" -end - -local function quote(v) - return "'"..v.."'" -end - -local function ellipses(v) - local s = tostring(v) - return #s <= 8 and s or (string.sub(s,1,8)..'...') -end - -local pretty = { - ['table']=bracket, - ['function']=bracket, - ['thread']=bracket, - ['userdata']=bracket, - ['string']= quote, - ['number']= ellipses, -} - -local function values(list) - local t = {} - for i=1,(list.n or #list) do - local ai = list[i] - local fi = pretty[type(ai)] - t[i] = fi and fi(ai) or tostring(ai) - end - return table.concat(t,',') -end - -local function types(list) - local t = {} - for i=1,(list.n or #list) do - local ai = list[i] - t[i] = type(ai) - end - return table.concat(t,',') -end - -local function signature(name,arglist) - return name..'('..values(arglist)..')' -end - -local function dup(t) - local s = {} - for i=1,(t.n or #t) do - s[i] = t[i] - end - return s -end - -local function split(t) - local s = {} - local n = (t.n or #t) - for i=1,n-1 do - s[i] = t[i] - end - return s,t[n] -end - -local function expand(argsets, typesets, ...) - local arg = table.pack(...) - local n = typesets and #typesets or 0 - if n <= 0 then - table.insert(argsets,arg) - return argsets - end - - local s,v = split(typesets) - for i=1,(v.n or #v) do - expand(argsets, s, v[i], table.unpack(arg,1,arg.n)) - end - return argsets -end - -local function arglists(typesets) - local argsets = expand({},typesets) - return ipairs(argsets) -end - -function lookup( name ) - return load('return '..name)() -end - -function invoke( name, arglist ) - local s,c = pcall(lookup, name) - if not s then return s,c end - return pcall(c, table.unpack(arglist,1,arglist.n or #arglist)) -end - --- messages, banners -local _print = print -local _tostring = tostring -local _find = string.find -function banner(name) - _print( '====== '.._tostring(name)..' ======' ) -end - -local function subbanner(name) - _print( '--- '.._tostring(name) ) -end - -local function pack(s,...) - return s,{...} -end - --- check that all combinations of arguments pass -function checkallpass( name, typesets, typesonly ) - subbanner('checkallpass') - for i,v in arglists(typesets) do - local sig = signature(name,v) - local s,r = pack( invoke( name, v ) ) - if s then - if typesonly then - _print( ok, sig, types(r) ) - else - _print( ok, sig, values(r) ) - end - else - _print( fail, sig, values(r) ) - end - end -end - --- check that all combinations of arguments fail in some way, --- ignore error messages -function checkallerrors( name, typesets, template ) - subbanner('checkallerrors') - template = _tostring(template) - for i,v in arglists(typesets) do - local sig = signature(name,v) - local s,e = invoke( name, v ) - if not s then - if _find(e, template, 1, true) then - _print( ok, sig, '...'..template..'...' ) - else - _print( badmsg, sig, "template='"..template.."' actual='"..e.."'" ) - end - else - _print( needcheck, sig, e ) - end - end -end diff --git a/test/lua/errors/baselibargs.lua b/test/lua/errors/baselibargs.lua deleted file mode 100644 index a2cc6d1c..00000000 --- a/test/lua/errors/baselibargs.lua +++ /dev/null @@ -1,145 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - --- arg types for basic library functions - --- assert -banner('assert') -checkallpass('assert',{{true,123},anylua}) -checkallerrors('assert',{{nil,false,n=2},{nil,n=1}},'assertion failed') -checkallerrors('assert',{{nil,false,n=2},{'message'}},'message') - --- collectgarbage -banner('collectgarbage') -checkallpass('collectgarbage',{{'collect','count'}},true) -checkallerrors('collectgarbage',{{astring, anumber}},'bad argument') -checkallerrors('collectgarbage',{{aboolean, atable, afunction, athread}},'string expected') - --- dofile -banner('dofile') ---checkallpass('dofile', {}) ---checkallpass('dofile', {{'test/lua/errors/args.lua'}}) ---checkallerrors('dofile', {{'foo.bar'}}, 'cannot open foo.bar') ---checkallerrors('dofile', {nonstring}, 'bad argument') - --- error -banner('error') ---checkallerrors('error', {{'message'},{nil,0,1,2,n=4}}, 'message') ---checkallerrors('error', {{123},{nil,1,2,n=3}}, 123) - --- getmetatable -banner('getmetatable') -checkallpass('getmetatable', {notanil}) -checkallerrors('getmetatable',{},'bad argument') - --- ipairs -banner('ipairs') -checkallpass('ipairs', {sometable}) -checkallerrors('ipairs', {notatable}, 'bad argument') - --- load -banner('load') -checkallpass('load', {somefunction,{nil,astring,n=2}}) -checkallerrors('load', {notafunction,{nil,astring,anumber,n=3}}, 'bad argument') -checkallerrors('load', {somefunction,{afunction,atable}}, 'bad argument') - --- loadfile -banner('loadfile') ---checkallpass('loadfile', {}) ---checkallpass('loadfile', {{'bogus'}}) ---checkallpass('loadfile', {{'test/lua/errors/args.lua'}}) ---checkallpass('loadfile', {{'args.lua'}}) ---checkallerrors('loadfile', {nonstring}, 'bad argument') - --- load -banner('load') -checkallpass('load', {{'return'}}) -checkallpass('load', {{'return'},{'mychunk'}}) -checkallpass('load', {{'return a ... b'},{'mychunk'}},true) -checkallerrors('load', {notastring,{nil,astring,anumber,n=3}}, 'bad argument') -checkallerrors('load', {{'return'},{afunction,atable}}, 'bad argument') - --- next -banner('next') -checkallpass('next', {sometable,somekey}) -checkallerrors('next', {notatable,{nil,1,n=2}}, 'bad argument') -checkallerrors('next', {sometable,nonkey}, 'invalid key') - --- pairs -banner('pairs') -checkallpass('pairs', {sometable}) -checkallerrors('pairs', {notatable}, 'bad argument') - --- pcall -banner('pcall') -checkallpass('pcall', {notanil,anylua}, true) -checkallerrors('pcall',{},'bad argument') - --- print -banner('print') -checkallpass('print', {}) -checkallpass('print', {{nil,astring,anumber,aboolean,n=4}}) - --- rawequal -banner('rawequal') -checkallpass('rawequal', {notanil,notanil}) -checkallerrors('rawequal', {}, 'bad argument') -checkallerrors('rawequal', {notanil}, 'bad argument') - --- rawget -banner('rawget') -checkallpass('rawget', {sometable,somekey}) -checkallpass('rawget', {sometable,nonkey}) -checkallerrors('rawget', {sometable,somenil},'bad argument') -checkallerrors('rawget', {notatable,notakey}, 'bad argument') -checkallerrors('rawget', {}, 'bad argument') - --- rawset -banner('rawset') -checkallpass('rawset', {sometable,somekey,notanil}) -checkallpass('rawset', {sometable,nonkey,notanil}) -checkallerrors('rawset', {sometable,somenil},'table index is nil') -checkallerrors('rawset', {}, 'bad argument') -checkallerrors('rawset', {notatable,somestring,somestring}, 'bad argument') -checkallerrors('rawset', {sometable,somekey}, 'bad argument') - --- select -banner('select') -checkallpass('select', {{anumber,'#'},anylua}) -checkallerrors('select', {notanumber}, 'bad argument') - --- setmetatable -banner('setmetatable') -checkallpass('setmetatable', {sometable,sometable}) -checkallpass('setmetatable', {sometable,{}}) -checkallerrors('setmetatable',{notatable,sometable},'bad argument') -checkallerrors('setmetatable',{sometable,nontable},'bad argument') - --- tonumber -banner('tonumber') -checkallpass('tonumber',{somenumber,{nil,2,10,36,n=4}}) -checkallpass('tonumber',{notanil,{nil,10,n=2}}) -checkallerrors('tonumber',{{nil,afunction,atable,n=3},{2,9,11,36}},'bad argument') -checkallerrors('tonumber',{somenumber,{1,37,atable,afunction,aboolean}},'bad argument') - --- tostring -banner('tostring') -checkallpass('tostring',{{astring,anumber,aboolean}}) -checkallpass('tostring',{{atable,afunction,athread}},true) -checkallpass('tostring',{{astring,anumber,aboolean},{'anchor'}}) -checkallpass('tostring',{{atable,afunction,athread},{'anchor'}},true) -checkallerrors('tostring',{},'bad argument') - --- type -banner('type') -checkallpass('type',{notanil}) -checkallpass('type',{anylua,{'anchor'}}) -checkallerrors('type',{},'bad argument') - --- xpcall -banner('xpcall') -checkallpass('xpcall', {notanil,nonfunction}) -checkallpass('xpcall', {notanil,{function(...)return 'aaa', 'bbb', #{...} end}}) -checkallerrors('xpcall',{anylua},'bad argument') - - diff --git a/test/lua/errors/coroutinelibargs.lua b/test/lua/errors/coroutinelibargs.lua deleted file mode 100644 index caad6200..00000000 --- a/test/lua/errors/coroutinelibargs.lua +++ /dev/null @@ -1,47 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - --- arg type tests for coroutine library functions - --- coroutine.create -banner('coroutine.create') -checkallpass('coroutine.create',{somefunction}) -checkallerrors('coroutine.create',{notafunction},'bad argument') - --- coroutine.resume -banner('coroutine.resume') -local co = coroutine.create(function() while true do coroutine.yield() end end) -checkallpass('coroutine.resume',{{co},anylua}) -checkallerrors('coroutine.resume',{notathread},'bad argument') - --- coroutine.running -banner('coroutine.running') -checkallpass('coroutine.running',{anylua}) - --- coroutine.status -banner('coroutine.status') -checkallpass('coroutine.status',{{co}}) -checkallerrors('coroutine.status',{notathread},'bad argument') - --- coroutine.wrap -banner('coroutine.wrap') -checkallpass('coroutine.wrap',{somefunction}) -checkallerrors('coroutine.wrap',{notafunction},'bad argument') - --- coroutine.yield -banner('coroutine.yield') -local function f() - print( 'yield', coroutine.yield() ) - print( 'yield', coroutine.yield(astring,anumber,aboolean) ) - error('error within coroutine thread') -end -local co = coroutine.create( f ) -print( 'status', coroutine.status(co) ) -print( coroutine.resume(co,astring,anumber) ) -print( 'status', coroutine.status(co) ) -print( coroutine.resume(co,astring,anumber) ) -print( 'status', coroutine.status(co) ) -local s,e = coroutine.resume(co,astring,anumber) -print( s, string.match(e,'error within coroutine thread') or 'bad message: '..tostring(e) ) -print( 'status', coroutine.status(co) ) - diff --git a/test/lua/errors/debuglibargs.lua b/test/lua/errors/debuglibargs.lua deleted file mode 100644 index ad4a9300..00000000 --- a/test/lua/errors/debuglibargs.lua +++ /dev/null @@ -1,150 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - -local alevel = {25,'25'} -local afuncorlevel = {afunction,25,'25'} -local notafuncorlevel = {nil,astring,aboolean,athread} -local notafuncorthread = {nil,astring,aboolean} - --- debug.debug() -banner('debug.debug - no tests') - --- debug.gethook ([thread]) -banner('debug.gethook') -checkallpass('debug.gethook',{}) - --- debug.getinfo ([thread,] f [, what]) -banner('debug.getinfo') -local awhat = {"","n","flnStu"} -local notawhat = {"qzQZ"} -checkallpass('debug.getinfo',{afuncorlevel}) -checkallpass('debug.getinfo',{somethread,afuncorlevel}) -checkallpass('debug.getinfo',{afuncorlevel,awhat}) -checkallpass('debug.getinfo',{somethread,afuncorlevel,awhat}) -checkallerrors('debug.getinfo',{},'function or level') -checkallerrors('debug.getinfo',{notafuncorlevel},'function or level') -checkallerrors('debug.getinfo',{somefunction,nonstring}, 'string expected') -checkallerrors('debug.getinfo',{notafuncorthread,somefunction}, 'string expected') -checkallerrors('debug.getinfo',{nonthread,somefunction,{astring}}, 'string expected') -checkallerrors('debug.getinfo',{somethread,somefunction,notawhat}, 'invalid option') - --- debug.getlocal ([thread,] f, local) -banner('debug.getlocal') -local p,q = 'p','q'; -f = function(x,y) - print('f: x,y,a,b,p,q', x, y, a, b, p, q) - local a,b = x,y - local t = coroutine.running() - checkallpass('debug.getlocal',{{f,1},{1,'2'}}) - checkallpass('debug.getlocal',{{t},{f},{1}}) - checkallerrors('debug.getlocal',{},'number expected') - checkallerrors('debug.getlocal',{afuncorlevel,notanumber},'number expected') - checkallerrors('debug.getlocal',{notafuncorlevel,somenumber}, 'number expected') - checkallerrors('debug.getlocal',{{t},afuncorlevel}, 'got no value') - checkallerrors('debug.getlocal',{nonthread,{f},{1,'2'}}, 'number expected') - checkallerrors('debug.getlocal',{{t},{100},{1}}, 'level out of range') -end -f(1,2) - --- debug.getmetatable (value) -banner('debug.getmetatable') -checkallpass('debug.getmetatable',{anylua}) -checkallerrors('debug.getmetatable',{},'value expected') - --- debug.getregistry () -banner('debug.getregistry') -checkallpass('debug.getregistry',{}) -checkallpass('debug.getregistry',{anylua}) - --- debug.getupvalue (f, up) -banner('debug.getupvalue') -checkallpass('debug.getupvalue',{{f},{1,'2'}}) -checkallerrors('debug.getupvalue',{},'number expected') -checkallerrors('debug.getupvalue',{notafunction,{1,'2'}}, 'function expected') -checkallerrors('debug.getupvalue',{{f},notanumber}, 'number expected') - --- debug.getuservalue (u) -checkallpass('debug.getuservalue',{}) -checkallpass('debug.getuservalue',{anylua}) - --- debug.sethook ([thread,] hook, mask [, count]) -local ahookstr = {"cr","l"} -checkallpass('debug.sethook',{}) -checkallpass('debug.sethook',{somenil,ahookstr}) -checkallpass('debug.sethook',{somefunction,ahookstr}) -checkallpass('debug.sethook',{{nil,athread,n=2},somefunction,ahookstr}) -checkallerrors('debug.sethook',{{astring,afunction,aboolean}},'string expected') -checkallerrors('debug.sethook',{{astring,afunction,aboolean},{nil,afunction,n=2},ahookstr},'string expected') - --- debug.setlocal ([thread,] level, local, value) -banner('debug.setlocal') -local p,q = 'p','q'; -f = function(x,y) - print('f: x,y,a,b,p,q', x, y, a, b, p, q) - local a,b = x,y - local t = coroutine.running() - checkallpass('debug.setlocal',{{1},{1},{nil,'foo',n=2}}) - print('f: x,y,a,b,p,q', x, y, a, b, p, q) - checkallpass('debug.setlocal',{{t},{1},{2},{nil,'bar',n=2}}) - print('f: x,y,a,b,p,q', x, y, a, b, p, q) - checkallerrors('debug.setlocal',{},'number expected') - checkallerrors('debug.setlocal',{{1}},'value expected') - checkallerrors('debug.setlocal',{{1},{1}}, 'value expected') - checkallerrors('debug.setlocal',{{t},{1},{2}}, 'value expected') - checkallerrors('debug.setlocal',{{atable,astring},{1}}, 'number expected') - checkallerrors('debug.setlocal',{{1},nonnumber}, 'value expected') - checkallerrors('debug.setlocal',{{atable,astring},{1},{1},{nil,'foo',n=2}}, 'number expected') - checkallerrors('debug.setlocal',{{10},{1},{'foo'}}, 'level out of range') - return p,q -end -f(1,2) - --- debug.setmetatable (value, table) -banner('debug.setmetatable') -checkallpass('debug.setmetatable',{anylua,{atable,nil,n=2}}) -checkallerrors('debug.setmetatable',{},'nil or table') -checkallerrors('debug.setmetatable',{anylua},'nil or table') - --- debug.setupvalue (f, up, value) -banner('debug.setupvalue') -checkallpass('debug.setupvalue',{{f},{2,'3'},{nil,aboolean,astring,n=3}}) -print('p,q', p, q) -checkallerrors('debug.setupvalue',{},'value expected') -checkallerrors('debug.setupvalue',{{f}},'value expected') -checkallerrors('debug.setupvalue',{{f},{2}},'value expected') -checkallerrors('debug.setupvalue',{notafunction,{2}}, 'value expected') -checkallerrors('debug.setupvalue',{{f},notanumber}, 'value expected') - --- debug.setuservalue (udata, value) -banner('debug.setuservalue') -checkallerrors('debug.setuservalue',{},'userdata expected') -checkallerrors('debug.setuservalue',{anylua},'userdata expected') -checkallerrors('debug.setuservalue',{anylua,somestring},'userdata expected') - --- debug.traceback ([thread,] [message [, level]]) -banner('debug.traceback') -local t = coroutine.running() -checkallpass('debug.traceback',{}) -checkallpass('debug.traceback',{{astring}}) -checkallpass('debug.traceback',{{astring},{anumber}}) -checkallpass('debug.traceback',{{t}}) -checkallpass('debug.traceback',{{t},{astring}}) -checkallpass('debug.traceback',{{t},{astring},{anumber}}) -checkallpass('debug.traceback',{{afunction,aboolean,atable}}) -checkallpass('debug.traceback',{{afunction,aboolean,atable},notanumber}) - --- debug.upvalueid (f, n) -banner('debug.upvalueid') -checkallpass('debug.upvalueid',{{f},{1,'2'}}) -checkallerrors('debug.upvalueid',{},'number expected') -checkallerrors('debug.upvalueid',{notafunction,{1,'2'}}, 'function expected') -checkallerrors('debug.upvalueid',{{f},notanumber}, 'number expected') - --- debug.upvaluejoin (f1, n1, f2, n2) -banner('debug.upvaluejoin') -checkallpass('debug.upvaluejoin',{{f},{1,'2'},{f},{1,'2'}}) -checkallerrors('debug.upvaluejoin',{},'number expected') -checkallerrors('debug.upvaluejoin',{notafunction,{1,'2'}}, 'function expected') -checkallerrors('debug.upvaluejoin',{{f},notanumber}, 'number expected') -checkallerrors('debug.upvaluejoin',{{f},{1},notafunction,{1,'2'}}, 'function expected') -checkallerrors('debug.upvaluejoin',{{f},{1},{f},notanumber}, 'number expected') diff --git a/test/lua/errors/iolibargs.lua b/test/lua/errors/iolibargs.lua deleted file mode 100644 index 1f8a3ac4..00000000 --- a/test/lua/errors/iolibargs.lua +++ /dev/null @@ -1,85 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - --- arg type tests for io library functions -local f - --- io.close ([file]) -banner('io.close') -f = io.open("abc.txt","w") -checkallpass('io.close',{{f}}) -checkallerrors('io.close',{notanil},'bad argument') - --- io.input ([file]) -banner('io.input') -f = io.open("abc.txt","r") -checkallpass('io.input',{{nil,f,"abc.txt",n=3}}) -checkallerrors('io.input',{nonstring},'bad argument') - --- io.lines ([filename]) -banner('io.lines') -io.input("abc.txt") -checkallpass('io.lines',{{"abc.txt"}}) -checkallerrors('io.lines',{{f}},'bad argument') -checkallerrors('io.lines',{notastring},'bad argument') - --- io.open (filename [, mode]) -banner('io.open') -checkallpass('io.open',{{"abc.txt"},{nil,"r","w","a","r+","w+","a+"}}) -checkallerrors('io.open',{notastring},'bad argument') -checkallerrors('io.open',{{"abc.txt"},{nonstring}},'bad argument') - --- io.output ([file]) -banner('io.output') -checkallpass('io.output',{{nil,f,"abc.txt",n=3}}) -checkallerrors('io.output',{nonstring},'bad argument') - --- io.popen (prog [, mode]) -banner('io.popen') ---checkallpass('io.popen',{{"hostname"},{nil,"w",n=2}}) -checkallerrors('io.popen',{notastring},'bad argument') -checkallerrors('io.popen',{{"hostname"},{nonstring}},'bad argument') - --- io.read (���) -banner('io.read') -checkallpass('io.read',{}) -checkallpass('io.read',{{2,"*n","*a","*l"}}) -checkallpass('io.read',{{2,"*n","*a","*l"},{2,"*a","*l"}}) -checkallerrors('io.read',{{aboolean,afunction,atable,"3"}},'bad argument') - --- io.write (���) -banner('io.write') -checkallpass('io.write',{}) -checkallpass('io.write',{somestring}) -checkallpass('io.write',{somestring,somestring}) -checkallerrors('io.write',{nonstring},'bad argument') -checkallerrors('io.write',{somestring,nonstring},'bad argument') - --- file:write () -banner('file:write') -file = io.open("seektest.txt","w") -checkallpass('file.write',{{file},somestring}) -checkallpass('file.write',{{file},somestring,somestring}) -checkallerrors('file.write',{},'bad argument') -checkallerrors('file.write',{{file},nonstring},'bad argument') -checkallerrors('file.write',{{file},somestring,nonstring},'bad argument') -pcall( file.close, file ) - --- file:seek ([whence] [, offset]) -banner('file:seek') -file = io.open("seektest.txt","r") -checkallpass('file.seek',{{file}}) -checkallpass('file.seek',{{file},{"set","cur","end"}}) -checkallpass('file.seek',{{file},{"set","cur","end"},{2,"3"}}) -checkallerrors('file.seek',{},'bad argument') -checkallerrors('file.seek',{{file},nonstring},'bad argument') -checkallerrors('file.seek',{{file},{"set","cur","end"},nonnumber},'bad argument') - --- file:setvbuf (mode [, size]) -banner('file:setvbuf') -checkallpass('file.setvbuf',{{file},{"no","full","line"}}) -checkallpass('file.setvbuf',{{file},{"full"},{1024,"512"}}) -checkallerrors('file.setvbuf',{},'bad argument') -checkallerrors('file.setvbuf',{{file},notastring},'bad argument') -checkallerrors('file.setvbuf',{{file},{"full"},nonnumber},'bad argument') - diff --git a/test/lua/errors/mathlibargs.lua b/test/lua/errors/mathlibargs.lua deleted file mode 100644 index 54d48e20..00000000 --- a/test/lua/errors/mathlibargs.lua +++ /dev/null @@ -1,112 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - -local tostring = tostring -_G.tostring = function(x) - local s = tostring(x) - return type(x)=='number' and #s>4 and (s:sub(1,5)..'...') or s -end - --- arg type tests for math library functions -local somenumber = {1,0.75,'-1','-0.25'} -local somepositive = {1,0.75,'2', '2.5'} -local notanumber = {nil,astring,aboolean,afunction,atable,athread} -local nonnumber = {astring,aboolean,afunction,atable} - -local singleargfunctions = { - 'abs', 'acos', 'asin', 'atan', 'cos', 'cosh', 'deg', 'exp', 'floor', - 'rad', 'randomseed', 'sin', 'sinh', 'tan', 'tanh', 'frexp', - } - -local singleargposdomain = { - 'log', 'sqrt', 'ceil', - } - -local twoargfunctions = { - 'atan2', - } - -local twoargsposdomain = { - 'pow', 'fmod', -} - --- single argument tests -for i,v in ipairs(singleargfunctions) do - local funcname = 'math.'..v - banner(funcname) - checkallpass(funcname,{somenumber}) - checkallerrors(funcname,{notanumber},'bad argument') -end - --- single argument, positive domain tests -for i,v in ipairs(singleargposdomain) do - local funcname = 'math.'..v - banner(funcname) - checkallpass(funcname,{somepositive}) - checkallerrors(funcname,{notanumber},'bad argument') -end - --- two-argument tests -for i,v in ipairs(twoargfunctions) do - local funcname = 'math.'..v - banner(funcname) - checkallpass(funcname,{somenumber,somenumber}) - checkallerrors(funcname,{},'bad argument') - checkallerrors(funcname,{notanumber},'bad argument') - checkallerrors(funcname,{notanumber,somenumber},'bad argument') - checkallerrors(funcname,{somenumber},'bad argument') - checkallerrors(funcname,{somenumber,notanumber},'bad argument') -end - --- two-argument, positive domain tests -for i,v in ipairs(twoargsposdomain) do - local funcname = 'math.'..v - banner(funcname) - checkallpass(funcname,{somepositive,somenumber}) - checkallerrors(funcname,{},'bad argument') - checkallerrors(funcname,{notanumber},'bad argument') - checkallerrors(funcname,{notanumber,somenumber},'bad argument') - checkallerrors(funcname,{somenumber},'bad argument') - checkallerrors(funcname,{somenumber,notanumber},'bad argument') -end - --- math.max -banner('math.max') -checkallpass('math.max',{somenumber}) -checkallpass('math.max',{somenumber,somenumber}) -checkallerrors('math.max',{},'bad argument') -checkallerrors('math.max',{nonnumber},'bad argument') -checkallerrors('math.max',{somenumber,nonnumber},'bad argument') - --- math.min -banner('math.min') -checkallpass('math.min',{somenumber}) -checkallpass('math.min',{somenumber,somenumber}) -checkallerrors('math.min',{},'bad argument') -checkallerrors('math.min',{nonnumber},'bad argument') -checkallerrors('math.min',{somenumber,nonnumber},'bad argument') - --- math.random -local somem = {3,4.5,'6.7'} -local somen = {8,9.10,'12.34'} -local notamn = {astring,aboolean,atable,afunction} -banner('math.random') -checkallpass('math.random',{},true) -checkallpass('math.random',{somem},true) -checkallpass('math.random',{somem,somen},true) -checkallpass('math.random',{{-4,-5.6,'-7','-8.9'},{-1,100,23.45,'-1.23'}},true) -checkallerrors('math.random',{{-4,-5.6,'-7','-8.9'}},'interval is empty') -checkallerrors('math.random',{somen,somem},'interval is empty') -checkallerrors('math.random',{notamn,somen},'bad argument') -checkallerrors('math.random',{somem,notamn},'bad argument') - --- math.ldexp -local somee = {-3,0,3,9.10,'12.34'} -local notae = {nil,astring,aboolean,atable,afunction} -banner('math.ldexp') -checkallpass('math.ldexp',{somenumber,somee}) -checkallerrors('math.ldexp',{},'bad argument') -checkallerrors('math.ldexp',{notanumber},'bad argument') -checkallerrors('math.ldexp',{notanumber,somee},'bad argument') -checkallerrors('math.ldexp',{somenumber},'bad argument') -checkallerrors('math.ldexp',{somenumber,notae},'bad argument') \ No newline at end of file diff --git a/test/lua/errors/modulelibargs.lua b/test/lua/errors/modulelibargs.lua deleted file mode 100644 index d323123b..00000000 --- a/test/lua/errors/modulelibargs.lua +++ /dev/null @@ -1,21 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - --- arg type tests for module library functions - --- require -banner('require') -checkallpass('require',{{'math','coroutine','package','string','table'}},true) -checkallerrors('require',{{anumber}},'not found') -checkallerrors('require',{{anil,aboolean,afunction,atable}},'bad argument') - --- package.loadlib -banner('package.loadlib') -checkallpass('package.loadlib',{{'foo'},{'bar'}},true) -checkallerrors('package.loadlib',{notastring},'bad argument') - --- package.seeall -banner('package.seeall') -checkallpass('package.seeall',{sometable}) -checkallerrors('package.seeall',{notatable},'bad argument') - diff --git a/test/lua/errors/operators.lua b/test/lua/errors/operators.lua deleted file mode 100644 index ba53b507..00000000 --- a/test/lua/errors/operators.lua +++ /dev/null @@ -1,157 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - --- arg types for language operator - --- ========= unary operators: - # not - --- unary minus - -banner('unary -') -negative = function(a) return - a end -checkallpass('negative',{somenumber}) -checkallerrors('negative',{notanumber},'attempt to perform arithmetic') - --- length -banner('#') -lengthop = function(a) return #a end -checkallpass('lengthop',{sometable}) -checkallerrors('lengthop',{notatable},'attempt to get length of') - --- length -banner('not') -notop = function(a) return not a end -checkallpass('notop',{somenumber}) -checkallpass('notop',{notanumber}) - --- function call -banner( '()' ) -funcop = function(a) return a() end -checkallpass('funcop',{somefunction}) -checkallerrors('funcop',{notafunction},'attempt to call') - --- ========= binary ops: .. + - * / % ^ == ~= <= >= < > [] . and or -banner( '..' ) -concatop = function(a,b) return a..b end -checkallpass('concatop',{somestring,somestring}) -checkallerrors('concatop',{notastring,somestring},'attempt to concatenate') -checkallerrors('concatop',{somestring,notastring},'attempt to concatenate') - -banner( '+' ) -plusop = function(a,b) return a+b end -checkallpass('plusop',{somenumber,somenumber}) -checkallerrors('plusop',{notanumber,somenumber},'attempt to perform arithmetic') -checkallerrors('plusop',{somenumber,notanumber},'attempt to perform arithmetic') - -banner( '-' ) -minusop = function(a,b) return a-b end -checkallpass('minusop',{somenumber,somenumber}) -checkallerrors('minusop',{notanumber,somenumber},'attempt to perform arithmetic') -checkallerrors('minusop',{somenumber,notanumber},'attempt to perform arithmetic') - -banner( '*' ) -timesop = function(a,b) return a*b end -checkallpass('timesop',{somenumber,somenumber}) -checkallerrors('timesop',{notanumber,somenumber},'attempt to perform arithmetic') -checkallerrors('timesop',{somenumber,notanumber},'attempt to perform arithmetic') - -banner( '/' ) -divideop = function(a,b) return a/b end -checkallpass('divideop',{somenumber,somenumber}) -checkallerrors('divideop',{notanumber,somenumber},'attempt to perform arithmetic') -checkallerrors('divideop',{somenumber,notanumber},'attempt to perform arithmetic') - -banner( '%' ) -modop = function(a,b) return a%b end -checkallpass('modop',{somenumber,somenumber}) -checkallerrors('modop',{notanumber,somenumber},'attempt to perform arithmetic') -checkallerrors('modop',{somenumber,notanumber},'attempt to perform arithmetic') - -banner( '^' ) -powerop = function(a,b) return a^b end -checkallpass('powerop',{{2,'2.5'},{3,'3.5'}}) -checkallerrors('powerop',{notanumber,{3,'3.1'}},'attempt to perform arithmetic') -checkallerrors('powerop',{{2,'2.1'},notanumber},'attempt to perform arithmetic') - -banner( '==' ) -equalsop = function(a,b) return a==b end -checkallpass('equalsop',{anylua,anylua}) - -banner( '~=' ) -noteqop = function(a,b) return a~=b end -checkallpass('noteqop',{anylua,anylua}) - -banner( '<=' ) -leop = function(a,b) return a<=b end -checkallpass('leop',{{anumber},{anumber}}) -checkallpass('leop',{{astring,astrnum},{astring,astrnum}}) -checkallerrors('leop',{notanumber,{anumber}},'attempt to compare') -checkallerrors('leop',{{astrnum},{anumber}},'attempt to compare') -checkallerrors('leop',{notastring,{astring,astrnum}},'attempt to compare') -checkallerrors('leop',{{anumber},notanumber},'attempt to compare') -checkallerrors('leop',{{anumber},{astrnum}},'attempt to compare') -checkallerrors('leop',{{astring,astrnum},notastring},'attempt to compare') - -banner( '>=' ) -geop = function(a,b) return a>=b end -checkallpass('geop',{{anumber},{anumber}}) -checkallpass('geop',{{astring,astrnum},{astring,astrnum}}) -checkallerrors('geop',{notanumber,{anumber}},'attempt to compare') -checkallerrors('geop',{{astrnum},{anumber}},'attempt to compare') -checkallerrors('geop',{notastring,{astring,astrnum}},'attempt to compare') -checkallerrors('geop',{{anumber},notanumber},'attempt to compare') -checkallerrors('geop',{{anumber},{astrnum}},'attempt to compare') -checkallerrors('geop',{{astring,astrnum},notastring},'attempt to compare') - -banner( '<' ) -ltop = function(a,b) return a' ) -gtop = function(a,b) return a>b end -checkallpass('gtop',{{anumber},{anumber}}) -checkallpass('gtop',{{astring,astrnum},{astring,astrnum}}) -checkallerrors('gtop',{notanumber,{anumber}},'attempt to compare') -checkallerrors('gtop',{{astrnum},{anumber}},'attempt to compare') -checkallerrors('gtop',{notastring,{astring,astrnum}},'attempt to compare') -checkallerrors('gtop',{{anumber},notanumber},'attempt to compare') -checkallerrors('gtop',{{anumber},{astrnum}},'attempt to compare') -checkallerrors('gtop',{{astring,astrnum},notastring},'attempt to compare') - -banner( '[]' ) -bracketop = function(a,b) return a[b] end -checkallpass('bracketop',{sometable,notanil}) -checkallerrors('bracketop',{notatable,notanil},'attempt to index') -checkallerrors('bracketop',{sometable},'attempt to index') - -banner( '.' ) -dotop = function(a,b) return a.b end -checkallpass('dotop',{sometable,notanil}) -checkallerrors('dotop',{notatable,notanil},'attempt to index') -checkallerrors('dotop',{sometable},'attempt to index') - -banner( 'and' ) -types = {['table']='table',['function']='function',['thread']='thread'} -clean = function(x) return types[type(x)] or x end -andop = function(a,b) return clean(a and b) end -checkallpass('andop',{anylua,anylua}) - -banner( 'or' ) -orop = function(a,b) return clean(a or b) end -checkallpass('orop',{anylua,anylua}) - --- ========= for x in y -banner( 'for x=a,b,c' ) -forop = function(a,b,c) for x=a,b,c do end end -checkallpass('forop',{{1,'1.1'},{10,'10.1'},{2,'2.1'}}) -checkallerrors('forop',{notanumber,{10,'10.1'},{2,'2.1'}},"'for' initial value must be a number") -checkallerrors('forop',{{1,'1.1'},notanumber,{2,'2.1'}},"'for' limit must be a number") -checkallerrors('forop',{{1,'1.1'},{10,'10.1'},notanumber},"'for' step must be a number") - - diff --git a/test/lua/errors/stringlibargs.lua b/test/lua/errors/stringlibargs.lua deleted file mode 100644 index 6cb732e8..00000000 --- a/test/lua/errors/stringlibargs.lua +++ /dev/null @@ -1,120 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - --- arg type tests for string library functions - --- string.byte -banner('string.byte') -checkallpass('string.byte',{somestring}) -checkallpass('string.byte',{somestring,somenumber}) -checkallpass('string.byte',{somestring,somenumber,somenumber}) -checkallerrors('string.byte',{somestring,{astring,afunction,atable}},'bad argument') -checkallerrors('string.byte',{notastring,{nil,111,n=2}},'bad argument') - --- string.char -function string_char(...) - return string.byte( string.char( ... ) ) -end -banner('string_char') -checkallpass('string.char',{{60}}) -checkallpass('string.char',{{60},{70}}) -checkallpass('string.char',{{60},{70},{80}}) -checkallpass('string_char',{{0,9,40,127,128,255,'0','9','255','9.2',9.2}}) -checkallpass('string_char',{{0,127,255},{0,127,255}}) -checkallerrors('string_char',{},'bad argument') -checkallerrors('string_char',{{nil,-1,256,3}},'bad argument') -checkallerrors('string_char',{notanumber,{23,'45',6.7}},'bad argument') -checkallerrors('string_char',{{23,'45',6.7},nonnumber},'bad argument') - --- string.dump -banner('string.dump') -local someupval = 435 -local function funcwithupvals() return someupval end -checkallpass('string.dump',{{function() return 123 end}}) -checkallpass('string.dump',{{funcwithupvals}}) -checkallerrors('string.dump',{notafunction},'bad argument') - --- string.find -banner('string.find') -checkallpass('string.find',{somestring,somestring}) -checkallpass('string.find',{somestring,somestring,{nil,-3,3,n=3}}) -checkallpass('string.find',{somestring,somestring,somenumber,anylua}) -checkallerrors('string.find',{notastring,somestring},'bad argument') -checkallerrors('string.find',{somestring,notastring},'bad argument') -checkallerrors('string.find',{somestring,somestring,nonnumber},'bad argument') - --- string.format ---local numfmts = {'%c','%d','%E','%e','%f','%g','%G','%i','%o','%u','%X','%x'} -local numfmts = {'%c','%d','%i','%o','%u','%X','%x'} -local strfmts = {'%q','%s'} -local badfmts = {'%w'} -banner('string.format') -checkallpass('string.format',{somestring,anylua}) -checkallpass('string.format',{numfmts,somenumber}) -checkallpass('string.format',{strfmts,somestring}) -checkallerrors('string.format',{numfmts,notanumber},'bad argument') -checkallerrors('string.format',{strfmts,notastring},'bad argument') -checkallerrors('string.format',{badfmts,somestring},"invalid option '%w'") - --- string.gmatch -banner('string.gmatch') -checkallpass('string.gmatch',{somestring,somestring}) -checkallerrors('string.gmatch',{notastring,somestring},'bad argument') -checkallerrors('string.gmatch',{somestring,notastring},'bad argument') - --- string.gsub -local somerepl = {astring,atable,afunction} -local notarepl = {nil,aboolean,n=2} -banner('string.gsub') -checkallpass('string.gsub',{somestring,somestring,somerepl,{nil,-1,n=2}}) -checkallerrors('string.gsub',{nonstring,somestring,somerepl},'bad argument') -checkallerrors('string.gsub',{somestring,nonstring,somerepl},'bad argument') -checkallerrors('string.gsub',{{astring},{astring},notarepl},'bad argument') -checkallerrors('string.gsub',{{astring},{astring},somerepl,nonnumber},'bad argument') - --- string.len -banner('string.len') -checkallpass('string.len',{somestring}) -checkallerrors('string.len',{notastring},'bad argument') - --- string.lower -banner('string.lower') -checkallpass('string.lower',{somestring}) -checkallerrors('string.lower',{notastring},'bad argument') - --- string.match -banner('string.match') -checkallpass('string.match',{somestring,somestring}) -checkallpass('string.match',{somestring,somestring,{nil,-3,3,n=3}}) -checkallerrors('string.match',{},'bad argument') -checkallerrors('string.match',{nonstring,somestring},'bad argument') -checkallerrors('string.match',{somestring},'bad argument') -checkallerrors('string.match',{somestring,nonstring},'bad argument') -checkallerrors('string.match',{somestring,somestring,notanumber},'bad argument') - --- string.reverse -banner('string.reverse') -checkallpass('string.reverse',{somestring}) -checkallerrors('string.reverse',{notastring},'bad argument') - --- string.rep -banner('string.rep') -checkallpass('string.rep',{somestring,somenumber}) -checkallerrors('string.rep',{notastring,somenumber},'bad argument') -checkallerrors('string.rep',{somestring,notanumber},'bad argument') - --- string.sub -banner('string.sub') -checkallpass('string.sub',{somestring,somenumber}) -checkallpass('string.sub',{somestring,somenumber,somenumber}) -checkallerrors('string.sub',{},'bad argument') -checkallerrors('string.sub',{nonstring,somenumber,somenumber},'bad argument') -checkallerrors('string.sub',{somestring},'bad argument') -checkallerrors('string.sub',{somestring,nonnumber,somenumber},'bad argument') -checkallerrors('string.sub',{somestring,somenumber,nonnumber},'bad argument') - --- string.upper -banner('string.upper') -checkallpass('string.upper',{somestring}) -checkallerrors('string.upper',{notastring},'bad argument') - diff --git a/test/lua/errors/tablelibargs.lua b/test/lua/errors/tablelibargs.lua deleted file mode 100644 index 895b79a6..00000000 --- a/test/lua/errors/tablelibargs.lua +++ /dev/null @@ -1,70 +0,0 @@ -package.path = "?.lua;test/lua/errors/?.lua" -require 'args' - --- arg type tests for table library functions - --- table.concat -local somestringstable = {{8,7,6,5,4,3,2,1,}} -local somenonstringtable = {{true,true,true,true,true,true,true,true,}} -local somesep = {',',1.23} -local notasep = {aboolean,atable,afunction} -local somei = {2,'2','2.2'} -local somej = {4,'4','4.4'} -local notij = {astring,aboolean,atable,afunction} -banner('table.concat') -checkallpass('table.concat',{somestringstable}) -checkallpass('table.concat',{somestringstable,somesep}) -checkallpass('table.concat',{somestringstable,{'-'},somei}) -checkallpass('table.concat',{somestringstable,{'-'},{2},somej}) -checkallerrors('table.concat',{notatable},'bad argument') -checkallerrors('table.concat',{somenonstringtable},'boolean') -checkallerrors('table.concat',{somestringstable,notasep},'bad argument') -checkallerrors('table.concat',{somestringstable,{'-'},notij},'bad argument') -checkallerrors('table.concat',{somestringstable,{'-'},{2},notij},'bad argument') - --- table.insert -banner('table.insert') -checkallpass('table.insert',{sometable,notanil}) -checkallpass('table.insert',{sometable,somei,notanil}) -checkallerrors('table.insert',{notatable,somestring},'bad argument') -checkallerrors('table.insert',{sometable,notij,notanil},'bad argument') - --- table.remove -banner('table.remove') -checkallpass('table.remove',{sometable}) -checkallpass('table.remove',{sometable,somei}) -checkallerrors('table.remove',{notatable},'bad argument') -checkallerrors('table.remove',{notatable,somei},'bad argument') -checkallerrors('table.remove',{sometable,notij},'bad argument') - --- table.sort -local somecomp = {nil,afunction,n=2} -local notacomp = {astring,anumber,aboolean,atable} -banner('table.sort') -checkallpass('table.sort',{somestringstable,somecomp}) -checkallerrors('table.sort',{sometable},'attempt to') -checkallerrors('table.sort',{notatable,somecomp},'bad argument') -checkallerrors('table.sort',{sometable,notacomp},'bad argument') - --- table get -banner('table_get - tbl[key]') -function table_get(tbl,key) return tbl[key] end -checkallpass('table_get',{sometable,anylua}) - --- table set -banner('table_set - tbl[key]=val') -function table_set(tbl,key,val) tbl[key]=val end -function table_set_nil_key(tbl,val) tbl[nil]=val end -checkallpass('table_set',{sometable,notanil,anylua}) -checkallerrors('table_set_nil_key',{sometable,anylua},'table index') - --- table.unpack -banner('table.unpack') -checkallpass('table.unpack',{sometable}) -checkallpass('table.unpack',{sometable,{3,'5'}}) -checkallpass('table.unpack',{sometable,{3,'5'},{1.25,'7'}}) -checkallerrors('table.unpack',{notatable,somenumber,somenumber},'bad argument') -checkallerrors('table.unpack',{sometable,nonnumber,somenumber},'bad argument') -checkallerrors('table.unpack',{sometable,somenumber,nonnumber},'bad argument') - - diff --git a/test/lua/functions.lua b/test/lua/functions.lua deleted file mode 100644 index e55f0357..00000000 --- a/test/lua/functions.lua +++ /dev/null @@ -1,74 +0,0 @@ - -function f0() print( "f0:" ) end -function f1(a) print( "f1:", a ) end -function f2(a,b) print( "f2:", a, b ) end -function f3(a,b,c) print( "f3:", a, b, c ) end -function f4(a,b,c,d) print( "f4:", a, b, c, d ) end - -f0() f0( "a1/1" ) f0( "a1/2", "a2/2" ) f0( "a1/3", "a2/3", "a3/3" ) f0( "a1/4", "a2/4", "a3/4", "a4/4" ) -f1() f1( "a1/1" ) f1( "a1/2", "a2/2" ) f1( "a1/3", "a2/3", "a3/3" ) f1( "a1/4", "a2/4", "a3/4", "a4/4" ) -f2() f2( "a1/1" ) f2( "a1/2", "a2/2" ) f2( "a1/3", "a2/3", "a3/3" ) f2( "a1/4", "a2/4", "a3/4", "a4/4" ) -f3() f3( "a1/1" ) f3( "a1/2", "a2/2" ) f3( "a1/3", "a2/3", "a3/3" ) f3( "a1/4", "a2/4", "a3/4", "a4/4" ) -f4() f4( "a1/1" ) f4( "a1/2", "a2/2" ) f4( "a1/3", "a2/3", "a3/3" ) f4( "a1/4", "a2/4", "a3/4", "a4/4" ) - -function g0(a,b,c,d) return end -function g1(a,b,c,d) return d end -function g2(a,b,c,d) return c, d end -function g3(a,b,c,d) return b, c, d end -function g4(a,b,c,d) return a, b, c, d end - -z = g0("c0.1/4", "c0.2/4", "c0.3/4", "c0.4/4") -print( "z0:", z ) -z = g2("c2.1/4", "c2.2/4", "c2.3/4", "c2.4/4") -print( "z2:", z ) -z = g4("c4.1/4", "c4.2/4", "c4.3/4", "c4.4/4") -print( "z4:", z ) - -a,b,c,d = g0( "c0.1/4", "c0.2/4", "c0.3/4", "c0.4/4" ) -print( "g0:", a, b, c, d, "(eol)" ) -a,b,c,d = g2( "b2.1/4", "b2.2/4", "b2.3/4", "b2.4/4" ) -print( "g2:", a, b, c, d, "(eol)" ) -a,b,c,d = g4( "b4.1/4", "b4.2/4", "b4.3/4", "b4.4/4" ) -print( "g4:", a, b, c, d, "(eol)" ) - -function func(a,b,c) - return a, b, c -end - -print( func(11, 12, 13) ) -print( func(23, 22, 21) ) -print( func(func(32,33,34), func(45,46,47), func(58,59,50)) ) - -function p(a,...) - print("a",a) - print("...",...) - print("...,a",...,a) - print("a,...",a,...) -end -p() -p("q") -p("q","r") -p("q","r","s") - --- tail call tests -function first(...) - return 'abc', ..., '|', ... -end - -function second(a,...) - return 'def', ..., '|', a, ... -end - -function third( a, b, c ) - print( 'third', first( a, b, c ) ) - print( 'third', second( a, b, c ) ) - return second( a, b, c ) -end - -print( 'third', third() ) -print( 'third', third('p') ) -print( 'third', third('p','q') ) -print( 'third', third('p','q','r') ) -print( 'third', third('p','q','r','s') ) -print( 'third', third() ) - diff --git a/test/lua/iolib.lua b/test/lua/iolib.lua deleted file mode 100644 index ab086e51..00000000 --- a/test/lua/iolib.lua +++ /dev/null @@ -1,153 +0,0 @@ -local platform = ... ---print( 'platform', platform ) - --- simple io-library tests --- --- C version on Windows will add change \n into \r\n for text files at least --- -local tostr,files,nfiles = tostring,{},0 -tostring = function(x) - local s = tostr(x) - if s:sub(1,4) ~= 'file' then return s end - if files[s] then return files[s] end - files[s] = 'file.'..nfiles - nfiles = nfiles + 1 - return files[s] -end -print( io ~= nil ) -print( io.open ~= nil ) -print( io.stdin ~= nil ) -print( io.stdout ~= nil ) -print( io.stderr ~= nil ) -print( 'write', io.write() ) -print( 'write', io.write("This") ) -print( 'write', io.write(" is a pen.") ) -print( 'flush', io.flush() ) - -local f = io.open("abc.txt","w") -print( 'f', type(f) ) -print( io.type(f) ) -print( 'write', f:write("abcdef 12345 \t\t 678910 more\aaaaaaa\bbbbthe rest") ) -print( 'type(f)', io.type(f) ) -print( 'close', f:close() ) -print( 'type(f)', io.type(f) ) -print( 'type("f")', io.type("f") ) - -local g = io.open("abc.txt","r") -local t = { g:read(3, 3, "*n", "*n", "*l", "*l", "*a") } -for i,v in ipairs(t) do - print( string.format("%q",tostring(v)), type(v)) - print( '----- ', i ) -end - -local h,s = io.open("abc.txt", "a") -print( 'h', io.type(h), string.sub(tostring(h),1,6), s ) -print( 'write', h:write('and more and more and more text.') ) -print( 'close', h:close() ) - -if platform ~= 'JME' then - local j = io.open( "abc.txt", "r" ) - print( 'j', io.type(j) ) - print( 'seek', j:seek("set", 3) ) - print( 'read', j:read(4), j:read(3) ) - print( 'seek', j:seek("set", 2) ) - print( 'read', j:read(4), j:read(3) ) - print( 'seek', j:seek("cur", -8 ) ) - print( 'read', j:read(4), j:read(3) ) - print( 'seek(cur,0)', j:seek("cur",0) ) - print( 'seek(cur,20)', j:seek("cur",20) ) - print( 'seek(end,-5)', j:seek("end", -5) ) - print( 'read(4)', string.format("%q", tostring(j:read(4))) ) - print( 'read(4)', string.format("%q", tostring(j:read(4))) ) - print( 'read(4)', string.format("%q", tostring(j:read(4))) ) - print( 'close', j:close() ) -end - --- write a few lines, including a non-terminating one -files = {} -f = io.open("abc.txt","w") -print( 'f.type', io.type(f) ) -print( 'f', f ) -print( 'write', f:write("line one\nline two\n\nafter blank line\nunterminated line") ) -print( 'type(f)', io.type(f) ) -print( 'close', f:close() ) -files = {} - --- read using io.lines() -for l in io.lines("abc.txt") do - print( string.format('%q',l) ) -end -io.input("abc.txt") -for l in io.lines() do - print( string.format('%q',l) ) -end -io.input(io.open("abc.txt","r")) -for l in io.lines() do - print( string.format('%q',l) ) -end -io.input("abc.txt") -io.input(io.input()) -for l in io.lines() do - print( string.format('%q',l) ) -end - -local count = 0 -io.tmpfile = function() - count = count + 1 - return io.open("tmp"..count..".out","w") -end - -local a = io.tmpfile() -local b = io.tmpfile() -print( io.type(a) ) -print( io.type(b) ) -print( "a:write", a:write('aaaaaaa') ) -print( "b:write", b:write('bbbbbbb') ) -print( "a:setvbuf", a:setvbuf("no") ) -print( "a:setvbuf", a:setvbuf("full",1024) ) -print( "a:setvbuf", a:setvbuf("line") ) -print( "a:write", a:write('ccccc') ) -print( "b:write", b:write('ddddd') ) -print( "a:flush", a:flush() ) -print( "b:flush", b:flush() ) ---[[ -print( "a:read", a:read(7) ) -print( "b:read", b:read(7) ) -print( "a:seek", a:seek("cur",-4) ) -print( "b:seek", b:seek("cur",-4) ) -print( "a:read", ( a:read(7) ) ) -print( "b:read", ( b:read(7) ) ) -print( "a:seek", a:seek("cur",-8) ) -print( "b:seek", b:seek("cur",-8) ) -print( "a:read", ( a:read(7) ) ) -print( "b:read", ( b:read(7) ) ) ---]] - -local pcall = function(...) - local s,e = pcall(...) - if s then return s end - return s,e:match("closed") -end - -print( 'a:close', pcall( a.close, a ) ) -print( 'a:write', pcall( a.write, a, 'eee') ) -print( 'a:flush', pcall( a.flush, a) ) -print( 'a:read', pcall( a.read, a, 5) ) -print( 'a:lines', pcall( a.lines, a) ) -print( 'a:seek', pcall( a.seek, a, "cur", -2) ) -print( 'a:setvbuf', pcall( a.setvbuf, a, "no") ) -print( 'a:close', pcall( a.close, a ) ) -print( 'io.type(a)', pcall( io.type, a ) ) - -print( 'io.close()', pcall( io.close ) ) -print( 'io.close(io.output())', pcall( io.close, io.output() ) ) - -io.output('abc.txt') -print( 'io.close()', pcall( io.close ) ) -print( 'io.write', pcall( io.write, 'eee') ) -print( 'io.flush', pcall( io.flush) ) -print( 'io.close', pcall( io.close ) ) -io.input('abc.txt'):close() -print( 'io.read', pcall( io.read, 5) ) -print( 'io.lines', pcall( io.lines) ) - diff --git a/test/lua/luaj3.0-tests.zip b/test/lua/luaj3.0-tests.zip deleted file mode 100644 index 40b70f0281b64829cacc25e795a12f6a9d97975c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323550 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�P&G(>$05E>-P#%+rv{Y&r%qy9I{;?ZPC` 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

    gCv0cCMS`pHsC~V7f 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

    Z|0b-NI3JkQdSN>SaBd7|gGf=XZVgw1 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 diff --git a/test/lua/manyupvals.lua b/test/lua/manyupvals.lua deleted file mode 100644 index e1ae06ce..00000000 --- a/test/lua/manyupvals.lua +++ /dev/null @@ -1,37 +0,0 @@ -local t = {} -local template = [[ - local f - do - local result - function f() - if not result then - result = f() + f() - end - return result - end - end -]] -t[1] = [[ - local f1 - f1 = function() return 1 end -]] -t[2] = [[ - local f2 - f2 = function() return 1 end -]] -for i = 3, 199 do - t[i] = template:gsub("<([^>]+)>", function(s) - local c = assert(load('return '..s, 'f'..i, 'bt', { i = i }), 'could not compile: '..s) - return c() - end) -end -t[200] = [[ - print("5th fibonacci number is", f5()) - print("10th fibonacci number is", f10()) - print("199th fibonacci number is", f199()) -]] - -local s = table.concat(t) -print(s) -f = load(s) -f() diff --git a/test/lua/mathlib.lua b/test/lua/mathlib.lua deleted file mode 100644 index 64598093..00000000 --- a/test/lua/mathlib.lua +++ /dev/null @@ -1,239 +0,0 @@ -local platform = ... ---print( 'platform', platform ) - -local aliases = { - ['0']='', - ['-0']='', - ['nan']='', - ['inf']='', - ['-inf']='', - ['1.#INF']='', - ['-1.#INF']='', - ['1.#IND']='', - ['-1.#IND']='', -} - -local UNOPVALUES = { -2.5, -2, 0, 2, 2.5, "'-2.5'", "'-2'", "'0'", "'2'", "'2.5'" } - -local NUMBERPAIRS = { - { 2, 0 }, { -2.5, 0 }, { 2, 1 }, - { 5, 2 }, {-5, 2 }, {16, 2}, {-16, -2}, - { .5, 0}, {.5, 1}, {.5, 2}, {.5, -1}, {.5, 2}, - {2.25, 0}, {2.25, 2}, {-2, 0}, - { 3, 3 }, -} - -local STRINGPAIRS = { - { "'2'", "'0'" }, { "'2.5'","'3'" }, { "'-2'", "'1.5'" }, { "'-2.5'", "'-1.5'" }, - { "'3.0'", "'3.0'" }, { 2.75, 2.75 }, { "'2.75'", "'2.75'" }, -} - -local MIXEDPAIRS = { - { 3, "'3'" }, { "'3'", 3 }, { 2.75, "'2.75'" }, { "'2.75'", 2.75 }, - { -3, "'-4'" }, { "'-3'", 4 }, { -3, "'4'" }, { "'-3'", -4 }, - { -4.75, "'2.75'" }, { "'-2.75'", 1.75 }, { 4.75, "'-2.75'" }, { "'2.75'", -1.75 }, -} - -local BINOPVALUES = {} - -local RELATIONALOPVALUES = {} - -local function addall( t, s ) - for i,v in ipairs(s) do - t[#t+1] = v - end -end -addall( BINOPVALUES, NUMBERPAIRS ) -addall( BINOPVALUES, STRINGPAIRS ) -addall( BINOPVALUES, MIXEDPAIRS ) -addall( RELATIONALOPVALUES, NUMBERPAIRS ) -addall( RELATIONALOPVALUES, STRINGPAIRS ) - -local VARARGSVALUES = { - { 4, }, { -4.5 }, { "'5.5'" }, { "'-5'" }, - { 4, "'8'" }, { -4.5, "'-8'" }, { "'5.5'", 2.2 }, { "'-5'", -2.2 }, - { 111,222,333 }, { -222,-333,-111 }, { 444,-111,-222 }, -} - -local CONSTANTS = { - "huge", "pi", -} -local UNARYOPS = { - "-", "not ", -} -local BINARYOPS = { - "+", "-", "*", "^", "/", "%", -} -local RELATIONALS = { - "==", "~=", ">", "<", ">=", "<=", -} -local ONEARG_JME = { - "abs", "ceil", "cos", "deg", - "exp", "floor", "frexp", "modf", - "rad", "sin", "sqrt", "tan", -} -local ONEARG_JSE = { - "acos", "asin", "atan", "cosh", - "log", "sinh", "tanh", -} -local TWOARGS_JME = { - "fmod", "ldexp", "pow", -} -local TWOARGS_JSE = { - "atan2", -} -local VARARGSFUNCS = { - "max", "min", -} - -local ts = tostring -tostring = function(x) - local s = ts(x) - if type(x)~='number' then return s end - if aliases[s] then return aliases[s] end - if #s < 7 then return s end - local a,b = string.match(s,'([%-0-9%.]*)([eE]?[%-0-9]*)') - return a and (string.sub(a,1,6)..(b or '')) or s -end - -local function eval( expr, script ) - script = script or ('return '..expr) - local s,a,b = load( script, 'expr' ) - if s then print( expr, pcall( s ) ) - else print( expr, 'load:', a ) end -end - --- misc tests -print( '---------- miscellaneous tests ----------' ) -eval( 'math.sin( 0.0 )' ) -eval( 'math.cos( math.pi )' ) -eval( 'math.sqrt( 9.0 )' ) -eval( 'math.modf( 5.25 )') -eval( 'math.frexp(0.00625)' ) -eval( '-5 ^ 2' ) -eval( '-5 / 2' ) -eval( '-5 % 2' ) - --- constants -print( '---------- constants ----------' ) -for i,v in ipairs(CONSTANTS) do - eval( 'math.'..v ) -end - --- unary operators -for i,v in ipairs(UNARYOPS) do - print( '---------- unary operator '..v..' ----------' ) - for j,a in ipairs(UNOPVALUES) do - eval( v..a, 'return '..v..a ) - end -end - --- binary operators -for i,v in ipairs(BINARYOPS) do - print( '---------- binary operator '..v..' ----------' ) - for j,xy in ipairs(BINOPVALUES) do - eval( xy[1]..v..xy[2], - 'local x,y='..xy[1]..','..xy[2]..'; return x'..v..'y' ) - end -end - --- relational operators -for i,v in ipairs(RELATIONALS) do - print( '---------- binary operator '..v..' ----------' ) - for j,xy in ipairs(RELATIONALOPVALUES) do - eval( xy[1]..v..xy[2], - 'local x,y='..xy[1]..','..xy[2]..'; return x'..v..'y' ) - end -end - --- one-argument math functions -for i,v in ipairs(ONEARG_JME) do - print( '---------- math.'..v..' ----------' ) - for j,x in ipairs(UNOPVALUES) do - eval( 'math.'..v..'('..x..')' ) - end -end -if platform ~= 'JME' then - for i,v in ipairs(ONEARG_JSE) do - print( '---------- math.'..v..' (jse only) ----------' ) - for j,x in ipairs(UNOPVALUES) do - eval( 'math.'..v..'('..x..')' ) - end - end -end - --- two-argument math functions -for i,v in ipairs(TWOARGS_JME) do - print( '---------- math.'..v..' ----------' ) - for j,x in ipairs(BINOPVALUES) do - eval( 'math.'..v..'('..x[1]..','..x[2]..')' ) - end -end -if platform ~= 'JME' then - for i,v in ipairs(TWOARGS_JSE) do - print( '---------- math.'..v..' (jse only) ----------' ) - for j,x in ipairs(BINOPVALUES) do - eval( 'math.'..v..'('..x[1]..','..x[2]..')' ) - end - end -end - --- var-arg math functions -for i,v in ipairs(VARARGSFUNCS) do - print( '---------- math.'..v..' ----------' ) - for j,x in ipairs(VARARGSVALUES) do - eval( 'math.'..v..'('..table.concat(x,',')..')' ) - end -end - --- random tests -print("----------- Random number tests") -local function testrandom(string,lo,hi) - local c,e = load('return '..string) - for i=1,5 do - local s,e = pcall(c) - if s then - print( string, s and type(e) or e, (e>=lo) and (e<=hi) ) - else - print( string, 'error', e ) - end - end -end -testrandom('math.random()',0,1) -testrandom('math.random(5,10)',5,10) -testrandom('math.random(30)',0,30) -testrandom('math.random(-4,-2)',-4,-2) -local t = {} -print( math.randomseed(20) ) -for i=1,20 do - t[i] = math.random() -end -print( '-- comparing new numbers') -for i=1,20 do - print( t[i] == math.random(), t[i] == t[0] ) -end -print( '-- resetting seed') - -print( math.randomseed(20) ) -for i=1,20 do - print( t[i] == math.random() ) -end - --- tests involving -0, which is folded into 0 for luaj, but not for plain lua -print("----------- Tests involving -0 and NaN") -print('0 == -0', 0 == -0) -t = {[0] = 10, 20, 30, 40, 50} -print('t[-0] == t[0]',t[-0] == t[0]) -local x = -1 -local mz, z = 0/x, 0 -- minus zero, zero -print('mz, z', mz, z) -print('mz == z', mz == z) -local a = {[mz] = 1} -print('a[z] == 1 and a[mz] == 1', a[z] == 1 and a[mz] == 1) --- string with same binary representation as 0.0 (may create problems --- for constant manipulation in the pre-compiler) -local a1, a2, a3, a4, a5 = 0, 0, "\0\0\0\0\0\0\0\0", 0, "\0\0\0\0\0\0\0\0" -assert(a1 == a2 and a2 == a4 and a1 ~= a3) -assert(a3 == a5) - ---]] diff --git a/test/lua/metatags.lua b/test/lua/metatags.lua deleted file mode 100644 index 676590be..00000000 --- a/test/lua/metatags.lua +++ /dev/null @@ -1,286 +0,0 @@ -local anumber,bnumber = 111,23.45 -local astring,bstring = "abc","def" -local anumstr,bnumstr = tostring(anumber),tostring(bnumber) -local aboolean,bboolean = false,true -local afunction,bfunction = function() end, function() end -local athread,bthead = coroutine.create(afunction),coroutine.create(bfunction) -local atable,btable = {},{} -local values = { anumber, aboolean, afunction, athread, atable } -local groups -local ts = tostring -local tb,count = {},0 - -tostring = function(o) - local t = type(o) - if t~='thread' and t~='function' and t~='table' then return ts(o) end - if not tb[o] then - count = count + 1 - tb[o] = t..'.'..count - end - return tb[o] -end - -local buildop = function(name) - return function(a,b) - print( 'mt.__'..name..'()', a, b ) - return '__'..name..'-result' - end -end -local buildop3 = function(name) - return function(a,b,c) - print( 'mt.__'..name..'()', a, b, c ) - return '__'..name..'-result' - end -end -local buildop1 = function(name) - return function(a) - print( 'mt.__'..name..'()', a ) - return '__'..name..'-result' - end -end - -local mt = { - __call=buildop('call'), - __add=buildop('add'), - __sub=buildop('sub'), - __mul=buildop('mul'), - __div=buildop('div'), - __pow=buildop('pow'), - __mod=buildop('mod'), - __unm=buildop1('unm'), - __len=buildop1('len'), - __lt=buildop('lt'), - __le=buildop('le'), - __index=buildop('index'), - __newindex=buildop3('newindex'), - __concat=buildop('concat'), -} - --- pcall a function and check for a pattern in the error string -ecall = function(pattern, ...) - local s,e = pcall(...) - if not s then e = string.match(e,pattern) or e end - return s,e -end - -print( '---- __eq same types' ) -local eqmt = { __eq=buildop('eq'), } -groups = { {nil,nil}, {true,false}, {123,456}, {11,5.5}, {afunction,bfunction}, {athread,bthread}, {astring,bstring}, {anumber,anumstr} } -for i=1,#groups do - local a,b = groups[i][1], groups[i][2] - local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) - print( type(a), type(b), 'before', pcall( function() return a==b end ) ) - print( type(a), type(b), 'before', pcall( function() return a~=b end ) ) - print( debug.setmetatable( a, eqmt ) ) - print( debug.setmetatable( b, eqmt ) ) - print( type(a), type(b), 'after', pcall( function() return a==b end ) ) - print( type(a), type(b), 'after', pcall( function() return a~=b end ) ) - print( debug.setmetatable( a, amt ) ) - print( debug.setmetatable( b, bmt ) ) -end - -print( '---- __eq, tables - should invoke metatag comparison' ) -groups = { {atable,btable} } -for i=1,#groups do - local a,b = groups[i][1], groups[i][2] - local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) - print( type(a), type(b), 'before', pcall( function() return a==b end ) ) - print( type(a), type(b), 'before', pcall( function() return a~=b end ) ) - print( debug.setmetatable( a, eqmt ) ) - print( debug.setmetatable( b, eqmt ) ) - print( type(a), type(b), 'after-a', pcall( function() return a==b end ) ) - print( type(a), type(b), 'after-a', pcall( function() return a~=b end ) ) - print( debug.setmetatable( a, amt ) ) - print( debug.setmetatable( b, bmt ) ) -end - - -print( 'nilmt', debug.getmetatable(nil) ) -print( 'boolmt', debug.getmetatable(true) ) -print( 'number', debug.getmetatable(1) ) -print( 'function', debug.getmetatable(afunction) ) -print( 'thread', debug.getmetatable(athread) ) - -print( '---- __call' ) -for i=1,#values do - local a = values[i] - local amt = debug.getmetatable(a) - print( type(a), 'before', ecall( 'attempt to call', function() return a('a','b') end ) ) - print( debug.setmetatable( a, mt ) ) - print( type(a), 'after', pcall( function() return a() end ) ) - print( type(a), 'after', pcall( function() return a('a') end ) ) - print( type(a), 'after', pcall( function() return a('a','b') end ) ) - print( type(a), 'after', pcall( function() return a('a','b','c') end ) ) - print( type(a), 'after', pcall( function() return a('a','b','c','d') end ) ) - print( debug.setmetatable( a, amt ) ) -end - -print( '---- __add, __sub, __mul, __div, __pow, __mod' ) -local groups = { {aboolean, aboolean}, {aboolean, athread}, {aboolean, afunction}, {aboolean, "abc"}, {aboolean, atable} } -for i=1,#groups do - local a,b = groups[i][1], groups[i][2] - local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a+b end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b+a end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a-b end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b-a end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a*b end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b*a end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a^b end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b^a end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return a%b end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to perform arithmetic', function() return b%a end ) ) - print( debug.setmetatable( a, mt ) ) - print( type(a), type(b), 'after', pcall( function() return a+b end ) ) - print( type(a), type(b), 'after', pcall( function() return b+a end ) ) - print( type(a), type(b), 'after', pcall( function() return a-b end ) ) - print( type(a), type(b), 'after', pcall( function() return b-a end ) ) - print( type(a), type(b), 'after', pcall( function() return a*b end ) ) - print( type(a), type(b), 'after', pcall( function() return b*a end ) ) - print( type(a), type(b), 'after', pcall( function() return a^b end ) ) - print( type(a), type(b), 'after', pcall( function() return b^a end ) ) - print( type(a), type(b), 'after', pcall( function() return a%b end ) ) - print( type(a), type(b), 'after', pcall( function() return b%a end ) ) - print( debug.setmetatable( a, amt ) ) - print( debug.setmetatable( b, bmt ) ) -end - -print( '---- __len' ) -values = { aboolean, afunction, athread, anumber } -for i=1,#values do - local a = values[i] - local amt = debug.getmetatable(a) - print( type(a), 'before', ecall( 'attempt to get length of ', function() return #a end ) ) - print( debug.setmetatable( a, mt ) ) - print( type(a), 'after', pcall( function() return #a end ) ) - print( debug.setmetatable( a, amt ) ) -end --- -print( '---- __neg' ) -values = { aboolean, afunction, athread, "abcd", atable, anumber } -for i=1,#values do - local a = values[i] - local amt = debug.getmetatable(a) - print( type(v), 'before', ecall( 'attempt to perform arithmetic ', function() return -a end ) ) - print( debug.setmetatable( a, mt ) ) - print( type(v), 'after', pcall( function() return -a end ) ) - print( debug.setmetatable( a, amt ) ) -end - -print( '---- __lt, __le, same types' ) -local bfunction = function() end -local bthread = coroutine.create( bfunction ) -local btable = {} -local groups -groups = { {true, true}, {true, false}, {afunction, bfunction}, {athread, bthread}, {atable, atable}, {atable, btable} } -for i=1,#groups do - local a,b = groups[i][1], groups[i][2] - local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) - print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return ab end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) ) - print( debug.setmetatable( a, mt ) ) - print( debug.setmetatable( b, mt ) ) - print( type(a), type(b), 'after', pcall( function() return ab end ) ) - print( type(a), type(b), 'after', pcall( function() return a>=b end ) ) - print( debug.setmetatable( a, amt ) ) - print( debug.setmetatable( b, bmt ) ) -end - -print( '---- __lt, __le, different types' ) -groups = { {aboolean, athread}, } -for i=1,#groups do - local a,b = groups[i][1], groups[i][2] - local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) - print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return ab end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to compare', function() return a>=b end ) ) - print( debug.setmetatable( a, mt ) ) - print( debug.setmetatable( b, mt ) ) - print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return ab end ) ) - print( type(a), type(b), 'after-a', ecall( 'attempt to compare', function() return a>=b end ) ) - print( debug.setmetatable( a, amt ) ) - print( debug.setmetatable( b, bmt ) ) -end - -print( '---- __tostring' ) -values = { aboolean, afunction, athread, atable, "abc" } -local strmt = { __tostring=function(a) - return 'mt.__tostring('..type(a)..')' - end, -} -for i=1,#values do - local a = values[i] - local amt = debug.getmetatable(a) - print( debug.setmetatable( a, strmt ) ) - print( type(a), 'after', pcall( function() return ts(a) end ) ) - print( debug.setmetatable( a, amt ) ) -end - -print( '---- __index, __newindex' ) -values = { aboolean, anumber, afunction, athread } -for i=1,#values do - local a = values[i] - local amt = debug.getmetatable(a) - print( type(a), 'before', ecall( 'attempt to index', function() return a.foo end ) ) - print( type(a), 'before', ecall( 'attempt to index', function() return a[123] end ) ) - print( type(a), 'before', ecall( 'index', function() a.foo = 'bar' end ) ) - print( type(a), 'before', ecall( 'index', function() a[123] = 'bar' end ) ) - print( type(a), 'before', ecall( 'attempt to index', function() return a:foo() end ) ) - print( debug.setmetatable( a, mt ) ) - print( type(a), 'after', pcall( function() return a.foo end ) ) - print( type(a), 'after', pcall( function() return a[123] end ) ) - print( type(a), 'after', pcall( function() a.foo = 'bar' end ) ) - print( type(a), 'after', pcall( function() a[123] = 'bar' end ) ) - print( type(a), 'after', ecall( 'attempt to call', function() return a:foo() end ) ) - print( debug.setmetatable( a, amt ) ) -end - -print( '---- __concat' ) -groups = { {atable, afunction}, {afunction, atable}, {123, nil}, {nil, 123} } -local s,t,u = 'sss',777 -local concatresult = setmetatable( { '__concat-result' }, { - __tostring=function() - return 'concat-string-result' - end } ) -local concatmt = { - __concat=function(a,b) - print( 'mt.__concat('..type(a)..','..type(b)..')', a, b ) - return concatresult - end -} -for i=1,#groups do - local a,b = groups[i][1], groups[i][2] - local amt,bmt = debug.getmetatable(a),debug.getmetatable(b) - print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return a..b end ) ) - print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return b..a end ) ) - print( type(a), type(s), type(t), 'before', ecall( 'attempt to concatenate ', function() return a..s..t end ) ) - print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) ) - print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) ) - print( debug.setmetatable( a, concatmt ) ) - print( type(a), type(b), 'after', pcall( function() return a..b end ) ) - print( type(a), type(b), 'after', pcall( function() return b..a end ) ) - print( type(a), type(s), type(t), 'before', pcall( function() return a..s..t end ) ) - print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) ) - print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) ) - print( debug.setmetatable( a, amt ) ) - print( debug.setmetatable( b, bmt ) ) -end - -print( '---- __metatable' ) -values = { aboolean, afunction, athread, atable, "abc" } -local mtmt = { __metatable={}, } -for i=1,#values do - local a = values[i] - local amt = debug.getmetatable(a) - print( type(a), 'before', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) ) - print( debug.setmetatable( a, mtmt ) ) - print( type(a), 'after', pcall( function() return debug.getmetatable(a), getmetatable(a) end ) ) - print( debug.setmetatable( a, amt ) ) -end diff --git a/test/lua/oslib.lua b/test/lua/oslib.lua deleted file mode 100644 index dd40a791..00000000 --- a/test/lua/oslib.lua +++ /dev/null @@ -1,60 +0,0 @@ --- simple os-library tests --- --- because the nature of the "os" library is to provide os-specific behavior, --- the compatibility tests must be extremely loose, and can really only --- compare things like return value type to be meaningful. --- --- actual os behavior needs to go in an oslib function test --- -local pcall = function(...) - local s,e,f = pcall(...) - return s,type(e),type(f) -end -print( 'os', type(os) ) -print( 'os.clock()', pcall( os.clock ) ) -print( 'os.date()', pcall( os.date ) ) -print( 'os.difftime(123000, 21500)', pcall( os.difftime, 123000, 21250 ) ) -print( 'os.getenv()', pcall( os.getenv ) ) -print( 'os.getenv("bogus.key")', pcall( os.getenv, 'bogus.key' ) ) -local s,p = pcall( os.tmpname ) -local s,q = pcall( os.tmpname ) -print( 'os.tmpname()', s, p ) -print( 'os.tmpname()', s, q ) --- permission denied on windows ---print( 'os.remove(p)', pcall( os.remove, p ) ) ---print( 'os.rename(p,q)', pcall( os.rename, p, q ) ) -local s,f = pcall( io.open, p,"w" ) -print( 'io.open', s, f ) -print( 'write', pcall( f.write, f, "abcdef 12345" ) ) -print( 'close', pcall( f.close, f ) ) -print( 'os.rename(p,q)', pcall( os.rename, p, q ) ) -print( 'os.remove(q)', pcall( os.remove, q ) ) -print( 'os.remove(q)', pcall( os.remove, q ) ) --- setlocale not supported on jse yet --- print( 'os.setlocale()', pcall( os.setlocale ) ) --- print( 'os.setlocale("jp")', pcall( os.setlocale, "jp" ) ) --- print( 'os.setlocale("us","monetary")', pcall( os.setlocale, "us", "monetary" ) ) --- print( 'os.setlocale(nil,"all")', pcall( os.setlocale, nil, "all" ) ) -print( 'os.setlocale("C")', pcall( os.setlocale, "C" ) ) -print( 'os.exit', type(os.exit) ) - --- os.date() formatting -local t = 1281364496 -- Aug 9, 2010, 2:34:56 PM (Monday) -local function p(s) - if pcall(os.date, s, t) then - print( "os.date('"..s.."', "..t..")", pcall(os.date, s, t)) - end -end -for i= 65, 90 do - p('%'..string.char(i + 97 - 65)) - p('%'..string.char(i)) -end -local tbl = os.date('*t', t) -for i,k in ipairs({'year', 'month', 'day', 'hour', 'min', 'sec', 'wday', 'yday', 'isdst'}) do - local v = tbl[k] - print('k', type(k), k, 'v', type(v), v) -end - -print('type(os.time())', type(os.time())) -print('os.time({year=1971, month=2, day=25})', os.time({year=1971, month=2, day=25})) -print('os.time({year=1971, month=2, day=25, hour=11, min=22, sec=33})', os.time({year=1971, month=2, day=25, hour=11, min=22, sec=33})) diff --git a/test/lua/perf/binarytrees.lua b/test/lua/perf/binarytrees.lua deleted file mode 100644 index 04ca7eee..00000000 --- a/test/lua/perf/binarytrees.lua +++ /dev/null @@ -1,50 +0,0 @@ --- The Computer Language Benchmarks Game --- http://shootout.alioth.debian.org/ --- contributed by Mike Pall - -local function BottomUpTree(item, depth) - if depth > 0 then - local i = item + item - depth = depth - 1 - local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) - return { item, left, right } - else - return { item } - end -end - -local function ItemCheck(tree) - if tree[2] then - return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) - else - return tree[1] - end -end - -local N = tonumber(arg and arg[1]) or 0 -local mindepth = 4 -local maxdepth = mindepth + 2 -if maxdepth < N then maxdepth = N end - -do - local stretchdepth = maxdepth + 1 - local stretchtree = BottomUpTree(0, stretchdepth) - io.write(string.format("stretch tree of depth %d\t check: %d\n", - stretchdepth, ItemCheck(stretchtree))) -end - -local longlivedtree = BottomUpTree(0, maxdepth) - -for depth=mindepth,maxdepth,2 do - local iterations = 2 ^ (maxdepth - depth + mindepth) - local check = 0 - for i=1,iterations do - check = check + ItemCheck(BottomUpTree(1, depth)) + - ItemCheck(BottomUpTree(-1, depth)) - end - io.write(string.format("%d\t trees of depth %d\t check: %d\n", - iterations*2, depth, check)) -end - -io.write(string.format("long lived tree of depth %d\t check: %d\n", - maxdepth, ItemCheck(longlivedtree))) diff --git a/test/lua/perf/fannkuch.lua b/test/lua/perf/fannkuch.lua deleted file mode 100644 index fc706d7f..00000000 --- a/test/lua/perf/fannkuch.lua +++ /dev/null @@ -1,51 +0,0 @@ --- The Computer Language Benchmarks Game --- http://shootout.alioth.debian.org/ --- contributed by Mike Pall - -local function fannkuch(n) - local p, q, s, odd, check, maxflips = {}, {}, {}, true, 0, 0 - for i=1,n do p[i] = i; q[i] = i; s[i] = i end - repeat - -- Print max. 30 permutations. - if check < 30 then - if not p[n] then return maxflips end -- Catch n = 0, 1, 2. - io.write(table.unpack(p)); io.write("\n") - check = check + 1 - end - -- Copy and flip. - local q1 = p[1] -- Cache 1st element. - if p[n] ~= n and q1 ~= 1 then -- Avoid useless work. - for i=2,n do q[i] = p[i] end -- Work on a copy. - for flips=1,1000000 do -- Flip ... - local qq = q[q1] - if qq == 1 then -- ... until 1st element is 1. - if flips > maxflips then maxflips = flips end -- New maximum? - break - end - q[q1] = q1 - if q1 >= 4 then - local i, j = 2, q1 - 1 - repeat q[i], q[j] = q[j], q[i]; i = i + 1; j = j - 1; until i >= j - end - q1 = qq - end - end - -- Permute. - if odd then - p[2], p[1] = p[1], p[2]; odd = false -- Rotate 1<-2. - else - p[2], p[3] = p[3], p[2]; odd = true -- Rotate 1<-2 and 1<-2<-3. - for i=3,n do - local sx = s[i] - if sx ~= 1 then s[i] = sx-1; break end - if i == n then return maxflips end -- Out of permutations. - s[i] = i - -- Rotate 1<-...<-i+1. - local t = p[1]; for j=1,i do p[j] = p[j+1] end; p[i+1] = t - end - end - until false -end - -local n = tonumber(arg and arg[1]) or 1 -io.write("Pfannkuchen(", n, ") = ", fannkuch(n), "\n") diff --git a/test/lua/perf/nbody.lua b/test/lua/perf/nbody.lua deleted file mode 100644 index b244adf3..00000000 --- a/test/lua/perf/nbody.lua +++ /dev/null @@ -1,123 +0,0 @@ --- The Great Computer Language Shootout --- http://shootout.alioth.debian.org/ --- contributed by Isaac Gouy, tuned by Mike Pall - -local sqrt = math.sqrt - -local PI = 3.141592653589793 -local SOLAR_MASS = 4 * PI * PI -local DAYS_PER_YEAR = 365.24 - -local Jupiter = { - x = 4.84143144246472090e+00 - ,y = -1.16032004402742839e+00 - ,z = -1.03622044471123109e-01 - ,vx = 1.66007664274403694e-03 * DAYS_PER_YEAR - ,vy = 7.69901118419740425e-03 * DAYS_PER_YEAR - ,vz = -6.90460016972063023e-05 * DAYS_PER_YEAR - ,mass = 9.54791938424326609e-04 * SOLAR_MASS -} - -local Saturn = { - x = 8.34336671824457987e+00 - ,y = 4.12479856412430479e+00 - ,z = -4.03523417114321381e-01 - ,vx = -2.76742510726862411e-03 * DAYS_PER_YEAR - ,vy = 4.99852801234917238e-03 * DAYS_PER_YEAR - ,vz = 2.30417297573763929e-05 * DAYS_PER_YEAR - ,mass = 2.85885980666130812e-04 * SOLAR_MASS -} - -local Uranus = { - x = 1.28943695621391310e+01 - ,y = -1.51111514016986312e+01 - ,z = -2.23307578892655734e-01 - ,vx = 2.96460137564761618e-03 * DAYS_PER_YEAR - ,vy = 2.37847173959480950e-03 * DAYS_PER_YEAR - ,vz = -2.96589568540237556e-05 * DAYS_PER_YEAR - ,mass = 4.36624404335156298e-05 * SOLAR_MASS -} - -local Neptune = { - x = 1.53796971148509165e+01 - ,y = -2.59193146099879641e+01 - ,z = 1.79258772950371181e-01 - ,vx = 2.68067772490389322e-03 * DAYS_PER_YEAR - ,vy = 1.62824170038242295e-03 * DAYS_PER_YEAR - ,vz = -9.51592254519715870e-05 * DAYS_PER_YEAR - ,mass = 5.15138902046611451e-05 * SOLAR_MASS -} - -local Sun = { x = 0, y = 0, z = 0, - vx = 0, vy = 0, vz = 0, mass = SOLAR_MASS } - -local function advance(bodies, nbody, dt) - for i=1,nbody do - local bi = bodies[i] - local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass - local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz - for j=i+1,nbody do - local bj = bodies[j] - local dx, dy, dz = bix-bj.x, biy-bj.y, biz-bj.z - local distance = sqrt(dx*dx + dy*dy + dz*dz) - local mag = dt / (distance * distance * distance) - local bim, bjm = bimass*mag, bj.mass*mag - bivx = bivx - (dx * bjm) - bivy = bivy - (dy * bjm) - bivz = bivz - (dz * bjm) - bj.vx = bj.vx + (dx * bim) - bj.vy = bj.vy + (dy * bim) - bj.vz = bj.vz + (dz * bim) - end - bi.vx = bivx - bi.vy = bivy - bi.vz = bivz - end - for i=1,nbody do - local bi = bodies[i] - bi.x = bi.x + (dt * bi.vx) - bi.y = bi.y + (dt * bi.vy) - bi.z = bi.z + (dt * bi.vz) - end -end - - -local function energy(bodies, nbody) - local e = 0 - for i=1,nbody do - local bi = bodies[i] - local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass - e = e + (0.5 * bim * (vx*vx + vy*vy + vz*vz)) - for j=i+1,nbody do - local bj = bodies[j] - local dx, dy, dz = bi.x-bj.x, bi.y-bj.y, bi.z-bj.z - local distance = sqrt(dx*dx + dy*dy + dz*dz) - e = e - ((bim * bj.mass) / distance) - end - end - return e -end - - -local function offsetMomentum(b, nbody) - local px, py, pz = 0, 0, 0 - for i=1,nbody do - local bi = b[i] - local bim = bi.mass - px = px + (bi.vx * bim) - py = py + (bi.vy * bim) - pz = pz + (bi.vz * bim) - end - b[1].vx = -px / SOLAR_MASS - b[1].vy = -py / SOLAR_MASS - b[1].vz = -pz / SOLAR_MASS -end - -local N = tonumber(arg and arg[1]) or 1000 -local bodies = { Sun, Jupiter, Saturn, Uranus, Neptune } -local nbody = #bodies - -offsetMomentum(bodies, nbody) -io.write( string.format("%0.9f",energy(bodies, nbody)), "\n") -for i=1,N do advance(bodies, nbody, 0.01) end -io.write( string.format("%0.9f",energy(bodies, nbody)), "\n") diff --git a/test/lua/perf/nsieve.lua b/test/lua/perf/nsieve.lua deleted file mode 100644 index 475a05b4..00000000 --- a/test/lua/perf/nsieve.lua +++ /dev/null @@ -1,35 +0,0 @@ --- The Computer Language Shootout --- http://shootout.alioth.debian.org/ --- contributed by Isaac Gouy --- modified by Mike Pall - - -local function nsieve(m,isPrime) - for i=2,m do - isPrime[i] = true - end - local count = 0 - - for i=2,m do - if isPrime[i] then - for k=i+i, m, i do - if isPrime[k] then isPrime[k] = false end - end - count = count + 1 - end - end - return count -end - - -local n = tonumber(arg and arg[1]) or 1 -local flags = {} - -local m = (2^n)*10000 -print( string.format("Primes up to %8d %8d", m, nsieve(m,flags))) - -m = (2^(n-1))*10000 -print( string.format("Primes up to %8d %8d", m, nsieve(m,flags))) - -m = (2^(n-2))*10000 -print( string.format("Primes up to %8d %8d", m, nsieve(m,flags))) diff --git a/test/lua/repack.sh b/test/lua/repack.sh deleted file mode 100644 index ffece46c..00000000 --- a/test/lua/repack.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# -# unpack the luaj test archive, compile and run it locally, and repack the results - -# unzip existing archive -unzip -n luaj3.0-tests.zip -rm *.lc *.out */*.lc */*.out - -# compile tests for compiler and save binary files -for DIR in "lua5.2.1-tests" "regressions"; do - cd ${DIR} - FILES=`ls -1 *.lua | awk 'BEGIN { FS="." } ; { print $1 }'` - for FILE in $FILES ; do - echo 'compiling' `pwd` $FILE - luac ${FILE}.lua - mv luac.out ${FILE}.lc - done - cd .. -done - -# run test lua scripts and save output -for DIR in "errors" "perf" "."; do - cd ${DIR} - FILES=`ls -1 *.lua | awk 'BEGIN { FS="." } ; { print $1 }'` - for FILE in $FILES ; do - echo 'executing' `pwd` $FILE - lua ${FILE}.lua JSE > ${FILE}.out - done - cd .. -done -cd lua - -# create new zipfile -rm -f luaj3.0-tests.zip regressions -zip luaj3.0-tests.zip *.lua *.lc *.out */*.lua */*.lc */*.out - -# cleanup -rm *.out */*.lc */*.out -rm -r lua5.2.1-tests diff --git a/test/lua/stringlib.lua b/test/lua/stringlib.lua deleted file mode 100644 index dbaf1931..00000000 --- a/test/lua/stringlib.lua +++ /dev/null @@ -1,192 +0,0 @@ -print( string.find("1234567890", ".", 0, true) ) -print( string.find( 'alo alx 123 b\0o b\0o', '(..*) %1' ) ) -print( string.find( 'aloALO', '%l*' ) ) -print( string.find( ' \n isto � assim', '%S%S*' ) ) - -print( string.find( "", "" ) ) -print( string.find( "ababaabbaba", "abb" ) ) -print( string.find( "ababaabbaba", "abb", 7 ) ) - -print( string.match( "aabaa", "a*" ) ) -print( string.match( "aabaa", "a*", 3 ) ) -print( string.match( "aabaa", "a*b" ) ) -print( string.match( "aabaa", "a*b", 3 ) ) - -print( string.match( "abbaaababaabaaabaa", "b(a*)b" ) ) - -print( string.match( "abbaaababaabaaabaa", "b(a*)()b" ) ) -print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 3 ) ) -print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 8 ) ) -print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 12 ) ) - -print( string.byte("hi", -3) ) - -print( string.gsub("ABC", "@(%x+)", function(s) return "|abcd" end) ) -print( string.gsub("@123", "@(%x+)", function(s) return "|abcd" end) ) -print( string.gsub("ABC@123", "@(%x+)", function(s) return "|abcd" end) ) -print( string.gsub("ABC@123@def", "@(%x+)", function(s) return "|abcd" end) ) -print( string.gsub("ABC@123@qrs@def@tuv", "@(%x+)", function(s) return "|abcd" end) ) -print( string.gsub("ABC@123@qrs@def@tuv", "@(%x+)", function(s) return "@ab" end) ) - -print( tostring(1234567890123) ) -print( tostring(1234567890124) ) -print( tostring(1234567890125) ) - -function f1(s, p) - print(p) - p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end) - print(p) - p = string.gsub(p, "^(^?)", "%1()", 1) - print(p) - p = string.gsub(p, "($?)$", "()%1", 1) - print(p) - local t = {string.match(s, p)} - return string.sub(s, t[1], t[#t] - 1) -end - -print( pcall( f1, 'alo alx 123 b\0o b\0o', '(..*) %1' ) ) - -local function badpat() - print( string.gsub( "alo", "(.)", "%2" ) ) -end - -print( ( pcall( badpat ) ) ) - -for k, v in string.gmatch("w=200&h=150", "(%w+)=(%w+)") do - print(k, v) -end - --- string.sub -function t(str) - local i = { 0, 1, 2, 8, -1 } - for ki,vi in ipairs(i) do - local s,v = pcall( string.sub, str, vi ) - print( 'string.sub("'..str..'",'..tostring(vi)..')='..tostring(s)..',"'..tostring(v)..'"' ) - local j = { 0, 1, 2, 4, 8, -1 } - for kj,vj in ipairs(j) do - local s,v = pcall( string.sub, str, vi, vj ) - print( 'string.sub("'..str..'",'..tostring(vi)..','..tostring(vj)..')='..tostring(s)..',"'..tostring(v)..'"' ) - end - end -end -t( 'abcdefghijklmn' ) -t( 'abcdefg' ) -t( 'abcd' ) -t( 'abc' ) -t( 'ab' ) -t( 'a' ) -t( '' ) - -print(string.len("Hello, world")) -print(#"Hello, world") -print(string.len("\0\0\0")) -print(#"\0\0\0") -print(string.len("\0\1\2\3")) -print(#"\0\1\2\3") -local s = "My JaCk-O-lAnTeRn CaSe TeXt" -print(s, string.len(s), #s) - - --- string.format -print(string.format("(%.0d) (%.0d) (%.0d)", 0, -5, 9)) -print(string.format("(%.1d) (%.1d) (%.1d)", 0, -5, 9)) -print(string.format("(%.2d) (%.2d) (%.2d)", 0, -5, 9)) - -print(string.format("(%+.0d) (%+.0d) (%+.0d)", 0, -5, 9)) -print(string.format("(%+.1d) (%+.1d) (%+.1d)", 0, -5, 9)) -print(string.format("(%+.2d) (%+.2d) (%+.2d)", 0, -5, 9)) - -print(string.format("(%+3d) (% 3d) (%+ 3d)", 55, 55, 55)) - -print(string.format("(%-1d) (%-1d) (%-1d)", 1, 12, -12)) -print(string.format("(%-2d) (%-2d) (%-2d)", 1, 12, -12)) -print(string.format("(%-3d) (%-3d) (%-3d)", 1, 12, -12)) - - -print(string.format("(%8x) (%8d) (%8o)", 255, 255, 255)) -print(string.format("(%08x) (%08d) (%08o)", 255, 255, 255)) - -print(string.format("simple%ssimple", " simple ")) - -local testformat = function(message,fmt,...) - local s,e = pcall( string.format, fmt, ... ) - if s then - if string.find(fmt, 'q') then - print(message, e) - end - print( message, string.byte(e,1,#e) ) - else - print( message, 'error', e ) - end -end - -testformat('plain %', "%%") -testformat("specials (%s)", "---%s---", " %% \000 \r \n ") -testformat("specials (%q)", "---%q---", " %% \000 \r \n ") -testformat("specials (%q)", "---%q---", "0%%0\0000\r0\n0") -testformat("controls (%q)", "---%q---", ' \a \b \f \t \v \\ ') -testformat("controls (%q)", "---%q---", '0\a0\b0\f0\t0\v0\\0') -testformat("extended (%q)", "---%q---", ' \222 \223 \224 ') -testformat("extended (%q)", "---%q---", '0\2220\2230\2240') -testformat("embedded newlines", "%s\r%s\n%s", '===', '===', '===') - --- format long string -print("this is a %s long string", string.rep("really, ", 30)) - -local function pc(...) - local s,e = pcall(...) - return s and e or 'false-'..type(e) -end - -local function strtests(name,func,...) - print(name, 'good', pc( func, ... ) ) - print(name, 'empty', pc( func ) ) - print(name, 'table', pc( func, {} ) ) - print(name, 'nil', pc( func, nil ) ) -end - -strtests('lower', string.lower, s ) -strtests('upper', string.upper, s ) -strtests('reverse', string.reverse, s ) -strtests('char', string.char, 92, 60, 61, 93 ) -stringdumptest = function() - return load(string.dump(function(x) return 'foo->'..x end),'bar')('bat') -end -print( 'string.dump test:', pcall(stringdumptest) ) - - --- floating point formats (not supported yet) ---[==[ -local prefixes = {'','+','-'} -local lengths = {'7','2','0','1',''} -local letters = {'f','e','g'} -local fmt, spec, desc -for i,letter in ipairs(letters) do - for k,before in ipairs(lengths) do - for j,prefix in ipairs(prefixes) do - spec = '(%'..prefix..before..letter..')' - fmt = spec..'\t'..spec..'\t'..spec..'\t'..spec..'\t'..spec..'\t'..spec - print(spec, string.format(fmt, 12.34, -12.34, 1/11, -1/11, 300/11, -300/11) ) - for l,after in ipairs(lengths) do - spec = '(%'..prefix..before..'.'..after..letter..')' - fmt = spec..' '..spec..' '..spec..' '..spec..' '..spec..' '..spec - print(spec, string.format(fmt, 12.34, -12.34, 1/11, -1/11, 300/11, -300/11) ) - end - end - end -end ---]==] - -local function fmterr(...) - local r, s = pcall(...) - if r then - return s - else - s = string.gsub(s, "stdin:%d+:%s*", "") - return s - end -end - -print(fmterr(string.find, "ab%c)0(", "%")) -print(fmterr(string.find, "ab%c)0(", "(")) -print(pcall(string.find, "ab%c)0(", ")")) diff --git a/test/lua/tablelib.lua b/test/lua/tablelib.lua deleted file mode 100644 index 8f99ca71..00000000 --- a/test/lua/tablelib.lua +++ /dev/null @@ -1,284 +0,0 @@ -local func = function(t,...) - return (...) -end -local tbl = setmetatable({},{__index=func}) -print( tbl[2] ) - - --- tostring replacement that assigns ids -local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} -tostring = function(x) - if not x or not types[type(x)] then return ts(x) end - if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end - return id[x] -end - -local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' } - -table.insert(t,'six'); -table.insert(t,1,'seven'); -table.insert(t,4,'eight'); -table.insert(t,7,'nine'); -table.insert(t,10,'ten'); print( #t ) - --- concat -print( '-- concat tests' ) -function tryconcat(t) - print( table.concat(t) ) - print( table.concat(t,'--') ) - print( table.concat(t,',',2) ) - print( table.concat(t,',',2,2) ) - print( table.concat(t,',',5,2) ) -end -tryconcat( { "one", "two", "three", a='aaa', b='bbb', c='ccc' } ) -tryconcat( { "one", "two", "three", "four", "five" } ) -function tryconcat(t) - print( table.concat(t) ) - print( table.concat(t,'--') ) - print( table.concat(t,',',2) ) -end -tryconcat( { a='aaa', b='bbb', c='ccc', d='ddd', e='eee' } ) -tryconcat( { [501]="one", [502]="two", [503]="three", [504]="four", [505]="five" } ) -tryconcat( {} ) - --- print the elements of a table in a platform-independent way -function eles(t,f) - f = f or pairs - all = {} - for k,v in f(t) do - table.insert( all, "["..tostring(k).."]="..tostring(v) ) - end - table.sort( all ) - return "{"..table.concat(all,',').."}" -end - --- insert, len -print( '-- insert, len tests' ) -local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' } - -print( eles(t), #t ) -table.insert(t,'six'); print( eles(t), #t ) -table.insert(t,1,'seven'); print( eles(t), #t ) -table.insert(t,4,'eight'); print( eles(t), #t ) -table.insert(t,7,'nine'); print( eles(t), #t ) -table.insert(t,10,'ten'); print( eles(t), #t ) -print( '#{}', #{} ) -print( '#{"a"}', #{"a"} ) -print( '#{"a","b"}', #{"a","b"} ) -print( '#{"a",nil}', #{"a",nil} ) -print( '#{nil,nil}', #{nil,nil} ) -print( '#{nil,"b"}', #{nil,"b"}==0 or #{nil,"b"}==2 ) -print( '#{"a","b","c"}', #{"a","b","c"} ) -print( '#{"a","b",nil}', #{"a","b",nil} ) -print( '#{"a",nil,nil}', #{"a",nil,nil} ) -print( '#{nil,nil,nil}', #{nil,nil,nil} ) -print( '#{nil,nil,"c"}', #{nil,nil,"c"}==0 or #{nil,nil,"c"}==3 ) -print( '#{nil,"b","c"}', #{nil,"b","c"}==0 or #{nil,"b","c"}==3 ) -print( '#{nil,"b",nil}', #{nil,"b",nil}==0 or #{nil,"b",nil}==2 ) -print( '#{"a",nil,"c"}', #{"a",nil,"c"}==1 or #{"a",nil,"c"}==3 ) - --- remove -print( '-- remove tests' ) -t = { "one", "two", "three", "four", "five", "six", "seven", [10]="ten", a='aaa', b='bbb', c='ccc' } -print( eles(t), #t ) -print( 'table.remove(t)', table.remove(t) ); print( eles(t), #t ) -print( 'table.remove(t,1)', table.remove(t,1) ); print( eles(t), #t ) -print( 'table.remove(t,3)', table.remove(t,3) ); print( eles(t), #t ) -print( 'table.remove(t,5)', table.remove(t,5) ); print( eles(t), #t ) -print( 'table.remove(t,10)', table.remove(t,10) ); print( eles(t), #t ) -print( 'table.remove(t,-1)', table.remove(t,-1) ); print( eles(t), #t ) -print( 'table.remove(t,-1)', table.remove(t,-1) ) ; print( eles(t), #t ) - --- sort -print( '-- sort tests' ) -function sorttest(t,f) - t = (t) - print( table.concat(t,'-') ) - if f then - table.sort(t,f) - else - table.sort(t) - end - print( table.concat(t,'-') ) -end -sorttest{ "one", "two", "three" } -sorttest{ "www", "vvv", "uuu", "ttt", "sss", "zzz", "yyy", "xxx" } -sorttest( { "www", "vvv", "uuu", "ttt", "sss", "zzz", "yyy", "xxx" }, function(a,b) return b0, returning f2(n-1,n,...)", n-1,n,... ) - return f2(n-1,n,...) -end - -local function f3(n,...) - if n <= 0 then - return sum(...) - end - print( " f3,n-1,n,...", f3,n-1,n,... ) - return pcall(f3,n-1,n,...) -end - -local function all(f) - for n=0,3 do - t = {} - for m=1,5 do - print( "--f, n, table.unpack(t)", f, n, table.unpack(t) ) - print( pcall( f, n, table.unpack(t)) ) - t[m] = m - end - end -end - -all(f1) -all(f2) -all(f3) - - -local function f(x) - -- tailcall to a builtin - return math.abs(x) -end - -local function factorial(i) - local function helper(product, n) - if n <= 0 then - return product - else - -- tail call to a nested Lua function - return helper(n * product, n - 1) - end - end - return helper(1, i) -end - -local result1 = factorial(5) -print(result1) -print(factorial(5)) - -local result2 = f(-1234) -print( result2 ) - -local function fib_bad(n) - local function helper(i, a, b) - if i >= n then - return a - else - -- not recognized by luac as a tailcall! - local result = helper(i + 1, b, a + b) - return result - end - end - return helper(1, 1, 1) -end - -local function fib_good(n) - local function helper(i, a, b) - if i >= n then - return a - else - -- must be a tail call! - return helper(i + 1, b, a + b) - end - end - return helper(1, 1, 1) -end - -local aliases = { - ['1.#INF'] = 'inf', - ['-1.#INF'] = '-inf', - ['1.#IND'] = 'nan', - ['-1.#IND'] = 'nan', -} - -local p = function( s,e ) - print( s, e and aliases[tostring(e)] or e ) -end -p(pcall(fib_bad, 30)) ---p((pcall(fib_bad, 25000))) -p(pcall(fib_good, 30)) -p(pcall(fib_good, 25000)) - -local function fib_all(n, i, a, b) - i = i or 1 - a = a or 1 - b = b or 1 - if i >= n then - return - else - return a, fib_all(n, i+1, b, a+b) - end -end - -print(fib_all(10)) diff --git a/test/lua/upvalues.lua b/test/lua/upvalues.lua deleted file mode 100644 index 2c263dd8..00000000 --- a/test/lua/upvalues.lua +++ /dev/null @@ -1,97 +0,0 @@ - -print( '-------- simple upvalues tests --------' ) -local function simpleupvalues() - function test() - local x = 5 - function f() - x = x + 1 - return x - end - function g() - x = x - 1 - return x - end - print(f()) - print(g()) - return f, g - end - - f1, g1 = test() - print("f1()=", f1()) - print("g1()=", g1()) - - f2, g2 = test() - print("f2()=", f2()) - print("g2()=", g2()) - - print("g1()=", g1()) - print("f1()=", f1()) -end -print( 'simplevalues result:', pcall( simpleupvalues ) ) - - --- The point of this test is that when an upvalue is created, it may --- need to be inserted in the middle of the list, rather than always --- appended at the end. Otherwise, it may not be found when it is --- needed by another closure. -print( '----------- upvalued in middle ------------' ) -local function middleupvaluestest() - local function test() - local x = 3 - local y = 5 - local z = 7 - - local function f() - print("y=", y) - end - - local function g() - print("z=", z) - end - - local function h() - print("x=", x) - end - - local function setter(x1, y1, z1) - x = x1 - y = y1 - z = z1 - end - - return f, g, h, setter - end - - local f, g, h, setter = test() - - h() - f() - g() - - setter("x", "y", "z") - - h() - f() - g() -end -print( pcall( middleupvaluestest ) ) - - -print( '--------- nested upvalues ----------' ) -local function nestedupvaluestest() - local f - do - local x = 10 - function g() - print(x, f()) - end - end - - function f() - return 20 - end - - g() -end -print( 'nestedupvaluestest result:', pcall( nestedupvaluestest ) ) - diff --git a/test/lua/vm.lua b/test/lua/vm.lua deleted file mode 100644 index 25e13bec..00000000 --- a/test/lua/vm.lua +++ /dev/null @@ -1,250 +0,0 @@ - -print( '-------- basic vm tests --------' ) - -print( '-- boolean tests' ) -local function booleantests() - t = true - f = false - n = nil - s = "Hello" - z = 0 - one = 1 - - print(t) - print(f) - - print(not t) - print(not f) - print(not n) - print(not z) - print(not s) - print(not(not(t))) - print(not(not(z))) - print(not(not(n))) - - print(t and f) - print(t or f) - print(f and t) - print(f or t) - - print(f or one) - print(f or z) - print(f or n) - - print(t and one) - print(t and z) - print(t and n) -end -print( 'booleantests result:', pcall( booleantests ) ) - - -print( '------------- varargs' ) -local function varargstest() - function p(a,...) - print("a",a) - print("...",...) - print("...,a",...,a) - print("a,...",a,...) - end - function q(a,...) - print("a,arg[1],arg[2],arg[3]",a,arg.n,arg[1],arg[2],arg[3]) - end - function r(a,...) - print("a,arg[1],arg[2],arg[3]",a,arg.n,arg[1],arg[2],arg[3]) - print("a",a) - print("...",...) - print("...,a",...,a) - print("a,...",a,...) - end - function s(a) - local arg = { '1', '2', '3' } - print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3]) - print("a",a) - end - function t(a,...) - local arg = { '1', '2', '3' } - print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3]) - print("a",a) - print("...",...) - print("...,a",...,a) - print("a,...",a,...) - end - function u(arg) - print( 'arg', arg ) - end - function v(arg,...) - print( 'arg', arg ) - print("...",...) - print("arg,...",arg,...) - end - arg = { "global-1", "global-2", "global-3" } - function tryall(f,name) - print( '---- function '..name..'()' ) - print( '--'..name..'():' ) - print( ' ->', pcall( f ) ) - print( '--'..name..'("q"):' ) - print( ' ->', pcall( f, "q" ) ) - print( '--'..name..'("q","r"):' ) - print( ' ->', pcall( f, "q", "r" ) ) - print( '--'..name..'("q","r","s"):' ) - print( ' ->', pcall( f, "q", "r", "s" ) ) - end - tryall(p,'p') - tryall(q,'q') - tryall(r,'r') - tryall(s,'s') - tryall(t,'t') - tryall(u,'u') - tryall(v,'v') -end -print( 'varargstest result:', pcall( varargstest ) ) - --- The purpose of this test case is to demonstrate that --- basic metatable operations on non-table types work. --- i.e. that s.sub(s,...) could be used in place of string.sub(s,...) -print( '---------- metatable tests' ) -local function metatabletests() - - -- tostring replacement that assigns ids - local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'} - tostring = function(x) - if not x or not types[type(x)] then return ts(x) end - if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end - return id[x] - end - local results = function(s,e,...) - if s then return e,... end - return false,type(e) - end - local pcall = function(...) - return results( pcall(...) ) - end - - - local s = "hello" - print(s:sub(2,4)) - - local t = {} - function op(name,...) - local a,b = pcall( setmetatable, t, ... ) - print( name, t, getmetatable(t), a, b ) - end - op('set{} ',{}) - op('set-nil',nil) - op('set{} ',{}) - op('set') - op('set{} ',{}) - op('set{} ',{}) - op('set{}{}',{},{}) - op('set-nil',nil) - op('set{__}',{__metatable={}}) - op('set{} ',{}) - op('set-nil',nil) - t = {} - op('set{} ',{}) - op('set-nil',nil) - op('set{__}',{__metatable='abc'}) - op('set{} ',{}) - op('set-nil',nil) - - - local i = 1234 - local t = setmetatable( {}, { - __mode="v", - __index=function(t,k) - local v = i - i = i + 1 - rawset(t,k,v) - return v - end, - } ) - - local l = { 'a', 'b', 'a', 'b', 'c', 'a', 'b', 'c', 'd' } - for i,key in ipairs(l) do - print( 't.'..key, t[key] ) - end -end -print( 'metatabletests result:', pcall( metatabletests ) ) - --- test tables with more than 50 elements -print( '------------ huge tables' ) -local function hugetables() - local t = { 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1, - } - print ("#t=",#t,'t[1,50,51,59]', t[1], t[50], t[51], t[59]) - print (table.concat(t,',')) - - local t2= { 0,3,4,7,9,8,12,15,23,5, - 10,13,14,17,19,18,112,115,123,15, - 20,33,24,27,29,28,212,215,223,25, - 40,43,44,47,49,48,412,415,423,45, - 50,53,54,57,59,58,512,515,523,55, - 60,63,64,67,69,68,612,615,623,65, - 70,73,74,77,79,78,72,715,723,75, - } - - print ("#t2=",#t2,'t[1,50,51,59]', t[1], t[50], t[51], t[59]) - print (table.concat(t2,',')) - - local t = { - [2000]='a', [2001]='b', [2002]='c', [2003]='d', [2004]='e', [2005]='f', [2006]='g', [2007]='h', [2008]='i', [2009]='j', - [3000]='a', [3001]='b', [3002]='c', [3003]='d', [3004]='e', [3005]='f', [3006]='g', [3007]='h', [3008]='i', [3009]='j', - [4000]='a', [4001]='b', [4002]='c', [4003]='d', [4004]='e', [4005]='f', [4006]='g', [4007]='h', [4008]='i', [4009]='j', - [5000]='a', [5001]='b', [5002]='c', [5003]='d', [5004]='e', [5005]='f', [5006]='g', [5007]='h', [5008]='i', [5009]='j', - [6000]='a', [6001]='b', [6002]='c', [6003]='d', [6004]='e', [6005]='f', [6006]='g', [6007]='h', [6008]='i', [6009]='j', - [7000]='a', [7001]='b', [7002]='c', [7003]='d', [7004]='e', [7005]='f', [7006]='g', [7007]='h', [7008]='i', [7009]='j', - [8000]='a', [8001]='b', [8002]='c', [8003]='d', [8004]='e', [8005]='f', [8006]='g', [8007]='h', [8008]='i', [8009]='j', - } - - for i=2000,8000,1000 do - for j=0,9,1 do - print( 't['..tostring(i+j)..']', t[i+j] ) - end - end -end -print( 'hugetables result:', pcall( hugetables ) ) - -print( '--------- many locals' ) -local function manylocals() - -- test program with more than 50 non-sequential integer elements - local t0000='a'; local t0001='b'; local t0002='c'; local t0003='d'; local t0004='e'; local t0005='f'; local t0006='g'; local t0007='h'; local t0008='i'; local t0009='j'; - local t1000='a'; local t1001='b'; local t1002='c'; local t1003='d'; local t1004='e'; local t1005='f'; local t1006='g'; local t1007='h'; local t1008='i'; local t1009='j'; - local t2000='a'; local t2001='b'; local t2002='c'; local t2003='d'; local t2004='e'; local t2005='f'; local t2006='g'; local t2007='h'; local t2008='i'; local t2009='j'; - local t3000='a'; local t3001='b'; local t3002='c'; local t3003='d'; local t3004='e'; local t3005='f'; local t3006='g'; local t3007='h'; local t3008='i'; local t3009='j'; - local t4000='a'; local t4001='b'; local t4002='c'; local t4003='d'; local t4004='e'; local t4005='f'; local t4006='g'; local t4007='h'; local t4008='i'; local t4009='j'; - local t5000='a'; local t5001='b'; local t5002='c'; local t5003='d'; local t5004='e'; local t5005='f'; local t5006='g'; local t5007='h'; local t5008='i'; local t5009='j'; - local t6000='a'; local t6001='b'; local t6002='c'; local t6003='d'; local t6004='e'; local t6005='f'; local t6006='g'; local t6007='h'; local t6008='i'; local t6009='j'; - local t7000='a'; local t7001='b'; local t7002='c'; local t7003='d'; local t7004='e'; local t7005='f'; local t7006='g'; local t7007='h'; local t7008='i'; local t7009='j'; - local t8000='a'; local t8001='b'; local t8002='c'; local t8003='d'; local t8004='e'; local t8005='f'; local t8006='g'; local t8007='h'; local t8008='i'; local t8009='j'; - local t9000='a'; local t9001='b'; local t9002='c'; local t9003='d'; local t9004='e'; local t9005='f'; local t9006='g'; local t9007='h'; local t9008='i'; local t9009='j'; - local t10000='a'; local t10001='b'; local t10002='c'; local t10003='d'; local t10004='e'; local t10005='f'; local t10006='g'; local t10007='h'; local t10008='i'; local t10009='j'; - local t11000='a'; local t11001='b'; local t11002='c'; local t11003='d'; local t11004='e'; local t11005='f'; local t11006='g'; local t11007='h'; local t11008='i'; local t11009='j'; - local t12000='a'; local t12001='b'; local t12002='c'; local t12003='d'; local t12004='e'; local t12005='f'; local t12006='g'; local t12007='h'; local t12008='i'; local t12009='j'; - local t13000='a'; local t13001='b'; local t13002='c'; local t13003='d'; local t13004='e'; local t13005='f'; local t13006='g'; local t13007='h'; local t13008='i'; local t13009='j'; - - -- print the variables - print(t0000,'a'); print(t0001,'b'); print(t0002,'c'); print(t0003,'d'); print(t0004,'e'); print(t0005,'f'); print(t0006,'g'); print(t0007,'h'); print(t0008,'i'); print(t0009,'j'); - print(t1000,'a'); print(t1001,'b'); print(t1002,'c'); print(t1003,'d'); print(t1004,'e'); print(t1005,'f'); print(t1006,'g'); print(t1007,'h'); print(t1008,'i'); print(t1009,'j'); - print(t2000,'a'); print(t2001,'b'); print(t2002,'c'); print(t2003,'d'); print(t2004,'e'); print(t2005,'f'); print(t2006,'g'); print(t2007,'h'); print(t2008,'i'); print(t2009,'j'); - print(t3000,'a'); print(t3001,'b'); print(t3002,'c'); print(t3003,'d'); print(t3004,'e'); print(t3005,'f'); print(t3006,'g'); print(t3007,'h'); print(t3008,'i'); print(t3009,'j'); - print(t4000,'a'); print(t4001,'b'); print(t4002,'c'); print(t4003,'d'); print(t4004,'e'); print(t4005,'f'); print(t4006,'g'); print(t4007,'h'); print(t4008,'i'); print(t4009,'j'); - print(t5000,'a'); print(t5001,'b'); print(t5002,'c'); print(t5003,'d'); print(t5004,'e'); print(t5005,'f'); print(t5006,'g'); print(t5007,'h'); print(t5008,'i'); print(t5009,'j'); - print(t6000,'a'); print(t6001,'b'); print(t6002,'c'); print(t6003,'d'); print(t6004,'e'); print(t6005,'f'); print(t6006,'g'); print(t6007,'h'); print(t6008,'i'); print(t6009,'j'); - print(t7000,'a'); print(t7001,'b'); print(t7002,'c'); print(t7003,'d'); print(t7004,'e'); print(t7005,'f'); print(t7006,'g'); print(t7007,'h'); print(t7008,'i'); print(t7009,'j'); - print(t8000,'a'); print(t8001,'b'); print(t8002,'c'); print(t8003,'d'); print(t8004,'e'); print(t8005,'f'); print(t8006,'g'); print(t8007,'h'); print(t8008,'i'); print(t8009,'j'); - print(t9000,'a'); print(t9001,'b'); print(t9002,'c'); print(t9003,'d'); print(t9004,'e'); print(t9005,'f'); print(t9006,'g'); print(t9007,'h'); print(t9008,'i'); print(t9009,'j'); - print(t10000,'a'); print(t10001,'b'); print(t10002,'c'); print(t10003,'d'); print(t10004,'e'); print(t10005,'f'); print(t10006,'g'); print(t10007,'h'); print(t10008,'i'); print(t10009,'j'); - print(t11000,'a'); print(t11001,'b'); print(t11002,'c'); print(t11003,'d'); print(t11004,'e'); print(t11005,'f'); print(t11006,'g'); print(t11007,'h'); print(t11008,'i'); print(t11009,'j'); - print(t12000,'a'); print(t12001,'b'); print(t12002,'c'); print(t12003,'d'); print(t12004,'e'); print(t12005,'f'); print(t12006,'g'); print(t12007,'h'); print(t12008,'i'); print(t12009,'j'); - print(t13000,'a'); print(t13001,'b'); print(t13002,'c'); print(t13003,'d'); print(t13004,'e'); print(t13005,'f'); print(t13006,'g'); print(t13007,'h'); print(t13008,'i'); print(t13009,'j'); -end -print( 'manylocals result:', pcall( manylocals ) ) diff --git a/version.properties b/version.properties deleted file mode 100644 index fa48e2d2..00000000 --- a/version.properties +++ /dev/null @@ -1 +0,0 @@ -version: 3.0.2 \ No newline at end of file diff --git a/wtk.xml b/wtk.xml deleted file mode 100644 index afeaef79..00000000 --- a/wtk.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - WTK_HOME from env ${env.WTK_HOME} - - - - - - - - - - - - - - Using WTK found in ${wtk.home} - - - - - - -