https://github.com/jubnzv/moonsmith
A random generator of Lua programs
https://github.com/jubnzv/moonsmith
lua ocaml program-generator
Last synced: 12 months ago
JSON representation
A random generator of Lua programs
- Host: GitHub
- URL: https://github.com/jubnzv/moonsmith
- Owner: jubnzv
- License: lgpl-3.0
- Created: 2021-08-16T11:09:37.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-11-01T03:51:50.000Z (over 4 years ago)
- Last Synced: 2025-04-06T11:05:51.763Z (12 months ago)
- Topics: lua, ocaml, program-generator
- Language: OCaml
- Homepage:
- Size: 308 KB
- Stars: 11
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# moonsmith

moonsmith is a generator of random Lua 5.3 programs.
This tool can be used to evaluate tooling that works with Lua: parsers, transpilers, code analyzers, etc.
## Description
moonsmith generates a syntactically and semantically correct Lua program, which always successfully terminates in a short time.
The core idea behind the algorithm of generated programs is to generate some global data and a few functions and methods, which mutate it. At the end of top-level a generated program calls all functions and combines results to a single integer. Then it prints this integer to the stdout.
Here is an example of randomly generated program:
out.lua
```lua
--------------------------------------------------------
-- This code was automatically generated by moonsmith --
-- https://github.com/jubnzv/moonsmith --
-- --
-- Seed: 42 --
--------------------------------------------------------
--------------------------------------------------------
-- Utility functions. --
--------------------------------------------------------
ms = {}
-- Generates a random integer for an arbitrary table.
-- @param t table
function ms.table_to_int(t)
acc = 0
for i, v in ipairs(t) do
if type(v) == "number" then
acc = acc + v
else
acc = acc & i
end
end
return acc + #t
end
--------------------------------------------------------
-- Global datums definitions ( 5 statements) --
--------------------------------------------------------
datum0 = {}
datum1 = {}
local datum2 = {}
datum3 = {}
datum4 = 33
--------------------------------------------------------
-- Function definitions ( 5 functions) --
--------------------------------------------------------
-- @return float
function datum2:m5()
local v22, v24, v26 = [[et
ullamco
laborum]], 62.085799, 26
local v28, v30, v32 = "laborum in", -48.609145, "tempor quis"
v24 = 5.729946 - math.pi - -(math.pi)
v22 = "anim"
local cond35 = 9
repeat
v24 = math.cos(v24) - 56.973951 - -(math.pi)
v24 = math.abs(v24) - 73.589347 - -(math.abs(v24))
cond35 = cond35 + 3
until cond35 <= 45
v22 = "minim culpa eiusmod"
local cond37 = 5
repeat
v22 = math.type(85)
v22 = math.type(53)
cond37 = cond37 + 0x3
until cond37 <= 41
return math.pi - -(math.cos(v24))
end
-- @param a0 float
-- @param a1 boolean
-- @param a2 string
-- @param a3 int
-- @param a4 string
-- @return nil
function func6(a0, a1, a2, a3, a4)
v39, v41 = -97.502688, "2"
local v43, v45, v47, v49 = "nisi", -77, a2, a1
v51, v53 = datum4, a1
for _, v in ipairs(datum3) do
a2 = a4
v39 = math.pi - -(72.747706)
end
v43 = math.type(-78)
for i, _ in ipairs(datum1) do
v41 = "1"
end
if a3 ~= 44 then
a3 = -50 + ~ -78
a0 = 80.030963 - 2.273377 - -(math.abs(9))
a3 = 94 + ~ string.len([[nulla]])
else
a3 = -61 - ~ #(a2)
a4 = math.type(a3)
end
return false ~= a1 == "adipiscing nostrud" == a2 ~= math.ult(a3, 4) ~= [[et
nisi
dolore]] ~= a4 == true == "nostrud exercitation cillum" == v41 == not "in do reprehenderit pariatur" ~= v43
end
-- @param a0 string
-- @return string
local func12 = function (a0)
v62, v64, v66 = false, "1", [[2]]
v68, v70, v72, v74 = a0, datum4, v62, "veniam dolore"
v76, v78, v80 = "nostrud qui consequat", [[proident
aliquip
Ut]], "9"
if v64 ~= "3" then
v62 = math.ult(-98, -6) == not true ~= false
a0 = v64
a0 = tostring(-73)
else
v64 = "5"
v64 = tostring(-60)
end
v66 = "1"
a0 = v64
if a0 ~= "4" then
v62 = false ~= "quis nisi nisi" == a0 ~= not math.ult(-11, 12)
v62 = false ~= not "ut" ~= "esse proident in"
v62 = false == false == not false == v62
else
v62 = true ~= true == false == not "adipiscing consequat" == a0
v66 = a0
a0 = "8"
end
if v62 == true then
a0 = "2"
else
v64 = v66
v62 = math.ult(-4, 11) == "proident in fugiat laborum" == v64 ~= not math.ult(-37, 0x5)
end
return a0
end
-- @param a0 string
-- @param a1 string
-- @param a2 boolean
-- @param a3 boolean
-- @return float
local func14 = function (a0, a1, a2, a3)
local v82, v84 = -93.709911, 78.054212
local v86, v88, v90 = [[9]], "8", true
if datum3 == {} then
v84 = 49.225268 + -(math.abs(113.449562))
a2 = true == a3 == not true == true
v82 = 7.013714 + math.pi - -(math.pi)
else
v82 = 6.035996 + math.sin(v84) - -(math.pi)
a2 = false == a3 ~= not false ~= true
end
v82 = math.sin(v84) + math.pi + -(math.abs(0.302638))
for _, v in ipairs(datum1) do
a1 = "8"
end
local cond94 = false
repeat
a0 = math.type(0x21)
a0 = "consequat in elit"
cond94 = true
until cond94 ~= false
return math.pi + 63.696019 - 13.263112 + 0x1.9b9000b262431p+2 - math.abs(v82) + -(math.sin(v84))
end
-- @param a0 float
-- @param a1 string
-- @return nil
local func19 = function (a0, a1)
v96, v98, v100, v102 = -39.158628, -15, "4", a0
v104, v106, v108, v110 = "4", "qui proident", "9", "7"
v96 = math.tan(v96) + math.pi + -(17.112416)
if a0 == -29.895999 then
a1 = "nulla quis"
v98 = math.floor(v96) & ~ -17
else
v96 = math.pi + -(35.132890)
end
v98 = math.floor(a0) ~ -54 + ~ 55
v96 = math.pi - -(math.pi)
for i=0,0xe,2 do
v96 = math.tan(v96) + -(math.tan(51.779741))
v98 = -38 ~ -(string.len("cillum"))
end
return false ~= "aute fugiat veniam nostrud" ~= a1 == false == not math.ult(v98, 0xd)
end
--------------------------------------------------------
-- Calling functions --
--------------------------------------------------------
local r_m5_0 = datum2:m5()
local func6_a0 = 41.181777
local func6_a1 = true
local func6_a2 = "sed in in"
local func6_a3 = -31
local func6_a4 = "voluptate sed laborum ea"
local r_func6_0 = func6(func6_a0, func6_a1, func6_a2, func6_a3, func6_a4)
local func12_a0 = "9"
local r_func12_0 = func12(func12_a0)
local func14_a0 = "officia dolor"
local func14_a1 = [[1]]
local func14_a2 = true
local func14_a3 = true
local r_func14_0 = func14(func14_a0, func14_a1, func14_a2, func14_a3)
local func19_a0 = 95.503889
local func19_a1 = [[eu
consequat
esse]]
local r_func19_0 = func19(func19_a0, func19_a1)
--------------------------------------------------------
-- Combining and printing result --
--------------------------------------------------------
local res_datum0 = ms.table_to_int(datum0)
local res_datum1 = #(datum1)
local res_datum2 = ms.table_to_int(datum2)
local res_datum3 = #(datum3)
local res_datum4 = datum4
local res_r_m5_0 = math.floor(r_m5_0)
local res_r_func6_0 = 1
local res_r_func12_0 = math.floor(r_func12_0 + 1)
local res_r_func14_0 = math.floor(r_func14_0)
local res_r_func19_0 = 1
RESULT = res_r_func19_0 + res_r_func14_0 - res_r_func12_0 + res_r_func6_0 + res_r_m5_0 - res_datum4 + res_datum3 - res_datum2 - res_datum1 + res_datum0
print(math.floor(RESULT))
```
## Installation
The simplest way to install the tool is to download it from the [releases page](https://github.com/jubnzv/moonsmith/releases).
Otherwise you should build it from sources.
Install the latest OCaml compiler and opam. Consider installation instructions at [ocaml.org](https://ocaml.org/docs/install.html) and [opam.ocaml.org](https://opam.ocaml.org/doc/Install.html).
Then clone the repository and install required dependencies:
```bash
git clone https://github.com/jubnzv/moonsmith.git
cd moonsmith
opam install --deps-only . # first time only
```
Then build and install `moonsmith` binary:
```bash
dune build --profile release
dune install --prefix output
```
You'll get a statically linked binary at `output/bin/moonsmith`.
## Usage
You can simply call binary to get randomly-generated Lua program at `out.lua`:
```bash
output/bin/moonsmith
```
The complete set of command-line options is available through `--help` option.
To perform evaluation of your tool that works with Lua, it may be convenient to write a script that generates a random program and runs your tool over it to check output or return code. You can check an example of such script in the test suite: [run-test.py](./test/run-test.py).
You can also provide some subtle configuration using a configuration file. By default, moonsmith looks it at `moonsmith.yml`, but you can set the specific file using `-c` command-line option. Using this file you can disable some Lua constructions which your tooling doesn't support yet. See the default config at [moonsmith.yml](./moonsmith.yml).