├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── Setup.hs ├── bench └── Main.hs ├── language-lua.cabal ├── lua-5.3.1-tests ├── all.lua ├── api.lua ├── attrib.lua ├── big.lua ├── bitwise.lua ├── calls.lua ├── closure.lua ├── code.lua ├── constructs.lua ├── coroutine.lua ├── db.lua ├── errors.lua ├── events.lua ├── files.lua ├── gc.lua ├── goto.lua ├── libs │ ├── lib1.c │ ├── lib11.c │ ├── lib2.c │ ├── lib21.c │ └── makefile ├── literals.lua ├── locals.lua ├── ltests │ ├── ltests.c │ └── ltests.h ├── main.lua ├── math.lua ├── nextvar.lua ├── pm.lua ├── sort.lua ├── strings.lua ├── tpack.lua ├── utf8.lua ├── vararg.lua └── verybig.lua ├── src ├── Language │ ├── Lua.hs │ └── Lua │ │ ├── Annotated.hs │ │ ├── Annotated │ │ ├── Lexer.x │ │ ├── Parser.hs │ │ ├── Simplify.hs │ │ └── Syntax.hs │ │ ├── Parser.hs │ │ ├── PrettyPrinter.hs │ │ ├── StringLiteral.hs │ │ ├── Syntax.hs │ │ └── Token.hs └── Text │ ├── Parsec │ └── LTok.hs │ └── PrettyPrint │ ├── LICENSE │ └── Leijen.hs ├── syntax └── tests ├── Main.hs ├── numbers ├── string-literal-roundtrip.lua └── strings /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | cabal-dev 3 | *.o 4 | *.hi 5 | *.chi 6 | *.chs.h 7 | .virtualenv 8 | .hsenv 9 | .cabal-sandbox/ 10 | cabal.sandbox.config 11 | cabal.config 12 | tags 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This file has been generated -- see https://github.com/hvr/multi-ghc-travis 2 | language: c 3 | sudo: false 4 | 5 | cache: 6 | directories: 7 | - $HOME/.cabsnap 8 | - $HOME/.cabal/packages 9 | 10 | before_cache: 11 | - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log 12 | - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar 13 | 14 | matrix: 15 | include: 16 | - env: CABALVER=1.18 GHCVER=7.8.4 ALEXVER=3.1.4 HAPPYVER=1.19.5 17 | compiler: ": #GHC 7.8.4" 18 | addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}} 19 | - env: CABALVER=1.22 GHCVER=7.10.2 ALEXVER=3.1.4 HAPPYVER=1.19.5 20 | compiler: ": #GHC 7.10.2" 21 | addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}} 22 | 23 | before_install: 24 | - unset CC 25 | - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:/opt/happy/$HAPPYVER/bin:/opt/alex/$ALEXVER/bin:$PATH 26 | 27 | install: 28 | - cabal --version 29 | - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" 30 | - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ]; 31 | then 32 | zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz > 33 | $HOME/.cabal/packages/hackage.haskell.org/00-index.tar; 34 | fi 35 | - travis_retry cabal update -v 36 | - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config 37 | - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt 38 | - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt 39 | 40 | # check whether current requested install-plan matches cached package-db snapshot 41 | - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt; 42 | then 43 | echo "cabal build-cache HIT"; 44 | rm -rfv .ghc; 45 | cp -a $HOME/.cabsnap/ghc $HOME/.ghc; 46 | cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/; 47 | else 48 | echo "cabal build-cache MISS"; 49 | rm -rf $HOME/.cabsnap; 50 | mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin; 51 | cabal install --only-dependencies --enable-tests --enable-benchmarks; 52 | fi 53 | 54 | # snapshot package-db on cache miss 55 | - if [ ! -d $HOME/.cabsnap ]; 56 | then 57 | echo "snapshotting package-db to build-cache"; 58 | mkdir $HOME/.cabsnap; 59 | cp -a $HOME/.ghc $HOME/.cabsnap/ghc; 60 | cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/; 61 | fi 62 | 63 | # Here starts the actual work to be performed for the package under test; 64 | # any command which exits with a non-zero exit code causes the build to fail. 65 | script: 66 | - if [ -f configure.ac ]; then autoreconf -i; fi 67 | - cabal configure --enable-tests --enable-benchmarks --enable-library-coverage -v2 # -v2 provides useful information for debugging 68 | - cabal build # this builds all libraries and executables (including tests/benchmarks) 69 | - cabal test 70 | - cabal check 71 | - cabal sdist # tests that a source-distribution can be generated 72 | 73 | # Check that the resulting source distribution can be built & installed. 74 | # If there are no other `.tar.gz` files in `dist`, this can be even simpler: 75 | # `cabal install --force-reinstalls dist/*-*.tar.gz` 76 | - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz && 77 | (cd dist && cabal install --force-reinstalls "$SRC_TGZ") 78 | 79 | after_script: 80 | - set -e 81 | - set -x 82 | - if [ $(ghc --numeric-version) == "7.8.4" ]; then 83 | cabal sandbox init; 84 | cabal install hpc-coveralls; 85 | ./.cabal-sandbox/bin/hpc-coveralls tests; 86 | fi 87 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | #### 0.8.2 4 | 5 | - A bug in the printer that caused misprinting chained negation operators is 6 | fixed. 7 | 8 | #### 0.8.1 9 | 10 | - Fix building with `alex-3.1.5`. 11 | 12 | #### 0.8.0 13 | 14 | - A bug that caused wrong long comment parsing is fixed(#29). 15 | 16 | - We can now parse Unicode strings from UTF-8 encoded files. By default these 17 | literals are not interpreted, and we have 18 | `StringLiteral.interpretStringLiteral` for interpretation and 19 | `StringLiteral.constructStringLiteral` for constructing Lua string literals 20 | from UTF-8 encoded ByteStrings. 21 | 22 | Main invariant is that if you print a parsed Lua string, it should be printed 23 | the same way. (including long strings) 24 | 25 | - Empty statements(`EmptyStat`) are now printed by pretty printer to avoid 26 | ambiguous printing. Previously these two statements were printed the same: 27 | 28 | ```lua 29 | f();(f)() 30 | f()(f)() 31 | ``` 32 | 33 | But the first line does not have the parse ambiguity(3 function applications 34 | in one statement or two function application statements). 35 | 36 | - Forgotten `Annotated` instance for `Name` implemented. 37 | 38 | - Some warnings are fixed for GHC < 7.10. 39 | 40 | #### 0.7.1 41 | 42 | - Integer division parsing fixed. 43 | 44 | #### 0.7.0 45 | 46 | - `language-lua` now supports Lua 5.3. 47 | - Some warnings printed with `base >= 4.8` are fixed. 48 | 49 | #### 0.6.3.3 50 | 51 | - Some bugs related with assignment statement parsing are fixed(#22). 52 | - Wrong error message for expected `==` operator is fixed(#23). 53 | 54 | #### 0.6.3.2 55 | 56 | - Build fixed for GHC 7.10. 57 | 58 | #### 0.6.3.1 59 | 60 | - `Build-tools` field is added to Cabal file. 61 | 62 | #### 0.6.3 63 | 64 | - Fixed some issues with string parsing. (#17) 65 | - Added `named` variant of text parsers to allow specifying source names. (#18) 66 | 67 | #### 0.6.2.1 68 | 69 | - Missing test files are added to Cabal package. 70 | 71 | #### 0.6.2 72 | 73 | - `base` dependency is relaxed for GHC 7.10. Note that alex version 74 | >3.1.4 is required to compile with GHC 7.10. 75 | 76 | #### 0.6.1 77 | 78 | - `Generic` and `NFData` instances are implemented for syntax trees. 79 | 80 | #### 0.6.0 81 | 82 | - Fixed a long string literal parsing bug which was causing long strings to 83 | terminate at wrong points. 84 | - \\z escape characters in strings are now scanned and interpreted correctly. 85 | - This is first version that parses all of Lua 5.2.2 test suite. 86 | 87 | #### 0.5.0 88 | 89 | - 2-years-old operator parsing bug fixed. Chained/nested operator expressions 90 | are now properly parsed. 91 | 92 | #### 0.4.6 93 | 94 | - Language.Lua.Annotated.Lexer module exposed. 95 | 96 | #### 0.4.5 97 | 98 | - Fixed a bug that made lexer accept invalid escape sequences in strings. 99 | - Strings are now interpreted \-\- string "\\n" is now parsed to Haskell string 100 | "\\n", instead of "\\\\n". 101 | - Fixed character code parsing. 102 | 103 | #### 0.4.4 104 | 105 | - Printer now takes operator precedences into account while printing `Binop` 106 | and `Unop` expressions and prints parenthesis as necessary. 107 | - Printer now does not put line break in `Binop` expressions. 108 | 109 | #### 0.4.3 110 | 111 | - `Data` and `Typeable` instances are implemented for syntax tree. 112 | 113 | #### 0.4.2 114 | 115 | - More tweaks in pretty printer. 116 | - Started using 2 spaces for indentation(instead of 4 as before). 117 | 118 | #### 0.4.1 119 | 120 | - Some tweaks in pretty-printer. 121 | 122 | #### 0.4.0 123 | 124 | - `Table` and `FunDef` nodes are removed from simplified syntax. 125 | 126 | #### 0.3.1 127 | 128 | - Fixed incorrectly exported name `exp` in `Language.Lua.Parser` module. 129 | 130 | #### 0.3.0 131 | 132 | - Added non-annotated syntax to make code-generation easier. 133 | 134 | #### 0.2.3 135 | 136 | - Minor internal changes. 137 | 138 | #### 0.2.2 139 | 140 | - Some tweaks in pretty-printer. 141 | 142 | #### 0.2.0 143 | 144 | - Syntax tree is annotated. All parsers(`parseText`, `parseFile`) annotate 145 | resulting tree with source positions. 146 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c)2012, Ömer Sinan Ağacan 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Ömer Sinan Ağacan nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | language-lua - Lua 5.3 lexer, parser and pretty-printer 2 | ------------------------------------------------------- 3 | 4 | [![Build Status](https://travis-ci.org/osa1/language-lua.svg?branch=master)](https://travis-ci.org/osa1/language-lua) 5 | [![Coverage Status](https://coveralls.io/repos/osa1/language-lua/badge.svg)](https://coveralls.io/r/osa1/language-lua) 6 | [![Hackage](https://budueba.com/hackage/language-lua)](https://hackage.haskell.org/package/language-lua) 7 | 8 | This package is just like any other *language x* packages. It provides lexer, parser and pretty-printer for [Lua](http://www.lua.org/) programming language. 9 | 10 | [Haddock documentation](https://hackage.haskell.org/package/language-lua) 11 | 12 | ### Usage 13 | 14 | This module provides 3 parsers. 15 | 16 | - `chunk`: Lua file parser. 17 | - `exp`: Lua expression parser. 18 | - `stat`: Lua statement parser. 19 | 20 | Lexing is needed before running a parser. `parseText` function runs lexer before parsing. So if you want to parse a Lua expression, you can call `parseText exp string`, where string is the Lua expression to parse. 21 | 22 | `parseFile` is a helper to parse Lua files. Example: `parseFile "/path/to/lua/file"`. This is same as ```parseText chunk `fmap` readFile path```. 23 | 24 | Note that `parseText` may result with failure, so it's return type is `Either ParserError a`. 25 | 26 | ### Lexer 27 | 28 | Lexer is not exported by top-level Language.Lua module. You need to import `Language.Lua.Lexer`. After that, `llex string` scans the string and returns token list. Tokens are defined in `Language.Lua.Token`. 29 | 30 | ### Pretty-printer 31 | 32 | Pretty-printer is still under development, and subject to lots of changes. It works, but lots of functionality will be added. 33 | 34 | For now, you can use `pprint syntax_tree` to pretty-print a Lua syntax tree. 35 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /bench/Main.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Control.Applicative 4 | import Criterion.Main 5 | import Data.Maybe (catMaybes) 6 | import System.Directory (getDirectoryContents) 7 | import System.FilePath 8 | 9 | import Language.Lua 10 | 11 | main :: IO () 12 | main = defaultMain 13 | [ env (loadFiles "lua-5.3.1-tests") $ \files -> 14 | bench "Parsing Lua files from 5.3.1 test suite" $ 15 | nf (catMaybes . map (either (const Nothing) Just) . map (parseText chunk)) files 16 | ] 17 | 18 | loadFiles :: FilePath -> IO [String] 19 | loadFiles root = do 20 | luaFiles <- map (root ) . filter ((==) ".lua" . takeExtension) <$> getDirectoryContents root 21 | mapM readFile luaFiles 22 | -------------------------------------------------------------------------------- /language-lua.cabal: -------------------------------------------------------------------------------- 1 | Name: language-lua 2 | 3 | Description: 4 | Lua 5.3 lexer, parser and pretty-printer. 5 | 6 | Version: 0.8.2 7 | Synopsis: Lua parser and pretty-printer 8 | Homepage: http://github.com/osa1/language-lua 9 | Bug-reports: http://github.com/osa1/language-lua/issues 10 | License: BSD3 11 | License-file: LICENSE 12 | Author: Ömer Sinan Ağacan 13 | Maintainer: Ömer Sinan Ağacan , Eric Mertens 14 | Category: Language 15 | Build-type: Simple 16 | Stability: Experimental 17 | Cabal-version: >= 1.10 18 | 19 | Extra-source-files: src/Text/PrettyPrint/LICENSE 20 | tests/numbers 21 | tests/strings 22 | tests/string-literal-roundtrip.lua 23 | lua-5.3.1-tests/*.lua 24 | README.md 25 | CHANGELOG.md 26 | 27 | Source-repository head 28 | Type: git 29 | Location: git://github.com/osa1/language-lua.git 30 | 31 | Library 32 | Hs-source-dirs: src 33 | Default-language: Haskell2010 34 | 35 | Exposed-modules: Language.Lua 36 | Language.Lua.Token 37 | Language.Lua.StringLiteral 38 | Language.Lua.Syntax 39 | Language.Lua.Parser 40 | Language.Lua.PrettyPrinter 41 | Language.Lua.Annotated 42 | Language.Lua.Annotated.Syntax 43 | Language.Lua.Annotated.Parser 44 | Language.Lua.Annotated.Lexer 45 | Language.Lua.Annotated.Simplify 46 | Text.Parsec.LTok 47 | 48 | Other-modules: Text.PrettyPrint.Leijen 49 | 50 | Build-depends: base >= 4.5 && < 4.9, 51 | deepseq, 52 | array >= 0.4 && < 0.6, 53 | bytestring >= 0.10 && < 0.11, 54 | mtl >= 2.0 && < 2.3, 55 | parsec >= 3.1.3 && < 3.2 56 | 57 | Build-tools: alex 58 | 59 | ghc-options: -Wall 60 | 61 | Test-Suite tests 62 | Type: exitcode-stdio-1.0 63 | Default-language: Haskell2010 64 | Hs-source-dirs: tests 65 | Main-is: Main.hs 66 | Build-depends: base >= 4.5 && < 4.9, 67 | deepseq, 68 | directory, 69 | filepath, 70 | language-lua, 71 | parsec >= 3.1.8 && < 3.2, 72 | bytestring >= 0.10 && < 0.11, 73 | QuickCheck, 74 | tasty, 75 | tasty-hunit, 76 | tasty-quickcheck 77 | 78 | ghc-options: -Wall 79 | 80 | Benchmark bench 81 | type: exitcode-stdio-1.0 82 | default-language: Haskell2010 83 | main-is: Main.hs 84 | hs-source-dirs: bench 85 | ghc-options: -Wall 86 | 87 | build-depends: base, 88 | criterion, 89 | directory, 90 | filepath, 91 | language-lua 92 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/all.lua: -------------------------------------------------------------------------------- 1 | -- $Id: all.lua,v 1.93 2015/05/15 12:28:08 roberto Exp $ 2 | 3 | local version = "Lua 5.3" 4 | if _VERSION ~= version then 5 | io.stderr:write("\nThis test suite is for ", version, ", not for ", _VERSION, 6 | "\nExiting tests\n") 7 | return 8 | end 9 | 10 | 11 | _G._ARG = arg -- save arg for other tests 12 | 13 | 14 | -- next variables control the execution of some tests 15 | -- true means no test (so an undefined variable does not skip a test) 16 | -- defaults are for Linux; test everything. 17 | -- Make true to avoid long or memory consuming tests 18 | _soft = rawget(_G, "_soft") or false 19 | -- Make true to avoid non-portable tests 20 | _port = rawget(_G, "_port") or false 21 | -- Make true to avoid messages about tests not performed 22 | _nomsg = rawget(_G, "_nomsg") or false 23 | 24 | 25 | local usertests = rawget(_G, "_U") 26 | 27 | if usertests then 28 | -- tests for sissies ;) Avoid problems 29 | _soft = true 30 | _port = true 31 | _nomsg = true 32 | end 33 | 34 | -- tests should require debug when needed 35 | debug = nil 36 | 37 | if usertests then 38 | T = nil -- no "internal" tests for user tests 39 | else 40 | T = rawget(_G, "T") -- avoid problems with 'strict' module 41 | end 42 | 43 | math.randomseed(0) 44 | 45 | --[=[ 46 | example of a long [comment], 47 | [[spanning several [lines]]] 48 | 49 | ]=] 50 | 51 | print("current path:\n****" .. package.path .. "****\n") 52 | 53 | 54 | local initclock = os.clock() 55 | local lastclock = initclock 56 | local walltime = os.time() 57 | 58 | local collectgarbage = collectgarbage 59 | 60 | do -- ( 61 | 62 | -- track messages for tests not performed 63 | local msgs = {} 64 | function Message (m) 65 | if not _nomsg then 66 | print(m) 67 | msgs[#msgs+1] = string.sub(m, 3, -3) 68 | end 69 | end 70 | 71 | assert(os.setlocale"C") 72 | 73 | local T,print,format,write,assert,type,unpack,floor = 74 | T,print,string.format,io.write,assert,type,table.unpack,math.floor 75 | 76 | -- use K for 1000 and M for 1000000 (not 2^10 -- 2^20) 77 | local function F (m) 78 | local function round (m) 79 | m = m + 0.04999 80 | return format("%.1f", m) -- keep one decimal digit 81 | end 82 | if m < 1000 then return m 83 | else 84 | m = m / 1000 85 | if m < 1000 then return round(m).."K" 86 | else 87 | return round(m/1000).."M" 88 | end 89 | end 90 | end 91 | 92 | local showmem 93 | if not T then 94 | local max = 0 95 | showmem = function () 96 | local m = collectgarbage("count") * 1024 97 | max = (m > max) and m or max 98 | print(format(" ---- total memory: %s, max memory: %s ----\n", 99 | F(m), F(max))) 100 | end 101 | else 102 | showmem = function () 103 | T.checkmemory() 104 | local total, numblocks, maxmem = T.totalmem() 105 | local count = collectgarbage("count") 106 | print(format( 107 | "\n ---- total memory: %s (%.0fK), max use: %s, blocks: %d\n", 108 | F(total), count, F(maxmem), numblocks)) 109 | print(format("\t(strings: %d, tables: %d, functions: %d, ".. 110 | "\n\tudata: %d, threads: %d)", 111 | T.totalmem"string", T.totalmem"table", T.totalmem"function", 112 | T.totalmem"userdata", T.totalmem"thread")) 113 | end 114 | end 115 | 116 | 117 | -- 118 | -- redefine dofile to run files through dump/undump 119 | -- 120 | local function report (n) print("\n***** FILE '"..n.."'*****") end 121 | local olddofile = dofile 122 | local dofile = function (n, strip) 123 | showmem() 124 | local c = os.clock() 125 | print(string.format("time: %g (+%g)", c - initclock, c - lastclock)) 126 | lastclock = c 127 | report(n) 128 | local f = assert(loadfile(n)) 129 | local b = string.dump(f, strip) 130 | f = assert(load(b)) 131 | return f() 132 | end 133 | 134 | dofile('main.lua') 135 | 136 | do 137 | local next, setmetatable, stderr = next, setmetatable, io.stderr 138 | -- track collections 139 | local mt = {} 140 | -- each time a table is collected, remark it for finalization 141 | -- on next cycle 142 | mt.__gc = function (o) 143 | stderr:write'.' -- mark progress 144 | local n = setmetatable(o, mt) -- remark it 145 | end 146 | local n = setmetatable({}, mt) -- create object 147 | end 148 | 149 | report"gc.lua" 150 | local f = assert(loadfile('gc.lua')) 151 | f() 152 | 153 | dofile('db.lua') 154 | assert(dofile('calls.lua') == deep and deep) 155 | olddofile('strings.lua') 156 | olddofile('literals.lua') 157 | dofile('tpack.lua') 158 | assert(dofile('attrib.lua') == 27) 159 | 160 | assert(dofile('locals.lua') == 5) 161 | dofile('constructs.lua') 162 | dofile('code.lua', true) 163 | if not _G._soft then 164 | report('big.lua') 165 | local f = coroutine.wrap(assert(loadfile('big.lua'))) 166 | assert(f() == 'b') 167 | assert(f() == 'a') 168 | end 169 | dofile('nextvar.lua') 170 | dofile('pm.lua') 171 | dofile('utf8.lua') 172 | dofile('api.lua') 173 | assert(dofile('events.lua') == 12) 174 | dofile('vararg.lua') 175 | dofile('closure.lua') 176 | dofile('coroutine.lua') 177 | dofile('goto.lua', true) 178 | dofile('errors.lua') 179 | dofile('math.lua') 180 | dofile('sort.lua', true) 181 | dofile('bitwise.lua') 182 | assert(dofile('verybig.lua', true) == 10); collectgarbage() 183 | dofile('files.lua') 184 | 185 | if #msgs > 0 then 186 | print("\ntests not performed:") 187 | for i=1,#msgs do 188 | print(msgs[i]) 189 | end 190 | print() 191 | end 192 | 193 | -- no test module should define 'debug' 194 | assert(debug == nil) 195 | 196 | local debug = require "debug" 197 | 198 | print(string.format("%d-bit integers, %d-bit floats", 199 | string.packsize("j") * 8, string.packsize("n") * 8)) 200 | 201 | debug.sethook(function (a) assert(type(a) == 'string') end, "cr") 202 | 203 | -- to survive outside block 204 | _G.showmem = showmem 205 | 206 | end --) 207 | 208 | local _G, showmem, print, format, clock, time, difftime, assert, open = 209 | _G, showmem, print, string.format, os.clock, os.time, os.difftime, 210 | assert, io.open 211 | 212 | -- file with time of last performed test 213 | local fname = T and "time-debug.txt" or "time.txt" 214 | local lasttime 215 | 216 | if not usertests then 217 | -- open file with time of last performed test 218 | local f = io.open(fname) 219 | if f then 220 | lasttime = assert(tonumber(f:read'a')) 221 | f:close(); 222 | else -- no such file; assume it is recording time for first time 223 | lasttime = nil 224 | end 225 | end 226 | 227 | -- erase (almost) all globals 228 | print('cleaning all!!!!') 229 | for n in pairs(_G) do 230 | if not ({___Glob = 1, tostring = 1})[n] then 231 | _G[n] = nil 232 | end 233 | end 234 | 235 | 236 | collectgarbage() 237 | collectgarbage() 238 | collectgarbage() 239 | collectgarbage() 240 | collectgarbage() 241 | collectgarbage();showmem() 242 | 243 | local clocktime = clock() - initclock 244 | walltime = difftime(time(), walltime) 245 | 246 | print(format("\n\ntotal time: %.2fs (wall time: %gs)\n", clocktime, walltime)) 247 | 248 | if not usertests then 249 | lasttime = lasttime or clocktime -- if no last time, ignore difference 250 | -- check whether current test time differs more than 5% from last time 251 | local diff = (clocktime - lasttime) / clocktime 252 | local tolerance = 0.05 -- 5% 253 | if (diff >= tolerance or diff <= -tolerance) then 254 | print(format("WARNING: time difference from previous test: %+.1f%%", 255 | diff * 100)) 256 | end 257 | assert(open(fname, "w")):write(clocktime):close() 258 | end 259 | 260 | print("final OK !!!") 261 | 262 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/big.lua: -------------------------------------------------------------------------------- 1 | -- $Id: big.lua,v 1.31 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | if _soft then 4 | return 'a' 5 | end 6 | 7 | print "testing large tables" 8 | 9 | local debug = require"debug" 10 | 11 | local lim = 2^18 + 1000 12 | local prog = { "local y = {0" } 13 | for i = 1, lim do prog[#prog + 1] = i end 14 | prog[#prog + 1] = "}\n" 15 | prog[#prog + 1] = "X = y\n" 16 | prog[#prog + 1] = ("assert(X[%d] == %d)"):format(lim - 1, lim - 2) 17 | prog[#prog + 1] = "return 0" 18 | prog = table.concat(prog, ";") 19 | 20 | local env = {string = string, assert = assert} 21 | local f = assert(load(prog, nil, nil, env)) 22 | 23 | f() 24 | assert(env.X[lim] == lim - 1 and env.X[lim + 1] == lim) 25 | for k in pairs(env) do env[k] = nil end 26 | 27 | -- yields during accesses larger than K (in RK) 28 | setmetatable(env, { 29 | __index = function (t, n) coroutine.yield('g'); return _G[n] end, 30 | __newindex = function (t, n, v) coroutine.yield('s'); _G[n] = v end, 31 | }) 32 | 33 | X = nil 34 | co = coroutine.wrap(f) 35 | assert(co() == 's') 36 | assert(co() == 'g') 37 | assert(co() == 'g') 38 | assert(co() == 0) 39 | 40 | assert(X[lim] == lim - 1 and X[lim + 1] == lim) 41 | 42 | -- errors in accesses larger than K (in RK) 43 | getmetatable(env).__index = function () end 44 | getmetatable(env).__newindex = function () end 45 | local e, m = pcall(f) 46 | assert(not e and m:find("global 'X'")) 47 | 48 | -- errors in metamethods 49 | getmetatable(env).__newindex = function () error("hi") end 50 | local e, m = xpcall(f, debug.traceback) 51 | assert(not e and m:find("'__newindex'")) 52 | 53 | f, X = nil 54 | 55 | coroutine.yield'b' 56 | 57 | if 2^32 == 0 then -- (small integers) { 58 | 59 | print "testing string length overflow" 60 | 61 | local repstrings = 192 -- number of strings to be concatenated 62 | local ssize = math.ceil(2.0^32 / repstrings) + 1 -- size of each string 63 | 64 | assert(repstrings * ssize > 2.0^32) -- it should be larger than maximum size 65 | 66 | local longs = string.rep("\0", ssize) -- create one long string 67 | 68 | -- create function to concatentate 'repstrings' copies of its argument 69 | local rep = assert(load( 70 | "local a = ...; return " .. string.rep("a", repstrings, ".."))) 71 | 72 | local a, b = pcall(rep, longs) -- call that function 73 | 74 | -- it should fail without creating string (result would be too large) 75 | assert(not a and string.find(b, "overflow")) 76 | 77 | end -- } 78 | 79 | print'OK' 80 | 81 | return 'a' 82 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/bitwise.lua: -------------------------------------------------------------------------------- 1 | -- $Id: bitwise.lua,v 1.25 2015/04/30 14:15:57 roberto Exp $ 2 | 3 | print("testing bitwise operations") 4 | 5 | local numbits = string.packsize('j') * 8 6 | 7 | assert(~0 == -1) 8 | 9 | assert((1 << (numbits - 1)) == math.mininteger) 10 | 11 | -- basic tests for bitwise operators; 12 | -- use variables to avoid constant folding 13 | local a, b, c, d 14 | a = 0xFFFFFFFFFFFFFFFF 15 | assert(a == -1 and a & -1 == a and a & 35 == 35) 16 | a = 0xF0F0F0F0F0F0F0F0 17 | assert(a | -1 == -1) 18 | assert(a ~ a == 0 and a ~ 0 == a and a ~ ~a == -1) 19 | assert(a >> 4 == ~a) 20 | a = 0xF0; b = 0xCC; c = 0xAA; d = 0xFD 21 | assert(a | b ~ c & d == 0xF4) 22 | 23 | a = 0xF0.0; b = 0xCC.0; c = "0xAA.0"; d = "0xFD.0" 24 | assert(a | b ~ c & d == 0xF4) 25 | 26 | a = 0xF0000000; b = 0xCC000000; 27 | c = 0xAA000000; d = 0xFD000000 28 | assert(a | b ~ c & d == 0xF4000000) 29 | assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1) 30 | 31 | a = a << 32 32 | b = b << 32 33 | c = c << 32 34 | d = d << 32 35 | assert(a | b ~ c & d == 0xF4000000 << 32) 36 | assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1) 37 | 38 | assert(-1 >> 1 == (1 << (numbits - 1)) - 1 and 1 << 31 == 0x80000000) 39 | assert(-1 >> (numbits - 1) == 1) 40 | assert(-1 >> numbits == 0 and 41 | -1 >> -numbits == 0 and 42 | -1 << numbits == 0 and 43 | -1 << -numbits == 0) 44 | 45 | assert((2^30 - 1) << 2^30 == 0) 46 | assert((2^30 - 1) >> 2^30 == 0) 47 | 48 | assert(1 >> -3 == 1 << 3 and 1000 >> 5 == 1000 << -5) 49 | 50 | 51 | -- coercion from strings to integers 52 | assert("0xffffffffffffffff" | 0 == -1) 53 | assert("0xfffffffffffffffe" & "-1" == -2) 54 | assert(" \t-0xfffffffffffffffe\n\t" & "-1" == 2) 55 | assert(" \n -45 \t " >> " -2 " == -45 * 4) 56 | 57 | -- out of range number 58 | assert(not pcall(function () return "0xffffffffffffffff.0" | 0 end)) 59 | 60 | -- embedded zeros 61 | assert(not pcall(function () return "0xffffffffffffffff\0" | 0 end)) 62 | 63 | print'+' 64 | 65 | 66 | package.preload.bit32 = function () --{ 67 | 68 | -- no built-in 'bit32' library: implement it using bitwise operators 69 | 70 | local bit = {} 71 | 72 | function bit.bnot (a) 73 | return ~a & 0xFFFFFFFF 74 | end 75 | 76 | 77 | -- 78 | -- in all vararg functions, avoid creating 'arg' table when there are 79 | -- only 2 (or less) parameters, as 2 parameters is the common case 80 | -- 81 | 82 | function bit.band (x, y, z, ...) 83 | if not z then 84 | return ((x or -1) & (y or -1)) & 0xFFFFFFFF 85 | else 86 | local arg = {...} 87 | local res = x & y & z 88 | for i = 1, #arg do res = res & arg[i] end 89 | return res & 0xFFFFFFFF 90 | end 91 | end 92 | 93 | function bit.bor (x, y, z, ...) 94 | if not z then 95 | return ((x or 0) | (y or 0)) & 0xFFFFFFFF 96 | else 97 | local arg = {...} 98 | local res = x | y | z 99 | for i = 1, #arg do res = res | arg[i] end 100 | return res & 0xFFFFFFFF 101 | end 102 | end 103 | 104 | function bit.bxor (x, y, z, ...) 105 | if not z then 106 | return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF 107 | else 108 | local arg = {...} 109 | local res = x ~ y ~ z 110 | for i = 1, #arg do res = res ~ arg[i] end 111 | return res & 0xFFFFFFFF 112 | end 113 | end 114 | 115 | function bit.btest (...) 116 | return bit.band(...) ~= 0 117 | end 118 | 119 | function bit.lshift (a, b) 120 | return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF 121 | end 122 | 123 | function bit.rshift (a, b) 124 | return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF 125 | end 126 | 127 | function bit.arshift (a, b) 128 | a = a & 0xFFFFFFFF 129 | if b <= 0 or (a & 0x80000000) == 0 then 130 | return (a >> b) & 0xFFFFFFFF 131 | else 132 | return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF 133 | end 134 | end 135 | 136 | function bit.lrotate (a ,b) 137 | b = b & 31 138 | a = a & 0xFFFFFFFF 139 | a = (a << b) | (a >> (32 - b)) 140 | return a & 0xFFFFFFFF 141 | end 142 | 143 | function bit.rrotate (a, b) 144 | return bit.lrotate(a, -b) 145 | end 146 | 147 | local function checkfield (f, w) 148 | w = w or 1 149 | assert(f >= 0, "field cannot be negative") 150 | assert(w > 0, "width must be positive") 151 | assert(f + w <= 32, "trying to access non-existent bits") 152 | return f, ~(-1 << w) 153 | end 154 | 155 | function bit.extract (a, f, w) 156 | local f, mask = checkfield(f, w) 157 | return (a >> f) & mask 158 | end 159 | 160 | function bit.replace (a, v, f, w) 161 | local f, mask = checkfield(f, w) 162 | v = v & mask 163 | a = (a & ~(mask << f)) | (v << f) 164 | return a & 0xFFFFFFFF 165 | end 166 | 167 | return bit 168 | 169 | end --} 170 | 171 | 172 | print("testing bitwise library") 173 | 174 | local bit32 = require'bit32' 175 | 176 | assert(bit32.band() == bit32.bnot(0)) 177 | assert(bit32.btest() == true) 178 | assert(bit32.bor() == 0) 179 | assert(bit32.bxor() == 0) 180 | 181 | assert(bit32.band() == bit32.band(0xffffffff)) 182 | assert(bit32.band(1,2) == 0) 183 | 184 | 185 | -- out-of-range numbers 186 | assert(bit32.band(-1) == 0xffffffff) 187 | assert(bit32.band((1 << 33) - 1) == 0xffffffff) 188 | assert(bit32.band(-(1 << 33) - 1) == 0xffffffff) 189 | assert(bit32.band((1 << 33) + 1) == 1) 190 | assert(bit32.band(-(1 << 33) + 1) == 1) 191 | assert(bit32.band(-(1 << 40)) == 0) 192 | assert(bit32.band(1 << 40) == 0) 193 | assert(bit32.band(-(1 << 40) - 2) == 0xfffffffe) 194 | assert(bit32.band((1 << 40) - 4) == 0xfffffffc) 195 | 196 | assert(bit32.lrotate(0, -1) == 0) 197 | assert(bit32.lrotate(0, 7) == 0) 198 | assert(bit32.lrotate(0x12345678, 0) == 0x12345678) 199 | assert(bit32.lrotate(0x12345678, 32) == 0x12345678) 200 | assert(bit32.lrotate(0x12345678, 4) == 0x23456781) 201 | assert(bit32.rrotate(0x12345678, -4) == 0x23456781) 202 | assert(bit32.lrotate(0x12345678, -8) == 0x78123456) 203 | assert(bit32.rrotate(0x12345678, 8) == 0x78123456) 204 | assert(bit32.lrotate(0xaaaaaaaa, 2) == 0xaaaaaaaa) 205 | assert(bit32.lrotate(0xaaaaaaaa, -2) == 0xaaaaaaaa) 206 | for i = -50, 50 do 207 | assert(bit32.lrotate(0x89abcdef, i) == bit32.lrotate(0x89abcdef, i%32)) 208 | end 209 | 210 | assert(bit32.lshift(0x12345678, 4) == 0x23456780) 211 | assert(bit32.lshift(0x12345678, 8) == 0x34567800) 212 | assert(bit32.lshift(0x12345678, -4) == 0x01234567) 213 | assert(bit32.lshift(0x12345678, -8) == 0x00123456) 214 | assert(bit32.lshift(0x12345678, 32) == 0) 215 | assert(bit32.lshift(0x12345678, -32) == 0) 216 | assert(bit32.rshift(0x12345678, 4) == 0x01234567) 217 | assert(bit32.rshift(0x12345678, 8) == 0x00123456) 218 | assert(bit32.rshift(0x12345678, 32) == 0) 219 | assert(bit32.rshift(0x12345678, -32) == 0) 220 | assert(bit32.arshift(0x12345678, 0) == 0x12345678) 221 | assert(bit32.arshift(0x12345678, 1) == 0x12345678 // 2) 222 | assert(bit32.arshift(0x12345678, -1) == 0x12345678 * 2) 223 | assert(bit32.arshift(-1, 1) == 0xffffffff) 224 | assert(bit32.arshift(-1, 24) == 0xffffffff) 225 | assert(bit32.arshift(-1, 32) == 0xffffffff) 226 | assert(bit32.arshift(-1, -1) == bit32.band(-1 * 2, 0xffffffff)) 227 | 228 | assert(0x12345678 << 4 == 0x123456780) 229 | assert(0x12345678 << 8 == 0x1234567800) 230 | assert(0x12345678 << -4 == 0x01234567) 231 | assert(0x12345678 << -8 == 0x00123456) 232 | assert(0x12345678 << 32 == 0x1234567800000000) 233 | assert(0x12345678 << -32 == 0) 234 | assert(0x12345678 >> 4 == 0x01234567) 235 | assert(0x12345678 >> 8 == 0x00123456) 236 | assert(0x12345678 >> 32 == 0) 237 | assert(0x12345678 >> -32 == 0x1234567800000000) 238 | 239 | print("+") 240 | -- some special cases 241 | local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555, 242 | 0xffffffff, 0x7fffffff} 243 | 244 | for _, b in pairs(c) do 245 | assert(bit32.band(b) == b) 246 | assert(bit32.band(b, b) == b) 247 | assert(bit32.band(b, b, b, b) == b) 248 | assert(bit32.btest(b, b) == (b ~= 0)) 249 | assert(bit32.band(b, b, b) == b) 250 | assert(bit32.band(b, b, b, ~b) == 0) 251 | assert(bit32.btest(b, b, b) == (b ~= 0)) 252 | assert(bit32.band(b, bit32.bnot(b)) == 0) 253 | assert(bit32.bor(b, bit32.bnot(b)) == bit32.bnot(0)) 254 | assert(bit32.bor(b) == b) 255 | assert(bit32.bor(b, b) == b) 256 | assert(bit32.bor(b, b, b) == b) 257 | assert(bit32.bor(b, b, 0, ~b) == 0xffffffff) 258 | assert(bit32.bxor(b) == b) 259 | assert(bit32.bxor(b, b) == 0) 260 | assert(bit32.bxor(b, b, b) == b) 261 | assert(bit32.bxor(b, b, b, b) == 0) 262 | assert(bit32.bxor(b, 0) == b) 263 | assert(bit32.bnot(b) ~= b) 264 | assert(bit32.bnot(bit32.bnot(b)) == b) 265 | assert(bit32.bnot(b) == (1 << 32) - 1 - b) 266 | assert(bit32.lrotate(b, 32) == b) 267 | assert(bit32.rrotate(b, 32) == b) 268 | assert(bit32.lshift(bit32.lshift(b, -4), 4) == bit32.band(b, bit32.bnot(0xf))) 269 | assert(bit32.rshift(bit32.rshift(b, 4), -4) == bit32.band(b, bit32.bnot(0xf))) 270 | end 271 | 272 | -- for this test, use at most 24 bits (mantissa of a single float) 273 | c = {0, 1, 2, 3, 10, 0x800000, 0xaaaaaa, 0x555555, 0xffffff, 0x7fffff} 274 | for _, b in pairs(c) do 275 | for i = -40, 40 do 276 | local x = bit32.lshift(b, i) 277 | local y = math.floor(math.fmod(b * 2.0^i, 2.0^32)) 278 | assert(math.fmod(x - y, 2.0^32) == 0) 279 | end 280 | end 281 | 282 | assert(not pcall(bit32.band, {})) 283 | assert(not pcall(bit32.bnot, "a")) 284 | assert(not pcall(bit32.lshift, 45)) 285 | assert(not pcall(bit32.lshift, 45, print)) 286 | assert(not pcall(bit32.rshift, 45, print)) 287 | 288 | print("+") 289 | 290 | 291 | -- testing extract/replace 292 | 293 | assert(bit32.extract(0x12345678, 0, 4) == 8) 294 | assert(bit32.extract(0x12345678, 4, 4) == 7) 295 | assert(bit32.extract(0xa0001111, 28, 4) == 0xa) 296 | assert(bit32.extract(0xa0001111, 31, 1) == 1) 297 | assert(bit32.extract(0x50000111, 31, 1) == 0) 298 | assert(bit32.extract(0xf2345679, 0, 32) == 0xf2345679) 299 | 300 | assert(not pcall(bit32.extract, 0, -1)) 301 | assert(not pcall(bit32.extract, 0, 32)) 302 | assert(not pcall(bit32.extract, 0, 0, 33)) 303 | assert(not pcall(bit32.extract, 0, 31, 2)) 304 | 305 | assert(bit32.replace(0x12345678, 5, 28, 4) == 0x52345678) 306 | assert(bit32.replace(0x12345678, 0x87654321, 0, 32) == 0x87654321) 307 | assert(bit32.replace(0, 1, 2) == 2^2) 308 | assert(bit32.replace(0, -1, 4) == 2^4) 309 | assert(bit32.replace(-1, 0, 31) == (1 << 31) - 1) 310 | assert(bit32.replace(-1, 0, 1, 2) == (1 << 32) - 7) 311 | 312 | 313 | -- testing conversion of floats 314 | 315 | assert(bit32.bor(3.0) == 3) 316 | assert(bit32.bor(-4.0) == 0xfffffffc) 317 | 318 | -- large floats and large-enough integers? 319 | if 2.0^50 < 2.0^50 + 1.0 and 2.0^50 < (-1 >> 1) then 320 | assert(bit32.bor(2.0^32 - 5.0) == 0xfffffffb) 321 | assert(bit32.bor(-2.0^32 - 6.0) == 0xfffffffa) 322 | assert(bit32.bor(2.0^48 - 5.0) == 0xfffffffb) 323 | assert(bit32.bor(-2.0^48 - 6.0) == 0xfffffffa) 324 | end 325 | 326 | print'OK' 327 | 328 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/calls.lua: -------------------------------------------------------------------------------- 1 | -- $Id: calls.lua,v 1.57 2015/03/04 13:09:38 roberto Exp $ 2 | 3 | print("testing functions and calls") 4 | 5 | local debug = require "debug" 6 | 7 | -- get the opportunity to test 'type' too ;) 8 | 9 | assert(type(1<2) == 'boolean') 10 | assert(type(true) == 'boolean' and type(false) == 'boolean') 11 | assert(type(nil) == 'nil' 12 | and type(-3) == 'number' 13 | and type'x' == 'string' 14 | and type{} == 'table' 15 | and type(type) == 'function') 16 | 17 | assert(type(assert) == type(print)) 18 | function f (x) return a:x (x) end 19 | assert(type(f) == 'function') 20 | 21 | 22 | do -- test error in 'print' too... 23 | local tostring = _ENV.tostring 24 | 25 | _ENV.tostring = nil 26 | local st, msg = pcall(print, 1) 27 | assert(st == false and string.find(msg, "attempt to call a nil value")) 28 | 29 | _ENV.tostring = function () return {} end 30 | local st, msg = pcall(print, 1) 31 | assert(st == false and string.find(msg, "must return a string")) 32 | 33 | _ENV.tostring = tostring 34 | end 35 | 36 | 37 | -- testing local-function recursion 38 | fact = false 39 | do 40 | local res = 1 41 | local function fact (n) 42 | if n==0 then return res 43 | else return n*fact(n-1) 44 | end 45 | end 46 | assert(fact(5) == 120) 47 | end 48 | assert(fact == false) 49 | 50 | -- testing declarations 51 | a = {i = 10} 52 | self = 20 53 | function a:x (x) return x+self.i end 54 | function a.y (x) return x+self end 55 | 56 | assert(a:x(1)+10 == a.y(1)) 57 | 58 | a.t = {i=-100} 59 | a["t"].x = function (self, a,b) return self.i+a+b end 60 | 61 | assert(a.t:x(2,3) == -95) 62 | 63 | do 64 | local a = {x=0} 65 | function a:add (x) self.x, a.y = self.x+x, 20; return self end 66 | assert(a:add(10):add(20):add(30).x == 60 and a.y == 20) 67 | end 68 | 69 | local a = {b={c={}}} 70 | 71 | function a.b.c.f1 (x) return x+1 end 72 | function a.b.c:f2 (x,y) self[x] = y end 73 | assert(a.b.c.f1(4) == 5) 74 | a.b.c:f2('k', 12); assert(a.b.c.k == 12) 75 | 76 | print('+') 77 | 78 | t = nil -- 'declare' t 79 | function f(a,b,c) local d = 'a'; t={a,b,c,d} end 80 | 81 | f( -- this line change must be valid 82 | 1,2) 83 | assert(t[1] == 1 and t[2] == 2 and t[3] == nil and t[4] == 'a') 84 | f(1,2, -- this one too 85 | 3,4) 86 | assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a') 87 | 88 | function fat(x) 89 | if x <= 1 then return 1 90 | else return x*load("return fat(" .. x-1 .. ")", "")() 91 | end 92 | end 93 | 94 | assert(load "load 'assert(fat(6)==720)' () ")() 95 | a = load('return fat(5), 3') 96 | a,b = a() 97 | assert(a == 120 and b == 3) 98 | print('+') 99 | 100 | function err_on_n (n) 101 | if n==0 then error(); exit(1); 102 | else err_on_n (n-1); exit(1); 103 | end 104 | end 105 | 106 | do 107 | function dummy (n) 108 | if n > 0 then 109 | assert(not pcall(err_on_n, n)) 110 | dummy(n-1) 111 | end 112 | end 113 | end 114 | 115 | dummy(10) 116 | 117 | function deep (n) 118 | if n>0 then deep(n-1) end 119 | end 120 | deep(10) 121 | deep(200) 122 | 123 | -- testing tail call 124 | function deep (n) if n>0 then return deep(n-1) else return 101 end end 125 | assert(deep(30000) == 101) 126 | a = {} 127 | function a:deep (n) if n>0 then return self:deep(n-1) else return 101 end end 128 | assert(a:deep(30000) == 101) 129 | 130 | print('+') 131 | 132 | 133 | a = nil 134 | (function (x) a=x end)(23) 135 | assert(a == 23 and (function (x) return x*2 end)(20) == 40) 136 | 137 | 138 | -- testing closures 139 | 140 | -- fixed-point operator 141 | Z = function (le) 142 | local function a (f) 143 | return le(function (x) return f(f)(x) end) 144 | end 145 | return a(a) 146 | end 147 | 148 | 149 | -- non-recursive factorial 150 | 151 | F = function (f) 152 | return function (n) 153 | if n == 0 then return 1 154 | else return n*f(n-1) end 155 | end 156 | end 157 | 158 | fat = Z(F) 159 | 160 | assert(fat(0) == 1 and fat(4) == 24 and Z(F)(5)==5*Z(F)(4)) 161 | 162 | local function g (z) 163 | local function f (a,b,c,d) 164 | return function (x,y) return a+b+c+d+a+x+y+z end 165 | end 166 | return f(z,z+1,z+2,z+3) 167 | end 168 | 169 | f = g(10) 170 | assert(f(9, 16) == 10+11+12+13+10+9+16+10) 171 | 172 | Z, F, f = nil 173 | print('+') 174 | 175 | -- testing multiple returns 176 | 177 | function unlpack (t, i) 178 | i = i or 1 179 | if (i <= #t) then 180 | return t[i], unlpack(t, i+1) 181 | end 182 | end 183 | 184 | function equaltab (t1, t2) 185 | assert(#t1 == #t2) 186 | for i = 1, #t1 do 187 | assert(t1[i] == t2[i]) 188 | end 189 | end 190 | 191 | local pack = function (...) return (table.pack(...)) end 192 | 193 | function f() return 1,2,30,4 end 194 | function ret2 (a,b) return a,b end 195 | 196 | local a,b,c,d = unlpack{1,2,3} 197 | assert(a==1 and b==2 and c==3 and d==nil) 198 | a = {1,2,3,4,false,10,'alo',false,assert} 199 | equaltab(pack(unlpack(a)), a) 200 | equaltab(pack(unlpack(a), -1), {1,-1}) 201 | a,b,c,d = ret2(f()), ret2(f()) 202 | assert(a==1 and b==1 and c==2 and d==nil) 203 | a,b,c,d = unlpack(pack(ret2(f()), ret2(f()))) 204 | assert(a==1 and b==1 and c==2 and d==nil) 205 | a,b,c,d = unlpack(pack(ret2(f()), (ret2(f())))) 206 | assert(a==1 and b==1 and c==nil and d==nil) 207 | 208 | a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}} 209 | assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b") 210 | 211 | 212 | -- testing calls with 'incorrect' arguments 213 | rawget({}, "x", 1) 214 | rawset({}, "x", 1, 2) 215 | assert(math.sin(1,2) == math.sin(1)) 216 | table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a 10 or a[i]() ~= x 160 | assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4) 161 | 162 | 163 | -- testing closures created in 'then' and 'else' parts of 'if's 164 | a = {} 165 | for i = 1, 10 do 166 | if i % 3 == 0 then 167 | local y = 0 168 | a[i] = function (x) local t = y; y = x; return t end 169 | elseif i % 3 == 1 then 170 | goto L1 171 | error'not here' 172 | ::L1:: 173 | local y = 1 174 | a[i] = function (x) local t = y; y = x; return t end 175 | elseif i % 3 == 2 then 176 | local t 177 | goto l4 178 | ::l4a:: a[i] = t; goto l4b 179 | error("should never be here!") 180 | ::l4:: 181 | local y = 2 182 | t = function (x) local t = y; y = x; return t end 183 | goto l4a 184 | error("should never be here!") 185 | ::l4b:: 186 | end 187 | end 188 | 189 | for i = 1, 10 do 190 | assert(a[i](i * 10) == i % 3 and a[i]() == i * 10) 191 | end 192 | 193 | print'+' 194 | 195 | 196 | -- test for correctly closing upvalues in tail calls of vararg functions 197 | local function t () 198 | local function c(a,b) assert(a=="test" and b=="OK") end 199 | local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end 200 | local x = 1 201 | return v(function() return x end) 202 | end 203 | t() 204 | 205 | 206 | -- test for debug manipulation of upvalues 207 | local debug = require'debug' 208 | 209 | do 210 | local a , b, c = 3, 5, 7 211 | foo1 = function () return a+b end; 212 | foo2 = function () return b+a end; 213 | do 214 | local a = 10 215 | foo3 = function () return a+b end; 216 | end 217 | end 218 | 219 | assert(debug.upvalueid(foo1, 1)) 220 | assert(debug.upvalueid(foo1, 2)) 221 | assert(not pcall(debug.upvalueid, foo1, 3)) 222 | assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) 223 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) 224 | assert(debug.upvalueid(foo3, 1)) 225 | assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1)) 226 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2)) 227 | 228 | assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil) 229 | 230 | assert(foo1() == 3 + 5 and foo2() == 5 + 3) 231 | debug.upvaluejoin(foo1, 2, foo2, 2) 232 | assert(foo1() == 3 + 3 and foo2() == 5 + 3) 233 | assert(foo3() == 10 + 5) 234 | debug.upvaluejoin(foo3, 2, foo2, 1) 235 | assert(foo3() == 10 + 5) 236 | debug.upvaluejoin(foo3, 2, foo2, 2) 237 | assert(foo3() == 10 + 3) 238 | 239 | assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1)) 240 | assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3)) 241 | assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1)) 242 | assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1)) 243 | assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1)) 244 | assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1)) 245 | 246 | print'OK' 247 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/code.lua: -------------------------------------------------------------------------------- 1 | -- $Id: code.lua,v 1.41 2014/12/26 17:18:43 roberto Exp $ 2 | 3 | if T==nil then 4 | (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n') 5 | return 6 | end 7 | print "testing code generation and optimizations" 8 | 9 | 10 | -- this code gave an error for the code checker 11 | do 12 | local function f (a) 13 | for k,v,w in a do end 14 | end 15 | end 16 | 17 | 18 | -- testing reuse in constant table 19 | local function checkKlist (func, list) 20 | local k = T.listk(func) 21 | assert(#k == #list) 22 | for i = 1, #k do 23 | assert(k[i] == list[i] and math.type(k[i]) == math.type(list[i])) 24 | end 25 | end 26 | 27 | local function foo () 28 | local a 29 | a = 3; 30 | a = 0; a = 0.0; a = -7 + 7 31 | a = 3.78/4; a = 3.78/4 32 | a = -3.78/4; a = 3.78/4; a = -3.78/4 33 | a = -3.79/4; a = 0.0; a = -0; 34 | a = 3; a = 3.0; a = 3; a = 3.0 35 | end 36 | 37 | checkKlist(foo, {3, 0, 0.0, 3.78/4, -3.78/4, -3.79/4, 3.0}) 38 | 39 | 40 | -- testing opcodes 41 | 42 | function check (f, ...) 43 | local arg = {...} 44 | local c = T.listcode(f) 45 | for i=1, #arg do 46 | -- print(arg[i], c[i]) 47 | assert(string.find(c[i], '- '..arg[i]..' *%d')) 48 | end 49 | assert(c[#arg+2] == nil) 50 | end 51 | 52 | 53 | function checkequal (a, b) 54 | a = T.listcode(a) 55 | b = T.listcode(b) 56 | for i = 1, #a do 57 | a[i] = string.gsub(a[i], '%b()', '') -- remove line number 58 | b[i] = string.gsub(b[i], '%b()', '') -- remove line number 59 | assert(a[i] == b[i]) 60 | end 61 | end 62 | 63 | 64 | -- some basic instructions 65 | check(function () 66 | (function () end){f()} 67 | end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN') 68 | 69 | 70 | -- sequence of LOADNILs 71 | check(function () 72 | local a,b,c 73 | local d; local e; 74 | local f,g,h; 75 | d = nil; d=nil; b=nil; a=nil; c=nil; 76 | end, 'LOADNIL', 'RETURN') 77 | 78 | check(function () 79 | local a,b,c,d = 1,1,1,1 80 | d=nil;c=nil;b=nil;a=nil 81 | end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN') 82 | 83 | do 84 | local a,b,c,d = 1,1,1,1 85 | d=nil;c=nil;b=nil;a=nil 86 | assert(a == nil and b == nil and c == nil and d == nil) 87 | end 88 | 89 | 90 | -- single return 91 | check (function (a,b,c) return a end, 'RETURN') 92 | 93 | 94 | -- infinite loops 95 | check(function () while true do local a = -1 end end, 96 | 'LOADK', 'JMP', 'RETURN') 97 | 98 | check(function () while 1 do local a = -1 end end, 99 | 'LOADK', 'JMP', 'RETURN') 100 | 101 | check(function () repeat local x = 1 until true end, 102 | 'LOADK', 'RETURN') 103 | 104 | 105 | -- concat optimization 106 | check(function (a,b,c,d) return a..b..c..d end, 107 | 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN') 108 | 109 | -- not 110 | check(function () return not not nil end, 'LOADBOOL', 'RETURN') 111 | check(function () return not not false end, 'LOADBOOL', 'RETURN') 112 | check(function () return not not true end, 'LOADBOOL', 'RETURN') 113 | check(function () return not not 1 end, 'LOADBOOL', 'RETURN') 114 | 115 | -- direct access to locals 116 | check(function () 117 | local a,b,c,d 118 | a = b*2 119 | c[4], a[b] = -((a + d/-20.5 - a[b]) ^ a.x), b 120 | end, 121 | 'LOADNIL', 122 | 'MUL', 123 | 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW', 124 | 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN') 125 | 126 | 127 | -- direct access to constants 128 | check(function () 129 | local a,b 130 | a.x = 0 131 | a.x = b 132 | a[b] = 'y' 133 | a = 1 - a 134 | b = 1/a 135 | b = 5+4 136 | a[true] = false 137 | end, 138 | 'LOADNIL', 139 | 'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK', 140 | 'SETTABLE', 'RETURN') 141 | 142 | 143 | -- constant folding 144 | local function checkK (func, val) 145 | check(func, 'LOADK', 'RETURN') 146 | local k = T.listk(func) 147 | assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val)) 148 | assert(func() == val) 149 | end 150 | checkK(function () return 0.0 end, 0.0) 151 | checkK(function () return 0 end, 0) 152 | checkK(function () return -0//1 end, 0) 153 | checkK(function () return 3^-1 end, 1/3) 154 | checkK(function () return (1 + 1)^(50 + 50) end, 2^100) 155 | checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0) 156 | checkK(function () return (-3^0 + 5) // 3.0 end, 1.0) 157 | checkK(function () return -3 % 5 end, 2) 158 | checkK(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0) 159 | checkK(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0) 160 | checkK(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4) 161 | checkK(function () return ~(~0xFF0 | 0xFF0) end, 0) 162 | checkK(function () return ~~-100024.0 end, -100024) 163 | checkK(function () return ((100 << 6) << -4) >> 2 end, 100) 164 | 165 | 166 | -- no foldings 167 | check(function () return -0.0 end, 'LOADK', 'UNM', 'RETURN') 168 | check(function () return 3/0 end, 'DIV', 'RETURN') 169 | check(function () return 0%0 end, 'MOD', 'RETURN') 170 | check(function () return -4//0 end, 'IDIV', 'RETURN') 171 | 172 | -- bug in constant folding for 5.1 173 | check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN') 174 | 175 | 176 | check(function () 177 | local a,b,c 178 | b[c], a = c, b 179 | b[a], a = c, b 180 | a, b = c, a 181 | a = a 182 | end, 183 | 'LOADNIL', 184 | 'MOVE', 'MOVE', 'SETTABLE', 185 | 'MOVE', 'MOVE', 'MOVE', 'SETTABLE', 186 | 'MOVE', 'MOVE', 'MOVE', 187 | -- no code for a = a 188 | 'RETURN') 189 | 190 | 191 | -- x == nil , x ~= nil 192 | checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end, 193 | function () if (a==9) then a=1 end; if a~=9 then a=1 end end) 194 | 195 | check(function () if a==nil then a=1 end end, 196 | 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN') 197 | 198 | -- de morgan 199 | checkequal(function () local a; if not (a or b) then b=a end end, 200 | function () local a; if (not a and not b) then b=a end end) 201 | 202 | checkequal(function (l) local a; return 0 <= a and a <= l end, 203 | function (l) local a; return not (not(a >= 0) or not(a <= l)) end) 204 | 205 | 206 | -- if-goto optimizations 207 | check(function (a) 208 | if a == 1 then goto l1 209 | elseif a == 2 then goto l2 210 | elseif a == 3 then goto l2 211 | else if a == 4 then goto l3 212 | else goto l3 213 | end 214 | end 215 | ::l1:: ::l2:: ::l3:: ::l4:: 216 | end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN') 217 | 218 | checkequal( 219 | function (a) while a < 10 do a = a + 1 end end, 220 | function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1; 221 | goto L2; ::L1:: end 222 | ) 223 | 224 | checkequal( 225 | function (a) while a < 10 do a = a + 1 end end, 226 | function (a) while true do if not(a < 10) then break end; a = a + 1; end end 227 | ) 228 | 229 | print 'OK' 230 | 231 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/constructs.lua: -------------------------------------------------------------------------------- 1 | -- $Id: constructs.lua,v 1.39 2015/03/04 13:09:38 roberto Exp $ 2 | 3 | ;;print "testing syntax";; 4 | 5 | local debug = require "debug" 6 | 7 | -- testing semicollons 8 | do ;;; end 9 | ; do ; a = 3; assert(a == 3) end; 10 | ; 11 | 12 | 13 | -- invalid operations should not raise errors when not executed 14 | if false then a = 3 // 0; a = 0 % 0 end 15 | 16 | 17 | -- testing priorities 18 | 19 | assert(2^3^2 == 2^(3^2)); 20 | assert(2^3*4 == (2^3)*4); 21 | assert(2.0^-2 == 1/4 and -2^- -2 == - - -4); 22 | assert(not nil and 2 and not(2>3 or 3<2)); 23 | assert(-3-1-5 == 0+0-9); 24 | assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0); 25 | assert(-3%5 == 2 and -3+5 == 2) 26 | assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33"); 27 | assert(not(2+1 > 3*1) and "a".."b" > "a"); 28 | 29 | assert("7" .. 3 << 1 == 146) 30 | assert(10 >> 1 .. "9" == 0) 31 | assert(10 | 1 .. "9" == 27) 32 | 33 | assert(0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4) 34 | assert(0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4) 35 | assert(0xF0 & 0x0F + 1 == 0x10) 36 | 37 | assert(3^4//2^3//5 == 2) 38 | 39 | assert(-3+4*5//2^3^2//9+4%10/3 == (-3)+(((4*5)//(2^(3^2)))//9)+((4%10)/3)) 40 | 41 | assert(not ((true or false) and nil)) 42 | assert( true or false and nil) 43 | 44 | -- old bug 45 | assert((((1 or false) and true) or false) == true) 46 | assert((((nil and true) or false) and true) == false) 47 | 48 | local a,b = 1,nil; 49 | assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75); 50 | x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x); 51 | x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x); 52 | 53 | x,y=1,2; 54 | assert((x>y) and x or y == 2); 55 | x,y=2,1; 56 | assert((x>y) and x or y == 2); 57 | 58 | assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891) 59 | 60 | 61 | -- silly loops 62 | repeat until 1; repeat until true; 63 | while false do end; while nil do end; 64 | 65 | do -- test old bug (first name could not be an `upvalue') 66 | local a; function f(x) x={a=1}; x={x=1}; x={G=1} end 67 | end 68 | 69 | function f (i) 70 | if type(i) ~= 'number' then return i,'jojo'; end; 71 | if i > 0 then return i, f(i-1); end; 72 | end 73 | 74 | x = {f(3), f(5), f(10);}; 75 | assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1); 76 | assert(x[nil] == nil) 77 | x = {f'alo', f'xixi', nil}; 78 | assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil); 79 | x = {f'alo'..'xixi'}; 80 | assert(x[1] == 'aloxixi') 81 | x = {f{}} 82 | assert(x[2] == 'jojo' and type(x[1]) == 'table') 83 | 84 | 85 | local f = function (i) 86 | if i < 10 then return 'a'; 87 | elseif i < 20 then return 'b'; 88 | elseif i < 30 then return 'c'; 89 | end; 90 | end 91 | 92 | assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil) 93 | 94 | for i=1,1000 do break; end; 95 | n=100; 96 | i=3; 97 | t = {}; 98 | a=nil 99 | while not a do 100 | a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end; 101 | end 102 | assert(a == n*(n+1)/2 and i==3); 103 | assert(t[1] and t[n] and not t[0] and not t[n+1]) 104 | 105 | function f(b) 106 | local x = 1; 107 | repeat 108 | local a; 109 | if b==1 then local b=1; x=10; break 110 | elseif b==2 then x=20; break; 111 | elseif b==3 then x=30; 112 | else local a,b,c,d=math.sin(1); x=x+1; 113 | end 114 | until x>=12; 115 | return x; 116 | end; 117 | 118 | assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12) 119 | 120 | 121 | local f = function (i) 122 | if i < 10 then return 'a' 123 | elseif i < 20 then return 'b' 124 | elseif i < 30 then return 'c' 125 | else return 8 126 | end 127 | end 128 | 129 | assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8) 130 | 131 | local a, b = nil, 23 132 | x = {f(100)*2+3 or a, a or b+2} 133 | assert(x[1] == 19 and x[2] == 25) 134 | x = {f=2+3 or a, a = b+2} 135 | assert(x.f == 5 and x.a == 25) 136 | 137 | a={y=1} 138 | x = {a.y} 139 | assert(x[1] == 1) 140 | 141 | function f(i) 142 | while 1 do 143 | if i>0 then i=i-1; 144 | else return; end; 145 | end; 146 | end; 147 | 148 | function g(i) 149 | while 1 do 150 | if i>0 then i=i-1 151 | else return end 152 | end 153 | end 154 | 155 | f(10); g(10); 156 | 157 | do 158 | function f () return 1,2,3; end 159 | local a, b, c = f(); 160 | assert(a==1 and b==2 and c==3) 161 | a, b, c = (f()); 162 | assert(a==1 and b==nil and c==nil) 163 | end 164 | 165 | local a,b = 3 and f(); 166 | assert(a==1 and b==nil) 167 | 168 | function g() f(); return; end; 169 | assert(g() == nil) 170 | function g() return nil or f() end 171 | a,b = g() 172 | assert(a==1 and b==nil) 173 | 174 | print'+'; 175 | 176 | 177 | f = [[ 178 | return function ( a , b , c , d , e ) 179 | local x = a >= b or c or ( d and e ) or nil 180 | return x 181 | end , { a = 1 , b = 2 >= 1 , } or { 1 }; 182 | ]] 183 | f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes 184 | f,a = load(f)(); 185 | assert(a.a == 1 and a.b) 186 | 187 | function g (a,b,c,d,e) 188 | if not (a>=b or c or d and e or nil) then return 0; else return 1; end; 189 | end 190 | 191 | function h (a,b,c,d,e) 192 | while (a>=b or c or (d and e) or nil) do return 1; end; 193 | return 0; 194 | end; 195 | 196 | assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1) 197 | assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1) 198 | assert(f(1,2,'a') 199 | ~= -- force SETLINE before nil 200 | nil, "") 201 | assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1) 202 | assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and 203 | h(1,2,nil,1,'x') == 1) 204 | assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and 205 | h(1,2,nil,nil,'x') == 0) 206 | assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and 207 | h(1,2,nil,1,nil) == 0) 208 | 209 | assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true) 210 | x = 2<3 and not 3; assert(x==false) 211 | x = 2<1 or (2>1 and 'a'); assert(x=='a') 212 | 213 | 214 | do 215 | local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2 216 | assert(a==2) 217 | end 218 | 219 | function F(a) 220 | assert(debug.getinfo(1, "n").name == 'F') 221 | return a,2,3 222 | end 223 | 224 | a,b = F(1)~=nil; assert(a == true and b == nil); 225 | a,b = F(nil)==nil; assert(a == true and b == nil) 226 | 227 | ---------------------------------------------------------------- 228 | ------------------------------------------------------------------ 229 | 230 | -- sometimes will be 0, sometimes will not... 231 | _ENV.GLOB1 = math.floor(os.time()) % 2 232 | 233 | -- basic expressions with their respective values 234 | local basiccases = { 235 | {"nil", nil}, 236 | {"false", false}, 237 | {"true", true}, 238 | {"10", 10}, 239 | {"(0==_ENV.GLOB1)", 0 == _ENV.GLOB1}, 240 | } 241 | 242 | print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')') 243 | 244 | 245 | -- operators with their respective values 246 | local binops = { 247 | {" and ", function (a,b) if not a then return a else return b end end}, 248 | {" or ", function (a,b) if a then return a else return b end end}, 249 | } 250 | 251 | local cases = {} 252 | 253 | -- creates all combinations of '(cases[i] op cases[n-i])' plus 254 | -- 'not(cases[i] op cases[n-i])' (syntax + value) 255 | local function createcases (n) 256 | local res = {} 257 | for i = 1, n - 1 do 258 | for _, v1 in ipairs(cases[i]) do 259 | for _, v2 in ipairs(cases[n - i]) do 260 | for _, op in ipairs(binops) do 261 | local t = { 262 | "(" .. v1[1] .. op[1] .. v2[1] .. ")", 263 | op[2](v1[2], v2[2]) 264 | } 265 | res[#res + 1] = t 266 | res[#res + 1] = {"not" .. t[1], not t[2]} 267 | end 268 | end 269 | end 270 | end 271 | return res 272 | end 273 | 274 | -- do not do too many combinations for soft tests 275 | local level = _soft and 3 or 4 276 | 277 | cases[1] = basiccases 278 | for i = 2, level do cases[i] = createcases(i) end 279 | print("+") 280 | 281 | local prog = [[if %s then IX = true end; return %s]] 282 | 283 | local i = 0 284 | for n = 1, level do 285 | for _, v in pairs(cases[n]) do 286 | local s = v[1] 287 | local p = load(string.format(prog, s, s), "") 288 | IX = false 289 | assert(p() == v[2] and IX == not not v[2]) 290 | i = i + 1 291 | if i % 60000 == 0 then print('+') end 292 | end 293 | end 294 | ------------------------------------------------------------------ 295 | 296 | -- testing some syntax errors (chosen through 'gcov') 297 | assert(string.find(select(2, load("for x do")), "expected")) 298 | assert(string.find(select(2, load("x:call")), "expected")) 299 | 300 | print'OK' 301 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/events.lua: -------------------------------------------------------------------------------- 1 | -- $Id: events.lua,v 1.41 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | print('testing metatables') 4 | 5 | local debug = require'debug' 6 | 7 | X = 20; B = 30 8 | 9 | _ENV = setmetatable({}, {__index=_G}) 10 | 11 | collectgarbage() 12 | 13 | X = X+10 14 | assert(X == 30 and _G.X == 20) 15 | B = false 16 | assert(B == false) 17 | B = nil 18 | assert(B == 30) 19 | 20 | assert(getmetatable{} == nil) 21 | assert(getmetatable(4) == nil) 22 | assert(getmetatable(nil) == nil) 23 | a={}; setmetatable(a, {__metatable = "xuxu", 24 | __tostring=function(x) return x.name end}) 25 | assert(getmetatable(a) == "xuxu") 26 | assert(tostring(a) == nil) 27 | -- cannot change a protected metatable 28 | assert(pcall(setmetatable, a, {}) == false) 29 | a.name = "gororoba" 30 | assert(tostring(a) == "gororoba") 31 | 32 | local a, t = {10,20,30; x="10", y="20"}, {} 33 | assert(setmetatable(a,t) == a) 34 | assert(getmetatable(a) == t) 35 | assert(setmetatable(a,nil) == a) 36 | assert(getmetatable(a) == nil) 37 | assert(setmetatable(a,t) == a) 38 | 39 | 40 | function f (t, i, e) 41 | assert(not e) 42 | local p = rawget(t, "parent") 43 | return (p and p[i]+3), "dummy return" 44 | end 45 | 46 | t.__index = f 47 | 48 | a.parent = {z=25, x=12, [4] = 24} 49 | assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10") 50 | 51 | collectgarbage() 52 | 53 | a = setmetatable({}, t) 54 | function f(t, i, v) rawset(t, i, v-3) end 55 | setmetatable(t, t) -- causes a bug in 5.1 ! 56 | t.__newindex = f 57 | a[1] = 30; a.x = "101"; a[5] = 200 58 | assert(a[1] == 27 and a.x == 98 and a[5] == 197) 59 | 60 | 61 | local c = {} 62 | a = setmetatable({}, t) 63 | t.__newindex = c 64 | a[1] = 10; a[2] = 20; a[3] = 90 65 | assert(c[1] == 10 and c[2] == 20 and c[3] == 90) 66 | 67 | 68 | do 69 | local a; 70 | a = setmetatable({}, {__index = setmetatable({}, 71 | {__index = setmetatable({}, 72 | {__index = function (_,n) return a[n-3]+4, "lixo" end})})}) 73 | a[0] = 20 74 | for i=0,10 do 75 | assert(a[i*3] == 20 + i*4) 76 | end 77 | end 78 | 79 | 80 | do -- newindex 81 | local foi 82 | local a = {} 83 | for i=1,10 do a[i] = 0; a['a'..i] = 0; end 84 | setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end}) 85 | foi = false; a[1]=0; assert(not foi) 86 | foi = false; a['a1']=0; assert(not foi) 87 | foi = false; a['a11']=0; assert(foi) 88 | foi = false; a[11]=0; assert(foi) 89 | foi = false; a[1]=nil; assert(not foi) 90 | foi = false; a[1]=nil; assert(foi) 91 | end 92 | 93 | 94 | setmetatable(t, nil) 95 | function f (t, ...) return t, {...} end 96 | t.__call = f 97 | 98 | do 99 | local x,y = a(table.unpack{'a', 1}) 100 | assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil) 101 | x,y = a() 102 | assert(x==a and y[1]==nil) 103 | end 104 | 105 | 106 | local b = setmetatable({}, t) 107 | setmetatable(b,t) 108 | 109 | function f(op) 110 | return function (...) cap = {[0] = op, ...} ; return (...) end 111 | end 112 | t.__add = f("add") 113 | t.__sub = f("sub") 114 | t.__mul = f("mul") 115 | t.__div = f("div") 116 | t.__idiv = f("idiv") 117 | t.__mod = f("mod") 118 | t.__unm = f("unm") 119 | t.__pow = f("pow") 120 | t.__len = f("len") 121 | t.__band = f("band") 122 | t.__bor = f("bor") 123 | t.__bxor = f("bxor") 124 | t.__shl = f("shl") 125 | t.__shr = f("shr") 126 | t.__bnot = f("bnot") 127 | 128 | assert(b+5 == b) 129 | assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil) 130 | assert(b+'5' == b) 131 | assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil) 132 | assert(5+b == 5) 133 | assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil) 134 | assert('5'+b == '5') 135 | assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil) 136 | b=b-3; assert(getmetatable(b) == t) 137 | assert(5-a == 5) 138 | assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil) 139 | assert('5'-a == '5') 140 | assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil) 141 | assert(a*a == a) 142 | assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil) 143 | assert(a/0 == a) 144 | assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil) 145 | assert(a%2 == a) 146 | assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil) 147 | assert(a // (1/0) == a) 148 | assert(cap[0] == "idiv" and cap[1] == a and cap[2] == 1/0 and cap[3]==nil) 149 | assert(a & "hi" == a) 150 | assert(cap[0] == "band" and cap[1] == a and cap[2] == "hi" and cap[3]==nil) 151 | assert(a | "hi" == a) 152 | assert(cap[0] == "bor" and cap[1] == a and cap[2] == "hi" and cap[3]==nil) 153 | assert("hi" ~ a == "hi") 154 | assert(cap[0] == "bxor" and cap[1] == "hi" and cap[2] == a and cap[3]==nil) 155 | assert(-a == a) 156 | assert(cap[0] == "unm" and cap[1] == a) 157 | assert(a^4 == a) 158 | assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil) 159 | assert(a^'4' == a) 160 | assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil) 161 | assert(4^a == 4) 162 | assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil) 163 | assert('4'^a == '4') 164 | assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil) 165 | assert(#a == a) 166 | assert(cap[0] == "len" and cap[1] == a) 167 | assert(~a == a) 168 | assert(cap[0] == "bnot" and cap[1] == a) 169 | assert(a << 3 == a) 170 | assert(cap[0] == "shl" and cap[1] == a and cap[2] == 3) 171 | assert(1.5 >> a == 1.5) 172 | assert(cap[0] == "shr" and cap[1] == 1.5 and cap[2] == a) 173 | 174 | 175 | -- test for rawlen 176 | t = setmetatable({1,2,3}, {__len = function () return 10 end}) 177 | assert(#t == 10 and rawlen(t) == 3) 178 | assert(rawlen"abc" == 3) 179 | assert(not pcall(rawlen, io.stdin)) 180 | assert(not pcall(rawlen, 34)) 181 | assert(not pcall(rawlen)) 182 | 183 | t = {} 184 | t.__lt = function (a,b,c) 185 | collectgarbage() 186 | assert(c == nil) 187 | if type(a) == 'table' then a = a.x end 188 | if type(b) == 'table' then b = b.x end 189 | return aOp(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1))) 202 | assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a'))) 203 | assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1))) 204 | assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1)) 205 | assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a'))) 206 | assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a'))) 207 | end 208 | 209 | test() 210 | 211 | t.__le = function (a,b,c) 212 | assert(c == nil) 213 | if type(a) == 'table' then a = a.x end 214 | if type(b) == 'table' then b = b.x end 215 | return a<=b, "dummy" 216 | end 217 | 218 | test() -- retest comparisons, now using both `lt' and `le' 219 | 220 | 221 | -- test `partial order' 222 | 223 | local function rawSet(x) 224 | local y = {} 225 | for _,k in pairs(x) do y[k] = 1 end 226 | return y 227 | end 228 | 229 | local function Set(x) 230 | return setmetatable(rawSet(x), t) 231 | end 232 | 233 | t.__lt = function (a,b) 234 | for k in pairs(a) do 235 | if not b[k] then return false end 236 | b[k] = nil 237 | end 238 | return next(b) ~= nil 239 | end 240 | 241 | t.__le = nil 242 | 243 | assert(Set{1,2,3} < Set{1,2,3,4}) 244 | assert(not(Set{1,2,3,4} < Set{1,2,3,4})) 245 | assert((Set{1,2,3,4} <= Set{1,2,3,4})) 246 | assert((Set{1,2,3,4} >= Set{1,2,3,4})) 247 | assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-) 248 | 249 | t.__le = function (a,b) 250 | for k in pairs(a) do 251 | if not b[k] then return false end 252 | end 253 | return true 254 | end 255 | 256 | assert(not (Set{1,3} <= Set{3,5})) -- now its OK! 257 | assert(not(Set{1,3} <= Set{3,5})) 258 | assert(not(Set{1,3} >= Set{3,5})) 259 | 260 | t.__eq = function (a,b) 261 | for k in pairs(a) do 262 | if not b[k] then return false end 263 | b[k] = nil 264 | end 265 | return next(b) == nil 266 | end 267 | 268 | local s = Set{1,3,5} 269 | assert(s == Set{3,5,1}) 270 | assert(not rawequal(s, Set{3,5,1})) 271 | assert(rawequal(s, s)) 272 | assert(Set{1,3,5,1} == rawSet{3,5,1}) 273 | assert(rawSet{1,3,5,1} == Set{3,5,1}) 274 | assert(Set{1,3,5} ~= Set{3,5,1,6}) 275 | 276 | -- '__eq' is not used for table accesses 277 | t[Set{1,3,5}] = 1 278 | assert(t[Set{1,3,5}] == nil) 279 | 280 | 281 | if not T then 282 | (Message or print)('\n >>> testC not active: skipping tests for \z 283 | userdata equality <<<\n') 284 | else 285 | local u1 = T.newuserdata(0) 286 | local u2 = T.newuserdata(0) 287 | local u3 = T.newuserdata(0) 288 | assert(u1 ~= u2 and u1 ~= u3) 289 | debug.setuservalue(u1, 1); 290 | debug.setuservalue(u2, 2); 291 | debug.setuservalue(u3, 1); 292 | debug.setmetatable(u1, {__eq = function (a, b) 293 | return debug.getuservalue(a) == debug.getuservalue(b) 294 | end}) 295 | debug.setmetatable(u2, {__eq = function (a, b) 296 | return true 297 | end}) 298 | assert(u1 == u3 and u3 == u1 and u1 ~= u2) 299 | assert(u2 == u1 and u2 == u3 and u3 == u2) 300 | assert(u2 ~= {}) -- different types cannot be equal 301 | end 302 | 303 | 304 | t.__concat = function (a,b,c) 305 | assert(c == nil) 306 | if type(a) == 'table' then a = a.val end 307 | if type(b) == 'table' then b = b.val end 308 | if A then return a..b 309 | else 310 | return setmetatable({val=a..b}, t) 311 | end 312 | end 313 | 314 | c = {val="c"}; setmetatable(c, t) 315 | d = {val="d"}; setmetatable(d, t) 316 | 317 | A = true 318 | assert(c..d == 'cd') 319 | assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g") 320 | 321 | A = false 322 | assert((c..d..c..d).val == 'cdcd') 323 | x = c..d 324 | assert(getmetatable(x) == t and x.val == 'cd') 325 | x = 0 .."a".."b"..c..d.."e".."f".."g" 326 | assert(x.val == "0abcdefg") 327 | 328 | 329 | -- concat metamethod x numbers (bug in 5.1.1) 330 | c = {} 331 | local x 332 | setmetatable(c, {__concat = function (a,b) 333 | assert(type(a) == "number" and b == c or type(b) == "number" and a == c) 334 | return c 335 | end}) 336 | assert(c..5 == c and 5 .. c == c) 337 | assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c) 338 | 339 | 340 | -- test comparison compatibilities 341 | local t1, t2, c, d 342 | t1 = {}; c = {}; setmetatable(c, t1) 343 | d = {} 344 | t1.__eq = function () return true end 345 | t1.__lt = function () return true end 346 | setmetatable(d, t1) 347 | assert(c == d and c < d and not(d <= c)) 348 | t2 = {} 349 | t2.__eq = t1.__eq 350 | t2.__lt = t1.__lt 351 | setmetatable(d, t2) 352 | assert(c == d and c < d and not(d <= c)) 353 | 354 | 355 | 356 | -- test for several levels of calls 357 | local i 358 | local tt = { 359 | __call = function (t, ...) 360 | i = i+1 361 | if t.f then return t.f(...) 362 | else return {...} 363 | end 364 | end 365 | } 366 | 367 | local a = setmetatable({}, tt) 368 | local b = setmetatable({f=a}, tt) 369 | local c = setmetatable({f=b}, tt) 370 | 371 | i = 0 372 | x = c(3,4,5) 373 | assert(i == 3 and x[1] == 3 and x[3] == 5) 374 | 375 | 376 | assert(_G.X == 20) 377 | 378 | print'+' 379 | 380 | local _g = _G 381 | _ENV = setmetatable({}, {__index=function (_,k) return _g[k] end}) 382 | 383 | 384 | a = {} 385 | rawset(a, "x", 1, 2, 3) 386 | assert(a.x == 1 and rawget(a, "x", 3) == 1) 387 | 388 | print '+' 389 | 390 | -- testing metatables for basic types 391 | mt = {__index = function (a,b) return a+b end, 392 | __len = function (x) return math.floor(x) end} 393 | debug.setmetatable(10, mt) 394 | assert(getmetatable(-2) == mt) 395 | assert((10)[3] == 13) 396 | assert((10)["3"] == 13) 397 | assert(#3.45 == 3) 398 | debug.setmetatable(23, nil) 399 | assert(getmetatable(-2) == nil) 400 | 401 | debug.setmetatable(true, mt) 402 | assert(getmetatable(false) == mt) 403 | mt.__index = function (a,b) return a or b end 404 | assert((true)[false] == true) 405 | assert((false)[false] == false) 406 | debug.setmetatable(false, nil) 407 | assert(getmetatable(true) == nil) 408 | 409 | debug.setmetatable(nil, mt) 410 | assert(getmetatable(nil) == mt) 411 | mt.__add = function (a,b) return (a or 0) + (b or 0) end 412 | assert(10 + nil == 10) 413 | assert(nil + 23 == 23) 414 | assert(nil + nil == 0) 415 | debug.setmetatable(nil, nil) 416 | assert(getmetatable(nil) == nil) 417 | 418 | debug.setmetatable(nil, {}) 419 | 420 | 421 | -- loops in delegation 422 | a = {}; setmetatable(a, a); a.__index = a; a.__newindex = a 423 | assert(not pcall(function (a,b) return a[b] end, a, 10)) 424 | assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true)) 425 | 426 | -- bug in 5.1 427 | T, K, V = nil 428 | grandparent = {} 429 | grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end 430 | 431 | parent = {} 432 | parent.__newindex = parent 433 | setmetatable(parent, grandparent) 434 | 435 | child = setmetatable({}, parent) 436 | child.foo = 10 --> CRASH (on some machines) 437 | assert(T == parent and K == "foo" and V == 10) 438 | 439 | print 'OK' 440 | 441 | return 12 442 | 443 | 444 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/goto.lua: -------------------------------------------------------------------------------- 1 | -- $Id: goto.lua,v 1.11 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | collectgarbage() 4 | 5 | local function errmsg (code, m) 6 | local st, msg = load(code) 7 | assert(not st and string.find(msg, m)) 8 | end 9 | 10 | -- cannot see label inside block 11 | errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'") 12 | errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'") 13 | 14 | -- repeated label 15 | errmsg([[ ::l1:: ::l1:: ]], "label 'l1'") 16 | 17 | 18 | -- undefined label 19 | errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'") 20 | 21 | -- jumping over variable definition 22 | errmsg([[ 23 | do local bb, cc; goto l1; end 24 | local aa 25 | ::l1:: print(3) 26 | ]], "local 'aa'") 27 | 28 | -- jumping into a block 29 | errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'") 30 | errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'") 31 | 32 | -- cannot continue a repeat-until with variables 33 | errmsg([[ 34 | repeat 35 | if x then goto cont end 36 | local xuxu = 10 37 | ::cont:: 38 | until xuxu < x 39 | ]], "local 'xuxu'") 40 | 41 | -- simple gotos 42 | local x 43 | do 44 | local y = 12 45 | goto l1 46 | ::l2:: x = x + 1; goto l3 47 | ::l1:: x = y; goto l2 48 | end 49 | ::l3:: ::l3_1:: assert(x == 13) 50 | 51 | 52 | -- long labels 53 | do 54 | local prog = [[ 55 | do 56 | local a = 1 57 | goto l%sa; a = a + 1 58 | ::l%sa:: a = a + 10 59 | goto l%sb; a = a + 2 60 | ::l%sb:: a = a + 20 61 | return a 62 | end 63 | ]] 64 | local label = string.rep("0123456789", 40) 65 | prog = string.format(prog, label, label, label, label) 66 | assert(assert(load(prog))() == 31) 67 | end 68 | 69 | -- goto to correct label when nested 70 | do goto l3; ::l3:: end -- does not loop jumping to previous label 'l3' 71 | 72 | -- ok to jump over local dec. to end of block 73 | do 74 | goto l1 75 | local a = 23 76 | x = a 77 | ::l1::; 78 | end 79 | 80 | while true do 81 | goto l4 82 | goto l1 -- ok to jump over local dec. to end of block 83 | goto l1 -- multiple uses of same label 84 | local x = 45 85 | ::l1:: ;;; 86 | end 87 | ::l4:: assert(x == 13) 88 | 89 | if print then 90 | goto l1 -- ok to jump over local dec. to end of block 91 | error("should not be here") 92 | goto l2 -- ok to jump over local dec. to end of block 93 | local x 94 | ::l1:: ; ::l2:: ;; 95 | else end 96 | 97 | -- to repeat a label in a different function is OK 98 | local function foo () 99 | local a = {} 100 | goto l3 101 | ::l1:: a[#a + 1] = 1; goto l2; 102 | ::l2:: a[#a + 1] = 2; goto l5; 103 | ::l3:: 104 | ::l3a:: a[#a + 1] = 3; goto l1; 105 | ::l4:: a[#a + 1] = 4; goto l6; 106 | ::l5:: a[#a + 1] = 5; goto l4; 107 | ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and 108 | a[4] == 5 and a[5] == 4) 109 | if not a[6] then a[6] = true; goto l3a end -- do it twice 110 | end 111 | 112 | ::l6:: foo() 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- 117 | -- testing closing of upvalues 118 | 119 | local debug = require 'debug' 120 | 121 | local function foo () 122 | local t = {} 123 | do 124 | local i = 1 125 | local a, b, c, d 126 | t[1] = function () return a, b, c, d end 127 | ::l1:: 128 | local b 129 | do 130 | local c 131 | t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6] 132 | if i > 2 then goto l2 end 133 | do 134 | local d 135 | t[#t + 1] = function () return a, b, c, d end -- t[3], t[5] 136 | i = i + 1 137 | local a 138 | goto l1 139 | end 140 | end 141 | end 142 | ::l2:: return t 143 | end 144 | 145 | local a = foo() 146 | assert(#a == 6) 147 | 148 | -- all functions share same 'a' 149 | for i = 2, 6 do 150 | assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1)) 151 | end 152 | 153 | -- 'b' and 'c' are shared among some of them 154 | for i = 2, 6 do 155 | -- only a[1] uses external 'b'/'b' 156 | assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2)) 157 | assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3)) 158 | end 159 | 160 | for i = 3, 5, 2 do 161 | -- inner functions share 'b'/'c' with previous ones 162 | assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2)) 163 | assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3)) 164 | -- but not with next ones 165 | assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2)) 166 | assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3)) 167 | end 168 | 169 | -- only external 'd' is shared 170 | for i = 2, 6, 2 do 171 | assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4)) 172 | end 173 | 174 | -- internal 'd's are all different 175 | for i = 3, 5, 2 do 176 | for j = 1, 6 do 177 | assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4)) 178 | == (i == j)) 179 | end 180 | end 181 | 182 | -------------------------------------------------------------------------------- 183 | -- testing if x goto optimizations 184 | 185 | local function testG (a) 186 | if a == 1 then 187 | goto l1 188 | error("should never be here!") 189 | elseif a == 2 then goto l2 190 | elseif a == 3 then goto l3 191 | elseif a == 4 then 192 | goto l1 -- go to inside the block 193 | error("should never be here!") 194 | ::l1:: a = a + 1 -- must go to 'if' end 195 | else 196 | goto l4 197 | ::l4a:: a = a * 2; goto l4b 198 | error("should never be here!") 199 | ::l4:: goto l4a 200 | error("should never be here!") 201 | ::l4b:: 202 | end 203 | do return a end 204 | ::l2:: do return "2" end 205 | ::l3:: do return "3" end 206 | ::l1:: return "1" 207 | end 208 | 209 | assert(testG(1) == "1") 210 | assert(testG(2) == "2") 211 | assert(testG(3) == "3") 212 | assert(testG(4) == 5) 213 | assert(testG(5) == 10) 214 | -------------------------------------------------------------------------------- 215 | 216 | 217 | print'OK' 218 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/libs/lib1.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | #include "lauxlib.h" 3 | 4 | static int id (lua_State *L) { 5 | return lua_gettop(L); 6 | } 7 | 8 | 9 | static const struct luaL_Reg funcs[] = { 10 | {"id", id}, 11 | {NULL, NULL} 12 | }; 13 | 14 | 15 | /* function used by lib11.c */ 16 | LUAMOD_API int lib1_export (lua_State *L) { 17 | lua_pushstring(L, "exported"); 18 | return 1; 19 | } 20 | 21 | 22 | LUAMOD_API int onefunction (lua_State *L) { 23 | luaL_checkversion(L); 24 | lua_settop(L, 2); 25 | lua_pushvalue(L, 1); 26 | return 2; 27 | } 28 | 29 | 30 | LUAMOD_API int anotherfunc (lua_State *L) { 31 | luaL_checkversion(L); 32 | lua_pushfstring(L, "%d%%%d\n", (int)lua_tointeger(L, 1), 33 | (int)lua_tointeger(L, 2)); 34 | return 1; 35 | } 36 | 37 | 38 | LUAMOD_API int luaopen_lib1_sub (lua_State *L) { 39 | lua_setglobal(L, "y"); /* 2nd arg: extra value (file name) */ 40 | lua_setglobal(L, "x"); /* 1st arg: module name */ 41 | luaL_newlib(L, funcs); 42 | return 1; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/libs/lib11.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | 3 | /* function from lib1.c */ 4 | int lib1_export (lua_State *L); 5 | 6 | LUAMOD_API int luaopen_lib11 (lua_State *L) { 7 | return lib1_export(L); 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/libs/lib2.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | #include "lauxlib.h" 3 | 4 | static int id (lua_State *L) { 5 | return lua_gettop(L); 6 | } 7 | 8 | 9 | static const struct luaL_Reg funcs[] = { 10 | {"id", id}, 11 | {NULL, NULL} 12 | }; 13 | 14 | 15 | LUAMOD_API int luaopen_lib2 (lua_State *L) { 16 | lua_settop(L, 2); 17 | lua_setglobal(L, "y"); /* y gets 2nd parameter */ 18 | lua_setglobal(L, "x"); /* x gets 1st parameter */ 19 | luaL_newlib(L, funcs); 20 | return 1; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/libs/lib21.c: -------------------------------------------------------------------------------- 1 | #include "lua.h" 2 | 3 | 4 | int luaopen_lib2 (lua_State *L); 5 | 6 | LUAMOD_API int luaopen_lib21 (lua_State *L) { 7 | return luaopen_lib2(L); 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/libs/makefile: -------------------------------------------------------------------------------- 1 | # change this variable to point to the directory with Lua headers 2 | # of the version being tested 3 | LUA_DIR = ../.. 4 | 5 | CC = gcc 6 | 7 | # compilation should generate Dynamic-Link Libraries 8 | CFLAGS = -Wall -std=gnu99 -O2 -I$(LUA_DIR) -fPIC -shared 9 | 10 | # libraries used by the tests 11 | all: lib1.so lib11.so lib2.so lib21.so lib2-v2.so 12 | 13 | lib1.so: lib1.c 14 | $(CC) $(CFLAGS) -o lib1.so lib1.c 15 | 16 | lib11.so: lib11.c 17 | $(CC) $(CFLAGS) -o lib11.so lib11.c 18 | 19 | lib2.so: lib2.c 20 | $(CC) $(CFLAGS) -o lib2.so lib2.c 21 | 22 | lib21.so: lib21.c 23 | $(CC) $(CFLAGS) -o lib21.so lib21.c 24 | 25 | lib2-v2.so: lib2.so 26 | mv lib2.so ./lib2-v2.so 27 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/literals.lua: -------------------------------------------------------------------------------- 1 | -- $Id: literals.lua,v 1.34 2015/03/04 13:09:38 roberto Exp $ 2 | 3 | print('testing scanner') 4 | 5 | local debug = require "debug" 6 | 7 | 8 | local function dostring (x) return assert(load(x), "")() end 9 | 10 | dostring("x \v\f = \t\r 'a\0a' \v\f\f") 11 | assert(x == 'a\0a' and string.len(x) == 3) 12 | 13 | -- escape sequences 14 | assert('\n\"\'\\' == [[ 15 | 16 | "'\]]) 17 | 18 | assert(string.find("\a\b\f\n\r\t\v", "^%c%c%c%c%c%c%c$")) 19 | 20 | -- assume ASCII just for tests: 21 | assert("\09912" == 'c12') 22 | assert("\99ab" == 'cab') 23 | assert("\099" == '\99') 24 | assert("\099\n" == 'c\10') 25 | assert('\0\0\0alo' == '\0' .. '\0\0' .. 'alo') 26 | 27 | assert(010 .. 020 .. -030 == "1020-30") 28 | 29 | -- hexadecimal escapes 30 | assert("\x00\x05\x10\x1f\x3C\xfF\xe8" == "\0\5\16\31\60\255\232") 31 | 32 | local function lexstring (x, y, n) 33 | local f = assert(load('return ' .. x .. 34 | ', require"debug".getinfo(1).currentline', '')) 35 | local s, l = f() 36 | assert(s == y and l == n) 37 | end 38 | 39 | lexstring("'abc\\z \n efg'", "abcefg", 2) 40 | lexstring("'abc\\z \n\n\n'", "abc", 4) 41 | lexstring("'\\z \n\t\f\v\n'", "", 3) 42 | lexstring("[[\nalo\nalo\n\n]]", "alo\nalo\n\n", 5) 43 | lexstring("[[\nalo\ralo\n\n]]", "alo\nalo\n\n", 5) 44 | lexstring("[[\nalo\ralo\r\n]]", "alo\nalo\n", 4) 45 | lexstring("[[\ralo\n\ralo\r\n]]", "alo\nalo\n", 4) 46 | lexstring("[[alo]\n]alo]]", "alo]\n]alo", 2) 47 | 48 | assert("abc\z 49 | def\z 50 | ghi\z 51 | " == 'abcdefghi') 52 | 53 | 54 | -- UTF-8 sequences 55 | assert("\u{0}\u{00000000}\x00\0" == string.char(0, 0, 0, 0)) 56 | 57 | -- limits for 1-byte sequences 58 | assert("\u{0}\u{7F}" == "\x00\z\x7F") 59 | 60 | -- limits for 2-byte sequences 61 | assert("\u{80}\u{7FF}" == "\xC2\x80\z\xDF\xBF") 62 | 63 | -- limits for 3-byte sequences 64 | assert("\u{800}\u{FFFF}" == "\xE0\xA0\x80\z\xEF\xBF\xBF") 65 | 66 | -- limits for 4-byte sequences 67 | assert("\u{10000}\u{10FFFF}" == "\xF0\x90\x80\x80\z\xF4\x8F\xBF\xBF") 68 | 69 | 70 | -- Error in escape sequences 71 | local function lexerror (s, err) 72 | local st, msg = load('return ' .. s, '') 73 | if err ~= '' then err = err .. "'" end 74 | assert(not st and string.find(msg, "near .-" .. err)) 75 | end 76 | 77 | lexerror([["abc\x"]], [[\x"]]) 78 | lexerror([["abc\x]], [[\x]]) 79 | lexerror([["\x]], [[\x]]) 80 | lexerror([["\x5"]], [[\x5"]]) 81 | lexerror([["\x5]], [[\x5]]) 82 | lexerror([["\xr"]], [[\xr]]) 83 | lexerror([["\xr]], [[\xr]]) 84 | lexerror([["\x.]], [[\x.]]) 85 | lexerror([["\x8%"]], [[\x8%%]]) 86 | lexerror([["\xAG]], [[\xAG]]) 87 | lexerror([["\g"]], [[\g]]) 88 | lexerror([["\g]], [[\g]]) 89 | lexerror([["\."]], [[\%.]]) 90 | 91 | lexerror([["\999"]], [[\999"]]) 92 | lexerror([["xyz\300"]], [[\300"]]) 93 | lexerror([[" \256"]], [[\256"]]) 94 | 95 | -- errors in UTF-8 sequences 96 | lexerror([["abc\u{110000}"]], [[abc\u{110000]]) -- too large 97 | lexerror([["abc\u11r"]], [[abc\u1]]) -- missing '{' 98 | lexerror([["abc\u"]], [[abc\u"]]) -- missing '{' 99 | lexerror([["abc\u{11r"]], [[abc\u{11r]]) -- missing '}' 100 | lexerror([["abc\u{11"]], [[abc\u{11"]]) -- missing '}' 101 | lexerror([["abc\u{11]], [[abc\u{11]]) -- missing '}' 102 | lexerror([["abc\u{r"]], [[abc\u{r]]) -- no digits 103 | 104 | -- unfinished strings 105 | lexerror("[=[alo]]", "") 106 | lexerror("[=[alo]=", "") 107 | lexerror("[=[alo]", "") 108 | lexerror("'alo", "") 109 | lexerror("'alo \\z \n\n", "") 110 | lexerror("'alo \\z", "") 111 | lexerror([['alo \98]], "") 112 | 113 | -- valid characters in variable names 114 | for i = 0, 255 do 115 | local s = string.char(i) 116 | assert(not string.find(s, "[a-zA-Z_]") == not load(s .. "=1", "")) 117 | assert(not string.find(s, "[a-zA-Z_0-9]") == 118 | not load("a" .. s .. "1 = 1", "")) 119 | end 120 | 121 | 122 | -- long variable names 123 | 124 | var1 = string.rep('a', 15000) .. '1' 125 | var2 = string.rep('a', 15000) .. '2' 126 | prog = string.format([[ 127 | %s = 5 128 | %s = %s + 1 129 | return function () return %s - %s end 130 | ]], var1, var2, var1, var1, var2) 131 | local f = dostring(prog) 132 | assert(_G[var1] == 5 and _G[var2] == 6 and f() == -1) 133 | var1, var2, f = nil 134 | print('+') 135 | 136 | -- escapes -- 137 | assert("\n\t" == [[ 138 | 139 | ]]) 140 | assert([[ 141 | 142 | $debug]] == "\n $debug") 143 | assert([[ [ ]] ~= [[ ] ]]) 144 | -- long strings -- 145 | b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789" 146 | assert(string.len(b) == 960) 147 | prog = [=[ 148 | print('+') 149 | 150 | a1 = [["this is a 'string' with several 'quotes'"]] 151 | a2 = "'quotes'" 152 | 153 | assert(string.find(a1, a2) == 34) 154 | print('+') 155 | 156 | a1 = [==[temp = [[an arbitrary value]]; ]==] 157 | assert(load(a1))() 158 | assert(temp == 'an arbitrary value') 159 | -- long strings -- 160 | b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789" 161 | assert(string.len(b) == 960) 162 | print('+') 163 | 164 | a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789 165 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 166 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 167 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 168 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 169 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 170 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 171 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 172 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 173 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 174 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 175 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 176 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 177 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 178 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 179 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 180 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 181 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 182 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 183 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 184 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 185 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 186 | 00123456789012345678901234567890123456789123456789012345678901234567890123456789 187 | ]] 188 | assert(string.len(a) == 1863) 189 | assert(string.sub(a, 1, 40) == string.sub(b, 1, 40)) 190 | x = 1 191 | ]=] 192 | 193 | print('+') 194 | x = nil 195 | dostring(prog) 196 | assert(x) 197 | 198 | prog = nil 199 | a = nil 200 | b = nil 201 | 202 | 203 | -- testing line ends 204 | prog = [[ 205 | a = 1 -- a comment 206 | b = 2 207 | 208 | 209 | x = [=[ 210 | hi 211 | ]=] 212 | y = "\ 213 | hello\r\n\ 214 | " 215 | return require"debug".getinfo(1).currentline 216 | ]] 217 | 218 | for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do 219 | local prog, nn = string.gsub(prog, "\n", n) 220 | assert(dostring(prog) == nn) 221 | assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n") 222 | end 223 | 224 | 225 | -- testing comments and strings with long brackets 226 | a = [==[]=]==] 227 | assert(a == "]=") 228 | 229 | a = [==[[===[[=[]]=][====[]]===]===]==] 230 | assert(a == "[===[[=[]]=][====[]]===]===") 231 | 232 | a = [====[[===[[=[]]=][====[]]===]===]====] 233 | assert(a == "[===[[=[]]=][====[]]===]===") 234 | 235 | a = [=[]]]]]]]]]=] 236 | assert(a == "]]]]]]]]") 237 | 238 | 239 | --[===[ 240 | x y z [==[ blu foo 241 | ]== 242 | ] 243 | ]=]==] 244 | error error]=]===] 245 | 246 | -- generate all strings of four of these chars 247 | local x = {"=", "[", "]", "\n"} 248 | local len = 4 249 | local function gen (c, n) 250 | if n==0 then coroutine.yield(c) 251 | else 252 | for _, a in pairs(x) do 253 | gen(c..a, n-1) 254 | end 255 | end 256 | end 257 | 258 | for s in coroutine.wrap(function () gen("", len) end) do 259 | assert(s == load("return [====[\n"..s.."]====]", "")()) 260 | end 261 | 262 | 263 | -- testing decimal point locale 264 | if os.setlocale("pt_BR") or os.setlocale("ptb") then 265 | assert(not load("a = (3,4)")) 266 | assert(tonumber("3,4") == 3.4 and tonumber"3.4" == nil) 267 | assert(assert(load("return 3.4"))() == 3.4) 268 | assert(assert(load("return .4,3"))() == .4) 269 | assert(assert(load("return 4."))() == 4.) 270 | assert(assert(load("return 4.+.5"))() == 4.5) 271 | local a,b = load("return 4.5.") 272 | assert(string.find(b, "'4%.5%.'")) 273 | assert(os.setlocale("C")) 274 | else 275 | (Message or print)( 276 | '\n >>> pt_BR locale not available: skipping decimal point tests <<<\n') 277 | end 278 | 279 | 280 | -- testing %q x line ends 281 | local s = "a string with \r and \n and \r\n and \n\r" 282 | local c = string.format("return %q", s) 283 | assert(assert(load(c))() == s) 284 | 285 | -- testing errors 286 | assert(not load"a = 'non-ending string") 287 | assert(not load"a = 'non-ending string\n'") 288 | assert(not load"a = '\\345'") 289 | assert(not load"a = [=x]") 290 | 291 | print('OK') 292 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/locals.lua: -------------------------------------------------------------------------------- 1 | -- $Id: locals.lua,v 1.36 2015/03/04 13:09:38 roberto Exp $ 2 | 3 | print('testing local variables and environments') 4 | 5 | local debug = require"debug" 6 | 7 | 8 | -- bug in 5.1: 9 | 10 | local function f(x) x = nil; return x end 11 | assert(f(10) == nil) 12 | 13 | local function f() local x; return x end 14 | assert(f(10) == nil) 15 | 16 | local function f(x) x = nil; local y; return x, y end 17 | assert(f(10) == nil and select(2, f(20)) == nil) 18 | 19 | do 20 | local i = 10 21 | do local i = 100; assert(i==100) end 22 | do local i = 1000; assert(i==1000) end 23 | assert(i == 10) 24 | if i ~= 10 then 25 | local i = 20 26 | else 27 | local i = 30 28 | assert(i == 30) 29 | end 30 | end 31 | 32 | 33 | 34 | f = nil 35 | 36 | local f 37 | x = 1 38 | 39 | a = nil 40 | load('local a = {}')() 41 | assert(a == nil) 42 | 43 | function f (a) 44 | local _1, _2, _3, _4, _5 45 | local _6, _7, _8, _9, _10 46 | local x = 3 47 | local b = a 48 | local c,d = a,b 49 | if (d == b) then 50 | local x = 'q' 51 | x = b 52 | assert(x == 2) 53 | else 54 | assert(nil) 55 | end 56 | assert(x == 3) 57 | local f = 10 58 | end 59 | 60 | local b=10 61 | local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3 62 | 63 | 64 | assert(x == 1) 65 | 66 | f(2) 67 | assert(type(f) == 'function') 68 | 69 | 70 | local function getenv (f) 71 | local a,b = debug.getupvalue(f, 1) 72 | assert(a == '_ENV') 73 | return b 74 | end 75 | 76 | -- test for global table of loaded chunks 77 | assert(getenv(load"a=3") == _G) 78 | local c = {}; local f = load("a = 3", nil, nil, c) 79 | assert(getenv(f) == c) 80 | assert(c.a == nil) 81 | f() 82 | assert(c.a == 3) 83 | 84 | -- old test for limits for special instructions (now just a generic test) 85 | do 86 | local i = 2 87 | local p = 4 -- p == 2^i 88 | repeat 89 | for j=-3,3 do 90 | assert(load(string.format([[local a=%s; 91 | a=a+%s; 92 | assert(a ==2^%s)]], j, p-j, i), '')) () 93 | assert(load(string.format([[local a=%s; 94 | a=a-%s; 95 | assert(a==-2^%s)]], -j, p-j, i), '')) () 96 | assert(load(string.format([[local a,b=0,%s; 97 | a=b-%s; 98 | assert(a==-2^%s)]], -j, p-j, i), '')) () 99 | end 100 | p = 2 * p; i = i + 1 101 | until p <= 0 102 | end 103 | 104 | print'+' 105 | 106 | 107 | if rawget(_G, "querytab") then 108 | -- testing clearing of dead elements from tables 109 | collectgarbage("stop") -- stop GC 110 | local a = {[{}] = 4, [3] = 0, alo = 1, 111 | a1234567890123456789012345678901234567890 = 10} 112 | 113 | local t = querytab(a) 114 | 115 | for k,_ in pairs(a) do a[k] = nil end 116 | collectgarbage() -- restore GC and collect dead fiels in `a' 117 | for i=0,t-1 do 118 | local k = querytab(a, i) 119 | assert(k == nil or type(k) == 'number' or k == 'alo') 120 | end 121 | end 122 | 123 | 124 | -- testing lexical environments 125 | 126 | assert(_ENV == _G) 127 | 128 | do 129 | local dummy 130 | local _ENV = (function (...) return ... end)(_G, dummy) -- { 131 | 132 | do local _ENV = {assert=assert}; assert(true) end 133 | mt = {_G = _G} 134 | local foo,x 135 | A = false -- "declare" A 136 | do local _ENV = mt 137 | function foo (x) 138 | A = x 139 | do local _ENV = _G; A = 1000 end 140 | return function (x) return A .. x end 141 | end 142 | end 143 | assert(getenv(foo) == mt) 144 | x = foo('hi'); assert(mt.A == 'hi' and A == 1000) 145 | assert(x('*') == mt.A .. '*') 146 | 147 | do local _ENV = {assert=assert, A=10}; 148 | do local _ENV = {assert=assert, A=20}; 149 | assert(A==20);x=A 150 | end 151 | assert(A==10 and x==20) 152 | end 153 | assert(x==20) 154 | 155 | 156 | print('OK') 157 | 158 | return 5,f 159 | 160 | end -- } 161 | 162 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/ltests/ltests.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltests.h,v 2.47 2014/12/26 14:44:44 roberto Exp $ 3 | ** Internal Header for Debugging of the Lua Implementation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltests_h 8 | #define ltests_h 9 | 10 | 11 | #include 12 | 13 | /* test Lua with no compatibility code */ 14 | #undef LUA_COMPAT_MATHLIB 15 | #undef LUA_COMPAT_IPAIRS 16 | #undef LUA_COMPAT_BITLIB 17 | #undef LUA_COMPAT_APIINTCASTS 18 | #undef LUA_COMPAT_FLOATSTRING 19 | #undef LUA_COMPAT_UNPACK 20 | #undef LUA_COMPAT_LOADERS 21 | #undef LUA_COMPAT_LOG10 22 | #undef LUA_COMPAT_LOADSTRING 23 | #undef LUA_COMPAT_MAXN 24 | #undef LUA_COMPAT_MODULE 25 | 26 | 27 | #define LUA_DEBUG 28 | 29 | 30 | /* turn on assertions */ 31 | #undef NDEBUG 32 | #include 33 | #define lua_assert(c) assert(c) 34 | 35 | 36 | /* to avoid warnings, and to make sure value is really unused */ 37 | #define UNUSED(x) (x=0, (void)(x)) 38 | 39 | 40 | /* memory-allocator control variables */ 41 | typedef struct Memcontrol { 42 | unsigned long numblocks; 43 | unsigned long total; 44 | unsigned long maxmem; 45 | unsigned long memlimit; 46 | unsigned long objcount[LUA_NUMTAGS]; 47 | } Memcontrol; 48 | 49 | LUA_API Memcontrol l_memcontrol; 50 | 51 | 52 | /* 53 | ** generic variable for debug tricks 54 | */ 55 | extern void *l_Trick; 56 | 57 | 58 | 59 | /* 60 | ** Function to traverse and check all memory used by Lua 61 | */ 62 | int lua_checkmemory (lua_State *L); 63 | 64 | 65 | /* test for lock/unlock */ 66 | 67 | struct L_EXTRA { int lock; int *plock; }; 68 | #undef LUA_EXTRASPACE 69 | #define LUA_EXTRASPACE sizeof(struct L_EXTRA) 70 | #define getlock(l) cast(struct L_EXTRA*, lua_getextraspace(l)) 71 | #define luai_userstateopen(l) \ 72 | (getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock)) 73 | #define luai_userstateclose(l) \ 74 | lua_assert(getlock(l)->lock == 1 && getlock(l)->plock == &(getlock(l)->lock)) 75 | #define luai_userstatethread(l,l1) \ 76 | lua_assert(getlock(l1)->plock == getlock(l)->plock) 77 | #define luai_userstatefree(l,l1) \ 78 | lua_assert(getlock(l)->plock == getlock(l1)->plock) 79 | #define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0) 80 | #define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0) 81 | 82 | 83 | 84 | LUA_API int luaB_opentests (lua_State *L); 85 | 86 | LUA_API void *debug_realloc (void *ud, void *block, 87 | size_t osize, size_t nsize); 88 | 89 | #if defined(lua_c) 90 | #define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) 91 | #define luaL_openlibs(L) \ 92 | { (luaL_openlibs)(L); luaL_requiref(L, "T", luaB_opentests, 1); } 93 | #endif 94 | 95 | 96 | 97 | /* change some sizes to give some bugs a chance */ 98 | 99 | #undef LUAL_BUFFERSIZE 100 | #define LUAL_BUFFERSIZE 23 101 | #define MINSTRTABSIZE 2 102 | 103 | 104 | /* make stack-overflow tests run faster */ 105 | #undef LUAI_MAXSTACK 106 | #define LUAI_MAXSTACK 50000 107 | 108 | 109 | #undef LUAI_USER_ALIGNMENT_T 110 | #define LUAI_USER_ALIGNMENT_T union { char b[sizeof(void*) * 8]; } 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/main.lua: -------------------------------------------------------------------------------- 1 | # testing special comment on first line 2 | -- $Id: main.lua,v 1.62 2015/05/15 12:28:08 roberto Exp $ 3 | 4 | -- most (all?) tests here assume a reasonable "Unix-like" shell 5 | if _port then return end 6 | 7 | -- use only "double quotes" inside shell scripts (better change to 8 | -- run on Windows) 9 | 10 | 11 | print ("testing stand-alone interpreter") 12 | 13 | assert(os.execute()) -- machine has a system command 14 | 15 | local arg = arg or _ARG 16 | 17 | local prog = os.tmpname() 18 | local otherprog = os.tmpname() 19 | local out = os.tmpname() 20 | 21 | local progname 22 | do 23 | local i = 0 24 | while arg[i] do i=i-1 end 25 | progname = arg[i+1] 26 | end 27 | print("progname: "..progname) 28 | 29 | local prepfile = function (s, p) 30 | p = p or prog 31 | io.output(p) 32 | io.write(s) 33 | assert(io.close()) 34 | end 35 | 36 | local function getoutput () 37 | io.input(out) 38 | local t = io.read("a") 39 | io.input():close() 40 | assert(os.remove(out)) 41 | return t 42 | end 43 | 44 | local function checkprogout (s) 45 | local t = getoutput() 46 | for line in string.gmatch(s, ".-\n") do 47 | assert(string.find(t, line, 1, true)) 48 | end 49 | end 50 | 51 | local function checkout (s) 52 | local t = getoutput() 53 | if s ~= t then print(string.format("'%s' - '%s'\n", s, t)) end 54 | assert(s == t) 55 | return t 56 | end 57 | 58 | 59 | local function RUN (p, ...) 60 | p = string.gsub(p, "lua", '"'..progname..'"', 1) 61 | local s = string.format(p, ...) 62 | assert(os.execute(s)) 63 | end 64 | 65 | local function NoRun (msg, p, ...) 66 | p = string.gsub(p, "lua", '"'..progname..'"', 1) 67 | local s = string.format(p, ...) 68 | s = string.format("%s 2> %s", s, out) -- will send error to 'out' 69 | assert(not os.execute(s)) 70 | assert(string.find(getoutput(), msg, 1, true)) -- check error message 71 | end 72 | 73 | RUN('lua -v') 74 | 75 | print(string.format("(temporary program file used in these tests: %s)", prog)) 76 | 77 | -- running stdin as a file 78 | prepfile"" 79 | RUN('lua - < %s > %s', prog, out) 80 | checkout("") 81 | 82 | prepfile[[ 83 | print( 84 | 1, a 85 | ) 86 | ]] 87 | RUN('lua - < %s > %s', prog, out) 88 | checkout("1\tnil\n") 89 | 90 | RUN('echo "print(10)\nprint(2)\n" | lua > %s', out) 91 | checkout("10\n2\n") 92 | 93 | 94 | -- test option '-' 95 | RUN('echo "print(arg[1])" | lua - -h > %s', out) 96 | checkout("-h\n") 97 | 98 | -- test environment variables used by Lua 99 | 100 | prepfile("print(package.path)") 101 | 102 | -- test LUA_PATH 103 | RUN('env LUA_INIT= LUA_PATH=x lua %s > %s', prog, out) 104 | checkout("x\n") 105 | 106 | -- test LUA_PATH_version 107 | RUN('env LUA_INIT= LUA_PATH_5_3=y LUA_PATH=x lua %s > %s', prog, out) 108 | checkout("y\n") 109 | 110 | -- test LUA_CPATH 111 | prepfile("print(package.cpath)") 112 | RUN('env LUA_INIT= LUA_CPATH=xuxu lua %s > %s', prog, out) 113 | checkout("xuxu\n") 114 | 115 | -- test LUA_CPATH_version 116 | RUN('env LUA_INIT= LUA_CPATH_5_3=yacc LUA_CPATH=x lua %s > %s', prog, out) 117 | checkout("yacc\n") 118 | 119 | -- test LUA_INIT (and its access to 'arg' table) 120 | prepfile("print(X)") 121 | RUN('env LUA_INIT="X=tonumber(arg[1])" lua %s 3.2 > %s', prog, out) 122 | checkout("3.2\n") 123 | 124 | -- test LUA_INIT_version 125 | prepfile("print(X)") 126 | RUN('env LUA_INIT_5_3="X=10" LUA_INIT="X=3" lua %s > %s', prog, out) 127 | checkout("10\n") 128 | 129 | -- test LUA_INIT for files 130 | prepfile("x = x or 10; print(x); x = x + 1") 131 | RUN('env LUA_INIT="@%s" lua %s > %s', prog, prog, out) 132 | checkout("10\n11\n") 133 | 134 | -- test errors in LUA_INIT 135 | NoRun('LUA_INIT:1: 10', 'env LUA_INIT="error(10)" lua') 136 | 137 | -- test option '-E' 138 | local defaultpath, defaultCpath 139 | 140 | do 141 | prepfile("print(package.path, package.cpath)") 142 | RUN('env LUA_INIT="error(10)" LUA_PATH=xxx LUA_CPATH=xxx lua -E %s > %s', 143 | prog, out) 144 | local out = getoutput() 145 | defaultpath = string.match(out, "^(.-)\t") 146 | defaultCpath = string.match(out, "\t(.-)$") 147 | end 148 | 149 | -- paths did not changed 150 | assert(not string.find(defaultpath, "xxx") and 151 | string.find(defaultpath, "lua") and 152 | not string.find(defaultCpath, "xxx") and 153 | string.find(defaultCpath, "lua")) 154 | 155 | 156 | -- test replacement of ';;' to default path 157 | local function convert (p) 158 | prepfile("print(package.path)") 159 | RUN('env LUA_PATH="%s" lua %s > %s', p, prog, out) 160 | local expected = getoutput() 161 | expected = string.sub(expected, 1, -2) -- cut final end of line 162 | assert(string.gsub(p, ";;", ";"..defaultpath..";") == expected) 163 | end 164 | 165 | convert(";") 166 | convert(";;") 167 | convert(";;;") 168 | convert(";;;;") 169 | convert(";;;;;") 170 | convert(";;a;;;bc") 171 | 172 | 173 | -- test -l over multiple libraries 174 | prepfile("print(1); a=2; return {x=15}") 175 | prepfile(("print(a); print(_G['%s'].x)"):format(prog), otherprog) 176 | RUN('env LUA_PATH="?;;" lua -l %s -l%s -lstring -l io %s > %s', prog, otherprog, otherprog, out) 177 | checkout("1\n2\n15\n2\n15\n") 178 | 179 | -- test 'arg' table 180 | local a = [[ 181 | assert(#arg == 3 and arg[1] == 'a' and 182 | arg[2] == 'b' and arg[3] == 'c') 183 | assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == '%s') 184 | assert(arg[4] == nil and arg[-4] == nil) 185 | local a, b, c = ... 186 | assert(... == 'a' and a == 'a' and b == 'b' and c == 'c') 187 | ]] 188 | a = string.format(a, progname) 189 | prepfile(a) 190 | RUN('lua "-e " -- %s a b c', prog) -- "-e " runs an empty command 191 | 192 | -- test 'arg' availability in libraries 193 | prepfile"assert(arg)" 194 | prepfile("assert(arg)", otherprog) 195 | RUN('env LUA_PATH="?;;" lua -l%s - < %s', prog, otherprog) 196 | 197 | -- test messing up the 'arg' table 198 | RUN('echo "print(...)" | lua -e "arg[1] = 100" - > %s', out) 199 | checkout("100\n") 200 | NoRun("'arg' is not a table", 'echo "" | lua -e "arg = 1" -') 201 | 202 | -- test error in 'print' 203 | RUN('echo 10 | lua -e "print=nil" -i > /dev/null 2> %s', out) 204 | assert(string.find(getoutput(), "error calling 'print'")) 205 | 206 | -- test 'debug.debug' 207 | RUN('echo "io.stderr:write(1000)\ncont" | lua -e "require\'debug\'.debug()" 2> %s', out) 208 | checkout("lua_debug> 1000lua_debug> ") 209 | 210 | -- test many arguments 211 | prepfile[[print(({...})[30])]] 212 | RUN('lua %s %s > %s', prog, string.rep(" a", 30), out) 213 | checkout("a\n") 214 | 215 | RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out) 216 | checkout("1\n3\n") 217 | 218 | -- test iteractive mode 219 | prepfile[[ 220 | (6*2-6) -- === 221 | a = 222 | 10 223 | print(a) 224 | a]] 225 | RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) 226 | checkprogout("6\n10\n10\n\n") 227 | 228 | prepfile("a = [[b\nc\nd\ne]]\n=a") 229 | RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) 230 | checkprogout("b\nc\nd\ne\n\n") 231 | 232 | prompt = "alo" 233 | prepfile[[ -- 234 | a = 2 235 | ]] 236 | RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out) 237 | local t = getoutput() 238 | assert(string.find(t, prompt .. ".*" .. prompt .. ".*" .. prompt)) 239 | 240 | -- test for error objects 241 | prepfile[[ 242 | debug = require "debug" 243 | m = {x=0} 244 | setmetatable(m, {__tostring = function(x) 245 | return tostring(debug.getinfo(4).currentline + x.x) 246 | end}) 247 | error(m) 248 | ]] 249 | NoRun(progname .. ": 6\n", [[lua %s]], prog) 250 | 251 | prepfile("error{}") 252 | NoRun("error object is a table value", [[lua %s]], prog) 253 | 254 | 255 | -- chunk broken in many lines 256 | s = [=[ -- 257 | function f ( x ) 258 | local a = [[ 259 | xuxu 260 | ]] 261 | local b = "\ 262 | xuxu\n" 263 | if x == 11 then return 1 + 12 , 2 + 20 end --[[ test multiple returns ]] 264 | return x + 1 265 | --\\ 266 | end 267 | return( f( 100 ) ) 268 | assert( a == b ) 269 | do return f( 11 ) end ]=] 270 | s = string.gsub(s, ' ', '\n\n') -- change all spaces for newlines 271 | prepfile(s) 272 | RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) 273 | checkprogout("101\n13\t22\n\n") 274 | 275 | prepfile[[#comment in 1st line without \n at the end]] 276 | RUN('lua %s', prog) 277 | 278 | prepfile[[#test line number when file starts with comment line 279 | debug = require"debug" 280 | print(debug.getinfo(1).currentline) 281 | ]] 282 | RUN('lua %s > %s', prog, out) 283 | checkprogout('3') 284 | 285 | -- close Lua with an open file 286 | prepfile(string.format([[io.output(%q); io.write('alo')]], out)) 287 | RUN('lua %s', prog) 288 | checkout('alo') 289 | 290 | -- bug in 5.2 beta (extra \0 after version line) 291 | RUN([[lua -v -e"print'hello'" > %s]], out) 292 | t = getoutput() 293 | assert(string.find(t, "PUC%-Rio\nhello")) 294 | 295 | 296 | -- testing os.exit 297 | prepfile("os.exit(nil, true)") 298 | RUN('lua %s', prog) 299 | prepfile("os.exit(0, true)") 300 | RUN('lua %s', prog) 301 | prepfile("os.exit(true, true)") 302 | RUN('lua %s', prog) 303 | prepfile("os.exit(1, true)") 304 | NoRun("", "lua %s", prog) -- no message 305 | prepfile("os.exit(false, true)") 306 | NoRun("", "lua %s", prog) -- no message 307 | 308 | -- remove temporary files 309 | assert(os.remove(prog)) 310 | assert(os.remove(otherprog)) 311 | assert(not os.remove(out)) 312 | 313 | -- invalid options 314 | NoRun("unrecognized option '-h'", "lua -h") 315 | NoRun("unrecognized option '---'", "lua ---") 316 | NoRun("unrecognized option '-Ex'", "lua -Ex") 317 | NoRun("unrecognized option '-vv'", "lua -vv") 318 | NoRun("unrecognized option '-iv'", "lua -iv") 319 | NoRun("'-e' needs argument", "lua -e") 320 | NoRun("syntax error", "lua -e a") 321 | NoRun("'-l' needs argument", "lua -l") 322 | 323 | 324 | if T then -- auxiliary library? 325 | print("testing 'not enough memory' to create a state") 326 | NoRun("not enough memory", "env MEMLIMIT=100 lua") 327 | end 328 | print('+') 329 | 330 | print('testing Ctrl C') 331 | do 332 | -- interrupt a script 333 | local function kill (pid) 334 | return os.execute(string.format('kill -INT %d 2> /dev/null', pid)) 335 | end 336 | 337 | -- function to run a script in background, returning its output file 338 | -- descriptor and its pid 339 | local function runback (luaprg) 340 | -- shell script to run 'luaprg' in background and echo its pid 341 | local shellprg = string.format('%s -e "%s" & echo $!', progname, luaprg) 342 | local f = io.popen(shellprg, "r") -- run shell script 343 | local pid = f:read() -- get pid for Lua script 344 | print("(if test fails now, it may leave a Lua script running in \z 345 | background, pid " .. pid .. ")") 346 | return f, pid 347 | end 348 | 349 | -- Lua script that runs protected infinite loop and then prints '42' 350 | local f, pid = runback[[ 351 | pcall(function () print(12); while true do end end); print(42)]] 352 | -- wait until script is inside 'pcall' 353 | assert(f:read() == "12") 354 | kill(pid) -- send INT signal to Lua script 355 | -- check that 'pcall' captured the exception and script continued running 356 | assert(f:read() == "42") -- expected output 357 | assert(f:close()) 358 | print("done") 359 | 360 | -- Lua script in a looooog unbreakable search 361 | local f, pid = runback[[ 362 | print(15); string.find(string.rep('a', 1000), '.*.*.*.*.*b')]] 363 | -- wait (so script can reach the loop) 364 | assert(f:read() == "15") 365 | assert(os.execute("sleep 1")) 366 | -- must send at least two INT signals to stop this Lua script 367 | local n = 100 368 | for i = 0, 100 do -- keep sending signals 369 | if not kill(pid) then -- until it fails 370 | n = i -- number of non-failed kills 371 | break 372 | end 373 | end 374 | assert(f:close()) 375 | assert(n >= 2) 376 | print(string.format("done (with %d kills)", n)) 377 | 378 | end 379 | 380 | print("OK") 381 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/pm.lua: -------------------------------------------------------------------------------- 1 | -- $Id: pm.lua,v 1.44 2015/03/04 13:09:38 roberto Exp $ 2 | 3 | print('testing pattern matching') 4 | 5 | local function checkerror (msg, f, ...) 6 | local s, err = pcall(f, ...) 7 | assert(not s and string.find(err, msg)) 8 | end 9 | 10 | 11 | function f(s, p) 12 | local i,e = string.find(s, p) 13 | if i then return string.sub(s, i, e) end 14 | end 15 | 16 | a,b = string.find('', '') -- empty patterns are tricky 17 | assert(a == 1 and b == 0); 18 | a,b = string.find('alo', '') 19 | assert(a == 1 and b == 0) 20 | a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position 21 | assert(a == 1 and b == 1) 22 | a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the midle 23 | assert(a == 5 and b == 7) 24 | a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the midle 25 | assert(a == 9 and b == 11) 26 | a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end 27 | assert(a == 9 and b == 11); 28 | a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position 29 | assert(a == 11 and b == 11) 30 | assert(string.find('a\0a\0a\0a\0\0ab', 'b\0') == nil) -- check ending 31 | assert(string.find('', '\0') == nil) 32 | assert(string.find('alo123alo', '12') == 4) 33 | assert(string.find('alo123alo', '^12') == nil) 34 | 35 | assert(string.match("aaab", ".*b") == "aaab") 36 | assert(string.match("aaa", ".*a") == "aaa") 37 | assert(string.match("b", ".*b") == "b") 38 | 39 | assert(string.match("aaab", ".+b") == "aaab") 40 | assert(string.match("aaa", ".+a") == "aaa") 41 | assert(not string.match("b", ".+b")) 42 | 43 | assert(string.match("aaab", ".?b") == "ab") 44 | assert(string.match("aaa", ".?a") == "aa") 45 | assert(string.match("b", ".?b") == "b") 46 | 47 | assert(f('aloALO', '%l*') == 'alo') 48 | assert(f('aLo_ALO', '%a*') == 'aLo') 49 | 50 | assert(f(" \n\r*&\n\r xuxu \n\n", "%g%g%g+") == "xuxu") 51 | 52 | assert(f('aaab', 'a*') == 'aaa'); 53 | assert(f('aaa', '^.*$') == 'aaa'); 54 | assert(f('aaa', 'b*') == ''); 55 | assert(f('aaa', 'ab*a') == 'aa') 56 | assert(f('aba', 'ab*a') == 'aba') 57 | assert(f('aaab', 'a+') == 'aaa') 58 | assert(f('aaa', '^.+$') == 'aaa') 59 | assert(f('aaa', 'b+') == nil) 60 | assert(f('aaa', 'ab+a') == nil) 61 | assert(f('aba', 'ab+a') == 'aba') 62 | assert(f('a$a', '.$') == 'a') 63 | assert(f('a$a', '.%$') == 'a$') 64 | assert(f('a$a', '.$.') == 'a$a') 65 | assert(f('a$a', '$$') == nil) 66 | assert(f('a$b', 'a$') == nil) 67 | assert(f('a$a', '$') == '') 68 | assert(f('', 'b*') == '') 69 | assert(f('aaa', 'bb*') == nil) 70 | assert(f('aaab', 'a-') == '') 71 | assert(f('aaa', '^.-$') == 'aaa') 72 | assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab') 73 | assert(f('aabaaabaaabaaaba', 'b.-b') == 'baaab') 74 | assert(f('alo xo', '.o$') == 'xo') 75 | assert(f(' \n isto é assim', '%S%S*') == 'isto') 76 | assert(f(' \n isto é assim', '%S*$') == 'assim') 77 | assert(f(' \n isto é assim', '[a-z]*$') == 'assim') 78 | assert(f('um caracter ? extra', '[^%sa-z]') == '?') 79 | assert(f('', 'a?') == '') 80 | assert(f('á', 'á?') == 'á') 81 | assert(f('ábl', 'á?b?l?') == 'ábl') 82 | assert(f(' ábl', 'á?b?l?') == '') 83 | assert(f('aa', '^aa?a?a') == 'aa') 84 | assert(f(']]]áb', '[^]]') == 'á') 85 | assert(f("0alo alo", "%x*") == "0a") 86 | assert(f("alo alo", "%C+") == "alo alo") 87 | print('+') 88 | 89 | 90 | function f1(s, p) 91 | p = string.gsub(p, "%%([0-9])", function (s) 92 | return "%" .. (tonumber(s)+1) 93 | end) 94 | p = string.gsub(p, "^(^?)", "%1()", 1) 95 | p = string.gsub(p, "($?)$", "()%1", 1) 96 | local t = {string.match(s, p)} 97 | return string.sub(s, t[1], t[#t] - 1) 98 | end 99 | 100 | assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o") 101 | assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3') 102 | assert(f1('=======', '^(=*)=%1$') == '=======') 103 | assert(string.match('==========', '^([=]*)=%1$') == nil) 104 | 105 | local function range (i, j) 106 | if i <= j then 107 | return i, range(i+1, j) 108 | end 109 | end 110 | 111 | local abc = string.char(range(0, 255)); 112 | 113 | assert(string.len(abc) == 256) 114 | 115 | function strset (p) 116 | local res = {s=''} 117 | string.gsub(abc, p, function (c) res.s = res.s .. c end) 118 | return res.s 119 | end; 120 | 121 | assert(string.len(strset('[\200-\210]')) == 11) 122 | 123 | assert(strset('[a-z]') == "abcdefghijklmnopqrstuvwxyz") 124 | assert(strset('[a-z%d]') == strset('[%da-uu-z]')) 125 | assert(strset('[a-]') == "-a") 126 | assert(strset('[^%W]') == strset('[%w]')) 127 | assert(strset('[]%%]') == '%]') 128 | assert(strset('[a%-z]') == '-az') 129 | assert(strset('[%^%[%-a%]%-b]') == '-[]^ab') 130 | assert(strset('%Z') == strset('[\1-\255]')) 131 | assert(strset('.') == strset('[\1-\255%z]')) 132 | print('+'); 133 | 134 | assert(string.match("alo xyzK", "(%w+)K") == "xyz") 135 | assert(string.match("254 K", "(%d*)K") == "") 136 | assert(string.match("alo ", "(%w*)$") == "") 137 | assert(string.match("alo ", "(%w+)$") == nil) 138 | assert(string.find("(álo)", "%(á") == 1) 139 | local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$") 140 | assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil) 141 | a, b, c, d = string.match('0123456789', '(.+(.?)())') 142 | assert(a == '0123456789' and b == '' and c == 11 and d == nil) 143 | print('+') 144 | 145 | assert(string.gsub('ülo ülo', 'ü', 'x') == 'xlo xlo') 146 | assert(string.gsub('alo úlo ', ' +$', '') == 'alo úlo') -- trim 147 | assert(string.gsub(' alo alo ', '^%s*(.-)%s*$', '%1') == 'alo alo') -- double trim 148 | assert(string.gsub('alo alo \n 123\n ', '%s+', ' ') == 'alo alo 123 ') 149 | t = "abç d" 150 | a, b = string.gsub(t, '(.)', '%1@') 151 | assert('@'..a == string.gsub(t, '', '@') and b == 5) 152 | a, b = string.gsub('abçd', '(.)', '%0@', 2) 153 | assert(a == 'a@b@çd' and b == 2) 154 | assert(string.gsub('alo alo', '()[al]', '%1') == '12o 56o') 155 | assert(string.gsub("abc=xyz", "(%w*)(%p)(%w+)", "%3%2%1-%0") == 156 | "xyz=abc-abc=xyz") 157 | assert(string.gsub("abc", "%w", "%1%0") == "aabbcc") 158 | assert(string.gsub("abc", "%w+", "%0%1") == "abcabc") 159 | assert(string.gsub('áéí', '$', '\0óú') == 'áéí\0óú') 160 | assert(string.gsub('', '^', 'r') == 'r') 161 | assert(string.gsub('', '$', 'r') == 'r') 162 | print('+') 163 | 164 | assert(string.gsub("um (dois) tres (quatro)", "(%(%w+%))", string.upper) == 165 | "um (DOIS) tres (QUATRO)") 166 | 167 | do 168 | local function setglobal (n,v) rawset(_G, n, v) end 169 | string.gsub("a=roberto,roberto=a", "(%w+)=(%w%w*)", setglobal) 170 | assert(_G.a=="roberto" and _G.roberto=="a") 171 | end 172 | 173 | function f(a,b) return string.gsub(a,'.',b) end 174 | assert(string.gsub("trocar tudo em |teste|b| é |beleza|al|", "|([^|]*)|([^|]*)|", f) == 175 | "trocar tudo em bbbbb é alalalalalal") 176 | 177 | local function dostring (s) return load(s, "")() or "" end 178 | assert(string.gsub("alo $a='x'$ novamente $return a$", 179 | "$([^$]*)%$", 180 | dostring) == "alo novamente x") 181 | 182 | x = string.gsub("$x=string.gsub('alo', '.', string.upper)$ assim vai para $return x$", 183 | "$([^$]*)%$", dostring) 184 | assert(x == ' assim vai para ALO') 185 | 186 | t = {} 187 | s = 'a alo jose joao' 188 | r = string.gsub(s, '()(%w+)()', function (a,w,b) 189 | assert(string.len(w) == b-a); 190 | t[a] = b-a; 191 | end) 192 | assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4) 193 | 194 | 195 | function isbalanced (s) 196 | return string.find(string.gsub(s, "%b()", ""), "[()]") == nil 197 | end 198 | 199 | assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a")) 200 | assert(not isbalanced("(9 ((8) 7) a b (\0 c) a")) 201 | assert(string.gsub("alo 'oi' alo", "%b''", '"') == 'alo " alo') 202 | 203 | 204 | local t = {"apple", "orange", "lime"; n=0} 205 | assert(string.gsub("x and x and x", "x", function () t.n=t.n+1; return t[t.n] end) 206 | == "apple and orange and lime") 207 | 208 | t = {n=0} 209 | string.gsub("first second word", "%w%w*", function (w) t.n=t.n+1; t[t.n] = w end) 210 | assert(t[1] == "first" and t[2] == "second" and t[3] == "word" and t.n == 3) 211 | 212 | t = {n=0} 213 | assert(string.gsub("first second word", "%w+", 214 | function (w) t.n=t.n+1; t[t.n] = w end, 2) == "first second word") 215 | assert(t[1] == "first" and t[2] == "second" and t[3] == nil) 216 | 217 | checkerror("invalid replacement value %(a table%)", 218 | string.gsub, "alo", ".", {a = {}}) 219 | checkerror("invalid capture index %%2", string.gsub, "alo", ".", "%2") 220 | checkerror("invalid capture index %%0", string.gsub, "alo", "(%0)", "a") 221 | checkerror("invalid capture index %%1", string.gsub, "alo", "(%1)", "a") 222 | checkerror("invalid use of '%%'", string.gsub, "alo", ".", "%x") 223 | 224 | -- bug since 2.5 (C-stack overflow) 225 | do 226 | local function f (size) 227 | local s = string.rep("a", size) 228 | local p = string.rep(".?", size) 229 | return pcall(string.match, s, p) 230 | end 231 | local r, m = f(80) 232 | assert(r and #m == 80) 233 | r, m = f(200000) 234 | assert(not r and string.find(m, "too complex")) 235 | end 236 | 237 | if not _soft then 238 | -- big strings 239 | local a = string.rep('a', 300000) 240 | assert(string.find(a, '^a*.?$')) 241 | assert(not string.find(a, '^a*.?b$')) 242 | assert(string.find(a, '^a-.?$')) 243 | 244 | -- bug in 5.1.2 245 | a = string.rep('a', 10000) .. string.rep('b', 10000) 246 | assert(not pcall(string.gsub, a, 'b')) 247 | end 248 | 249 | -- recursive nest of gsubs 250 | function rev (s) 251 | return string.gsub(s, "(.)(.+)", function (c,s1) return rev(s1)..c end) 252 | end 253 | 254 | local x = "abcdef" 255 | assert(rev(rev(x)) == x) 256 | 257 | 258 | -- gsub with tables 259 | assert(string.gsub("alo alo", ".", {}) == "alo alo") 260 | assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo") 261 | assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo") 262 | assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo") 263 | 264 | assert(string.gsub("alo alo", "().", {'x','yy','zzz'}) == "xyyzzz alo") 265 | 266 | t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end}) 267 | assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI") 268 | 269 | 270 | -- tests for gmatch 271 | local a = 0 272 | for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end 273 | assert(a==6) 274 | 275 | t = {n=0} 276 | for w in string.gmatch("first second word", "%w+") do 277 | t.n=t.n+1; t[t.n] = w 278 | end 279 | assert(t[1] == "first" and t[2] == "second" and t[3] == "word") 280 | 281 | t = {3, 6, 9} 282 | for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do 283 | assert(i == table.remove(t, 1)) 284 | end 285 | assert(#t == 0) 286 | 287 | t = {} 288 | for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do 289 | t[tonumber(i)] = tonumber(j) 290 | end 291 | a = 0 292 | for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end 293 | assert(a == 3) 294 | 295 | 296 | -- tests for `%f' (`frontiers') 297 | 298 | assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x") 299 | assert(string.gsub("[[]] [][] [[[[", "%f[[].", "x") == "x[]] x]x] x[[[") 300 | assert(string.gsub("01abc45de3", "%f[%d]", ".") == ".01abc.45de.3") 301 | assert(string.gsub("01abc45 de3x", "%f[%D]%w", ".") == "01.bc45 de3.") 302 | assert(string.gsub("function", "%f[\1-\255]%w", ".") == ".unction") 303 | assert(string.gsub("function", "%f[^\1-\255]", ".") == "function.") 304 | 305 | assert(string.find("a", "%f[a]") == 1) 306 | assert(string.find("a", "%f[^%z]") == 1) 307 | assert(string.find("a", "%f[^%l]") == 2) 308 | assert(string.find("aba", "%f[a%z]") == 3) 309 | assert(string.find("aba", "%f[%z]") == 4) 310 | assert(not string.find("aba", "%f[%l%z]")) 311 | assert(not string.find("aba", "%f[^%l%z]")) 312 | 313 | local i, e = string.find(" alo aalo allo", "%f[%S].-%f[%s].-%f[%S]") 314 | assert(i == 2 and e == 5) 315 | local k = string.match(" alo aalo allo", "%f[%S](.-%f[%s].-%f[%S])") 316 | assert(k == 'alo ') 317 | 318 | local a = {1, 5, 9, 14, 17,} 319 | for k in string.gmatch("alo alo th02 is 1hat", "()%f[%w%d]") do 320 | assert(table.remove(a, 1) == k) 321 | end 322 | assert(#a == 0) 323 | 324 | 325 | -- malformed patterns 326 | local function malform (p, m) 327 | m = m or "malformed" 328 | local r, msg = pcall(string.find, "a", p) 329 | assert(not r and string.find(msg, m)) 330 | end 331 | 332 | malform("(.", "unfinished capture") 333 | malform(".)", "invalid pattern capture") 334 | malform("[a") 335 | malform("[]") 336 | malform("[^]") 337 | malform("[a%]") 338 | malform("[a%") 339 | malform("%b") 340 | malform("%ba") 341 | malform("%") 342 | malform("%f", "missing") 343 | 344 | -- \0 in patterns 345 | assert(string.match("ab\0\1\2c", "[\0-\2]+") == "\0\1\2") 346 | assert(string.match("ab\0\1\2c", "[\0-\0]+") == "\0") 347 | assert(string.find("b$a", "$\0?") == 2) 348 | assert(string.find("abc\0efg", "%\0") == 4) 349 | assert(string.match("abc\0efg\0\1e\1g", "%b\0\1") == "\0efg\0\1e\1") 350 | assert(string.match("abc\0\0\0", "%\0+") == "\0\0\0") 351 | assert(string.match("abc\0\0\0", "%\0%\0?") == "\0\0") 352 | 353 | -- magic char after \0 354 | assert(string.find("abc\0\0","\0.") == 4) 355 | assert(string.find("abcx\0\0abc\0abc","x\0\0abc\0a.") == 4) 356 | 357 | print('OK') 358 | 359 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/sort.lua: -------------------------------------------------------------------------------- 1 | -- $Id: sort.lua,v 1.32 2015/03/04 13:09:38 roberto Exp $ 2 | 3 | print "testing (parts of) table library" 4 | 5 | print "testing unpack" 6 | 7 | local unpack = table.unpack 8 | 9 | local maxI = math.maxinteger 10 | local minI = math.mininteger 11 | 12 | 13 | local function checkerror (msg, f, ...) 14 | local s, err = pcall(f, ...) 15 | assert(not s and string.find(err, msg)) 16 | end 17 | 18 | 19 | checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4) 20 | 21 | local x,y,z,a,n 22 | a = {}; lim = _soft and 200 or 2000 23 | for i=1, lim do a[i]=i end 24 | assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim) 25 | x = unpack(a) 26 | assert(x == 1) 27 | x = {unpack(a)} 28 | assert(#x == lim and x[1] == 1 and x[lim] == lim) 29 | x = {unpack(a, lim-2)} 30 | assert(#x == 3 and x[1] == lim-2 and x[3] == lim) 31 | x = {unpack(a, 10, 6)} 32 | assert(next(x) == nil) -- no elements 33 | x = {unpack(a, 11, 10)} 34 | assert(next(x) == nil) -- no elements 35 | x,y = unpack(a, 10, 10) 36 | assert(x == 10 and y == nil) 37 | x,y,z = unpack(a, 10, 11) 38 | assert(x == 10 and y == 11 and z == nil) 39 | a,x = unpack{1} 40 | assert(a==1 and x==nil) 41 | a,x = unpack({1,2}, 1, 1) 42 | assert(a==1 and x==nil) 43 | 44 | do 45 | local maxi = (1 << 31) - 1 -- maximum value for an int (usually) 46 | local mini = -(1 << 31) -- minimum value for an int (usually) 47 | checkerror("too many results", unpack, {}, 0, maxi) 48 | checkerror("too many results", unpack, {}, 1, maxi) 49 | checkerror("too many results", unpack, {}, 0, maxI) 50 | checkerror("too many results", unpack, {}, 1, maxI) 51 | checkerror("too many results", unpack, {}, mini, maxi) 52 | checkerror("too many results", unpack, {}, -maxi, maxi) 53 | checkerror("too many results", unpack, {}, minI, maxI) 54 | unpack({}, maxi, 0) 55 | unpack({}, maxi, 1) 56 | unpack({}, maxI, minI) 57 | pcall(unpack, {}, 1, maxi + 1) 58 | local a, b = unpack({[maxi] = 20}, maxi, maxi) 59 | assert(a == 20 and b == nil) 60 | a, b = unpack({[maxi] = 20}, maxi - 1, maxi) 61 | assert(a == nil and b == 20) 62 | local t = {[maxI - 1] = 12, [maxI] = 23} 63 | a, b = unpack(t, maxI - 1, maxI); assert(a == 12 and b == 23) 64 | a, b = unpack(t, maxI, maxI); assert(a == 23 and b == nil) 65 | a, b = unpack(t, maxI, maxI - 1); assert(a == nil and b == nil) 66 | t = {[minI] = 12.3, [minI + 1] = 23.5} 67 | a, b = unpack(t, minI, minI + 1); assert(a == 12.3 and b == 23.5) 68 | a, b = unpack(t, minI, minI); assert(a == 12.3 and b == nil) 69 | a, b = unpack(t, minI + 1, minI); assert(a == nil and b == nil) 70 | end 71 | 72 | do -- length is not an integer 73 | local t = setmetatable({}, {__len = function () return 'abc' end}) 74 | assert(#t == 'abc') 75 | checkerror("object length is not an integer", table.insert, t, 1) 76 | end 77 | 78 | print "testing pack" 79 | 80 | a = table.pack() 81 | assert(a[1] == nil and a.n == 0) 82 | 83 | a = table.pack(table) 84 | assert(a[1] == table and a.n == 1) 85 | 86 | a = table.pack(nil, nil, nil, nil) 87 | assert(a[1] == nil and a.n == 4) 88 | 89 | 90 | -- testing move 91 | do 92 | local function eqT (a, b) 93 | for k, v in pairs(a) do assert(b[k] == v) end 94 | for k, v in pairs(b) do assert(a[k] == v) end 95 | end 96 | 97 | local a = table.move({10,20,30}, 1, 3, 2) -- move forward 98 | eqT(a, {10,10,20,30}) 99 | 100 | a = table.move({10,20,30}, 2, 3, 1) -- move backward 101 | eqT(a, {20,30,30}) 102 | 103 | a = table.move({10,20,30}, 1, 3, 1, {}) -- move 104 | eqT(a, {10,20,30}) 105 | 106 | a = table.move({10,20,30}, 1, 0, 3, {}) -- do not move 107 | eqT(a, {}) 108 | 109 | a = table.move({10,20,30}, 1, 10, 1) -- move to the same place 110 | eqT(a, {10,20,30}) 111 | 112 | a = table.move({[maxI - 2] = 1, [maxI - 1] = 2, [maxI] = 3}, 113 | maxI - 2, maxI, -10, {}) 114 | eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3}) 115 | 116 | a = table.move({[minI] = 1, [minI + 1] = 2, [minI + 2] = 3}, 117 | minI, minI + 2, -10, {}) 118 | eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3}) 119 | 120 | a = table.move({45}, 1, 1, maxI) 121 | eqT(a, {45, [maxI] = 45}) 122 | 123 | a = table.move({[maxI] = 100}, maxI, maxI, minI) 124 | eqT(a, {[minI] = 100, [maxI] = 100}) 125 | 126 | a = table.move({[minI] = 100}, minI, minI, maxI) 127 | eqT(a, {[minI] = 100, [maxI] = 100}) 128 | 129 | a = setmetatable({}, { 130 | __index = function (_,k) return k * 10 end, 131 | __newindex = error}) 132 | local b = table.move(a, 1, 10, 3, {}) 133 | eqT(a, {}) 134 | eqT(b, {nil,nil,10,20,30,40,50,60,70,80,90,100}) 135 | 136 | b = setmetatable({""}, { 137 | __index = error, 138 | __newindex = function (t,k,v) 139 | t[1] = string.format("%s(%d,%d)", t[1], k, v) 140 | end}) 141 | table.move(a, 10, 13, 3, b) 142 | assert(b[1] == "(3,100)(4,110)(5,120)(6,130)") 143 | local stat, msg = pcall(table.move, b, 10, 13, 3, b) 144 | assert(not stat and msg == b) 145 | end 146 | 147 | do 148 | -- for very long moves, just check initial accesses and interrupt 149 | -- move with an error 150 | local function checkmove (f, e, t, x, y) 151 | local pos1, pos2 152 | local a = setmetatable({}, { 153 | __index = function (_,k) pos1 = k end, 154 | __newindex = function (_,k) pos2 = k; error() end, }) 155 | local st, msg = pcall(table.move, a, f, e, t) 156 | assert(not st and not msg and pos1 == x and pos2 == y) 157 | end 158 | checkmove(1, maxI, 0, 1, 0) 159 | checkmove(0, maxI - 1, 1, maxI - 1, maxI) 160 | checkmove(minI, -2, 0, -2, maxI - 1) 161 | checkmove(minI + 1, -1, 1, -1, maxI) 162 | end 163 | 164 | checkerror("too many", table.move, {}, 0, maxI, 1) 165 | checkerror("too many", table.move, {}, -1, maxI - 1, 1) 166 | checkerror("too many", table.move, {}, minI, -1, 1) 167 | checkerror("too many", table.move, {}, minI, maxI, 1) 168 | checkerror("wrap around", table.move, {}, 1, maxI, 2) 169 | checkerror("wrap around", table.move, {}, 1, 2, maxI) 170 | checkerror("wrap around", table.move, {}, minI, -2, 2) 171 | 172 | 173 | print"testing sort" 174 | 175 | 176 | -- test checks for invalid order functions 177 | local function check (t) 178 | local function f(a, b) assert(a and b); return true end 179 | checkerror("invalid order function", table.sort, t, f) 180 | end 181 | 182 | check{1,2,3,4} 183 | check{1,2,3,4,5} 184 | check{1,2,3,4,5,6} 185 | 186 | 187 | function check (a, f) 188 | f = f or function (x,y) return xI" .. i, 0xAA) == s:reverse()) 69 | assert(unpack(">I" .. i, s:reverse()) == 0xAA) 70 | end 71 | 72 | do 73 | local lnum = 0x13121110090807060504030201 74 | local s = pack("i" .. i, ("\xFF"):rep(i - sizeLI) .. s:reverse()) == -lnum) 85 | assert(unpack("i" .. i, "\1" .. ("\x00"):rep(i - 1)) 90 | end 91 | end 92 | 93 | for i = 1, sizeLI do 94 | local lstr = "\1\2\3\4\5\6\7\8\9\10\11\12\13" 95 | local lnum = 0x13121110090807060504030201 96 | local n = lnum & (~(-1 << (i * 8))) 97 | local s = string.sub(lstr, 1, i) 98 | assert(pack("i" .. i, n) == s:reverse()) 100 | assert(unpack(">i" .. i, s:reverse()) == n) 101 | end 102 | 103 | -- sign extension 104 | do 105 | local u = 0xf0 106 | for i = 1, sizeLI - 1 do 107 | assert(unpack("I"..i, "\xf0"..("\xff"):rep(i - 1)) == u) 109 | u = u * 256 + 0xff 110 | end 111 | end 112 | 113 | -- mixed endianness 114 | do 115 | assert(pack(">i2 i2", "\10\0\0\20") 117 | assert(a == 10 and b == 20) 118 | assert(pack("=i4", 2001) == pack("i4", 2001)) 119 | end 120 | 121 | print("testing invalid formats") 122 | 123 | checkerror("out of limits", pack, "i0", 0) 124 | checkerror("out of limits", pack, "i" .. NB + 1, 0) 125 | checkerror("out of limits", pack, "!" .. NB + 1, 0) 126 | checkerror("%(17%) out of limits %[1,16%]", pack, "Xi" .. NB + 1) 127 | checkerror("invalid format option 'r'", pack, "i3r", 0) 128 | checkerror("16%-byte integer", unpack, "i16", string.rep('\3', 16)) 129 | checkerror("not power of 2", pack, "!4i3", 0); 130 | checkerror("missing size", pack, "c", "") 131 | checkerror("variable%-length format", packsize, "s") 132 | checkerror("variable%-length format", packsize, "z") 133 | 134 | -- overflow in option size (error will be in digit after limit) 135 | checkerror("invalid format", packsize, "c1" .. string.rep("0", 40)) 136 | 137 | if packsize("i") == 4 then 138 | -- result would be 2^31 (2^3 repetitions of 2^28 strings) 139 | local s = string.rep("c268435456", 2^3) 140 | checkerror("too large", packsize, s) 141 | -- one less is OK 142 | s = string.rep("c268435456", 2^3 - 1) .. "c268435455" 143 | assert(packsize(s) == 0x7fffffff) 144 | end 145 | 146 | -- overflow in packing 147 | for i = 1, sizeLI - 1 do 148 | local umax = (1 << (i * 8)) - 1 149 | local max = umax >> 1 150 | local min = ~max 151 | checkerror("overflow", pack, "I" .. i, umax + 1) 154 | 155 | checkerror("overflow", pack, ">i" .. i, umax) 156 | checkerror("overflow", pack, ">i" .. i, max + 1) 157 | checkerror("overflow", pack, "i" .. i, pack(">i" .. i, max)) == max) 160 | assert(unpack("I" .. i, pack(">I" .. i, umax)) == umax) 162 | end 163 | 164 | -- Lua integer size 165 | assert(unpack(">j", pack(">j", math.maxinteger)) == math.maxinteger) 166 | assert(unpack("f", 24)) 173 | end 174 | 175 | print "testing pack/unpack of floating-point numbers" 176 | 177 | for _, n in ipairs{0, -1.1, 1.9, 1/0, -1/0, 1e20, -1e20, 0.1, 2000.7} do 178 | assert(unpack("n", pack("n", n)) == n) 179 | assert(unpack("n", pack(">n", n)) == n) 181 | assert(pack("f", n):reverse()) 182 | assert(pack(">d", n) == pack("f", pack(">f", n)) == n) 189 | assert(unpack("d", pack(">d", n)) == n) 191 | end 192 | 193 | print "testing pack/unpack of strings" 194 | do 195 | local s = string.rep("abc", 1000) 196 | assert(pack("zB", s, 247) == s .. "\0\xF7") 197 | local s1, b = unpack("zB", s .. "\0\xF9") 198 | assert(b == 249 and s1 == s) 199 | s1 = pack("s", s) 200 | assert(unpack("s", s1) == s) 201 | 202 | checkerror("does not fit", pack, "s1", s) 203 | 204 | checkerror("contains zeros", pack, "z", "alo\0"); 205 | 206 | for i = 2, NB do 207 | local s1 = pack("s" .. i, s) 208 | assert(unpack("s" .. i, s1) == s and #s1 == #s + i) 209 | end 210 | end 211 | 212 | do 213 | local x = pack("s", "alo") 214 | checkerror("too short", unpack, "s", x:sub(1, -2)) 215 | checkerror("too short", unpack, "c5", "abcd") 216 | checkerror("out of limits", pack, "s100", "alo") 217 | end 218 | 219 | do 220 | assert(pack("c0", "") == "") 221 | assert(packsize("c0") == 0) 222 | assert(unpack("c0", "") == "") 223 | assert(pack("!4 c6", "abcdef") == "abcdef") 226 | checkerror("wrong length", pack, "c3", "ab") 227 | checkerror("2", pack, "c5", "123456") 228 | local a, b, c = unpack("!4 z c3", "abcdefghi\0xyz") 229 | assert(a == "abcdefghi" and b == "xyz" and c == 14) 230 | end 231 | 232 | 233 | -- testing multiple types and sequence 234 | do 235 | local x = pack("!8 b Xh i4 i8 c1 Xi8", -12, 100, 200, "\xEC") 246 | assert(#x == packsize(">!8 b Xh i4 i8 c1 Xi8")) 247 | assert(x == "\xf4" .. "\0\0\0" .. 248 | "\0\0\0\100" .. 249 | "\0\0\0\0\0\0\0\xC8" .. 250 | "\xEC" .. "\0\0\0\0\0\0\0") 251 | local a, b, c, d, pos = unpack(">!8 c1 Xh i4 i8 b Xi8 XI XH", x) 252 | assert(a == "\xF4" and b == 100 and c == 200 and d == -20 and (pos - 1) == #x) 253 | 254 | x = pack(">!4 c3 c4 c2 z i4 c5 c2 Xi4", 255 | "abc", "abcd", "xz", "hello", 5, "world", "xy") 256 | assert(x == "abcabcdxzhello\0\0\0\0\0\5worldxy\0") 257 | local a, b, c, d, e, f, g, pos = unpack(">!4 c3 c4 c2 z i4 c5 c2 Xh Xi4", x) 258 | assert(a == "abc" and b == "abcd" and c == "xz" and d == "hello" and 259 | e == 5 and f == "world" and g == "xy" and (pos - 1) % 4 == 0) 260 | 261 | x = pack(" b b Xd b Xb x", 1, 2, 3) 262 | assert(packsize(" b b Xd b Xb x") == 4) 263 | assert(x == "\1\2\3\0") 264 | a, b, c, pos = unpack("bbXdb", x) 265 | assert(a == 1 and b == 2 and c == 3 and pos == #x) 266 | 267 | -- only alignment 268 | assert(packsize("!8 xXi8") == 8) 269 | local pos = unpack("!8 xXi8", "0123456701234567"); assert(pos == 9) 270 | assert(packsize("!8 xXi2") == 2) 271 | local pos = unpack("!8 xXi2", "0123456701234567"); assert(pos == 3) 272 | assert(packsize("!2 xXi2") == 2) 273 | local pos = unpack("!2 xXi2", "0123456701234567"); assert(pos == 3) 274 | assert(packsize("!2 xXi8") == 2) 275 | local pos = unpack("!2 xXi8", "0123456701234567"); assert(pos == 3) 276 | assert(packsize("!16 xXi16") == 16) 277 | local pos = unpack("!16 xXi16", "0123456701234567"); assert(pos == 17) 278 | 279 | checkerror("invalid next option", pack, "X") 280 | checkerror("invalid next option", unpack, "XXi", "") 281 | checkerror("invalid next option", unpack, "X i", "") 282 | checkerror("invalid next option", pack, "Xc1") 283 | end 284 | 285 | do -- testing initial position 286 | local x = pack("i4i4i4i4", 1, 2, 3, 4) 287 | for pos = 1, 16, 4 do 288 | local i, p = unpack("i4", x, pos) 289 | assert(i == pos//4 + 1 and p == pos + 4) 290 | end 291 | 292 | -- with alignment 293 | for pos = 0, 12 do -- will always round position to power of 2 294 | local i, p = unpack("!4 i4", x, pos + 1) 295 | assert(i == (pos + 3)//4 + 1 and p == i*4 + 1) 296 | end 297 | 298 | -- negative indices 299 | local i, p = unpack("!4 i4", x, -4) 300 | assert(i == 4 and p == 17) 301 | local i, p = unpack("!4 i4", x, -7) 302 | assert(i == 4 and p == 17) 303 | local i, p = unpack("!4 i4", x, -#x) 304 | assert(i == 1 and p == 5) 305 | 306 | -- limits 307 | for i = 1, #x + 1 do 308 | assert(unpack("c0", x, i) == "") 309 | end 310 | checkerror("out of string", unpack, "c0", x, 0) 311 | checkerror("out of string", unpack, "c0", x, #x + 2) 312 | checkerror("out of string", unpack, "c0", x, -(#x + 1)) 313 | 314 | end 315 | 316 | print "OK" 317 | 318 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/utf8.lua: -------------------------------------------------------------------------------- 1 | -- $Id: utf8.lua,v 1.11 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | print "testing UTF-8 library" 4 | 5 | local utf8 = require'utf8' 6 | 7 | 8 | local function checkerror (msg, f, ...) 9 | local s, err = pcall(f, ...) 10 | assert(not s and string.find(err, msg)) 11 | end 12 | 13 | 14 | local function len (s) 15 | return #string.gsub(s, "[\x80-\xBF]", "") 16 | end 17 | 18 | 19 | local justone = "^" .. utf8.charpattern .. "$" 20 | 21 | -- 't' is the list of codepoints of 's' 22 | local function checksyntax (s, t) 23 | local ts = {"return '"} 24 | for i = 1, #t do ts[i + 1] = string.format("\\u{%x}", t[i]) end 25 | ts[#t + 2] = "'" 26 | ts = table.concat(ts) 27 | assert(assert(load(ts))() == s) 28 | end 29 | 30 | assert(utf8.offset("alo", 5) == nil) 31 | assert(utf8.offset("alo", -4) == nil) 32 | 33 | -- 't' is the list of codepoints of 's' 34 | local function check (s, t) 35 | local l = utf8.len(s) 36 | assert(#t == l and len(s) == l) 37 | assert(utf8.char(table.unpack(t)) == s) 38 | 39 | assert(utf8.offset(s, 0) == 1) 40 | 41 | checksyntax(s, t) 42 | 43 | local t1 = {utf8.codepoint(s, 1, -1)} 44 | assert(#t == #t1) 45 | for i = 1, #t do assert(t[i] == t1[i]) end 46 | 47 | for i = 1, l do 48 | local pi = utf8.offset(s, i) -- position of i-th char 49 | local pi1 = utf8.offset(s, 2, pi) -- position of next char 50 | assert(string.find(string.sub(s, pi, pi1 - 1), justone)) 51 | assert(utf8.offset(s, -1, pi1) == pi) 52 | assert(utf8.offset(s, i - l - 1) == pi) 53 | assert(pi1 - pi == #utf8.char(utf8.codepoint(s, pi))) 54 | for j = pi, pi1 - 1 do 55 | assert(utf8.offset(s, 0, j) == pi) 56 | end 57 | for j = pi + 1, pi1 - 1 do 58 | assert(not utf8.len(s, j)) 59 | end 60 | assert(utf8.len(s, pi, pi) == 1) 61 | assert(utf8.len(s, pi, pi1 - 1) == 1) 62 | assert(utf8.len(s, pi) == l - i + 1) 63 | assert(utf8.len(s, pi1) == l - i) 64 | assert(utf8.len(s, 1, pi) == i) 65 | end 66 | 67 | local i = 0 68 | for p, c in utf8.codes(s) do 69 | i = i + 1 70 | assert(c == t[i] and p == utf8.offset(s, i)) 71 | assert(utf8.codepoint(s, p) == c) 72 | end 73 | assert(i == #t) 74 | 75 | i = 0 76 | for p, c in utf8.codes(s) do 77 | i = i + 1 78 | assert(c == t[i] and p == utf8.offset(s, i)) 79 | end 80 | assert(i == #t) 81 | 82 | i = 0 83 | for c in string.gmatch(s, utf8.charpattern) do 84 | i = i + 1 85 | assert(c == utf8.char(t[i])) 86 | end 87 | assert(i == #t) 88 | 89 | for i = 1, l do 90 | assert(utf8.offset(s, i) == utf8.offset(s, i - l - 1, #s + 1)) 91 | end 92 | 93 | end 94 | 95 | 96 | do -- error indication in utf8.len 97 | local function check (s, p) 98 | local a, b = utf8.len(s) 99 | assert(not a and b == p) 100 | end 101 | check("abc\xE3def", 4) 102 | check("汉字\x80", #("汉字") + 1) 103 | check("\xF4\x9F\xBF", 1) 104 | check("\xF4\x9F\xBF\xBF", 1) 105 | end 106 | 107 | -- error in utf8.codes 108 | checkerror("invalid UTF%-8 code", 109 | function () 110 | local s = "ab\xff" 111 | for c in utf8.codes(s) do assert(c) end 112 | end) 113 | 114 | 115 | -- error in initial position for offset 116 | checkerror("position out of range", utf8.offset, "abc", 1, 5) 117 | checkerror("position out of range", utf8.offset, "abc", 1, -4) 118 | checkerror("position out of range", utf8.offset, "", 1, 2) 119 | checkerror("position out of range", utf8.offset, "", 1, -1) 120 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) 121 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) 122 | checkerror("continuation byte", utf8.offset, "\x80", 1) 123 | 124 | 125 | 126 | local s = "hello World" 127 | local t = {string.byte(s, 1, -1)} 128 | for i = 1, utf8.len(s) do assert(t[i] == string.byte(s, i)) end 129 | check(s, t) 130 | 131 | check("汉字/漢字", {27721, 23383, 47, 28450, 23383,}) 132 | 133 | do 134 | local s = "áéí\128" 135 | local t = {utf8.codepoint(s,1,#s - 1)} 136 | assert(#t == 3 and t[1] == 225 and t[2] == 233 and t[3] == 237) 137 | checkerror("invalid UTF%-8 code", utf8.codepoint, s, 1, #s) 138 | checkerror("out of range", utf8.codepoint, s, #s + 1) 139 | t = {utf8.codepoint(s, 4, 3)} 140 | assert(#t == 0) 141 | checkerror("out of range", utf8.codepoint, s, -(#s + 1), 1) 142 | checkerror("out of range", utf8.codepoint, s, 1, #s + 1) 143 | end 144 | 145 | assert(utf8.char() == "") 146 | assert(utf8.char(97, 98, 99) == "abc") 147 | 148 | assert(utf8.codepoint(utf8.char(0x10FFFF)) == 0x10FFFF) 149 | 150 | checkerror("value out of range", utf8.char, 0x10FFFF + 1) 151 | 152 | local function invalid (s) 153 | checkerror("invalid UTF%-8 code", utf8.codepoint, s) 154 | assert(not utf8.len(s)) 155 | end 156 | 157 | -- UTF-8 representation for 0x11ffff (value out of valid range) 158 | invalid("\xF4\x9F\xBF\xBF") 159 | 160 | -- overlong sequences 161 | invalid("\xC0\x80") -- zero 162 | invalid("\xC1\xBF") -- 0x7F (should be coded in 1 byte) 163 | invalid("\xE0\x9F\xBF") -- 0x7FF (should be coded in 2 bytes) 164 | invalid("\xF0\x8F\xBF\xBF") -- 0xFFFF (should be coded in 3 bytes) 165 | 166 | 167 | -- invalid bytes 168 | invalid("\x80") -- continuation byte 169 | invalid("\xBF") -- continuation byte 170 | invalid("\xFE") -- invalid byte 171 | invalid("\xFF") -- invalid byte 172 | 173 | 174 | -- empty string 175 | check("", {}) 176 | 177 | -- minimum and maximum values for each sequence size 178 | s = "\0 \x7F\z 179 | \xC2\x80 \xDF\xBF\z 180 | \xE0\xA0\x80 \xEF\xBF\xBF\z 181 | \xF0\x90\x80\x80 \xF4\x8F\xBF\xBF" 182 | s = string.gsub(s, " ", "") 183 | check(s, {0,0x7F, 0x80,0x7FF, 0x800,0xFFFF, 0x10000,0x10FFFF}) 184 | 185 | x = "日本語a-4\0éó" 186 | check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243}) 187 | 188 | 189 | -- Supplementary Characters 190 | check("𣲷𠜎𠱓𡁻𠵼ab𠺢", 191 | {0x23CB7, 0x2070E, 0x20C53, 0x2107B, 0x20D7C, 0x61, 0x62, 0x20EA2,}) 192 | 193 | check("𨳊𩶘𦧺𨳒𥄫𤓓\xF4\x8F\xBF\xBF", 194 | {0x28CCA, 0x29D98, 0x269FA, 0x28CD2, 0x2512B, 0x244D3, 0x10ffff}) 195 | 196 | 197 | local i = 0 198 | for p, c in string.gmatch(x, "()(" .. utf8.charpattern .. ")") do 199 | i = i + 1 200 | assert(utf8.offset(x, i) == p) 201 | assert(utf8.len(x, p) == utf8.len(x) - i + 1) 202 | assert(utf8.len(c) == 1) 203 | for j = 1, #c - 1 do 204 | assert(utf8.offset(x, 0, p + j - 1) == p) 205 | end 206 | end 207 | 208 | print'ok' 209 | 210 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/vararg.lua: -------------------------------------------------------------------------------- 1 | -- $Id: vararg.lua,v 1.24 2015/06/01 16:38:36 roberto Exp $ 2 | 3 | print('testing vararg') 4 | 5 | function f(a, ...) 6 | local arg = {n = select('#', ...), ...} 7 | for i=1,arg.n do assert(a[i]==arg[i]) end 8 | return arg.n 9 | end 10 | 11 | function c12 (...) 12 | assert(arg == _G.arg) -- no local 'arg' 13 | local x = {...}; x.n = #x 14 | local res = (x.n==2 and x[1] == 1 and x[2] == 2) 15 | if res then res = 55 end 16 | return res, 2 17 | end 18 | 19 | function vararg (...) return {n = select('#', ...), ...} end 20 | 21 | local call = function (f, args) return f(table.unpack(args, 1, args.n)) end 22 | 23 | assert(f() == 0) 24 | assert(f({1,2,3}, 1, 2, 3) == 3) 25 | assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5) 26 | 27 | assert(c12(1,2)==55) 28 | a,b = assert(call(c12, {1,2})) 29 | assert(a == 55 and b == 2) 30 | a = call(c12, {1,2;n=2}) 31 | assert(a == 55 and b == 2) 32 | a = call(c12, {1,2;n=1}) 33 | assert(not a) 34 | assert(c12(1,2,3) == false) 35 | local a = vararg(call(next, {_G,nil;n=2})) 36 | local b,c = next(_G) 37 | assert(a[1] == b and a[2] == c and a.n == 2) 38 | a = vararg(call(call, {c12, {1,2}})) 39 | assert(a.n == 2 and a[1] == 55 and a[2] == 2) 40 | a = call(print, {'+'}) 41 | assert(a == nil) 42 | 43 | local t = {1, 10} 44 | function t:f (...) local arg = {...}; return self[...]+#arg end 45 | assert(t:f(1,4) == 3 and t:f(2) == 11) 46 | print('+') 47 | 48 | lim = 20 49 | local i, a = 1, {} 50 | while i <= lim do a[i] = i+0.3; i=i+1 end 51 | 52 | function f(a, b, c, d, ...) 53 | local more = {...} 54 | assert(a == 1.3 and more[1] == 5.3 and 55 | more[lim-4] == lim+0.3 and not more[lim-3]) 56 | end 57 | 58 | function g(a,b,c) 59 | assert(a == 1.3 and b == 2.3 and c == 3.3) 60 | end 61 | 62 | call(f, a) 63 | call(g, a) 64 | 65 | a = {} 66 | i = 1 67 | while i <= lim do a[i] = i; i=i+1 end 68 | assert(call(math.max, a) == lim) 69 | 70 | print("+") 71 | 72 | 73 | -- new-style varargs 74 | 75 | function oneless (a, ...) return ... end 76 | 77 | function f (n, a, ...) 78 | local b 79 | assert(arg == _G.arg) -- no local 'arg' 80 | if n == 0 then 81 | local b, c, d = ... 82 | return a, b, c, d, oneless(oneless(oneless(...))) 83 | else 84 | n, b, a = n-1, ..., a 85 | assert(b == ...) 86 | return f(n, a, ...) 87 | end 88 | end 89 | 90 | a,b,c,d,e = assert(f(10,5,4,3,2,1)) 91 | assert(a==5 and b==4 and c==3 and d==2 and e==1) 92 | 93 | a,b,c,d,e = f(4) 94 | assert(a==nil and b==nil and c==nil and d==nil and e==nil) 95 | 96 | 97 | -- varargs for main chunks 98 | f = load[[ return {...} ]] 99 | x = f(2,3) 100 | assert(x[1] == 2 and x[2] == 3 and x[3] == nil) 101 | 102 | 103 | f = load[[ 104 | local x = {...} 105 | for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end 106 | assert(x[select('#', ...)+1] == nil) 107 | return true 108 | ]] 109 | 110 | assert(f("a", "b", nil, {}, assert)) 111 | assert(f()) 112 | 113 | a = {select(3, table.unpack{10,20,30,40})} 114 | assert(#a == 2 and a[1] == 30 and a[2] == 40) 115 | a = {select(1)} 116 | assert(next(a) == nil) 117 | a = {select(-1, 3, 5, 7)} 118 | assert(a[1] == 7 and a[2] == nil) 119 | a = {select(-2, 3, 5, 7)} 120 | assert(a[1] == 5 and a[2] == 7 and a[3] == nil) 121 | pcall(select, 10000) 122 | pcall(select, -10000) 123 | 124 | 125 | -- bug in 5.2.2 126 | 127 | function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, 128 | p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, 129 | p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, 130 | p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, 131 | p41, p42, p43, p44, p45, p46, p48, p49, p50, ...) 132 | local a1,a2,a3,a4,a5,a6,a7 133 | local a8,a9,a10,a11,a12,a13,a14 134 | end 135 | 136 | -- assertion fail here 137 | f() 138 | 139 | 140 | print('OK') 141 | 142 | -------------------------------------------------------------------------------- /lua-5.3.1-tests/verybig.lua: -------------------------------------------------------------------------------- 1 | -- $Id: verybig.lua,v 1.24 2014/12/26 17:20:53 roberto Exp $ 2 | 3 | print "testing RK" 4 | 5 | -- testing opcodes with RK arguments larger than K limit 6 | local function foo () 7 | local dummy = { 8 | -- fill first 256 entries in table of constants 9 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 11 | 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 12 | 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 13 | 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 14 | 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 15 | 97, 98, 99, 100, 101, 102, 103, 104, 16 | 105, 106, 107, 108, 109, 110, 111, 112, 17 | 113, 114, 115, 116, 117, 118, 119, 120, 18 | 121, 122, 123, 124, 125, 126, 127, 128, 19 | 129, 130, 131, 132, 133, 134, 135, 136, 20 | 137, 138, 139, 140, 141, 142, 143, 144, 21 | 145, 146, 147, 148, 149, 150, 151, 152, 22 | 153, 154, 155, 156, 157, 158, 159, 160, 23 | 161, 162, 163, 164, 165, 166, 167, 168, 24 | 169, 170, 171, 172, 173, 174, 175, 176, 25 | 177, 178, 179, 180, 181, 182, 183, 184, 26 | 185, 186, 187, 188, 189, 190, 191, 192, 27 | 193, 194, 195, 196, 197, 198, 199, 200, 28 | 201, 202, 203, 204, 205, 206, 207, 208, 29 | 209, 210, 211, 212, 213, 214, 215, 216, 30 | 217, 218, 219, 220, 221, 222, 223, 224, 31 | 225, 226, 227, 228, 229, 230, 231, 232, 32 | 233, 234, 235, 236, 237, 238, 239, 240, 33 | 241, 242, 243, 244, 245, 246, 247, 248, 34 | 249, 250, 251, 252, 253, 254, 255, 256, 35 | } 36 | assert(24.5 + 0.6 == 25.1) 37 | local t = {foo = function (self, x) return x + self.x end, x = 10} 38 | t.t = t 39 | assert(t:foo(1.5) == 11.5) 40 | assert(t.t:foo(0.5) == 10.5) -- bug in 5.2 alpha 41 | assert(24.3 == 24.3) 42 | assert((function () return t.x end)() == 10) 43 | end 44 | 45 | 46 | foo() 47 | foo = nil 48 | 49 | if _soft then return 10 end 50 | 51 | print "testing large programs (>64k)" 52 | 53 | -- template to create a very big test file 54 | prog = [[$ 55 | 56 | local a,b 57 | 58 | b = {$1$ 59 | b30009 = 65534, 60 | b30010 = 65535, 61 | b30011 = 65536, 62 | b30012 = 65537, 63 | b30013 = 16777214, 64 | b30014 = 16777215, 65 | b30015 = 16777216, 66 | b30016 = 16777217, 67 | b30017 = 0x7fffff, 68 | b30018 = -0x7fffff, 69 | b30019 = 0x1ffffff, 70 | b30020 = -0x1ffffd, 71 | b30021 = -65534, 72 | b30022 = -65535, 73 | b30023 = -65536, 74 | b30024 = -0xffffff, 75 | b30025 = 15012.5, 76 | $2$ 77 | }; 78 | 79 | assert(b.a50008 == 25004 and b["a11"] == -5.5) 80 | assert(b.a33007 == -16503.5 and b.a50009 == -25004.5) 81 | assert(b["b"..30024] == -0xffffff) 82 | 83 | function b:xxx (a,b) return a+b end 84 | assert(b:xxx(10, 12) == 22) -- pushself with non-constant index 85 | b.xxx = nil 86 | 87 | s = 0; n=0 88 | for a,b in pairs(b) do s=s+b; n=n+1 end 89 | -- with 32-bit floats, exact value of 's' depends on summation order 90 | assert(81800000.0 < s and s < 81860000 and n == 70001) 91 | 92 | a = nil; b = nil 93 | print'+' 94 | 95 | function f(x) b=x end 96 | 97 | a = f{$3$} or 10 98 | 99 | assert(a==10) 100 | assert(b[1] == "a10" and b[2] == 5 and b[#b-1] == "a50009") 101 | 102 | 103 | function xxxx (x) return b[x] end 104 | 105 | assert(xxxx(3) == "a11") 106 | 107 | a = nil; b=nil 108 | xxxx = nil 109 | 110 | return 10 111 | 112 | ]] 113 | 114 | -- functions to fill in the $n$ 115 | 116 | local function sig (x) 117 | return (x % 2 == 0) and '' or '-' 118 | end 119 | 120 | F = { 121 | function () -- $1$ 122 | for i=10,50009 do 123 | io.write('a', i, ' = ', sig(i), 5+((i-10)/2), ',\n') 124 | end 125 | end, 126 | 127 | function () -- $2$ 128 | for i=30026,50009 do 129 | io.write('b', i, ' = ', sig(i), 15013+((i-30026)/2), ',\n') 130 | end 131 | end, 132 | 133 | function () -- $3$ 134 | for i=10,50009 do 135 | io.write('"a', i, '", ', sig(i), 5+((i-10)/2), ',\n') 136 | end 137 | end, 138 | } 139 | 140 | file = os.tmpname() 141 | io.output(file) 142 | for s in string.gmatch(prog, "$([^$]+)") do 143 | local n = tonumber(s) 144 | if not n then io.write(s) else F[n]() end 145 | end 146 | io.close() 147 | result = dofile(file) 148 | assert(os.remove(file)) 149 | print'OK' 150 | return result 151 | 152 | -------------------------------------------------------------------------------- /src/Language/Lua.hs: -------------------------------------------------------------------------------- 1 | module Language.Lua 2 | ( module Language.Lua.Syntax 3 | , parseText 4 | , parseNamedText 5 | , parseFile 6 | , stat 7 | , exp 8 | , chunk 9 | , pprint 10 | ) where 11 | 12 | import Prelude hiding (exp) 13 | 14 | import Language.Lua.Parser 15 | import Language.Lua.PrettyPrinter 16 | import Language.Lua.Syntax 17 | -------------------------------------------------------------------------------- /src/Language/Lua/Annotated.hs: -------------------------------------------------------------------------------- 1 | module Language.Lua.Annotated 2 | ( module Language.Lua.Annotated.Syntax 3 | , parseText 4 | , parseNamedText 5 | , parseFile 6 | , stat 7 | , exp 8 | , chunk 9 | ) where 10 | 11 | import Prelude hiding (exp) 12 | 13 | import Language.Lua.Annotated.Parser 14 | import Language.Lua.Annotated.Syntax 15 | -------------------------------------------------------------------------------- /src/Language/Lua/Annotated/Simplify.hs: -------------------------------------------------------------------------------- 1 | -- | Remove annotations. 2 | module Language.Lua.Annotated.Simplify where 3 | 4 | import Data.Maybe (isJust) 5 | import Prelude hiding (EQ, GT, LT) 6 | 7 | import qualified Language.Lua.Annotated.Syntax as A 8 | import Language.Lua.Syntax 9 | 10 | sName :: A.Name a -> Name 11 | sName (A.Name _ s) = s 12 | 13 | sStat :: A.Stat a -> Stat 14 | sStat (A.Assign _ vs es) = Assign (map sVar vs) (map sExp es) 15 | sStat (A.FunCall _ fc) = FunCall (sFunCall fc) 16 | sStat (A.Label _ n) = Label (sName n) 17 | sStat (A.Break _) = Break 18 | sStat (A.Goto _ n) = Goto (sName n) 19 | sStat (A.Do _ b) = Do (sBlock b) 20 | sStat (A.While _ e b) = While (sExp e) (sBlock b) 21 | sStat (A.Repeat _ b e) = Repeat (sBlock b) (sExp e) 22 | sStat (A.If _ conds else_) = If (map sCond conds) (fmap sBlock else_) 23 | where sCond (e, b) = (sExp e, sBlock b) 24 | sStat (A.ForRange _ n e1 e2 oe3 b) = 25 | ForRange (sName n) (sExp e1) (sExp e2) (fmap sExp oe3) (sBlock b) 26 | sStat (A.ForIn _ ns es b) = ForIn (map sName ns) (map sExp es) (sBlock b) 27 | sStat (A.FunAssign _ fn fb) = FunAssign (sFunName fn) (sFunBody fb) 28 | sStat (A.LocalFunAssign _ n fb) = LocalFunAssign (sName n) (sFunBody fb) 29 | sStat (A.LocalAssign _ ns es) = LocalAssign (map sName ns) (fmap (map sExp) es) 30 | sStat (A.EmptyStat _) = EmptyStat 31 | 32 | sExp :: A.Exp a -> Exp 33 | sExp (A.Nil _) = Nil 34 | sExp (A.Bool _ b) = Bool b 35 | sExp (A.Number _ n) = Number n 36 | sExp (A.String _ s) = String s 37 | sExp (A.Vararg _) = Vararg 38 | sExp (A.EFunDef _ fd) = EFunDef (sFunDef fd) 39 | sExp (A.PrefixExp _ pe) = PrefixExp (sPrefixExp pe) 40 | sExp (A.TableConst _ t) = TableConst (sTable t) 41 | sExp (A.Binop _ bop e1 e2) = Binop (sBinop bop) (sExp e1) (sExp e2) 42 | sExp (A.Unop _ uop e) = Unop (sUnop uop) (sExp e) 43 | 44 | sBlock :: A.Block a -> Block 45 | sBlock (A.Block _ ss oes) = Block (map sStat ss) (fmap (map sExp) oes) 46 | 47 | sVar :: A.Var a -> Var 48 | sVar (A.VarName _ n) = VarName (sName n) 49 | sVar (A.Select _ pe e) = Select (sPrefixExp pe) (sExp e) 50 | sVar (A.SelectName _ pe n) = SelectName (sPrefixExp pe) (sName n) 51 | 52 | sFunCall :: A.FunCall a -> FunCall 53 | sFunCall (A.NormalFunCall _ pe a) = NormalFunCall (sPrefixExp pe) (sFunArg a) 54 | sFunCall (A.MethodCall _ pe n a) = MethodCall (sPrefixExp pe) (sName n) (sFunArg a) 55 | 56 | sFunName :: A.FunName a -> FunName 57 | sFunName (A.FunName _ n ns on) = FunName (sName n) (map sName ns) (fmap sName on) 58 | 59 | sFunBody :: A.FunBody a -> FunBody 60 | sFunBody (A.FunBody _ ns vararg b) = 61 | FunBody (map sName ns) (isJust vararg) (sBlock b) 62 | 63 | sFunDef :: A.FunDef a -> FunBody 64 | sFunDef (A.FunDef _ fb) = sFunBody fb 65 | 66 | sPrefixExp :: A.PrefixExp a -> PrefixExp 67 | sPrefixExp (A.PEVar _ v) = PEVar (sVar v) 68 | sPrefixExp (A.PEFunCall _ fc) = PEFunCall (sFunCall fc) 69 | sPrefixExp (A.Paren _ e) = Paren (sExp e) 70 | 71 | sTable :: A.Table a -> [TableField] 72 | sTable (A.Table _ fs) = map sTableField fs 73 | 74 | sBinop :: A.Binop a -> Binop 75 | sBinop A.Add{} = Add 76 | sBinop A.Sub{} = Sub 77 | sBinop A.Mul{} = Mul 78 | sBinop A.Div{} = Div 79 | sBinop A.IDiv{} = IDiv 80 | sBinop A.Exp{} = Exp 81 | sBinop A.Mod{} = Mod 82 | sBinop A.Concat{} = Concat 83 | sBinop A.LT{} = LT 84 | sBinop A.LTE{} = LTE 85 | sBinop A.GT{} = GT 86 | sBinop A.GTE{} = GTE 87 | sBinop A.EQ{} = EQ 88 | sBinop A.NEQ{} = NEQ 89 | sBinop A.And{} = And 90 | sBinop A.Or{} = Or 91 | sBinop A.BAnd{} = BAnd 92 | sBinop A.BOr{} = BOr 93 | sBinop A.BXor{} = BXor 94 | sBinop A.ShiftL{} = ShiftL 95 | sBinop A.ShiftR{} = ShiftR 96 | 97 | sUnop :: A.Unop a -> Unop 98 | sUnop A.Neg{} = Neg 99 | sUnop A.Not{} = Not 100 | sUnop A.Len{} = Len 101 | sUnop A.Complement{} = Complement 102 | 103 | sFunArg :: A.FunArg a -> FunArg 104 | sFunArg (A.Args _ es) = Args (map sExp es) 105 | sFunArg (A.TableArg _ t) = TableArg (sTable t) 106 | sFunArg (A.StringArg _ s) = StringArg s 107 | 108 | sTableField :: A.TableField a -> TableField 109 | sTableField (A.ExpField _ e1 e2) = ExpField (sExp e1) (sExp e2) 110 | sTableField (A.NamedField _ n e) = NamedField (sName n) (sExp e) 111 | sTableField (A.Field _ e) = Field (sExp e) 112 | -------------------------------------------------------------------------------- /src/Language/Lua/Annotated/Syntax.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DeriveDataTypeable, DeriveFunctor, DeriveGeneric #-} 2 | 3 | -- | Lua 5.3 syntax tree, as specified in . 4 | -- Annotation implementation is inspired by haskell-src-exts. 5 | module Language.Lua.Annotated.Syntax where 6 | 7 | import Control.DeepSeq (NFData) 8 | import Data.Data (Data, Typeable) 9 | import GHC.Generics (Generic) 10 | import Prelude hiding (EQ, GT, LT) 11 | 12 | data Name a = Name a String deriving (Show, Eq, Functor, Data, Typeable, Generic) 13 | 14 | data Stat a 15 | = Assign a [Var a] [Exp a] -- ^var1, var2 .. = exp1, exp2 .. 16 | | FunCall a (FunCall a) -- ^function call 17 | | Label a (Name a) -- ^label for goto 18 | | Break a -- ^break 19 | | Goto a (Name a) -- ^goto label 20 | | Do a (Block a) -- ^do .. end 21 | | While a (Exp a) (Block a) -- ^while .. do .. end 22 | | Repeat a (Block a) (Exp a) -- ^repeat .. until .. 23 | | If a [(Exp a, Block a)] (Maybe (Block a)) -- ^if .. then .. [elseif ..] [else ..] end 24 | | ForRange a (Name a) (Exp a) (Exp a) (Maybe (Exp a)) (Block a) -- ^for x=start, end [, step] do .. end 25 | | ForIn a [Name a] [Exp a] (Block a) -- ^for x in .. do .. end 26 | | FunAssign a (FunName a) (FunBody a) -- ^function \ (..) .. end 27 | | LocalFunAssign a (Name a) (FunBody a) -- ^local function \ (..) .. end 28 | | LocalAssign a [Name a] (Maybe [Exp a]) -- ^local var1, var2 .. = exp1, exp2 .. 29 | | EmptyStat a -- ^/;/ 30 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 31 | 32 | data Exp a 33 | = Nil a 34 | | Bool a Bool 35 | | Number a String 36 | | String a String 37 | | Vararg a -- ^/.../ 38 | | EFunDef a (FunDef a) -- ^/function (..) .. end/ 39 | | PrefixExp a (PrefixExp a) 40 | | TableConst a (Table a) -- ^table constructor 41 | | Binop a (Binop a) (Exp a) (Exp a) -- ^binary operators, /+ - * ^ % .. < <= > >= == ~= and or/ 42 | | Unop a (Unop a) (Exp a) -- ^unary operators, /- not #/ 43 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 44 | 45 | data Var a 46 | = VarName a (Name a) -- ^variable 47 | | Select a (PrefixExp a) (Exp a) -- ^/table[exp]/ 48 | | SelectName a (PrefixExp a) (Name a) -- ^/table.variable/ 49 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 50 | 51 | data Binop a = Add a | Sub a | Mul a | Div a | Exp a | Mod a | Concat a 52 | | LT a | LTE a | GT a | GTE a | EQ a | NEQ a | And a | Or a 53 | | IDiv a | ShiftL a | ShiftR a | BAnd a | BOr a | BXor a 54 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 55 | 56 | data Unop a = Neg a | Not a | Len a | Complement a 57 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 58 | 59 | data PrefixExp a 60 | = PEVar a (Var a) 61 | | PEFunCall a (FunCall a) 62 | | Paren a (Exp a) 63 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 64 | 65 | data Table a = Table a [TableField a] -- ^list of table fields 66 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 67 | 68 | data TableField a 69 | = ExpField a (Exp a) (Exp a) -- ^/[exp] = exp/ 70 | | NamedField a (Name a) (Exp a) -- ^/name = exp/ 71 | | Field a (Exp a) 72 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 73 | 74 | -- | A block is list of statements with optional return statement. 75 | data Block a = Block a [Stat a] (Maybe [Exp a]) 76 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 77 | 78 | data FunName a = FunName a (Name a) [Name a] (Maybe (Name a)) 79 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 80 | 81 | data FunDef a = FunDef a (FunBody a) 82 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 83 | 84 | data FunBody a = FunBody a [Name a] (Maybe a) (Block a) -- ^(args, vararg, block) 85 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 86 | 87 | data FunCall a 88 | = NormalFunCall a (PrefixExp a) (FunArg a) -- ^/prefixexp ( funarg )/ 89 | | MethodCall a (PrefixExp a) (Name a) (FunArg a) -- ^/prefixexp : name ( funarg )/ 90 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 91 | 92 | data FunArg a 93 | = Args a [Exp a] -- ^list of args 94 | | TableArg a (Table a) -- ^table constructor 95 | | StringArg a String -- ^string 96 | deriving (Show, Eq, Functor, Data, Typeable, Generic) 97 | 98 | 99 | class Functor ast => Annotated ast where 100 | -- | Retrieve the annotation of an AST node. 101 | ann :: ast l -> l 102 | -- | Change the annotation of an AST node. Note that only the annotation of 103 | -- the node itself is affected, and not the annotations of any child nodes. 104 | -- if all nodes in the AST tree are to be affected, use 'fmap'. 105 | amap :: (l -> l) -> ast l -> ast l 106 | 107 | instance Annotated Stat where 108 | ann (Assign a _ _) = a 109 | ann (FunCall a _) = a 110 | ann (Label a _) = a 111 | ann (Break a) = a 112 | ann (Goto a _) = a 113 | ann (Do a _) = a 114 | ann (While a _ _) = a 115 | ann (Repeat a _ _) = a 116 | ann (If a _ _) = a 117 | ann (ForRange a _ _ _ _ _) = a 118 | ann (ForIn a _ _ _) = a 119 | ann (FunAssign a _ _) = a 120 | ann (LocalFunAssign a _ _) = a 121 | ann (LocalAssign a _ _) = a 122 | ann (EmptyStat a) = a 123 | 124 | amap f (Assign a x1 x2) = Assign (f a) x1 x2 125 | amap f (FunCall a x1) = FunCall (f a) x1 126 | amap f (Label a x1) = Label (f a) x1 127 | amap f (Break a) = Break (f a) 128 | amap f (Goto a x1) = Goto (f a) x1 129 | amap f (Do a x1) = Do (f a) x1 130 | amap f (While a x1 x2) = While (f a) x1 x2 131 | amap f (Repeat a x1 x2) = Repeat (f a) x1 x2 132 | amap f (If a x1 x2) = If (f a) x1 x2 133 | amap f (ForRange a x1 x2 x3 x4 x5) = ForRange (f a) x1 x2 x3 x4 x5 134 | amap f (ForIn a x1 x2 x3) = ForIn (f a) x1 x2 x3 135 | amap f (FunAssign a x1 x2) = FunAssign (f a) x1 x2 136 | amap f (LocalFunAssign a x1 x2) = LocalFunAssign (f a) x1 x2 137 | amap f (LocalAssign a x1 x2) = LocalAssign (f a) x1 x2 138 | amap f (EmptyStat a) = EmptyStat (f a) 139 | 140 | instance Annotated Exp where 141 | ann (Nil a) = a 142 | ann (Bool a _) = a 143 | ann (Number a _) = a 144 | ann (String a _) = a 145 | ann (Vararg a) = a 146 | ann (EFunDef a _) = a 147 | ann (PrefixExp a _) = a 148 | ann (TableConst a _) = a 149 | ann (Binop a _ _ _) = a 150 | ann (Unop a _ _) = a 151 | 152 | amap f (Nil a) = Nil (f a) 153 | amap f (Bool a x1) = Bool (f a) x1 154 | amap f (Number a x1) = Number (f a) x1 155 | amap f (String a x1) = String (f a) x1 156 | amap f (Vararg a) = Vararg (f a) 157 | amap f (EFunDef a x1) = EFunDef (f a) x1 158 | amap f (PrefixExp a x1) = PrefixExp (f a) x1 159 | amap f (TableConst a x1) = TableConst (f a) x1 160 | amap f (Binop a x1 x2 x3) = Binop (f a) x1 x2 x3 161 | amap f (Unop a x1 x2) = Unop (f a) x1 x2 162 | 163 | instance Annotated Var where 164 | ann (VarName a _) = a 165 | ann (Select a _ _) = a 166 | ann (SelectName a _ _) = a 167 | 168 | amap f (VarName a x1) = VarName (f a) x1 169 | amap f (Select a x1 x2) = Select (f a) x1 x2 170 | amap f (SelectName a x1 x2) = SelectName (f a) x1 x2 171 | 172 | instance Annotated Binop where 173 | ann (Add a) = a 174 | ann (Sub a) = a 175 | ann (Mul a) = a 176 | ann (Div a) = a 177 | ann (Exp a) = a 178 | ann (Mod a) = a 179 | ann (Concat a) = a 180 | ann (LT a) = a 181 | ann (LTE a) = a 182 | ann (GT a) = a 183 | ann (GTE a) = a 184 | ann (EQ a) = a 185 | ann (NEQ a) = a 186 | ann (And a) = a 187 | ann (Or a) = a 188 | ann (BAnd a) = a 189 | ann (BOr a) = a 190 | ann (BXor a) = a 191 | ann (ShiftL a) = a 192 | ann (ShiftR a) = a 193 | ann (IDiv a) = a 194 | 195 | amap f (Add a) = Add (f a) 196 | amap f (Sub a) = Sub (f a) 197 | amap f (Mul a) = Mul (f a) 198 | amap f (Div a) = Div (f a) 199 | amap f (Exp a) = Exp (f a) 200 | amap f (Mod a) = Mod (f a) 201 | amap f (Concat a) = Concat (f a) 202 | amap f (LT a) = LT (f a) 203 | amap f (LTE a) = LTE (f a) 204 | amap f (GT a) = GT (f a) 205 | amap f (GTE a) = GTE (f a) 206 | amap f (EQ a) = EQ (f a) 207 | amap f (NEQ a) = NEQ (f a) 208 | amap f (And a) = And (f a) 209 | amap f (Or a) = Or (f a) 210 | amap f (BAnd a) = BAnd (f a) 211 | amap f (BOr a) = BOr (f a) 212 | amap f (BXor a) = BXor (f a) 213 | amap f (ShiftL a) = ShiftL (f a) 214 | amap f (ShiftR a) = ShiftR (f a) 215 | amap f (IDiv a) = IDiv (f a) 216 | 217 | instance Annotated Unop where 218 | ann (Neg a) = a 219 | ann (Not a) = a 220 | ann (Len a) = a 221 | ann (Complement a) = a 222 | 223 | amap f (Neg a) = Neg (f a) 224 | amap f (Not a) = Not (f a) 225 | amap f (Len a) = Len (f a) 226 | amap f (Complement a) = Complement (f a) 227 | 228 | instance Annotated PrefixExp where 229 | ann (PEVar a _) = a 230 | ann (PEFunCall a _) = a 231 | ann (Paren a _) = a 232 | 233 | amap f (PEVar a x1) = PEVar (f a) x1 234 | amap f (PEFunCall a x1) = PEFunCall (f a) x1 235 | amap f (Paren a x1) = Paren (f a) x1 236 | 237 | instance Annotated Table where 238 | ann (Table a _) = a 239 | amap f (Table a x1) = Table (f a) x1 240 | 241 | instance Annotated TableField where 242 | ann (ExpField a _ _) = a 243 | ann (NamedField a _ _) = a 244 | ann (Field a _) = a 245 | 246 | amap f (ExpField a x1 x2) = ExpField (f a) x1 x2 247 | amap f (NamedField a x1 x2) = NamedField (f a) x1 x2 248 | amap f (Field a x1) = Field (f a) x1 249 | 250 | instance Annotated Block where 251 | ann (Block a _ _) = a 252 | amap f (Block a x1 x2) = Block (f a) x1 x2 253 | 254 | instance Annotated FunName where 255 | ann (FunName a _ _ _) = a 256 | amap f (FunName a x1 x2 x3) = FunName (f a) x1 x2 x3 257 | 258 | instance Annotated FunDef where 259 | ann (FunDef a _) = a 260 | amap f (FunDef a x1) = FunDef (f a) x1 261 | 262 | instance Annotated FunBody where 263 | ann (FunBody a _ _ _) = a 264 | amap f (FunBody a x1 x2 x3) = FunBody (f a) x1 x2 x3 265 | 266 | instance Annotated FunCall where 267 | ann (NormalFunCall a _ _) = a 268 | ann (MethodCall a _ _ _) = a 269 | 270 | amap f (NormalFunCall a x1 x2) = NormalFunCall (f a) x1 x2 271 | amap f (MethodCall a x1 x2 x3) = MethodCall (f a) x1 x2 x3 272 | 273 | instance Annotated FunArg where 274 | ann (Args a _) = a 275 | ann (TableArg a _) = a 276 | ann (StringArg a _) = a 277 | 278 | amap f (Args a x1) = Args (f a) x1 279 | amap f (TableArg a x1) = TableArg (f a) x1 280 | amap f (StringArg a x1) = StringArg (f a) x1 281 | 282 | instance Annotated Name where 283 | ann (Name a _) = a 284 | amap f (Name a x1) = Name (f a) x1 285 | 286 | instance NFData a => NFData (Name a) 287 | instance NFData a => NFData (Stat a) 288 | instance NFData a => NFData (Exp a) 289 | instance NFData a => NFData (Var a) 290 | instance NFData a => NFData (Binop a) 291 | instance NFData a => NFData (Unop a) 292 | instance NFData a => NFData (PrefixExp a) 293 | instance NFData a => NFData (Table a) 294 | instance NFData a => NFData (TableField a) 295 | instance NFData a => NFData (Block a) 296 | instance NFData a => NFData (FunName a) 297 | instance NFData a => NFData (FunDef a) 298 | instance NFData a => NFData (FunBody a) 299 | instance NFData a => NFData (FunCall a) 300 | instance NFData a => NFData (FunArg a) 301 | -------------------------------------------------------------------------------- /src/Language/Lua/Parser.hs: -------------------------------------------------------------------------------- 1 | module Language.Lua.Parser 2 | ( A.parseText 3 | , A.parseNamedText 4 | , parseFile 5 | , stat 6 | , exp 7 | , chunk 8 | ) where 9 | 10 | import Control.Monad (liftM) 11 | import Prelude hiding (exp) 12 | import Text.Parsec 13 | import Text.Parsec.LTok 14 | 15 | import qualified Language.Lua.Annotated.Parser as A 16 | import Language.Lua.Annotated.Simplify 17 | import Language.Lua.Syntax 18 | 19 | parseFile :: FilePath -> IO (Either ParseError Block) 20 | parseFile = (liftM . liftM $ sBlock) . A.parseFile 21 | 22 | stat :: Parser Stat 23 | stat = fmap sStat A.stat 24 | 25 | exp :: Parser Exp 26 | exp = fmap sExp A.exp 27 | 28 | chunk :: Parser Block 29 | chunk = fmap sBlock A.chunk 30 | -------------------------------------------------------------------------------- /src/Language/Lua/PrettyPrinter.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances, CPP #-} 2 | 3 | -- | Lua pretty-printer. 4 | module Language.Lua.PrettyPrinter 5 | ( pprint 6 | , renderPretty 7 | , displayS 8 | , displayIO 9 | , LPretty 10 | ) where 11 | 12 | #if __GLASGOW_HASKELL__ >= 710 13 | import Prelude hiding (EQ, GT, LT, (<$>)) 14 | #else 15 | import Prelude hiding (EQ, GT, LT) 16 | #endif 17 | 18 | import Text.PrettyPrint.Leijen hiding ((<$>)) 19 | 20 | import Language.Lua.Syntax 21 | 22 | intercalate :: Doc -> [Doc] -> Doc 23 | intercalate s elems = sep (punctuate s elems) 24 | 25 | infixr 5 <$> 26 | (<$>) :: Doc -> Doc -> Doc 27 | x <$> y | isEmpty y = x 28 | | otherwise = x <> line <> y 29 | 30 | type Precedence = Int 31 | 32 | class LPretty a where 33 | pprint :: a -> Doc 34 | pprint = pprint' 0 35 | 36 | pprint' :: Precedence -> a -> Doc 37 | pprint' _ = pprint 38 | 39 | instance LPretty [Char] where 40 | pprint = text 41 | 42 | instance LPretty Bool where 43 | pprint True = text "true" 44 | pprint False = text "false" 45 | 46 | instance LPretty Exp where 47 | pprint' _ Nil = text "nil" 48 | pprint' _ (Bool s) = pprint s 49 | pprint' _ (Number n) = text n 50 | pprint' _ (String s) = text s 51 | pprint' _ Vararg = text "..." 52 | pprint' _ (EFunDef f) = pprint f 53 | pprint' _ (PrefixExp pe) = pprint pe 54 | pprint' _ (TableConst t) = pprint t 55 | pprint' p (Binop op e1 e2) = ps (pprint' opPrecL e1 <+> pprint op 56 | <+> case e2 of 57 | Unop{} -> pprint e2 58 | _ -> pprint' opPrecR e2) 59 | where 60 | (opPrecL, opPrecR) = getBinopPrec op 61 | ps = if min opPrecL opPrecR < p then parens else id 62 | 63 | -- We handle this as a special case: When we have a chain of negations, we 64 | -- should put a space between operators, otherwise we end up printing a 65 | -- comment. 66 | -- 67 | -- One another solution would be to always put a space after negation, but I 68 | -- like to put negation just before the expression, without any spaces. 69 | pprint' p (Unop Neg (Unop Neg e)) = 70 | ps (pprint Neg <+> pprint' opPrec (Unop Neg e)) 71 | where 72 | opPrec = getUnopPrec Neg 73 | ps = if opPrec < p then parens else id 74 | 75 | pprint' p (Unop op e) = ps (pprint op <> pprint' opPrec e) 76 | where 77 | opPrec = getUnopPrec op 78 | ps = if opPrec < p then parens else id 79 | 80 | instance LPretty Var where 81 | pprint (VarName n) = pprint n 82 | pprint (Select pe e) = pprint pe <> align (brackets (pprint e)) 83 | pprint (SelectName pe name) = pprint pe (char '.' <> pprint name) 84 | 85 | instance LPretty Binop where 86 | pprint Add = char '+' 87 | pprint Sub = char '-' 88 | pprint Mul = char '*' 89 | pprint Div = char '/' 90 | pprint IDiv = text "//" 91 | pprint Exp = char '^' 92 | pprint Mod = char '%' 93 | pprint Concat = text ".." 94 | pprint LT = char '<' 95 | pprint LTE = text "<=" 96 | pprint GT = char '>' 97 | pprint GTE = text ">=" 98 | pprint EQ = text "==" 99 | pprint NEQ = text "~=" 100 | pprint And = text "and" 101 | pprint Or = text "or" 102 | pprint BAnd = char '&' 103 | pprint BOr = char '|' 104 | pprint BXor = char '~' 105 | pprint ShiftL = text "<<" 106 | pprint ShiftR = text ">>" 107 | 108 | instance LPretty Unop where 109 | pprint Neg = char '-' 110 | pprint Not = text "not " 111 | pprint Len = char '#' 112 | pprint Complement = char '~' 113 | 114 | getBinopPrec :: Binop -> (Precedence, Precedence) 115 | getBinopPrec op = 116 | case op of 117 | Add -> (10, 10) 118 | Sub -> (10, 10) 119 | Mul -> (11, 11) 120 | Div -> (11, 11) 121 | IDiv -> (11, 11) 122 | Exp -> (14, 13) 123 | Mod -> (11, 11) 124 | Concat -> (9, 8) 125 | ShiftL -> (7, 7) 126 | ShiftR -> (7, 7) 127 | BAnd -> (6, 6) 128 | BXor -> (5, 5) 129 | BOr -> (4, 4) 130 | LT -> (3, 3) 131 | LTE -> (3, 3) 132 | GT -> (3, 3) 133 | GTE -> (3, 3) 134 | EQ -> (3, 3) 135 | NEQ -> (3, 3) 136 | And -> (2, 2) 137 | Or -> (1, 1) 138 | 139 | getUnopPrec :: Unop -> Precedence 140 | getUnopPrec = const 12 141 | 142 | instance LPretty PrefixExp where 143 | pprint (PEVar var) = pprint var 144 | pprint (PEFunCall funcall) = pprint funcall 145 | pprint (Paren e) = parens (pprint e) 146 | 147 | instance LPretty [TableField] where 148 | pprint fields = braces (align (fillSep (punctuate comma (map pprint fields)))) 149 | 150 | instance LPretty TableField where 151 | pprint (ExpField e1 e2) = brackets (pprint e1) <+> equals <+> pprint e2 152 | pprint (NamedField name e) = pprint name <+> equals <+> pprint e 153 | pprint (Field e) = pprint e 154 | 155 | instance LPretty Block where 156 | pprint (Block stats ret) = 157 | case stats of 158 | [] -> ret' 159 | _ -> vsep (map pprint stats) <$> ret' 160 | where ret' = case ret of 161 | Nothing -> empty 162 | Just [fun@EFunDef{}] -> text "return" <+> pprint fun 163 | Just e -> nest 2 (text "return" intercalate comma (map (align . pprint) e)) 164 | 165 | instance LPretty FunName where 166 | pprint (FunName name s methods) = cat (punctuate dot (map pprint $ name:s)) <> method' 167 | where method' = case methods of 168 | Nothing -> empty 169 | Just m' -> char ':' <> pprint m' 170 | 171 | instance LPretty FunBody where 172 | pprint = pprintFunction Nothing 173 | 174 | pprintFunction :: Maybe Doc -> FunBody -> Doc 175 | pprintFunction funname (FunBody args vararg block) = 176 | group (nest 2 (header <$> body) <$> end) 177 | where 178 | header = case funname of 179 | Nothing -> text "function" <+> args' 180 | Just n -> text "function" <+> n <> args' 181 | vararg' = if vararg then ["..."] else [] 182 | args' = parens (align (cat (punctuate (comma <> space) (map pprint (args ++ vararg'))))) 183 | body = pprint block 184 | end = text "end" 185 | 186 | instance LPretty FunCall where 187 | pprint (NormalFunCall pe arg) = pprint pe <> pprint arg 188 | pprint (MethodCall pe method arg) = pprint pe colon <> pprint method <> pprint arg 189 | 190 | instance LPretty FunArg where 191 | pprint (Args [fun@EFunDef{}]) = parens (pprint fun) 192 | pprint (Args exps) = parens (align (fillSep (punctuate comma (map (align . pprint) exps)))) 193 | pprint (TableArg t) = pprint t 194 | pprint (StringArg s) = text s 195 | 196 | instance LPretty Stat where 197 | pprint (Assign names vals) 198 | = intercalate comma (map pprint names) 199 | <+> equals 200 | <+> intercalate comma (map pprint vals) 201 | pprint (FunCall funcall) = pprint funcall 202 | pprint (Label name) = text "::" <> pprint name <> text "::" 203 | pprint Break = text "break" 204 | pprint (Goto name) = text "goto" <+> pprint name 205 | pprint (Do block) = group (nest 2 (text "do" <$> pprint block) <$> text "end") 206 | pprint (While guard e) 207 | = nest 2 (text "while" <+> pprint guard <+> text "do" <$> pprint e) 208 | <$> text "end" 209 | pprint (Repeat block guard) 210 | = nest 2 (text "repeat" <$> pprint block) 211 | nest 2 (text "until" pprint guard) 212 | 213 | pprint (If cases elsePart) = group (printIf cases elsePart) 214 | where 215 | printIf ((guard, block) : xs) e = 216 | nest 2 (text "if" <+> pprint guard <+> text "then" <$> pprint block) <$> printIf' xs e 217 | printIf [] _ = 218 | error $ "pprint: Trying to print invalid syntax:\n\t" ++ 219 | "if statement should have at least one case" 220 | 221 | printIf' [] Nothing = text "end" 222 | printIf' [] (Just b) = nest 2 (text "else" <$> pprint b) <$> text "end" 223 | printIf' ((guard, block) : xs) e = 224 | nest 2 (text "elseif" <+> pprint guard <+> text "then" <$> pprint block) <$> printIf' xs e 225 | 226 | pprint (ForRange name e1 e2 e3 block) 227 | = nest 2 (text "for" <+> pprint name <> equals <> pprint e1 228 | <> comma <> pprint e2 <> e3' <+> text "do" 229 | <$> pprint block) 230 | <$> text "end" 231 | where e3' = case e3 of 232 | Nothing -> empty 233 | Just e -> comma <> pprint e 234 | 235 | pprint (ForIn names exps block) 236 | = nest 2 (text "for" <+> intercalate comma (map pprint names) <+> text "in" 237 | <+> intercalate comma (map pprint exps) <+> text "do" 238 | <$> pprint block) 239 | <$> text "end" 240 | 241 | pprint (FunAssign name body) = pprintFunction (Just (pprint name)) body 242 | pprint (LocalFunAssign name body) = text "local" <+> pprintFunction (Just (pprint name)) body 243 | pprint (LocalAssign names exps) 244 | = text "local" <+> intercalate comma (map pprint names) <+> exps' 245 | where exps' = case exps of 246 | Nothing -> empty 247 | Just es -> equals intercalate comma (map pprint es) 248 | pprint EmptyStat = text ";" 249 | -------------------------------------------------------------------------------- /src/Language/Lua/StringLiteral.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | 3 | #ifndef MIN_VERSION_base 4 | #define MIN_VERSION_base(x,y,z) 1 5 | #endif 6 | 7 | module Language.Lua.StringLiteral 8 | ( interpretStringLiteral 9 | , constructStringLiteral 10 | ) where 11 | 12 | import Data.Char (ord, chr, isNumber, isPrint, isAscii) 13 | import Data.ByteString.Lazy (ByteString) 14 | import qualified Data.ByteString.Lazy as B 15 | import qualified Data.ByteString.Builder as B 16 | import qualified Data.ByteString.Lazy.Char8 as B8 17 | import Data.List (foldl') 18 | import Data.Bits ((.&.),shiftR) 19 | import Numeric (showHex) 20 | 21 | #if !(MIN_VERSION_base(4,8,0)) 22 | import Data.Monoid (mempty, mappend, mconcat) 23 | #endif 24 | 25 | skipWS :: String -> String 26 | skipWS (' ' : rest) = skipWS rest 27 | skipWS ('\n' : rest) = skipWS rest 28 | skipWS ('\r' : rest) = skipWS rest 29 | skipWS ('\f' : rest) = skipWS rest 30 | skipWS ('\t' : rest) = skipWS rest 31 | skipWS ('\v' : rest) = skipWS rest 32 | skipWS str = str 33 | 34 | hexToInt :: Char -> Int 35 | hexToInt c = 36 | case c of 37 | 'A' -> 10 38 | 'a' -> 10 39 | 'B' -> 11 40 | 'b' -> 11 41 | 'C' -> 12 42 | 'c' -> 12 43 | 'D' -> 13 44 | 'd' -> 13 45 | 'E' -> 14 46 | 'e' -> 14 47 | 'F' -> 15 48 | 'f' -> 15 49 | _ -> decToNum c 50 | 51 | {-# INLINE decToNum #-} 52 | decToNum :: Char -> Int 53 | decToNum c = fromEnum c - fromEnum '0' 54 | 55 | 56 | interpretStringLiteral :: String -> Maybe ByteString 57 | interpretStringLiteral xxs = 58 | case xxs of 59 | '\'':xs -> Just (decodeEscapes (dropLast 1 xs)) 60 | '"':xs -> Just (decodeEscapes (dropLast 1 xs)) 61 | '[':xs -> removeLongQuotes xs 62 | _ -> Nothing 63 | 64 | -- | Long-quoted string literals have no escapes. 65 | -- A leading newline on a long quoted string literal is ignored. 66 | removeLongQuotes :: String -> Maybe ByteString 67 | removeLongQuotes str = 68 | case span (=='=') str of 69 | (eqs,'[':'\n':xs) -> go (dropLast (2+length eqs) xs) 70 | (eqs,'[': xs) -> go (dropLast (2+length eqs) xs) 71 | _ -> Nothing 72 | where 73 | go = Just . B.toLazyByteString . mconcat . map encodeChar 74 | 75 | dropLast :: Int -> [a] -> [a] 76 | dropLast n xs = take (length xs - n) xs 77 | 78 | decodeEscapes :: String -> ByteString 79 | decodeEscapes = B.toLazyByteString . aux 80 | where 81 | aux xxs = 82 | case xxs of 83 | [] -> mempty 84 | '\\' : 'x' : h1 : h2 : rest -> 85 | B.word8 (fromIntegral (hexToInt h1 * 16 + hexToInt h2)) `mappend` aux rest 86 | 87 | '\\' : 'u' : '{' : rest -> 88 | case break (=='}') rest of 89 | (ds,_:rest') 90 | | code <= 0x10ffff -> encodeChar (chr code) `mappend` aux rest' 91 | where code = foldl' (\acc d -> acc * 16 + hexToInt d) 0 ds 92 | _ -> encodeChar '\xFFFD' `mappend` aux (dropWhile (/='}') rest) 93 | 94 | '\\' : c1 : c2 : c3 : rest 95 | | isNumber c1 && isNumber c2 && isNumber c3 -> 96 | let code = decToNum c1 * 100 + decToNum c2 * 10 + decToNum c3 97 | in B.word8 (fromIntegral code) `mappend` aux rest 98 | 99 | '\\' : c1 : c2 : rest 100 | | isNumber c1 && isNumber c2 -> 101 | let code = decToNum c1 * 10 + decToNum c2 102 | in B.word8 (fromIntegral code) `mappend` aux rest 103 | 104 | '\\' : c1 : rest 105 | | isNumber c1 -> B.word8 (fromIntegral (decToNum c1)) `mappend` aux rest 106 | 107 | '\\' : 'a' : rest -> B.char8 '\a' `mappend` aux rest 108 | '\\' : 'b' : rest -> B.char8 '\b' `mappend` aux rest 109 | '\\' : 'f' : rest -> B.char8 '\f' `mappend` aux rest 110 | '\\' : 'n' : rest -> B.char8 '\n' `mappend` aux rest 111 | '\\' : '\n' : rest -> B.char8 '\n' `mappend` aux rest 112 | '\\' : 'r' : rest -> B.char8 '\r' `mappend` aux rest 113 | '\\' : 't' : rest -> B.char8 '\t' `mappend` aux rest 114 | '\\' : 'v' : rest -> B.char8 '\v' `mappend` aux rest 115 | '\\' : '\\' : rest -> B.char8 '\\' `mappend` aux rest 116 | '\\' : '"' : rest -> B.char8 '"' `mappend` aux rest 117 | '\\' : '\'' : rest -> B.char8 '\'' `mappend` aux rest 118 | '\\' : 'z' : rest -> aux (skipWS rest) 119 | c : rest -> encodeChar c `mappend` aux rest 120 | 121 | -- | Convert a string literal body to string literal syntax 122 | constructStringLiteral :: ByteString -> String 123 | constructStringLiteral bs = '"' : aux 0 124 | where 125 | aux i 126 | | i >= B.length bs = "\"" 127 | | otherwise = 128 | case B8.index bs i of 129 | '\a' -> '\\' : 'a' : aux (i+1) 130 | '\b' -> '\\' : 'b' : aux (i+1) 131 | '\f' -> '\\' : 'f' : aux (i+1) 132 | '\n' -> '\\' : 'n' : aux (i+1) 133 | '\r' -> '\\' : 'r' : aux (i+1) 134 | '\t' -> '\\' : 't' : aux (i+1) 135 | '\v' -> '\\' : 'v' : aux (i+1) 136 | '\\' -> '\\' : '\\' : aux (i+1) 137 | '\"' -> '\\' : '"' : aux (i+1) 138 | x | isPrint x && isAscii x -> x : aux (i+1) 139 | | x <= '\x0f' -> '\\' : 'x' : '0' : showHex (ord x) (aux (i+1)) 140 | | otherwise -> '\\' : 'x' : showHex (ord x) (aux (i+1)) 141 | 142 | encodeChar :: Char -> B.Builder 143 | encodeChar c 144 | | oc <= 0x7f = asByte oc 145 | 146 | | oc <= 0x7ff = asByte (0xc0 + (oc `shiftR` 6)) 147 | `mappend` asByte (0x80 + oc .&. 0x3f) 148 | 149 | | oc <= 0xffff = asByte (0xe0 + (oc `shiftR` 12)) 150 | `mappend` asByte (0x80 + ((oc `shiftR` 6) .&. 0x3f)) 151 | `mappend` asByte (0x80 + oc .&. 0x3f) 152 | 153 | | otherwise = asByte (0xf0 + (oc `shiftR` 18)) 154 | `mappend` asByte (0x80 + ((oc `shiftR` 12) .&. 0x3f)) 155 | `mappend` asByte (0x80 + ((oc `shiftR` 6) .&. 0x3f)) 156 | `mappend` asByte (0x80 + oc .&. 0x3f) 157 | where 158 | asByte = B.word8 . fromIntegral 159 | oc = ord c 160 | -------------------------------------------------------------------------------- /src/Language/Lua/Syntax.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-} 2 | 3 | -- | Lua 5.3 syntax tree, as specified in . 4 | module Language.Lua.Syntax where 5 | 6 | import Control.DeepSeq (NFData) 7 | import Data.Data (Data, Typeable) 8 | import GHC.Generics (Generic) 9 | import Prelude hiding (EQ, GT, LT) 10 | 11 | type Name = String 12 | 13 | data Stat 14 | = Assign [Var] [Exp] -- ^var1, var2 .. = exp1, exp2 .. 15 | | FunCall FunCall -- ^function call 16 | | Label Name -- ^label for goto 17 | | Break -- ^break 18 | | Goto Name -- ^goto label 19 | | Do Block -- ^do .. end 20 | | While Exp Block -- ^while .. do .. end 21 | | Repeat Block Exp -- ^repeat .. until .. 22 | | If [(Exp, Block)] (Maybe Block) -- ^if .. then .. [elseif ..] [else ..] end 23 | | ForRange Name Exp Exp (Maybe Exp) Block -- ^for x=start, end [, step] do .. end 24 | | ForIn [Name] [Exp] Block -- ^for x in .. do .. end 25 | | FunAssign FunName FunBody -- ^function \ (..) .. end 26 | | LocalFunAssign Name FunBody -- ^local function \ (..) .. end 27 | | LocalAssign [Name] (Maybe [Exp]) -- ^local var1, var2 .. = exp1, exp2 .. 28 | | EmptyStat -- ^/;/ 29 | deriving (Show, Eq, Data, Typeable, Generic) 30 | 31 | data Exp 32 | = Nil 33 | | Bool Bool 34 | | Number String 35 | | String String 36 | | Vararg -- ^/.../ 37 | | EFunDef FunBody -- ^/function (..) .. end/ 38 | | PrefixExp PrefixExp 39 | | TableConst [TableField] -- ^table constructor 40 | | Binop Binop Exp Exp -- ^binary operators, /+ - * ^ % .. < <= > >= == ~= and or/ 41 | | Unop Unop Exp -- ^unary operators, /- not #/ 42 | deriving (Show, Eq, Data, Typeable, Generic) 43 | 44 | data Var 45 | = VarName Name -- ^variable 46 | | Select PrefixExp Exp -- ^/table[exp]/ 47 | | SelectName PrefixExp Name -- ^/table.variable/ 48 | deriving (Show, Eq, Data, Typeable, Generic) 49 | 50 | data Binop = Add | Sub | Mul | Div | Exp | Mod | Concat 51 | | LT | LTE | GT | GTE | EQ | NEQ | And | Or 52 | | IDiv | ShiftL | ShiftR | BAnd | BOr | BXor 53 | deriving (Show, Eq, Data, Typeable, Generic) 54 | 55 | data Unop = Neg | Not | Len | Complement 56 | deriving (Show, Eq, Data, Typeable, Generic) 57 | 58 | data PrefixExp 59 | = PEVar Var 60 | | PEFunCall FunCall 61 | | Paren Exp 62 | deriving (Show, Eq, Data, Typeable, Generic) 63 | 64 | data TableField 65 | = ExpField Exp Exp -- ^/[exp] = exp/ 66 | | NamedField Name Exp -- ^/name = exp/ 67 | | Field Exp 68 | deriving (Show, Eq, Data, Typeable, Generic) 69 | 70 | -- | A block is list of statements with optional return statement. 71 | data Block = Block [Stat] (Maybe [Exp]) 72 | deriving (Show, Eq, Data, Typeable, Generic) 73 | 74 | data FunName = FunName Name [Name] (Maybe Name) 75 | deriving (Show, Eq, Data, Typeable, Generic) 76 | 77 | data FunBody = FunBody [Name] Bool Block -- ^(args, vararg, block) 78 | deriving (Show, Eq, Data, Typeable, Generic) 79 | 80 | data FunCall 81 | = NormalFunCall PrefixExp FunArg -- ^/prefixexp ( funarg )/ 82 | | MethodCall PrefixExp Name FunArg -- ^/prefixexp : name ( funarg )/ 83 | deriving (Show, Eq, Data, Typeable, Generic) 84 | 85 | data FunArg 86 | = Args [Exp] -- ^list of args 87 | | TableArg [TableField] -- ^table constructor 88 | | StringArg String -- ^string 89 | deriving (Show, Eq, Data, Typeable, Generic) 90 | 91 | instance NFData Stat 92 | instance NFData Exp 93 | instance NFData Var 94 | instance NFData Binop 95 | instance NFData Unop 96 | instance NFData PrefixExp 97 | instance NFData TableField 98 | instance NFData Block 99 | instance NFData FunName 100 | instance NFData FunBody 101 | instance NFData FunCall 102 | instance NFData FunArg 103 | -------------------------------------------------------------------------------- /src/Language/Lua/Token.hs: -------------------------------------------------------------------------------- 1 | module Language.Lua.Token where 2 | 3 | -- | Lua tokens 4 | data LToken = LTokPlus -- ^+ 5 | | LTokMinus -- ^\- 6 | | LTokStar -- ^\* 7 | | LTokSlash -- ^/ 8 | | LTokPercent -- ^% 9 | | LTokExp -- ^^ 10 | | LTokSh -- ^# 11 | | LTokEqual -- ^== 12 | | LTokNotequal -- ^~= 13 | | LTokLEq -- ^<= 14 | | LTokGEq -- ^\>= 15 | | LTokLT -- ^< 16 | | LTokGT -- ^\> 17 | | LTokAssign -- ^= 18 | | LTokLParen -- ^( 19 | | LTokRParen -- ^) 20 | | LTokLBrace -- ^{ 21 | | LTokRBrace -- ^} 22 | | LTokLBracket -- ^\[ 23 | | LTokRBracket -- ^] 24 | | LTokDColon -- ^:: 25 | | LTokSemic -- ^; 26 | | LTokColon -- ^: 27 | | LTokComma -- ^, 28 | | LTokDot -- ^. 29 | | LTokDDot -- ^.. 30 | | LTokEllipsis -- ^... 31 | | LTokDLT -- ^<< 32 | | LTokDGT -- ^>> 33 | | LTokAmpersand -- ^& 34 | | LTokPipe -- ^| 35 | | LTokDSlash -- ^// 36 | | LTokTilde -- ^~ 37 | 38 | | LTokAnd -- ^and 39 | | LTokBreak -- ^break 40 | | LTokDo -- ^do 41 | | LTokElse -- ^else 42 | | LTokElseIf -- ^elseif 43 | | LTokEnd -- ^end 44 | | LTokFalse -- ^false 45 | | LTokFor -- ^for 46 | | LTokFunction -- ^function 47 | | LTokGoto -- ^goto 48 | | LTokIf -- ^if 49 | | LTokIn -- ^in 50 | | LTokLocal -- ^local 51 | | LTokNil -- ^nil 52 | | LTokNot -- ^not 53 | | LTokOr -- ^or 54 | | LTokRepeat -- ^repeat 55 | | LTokReturn -- ^return 56 | | LTokThen -- ^then 57 | | LTokTrue -- ^true 58 | | LTokUntil -- ^until 59 | | LTokWhile -- ^while 60 | 61 | | LTokNum String -- ^number constant 62 | | LTokSLit String -- ^string constant. Includes quotes! 63 | | LTokIdent String -- ^identifier 64 | | LTokEof -- ^end of file 65 | deriving Eq 66 | 67 | instance Show LToken where 68 | show LTokPlus = "`+`" 69 | show LTokMinus = "`-`" 70 | show LTokStar = "`*`" 71 | show LTokSlash = "`/`" 72 | show LTokPercent = "`%`" 73 | show LTokExp = "`^`" 74 | show LTokSh = "`#`" 75 | show LTokEqual = "`==`" 76 | show LTokNotequal = "`~=`" 77 | show LTokLEq = "`<=`" 78 | show LTokGEq = "`>=`" 79 | show LTokLT = "`<`" 80 | show LTokGT = "`>`" 81 | show LTokAssign = "`=`" 82 | show LTokLParen = "`(`" 83 | show LTokRParen = "`)`" 84 | show LTokLBrace = "`{`" 85 | show LTokRBrace = "`}`" 86 | show LTokLBracket = "`[`" 87 | show LTokRBracket = "`]`" 88 | show LTokDColon = "`::`" 89 | show LTokSemic = "`;`" 90 | show LTokColon = "`:`" 91 | show LTokComma = "`,`" 92 | show LTokDot = "`.`" 93 | show LTokDDot = "`..`" 94 | show LTokEllipsis = "`...`" 95 | show LTokDLT = "`<<`" 96 | show LTokDGT = "`>>`" 97 | show LTokAmpersand = "`&`" 98 | show LTokPipe = "`|`" 99 | show LTokDSlash = "`//`" 100 | show LTokTilde = "`~`" 101 | 102 | show LTokAnd = "`and`" 103 | show LTokBreak = "`break`" 104 | show LTokDo = "`do`" 105 | show LTokElse = "`else`" 106 | show LTokElseIf = "`elseif`" 107 | show LTokEnd = "`end`" 108 | show LTokFalse = "`false`" 109 | show LTokFor = "`for`" 110 | show LTokFunction = "`function`" 111 | show LTokGoto = "`goto`" 112 | show LTokIf = "`if`" 113 | show LTokIn = "`in`" 114 | show LTokLocal = "`local`" 115 | show LTokNil = "`nil`" 116 | show LTokNot = "`not`" 117 | show LTokOr = "`or`" 118 | show LTokRepeat = "`repeat`" 119 | show LTokReturn = "`return`" 120 | show LTokThen = "`then`" 121 | show LTokTrue = "`true`" 122 | show LTokUntil = "`until`" 123 | show LTokWhile = "`while`" 124 | 125 | show (LTokNum n) = "number: " ++ show n 126 | show (LTokSLit s) = "string: " ++ show s 127 | show (LTokIdent i) = "identifier: " ++ show i 128 | show LTokEof = "EOF" 129 | -------------------------------------------------------------------------------- /src/Text/Parsec/LTok.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | 3 | -- | Lexer/Parsec interface 4 | module Text.Parsec.LTok 5 | ( tok 6 | , tok' 7 | , anyIdent 8 | , number 9 | , stringlit 10 | , Parser 11 | ) where 12 | 13 | import Language.Lua.Annotated.Lexer (LTok, AlexPosn(..)) 14 | import Language.Lua.Token 15 | 16 | import Text.Parsec hiding (satisfy, string) 17 | 18 | type Parser = Parsec [LTok] () 19 | 20 | -- | This parser succeeds whenever the given predicate returns true when called with 21 | -- parsed `LTok`. Same as 'Text.Parsec.Char.satisfy'. 22 | satisfy :: (Stream [LTok] m LTok) => (LTok -> Bool) -> ParsecT [LTok] u m LToken 23 | satisfy f = tokenPrim show nextPos tokeq 24 | where 25 | tokeq :: LTok -> Maybe LToken 26 | tokeq t = if f t then Just (fst t) else Nothing 27 | 28 | satisfy' :: (Stream [LTok] m LTok) => (LTok -> Maybe a) -> ParsecT [LTok] u m a 29 | satisfy' = tokenPrim show nextPos 30 | 31 | nextPos :: SourcePos -> LTok -> [LTok] -> SourcePos 32 | nextPos pos _ ((_, AlexPn _ l c):_) = setSourceColumn (setSourceLine pos l) c 33 | nextPos pos _ [] = pos 34 | 35 | -- | Parses given `LToken`. 36 | tok :: (Stream [LTok] m LTok) => LToken -> ParsecT [LTok] u m LToken 37 | tok t = satisfy (\(t', _) -> t' == t) show t 38 | 39 | tok' :: (Stream [LTok] m LTok) => LToken -> ParsecT [LTok] u m () 40 | tok' p = tok p >> return () 41 | 42 | -- | Parses a `LTokIdent`. 43 | anyIdent :: Monad m => ParsecT [LTok] u m String 44 | anyIdent = satisfy' p "ident" 45 | where p (t, _) = case t of LTokIdent i -> Just i 46 | _ -> Nothing 47 | 48 | -- | Parses a `LTokNum`. 49 | number :: Monad m => ParsecT [LTok] u m String 50 | number = satisfy' p "number" 51 | where p (t, _) = case t of LTokNum n -> Just n 52 | _ -> Nothing 53 | 54 | -- | Parses a `LTokSLit`. 55 | stringlit :: Monad m => ParsecT [LTok] u m String 56 | stringlit = satisfy' p "string" 57 | where p (t, _) = case t of LTokSLit s -> Just s 58 | _ -> Nothing 59 | -------------------------------------------------------------------------------- /src/Text/PrettyPrint/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2000, Daan Leijen. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | This software is provided by the copyright holders "as is" and any 16 | express or implied warranties, including, but not limited to, the 17 | implied warranties of merchantability and fitness for a particular 18 | purpose are disclaimed. In no event shall the copyright holders be 19 | liable for any direct, indirect, incidental, special, exemplary, or 20 | consequential damages (including, but not limited to, procurement of 21 | substitute goods or services; loss of use, data, or profits; or 22 | business interruption) however caused and on any theory of liability, 23 | whether in contract, strict liability, or tort (including negligence 24 | or otherwise) arising in any way out of the use of this software, even 25 | if advised of the possibility of such damage. 26 | -------------------------------------------------------------------------------- /syntax: -------------------------------------------------------------------------------- 1 | chunk ::= block 2 | 3 | block ::= {stat} [retstat] 4 | 5 | stat ::= ‘;’ | 6 | varlist ‘=’ explist | 7 | functioncall | 8 | label | 9 | break | 10 | goto Name | 11 | do block end | 12 | while exp do block end | 13 | repeat block until exp | 14 | if exp then block {elseif exp then block} [else block] end | 15 | for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | 16 | for namelist in explist do block end | 17 | function funcname funcbody | 18 | local function Name funcbody | 19 | local namelist [‘=’ explist] 20 | 21 | retstat ::= return [explist] [‘;’] 22 | 23 | label ::= ‘::’ Name ‘::’ 24 | 25 | funcname ::= Name {‘.’ Name} [‘:’ Name] 26 | 27 | varlist ::= var {‘,’ var} 28 | 29 | var ::= Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name 30 | 31 | namelist ::= Name {‘,’ Name} 32 | 33 | explist ::= exp {‘,’ exp} 34 | 35 | exp ::= nil | false | true | Number | String | ‘...’ | functiondef | 36 | prefixexp | tableconstructor | exp binop exp | unop exp 37 | 38 | prefixexp ::= var | functioncall | ‘(’ exp ‘)’ 39 | 40 | functioncall ::= prefixexp args | prefixexp ‘:’ Name args 41 | 42 | args ::= ‘(’ [explist] ‘)’ | tableconstructor | String 43 | 44 | functiondef ::= function funcbody 45 | 46 | funcbody ::= ‘(’ [parlist] ‘)’ block end 47 | 48 | parlist ::= namelist [‘,’ ‘...’] | ‘...’ 49 | 50 | tableconstructor ::= ‘{’ [fieldlist] ‘}’ 51 | 52 | fieldlist ::= field {fieldsep field} [fieldsep] 53 | 54 | field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp 55 | 56 | fieldsep ::= ‘,’ | ‘;’ 57 | 58 | binop ::= ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘^’ | ‘%’ | ‘..’ | 59 | ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | 60 | and | or 61 | 62 | unop ::= ‘-’ | not | ‘#’ -------------------------------------------------------------------------------- /tests/numbers: -------------------------------------------------------------------------------- 1 | 3 2 | 3.0 3 | 3.1416 4 | 314.16e-2 5 | 0.31416E1 6 | 0xff 7 | 0x0.1E 8 | 0xA23p-4 9 | 0X1.921FB54442D18P+1 10 | -------------------------------------------------------------------------------- /tests/string-literal-roundtrip.lua: -------------------------------------------------------------------------------- 1 | x = "abc" 2 | x = "abc\ 3 | 123" 4 | x = "\0\1\10\010\100" 5 | x = "\"\"" 6 | x = "\a\b\t\n\f\r\v\\\'" 7 | x = [==[ 8 | abc123 9 | ]==] 10 | x = [[ 11 | abc 12 | 123 13 | ]] 14 | x = [===[]===] 15 | x = 'abc' 16 | x = 'abc\ 17 | 123' 18 | x = '\0\1\10\010\100' 19 | x = '\"\"' 20 | x = '\a\b\t\n\f\r\v\\\'' 21 | x = "汉字\x80" 22 | x = "汉字" 23 | x = '汉字\x80' 24 | x = '汉字' 25 | x = '\u{0}\u{000}\u{10ffff}' 26 | x = "\u{0}\u{000}\u{10ffff}" 27 | x = [[\a\b\c\d\f"""''']] 28 | x = "\x00\x01\xfe\xff" 29 | x = '\x00\x01\xfe\xff' 30 | -------------------------------------------------------------------------------- /tests/strings: -------------------------------------------------------------------------------- 1 | 'alo\n123"' 2 | "alo\n123\"" 3 | '\97lo\10\04923"' 4 | [[alo 5 | 123"]] 6 | [==[ 7 | alo 8 | 123"]==] 9 | --------------------------------------------------------------------------------