Full Code of prometheus-lua/Prometheus for AI

master 9d90158b54f4 cached
124 files
391.9 KB
102.0k tokens
1 requests
Download .txt
Showing preview only (424K chars total). Download the full file or copy to clipboard to get everything.
Repository: prometheus-lua/Prometheus
Branch: master
Commit: 9d90158b54f4
Files: 124
Total size: 391.9 KB

Directory structure:
gitextract_h0mah7x0/

├── .editorconfig
├── .gitattributes
├── .gitbook.yaml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   └── workflows/
│       ├── Build.yml
│       └── Test.yml
├── .gitignore
├── LICENSE
├── benchmark.lua
├── cli.lua
├── doc/
│   ├── README.md
│   ├── SUMMARY.md
│   ├── advanced/
│   │   └── using-prometheus-in-your-lua-application.md
│   ├── getting-started/
│   │   ├── command-line-options.md
│   │   ├── installation.md
│   │   ├── obfuscating-your-first-script.md
│   │   ├── presets.md
│   │   ├── the-config-object.md
│   │   └── writing-a-custom-config-file.md
│   └── steps/
│       ├── anti-tamper.md
│       ├── constantarray.md
│       ├── encryptstrings.md
│       ├── proxifylocals.md
│       ├── splitstrings.md
│       ├── vmify.md
│       └── wrapinfunction.md
├── prometheus-main.lua
├── readme.md
├── src/
│   ├── cli.lua
│   ├── colors.lua
│   ├── highlightlua.lua
│   ├── logger.lua
│   ├── presets.lua
│   ├── prometheus/
│   │   ├── ast.lua
│   │   ├── compiler/
│   │   │   ├── block.lua
│   │   │   ├── compile_core.lua
│   │   │   ├── compile_top.lua
│   │   │   ├── compiler.lua
│   │   │   ├── constants.lua
│   │   │   ├── emit.lua
│   │   │   ├── expressions/
│   │   │   │   ├── and.lua
│   │   │   │   ├── binary.lua
│   │   │   │   ├── boolean.lua
│   │   │   │   ├── function_call.lua
│   │   │   │   ├── function_literal.lua
│   │   │   │   ├── index.lua
│   │   │   │   ├── len.lua
│   │   │   │   ├── negate.lua
│   │   │   │   ├── nil.lua
│   │   │   │   ├── not.lua
│   │   │   │   ├── number.lua
│   │   │   │   ├── or.lua
│   │   │   │   ├── pass_self_function_call.lua
│   │   │   │   ├── string.lua
│   │   │   │   ├── table_constructor.lua
│   │   │   │   ├── vararg.lua
│   │   │   │   └── variable.lua
│   │   │   ├── expressions.lua
│   │   │   ├── register.lua
│   │   │   ├── statements/
│   │   │   │   ├── assignment.lua
│   │   │   │   ├── break_statement.lua
│   │   │   │   ├── compound.lua
│   │   │   │   ├── continue_statement.lua
│   │   │   │   ├── do_statement.lua
│   │   │   │   ├── for_in_statement.lua
│   │   │   │   ├── for_statement.lua
│   │   │   │   ├── function_call.lua
│   │   │   │   ├── function_declaration.lua
│   │   │   │   ├── if_statement.lua
│   │   │   │   ├── local_function_declaration.lua
│   │   │   │   ├── local_variable_declaration.lua
│   │   │   │   ├── pass_self_function_call.lua
│   │   │   │   ├── repeat_statement.lua
│   │   │   │   ├── return.lua
│   │   │   │   └── while_statement.lua
│   │   │   ├── statements.lua
│   │   │   └── upvalue.lua
│   │   ├── enums.lua
│   │   ├── namegenerators/
│   │   │   ├── Il.lua
│   │   │   ├── confuse.lua
│   │   │   ├── mangled.lua
│   │   │   ├── mangled_shuffled.lua
│   │   │   └── number.lua
│   │   ├── namegenerators.lua
│   │   ├── parser.lua
│   │   ├── pipeline.lua
│   │   ├── randomLiterals.lua
│   │   ├── randomStrings.lua
│   │   ├── scope.lua
│   │   ├── step.lua
│   │   ├── steps/
│   │   │   ├── AddVararg.lua
│   │   │   ├── AntiTamper.lua
│   │   │   ├── ConstantArray.lua
│   │   │   ├── EncryptStrings.lua
│   │   │   ├── NumbersToExpressions.lua
│   │   │   ├── ProxifyLocals.lua
│   │   │   ├── SplitStrings.lua
│   │   │   ├── Vmify.lua
│   │   │   ├── Watermark.lua
│   │   │   ├── WatermarkCheck.lua
│   │   │   └── WrapInFunction.lua
│   │   ├── steps.lua
│   │   ├── tokenizer.lua
│   │   ├── unparser.lua
│   │   ├── util.lua
│   │   └── visitast.lua
│   └── prometheus.lua
├── tests/
│   ├── ambiguous-call.lua
│   ├── closures.lua
│   ├── coroutines.lua
│   ├── fibonacci.lua
│   ├── iterator.lua
│   ├── loops.lua
│   ├── matrix.lua
│   ├── metatables.lua
│   ├── multi-return.lua
│   ├── primes.lua
│   ├── repeat-test.lua
│   ├── state-machine.lua
│   ├── strings.lua
│   ├── syntax.lua
│   ├── table-merge.lua
│   └── upvalues.lua
└── tests.lua

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
[*.lua]
indent_style = tab
indent_size = 4
end_of_line = lf


================================================
FILE: .gitattributes
================================================
*.lua text=auto
*.lua eol=lf


================================================
FILE: .gitbook.yaml
================================================
root: ./doc/


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**Expected behavior**
A clear and concise description of what you expected to happen.

**To Reproduce**
Steps to reproduce the behavior:

If your problem is a non-working obfuscated file, please also include a minimal source code example, your config file as well as the output file that you got.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/workflows/Build.yml
================================================
name: Build

on:
  push:
    branches:
      main

jobs:
  build:
    runs-on: windows-latest # gh-actions-lua doesn't work on windows
    steps:
      - name: Checkout repo
        uses: actions/checkout@master
      - name: Download srlua-mingw
        run: curl -o srlua.zip "https://raw.githubusercontent.com/joedf/LuaBuilds/gh-pages/hdata/srlua-5.1.5_Win32_bin.zip"
      - name: Unzip srlua-mingw
        run: |
          tar -xf srlua.zip
          Rename-Item -Path srglue.exe -NewName glue.exe
      - name: Download Lua53
        run: curl -o Lua53.zip "https://raw.githubusercontent.com/joedf/LuaBuilds/gh-pages/hdata/lua-5.3.5_Win64_bin.zip"
      - name: Unzip Lua53
        run: |
          tar -xf Lua53.zip
      - run: dir
      - name: Build the project
        run: |
          ./build.bat
        shell: bash
      - name: Zip the build
        uses: papeloto/action-zip@v1
        with:
          files: build/
          dest: build.zip
      - name: Load version and name
        run: | # I have no idea why but 5.1 just won't work for some reason
          echo "prometheus_full_version=$(./lua.exe ./src/config.lua --FullVersion)" >> $GITHUB_ENV
          echo "prometheus_version=$(./lua.exe ./src/config.lua --Version)" >> $GITHUB_ENV
        shell: bash
      - name: Upload binaries to release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: build.zip
          asset_name: ${{ env.prometheus_full_version }}.zip
          tag: release-${{ github.ref }}-${{ env.prometheus_version }}
          release_name: ${{ env.prometheus_version }}
          overwrite: true
          body: ${{ env.prometheus_full_version }}  ${{ github.event.commits[0].message }}

================================================
FILE: .github/workflows/Test.yml
================================================
name: Test
on:  
  push:
  pull_request:
    branches:
      - master

jobs:
  test-linux:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@master
      - name: Install Lua
        uses: leafo/gh-actions-lua@master
        with:
          luaVersion: 5.1
      - name: Run test case
        run: lua ./tests.lua --Linux --CI


================================================
FILE: .gitignore
================================================
# Ignore Vscode Folder
.vscode

# Ignore Lua Implementation and srlua
lua51.dll
luajit.exe
srlua
luajit
buildnotes.txt
srlua.exe
glue.exe
build

# Ignore Local Test Files
test.lua
test.obfuscated.lua
config.lua

================================================
FILE: LICENSE
================================================
PROMETHEUS LICENSE
Copyright (c) 2025 Elias Oelschner
https://github.com/prometheus-lua/Prometheus

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

  1. Retained Notice.
     The above copyright notice and this permission notice shall be included
     in all copies or substantial portions of the Software that are distributed
     in source or object form, unless explicitly stated otherwise in this
     license.

  2. Attribution Requirement.
     Any Product or Service that (a) includes, links to, wraps, depends on,
     is derived from, uses, or otherwise incorporates the Software (including
     via modification, obfuscation, binary linking, packaging, or embedding),
     whether distributed, provided for use, or made available over a network
     (collectively, "Using Products/Services"), must provide clear,
     reasonably prominent attribution to Prometheus as follows:

       "Based on Prometheus by Elias Oelschner, https://github.com/prometheus-lua/Prometheus"

     This attribution must appear in at least one of the following locations,
     as applicable and reasonably prominent for the type of Using Product/Service:

       a) In-user interface: a visible "About", "Credits", or equivalent screen
          within the product's primary user interface (graphical or web UI).
       b) On the product web site: a visible place such as a footer, About page,
          or documentation landing page that is accessible to the product's users.
       c) In the tool itself: the program's --version, --help output, or similar
          command-line/displayed metadata for CLI tools.
       d) Documentation: in user or developer documentation, README, or product
          manual that accompanies the product.

     For Software provided as a Network Service or SaaS (i.e., made available
     for use over a network rather than distributed as a copy), the attribution
     must be visible on the public-facing web UI (for example on the login
     screen, footer, About page, or a help/credits page accessible without an
     account), and must include the exact phrase above and the URL.

  3. Derivative Statement.
     Any derivative work, modification, fork, or reimplementation of the
     Software that is publicly distributed, publicly hosted, or provided as a
     service must include a prominent statement in its README (or equivalent
     public-facing documentation) that it is based on Prometheus and include the
     exact attribution text in section 2.

  4. Generated Output Exception.
     Files or artifacts produced by running or using the Software (for example,
     obfuscated output files, compiled artifacts, transformed source files,
     or other generated outputs) are NOT required by this license to carry
     copyright notices or license text. The attribution obligations in section 2
     continue to apply to the Using Product/Service that produces, distributes,
     or serves those outputs.

  5. No Trademark License.
     This license does not grant any rights to use the trade names, trademarks,
     service marks, or product names of the Licensor except as required for the
     textual attribution specified in section 2.

  6. Compliance and Termination.
     Any failure to comply with the obligations in sections 2 or 3 will
     terminate the rights granted under this license for the non-compliant
     party with respect to the Software. Rights may be reinstated if the
     non-compliant party cures the breach within thirty (30) days after
     receiving written notice from the Licensor and provides reasonable proof
     of cure.

  7. Sublicensing.
     You may sublicense the Software, provided that any sublicensee is bound
     by the terms of this license and the attribution obligations described
     herein.

  8. Warranty Disclaimer.
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

  9. Limitation of Liability.
     IN NO EVENT WILL THE COPYRIGHT HOLDER BE LIABLE FOR ANY INDIRECT,
     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING IN ANY
     WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
     OF SUCH DAMAGE.

  10. Governing Law.
     This license shall be governed by and construed in accordance with the
     laws of the jurisdiction chosen by the Licensor. This clause does not
     limit any mandatory consumer protections that may apply in certain
     jurisdictions.

By exercising any rights granted to you under this License, you accept and
agree to be bound by the terms and conditions of this License.


================================================
FILE: benchmark.lua
================================================
print("PROMETHEUS Benchmark")
print("Based On IronBrew Benchmark")
local Iterations = 100000
print("Iterations: " .. tostring(Iterations))

print("CLOSURE testing.")
local Start = os.clock()
local TStart = Start
for _ = 1, Iterations do
	(function()
		if not true then
			print("Hey gamer.")
		end
	end)()
end
print("Time:", os.clock() - Start .. "s")

print("SETTABLE testing.")
Start = os.clock()
local T = {}
for Idx = 1, Iterations do
	T[tostring(Idx)] = "EPIC GAMER " .. tostring(Idx)
end

print("Time:", os.clock() - Start .. "s")

print("GETTABLE testing.")
Start = os.clock()
for Idx = 1, Iterations do
	T[1] = T[tostring(Idx)]
end

print("Time:", os.clock() - Start .. "s")
print("Total Time:", os.clock() - TStart .. "s")


================================================
FILE: cli.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- cli.lua
--
-- This Script contains the Code for the Prometheus CLI

-- Configure package.path for requiring Prometheus
local function script_path()
	local str = debug.getinfo(2, "S").source:sub(2)
	return str:match("(.*[/%\\])") or "";
end
package.path = script_path() .. "?.lua;" .. package.path;
require("src.cli");

================================================
FILE: doc/README.md
================================================
---
description: Prometheus is an Lua Obfuscator, that is written in pure Lua.
---

# Prometheus

Prometheus can obfuscate Lua51 as well as Roblox's LuaU, which is an optionally typed superset of Lua51.

View Prometheus on [github](https://github.com/levno-710/Prometheus).

This Documentation only applies to the newest version of Prometheus.


================================================
FILE: doc/SUMMARY.md
================================================
# Table of contents

* [Prometheus](README.md)

## Getting Started

* [Installation](getting-started/installation.md)
* [Obfuscating your first script](getting-started/obfuscating-your-first-script.md)
* [Command Line Options](getting-started/command-line-options.md)
* [Presets](getting-started/presets.md)
* [Writing a custom Config File](getting-started/writing-a-custom-config-file.md)
* [The Config Object](getting-started/the-config-object.md)

## Steps

* [WrapInFunction](steps/wrapinfunction.md)
* [Vmify](steps/vmify.md)
* [SplitStrings](steps/splitstrings.md)
* [ProxifyLocals](steps/proxifylocals.md)
* [EncryptStrings](steps/encryptstrings.md)
* [ConstantArray](steps/constantarray.md)
* [AntiTamper](steps/anti-tamper.md)


## advanced

* [Using Prometheus in your Lua Application](advanced/using-prometheus-in-your-lua-application.md)


================================================
FILE: doc/advanced/using-prometheus-in-your-lua-application.md
================================================
# Using Prometheus in your Lua Application

Prometheus can also be used as a library for your custom Lua Applications instead of using its cli tool. 

In order to do that you'll first need to clone the github repo:

```batch
git clone "https://github.com/levno-710/Prometheus.git"
```

After that, you'll need to copy everything within the src folder to your project. Let's say you created a folder named `prometheus`, where all the Prometheus files are located. You can the use the following code to obfuscate a string:

{% code title="use_prometheus.lua" %}
```lua
local Prometheus = require("prometheus.prometheus")

-- If you don't want console output
Prometheus.Logger.logLevel = Prometheus.Logger.LogLevel.Error

-- Your code
local code = 'print("Hello, World!")'

-- Create a Pipeline using the Strong preset
local pipeline = Prometheus.Pipeline:fromConfig(Prometheus.Presets.Strong)

-- Apply the obfuscation and print the result
print(pipeline:apply(code));
```
{% endcode %}

Instead of passing the Strong preset you could also pass a custom [Config Object](../getting-started/the-config-object.md).


================================================
FILE: doc/getting-started/command-line-options.md
================================================
# Command Line Options

The following table provides a brief overview over the command line options:

| Option                        | Usage                                                       |
| ----------------------------- | ----------------------------------------------------------- |
| --preset \[name]; --p \[name] | Specify the config preset to be used; [Details](presets.md) |
| --config \[path]; --c \[path] | Specify the path to a custom config file                    |
| --out \[path]; --o \[path]    | Specify the path of the output file                         |
| --nocolors                    | Disable ansi colors escape sequences                        |
| --Lua51                       | Handle input as Lua 5.1                                     |
| --LuaU                        | Handle input as LuaU                                        |
| --pretty                      | Pretty print the output                                     |


================================================
FILE: doc/getting-started/installation.md
================================================
# Installation

To install Prometheus, simply clone the Github Repository using:

```batch
git clone "https://github.com/levno-710/Prometheus.git"
```

Alternatively you can download the Sources [here](https://github.com/levno-710/Prometheus/archive/refs/heads/master.zip).

Prometheus also Requires LuaJIT or Lua51 in order to work. The Lua51 binaries can be downloaded [here](https://sourceforge.net/projects/luabinaries/files/5.1.5/Tools%20Executables/).


================================================
FILE: doc/getting-started/obfuscating-your-first-script.md
================================================
# Obfuscating your first script

Now that you have downloaded and Prometheus, you probably wonder how to use it. In this quick tutorial you are going to learn how to obfuscate your first file.

Note that in the following command examples `lua` should be replaced by your lua implementation.

Create the following file within the Prometheus main directory that you just downloaded:

{% code title="hello_world.lua" %}
```lua
print("Hello, World")
```
{% endcode %}

Now run the following command inside of the Prometheus directory:

```batch
lua ./cli.lua ./hello_world.lua
```

You may notice, that the console output looks weird. If that is the case, your terminal does not support ansi color escape sequences. You should add the `--nocolors` option:

```batch
lua ./cli.lua --nocolors ./hello_world.lua
```

This should create the following file:

{% code title="hello_world.obfuscated.lua" %}
```lua
print("Hello, World")
```
{% endcode %}

As you can see, the file hasn't changed at all. That is because by default prometheus is just a minifier and the code we gave it was already as small as possible. To actually obfuscate the file, prometheus must be told which obfuscation steps it should apply in which order. In order to do this, the cli provides the `--preset` option which allows you to specify the name of a predefined configuration. There are currently the following presets:

* Minify
* Weak
* Medium
* Strong

In order to perform the obfuscation, you need to specify that Prometheus should use the Strong preset:

```batch
lua ./cli.lua --preset Medium ./hello_world.lua
```

The `hello_world.obfuscated.lua` should now contain the obfuscated code that should still print "Hello World".

Note that using the "Strong" preset is not recommended for large projects.


================================================
FILE: doc/getting-started/presets.md
================================================
# Presets

The following table provides an overview over the presets

| name   | size   | speed   |
| ------ | ------ | ------- |
| Minify | tiny   | fastest |
| Weak   | small  | fast    |
| Medium | medium | medium  |
| Strong | huge   | slowest |


================================================
FILE: doc/getting-started/the-config-object.md
================================================
# The Config Object

Prometheus takes a configuration object. In this object there can be many properties applied.   \
The following table provides an overview:

| Property      | type    | possible values                              | default           |
| ------------- | ------- | -------------------------------------------- | ----------------- |
| LuaVersion    | string  | "Lua51", "LuaU"                              | "Lua51"           |
| PrettyPrint   | boolean | true, false                                  | false             |
| VarNamePrefix | string  | any                                          | ""                |
| NameGenerator | string  | "Mangled", "MangledShuffled", "Il", "Number" | "MangledShuffled" |
| Seed          | number  | any                                          | 0                 |
| Steps         | table   | StepConfig\[]                                | {}                |

As this table shows, all properties in the config object are optional as they have a default value.

As an example, here is the code for the minify preset:

```lua
{
    -- The default LuaVersion is Lua51
    LuaVersion = "Lua51";
    -- For minifying no VarNamePrefix is applied
    VarNamePrefix = "";
    -- Name Generator for Variables
    NameGenerator = "MangledShuffled";
    -- No pretty printing
    PrettyPrint = false;
    -- Seed is generated based on current time
    Seed = 0;
    -- No obfuscation steps
    Steps = {}
};
```

### Steps

The most important property is the Steps property. This property must be a table of so called Step Configs. A Step in Prometheus describes a single transformation applied to your script by the Prometheus obfuscation pipeline. A StepConfiguration consists of the Name of the Step as well as settings for the step. All Steps will later be applied in the order they are defined. A single Step can be defined twice and will then be applied twice.

```lua
-- Obfuscation steps
Steps = {
    {
        -- This obfuscation step puts all constants into an array at the beginning of the code
        Name = "ConstantArray";
        Settings = {
            -- Apply to Strings only
            StringsOnly = true;
            -- Apply to all Constants, 0.5 would only affect 50% of strings
            Threshold = 1;
        }
    },
}
```

Under [Steps](broken-reference), you can find all current Steps, their names as well as the possible options.


================================================
FILE: doc/getting-started/writing-a-custom-config-file.md
================================================
# Writing a custom Config File

Configuration Files for Prometheus are just lua modules, that return a single object, which contains the configuration. Let's say we have the following config file:

{% code title="config.lua" %}
```lua
return {
        -- The default LuaVersion is Lua51
        LuaVersion = "Lua51"; -- or "LuaU"
        -- All Variables will start with this prefix
        VarNamePrefix = "";
        -- Name Generator for Variables that look like this: b, a, c, D, t, G
        NameGenerator = "MangledShuffled";
        -- No pretty printing
        PrettyPrint = false;
        -- Seed is generated based on current time
        -- When specifying a seed that is not 0, you will get the same output every time
        Seed = 0;
        -- Obfuscation steps
        Steps = {
            {
                -- This obfuscation step puts all constants into an array at the beginning of the code
                Name = "ConstantArray";
                Settings = {
                    -- Apply to Strings only
                    StringsOnly = true;
                    -- Apply to all Constants, 0.5 would only affect 50% of strings
                    Threshold = 1;
                }
            },
        }
    }
```
{% endcode %}

One can now obfuscate a script using this configuration by running:

```batch
lua ./cli.lua --config config.lua hello_world.lua
```

You should get the following output:

{% code title="hello_world.obfuscated.lua" %}
```lua
local N={"Hello, World!"}local function k(k)return N[k+40058]end print(k(-40057))
```
{% endcode %}

As you can see, the only transformation that was applied to our Hello World example was putting all strings (in this case only `"Hello, World!"` ) into an array and creating a wrapper function for retrieving the value.

### How does the Config File work?

The config file is simply a lua file, that returns the configuration object. Please note that this lua file is sandboxed by Prometheus when loading the configuration, meaning that you can't use any predefined functions like `tostring` or libraries like `math`.

See [The Config Object](the-config-object.md) to learn what this configuration object consists of.


================================================
FILE: doc/steps/anti-tamper.md
================================================
---
description: This step provides an obfuscation step, that breaks the script, when someone tries to tamper with it.
---

# Anti Tamper

### Settings

| Name        | type | description                                 | values                                  |
| ----------- | ---- | ------------------------------------------- | --------------------------------------- |
| UseDebug | boolean | Uses the debug library in lua. Disable this if you don't have access to debug library | "true","false" |


================================================
FILE: doc/steps/constantarray.md
================================================
---
description: >-
  This Step will Extract all Constants and put them into an Array at the
  beginning of the script
---

# ConstantArray

### Settings

| Name                 | type    | description                                                                                                  |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
| Threshold             | number  | The relative amount of nodes that will be affected"                                                          |
| StringsOnly          | boolean | Whether to only Extract Strings                                                                               |
| Shuffle              | boolean | Whether to shuffle the order of Elements in the Array                                                         |
| Rotate               | boolean | Whether to rotate the String Array by a specific (random) amount. This will be undone on runtime.             |
| LocalWrapperThreshold | number  | The relative amount of nodes functions, that will get local wrappers                                         |
| LocalWrapperCount    | number  | The number of Local wrapper Functions per scope. This only applies if LocalWrapperThreshold is greater than 0 |
| LocalWrapperArgCount | number  | The number of Arguments to the Local wrapper Functions                                                       |
| MaxWrapperOffset     | number  | The Max Offset for the Wrapper Functions                                                                     |

### Example

{% code title="in.lua" %}
```lua
print("1")
print("2")
print("3")
print("4")
```
{% endcode %}

{% code title="out.lua" %}
```lua
-- LocalWrapperCount = 3
-- LocalWrapperArgCount = 5
local F = {"4", "3", "2", "1"}
do
    local y, G = 1, 4
    while y < G do
        F[y], F[G] = F[G], F[y]
        y, G = y + 1, G - 1
    end
    y, G = 1, 3
    while y < G do
        F[y], F[G] = F[G], F[y]
        y, G = y + 1, G - 1
    end
    y, G = 4, 4
    while y < G do
        F[y], F[G] = F[G], F[y]
        y, G = y + 1, G - 1
    end
end
local function y(y)
    return F[y + 440]
end
local G = {cb = function(F, G, R, p, b)
        return y(G - 2277)
    end, n = function(F, G, R, p, b)
        return y(p + 47178)
    end, B = function(F, G, R, p, b)
        return y(F + 31775)
    end}
print(G.cb(1575, 1840, 2367, 1293, 1280))
print(G.B(-32213, -31781, -31538, -32780, -32728))
print(G.B(-32214, -33004, -31973, -32125, -31855))
print(G.B(-32211, -31884, -31217, -32222, -31210))

```
{% endcode %}


================================================
FILE: doc/steps/encryptstrings.md
================================================
---
description: This Step will encrypt all String constants in your code
---

# EncryptStrings

## Settings

None

## Example

{% code title="in.lua" %}
```lua
print("Hello, World!")
```
{% endcode %}

{% code title="out.lua" %}
```lua
-- Settings: None
local x, F
do
    local k = math.floor
    local I = math.random
    local Y = table.remove
    local i = string.char
    local K = 0
    local J = 2
    local Q = {}
    local W = {}
    local q = 0
    local R = {}
    for F = 1, 256, 1 do
        R[F] = F
    end
    repeat
        local F = I(1, #R)
        local x = Y(R, F)
        W[x] = i(x - 1)
    until #R == 0
    local j = {}
    local function B()
        if #j == 0 then
            K = (K * 173 + 8408159861491) % 35184372088832
            repeat
                J = (J * 160) % 257
            until J ~= 1
            local F = J % 32
            local x = (k(K / 2 ^ (13 - (J - F) / 32)) % 4294967296) / 2 ^ F
            local I = k((x % 1) * 4294967296) + k(x)
            local Y = I % 65536
            local i = (I - Y) / 65536
            local Q = Y % 256
            local W = (Y - Q) / 256
            local q = i % 256
            local R = (i - q) / 256
            j = {Q, W, q, R}
        end
        return table.remove(j)
    end
    local d = {}
    x = setmetatable({}, {__index = d, __metatable = nil})
    function F(x, k)
        local I = d
        if I[k] then
        else
            j = {}
            local F = W
            K = k % 35184372088832
            J = k % 255 + 2
            local Y = string.len(x)
            I[k] = ""
            local i = 198
            for Y = 1, Y, 1 do
                i = ((string.byte(x, Y) + B()) + i) % 256
                I[k] = I[k] .. F[i + 1]
            end
        end
        return k
    end
end
print(x[F("\219\018Q%~Y\225\128u\128\208&\155", 6909832146399)])

```
{% endcode %}


================================================
FILE: doc/steps/proxifylocals.md
================================================
---
description: This Step wraps all locals into Proxy Objects
---

# ProxifyLocals

### Settings

| Name        | type | description                                 | values                                  |
| ----------- | ---- | ------------------------------------------- | --------------------------------------- |
| LiteralType | enum | The type of the randomly generated literals | "dictionary", "number", "string", "any" |

### Example

{% code title="in.lua" %}
```lua
local x = "Hello, World!"
print(x)
```
{% endcode %}

{% code title="out.lua" %}
```lua
-- LiteralType = "dictionary"
local n = setmetatable
local D =
    n(
    {Wz = function()
        end},
    {__div = function(R, n)
            R.Wz = n
        end, __concat = function(R, n)
            return R.Wz
        end}
)
local R =
    n(
    {Js = "Hello, World!"},
    {__add = function(R, n)
            R.Js = n
        end, __index = function(R, n)
            return rawget(R, "Js")
        end}
)
print(R.Muirgen)
```
{% endcode %}


================================================
FILE: doc/steps/splitstrings.md
================================================
---
description: This Step splits Strings to a specific or random length
---

# SplitStrings

### Settings

| Name                      | type   | description                                                                                                                                                                            | Values                      |
| ------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| Threshold                  | number | The relative amount of nodes that will be affected                                                                                                                                     | 0 <= x <= 1                 |
| MinLength                 | number | The minimal length for the chunks in that the Strings are splitted                                                                                                                     | x > 0                       |
| MaxLength                 | number | The maximal length for the chunks in that the Strings are splitted                                                                                                                     | x >= MinLength              |
| ConcatenationType         | enum   | The Functions used for Concatenation. Note that when using custom, the String Array will also be Shuffled                                                                              | "strcat", "table", "custom" |
| CustomFunctionType        | enum   | <p>The Type of Function code injection This Option only applies when custom Concatenation is selected.<br>Note that when choosing inline, the code size may increase significantly!</p> | "global", "local", "inline" |
| CustomLocalFunctionsCount | number | The number of local functions per scope. This option only applies when CustomFunctionType = local                                                                                      | x > 0                       |

### Example

{% code title="in.lua" %}
```lua
print("Hello, World!")
```
{% endcode %}

{% code title="out.lua" %}
```lua
-- MinLength = 1
-- MaxLength = 1
local f = function(f)
    local k, C = f[#f], ""
    for j = 1, #k, 1 do
        C = C .. k[f[j]]
    end
    return C
end
print(f({13, 11, 4, 12, 1, 6, 8, 10, 9, 7, 3, 2, 5, {"o", "d", "l", "l", "!", ",", "r", " ", "o", "W", "e", "l", "H"}}))

```
{% endcode %}


================================================
FILE: doc/steps/vmify.md
================================================
---
description: This Step will Compile your script and run it within a VM.
---

# Vmify

### Settings

None


================================================
FILE: doc/steps/wrapinfunction.md
================================================
---
description: This Step Wraps the Entire Script into a Function
---

# WrapInFunction

### Settings

| Name       | type   | description              |
| ---------- | ------ | ------------------------ |
| Iterations | number | The Number Of Iterations |

### Example

{% code title="in.lua" %}
```lua
print("Hello, World!")
```
{% endcode %}

{% code title="out.lua" %}
```lua
-- Iterations = 1
return (function()
    print("Hello, World!")
end)()

```
{% endcode %}


================================================
FILE: prometheus-main.lua
================================================
require("cli")

================================================
FILE: readme.md
================================================
# :fire: Prometheus Lua Obfuscator
[![Test](https://github.com/prometheus-lua/Prometheus/actions/workflows/Test.yml/badge.svg)](https://github.com/prometheus-lua/Prometheus/actions/workflows/Test.yml)

Prometheus is a Lua obfuscator written in pure Lua.
It uses several AST-based transformations including Control-Flow Flattening, Constant Encryption and more.

This project was inspired by the amazing [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator).  
It can currently obfuscate Lua51 and Roblox's LuaU, however LuaU support is not finished yet.

You can find the full Documentation including a getting started guide [here](https://levno-710.gitbook.io/prometheus/).

Prometheus has an official [Discord server](https://discord.gg/U8h4d4Rf64).

<p align="center">
  <img src="assets/readme/obfuscation-preview.gif" alt="Prometheus obfuscation process preview" width="900" />
</p>

## Installation
To install Prometheus, simply clone the GitHub repository using:

```batch
git clone https://github.com/prometheus-lua/Prometheus.git
```

Alternatively you can download the sources [here](https://github.com/prometheus-lua/Prometheus/archive/refs/heads/master.zip).

Prometheus also Requires LuaJIT or Lua51 in order to work. The Lua51 binaries can be downloaded [here](https://sourceforge.net/projects/luabinaries/files/5.1.5/Tools%20Executables/).

## Usage
To quickly obfuscate a script:
```batch
lua ./cli.lua --preset Medium ./your_file.lua
```

### Example output
```lua
-- input.lua
print("Hello, World!");
```

```lua
-- input.obfuscated.lua
return(function(...)local L={"afT6mf1V","/7mJXsuvmE1c/fT3";"tn1ZSn6=","37ghSJM=";"WqermfWAWuuZpb3XX7M=","tqXGSJ3u","XQXpL9x21dxAWJa//p==","SrM=";"3q+5SJM=","/D==";"t7XUt0p=";"mIeOmIx9";"LdgrBfWdWuNABsb+KJxj","SJWJ4dahKsebW7t+KQv=","/cDu3AvP/D==";"Llv7uD==","tJWhFfTE";"TQ43ctIuy9HIop==","mEu93p==";"WJax1sXEXEaxWuxGt6==","t0gPSEp=",...
-- remaining obfuscated output omitted
```

For more advanced use cases see the [Documentation](https://levno-710.gitbook.io/prometheus/).
## Tests
To perform the Prometheus Tests, just run
```batch
lua ./tests.lua [--Linux]
```

## License and Commercial Use

Prometheus is licensed under the Prometheus License, a modified MIT-style license.
You are free to use, modify, and distribute this software, including for commercial purposes, under the following conditions:
 - Any commercial product, wrapper, or service (including SaaS or hosted solutions) that uses or integrates Prometheus must include clear attribution to:
```
Based on Prometheus by Elias Oelschner, https://github.com/prometheus-lua/Prometheus
```
 - The attribution must be visible in the product’s UI, documentation, and public website.
 - The obfuscated output files generated by Prometheus do not need to include any license or copyright notice.
 - Derivative works and public forks must also include a statement in their README noting that they are based on Prometheus.

Full license text: [Prometheus License](https://github.com/levno-710/Prometheus/blob/master/LICENSE)


================================================
FILE: src/cli.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- cli.lua
--
-- This Script contains the Code for the Prometheus CLI.

-- Configure package.path for requiring Prometheus.
local function script_path()
	local str = debug.getinfo(2, "S").source:sub(2)
	return str:match("(.*[/%\\])")
end
package.path = script_path() .. "?.lua;" .. package.path
---@diagnostic disable-next-line: different-requires
local Prometheus = require("prometheus")
Prometheus.Logger.logLevel = Prometheus.Logger.LogLevel.Info

-- Check if the file exists
local function file_exists(file)
	local f = io.open(file, "rb")
	if f then
		f:close()
	end
	return f ~= nil
end

string.split = function(str, sep)
	local fields = {}
	local pattern = string.format("([^%s]+)", sep)
	str:gsub(pattern, function(c)
		fields[#fields + 1] = c
	end)
	return fields
end

-- get all lines from a file, returns an empty
-- list/table if the file does not exist
local function lines_from(file)
	if not file_exists(file) then
		return {}
	end
	local lines = {}
	for line in io.lines(file) do
		lines[#lines + 1] = line
	end
	return lines
end

local function load_chunk(content, chunkName, environment)
	if type(loadstring) == "function" then
		local func, err = loadstring(content, chunkName)
		if not func then
			return nil, err
		end
		if environment and type(setfenv) == "function" then
			setfenv(func, environment)
		elseif environment and type(load) == "function" then
			return load(content, chunkName, "t", environment)
		end
		return func
	end

	if type(load) ~= "function" then
		return nil, "No load function available"
	end

	return load(content, chunkName, "t", environment)
end

-- CLI
local config, sourceFile, outFile, luaVersion, prettyPrint

Prometheus.colors.enabled = true

-- Parse Arguments
local i = 1
while i <= #arg do
	local curr = arg[i]
	if curr:sub(1, 2) == "--" then
		if curr == "--preset" or curr == "--p" then
			if config then
				Prometheus.Logger:warn("The config was set multiple times")
			end

			i = i + 1
			local preset = Prometheus.Presets[arg[i]]
			if not preset then
				Prometheus.Logger:error(string.format('A Preset with the name "%s" was not found!', tostring(arg[i])))
			end

			config = preset
		elseif curr == "--config" or curr == "--c" then
			i = i + 1
			local filename = tostring(arg[i])
			if not file_exists(filename) then
				Prometheus.Logger:error(string.format('The config file "%s" was not found!', filename))
			end

			local content = table.concat(lines_from(filename), "\n")
			-- Load Config from File
			local func, err = load_chunk(content, "@" .. filename, {})
			if not func then
				Prometheus.Logger:error(string.format('Failed to parse config file "%s": %s', filename, tostring(err)))
			end
			config = func()
		elseif curr == "--out" or curr == "--o" then
			i = i + 1
			if outFile then
				Prometheus.Logger:warn("The output file was specified multiple times!")
			end
			outFile = arg[i]
		elseif curr == "--nocolors" then
			Prometheus.colors.enabled = false
		elseif curr == "--Lua51" then
			luaVersion = "Lua51"
		elseif curr == "--LuaU" then
			luaVersion = "LuaU"
		elseif curr == "--pretty" then
			prettyPrint = true
		elseif curr == "--saveerrors" then
			-- Override error callback
			Prometheus.Logger.errorCallback = function(...)
				print(Prometheus.colors(Prometheus.Config.NameUpper .. ": " .. ..., "red"))

				local args = { ... }
				local message = table.concat(args, " ")

				local fileName = sourceFile:sub(-4) == ".lua" and sourceFile:sub(0, -5) .. ".error.txt"
					or sourceFile .. ".error.txt"
				local handle = io.open(fileName, "w")
				handle:write(message)
				handle:close()

				os.exit(1)
			end
		else
			Prometheus.Logger:warn(string.format('The option "%s" is not valid and therefore ignored', curr))
		end
	else
		if sourceFile then
			Prometheus.Logger:error(string.format('Unexpected argument "%s"', arg[i]))
		end
		sourceFile = tostring(arg[i])
	end
	i = i + 1
end

if not sourceFile then
	Prometheus.Logger:error("No input file was specified!")
end

if not config then
	Prometheus.Logger:warn("No config was specified, falling back to Minify preset")
	config = Prometheus.Presets.Minify
end

-- Add Option to override Lua Version
config.LuaVersion = luaVersion or config.LuaVersion
config.PrettyPrint = prettyPrint ~= nil and prettyPrint or config.PrettyPrint

if not file_exists(sourceFile) then
	Prometheus.Logger:error(string.format('The File "%s" was not found!', sourceFile))
end

if not outFile then
	if sourceFile:sub(-4) == ".lua" then
		outFile = sourceFile:sub(0, -5) .. ".obfuscated.lua"
	else
		outFile = sourceFile .. ".obfuscated.lua"
	end
end

local source = table.concat(lines_from(sourceFile), "\n")
local pipeline = Prometheus.Pipeline:fromConfig(config)
local out = pipeline:apply(source, sourceFile)
Prometheus.Logger:info(string.format('Writing output to "%s"', outFile))

-- Write Output
local handle = io.open(outFile, "w")
handle:write(out)
handle:close()


================================================
FILE: src/colors.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- colors.lua
--
-- This Script provides a simple method for syntax highlighting of Lua code

local keys = {
	reset = 0,
	bright = 1,
	dim = 2,
	underline = 4,
	blink = 5,
	reverse = 7,
	hidden = 8,
	black = 30,
	pink = 91,
	red = 31,
	green = 32,
	yellow = 33,
	blue = 34,
	magenta = 35,
	cyan = 36,
	grey = 37,
	gray = 37,
	white = 97,
	blackbg = 40,
	redbg = 41,
	greenbg = 42,
	yellowbg = 43,
	bluebg = 44,
	magentabg = 45,
	cyanbg = 46,
	greybg = 47,
	graybg = 47,
	whitebg = 107,
}

local escapeString = string.char(27) .. "[%dm"
local function escapeNumber(number)
	return escapeString:format(number)
end

local settings = {
	enabled = true,
}

local function colors(str, ...)
	if not settings.enabled then
		return str
	end
	str = tostring(str or "")

	local escapes = {}
	for _, name in ipairs({ ... }) do
		table.insert(escapes, escapeNumber(keys[name]))
	end

	return escapeNumber(keys.reset) .. table.concat(escapes) .. str .. escapeNumber(keys.reset)
end

return setmetatable(settings, {
	__call = function(_, ...)
		return colors(...)
	end,
})


================================================
FILE: src/highlightlua.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- highlightlua.lua
--
-- This Script provides a simple Method for Syntax Highlighting of Lua code

local Tokenizer = require("prometheus.tokenizer");
local colors = require("colors");
local TokenKind = Tokenizer.TokenKind;
local lookupify = require("prometheus.util").lookupify;

return function(code, luaVersion)
    local out = "";
    local tokenizer = Tokenizer:new({
        LuaVersion = luaVersion,
    });

    tokenizer:append(code);
    local tokens = tokenizer:scanAll();

    local nonColorSymbols = lookupify{
        ",", ";", "(", ")", "{", "}", ".", ":", "[", "]"
    }

    local defaultGlobals = lookupify{
        "string", "table", "bit32", "bit"
    }

    local currentPos = 1;
    for _, token in ipairs(tokens) do
        if token.startPos >= currentPos then
            out = out .. string.sub(code, currentPos, token.startPos);
        end
        if token.kind == TokenKind.Ident then
            if defaultGlobals[token.source] then
                out = out .. colors(token.source, "red");
            else
                out = out .. token.source;
            end
        elseif token.kind == TokenKind.Keyword then
            if token.source == "nil" then
                out = out .. colors(token.source, "yellow");
            else
                out = out .. colors(token.source, "yellow");
            end
        elseif token.kind == TokenKind.Symbol then
            if nonColorSymbols[token.source] then
                out = out .. token.source;
            else
                out = out .. colors(token.source, "yellow");
            end
        elseif token.kind == TokenKind.String then
            out = out .. colors(token.source, "green")
        elseif token.kind == TokenKind.Number then
            out = out .. colors(token.source, "red")
        else
            out = out .. token.source;
        end

        currentPos = token.endPos + 1;
    end
    return out;
end

================================================
FILE: src/logger.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- logger.lua
--
-- This Script provides a Logger for Prometheus.

local logger = {}
local config = require("config");
local colors = require("colors");

logger.LogLevel = {
	Error = 0,
	Warn = 1,
	Log = 2,
	Info = 2,
	Debug = 3,
}

logger.logLevel = logger.LogLevel.Log;

logger.debugCallback = function(...)
	print(colors(config.NameUpper .. ": " ..  ..., "grey"));
end;
function logger:debug(...)
	if self.logLevel >= self.LogLevel.Debug then
		self.debugCallback(...);
	end
end

logger.logCallback = function(...)
	print(colors(config.NameUpper .. ": ", "magenta") .. ...);
end;
function logger:log(...)
	if self.logLevel >= self.LogLevel.Log then
		self.logCallback(...);
	end
end

function logger:info(...)
	if self.logLevel >= self.LogLevel.Log then
		self.logCallback(...);
	end
end

logger.warnCallback = function(...)
	print(colors(config.NameUpper .. ": " .. ..., "yellow"));
end;
function logger:warn(...)
	if self.logLevel >= self.LogLevel.Warn then
		self.warnCallback(...);
	end
end

logger.errorCallback = function(...)
	print(colors(config.NameUpper .. ": " .. ..., "red"))
	error(...);
end;
function logger:error(...)
	self.errorCallback(...);
	error(config.NameUpper .. ": logger.errorCallback did not throw an Error!");
end


return logger;

================================================
FILE: src/presets.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- presets.lua
--
-- This Script provides the predefined obfuscation presets for Prometheus

return {
	-- Minifies your code. Does not obfuscate it. No performance loss.
	["Minify"] = {
		LuaVersion = "Lua51",
		VarNamePrefix = "",
		NameGenerator = "MangledShuffled",
		PrettyPrint = false,
		Seed = 0,
		Steps = {},
	},

	-- Weak obfuscation. Very readable, low performance loss.
	["Weak"] = {
		LuaVersion = "Lua51",
		VarNamePrefix = "",
		NameGenerator = "MangledShuffled",
		PrettyPrint = false,
		Seed = 0,
		Steps = {
			{ Name = "Vmify", Settings = {} },
			{
				Name = "ConstantArray",
				Settings = {
					Threshold = 1,
					StringsOnly = true
				},
			},
			{ Name = "WrapInFunction", Settings = {} },
		},
	},

	-- This is here for the tests.lua file.
	-- It helps isolate any problems with the Vmify step.
	-- It is not recommended to use this preset for obfuscation.
	-- Use the Weak, Medium, or Strong for obfuscation instead.
	["Vmify"] = {
		LuaVersion = "Lua51",
		VarNamePrefix = "",
		NameGenerator = "MangledShuffled",
		PrettyPrint = false,
		Seed = 0,
		Steps = {
			{ Name = "Vmify", Settings = {} },
		},
	},

	-- Medium obfuscation. Moderate obfuscation, moderate performance loss.
	["Medium"] = {
		LuaVersion = "Lua51",
		VarNamePrefix = "",
		NameGenerator = "MangledShuffled",
		PrettyPrint = false,
		Seed = 0,
		Steps = {
			{ Name = "EncryptStrings", Settings = {} },
			{
				Name = "AntiTamper",
				Settings = {
					UseDebug = false,
				},
			},
			{ Name = "Vmify", Settings = {} },
			{
				Name = "ConstantArray",
				Settings = {
					Threshold = 1,
					StringsOnly = true,
					Shuffle = true,
					Rotate = true,
					LocalWrapperThreshold = 0,
				},
			},
			{ Name = "NumbersToExpressions", Settings = {} },
			{ Name = "WrapInFunction", Settings = {} },
		},
	},

	-- Strong obfuscation, high performance loss.
	["Strong"] = {
		LuaVersion = "Lua51",
		VarNamePrefix = "",
		NameGenerator = "MangledShuffled",
		PrettyPrint = false,
		Seed = 0,
		Steps = {
			{ Name = "Vmify", Settings = {} },
			{ Name = "EncryptStrings", Settings = {} },
			{
				Name = "AntiTamper",
				Settings = {
					UseDebug = false,
				},
			},
			{ Name = "Vmify", Settings = {} },
			{
				Name = "ConstantArray",
				Settings = {
					Threshold = 1,
					StringsOnly = true,
					Shuffle = true,
					Rotate = true,
					LocalWrapperThreshold = 0
				},
			},
			{
				Name = "NumbersToExpressions",
				Settings = {
					NumberRepresentationMutaton = true
				},
			},
			{ Name = "WrapInFunction", Settings = {} },
		},
	},
}


================================================
FILE: src/prometheus/ast.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- ast.lua
--
-- This Script provides the Abstract Syntax Tree (AST) for Prometheus.

local Ast = {}

local AstKind = {
	-- Misc
	TopNode = "TopNode";
	Block = "Block";

	-- Statements
	ContinueStatement = "ContinueStatement";
	BreakStatement = "BreakStatement";
	DoStatement = "DoStatement";
	WhileStatement = "WhileStatement";
	ReturnStatement = "ReturnStatement";
	RepeatStatement = "RepeatStatement";
	ForInStatement = "ForInStatement";
	ForStatement = "ForStatement";
	IfStatement = "IfStatement";
	FunctionDeclaration = "FunctionDeclaration";
	LocalFunctionDeclaration = "LocalFunctionDeclaration";
	LocalVariableDeclaration = "LocalVariableDeclaration";
	FunctionCallStatement = "FunctionCallStatement";
	PassSelfFunctionCallStatement = "PassSelfFunctionCallStatement";
	AssignmentStatement = "AssignmentStatement";

	-- LuaU Compound Statements
	CompoundAddStatement = "CompoundAddStatement";
	CompoundSubStatement = "CompoundSubStatement";
	CompoundMulStatement = "CompoundMulStatement";
	CompoundDivStatement = "CompoundDivStatement";
	CompoundModStatement = "CompoundModStatement";
	CompoundPowStatement = "CompoundPowStatement";
	CompoundConcatStatement = "CompoundConcatStatement";

	-- Assignment Index
	AssignmentIndexing = "AssignmentIndexing";
	AssignmentVariable = "AssignmentVariable";

	-- Expression Nodes
	BooleanExpression = "BooleanExpression";
	NumberExpression = "NumberExpression";
	StringExpression = "StringExpression";
	NilExpression = "NilExpression";
	VarargExpression = "VarargExpression";
	OrExpression = "OrExpression";
	AndExpression = "AndExpression";
	LessThanExpression = "LessThanExpression";
	GreaterThanExpression = "GreaterThanExpression";
	LessThanOrEqualsExpression = "LessThanOrEqualsExpression";
	GreaterThanOrEqualsExpression = "GreaterThanOrEqualsExpression";
	NotEqualsExpression = "NotEqualsExpression";
	EqualsExpression = "EqualsExpression";
	StrCatExpression = "StrCatExpression";
	AddExpression = "AddExpression";
	SubExpression = "SubExpression";
	MulExpression = "MulExpression";
	DivExpression = "DivExpression";
	ModExpression = "ModExpression";
	NotExpression = "NotExpression";
	LenExpression = "LenExpression";
	NegateExpression = "NegateExpression";
	PowExpression = "PowExpression";
	IndexExpression = "IndexExpression";
	FunctionCallExpression = "FunctionCallExpression";
	PassSelfFunctionCallExpression = "PassSelfFunctionCallExpression";
	VariableExpression = "VariableExpression";
	FunctionLiteralExpression = "FunctionLiteralExpression";
	TableConstructorExpression = "TableConstructorExpression";

	-- Table Entry
	TableEntry = "TableEntry";
	KeyedTableEntry = "KeyedTableEntry";

	-- Misc
	NopStatement = "NopStatement";

	IfElseExpression = "IfElseExpression";
}

local astKindExpressionLookup = {
	[AstKind.BooleanExpression] = 0;
	[AstKind.NumberExpression] = 0;
	[AstKind.StringExpression] = 0;
	[AstKind.NilExpression] = 0;
	[AstKind.VarargExpression] = 0;
	[AstKind.OrExpression] = 12;
	[AstKind.AndExpression] = 11;
	[AstKind.LessThanExpression] = 10;
	[AstKind.GreaterThanExpression] = 10;
	[AstKind.LessThanOrEqualsExpression] = 10;
	[AstKind.GreaterThanOrEqualsExpression] = 10;
	[AstKind.NotEqualsExpression] = 10;
	[AstKind.EqualsExpression] = 10;
	[AstKind.StrCatExpression] = 9;
	[AstKind.AddExpression] = 8;
	[AstKind.SubExpression] = 8;
	[AstKind.MulExpression] = 7;
	[AstKind.DivExpression] = 7;
	[AstKind.ModExpression] = 7;
	[AstKind.NotExpression] = 5;
	[AstKind.LenExpression] = 5;
	[AstKind.NegateExpression] = 5;
	[AstKind.PowExpression] = 4;
	[AstKind.IndexExpression] = 1;
	[AstKind.AssignmentIndexing] = 1;
	[AstKind.FunctionCallExpression] = 2;
	[AstKind.PassSelfFunctionCallExpression] = 2;
	[AstKind.VariableExpression] = 0;
	[AstKind.AssignmentVariable] = 0;
	[AstKind.FunctionLiteralExpression] = 3;
	[AstKind.TableConstructorExpression] = 3;
}

Ast.AstKind = AstKind;

function Ast.astKindExpressionToNumber(kind)
	return astKindExpressionLookup[kind] or 100;
end

function Ast.ConstantNode(val)
	if type(val) == "nil" then
		return Ast.NilExpression();
	end

	if type(val) == "string" then
		return Ast.StringExpression(val);
	end

	if type(val) == "number" then
		return Ast.NumberExpression(val);
	end

	if type(val) == "boolean" then
		return Ast.BooleanExpression(val);
	end
end



function Ast.NopStatement()
	return {
		kind = AstKind.NopStatement;
	}
end

function Ast.IfElseExpression(condition, true_value, false_value)
	return {
		kind = AstKind.IfElseExpression,
		condition = condition,
		true_value = true_value,
		false_value = false_value
	}
end

-- Create Ast Top Node
function Ast.TopNode(body, globalScope)
	return {
		kind = AstKind.TopNode,
		body = body,
		globalScope = globalScope,

	}
end

function Ast.TableEntry(value)
	return {
		kind = AstKind.TableEntry,
		value = value,

	}
end

function Ast.KeyedTableEntry(key, value)
	return {
		kind = AstKind.KeyedTableEntry,
		key = key,
		value = value,

	}
end

function Ast.TableConstructorExpression(entries)
	return {
		kind = AstKind.TableConstructorExpression,
		entries = entries,
	};
end

-- Create Statement Block
function Ast.Block(statements, scope)
	return {
		kind = AstKind.Block,
		statements = statements,
		scope = scope,
	}
end

-- Create Break Statement
function Ast.BreakStatement(loop, scope)
	return {
		kind = AstKind.BreakStatement,
		loop = loop,
		scope = scope,
	}
end

-- Create Continue Statement
function Ast.ContinueStatement(loop, scope)
	return {
		kind = AstKind.ContinueStatement,
		loop = loop,
		scope = scope,
	}
end

function Ast.PassSelfFunctionCallStatement(base, passSelfFunctionName, args)
	return {
		kind = AstKind.PassSelfFunctionCallStatement,
		base = base,
		passSelfFunctionName = passSelfFunctionName,
		args = args,
	}
end

function Ast.AssignmentStatement(lhs, rhs)
	if(#lhs < 1) then
		print(debug.traceback());
		error("Something went wrong!");
	end
	return {
		kind = AstKind.AssignmentStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.CompoundAddStatement(lhs, rhs)
	return {
		kind = AstKind.CompoundAddStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.CompoundSubStatement(lhs, rhs)
	return {
		kind = AstKind.CompoundSubStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.CompoundMulStatement(lhs, rhs)
	return {
		kind = AstKind.CompoundMulStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.CompoundDivStatement(lhs, rhs)
	return {
		kind = AstKind.CompoundDivStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.CompoundPowStatement(lhs, rhs)
	return {
		kind = AstKind.CompoundPowStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.CompoundModStatement(lhs, rhs)
	return {
		kind = AstKind.CompoundModStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.CompoundConcatStatement(lhs, rhs)
	return {
		kind = AstKind.CompoundConcatStatement,
		lhs = lhs,
		rhs = rhs,
	}
end

function Ast.FunctionCallStatement(base, args)
	return {
		kind = AstKind.FunctionCallStatement,
		base = base,
		args = args,
	}
end

function Ast.ReturnStatement(args)
	return {
		kind = AstKind.ReturnStatement,
		args = args,
	}
end

function Ast.DoStatement(body)
	return {
		kind = AstKind.DoStatement,
		body = body,
	}
end

function Ast.WhileStatement(body, condition, parentScope)
	return {
		kind = AstKind.WhileStatement,
		body = body,
		condition = condition,
		parentScope = parentScope,
	}
end

function Ast.ForInStatement(scope, vars, expressions, body, parentScope)
	return {
		kind = AstKind.ForInStatement,
		scope = scope,
		ids = vars,
		vars = vars,
		expressions = expressions,
		body = body,
		parentScope = parentScope,
	}
end

function Ast.ForStatement(scope, id, initialValue, finalValue, incrementBy, body, parentScope)
	return {
		kind = AstKind.ForStatement,
		scope = scope,
		id = id,
		initialValue = initialValue,
		finalValue = finalValue,
		incrementBy = incrementBy,
		body = body,
		parentScope = parentScope,
	}
end

function Ast.RepeatStatement(condition, body, parentScope)
	return {
		kind = AstKind.RepeatStatement,
		body = body,
		condition = condition,
		parentScope = parentScope,
	}
end

function Ast.IfStatement(condition, body, elseifs, elsebody)
	return {
		kind = AstKind.IfStatement,
		condition = condition,
		body = body,
		elseifs = elseifs,
		elsebody = elsebody,
	}
end

function Ast.FunctionDeclaration(scope, id, indices, args, body)
	return {
		kind = AstKind.FunctionDeclaration,
		scope = scope,
		baseScope = scope,
		id = id,
		baseId = id,
		indices = indices,
		args = args,
		body = body,
		getName = function(self)
			return self.scope:getVariableName(self.id);
		end,
	}
end

function Ast.LocalFunctionDeclaration(scope, id, args, body)
	return {
		kind = AstKind.LocalFunctionDeclaration,
		scope = scope,
		id = id,
		args = args,
		body = body,
		getName = function(self)
			return self.scope:getVariableName(self.id);
		end,
	}
end

function Ast.LocalVariableDeclaration(scope, ids, expressions)
	return {
		kind = AstKind.LocalVariableDeclaration,
		scope = scope,
		ids = ids,
		expressions = expressions,
	}
end

function Ast.VarargExpression()
	return {
		kind = AstKind.VarargExpression;
		isConstant = false,
	}
end

function Ast.BooleanExpression(value)
	return {
		kind = AstKind.BooleanExpression,
		isConstant = true,
		value = value,
	}
end

function Ast.NilExpression()
	return {
		kind = AstKind.NilExpression,
		isConstant = true,
		value = nil,
	}
end

function Ast.NumberExpression(value)
	return {
		kind = AstKind.NumberExpression,
		isConstant = true,
		value = value,
	}
end

function Ast.StringExpression(value)
	return {
		kind = AstKind.StringExpression,
		isConstant = true,
		value = value,
	}
end

function Ast.OrExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value or rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.OrExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.AndExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value and rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.AndExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.LessThanExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value < rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.LessThanExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.GreaterThanExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value > rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.GreaterThanExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.LessThanOrEqualsExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value <= rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.LessThanOrEqualsExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.GreaterThanOrEqualsExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value >= rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.GreaterThanOrEqualsExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.NotEqualsExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value ~= rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.NotEqualsExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.EqualsExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value == rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.EqualsExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.StrCatExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value .. rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.StrCatExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.AddExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value + rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.AddExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.SubExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value - rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.SubExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.MulExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value * rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.MulExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.DivExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant and rhs.value ~= 0) then
		local success, val = pcall(function() return lhs.value / rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.DivExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.ModExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value % rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.ModExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.NotExpression(rhs, simplify)
	if(simplify and rhs.isConstant) then
		local success, val = pcall(function() return not rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.NotExpression,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.NegateExpression(rhs, simplify)
	if(simplify and rhs.isConstant) then
		local success, val = pcall(function() return -rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.NegateExpression,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.LenExpression(rhs, simplify)
	if(simplify and rhs.isConstant) then
		local success, val = pcall(function() return #rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.LenExpression,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.PowExpression(lhs, rhs, simplify)
	if(simplify and rhs.isConstant and lhs.isConstant) then
		local success, val = pcall(function() return lhs.value ^ rhs.value end);
		if success then
			return Ast.ConstantNode(val);
		end
	end

	return {
		kind = AstKind.PowExpression,
		lhs = lhs,
		rhs = rhs,
		isConstant = false,
	}
end

function Ast.IndexExpression(base, index)
	return {
		kind = AstKind.IndexExpression,
		base = base,
		index = index,
		isConstant = false,
	}
end

function Ast.AssignmentIndexing(base, index)
	return {
		kind = AstKind.AssignmentIndexing,
		base = base,
		index = index,
		isConstant = false,
	}
end

function Ast.PassSelfFunctionCallExpression(base, passSelfFunctionName, args)
	return {
		kind = AstKind.PassSelfFunctionCallExpression,
		base = base,
		passSelfFunctionName = passSelfFunctionName,
		args = args,

	}
end

function Ast.FunctionCallExpression(base, args)
	return {
		kind = AstKind.FunctionCallExpression,
		base = base,
		args = args,
	}
end

function Ast.VariableExpression(scope, id)
	scope:addReference(id);
	return {
		kind = AstKind.VariableExpression,
		scope = scope,
		id = id,
		getName = function(self)
			return self.scope.getVariableName(self.id);
		end,
	}
end

function Ast.AssignmentVariable(scope, id)
	scope:addReference(id);
	return {
		kind = AstKind.AssignmentVariable,
		scope = scope,
		id = id,
		getName = function(self)
			return self.scope.getVariableName(self.id);
		end,
	}
end

function Ast.FunctionLiteralExpression(args, body)
	return {
		kind = AstKind.FunctionLiteralExpression,
		args = args,
		body = body,
	}
end



return Ast;


================================================
FILE: src/prometheus/compiler/block.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- block.lua
--
-- Block management for the compiler

local Scope = require("prometheus.scope");
local util = require("prometheus.util");

local lookupify = util.lookupify;

return function(Compiler)
    function Compiler:createBlock()
        local id;
        repeat
            id = math.random(0, 2^24)
        until not self.usedBlockIds[id];
        self.usedBlockIds[id] = true;

        local scope = Scope:new(self.containerFuncScope);
        local block = {
            id = id;
            statements = {};
            scope = scope;
            advanceToNextBlock = true;
        };
        table.insert(self.blocks, block);
        return block;
    end

    function Compiler:setActiveBlock(block)
        self.activeBlock = block;
    end

    function Compiler:addStatement(statement, writes, reads, usesUpvals)
        if(self.activeBlock.advanceToNextBlock) then
            table.insert(self.activeBlock.statements, {
                statement = statement,
                writes = lookupify(writes),
                reads = lookupify(reads),
                usesUpvals = usesUpvals or false,
            });
        end
    end
end



================================================
FILE: src/prometheus/compiler/compile_core.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- compile_core.lua
-- This Script contains the core compilation functions: compileTopNode, compileFunction, compileBlock,
-- compileStatement, and compileExpression

local compileTop = require("prometheus.compiler.compile_top");
local statementHandlers = require("prometheus.compiler.statements");
local expressionHandlers = require("prometheus.compiler.expressions");
local Ast = require("prometheus.ast");
local logger = require("logger");

return function(Compiler)
    compileTop(Compiler);

    function Compiler:compileStatement(statement, funcDepth)
        local handler = statementHandlers[statement.kind];
        if handler then
            handler(self, statement, funcDepth);
            return;
        end
        logger:error(string.format("%s is not a compileable statement!", statement.kind));
    end

    function Compiler:compileExpression(expression, funcDepth, numReturns)
        local handler = expressionHandlers[expression.kind];
        if handler then
            return handler(self, expression, funcDepth, numReturns);
        end
        logger:error(string.format("%s is not an compliable expression!", expression.kind));
    end
end


================================================
FILE: src/prometheus/compiler/compile_top.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- compile_top.lua
--
-- This Script contains the compilation of the top node, function, and block.

local Ast = require("prometheus.ast");
local util = require("prometheus.util");
local visitast = require("prometheus.visitast");

local lookupify = util.lookupify;
local AstKind = Ast.AstKind;

return function(Compiler)
    function Compiler:compileTopNode(node)
        local startBlock = self:createBlock();
        local scope = startBlock.scope;
        self.startBlockId = startBlock.id;
        self:setActiveBlock(startBlock);

        local varAccessLookup = lookupify{
            AstKind.AssignmentVariable,
            AstKind.VariableExpression,
            AstKind.FunctionDeclaration,
            AstKind.LocalFunctionDeclaration,
        }

        local functionLookup = lookupify{
            AstKind.FunctionDeclaration,
            AstKind.LocalFunctionDeclaration,
            AstKind.FunctionLiteralExpression,
            AstKind.TopNode,
        }
        visitast(node, function(node, data)
            if node.kind == AstKind.Block then
                node.scope.__depth = data.functionData.depth;
            end

            if varAccessLookup[node.kind] then
                if not node.scope.isGlobal then
                    if node.scope.__depth < data.functionData.depth then
                        if not self:isUpvalue(node.scope, node.id) then
                            self:makeUpvalue(node.scope, node.id);
                        end
                    end
                end
            end
        end, nil, nil)

        self.varargReg = self:allocRegister(true);
        scope:addReferenceToHigherScope(self.containerFuncScope, self.argsVar);
        scope:addReferenceToHigherScope(self.scope, self.selectVar);
        scope:addReferenceToHigherScope(self.scope, self.unpackVar);
        self:addStatement(self:setRegister(scope, self.varargReg, Ast.VariableExpression(self.containerFuncScope, self.argsVar)), {self.varargReg}, {}, false);

        self:compileBlock(node.body, 0);
        if(self.activeBlock.advanceToNextBlock) then
            self:addStatement(self:setPos(self.activeBlock.scope, nil), {self.POS_REGISTER}, {}, false);
            self:addStatement(self:setReturn(self.activeBlock.scope, Ast.TableConstructorExpression({})), {self.RETURN_REGISTER}, {}, false)
            self.activeBlock.advanceToNextBlock = false;
        end

        self:resetRegisters();
    end

    function Compiler:compileFunction(node, funcDepth)
        funcDepth = funcDepth + 1;
        local oldActiveBlock = self.activeBlock;

        local upperVarargReg = self.varargReg;
        self.varargReg = nil;

        local upvalueExpressions = {};
        local upvalueIds = {};
        local usedRegs = {};

        local oldGetUpvalueId = self.getUpvalueId;
        self.getUpvalueId = function(self, scope, id)
            if(not upvalueIds[scope]) then
                upvalueIds[scope] = {};
            end
            if(upvalueIds[scope][id]) then
                return upvalueIds[scope][id];
            end
            local scopeFuncDepth = self.scopeFunctionDepths[scope];
            local expression;
            if(scopeFuncDepth == funcDepth) then
                oldActiveBlock.scope:addReferenceToHigherScope(self.scope, self.allocUpvalFunction);
                expression = Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {});
            elseif(scopeFuncDepth == funcDepth - 1) then
                local varReg = self:getVarRegister(scope, id, scopeFuncDepth, nil);
                expression = self:register(oldActiveBlock.scope, varReg);
                table.insert(usedRegs, varReg);
            else
                local higherId = oldGetUpvalueId(self, scope, id);
                oldActiveBlock.scope:addReferenceToHigherScope(self.containerFuncScope, self.currentUpvaluesVar);
                expression = Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.currentUpvaluesVar), Ast.NumberExpression(higherId));
            end
            table.insert(upvalueExpressions, Ast.TableEntry(expression));
            local uid = #upvalueExpressions;
            upvalueIds[scope][id] = uid;
            return uid;
        end

        local block = self:createBlock();
        self:setActiveBlock(block);
        local scope = self.activeBlock.scope;
        self:pushRegisterUsageInfo();
        for i, arg in ipairs(node.args) do
            if(arg.kind == AstKind.VariableExpression) then
                if(self:isUpvalue(arg.scope, arg.id)) then
                    scope:addReferenceToHigherScope(self.scope, self.allocUpvalFunction);
                    local argReg = self:getVarRegister(arg.scope, arg.id, funcDepth, nil);
                    self:addStatement(self:setRegister(scope, argReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {})), {argReg}, {}, false);
                    self:addStatement(self:setUpvalueMember(scope, self:register(scope, argReg), Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.argsVar), Ast.NumberExpression(i))), {}, {argReg}, true);
                else
                    local argReg = self:getVarRegister(arg.scope, arg.id, funcDepth, nil);
                    scope:addReferenceToHigherScope(self.containerFuncScope, self.argsVar);
                    self:addStatement(self:setRegister(scope, argReg, Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.argsVar), Ast.NumberExpression(i))), {argReg}, {}, false);
                end
            else
                self.varargReg = self:allocRegister(true);
                scope:addReferenceToHigherScope(self.containerFuncScope, self.argsVar);
                scope:addReferenceToHigherScope(self.scope, self.selectVar);
                scope:addReferenceToHigherScope(self.scope, self.unpackVar);
                self:addStatement(self:setRegister(scope, self.varargReg, Ast.TableConstructorExpression({
                    Ast.TableEntry(Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.selectVar), {
                        Ast.NumberExpression(i);
                        Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.unpackVar), {
                            Ast.VariableExpression(self.containerFuncScope, self.argsVar),
                        });
                    })),
                })), {self.varargReg}, {}, false);
            end
        end

        self:compileBlock(node.body, funcDepth);
        if(self.activeBlock.advanceToNextBlock) then
            self:addStatement(self:setPos(self.activeBlock.scope, nil), {self.POS_REGISTER}, {}, false);
            self:addStatement(self:setReturn(self.activeBlock.scope, Ast.TableConstructorExpression({})), {self.RETURN_REGISTER}, {}, false);
            self.activeBlock.advanceToNextBlock = false;
        end

        if(self.varargReg) then
            self:freeRegister(self.varargReg, true);
        end
        self.varargReg = upperVarargReg;
        self.getUpvalueId = oldGetUpvalueId;

        self:popRegisterUsageInfo();
        self:setActiveBlock(oldActiveBlock);

        local scope = self.activeBlock.scope;

        local retReg = self:allocRegister(false);

        local isVarargFunction = #node.args > 0 and node.args[#node.args].kind == AstKind.VarargExpression;

        local retrieveExpression
        if isVarargFunction then
            scope:addReferenceToHigherScope(self.scope, self.createVarargClosureVar);
            retrieveExpression = Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.createVarargClosureVar), {
                Ast.NumberExpression(block.id),
                Ast.TableConstructorExpression(upvalueExpressions)
            });
        else
            local varScope, var = self:getCreateClosureVar(#node.args + math.random(0, 5));
            scope:addReferenceToHigherScope(varScope, var);
            retrieveExpression = Ast.FunctionCallExpression(Ast.VariableExpression(varScope, var), {
                Ast.NumberExpression(block.id),
                Ast.TableConstructorExpression(upvalueExpressions)
            });
        end

        self:addStatement(self:setRegister(scope, retReg, retrieveExpression), {retReg}, usedRegs, false);
        return retReg;
    end

    function Compiler:compileBlock(block, funcDepth)
        for i, stat in ipairs(block.statements) do
            self:compileStatement(stat, funcDepth);
        end

        local scope = self.activeBlock.scope;
        for id, name in ipairs(block.scope.variables) do
            local varReg = self:getVarRegister(block.scope, id, funcDepth, nil);
            if self:isUpvalue(block.scope, id) then
                scope:addReferenceToHigherScope(self.scope, self.freeUpvalueFunc);
                self:addStatement(self:setRegister(scope, varReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.freeUpvalueFunc), {
                    self:register(scope, varReg)
                })), {varReg}, {varReg}, false);
            else
                self:addStatement(self:setRegister(scope, varReg, Ast.NilExpression()), {varReg}, {}, false);
            end
            self:freeRegister(varReg, true);
        end
    end
end



================================================
FILE: src/prometheus/compiler/compiler.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- compiler.lua
--
-- This Script is the main compiler module.

local Ast = require("prometheus.ast");
local Scope = require("prometheus.scope");
local util = require("prometheus.util");

local lookupify = util.lookupify;
local AstKind = Ast.AstKind;

local unpack = unpack or table.unpack;

local blockModule = require("prometheus.compiler.block");
local registerModule = require("prometheus.compiler.register");
local upvalueModule = require("prometheus.compiler.upvalue");
local emitModule = require("prometheus.compiler.emit");
local compileCoreModule = require("prometheus.compiler.compile_core");

local Compiler = {};

function Compiler:new()
    local compiler = {
        blocks = {};
        registers = {};
        activeBlock = nil;
        registersForVar = {};
        usedRegisters = 0;
        maxUsedRegister = 0;
        registerVars = {};

        VAR_REGISTER = newproxy(false);
        RETURN_ALL = newproxy(false);
        POS_REGISTER = newproxy(false);
        RETURN_REGISTER = newproxy(false);
        UPVALUE = newproxy(false);

        BIN_OPS = lookupify{
            AstKind.LessThanExpression,
            AstKind.GreaterThanExpression,
            AstKind.LessThanOrEqualsExpression,
            AstKind.GreaterThanOrEqualsExpression,
            AstKind.NotEqualsExpression,
            AstKind.EqualsExpression,
            AstKind.StrCatExpression,
            AstKind.AddExpression,
            AstKind.SubExpression,
            AstKind.MulExpression,
            AstKind.DivExpression,
            AstKind.ModExpression,
            AstKind.PowExpression,
        };
    };

    setmetatable(compiler, self);
    self.__index = self;

    return compiler;
end

blockModule(Compiler);
registerModule(Compiler);
upvalueModule(Compiler);
emitModule(Compiler);
compileCoreModule(Compiler);

function Compiler:pushRegisterUsageInfo()
    table.insert(self.registerUsageStack, {
        usedRegisters = self.usedRegisters;
        registers = self.registers;
    });
    self.usedRegisters = 0;
    self.registers = {};
end

function Compiler:popRegisterUsageInfo()
    local info = table.remove(self.registerUsageStack);
    self.usedRegisters = info.usedRegisters;
    self.registers = info.registers;
end

function Compiler:compile(ast)
    self.blocks = {};
    self.registers = {};
    self.activeBlock = nil;
    self.registersForVar = {};
    self.scopeFunctionDepths = {};
    self.maxUsedRegister = 0;
    self.usedRegisters = 0;
    self.registerVars = {};
    self.usedBlockIds = {};

    self.upvalVars = {};
    self.registerUsageStack = {};

    self.upvalsProxyLenReturn = math.random(-2^22, 2^22);

    local newGlobalScope = Scope:newGlobal();
    local psc = Scope:new(newGlobalScope, nil);

    local _, getfenvVar = newGlobalScope:resolve("getfenv");
    local _, tableVar = newGlobalScope:resolve("table");
    local _, unpackVar = newGlobalScope:resolve("unpack");
    local _, envVar = newGlobalScope:resolve("_ENV");
    local _, newproxyVar = newGlobalScope:resolve("newproxy");
    local _, setmetatableVar = newGlobalScope:resolve("setmetatable");
    local _, getmetatableVar = newGlobalScope:resolve("getmetatable");
    local _, selectVar = newGlobalScope:resolve("select");

    psc:addReferenceToHigherScope(newGlobalScope, getfenvVar, 2);
    psc:addReferenceToHigherScope(newGlobalScope, tableVar);
    psc:addReferenceToHigherScope(newGlobalScope, unpackVar);
    psc:addReferenceToHigherScope(newGlobalScope, envVar);
    psc:addReferenceToHigherScope(newGlobalScope, newproxyVar);
    psc:addReferenceToHigherScope(newGlobalScope, setmetatableVar);
    psc:addReferenceToHigherScope(newGlobalScope, getmetatableVar);

    self.scope = Scope:new(psc);
    self.envVar = self.scope:addVariable();
    self.containerFuncVar = self.scope:addVariable();
    self.unpackVar = self.scope:addVariable();
    self.newproxyVar = self.scope:addVariable();
    self.setmetatableVar = self.scope:addVariable();
    self.getmetatableVar = self.scope:addVariable();
    self.selectVar = self.scope:addVariable();

    local argVar = self.scope:addVariable();

    self.containerFuncScope = Scope:new(self.scope);
    self.whileScope = Scope:new(self.containerFuncScope);

    self.posVar = self.containerFuncScope:addVariable();
    self.argsVar = self.containerFuncScope:addVariable();
    self.currentUpvaluesVar = self.containerFuncScope:addVariable();
    self.detectGcCollectVar = self.containerFuncScope:addVariable();
    self.returnVar = self.containerFuncScope:addVariable();

    self.upvaluesTable = self.scope:addVariable();
    self.upvaluesReferenceCountsTable = self.scope:addVariable();
    self.allocUpvalFunction = self.scope:addVariable();
    self.currentUpvalId = self.scope:addVariable();

    self.upvaluesProxyFunctionVar = self.scope:addVariable();
    self.upvaluesGcFunctionVar = self.scope:addVariable();
    self.freeUpvalueFunc = self.scope:addVariable();

    self.createClosureVars = {};
    self.createVarargClosureVar = self.scope:addVariable();
    local createClosureScope = Scope:new(self.scope);
    local createClosurePosArg = createClosureScope:addVariable();
    local createClosureUpvalsArg = createClosureScope:addVariable();
    local createClosureProxyObject = createClosureScope:addVariable();
    local createClosureFuncVar = createClosureScope:addVariable();

    local createClosureSubScope = Scope:new(createClosureScope);

    local upvalEntries = {};
    local upvalueIds = {};
    self.getUpvalueId = function(self, scope, id)
        local expression;
        local scopeFuncDepth = self.scopeFunctionDepths[scope];
        if(scopeFuncDepth == 0) then
            if upvalueIds[id] then
                return upvalueIds[id];
            end
            expression = Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {});
        else
            require("logger"):error("Unresolved Upvalue, this error should not occur!");
        end
        table.insert(upvalEntries, Ast.TableEntry(expression));
        local uid = #upvalEntries;
        upvalueIds[id] = uid;
        return uid;
    end

    createClosureSubScope:addReferenceToHigherScope(self.scope, self.containerFuncVar);
    createClosureSubScope:addReferenceToHigherScope(createClosureScope, createClosurePosArg)
    createClosureSubScope:addReferenceToHigherScope(createClosureScope, createClosureUpvalsArg, 1)
    createClosureScope:addReferenceToHigherScope(self.scope, self.upvaluesProxyFunctionVar)
    createClosureSubScope:addReferenceToHigherScope(createClosureScope, createClosureProxyObject);

    self:compileTopNode(ast);

    local functionNodeAssignments = {
        {
            var = Ast.AssignmentVariable(self.scope, self.containerFuncVar),
            val = Ast.FunctionLiteralExpression({
                Ast.VariableExpression(self.containerFuncScope, self.posVar),
                Ast.VariableExpression(self.containerFuncScope, self.argsVar),
                Ast.VariableExpression(self.containerFuncScope, self.currentUpvaluesVar),
                Ast.VariableExpression(self.containerFuncScope, self.detectGcCollectVar)
            }, self:emitContainerFuncBody());
        }, {
            var = Ast.AssignmentVariable(self.scope, self.createVarargClosureVar),
            val = Ast.FunctionLiteralExpression({
                    Ast.VariableExpression(createClosureScope, createClosurePosArg),
                    Ast.VariableExpression(createClosureScope, createClosureUpvalsArg),
                },
                Ast.Block({
                    Ast.LocalVariableDeclaration(createClosureScope, {
                        createClosureProxyObject
                    }, {
                        Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.upvaluesProxyFunctionVar), {
                            Ast.VariableExpression(createClosureScope, createClosureUpvalsArg)
                        })
                    }),
                    Ast.LocalVariableDeclaration(createClosureScope, {createClosureFuncVar},{
                        Ast.FunctionLiteralExpression({
                            Ast.VarargExpression();
                        },
                        Ast.Block({
                            Ast.ReturnStatement{
                                Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.containerFuncVar), {
                                    Ast.VariableExpression(createClosureScope, createClosurePosArg),
                                    Ast.TableConstructorExpression({Ast.TableEntry(Ast.VarargExpression())}),
                                    Ast.VariableExpression(createClosureScope, createClosureUpvalsArg),
                                    Ast.VariableExpression(createClosureScope, createClosureProxyObject)
                                })
                            }
                        }, createClosureSubScope)
                        );
                    });
                    Ast.ReturnStatement{Ast.VariableExpression(createClosureScope, createClosureFuncVar)};
                }, createClosureScope)
            );
        }, {
            var = Ast.AssignmentVariable(self.scope, self.upvaluesTable),
            val = Ast.TableConstructorExpression({}),
        }, {
            var = Ast.AssignmentVariable(self.scope, self.upvaluesReferenceCountsTable),
            val = Ast.TableConstructorExpression({}),
        }, {
            var = Ast.AssignmentVariable(self.scope, self.allocUpvalFunction),
            val = self:createAllocUpvalFunction(),
        }, {
            var = Ast.AssignmentVariable(self.scope, self.currentUpvalId),
            val = Ast.NumberExpression(0),
        }, {
            var = Ast.AssignmentVariable(self.scope, self.upvaluesProxyFunctionVar),
            val = self:createUpvaluesProxyFunc(),
        }, {
            var = Ast.AssignmentVariable(self.scope, self.upvaluesGcFunctionVar),
            val = self:createUpvaluesGcFunc(),
        }, {
            var = Ast.AssignmentVariable(self.scope, self.freeUpvalueFunc),
            val = self:createFreeUpvalueFunc(),
        },
    }

    local tbl = {
        Ast.VariableExpression(self.scope, self.containerFuncVar),
        Ast.VariableExpression(self.scope, self.createVarargClosureVar),
        Ast.VariableExpression(self.scope, self.upvaluesTable),
        Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable),
        Ast.VariableExpression(self.scope, self.allocUpvalFunction),
        Ast.VariableExpression(self.scope, self.currentUpvalId),
        Ast.VariableExpression(self.scope, self.upvaluesProxyFunctionVar),
        Ast.VariableExpression(self.scope, self.upvaluesGcFunctionVar),
        Ast.VariableExpression(self.scope, self.freeUpvalueFunc),
    };
    for i, entry in pairs(self.createClosureVars) do
        table.insert(functionNodeAssignments, entry);
        table.insert(tbl, Ast.VariableExpression(entry.var.scope, entry.var.id));
    end

    util.shuffle(functionNodeAssignments);
    local assignmentStatLhs, assignmentStatRhs = {}, {};
    for i, v in ipairs(functionNodeAssignments) do
        assignmentStatLhs[i] = v.var;
        assignmentStatRhs[i] = v.val;
    end


    -- NEW: Position Shuffler
    local ids = util.shuffle({1, 2, 3, 4, 5, 6, 7});

    local items = {
        Ast.VariableExpression(self.scope, self.envVar),
        Ast.VariableExpression(self.scope, self.unpackVar),
        Ast.VariableExpression(self.scope, self.newproxyVar),
        Ast.VariableExpression(self.scope, self.setmetatableVar),
        Ast.VariableExpression(self.scope, self.getmetatableVar),
        Ast.VariableExpression(self.scope, self.selectVar),
        Ast.VariableExpression(self.scope, argVar),
    }

    local astItems = {
        Ast.OrExpression(Ast.AndExpression(Ast.VariableExpression(newGlobalScope, getfenvVar), Ast.FunctionCallExpression(Ast.VariableExpression(newGlobalScope, getfenvVar), {})), Ast.VariableExpression(newGlobalScope, envVar));
        Ast.OrExpression(Ast.VariableExpression(newGlobalScope, unpackVar), Ast.IndexExpression(Ast.VariableExpression(newGlobalScope, tableVar), Ast.StringExpression("unpack")));
        Ast.VariableExpression(newGlobalScope, newproxyVar);
        Ast.VariableExpression(newGlobalScope, setmetatableVar);
        Ast.VariableExpression(newGlobalScope, getmetatableVar);
        Ast.VariableExpression(newGlobalScope, selectVar);
        Ast.TableConstructorExpression({
            Ast.TableEntry(Ast.VarargExpression());
        })
    }

    local functionNode = Ast.FunctionLiteralExpression({
      items[ids[1]], items[ids[2]], items[ids[3]], items[ids[4]],
      items[ids[5]], items[ids[6]], items[ids[7]],
      unpack(util.shuffle(tbl))
    }, Ast.Block({
        Ast.AssignmentStatement(assignmentStatLhs, assignmentStatRhs);
        Ast.ReturnStatement{
            Ast.FunctionCallExpression(Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.createVarargClosureVar), {
                    Ast.NumberExpression(self.startBlockId);
                    Ast.TableConstructorExpression(upvalEntries);
                }), {Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.unpackVar), {Ast.VariableExpression(self.scope, argVar)})});
        }
    }, self.scope));

    return Ast.TopNode(Ast.Block({
        Ast.ReturnStatement{Ast.FunctionCallExpression(functionNode, {
            astItems[ids[1]], astItems[ids[2]], astItems[ids[3]], astItems[ids[4]],
            astItems[ids[5]], astItems[ids[6]], astItems[ids[7]],
        })};
    }, psc), newGlobalScope);
end

function Compiler:getCreateClosureVar(argCount)
    if not self.createClosureVars[argCount] then
        local var = Ast.AssignmentVariable(self.scope, self.scope:addVariable());
        local createClosureScope = Scope:new(self.scope);
        local createClosureSubScope = Scope:new(createClosureScope);

        local createClosurePosArg = createClosureScope:addVariable();
        local createClosureUpvalsArg = createClosureScope:addVariable();
        local createClosureProxyObject = createClosureScope:addVariable();
        local createClosureFuncVar = createClosureScope:addVariable();

        createClosureSubScope:addReferenceToHigherScope(self.scope, self.containerFuncVar);
        createClosureSubScope:addReferenceToHigherScope(createClosureScope, createClosurePosArg)
        createClosureSubScope:addReferenceToHigherScope(createClosureScope, createClosureUpvalsArg, 1)
        createClosureScope:addReferenceToHigherScope(self.scope, self.upvaluesProxyFunctionVar)
        createClosureSubScope:addReferenceToHigherScope(createClosureScope, createClosureProxyObject);

        local  argsTb, argsTb2 = {}, {};
        for i = 1, argCount do
            local arg = createClosureSubScope:addVariable()
            argsTb[i] = Ast.VariableExpression(createClosureSubScope, arg);
            argsTb2[i] = Ast.TableEntry(Ast.VariableExpression(createClosureSubScope, arg));
        end

        local val = Ast.FunctionLiteralExpression({
            Ast.VariableExpression(createClosureScope, createClosurePosArg),
            Ast.VariableExpression(createClosureScope, createClosureUpvalsArg),
        }, Ast.Block({
                Ast.LocalVariableDeclaration(createClosureScope, {
                    createClosureProxyObject
                }, {
                    Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.upvaluesProxyFunctionVar), {
                        Ast.VariableExpression(createClosureScope, createClosureUpvalsArg)
                    })
                }),
                Ast.LocalVariableDeclaration(createClosureScope, {createClosureFuncVar},{
                    Ast.FunctionLiteralExpression(argsTb,
                    Ast.Block({
                        Ast.ReturnStatement{
                            Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.containerFuncVar), {
                                Ast.VariableExpression(createClosureScope, createClosurePosArg),
                                Ast.TableConstructorExpression(argsTb2),
                                Ast.VariableExpression(createClosureScope, createClosureUpvalsArg),
                                Ast.VariableExpression(createClosureScope, createClosureProxyObject)
                            })
                        }
                    }, createClosureSubScope)
                    );
                });
                Ast.ReturnStatement{Ast.VariableExpression(createClosureScope, createClosureFuncVar)}
            }, createClosureScope)
        );
        self.createClosureVars[argCount] = {
            var = var,
            val = val,
        }
    end


    local var = self.createClosureVars[argCount].var;
    return var.scope, var.id;
end

return Compiler;


================================================
FILE: src/prometheus/compiler/constants.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- constants.lua
--
-- This Script contains the compiler constants shared across modules.

return {
    MAX_REGS = 100,
    MAX_REGS_MUL = 0,
}



================================================
FILE: src/prometheus/compiler/emit.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- emit.lua
--
-- This Script contains the container function body emission for the compiler.

local Ast = require("prometheus.ast");
local Scope = require("prometheus.scope");
local util = require("prometheus.util");
local constants = require("prometheus.compiler.constants");
local AstKind = Ast.AstKind;

local MAX_REGS = constants.MAX_REGS;

return function(Compiler)
    local function hasAnyEntries(tbl)
        return type(tbl) == "table" and next(tbl) ~= nil;
    end

    local function unionLookupTables(a, b)
        local out = {};
        for k, v in pairs(a or {}) do
            out[k] = v;
        end
        for k, v in pairs(b or {}) do
            out[k] = v;
        end
        return out;
    end

    local function canMergeParallelAssignmentStatements(statA, statB)
        if type(statA) ~= "table" or type(statB) ~= "table" then
            return false;
        end

        if statA.usesUpvals or statB.usesUpvals then
            return false;
        end

        local a = statA.statement;
        local b = statB.statement;
        if type(a) ~= "table" or type(b) ~= "table" then
            return false;
        end
        if a.kind ~= AstKind.AssignmentStatement or b.kind ~= AstKind.AssignmentStatement then
            return false;
        end

        if type(a.lhs) ~= "table" or type(a.rhs) ~= "table" or type(b.lhs) ~= "table" or type(b.rhs) ~= "table" then
            return false;
        end

        if #a.lhs ~= #a.rhs or #b.lhs ~= #b.rhs then
            return false;
        end

        -- Avoid merging vararg/call assignments because they can affect multi-return behavior.
        local function hasUnsafeRhs(rhsList)
            for _, rhsExpr in ipairs(rhsList) do
                if type(rhsExpr) ~= "table" then
                    return true;
                end
                local kind = rhsExpr.kind;
                if kind == AstKind.FunctionCallExpression or kind == AstKind.PassSelfFunctionCallExpression or kind == AstKind.VarargExpression then
                    return true;
                end
            end
            return false;
        end
        if hasUnsafeRhs(a.rhs) or hasUnsafeRhs(b.rhs) then
            return false;
        end

        local aReads = type(statA.reads) == "table" and statA.reads or {};
        local aWrites = type(statA.writes) == "table" and statA.writes or {};
        local bReads = type(statB.reads) == "table" and statB.reads or {};
        local bWrites = type(statB.writes) == "table" and statB.writes or {};

        -- Allow merging even if one statement has no writes (e.g., x = o(x) style assignments)
        -- Only require that at least one of them has writes
        if not hasAnyEntries(aWrites) and not hasAnyEntries(bWrites) then
            return false;
        end

        for r in pairs(aReads) do
            if bWrites[r] then
                return false;
            end
        end

        for r, b in pairs(aWrites) do
            if bWrites[r] or bReads[r] then
                return false;
            end
        end

        return true;
    end

    local function mergeParallelAssignmentStatements(statA, statB)
        local lhs = {};
        local rhs = {};
        local aLhs, bLhs = statA.statement.lhs, statB.statement.lhs;
        local aRhs, bRhs = statA.statement.rhs, statB.statement.rhs;
        for i = 1, #aLhs do lhs[i] = aLhs[i]; end
        for i = 1, #bLhs do lhs[#aLhs + i] = bLhs[i]; end
        for i = 1, #aRhs do rhs[i] = aRhs[i]; end
        for i = 1, #bRhs do rhs[#aRhs + i] = bRhs[i]; end

        return {
            statement = Ast.AssignmentStatement(lhs, rhs),
            writes = unionLookupTables(statA.writes, statB.writes),
            reads = unionLookupTables(statA.reads, statB.reads),
            usesUpvals = statA.usesUpvals or statB.usesUpvals,
        };
    end

    local function mergeAdjacentParallelAssignments(blockstats)
        local merged = {};
        local i = 1;
        while i <= #blockstats do
            local stat = blockstats[i];
            i = i + 1;

            while i <= #blockstats and canMergeParallelAssignmentStatements(stat, blockstats[i]) do
                stat = mergeParallelAssignmentStatements(stat, blockstats[i]);
                i = i + 1;
            end

            table.insert(merged, stat);
        end
        return merged;
    end

    function Compiler:emitContainerFuncBody()
        local blocks = {};

        util.shuffle(self.blocks);

        for i, block in ipairs(self.blocks) do
            local id = block.id;
            local blockstats = block.statements;

            for i = 2, #blockstats do
                local stat = blockstats[i];
                local reads = stat.reads;
                local writes = stat.writes;
                local maxShift = 0;
                local usesUpvals = stat.usesUpvals;
                for shift = 1, i - 1 do
                    local stat2 = blockstats[i - shift];

                    if stat2.usesUpvals and usesUpvals then
                        break;
                    end

                    local reads2 = stat2.reads;
                    local writes2 = stat2.writes;
                    local f = true;

                    for r, b in pairs(reads2) do
                        if(writes[r]) then
                            f = false;
                            break;
                        end
                    end

                    if f then
                        for r, b in pairs(writes2) do
                            if(writes[r]) then
                                f = false;
                                break;
                            end
                            if(reads[r]) then
                                f = false;
                                break;
                            end
                        end
                    end

                    if not f then
                        break
                    end

                    maxShift = shift;
                end

                local shift = math.random(0, maxShift);
                for j = 1, shift do
                    blockstats[i - j], blockstats[i - j + 1] = blockstats[i - j + 1], blockstats[i - j];
                end
            end

            local mergedBlockStats = mergeAdjacentParallelAssignments(blockstats);
            for _=1, 7 do
                mergedBlockStats = mergeAdjacentParallelAssignments(mergedBlockStats);
            end

            blockstats = {};
            for _, stat in ipairs(mergedBlockStats) do
                table.insert(blockstats, stat.statement);
            end

            local block = { id = id, index = i, block = Ast.Block(blockstats, block.scope) }
            table.insert(blocks, block);
            blocks[id] = block;
        end

        table.sort(blocks, function(a, b) return a.id < b.id end);

        -- Build a strict threshold condition between adjacent block IDs.
        -- Using a midpoint avoids exact-id comparisons while preserving dispatch.
        local function buildBlockThresholdCondition(scope, leftId, rightId, useAndOr)
            local bound = math.floor((leftId + rightId) / 2);
            local posExpr = self:pos(scope);
            local boundExpr = Ast.NumberExpression(bound);

            if useAndOr then
                -- Kept for compatibility with caller variations.
                return Ast.LessThanExpression(posExpr, boundExpr);
            else
                local variant = math.random(1, 2);
                if variant == 1 then
                    return Ast.LessThanExpression(posExpr, boundExpr);
                else
                    return Ast.GreaterThanExpression(boundExpr, posExpr);
                end
            end
        end

        -- Build an elseif chain for a range of blocks
        local function buildElseifChain(tb, l, r, pScope)
            -- Handle invalid range by returning an empty block
            if r < l then
                local emptyScope = Scope:new(pScope);
                return Ast.Block({}, emptyScope);
            end

            local len = r - l + 1;

            -- For single block
            if len == 1 then
                tb[l].block.scope:setParent(pScope);
                return tb[l].block;
            end

            -- For small ranges, use elseif chain
            if len <= 4 then
                local ifScope = Scope:new(pScope);
                local elseifs = {};

                -- First block uses the first midpoint threshold
                tb[l].block.scope:setParent(ifScope);
                local firstCondition = buildBlockThresholdCondition(ifScope, tb[l].id, tb[l + 1].id, false);
                local firstBlock = tb[l].block;

                -- Middle blocks use their upper midpoint threshold
                for i = l + 1, r - 1 do
                    tb[i].block.scope:setParent(ifScope);
                    local condition = buildBlockThresholdCondition(ifScope, tb[i].id, tb[i + 1].id, false);
                    table.insert(elseifs, {
                        condition = condition,
                        body = tb[i].block
                    });
                end

                -- Last block becomes else
                tb[r].block.scope:setParent(ifScope);
                local elseBlock = tb[r].block;

                return Ast.Block({
                    Ast.IfStatement(firstCondition, firstBlock, elseifs, elseBlock);
                }, ifScope);
            end

            -- For larger ranges, use binary split with and/or chaining
            local mid = l + math.ceil(len / 2);
            local leftMaxId = tb[mid - 1].id;
            local rightMinId = tb[mid].id;
            -- Float-safe split: any bound strictly between adjacent IDs works.
            -- Midpoint avoids integer-only math.random(min, max) behavior.
            local bound = math.floor((leftMaxId + rightMinId) / 2);
            local ifScope = Scope:new(pScope);

            local lBlock = buildElseifChain(tb, l, mid - 1, ifScope);
            local rBlock = buildElseifChain(tb, mid, r, ifScope);

            -- Randomly choose between different condition styles
            local condStyle = math.random(1, 3);
            local condition;
            local trueBlock, falseBlock;

            if condStyle == 1 then
                -- pos < bound
                condition = Ast.LessThanExpression(self:pos(ifScope), Ast.NumberExpression(bound));
                trueBlock, falseBlock = lBlock, rBlock;
            elseif condStyle == 2 then
                -- bound > pos
                condition = Ast.GreaterThanExpression(Ast.NumberExpression(bound), self:pos(ifScope));
                trueBlock, falseBlock = lBlock, rBlock;
            else
                -- Equivalent split using strict > with branches reversed.
                condition = Ast.GreaterThanExpression(self:pos(ifScope), Ast.NumberExpression(bound));
                trueBlock, falseBlock = rBlock, lBlock;
            end

            return Ast.Block({
                Ast.IfStatement(condition, trueBlock, {}, falseBlock);
            }, ifScope);
        end

        local whileBody = buildElseifChain(blocks, 1, #blocks, self.containerFuncScope);
        if self.whileScope then
            -- Ensure whileScope is properly connected
            self.whileScope:setParent(self.containerFuncScope);
        end

        self.whileScope:addReferenceToHigherScope(self.containerFuncScope, self.returnVar, 1);
        self.whileScope:addReferenceToHigherScope(self.containerFuncScope, self.posVar);

        self.containerFuncScope:addReferenceToHigherScope(self.scope, self.unpackVar);

        local declarations = {
            self.returnVar,
        }

        for i, var in pairs(self.registerVars) do
            if(i ~= MAX_REGS) then
                table.insert(declarations, var);
            end
        end

        local stats = {}

        if self.maxUsedRegister >= MAX_REGS then
            table.insert(stats, Ast.LocalVariableDeclaration(self.containerFuncScope, {self.registerVars[MAX_REGS]}, {Ast.TableConstructorExpression({})}));
        end

        table.insert(stats, Ast.LocalVariableDeclaration(self.containerFuncScope, util.shuffle(declarations), {}));

        table.insert(stats, Ast.WhileStatement(whileBody, Ast.VariableExpression(self.containerFuncScope, self.posVar)));


        table.insert(stats, Ast.AssignmentStatement({
            Ast.AssignmentVariable(self.containerFuncScope, self.posVar)
        }, {
            Ast.LenExpression(Ast.VariableExpression(self.containerFuncScope, self.detectGcCollectVar))
        }));

        table.insert(stats, Ast.ReturnStatement{
            Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.unpackVar), {
                Ast.VariableExpression(self.containerFuncScope, self.returnVar)
            });
        });

        return Ast.Block(stats, self.containerFuncScope);
    end
end


================================================
FILE: src/prometheus/compiler/expressions/and.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- and.lua
--
-- This Script contains the expression handler for the AndExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local posState = self.registers[self.POS_REGISTER];
    self.registers[self.POS_REGISTER] = self.VAR_REGISTER;

    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i ~= 1 then
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end

    local resReg = regs[1];
    local tmpReg;

    if posState then
        tmpReg = self:allocRegister(false);
        self:addStatement(self:copyRegisters(scope, {tmpReg}, {self.POS_REGISTER}), {tmpReg}, {self.POS_REGISTER}, false);
    end

    local lhsReg = self:compileExpression(expression.lhs, funcDepth, 1)[1];
    if expression.rhs.isConstant then
        local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];
        self:addStatement(self:setRegister(scope, resReg, Ast.AndExpression(self:register(scope, lhsReg), self:register(scope, rhsReg))), {resReg}, {lhsReg, rhsReg}, false);
        if tmpReg then
            self:freeRegister(tmpReg, false);
        end
        self:freeRegister(lhsReg, false);
        self:freeRegister(rhsReg, false);
        return regs;
    end

    local block1, block2 = self:createBlock(), self:createBlock();
    self:addStatement(self:copyRegisters(scope, {resReg}, {lhsReg}), {resReg}, {lhsReg}, false);
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(scope, lhsReg), Ast.NumberExpression(block1.id)), Ast.NumberExpression(block2.id))), {self.POS_REGISTER}, {lhsReg}, false);
    self:freeRegister(lhsReg, false);
    do
        self:setActiveBlock(block1);
        scope = block1.scope;
        local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];
        self:addStatement(self:copyRegisters(scope, {resReg}, {rhsReg}), {resReg}, {rhsReg}, false);
        self:freeRegister(rhsReg, false);

        self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(block2.id)), {self.POS_REGISTER}, {}, false);
    end

    self.registers[self.POS_REGISTER] = posState;

    self:setActiveBlock(block2);
    scope = block2.scope;

    if tmpReg then
        self:addStatement(self:copyRegisters(scope, {self.POS_REGISTER}, {tmpReg}), {self.POS_REGISTER}, {tmpReg}, false);
        self:freeRegister(tmpReg, false);
    end

    return regs;
end;


================================================
FILE: src/prometheus/compiler/expressions/binary.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- binary.lua
--
-- This Script contains the expression handler for the Binary operations (Add, Sub, Mul, Div, etc.).

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            local lhsReg = self:compileExpression(expression.lhs, funcDepth, 1)[1];
            local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];

            local binaryExpr = Ast[expression.kind](self:register(scope, lhsReg), self:register(scope, rhsReg));
            self:addStatement(self:setRegister(scope, regs[i], binaryExpr), {regs[i]}, {lhsReg, rhsReg}, true);
            self:freeRegister(rhsReg, false);
            self:freeRegister(lhsReg, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;


================================================
FILE: src/prometheus/compiler/expressions/boolean.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- boolean.lua
--
-- This Script contains the expression handler for the BooleanExpression.

local Ast = require("prometheus.ast");

local expressionEvaluators = {
    [Ast.GreaterThanExpression] = function(left, right)
        return left > right
    end,
    [Ast.LessThanExpression] = function(left, right)
        return left < right
    end,
    [Ast.GreaterThanOrEqualsExpression] = function(left, right)
        return left >= right
    end,
    [Ast.LessThanOrEqualsExpression] = function(left, right)
        return left <= right
    end,
    [Ast.NotEqualsExpression] = function(left, right)
        return left ~= right
    end,
}

local function createRandomASTCFlowExpression(resultBool)
    local expTB = {
        Ast.GreaterThanExpression,
        Ast.LessThanExpression,
        Ast.GreaterThanOrEqualsExpression,
        Ast.LessThanOrEqualsExpression,
        Ast.NotEqualsExpression
    }

    local leftInt, rightInt, boolResult, randomExp
    repeat
        randomExp = expTB[math.random(1, #expTB)]
        leftInt = Ast.NumberExpression(math.random(1, 2^24))
        rightInt = Ast.NumberExpression(math.random(1, 2^24))
        boolResult = expressionEvaluators[randomExp](leftInt.value, rightInt.value)
    until boolResult == resultBool

    return randomExp(leftInt, rightInt, false)
end

return function(self, expression, _, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            self:addStatement(self:setRegister(scope, regs[i], createRandomASTCFlowExpression(expression.value)), {regs[i]}, {}, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;


================================================
FILE: src/prometheus/compiler/expressions/function_call.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- function_call.lua
--
-- This Script contains the expression handler for the FunctionCallExpression.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local baseReg = self:compileExpression(expression.base, funcDepth, 1)[1];

    local retRegs = {};
    local returnAll = numReturns == self.RETURN_ALL;
    if returnAll then
        retRegs[1] = self:allocRegister(false);
    else
        for i = 1, numReturns do
            retRegs[i] = self:allocRegister(false);
        end
    end

    local regs = {};
    local args = {};
    for i, expr in ipairs(expression.args) do
        if i == #expression.args and (expr.kind == AstKind.FunctionCallExpression or expr.kind == AstKind.PassSelfFunctionCallExpression or expr.kind == AstKind.VarargExpression) then
            local reg = self:compileExpression(expr, funcDepth, self.RETURN_ALL)[1];
            table.insert(args, Ast.FunctionCallExpression(
                self:unpack(scope),
                {self:register(scope, reg)}));
            table.insert(regs, reg);
        else
            local reg = self:compileExpression(expr, funcDepth, 1)[1];
            table.insert(args, self:register(scope, reg));
            table.insert(regs, reg);
        end
    end

    if returnAll then
        self:addStatement(self:setRegister(scope, retRegs[1], Ast.TableConstructorExpression{Ast.TableEntry(Ast.FunctionCallExpression(self:register(scope, baseReg), args))}), {retRegs[1]}, {baseReg, unpack(regs)}, true);
    else
        if numReturns > 1 then
            local tmpReg = self:allocRegister(false);

            self:addStatement(self:setRegister(scope, tmpReg, Ast.TableConstructorExpression{Ast.TableEntry(Ast.FunctionCallExpression(self:register(scope, baseReg), args))}), {tmpReg}, {baseReg, unpack(regs)}, true);


            for i, reg in ipairs(retRegs) do
                self:addStatement(self:setRegister(scope, reg, Ast.IndexExpression(self:register(scope, tmpReg), Ast.NumberExpression(i))), {reg}, {tmpReg}, false);
            end

            self:freeRegister(tmpReg, false);
        else
            self:addStatement(self:setRegister(scope, retRegs[1], Ast.FunctionCallExpression(self:register(scope, baseReg), args)), {retRegs[1]}, {baseReg, unpack(regs)}, true);
        end
    end

    self:freeRegister(baseReg, false);
    for i, reg in ipairs(regs) do
        self:freeRegister(reg, false);
    end

    return retRegs;
end;


================================================
FILE: src/prometheus/compiler/expressions/function_literal.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- function_literal.lua
--
-- This Script contains the expression handler for the FunctionLiteralExpression

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        if i == 1 then
            regs[i] = self:compileFunction(expression, funcDepth);
        else
            regs[i] = self:allocRegister();
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/index.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- index.lua
--
-- This Script contains the expression handler for the IndexExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            local baseReg = self:compileExpression(expression.base, funcDepth, 1)[1];
            local indexReg = self:compileExpression(expression.index, funcDepth, 1)[1];



            self:addStatement(self:setRegister(scope, regs[i], Ast.IndexExpression(self:register(scope, baseReg), self:register(scope, indexReg))), {regs[i]}, {baseReg, indexReg}, true);

            self:freeRegister(baseReg, false);
            self:freeRegister(indexReg, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;


================================================
FILE: src/prometheus/compiler/expressions/len.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- len.lua
--
-- This Script contains the expression handler for the LenExpression

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];

            self:addStatement(self:setRegister(scope, regs[i], Ast.LenExpression(self:register(scope, rhsReg))), {regs[i]}, {rhsReg}, true);
            self:freeRegister(rhsReg, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/negate.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- negate.lua
--
-- This Script contains the expression handler for the NegateExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];

            self:addStatement(self:setRegister(scope, regs[i], Ast.NegateExpression(self:register(scope, rhsReg))), {regs[i]}, {rhsReg}, true);
            self:freeRegister(rhsReg, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/nil.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- nil.lua
--
-- This Script contains the expression handler for the NilExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/not.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- not.lua
--
-- This Script contains the expression handler for the NotExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];

            self:addStatement(self:setRegister(scope, regs[i], Ast.NotExpression(self:register(scope, rhsReg))), {regs[i]}, {rhsReg}, false);
            self:freeRegister(rhsReg, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/number.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- number.lua
--
-- This Script contains the expression handler for the NumberExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            self:addStatement(self:setRegister(scope, regs[i], Ast.NumberExpression(expression.value)), {regs[i]}, {}, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/or.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- or.lua
--
-- This Script contains the expression handler for the OrExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local posState = self.registers[self.POS_REGISTER];
    self.registers[self.POS_REGISTER] = self.VAR_REGISTER;

    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i ~= 1 then
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end

    local resReg = regs[1];
    local tmpReg;

    if posState then
        tmpReg = self:allocRegister(false);
        self:addStatement(self:copyRegisters(scope, {tmpReg}, {self.POS_REGISTER}), {tmpReg}, {self.POS_REGISTER}, false);
    end

    local lhsReg = self:compileExpression(expression.lhs, funcDepth, 1)[1];
    if expression.rhs.isConstant then
        local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];
        self:addStatement(self:setRegister(scope, resReg, Ast.OrExpression(self:register(scope, lhsReg), self:register(scope, rhsReg))), {resReg}, {lhsReg, rhsReg}, false);
        if tmpReg then
            self:freeRegister(tmpReg, false);
        end
        self:freeRegister(lhsReg, false);
        self:freeRegister(rhsReg, false);
        return regs;
    end

    local block1, block2 = self:createBlock(), self:createBlock();
    self:addStatement(self:copyRegisters(scope, {resReg}, {lhsReg}), {resReg}, {lhsReg}, false);
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(scope, lhsReg), Ast.NumberExpression(block2.id)), Ast.NumberExpression(block1.id))), {self.POS_REGISTER}, {lhsReg}, false);
    self:freeRegister(lhsReg, false);

    do
        self:setActiveBlock(block1);
        local scope = block1.scope;
        local rhsReg = self:compileExpression(expression.rhs, funcDepth, 1)[1];
        self:addStatement(self:copyRegisters(scope, {resReg}, {rhsReg}), {resReg}, {rhsReg}, false);
        self:freeRegister(rhsReg, false);


        self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(block2.id)), {self.POS_REGISTER}, {}, false);
    end

    self.registers[self.POS_REGISTER] = posState;

    self:setActiveBlock(block2);
    scope = block2.scope;

    if tmpReg then
        self:addStatement(self:copyRegisters(scope, {self.POS_REGISTER}, {tmpReg}), {self.POS_REGISTER}, {tmpReg}, false);
        self:freeRegister(tmpReg, false);
    end

    return regs;
end;


================================================
FILE: src/prometheus/compiler/expressions/pass_self_function_call.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- pass_self_function_call.lua
--
-- This Script contains the expression handler for the PassSelfFunctionCallExpression.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local baseReg = self:compileExpression(expression.base, funcDepth, 1)[1];
    local retRegs = {};
    local returnAll = numReturns == self.RETURN_ALL;
    if returnAll then
        retRegs[1] = self:allocRegister(false);
    else
        for i = 1, numReturns do
            retRegs[i] = self:allocRegister(false);
        end
    end

    local args = { self:register(scope, baseReg) };
    local regs = { baseReg };

    for i, expr in ipairs(expression.args) do
        if i == #expression.args and (expr.kind == AstKind.FunctionCallExpression or expr.kind == AstKind.PassSelfFunctionCallExpression or expr.kind == AstKind.VarargExpression) then
            local reg = self:compileExpression(expr, funcDepth, self.RETURN_ALL)[1];
            table.insert(args, Ast.FunctionCallExpression(
                self:unpack(scope),
                {self:register(scope, reg)}));
            table.insert(regs, reg);
        else
            local reg = self:compileExpression(expr, funcDepth, 1)[1];
            table.insert(args, self:register(scope, reg));
            table.insert(regs, reg);
        end
    end

    if returnAll or numReturns > 1 then
        local tmpReg = self:allocRegister(false);

        self:addStatement(self:setRegister(scope, tmpReg, Ast.StringExpression(expression.passSelfFunctionName)), {tmpReg}, {}, false);
        self:addStatement(self:setRegister(scope, tmpReg, Ast.IndexExpression(self:register(scope, baseReg), self:register(scope, tmpReg))), {tmpReg}, {baseReg, tmpReg}, false);

        if returnAll then
            self:addStatement(self:setRegister(scope, retRegs[1], Ast.TableConstructorExpression{Ast.TableEntry(Ast.FunctionCallExpression(self:register(scope, tmpReg), args))}), {retRegs[1]}, {tmpReg, unpack(regs)}, true);
        else
            self:addStatement(self:setRegister(scope, tmpReg, Ast.TableConstructorExpression{Ast.TableEntry(Ast.FunctionCallExpression(self:register(scope, tmpReg), args))}), {tmpReg}, {tmpReg, unpack(regs)}, true);

            for i, reg in ipairs(retRegs) do
                self:addStatement(self:setRegister(scope, reg, Ast.IndexExpression(self:register(scope, tmpReg), Ast.NumberExpression(i))), {reg}, {tmpReg}, false);
            end
        end

        self:freeRegister(tmpReg, false);
    else
        local tmpReg = retRegs[1] or self:allocRegister(false);

        self:addStatement(self:setRegister(scope, tmpReg, Ast.StringExpression(expression.passSelfFunctionName)), {tmpReg}, {}, false);
        self:addStatement(self:setRegister(scope, tmpReg, Ast.IndexExpression(self:register(scope, baseReg), self:register(scope, tmpReg))), {tmpReg}, {baseReg, tmpReg}, false);
        self:addStatement(self:setRegister(scope, retRegs[1], Ast.FunctionCallExpression(self:register(scope, tmpReg), args)), {retRegs[1]}, {baseReg, unpack(regs)}, true);
    end

    for i, reg in ipairs(regs) do
        self:freeRegister(reg, false);
    end

    return retRegs;
end;


================================================
FILE: src/prometheus/compiler/expressions/string.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- string.lua
--
-- This Script contains the expression handler for the StringExpression.

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns, 1 do
        regs[i] = self:allocRegister();
        if i == 1 then
            self:addStatement(self:setRegister(scope, regs[i], Ast.StringExpression(expression.value)), {regs[i]}, {}, false);
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/table_constructor.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- table_constructor.lua
--
-- This Script contains the expression handler for the TableConstructorExpression.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister();
        if i == 1 then
            local entries = {};
            local entryRegs = {};
            for i, entry in ipairs(expression.entries) do
                if entry.kind == AstKind.TableEntry then
                    local value = entry.value;
                    if i == #expression.entries and (value.kind == AstKind.FunctionCallExpression or value.kind == AstKind.PassSelfFunctionCallExpression or value.kind == AstKind.VarargExpression) then
                        local reg = self:compileExpression(entry.value, funcDepth, self.RETURN_ALL)[1];
                        table.insert(entries, Ast.TableEntry(Ast.FunctionCallExpression(
                            self:unpack(scope),
                            {self:register(scope, reg)})));
                        table.insert(entryRegs, reg);
                    else
                        local reg = self:compileExpression(entry.value, funcDepth, 1)[1];
                        table.insert(entries, Ast.TableEntry(self:register(scope, reg)));
                        table.insert(entryRegs, reg);
                    end
                else
                    local keyReg = self:compileExpression(entry.key, funcDepth, 1)[1];
                    local valReg = self:compileExpression(entry.value, funcDepth, 1)[1];
                    table.insert(entries, Ast.KeyedTableEntry(self:register(scope, keyReg), self:register(scope, valReg)));
                    table.insert(entryRegs, valReg);
                    table.insert(entryRegs, keyReg);
                end
            end
            self:addStatement(self:setRegister(scope, regs[i], Ast.TableConstructorExpression(entries)), {regs[i]}, entryRegs, false);
            for i, reg in ipairs(entryRegs) do
                self:freeRegister(reg, false);
            end
        else
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;


================================================
FILE: src/prometheus/compiler/expressions/vararg.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- vararg.lua
--
-- This Script contains the expression handler for the VarargExpression

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    if numReturns == self.RETURN_ALL then
        return {self.varargReg};
    end
    local regs = {};
    for i = 1, numReturns do
        regs[i] = self:allocRegister(false);
        self:addStatement(self:setRegister(scope, regs[i], Ast.IndexExpression(self:register(scope, self.varargReg), Ast.NumberExpression(i))), {regs[i]}, {self.varargReg}, false);
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions/variable.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- variable.lua
--
-- This Script contains the expression handler for the VariableExpression

local Ast = require("prometheus.ast");

return function(self, expression, funcDepth, numReturns)
    local scope = self.activeBlock.scope;
    local regs = {};
    for i = 1, numReturns do
        if i == 1 then
            if expression.scope.isGlobal then
                regs[i] = self:allocRegister(false);
                local tmpReg = self:allocRegister(false);
                self:addStatement(self:setRegister(scope, tmpReg, Ast.StringExpression(expression.scope:getVariableName(expression.id))), {tmpReg}, {}, false);
                self:addStatement(self:setRegister(scope, regs[i], Ast.IndexExpression(self:env(scope), self:register(scope, tmpReg))), {regs[i]}, {tmpReg}, true);
                self:freeRegister(tmpReg, false);
            else
                if self.scopeFunctionDepths[expression.scope] == funcDepth then
                    if self:isUpvalue(expression.scope, expression.id) then
                        local reg = self:allocRegister(false);
                        local varReg = self:getVarRegister(expression.scope, expression.id, funcDepth, nil);
                        self:addStatement(self:setRegister(scope, reg, self:getUpvalueMember(scope, self:register(scope, varReg))), {reg}, {varReg}, true);
                        regs[i] = reg;
                    else
                        regs[i] = self:getVarRegister(expression.scope, expression.id, funcDepth, nil);
                    end
                else
                    local reg = self:allocRegister(false);
                    local upvalId = self:getUpvalueId(expression.scope, expression.id);
                    scope:addReferenceToHigherScope(self.containerFuncScope, self.currentUpvaluesVar);
                    self:addStatement(self:setRegister(scope, reg, self:getUpvalueMember(scope, Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.currentUpvaluesVar), Ast.NumberExpression(upvalId)))), {reg}, {}, true);
                    regs[i] = reg;
                end
            end
        else
            regs[i] = self:allocRegister();
            self:addStatement(self:setRegister(scope, regs[i], Ast.NilExpression()), {regs[i]}, {}, false);
        end
    end
    return regs;
end;



================================================
FILE: src/prometheus/compiler/expressions.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- expressions.lua
--
-- This Script contains the expression handlers: exports handler table keyed by AstKind.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

local handlers = {};
local expressions = "prometheus.compiler.expressions.";
local function requireExpression(name)
    return require(expressions .. name);
end
handlers[AstKind.StringExpression] = requireExpression("string");
handlers[AstKind.NumberExpression] = requireExpression("number");
handlers[AstKind.BooleanExpression] = requireExpression("boolean");
handlers[AstKind.NilExpression] = requireExpression("nil");
handlers[AstKind.VariableExpression] = requireExpression("variable");
handlers[AstKind.FunctionCallExpression] = requireExpression("function_call");
handlers[AstKind.PassSelfFunctionCallExpression] = requireExpression("pass_self_function_call");
handlers[AstKind.IndexExpression] = requireExpression("index");
handlers[AstKind.NotExpression] = requireExpression("not");
handlers[AstKind.NegateExpression] = requireExpression("negate");
handlers[AstKind.LenExpression] = requireExpression("len");
handlers[AstKind.OrExpression] = requireExpression("or");
handlers[AstKind.AndExpression] = requireExpression("and");
handlers[AstKind.TableConstructorExpression] = requireExpression("table_constructor");
handlers[AstKind.FunctionLiteralExpression] = requireExpression("function_literal");
handlers[AstKind.VarargExpression] = requireExpression("vararg");

-- Binary ops share one handler
local binaryHandler = requireExpression("binary");
handlers[AstKind.LessThanExpression] = binaryHandler;
handlers[AstKind.GreaterThanExpression] = binaryHandler;
handlers[AstKind.LessThanOrEqualsExpression] = binaryHandler;
handlers[AstKind.GreaterThanOrEqualsExpression] = binaryHandler;
handlers[AstKind.NotEqualsExpression] = binaryHandler;
handlers[AstKind.EqualsExpression] = binaryHandler;
handlers[AstKind.StrCatExpression] = binaryHandler;
handlers[AstKind.AddExpression] = binaryHandler;
handlers[AstKind.SubExpression] = binaryHandler;
handlers[AstKind.MulExpression] = binaryHandler;
handlers[AstKind.DivExpression] = binaryHandler;
handlers[AstKind.ModExpression] = binaryHandler;
handlers[AstKind.PowExpression] = binaryHandler;

return handlers;



================================================
FILE: src/prometheus/compiler/register.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- register.lua
--
-- This Script contains the register management for the compiler.

local Ast = require("prometheus.ast");
local constants = require("prometheus.compiler.constants");
local randomStrings = require("prometheus.randomStrings");

local MAX_REGS = constants.MAX_REGS;

return function(Compiler)
    function Compiler:freeRegister(id, force)
        if force or not (self.registers[id] == self.VAR_REGISTER) then
            self.usedRegisters = self.usedRegisters - 1;
            self.registers[id] = false
        end
    end

    function Compiler:isVarRegister(id)
        return self.registers[id] == self.VAR_REGISTER;
    end

    function Compiler:allocRegister(isVar)
        self.usedRegisters = self.usedRegisters + 1;

        if not isVar then
            if not self.registers[self.POS_REGISTER] then
                self.registers[self.POS_REGISTER] = true;
                return self.POS_REGISTER;
            end

            if not self.registers[self.RETURN_REGISTER] then
                self.registers[self.RETURN_REGISTER] = true;
                return self.RETURN_REGISTER;
            end
        end

        local id = 0;
        if self.usedRegisters < MAX_REGS * constants.MAX_REGS_MUL then
            repeat
                id = math.random(1, MAX_REGS - 1);
            until not self.registers[id];
        else
            repeat
                id = id + 1;
            until not self.registers[id];
        end

        if id > self.maxUsedRegister then
            self.maxUsedRegister = id;
        end

        if(isVar) then
            self.registers[id] = self.VAR_REGISTER;
        else
            self.registers[id] = true
        end
        return id;
    end

    function Compiler:isUpvalue(scope, id)
        return self.upvalVars[scope] and self.upvalVars[scope][id];
    end

    function Compiler:makeUpvalue(scope, id)
        if(not self.upvalVars[scope]) then
            self.upvalVars[scope] = {}
        end
        self.upvalVars[scope][id] = true;
    end

    function Compiler:getVarRegister(scope, id, functionDepth, potentialId)
        if(not self.registersForVar[scope]) then
            self.registersForVar[scope] = {};
            self.scopeFunctionDepths[scope] = functionDepth;
        end

        local reg = self.registersForVar[scope][id];
        if not reg then
            if potentialId and self.registers[potentialId] ~= self.VAR_REGISTER and potentialId ~= self.POS_REGISTER and potentialId ~= self.RETURN_REGISTER then
                self.registers[potentialId] = self.VAR_REGISTER;
                reg = potentialId;
            else
                reg = self:allocRegister(true);
            end
            self.registersForVar[scope][id] = reg;
        end
        return reg;
    end

    function Compiler:getRegisterVarId(id)
        local varId = self.registerVars[id];
        if not varId then
            varId = self.containerFuncScope:addVariable();
            self.registerVars[id] = varId;
        end
        return varId;
    end

    function Compiler:register(scope, id)
        if id == self.POS_REGISTER then
            return self:pos(scope);
        end

        if id == self.RETURN_REGISTER then
            return self:getReturn(scope);
        end

        if id < MAX_REGS then
            local vid = self:getRegisterVarId(id);
            scope:addReferenceToHigherScope(self.containerFuncScope, vid);
            return Ast.VariableExpression(self.containerFuncScope, vid);
        end

        local vid = self:getRegisterVarId(MAX_REGS);
        scope:addReferenceToHigherScope(self.containerFuncScope, vid);
        return Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, vid), Ast.NumberExpression((id - MAX_REGS) + 1));
    end

    function Compiler:registerList(scope, ids)
        local l = {};
        for i, id in ipairs(ids) do
            table.insert(l, self:register(scope, id));
        end
        return l;
    end

    function Compiler:registerAssignment(scope, id)
        if id == self.POS_REGISTER then
            return self:posAssignment(scope);
        end
        if id == self.RETURN_REGISTER then
            return self:returnAssignment(scope);
        end

        if id < MAX_REGS then
            local vid = self:getRegisterVarId(id);
            scope:addReferenceToHigherScope(self.containerFuncScope, vid);
            return Ast.AssignmentVariable(self.containerFuncScope, vid);
        end

        local vid = self:getRegisterVarId(MAX_REGS);
        scope:addReferenceToHigherScope(self.containerFuncScope, vid);
        return Ast.AssignmentIndexing(Ast.VariableExpression(self.containerFuncScope, vid), Ast.NumberExpression((id - MAX_REGS) + 1));
    end

    function Compiler:setRegister(scope, id, val, compundArg)
        if(compundArg) then
            return compundArg(self:registerAssignment(scope, id), val);
        end
        return Ast.AssignmentStatement({
            self:registerAssignment(scope, id)
        }, {
            val
        });
    end

    function Compiler:setRegisters(scope, ids, vals)
        local idStats = {};
        for i, id in ipairs(ids) do
            table.insert(idStats, self:registerAssignment(scope, id));
        end

        return Ast.AssignmentStatement(idStats, vals);
    end

    function Compiler:copyRegisters(scope, to, from)
        local idStats = {};
        local vals = {};
        for i, id in ipairs(to) do
            local fromId = from[i];
            if(fromId ~= id) then
                table.insert(idStats, self:registerAssignment(scope, id));
                table.insert(vals, self:register(scope, fromId));
            end
        end

        if(#idStats > 0 and #vals > 0) then
            return Ast.AssignmentStatement(idStats, vals);
        end
    end

    function Compiler:resetRegisters()
        self.registers = {};
    end

    function Compiler:pos(scope)
        scope:addReferenceToHigherScope(self.containerFuncScope, self.posVar);
        return Ast.VariableExpression(self.containerFuncScope, self.posVar);
    end

    function Compiler:posAssignment(scope)
        scope:addReferenceToHigherScope(self.containerFuncScope, self.posVar);
        return Ast.AssignmentVariable(self.containerFuncScope, self.posVar);
    end

    function Compiler:args(scope)
        scope:addReferenceToHigherScope(self.containerFuncScope, self.argsVar);
        return Ast.VariableExpression(self.containerFuncScope, self.argsVar);
    end

    function Compiler:unpack(scope)
        scope:addReferenceToHigherScope(self.scope, self.unpackVar);
        return Ast.VariableExpression(self.scope, self.unpackVar);
    end

    function Compiler:env(scope)
        scope:addReferenceToHigherScope(self.scope, self.envVar);
        return Ast.VariableExpression(self.scope, self.envVar);
    end

    function Compiler:jmp(scope, to)
        scope:addReferenceToHigherScope(self.containerFuncScope, self.posVar);
        return Ast.AssignmentStatement({Ast.AssignmentVariable(self.containerFuncScope, self.posVar)},{to});
    end

    function Compiler:setPos(scope, val)
        if not val then
            local v = Ast.IndexExpression(self:env(scope), randomStrings.randomStringNode(math.random(12, 14)));
            scope:addReferenceToHigherScope(self.containerFuncScope, self.posVar);
            return Ast.AssignmentStatement({Ast.AssignmentVariable(self.containerFuncScope, self.posVar)}, {v});
        end
        scope:addReferenceToHigherScope(self.containerFuncScope, self.posVar);
        return Ast.AssignmentStatement({Ast.AssignmentVariable(self.containerFuncScope, self.posVar)}, {Ast.NumberExpression(val) or Ast.NilExpression()});
    end

    function Compiler:setReturn(scope, val)
        scope:addReferenceToHigherScope(self.containerFuncScope, self.returnVar);
        return Ast.AssignmentStatement({Ast.AssignmentVariable(self.containerFuncScope, self.returnVar)}, {val});
    end

    function Compiler:getReturn(scope)
        scope:addReferenceToHigherScope(self.containerFuncScope, self.returnVar);
        return Ast.VariableExpression(self.containerFuncScope, self.returnVar);
    end

    function Compiler:returnAssignment(scope)
        scope:addReferenceToHigherScope(self.containerFuncScope, self.returnVar);
        return Ast.AssignmentVariable(self.containerFuncScope, self.returnVar);
    end

    function Compiler:setUpvalueMember(scope, idExpr, valExpr, compoundConstructor)
        scope:addReferenceToHigherScope(self.scope, self.upvaluesTable);
        if compoundConstructor then
            return compoundConstructor(Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesTable), idExpr), valExpr);
        end
        return Ast.AssignmentStatement({Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesTable), idExpr)}, {valExpr});
    end

    function Compiler:getUpvalueMember(scope, idExpr)
        scope:addReferenceToHigherScope(self.scope, self.upvaluesTable);
        return Ast.IndexExpression(Ast.VariableExpression(self.scope, self.upvaluesTable), idExpr);
    end
end



================================================
FILE: src/prometheus/compiler/statements/assignment.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- assignment.lua
--
-- This Script contains the statement handler for the AssignmentStatement.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local exprregs = {};
    local assignmentIndexingRegs = {};
    for i, primaryExpr in ipairs(statement.lhs) do
        if(primaryExpr.kind == AstKind.AssignmentIndexing) then
            assignmentIndexingRegs [i] = {
                base = self:compileExpression(primaryExpr.base, funcDepth, 1)[1],
                index = self:compileExpression(primaryExpr.index, funcDepth, 1)[1],
            };
        end
    end

    for i, expr in ipairs(statement.rhs) do
        if(i == #statement.rhs and #statement.lhs > #statement.rhs) then
            local regs = self:compileExpression(expr, funcDepth, #statement.lhs - #statement.rhs + 1);

            for i, reg in ipairs(regs) do
                if(self:isVarRegister(reg)) then
                    local ro = reg;
                    reg = self:allocRegister(false);
                    self:addStatement(self:copyRegisters(scope, {reg}, {ro}), {reg}, {ro}, false);
                end
                table.insert(exprregs, reg);
            end
        else
            if statement.lhs[i] or expr.kind == AstKind.FunctionCallExpression or expr.kind == AstKind.PassSelfFunctionCallExpression then
                local reg = self:compileExpression(expr, funcDepth, 1)[1];
                if(self:isVarRegister(reg)) then
                    local ro = reg;
                    reg = self:allocRegister(false);
                    self:addStatement(self:copyRegisters(scope, {reg}, {ro}), {reg}, {ro}, false);
                end
                table.insert(exprregs, reg);
            end
        end
    end

    for i, primaryExpr in ipairs(statement.lhs) do
        if primaryExpr.kind == AstKind.AssignmentVariable then
            if primaryExpr.scope.isGlobal then
                local tmpReg = self:allocRegister(false);
                self:addStatement(self:setRegister(scope, tmpReg, Ast.StringExpression(primaryExpr.scope:getVariableName(primaryExpr.id))), {tmpReg}, {}, false);
                self:addStatement(Ast.AssignmentStatement({Ast.AssignmentIndexing(self:env(scope), self:register(scope, tmpReg))},
                 {self:register(scope, exprregs[i])}), {}, {tmpReg, exprregs[i]}, true);
                self:freeRegister(tmpReg, false);
            else
                if self.scopeFunctionDepths[primaryExpr.scope] == funcDepth then
                    if self:isUpvalue(primaryExpr.scope, primaryExpr.id) then
                        local reg = self:getVarRegister(primaryExpr.scope, primaryExpr.id, funcDepth);
                        self:addStatement(self:setUpvalueMember(scope, self:register(scope, reg), self:register(scope, exprregs[i])), {}, {reg, exprregs[i]}, true);
                    else
                        local reg = self:getVarRegister(primaryExpr.scope, primaryExpr.id, funcDepth, exprregs[i]);
                        if reg ~= exprregs[i] then
                            self:addStatement(self:setRegister(scope, reg, self:register(scope, exprregs[i])), {reg}, {exprregs[i]}, false);
                        end
                    end
                else
                    local upvalId = self:getUpvalueId(primaryExpr.scope, primaryExpr.id);
                    scope:addReferenceToHigherScope(self.containerFuncScope, self.currentUpvaluesVar);
                    self:addStatement(self:setUpvalueMember(scope, Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.currentUpvaluesVar), Ast.NumberExpression(upvalId)), self:register(scope, exprregs[i])), {}, {exprregs[i]}, true);
                end
            end
        elseif primaryExpr.kind == AstKind.AssignmentIndexing then
            local baseReg = assignmentIndexingRegs[i].base;
            local indexReg = assignmentIndexingRegs[i].index;
            self:addStatement(Ast.AssignmentStatement({
                Ast.AssignmentIndexing(self:register(scope, baseReg), self:register(scope, indexReg))
            }, {
                self:register(scope, exprregs[i])
            }), {}, {exprregs[i], baseReg, indexReg}, true);
            self:freeRegister(exprregs[i], false);
            self:freeRegister(baseReg, false);
            self:freeRegister(indexReg, false);
        else
            error(string.format("Invalid Assignment lhs: %s", statement.lhs));
        end
    end
end;


================================================
FILE: src/prometheus/compiler/statements/break_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- break_statement.lua
--
-- This Script contains the statement handler for the BreakStatement.

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local toFreeVars = {};
    local statScope;
    repeat
        statScope = statScope and statScope.parentScope or statement.scope;
        for id, name in ipairs(statScope.variables) do
            table.insert(toFreeVars, {
                scope = statScope,
                id = id;
            });
        end
    until statScope == statement.loop.body.scope;

    for i, var in pairs(toFreeVars) do
        local varScope, id = var.scope, var.id;
        local varReg = self:getVarRegister(varScope, id, nil, nil);
        if self:isUpvalue(varScope, id) then
            scope:addReferenceToHigherScope(self.scope, self.freeUpvalueFunc);
            self:addStatement(self:setRegister(scope, varReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.freeUpvalueFunc), {
                self:register(scope, varReg)
            })), {varReg}, {varReg}, false);
        else
            self:addStatement(self:setRegister(scope, varReg, Ast.NilExpression()), {varReg}, {}, false);
        end
    end


    self:addStatement(self:setPos(scope, statement.loop.__final_block.id), {self.POS_REGISTER}, {}, false);
    self.activeBlock.advanceToNextBlock = false;
end;


================================================
FILE: src/prometheus/compiler/statements/compound.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- compound.lua
--
-- This Script contains the statement handler for the Compound statements (compound add, sub, mul, etc.)

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

local compoundConstructors = {
    [AstKind.CompoundAddStatement] = Ast.CompoundAddStatement,
    [AstKind.CompoundSubStatement] = Ast.CompoundSubStatement,
    [AstKind.CompoundMulStatement] = Ast.CompoundMulStatement,
    [AstKind.CompoundDivStatement] = Ast.CompoundDivStatement,
    [AstKind.CompoundModStatement] = Ast.CompoundModStatement,
    [AstKind.CompoundPowStatement] = Ast.CompoundPowStatement,
    [AstKind.CompoundConcatStatement] = Ast.CompoundConcatStatement,
};

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local compoundConstructor = compoundConstructors[statement.kind];
    if statement.lhs.kind == AstKind.AssignmentIndexing then
        local indexing = statement.lhs;
        local baseReg = self:compileExpression(indexing.base, funcDepth, 1)[1];
        local indexReg = self:compileExpression(indexing.index, funcDepth, 1)[1];
        local valueReg = self:compileExpression(statement.rhs, funcDepth, 1)[1];

        self:addStatement(compoundConstructor(Ast.AssignmentIndexing(self:register(scope, baseReg), self:register(scope, indexReg)), self:register(scope, valueReg)), {}, {baseReg, indexReg, valueReg}, true);
        self:freeRegister(baseReg, false);
        self:freeRegister(indexReg, false);
        self:freeRegister(valueReg, false);
    else
        local valueReg = self:compileExpression(statement.rhs, funcDepth, 1)[1];
        local primaryExpr = statement.lhs;
        if primaryExpr.scope.isGlobal then
            local tmpReg = self:allocRegister(false);
            self:addStatement(self:setRegister(scope, tmpReg, Ast.StringExpression(primaryExpr.scope:getVariableName(primaryExpr.id))), {tmpReg}, {}, false);
            self:addStatement(compoundConstructor(Ast.AssignmentIndexing(self:env(scope), self:register(scope, tmpReg)),
             self:register(scope, valueReg)), {}, {tmpReg, valueReg}, true);
            self:freeRegister(tmpReg, false);
            self:freeRegister(valueReg, false);
        else
            if self.scopeFunctionDepths[primaryExpr.scope] == funcDepth then
                if self:isUpvalue(primaryExpr.scope, primaryExpr.id) then
                    local reg = self:getVarRegister(primaryExpr.scope, primaryExpr.id, funcDepth);
                    self:addStatement(self:setUpvalueMember(scope, self:register(scope, reg), self:register(scope, valueReg), compoundConstructor), {}, {reg, valueReg}, true);
                else
                    local reg = self:getVarRegister(primaryExpr.scope, primaryExpr.id, funcDepth, valueReg);
                    if reg ~= valueReg then
                        self:addStatement(self:setRegister(scope, reg, self:register(scope, valueReg), compoundConstructor), {reg}, {valueReg}, false);
                    end
                end
            else
                local upvalId = self:getUpvalueId(primaryExpr.scope, primaryExpr.id);
                scope:addReferenceToHigherScope(self.containerFuncScope, self.currentUpvaluesVar);
                self:addStatement(self:setUpvalueMember(scope, Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.currentUpvaluesVar), Ast.NumberExpression(upvalId)), self:register(scope, valueReg), compoundConstructor), {}, {valueReg}, true);
            end
            self:freeRegister(valueReg, false);
        end
    end
end;


================================================
FILE: src/prometheus/compiler/statements/continue_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- continue_statement.lua
--
-- This Script contains the statement handler for the ContinueStatement.

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local toFreeVars = {};
    local statScope;
    repeat
        statScope = statScope and statScope.parentScope or statement.scope;
        for id, _ in pairs(statScope.variables) do
            table.insert(toFreeVars, {
                scope = statScope,
                id = id;
            });
        end
    until statScope == statement.loop.body.scope;

    for _, var in ipairs(toFreeVars) do
        local varScope, id = var.scope, var.id;
        local varReg = self:getVarRegister(varScope, id, nil, nil);
        if self:isUpvalue(varScope, id) then
            scope:addReferenceToHigherScope(self.scope, self.freeUpvalueFunc);
            self:addStatement(self:setRegister(scope, varReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.freeUpvalueFunc), {
                self:register(scope, varReg)
            })), {varReg}, {varReg}, false);
        else
            self:addStatement(self:setRegister(scope, varReg, Ast.NilExpression()), {varReg}, {}, false);
        end
    end


    self:addStatement(self:setPos(scope, statement.loop.__start_block.id), {self.POS_REGISTER}, {}, false);
    self.activeBlock.advanceToNextBlock = false;
end;


================================================
FILE: src/prometheus/compiler/statements/do_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- do_statement.lua
--
-- This Script contains the statement handler for the DoStatement.

return function(self, statement, funcDepth)
    self:compileBlock(statement.body, funcDepth);
end;



================================================
FILE: src/prometheus/compiler/statements/for_in_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- for_in_statement.lua
--
-- This Script contains the statement handler for the ForInStatement

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local expressionsLength = #statement.expressions;
    local exprregs = {};
    for i, expr in ipairs(statement.expressions) do
        if(i == expressionsLength and expressionsLength < 3) then
            local regs = self:compileExpression(expr, funcDepth, 4 - expressionsLength);
            for i = 1, 4 - expressionsLength do
                table.insert(exprregs, regs[i]);
            end
        else
            if i <= 3 then
                table.insert(exprregs, self:compileExpression(expr, funcDepth, 1)[1])
            else
                self:freeRegister(self:compileExpression(expr, funcDepth, 1)[1], false);
            end
        end
    end

    for i, reg in ipairs(exprregs) do
        if reg and self.registers[reg] ~= self.VAR_REGISTER and reg ~= self.POS_REGISTER and reg ~= self.RETURN_REGISTER then
            self.registers[reg] = self.VAR_REGISTER;
        else
            exprregs[i] = self:allocRegister(true);
            self:addStatement(self:copyRegisters(scope, {exprregs[i]}, {reg}), {exprregs[i]}, {reg}, false);
        end
    end

    local checkBlock = self:createBlock();
    local bodyBlock = self:createBlock();
    local finalBlock = self:createBlock();

    statement.__start_block = checkBlock;
    statement.__final_block = finalBlock;

    self:addStatement(self:setPos(scope, checkBlock.id), {self.POS_REGISTER}, {}, false);

    self:setActiveBlock(checkBlock);
    local scope = self.activeBlock.scope;

    local varRegs = {};
    for i, id in ipairs(statement.ids) do
        varRegs[i] = self:getVarRegister(statement.scope, id, funcDepth)
    end



    self:addStatement(Ast.AssignmentStatement({
        self:registerAssignment(scope, exprregs[3]),
        varRegs[2] and self:registerAssignment(scope, varRegs[2]),
    }, {
        Ast.FunctionCallExpression(self:register(scope, exprregs[1]), {
            self:register(scope, exprregs[2]),
            self:register(scope, exprregs[3]),
        })
    }), {exprregs[3], varRegs[2]}, {exprregs[1], exprregs[2], exprregs[3]}, true);



    self:addStatement(Ast.AssignmentStatement({
        self:posAssignment(scope)
    }, {
        Ast.OrExpression(Ast.AndExpression(self:register(scope, exprregs[3]), Ast.NumberExpression(bodyBlock.id)), Ast.NumberExpression(finalBlock.id))
    }), {self.POS_REGISTER}, {exprregs[3]}, false);

    self:setActiveBlock(bodyBlock);
    local scope = self.activeBlock.scope;

    self:addStatement(self:copyRegisters(scope, {varRegs[1]}, {exprregs[3]}), {varRegs[1]}, {exprregs[3]}, false);

    for i=3, #varRegs do
        self:addStatement(self:setRegister(scope, varRegs[i], Ast.NilExpression()), {varRegs[i]}, {}, false);
    end

    for i, id in ipairs(statement.ids) do
        if(self:isUpvalue(statement.scope, id)) then
            local varreg = varRegs[i];
            local tmpReg = self:allocRegister(false);
            scope:addReferenceToHigherScope(self.scope, self.allocUpvalFunction);
            self:addStatement(self:setRegister(scope, tmpReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {})), {tmpReg}, {}, false);
            self:addStatement(self:setUpvalueMember(scope, self:register(scope, tmpReg), self:register(scope, varreg)), {}, {tmpReg, varreg}, true);
            self:addStatement(self:copyRegisters(scope, {varreg}, {tmpReg}), {varreg}, {tmpReg}, false);
            self:freeRegister(tmpReg, false);
        end
    end

    self:compileBlock(statement.body, funcDepth);
    self:addStatement(self:setPos(scope, checkBlock.id), {self.POS_REGISTER}, {}, false);
    self:setActiveBlock(finalBlock);

    for i, _ in ipairs(exprregs) do
        self:freeRegister(exprregs[i], true)
    end
end;


================================================
FILE: src/prometheus/compiler/statements/for_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- for_statement.lua
--
-- This Script contains the statement handler for the ForStatement

local Ast = require("prometheus.ast");
local util = require("prometheus.util");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local checkBlock = self:createBlock();
    local innerBlock = self:createBlock();
    local finalBlock = self:createBlock();

    statement.__start_block = checkBlock;
    statement.__final_block = finalBlock;

    local posState = self.registers[self.POS_REGISTER];
    self.registers[self.POS_REGISTER] = self.VAR_REGISTER;

    local initialReg = self:compileExpression(statement.initialValue, funcDepth, 1)[1];

    local finalExprReg = self:compileExpression(statement.finalValue, funcDepth, 1)[1];
    local finalReg = self:allocRegister(false);
    self:addStatement(self:copyRegisters(scope, {finalReg}, {finalExprReg}), {finalReg}, {finalExprReg}, false);
    self:freeRegister(finalExprReg);

    local incrementExprReg = self:compileExpression(statement.incrementBy, funcDepth, 1)[1];
    local incrementReg = self:allocRegister(false);
    self:addStatement(self:copyRegisters(scope, {incrementReg}, {incrementExprReg}), {incrementReg}, {incrementExprReg}, false);
    self:freeRegister(incrementExprReg);

    local tmpReg = self:allocRegister(false);
    self:addStatement(self:setRegister(scope, tmpReg, Ast.NumberExpression(0)), {tmpReg}, {}, false);
    local incrementIsNegReg = self:allocRegister(false);

    local shouldSwap3 = math.random(1, 2) == 2;
    local shuffledRegs4 = shouldSwap3 and {incrementReg, tmpReg} or {tmpReg, incrementReg};
    self:addStatement(self:setRegister(scope, incrementIsNegReg, Ast[shouldSwap3 and "LessThanExpression" or "GreaterThanExpression"](self:register(scope, shuffledRegs4[1]), self:register(scope, shuffledRegs4[2]))), {incrementIsNegReg}, {shuffledRegs4[1], shuffledRegs4[2]}, false);

    self:freeRegister(tmpReg);

    local currentReg = self:allocRegister(true);
    self:addStatement(self:setRegister(scope, currentReg, Ast.SubExpression(self:register(scope, initialReg), self:register(scope, incrementReg))), {currentReg}, {initialReg, incrementReg}, false);
    self:freeRegister(initialReg);

    self:addStatement(self:jmp(scope, Ast.NumberExpression(checkBlock.id)), {self.POS_REGISTER}, {}, false);

    self:setActiveBlock(checkBlock);

    scope = checkBlock.scope;

    -- x = x + y or x = y + x instead of just x = x + y.
    --> NEW: In an attempt to thwart deobfuscations, despite this being a simple comparison... Shuffling these causes problems for decompilers.
    --> NOTE: This isn't unstable code, I've tested it multiple times.

    local shuffledRegs = util.shuffle({currentReg, incrementReg});
    self:addStatement(self:setRegister(scope, currentReg, Ast.AddExpression(self:register(scope, shuffledRegs[1]), self:register(scope, shuffledRegs[2]))), {currentReg}, {shuffledRegs[1], shuffledRegs[2]}, false);
    local tmpReg1 = self:allocRegister(false);
    local tmpReg2 = self:allocRegister(false);
    self:addStatement(self:setRegister(scope, tmpReg2, Ast.NotExpression(self:register(scope, incrementIsNegReg))), {tmpReg2}, {incrementIsNegReg}, false);

    local shouldSwap = math.random(1, 2) == 2;
    local shuffledRegs2 = shouldSwap and {currentReg, finalReg} or {finalReg, currentReg};
    self:addStatement(self:setRegister(scope, tmpReg1, Ast[shouldSwap and "LessThanOrEqualsExpression" or "GreaterThanOrEqualsExpression"](self:register(scope, shuffledRegs2[1]), self:register(scope, shuffledRegs2[2]))), {tmpReg1}, {shuffledRegs2[1], shuffledRegs2[2]}, false);
    self:addStatement(self:setRegister(scope, tmpReg1, Ast.AndExpression(self:register(scope, tmpReg2), self:register(scope, tmpReg1))), {tmpReg1}, {tmpReg1, tmpReg2}, false);

    local shouldSwap2 = math.random(1, 2) == 2;
    local shuffledRegs3 = shouldSwap2 and {currentReg, finalReg} or {finalReg, currentReg};
    self:addStatement(self:setRegister(scope, tmpReg2, Ast[shouldSwap2 and "GreaterThanOrEqualsExpression" or "LessThanOrEqualsExpression"](self:register(scope, shuffledRegs3[1]), self:register(scope, shuffledRegs3[2]))), {tmpReg2}, {shuffledRegs3[1], shuffledRegs3[2]}, false);

    self:addStatement(self:setRegister(scope, tmpReg2, Ast.AndExpression(self:register(scope, incrementIsNegReg), self:register(scope, tmpReg2))), {tmpReg2}, {tmpReg2, incrementIsNegReg}, false);
    self:addStatement(self:setRegister(scope, tmpReg1, Ast.OrExpression(self:register(scope, tmpReg2), self:register(scope, tmpReg1))), {tmpReg1}, {tmpReg1, tmpReg2}, false);
    self:freeRegister(tmpReg2);
    tmpReg2 = self:compileExpression(Ast.NumberExpression(innerBlock.id), funcDepth, 1)[1];
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.AndExpression(self:register(scope, tmpReg1), self:register(scope, tmpReg2))), {self.POS_REGISTER}, {tmpReg1, tmpReg2}, false);
    self:freeRegister(tmpReg2);
    self:freeRegister(tmpReg1);
    tmpReg2 = self:compileExpression(Ast.NumberExpression(finalBlock.id), funcDepth, 1)[1];
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(self:register(scope, self.POS_REGISTER), self:register(scope, tmpReg2))), {self.POS_REGISTER}, {self.POS_REGISTER, tmpReg2}, false);
    self:freeRegister(tmpReg2);

    self:setActiveBlock(innerBlock);
    scope = innerBlock.scope;
    self.registers[self.POS_REGISTER] = posState;

    local varReg = self:getVarRegister(statement.scope, statement.id, funcDepth, nil);

    if(self:isUpvalue(statement.scope, statement.id)) then
        scope:addReferenceToHigherScope(self.scope, self.allocUpvalFunction);
        self:addStatement(self:setRegister(scope, varReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {})), {varReg}, {}, false);
        self:addStatement(self:setUpvalueMember(scope, self:register(scope, varReg), self:register(scope, currentReg)), {}, {varReg, currentReg}, true);
    else
        self:addStatement(self:setRegister(scope, varReg, self:register(scope, currentReg)), {varReg}, {currentReg}, false);
    end


    self:compileBlock(statement.body, funcDepth);
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(checkBlock.id)), {self.POS_REGISTER}, {}, false);

    self.registers[self.POS_REGISTER] = self.VAR_REGISTER;
    self:freeRegister(finalReg);
    self:freeRegister(incrementIsNegReg);
    self:freeRegister(incrementReg);
    self:freeRegister(currentReg, true);

    self.registers[self.POS_REGISTER] = posState;
    self:setActiveBlock(finalBlock);
end;



================================================
FILE: src/prometheus/compiler/statements/function_call.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- function_call.lua
--
-- This Script contains the statement handler for the FunctionCallStatement.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local baseReg = self:compileExpression(statement.base, funcDepth, 1)[1];
    local retReg = self:allocRegister(false);
    local regs = {};
    local args = {};

    for i, expr in ipairs(statement.args) do
        if i == #statement.args and (expr.kind == AstKind.FunctionCallExpression or expr.kind == AstKind.PassSelfFunctionCallExpression or expr.kind == AstKind.VarargExpression) then
            local reg = self:compileExpression(expr, funcDepth, self.RETURN_ALL)[1];
            table.insert(args, Ast.FunctionCallExpression(
                self:unpack(scope),
                {self:register(scope, reg)}));
            table.insert(regs, reg);
        else
            local reg = self:compileExpression(expr, funcDepth, 1)[1];
            local argExpr = self:register(scope, reg);
            table.insert(args, argExpr);
            table.insert(regs, reg);
        end
    end

    self:addStatement(self:setRegister(scope, retReg, Ast.FunctionCallExpression(self:register(scope, baseReg), args)), {retReg}, {baseReg, unpack(regs)}, true);
    self:freeRegister(baseReg, false);
    self:freeRegister(retReg, false);
    for _, reg in ipairs(regs) do
        self:freeRegister(reg, false);
    end
end;



================================================
FILE: src/prometheus/compiler/statements/function_declaration.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- function_declaration.lua
--
-- This Script contains the statement handler for the FunctionDeclaration.

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local retReg = self:compileFunction(statement, funcDepth);
    if(#statement.indices > 0) then
        local tblReg;
        if statement.scope.isGlobal then
            tblReg = self:allocRegister(false);
            self:addStatement(self:setRegister(scope, tblReg, Ast.StringExpression(statement.scope:getVariableName(statement.id))), {tblReg}, {}, false);
            self:addStatement(self:setRegister(scope, tblReg, Ast.IndexExpression(self:env(scope), self:register(scope, tblReg))), {tblReg}, {tblReg}, true);
        else
            if self.scopeFunctionDepths[statement.scope] == funcDepth then
                if self:isUpvalue(statement.scope, statement.id) then
                    tblReg = self:allocRegister(false);
                    local reg = self:getVarRegister(statement.scope, statement.id, funcDepth);
                    self:addStatement(self:setRegister(scope, tblReg, self:getUpvalueMember(scope, self:register(scope, reg))), {tblReg}, {reg}, true);
                else
                    tblReg = self:getVarRegister(statement.scope, statement.id, funcDepth, retReg);
                end
            else
                tblReg = self:allocRegister(false);
                local upvalId = self:getUpvalueId(statement.scope, statement.id);
                scope:addReferenceToHigherScope(self.containerFuncScope, self.currentUpvaluesVar);
                self:addStatement(self:setRegister(scope, tblReg, self:getUpvalueMember(scope, Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.currentUpvaluesVar), Ast.NumberExpression(upvalId)))), {tblReg}, {}, true);
            end
        end

        for i = 1, #statement.indices - 1 do
            local index = statement.indices[i];
            local indexReg = self:compileExpression(Ast.StringExpression(index), funcDepth, 1)[1];
            local tblRegOld = tblReg;
            tblReg = self:allocRegister(false);
            self:addStatement(self:setRegister(scope, tblReg, Ast.IndexExpression(self:register(scope, tblRegOld), self:register(scope, indexReg))), {tblReg}, {tblReg, indexReg}, false);
            self:freeRegister(tblRegOld, false);
            self:freeRegister(indexReg, false);
        end

        local index = statement.indices[#statement.indices];
        local indexReg = self:compileExpression(Ast.StringExpression(index), funcDepth, 1)[1];
        self:addStatement(Ast.AssignmentStatement({
            Ast.AssignmentIndexing(self:register(scope, tblReg), self:register(scope, indexReg)),
        }, {
            self:register(scope, retReg),
        }), {}, {tblReg, indexReg, retReg}, true);
        self:freeRegister(indexReg, false);
        self:freeRegister(tblReg, false);
        self:freeRegister(retReg, false);

        return;
    end
    if statement.scope.isGlobal then
        local tmpReg = self:allocRegister(false);
        self:addStatement(self:setRegister(scope, tmpReg, Ast.StringExpression(statement.scope:getVariableName(statement.id))), {tmpReg}, {}, false);
        self:addStatement(Ast.AssignmentStatement({Ast.AssignmentIndexing(self:env(scope), self:register(scope, tmpReg))},
         {self:register(scope, retReg)}), {}, {tmpReg, retReg}, true);
        self:freeRegister(tmpReg, false);
    else
        if self.scopeFunctionDepths[statement.scope] == funcDepth then
            if self:isUpvalue(statement.scope, statement.id) then
                local reg = self:getVarRegister(statement.scope, statement.id, funcDepth);
                self:addStatement(self:setUpvalueMember(scope, self:register(scope, reg), self:register(scope, retReg)), {}, {reg, retReg}, true);
            else
                local reg = self:getVarRegister(statement.scope, statement.id, funcDepth, retReg);
                if reg ~= retReg then
                    self:addStatement(self:setRegister(scope, reg, self:register(scope, retReg)), {reg}, {retReg}, false);
                end
            end
        else
            local upvalId = self:getUpvalueId(statement.scope, statement.id);
            scope:addReferenceToHigherScope(self.containerFuncScope, self.currentUpvaluesVar);
            self:addStatement(self:setUpvalueMember(scope, Ast.IndexExpression(Ast.VariableExpression(self.containerFuncScope, self.currentUpvaluesVar), Ast.NumberExpression(upvalId)), self:register(scope, retReg)), {}, {retReg}, true);
        end
    end
    self:freeRegister(retReg, false);
end;



================================================
FILE: src/prometheus/compiler/statements/if_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- if_statement.lua
--
-- This Script contains the statement handler for the IfStatement.

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local conditionReg = self:compileExpression(statement.condition, funcDepth, 1)[1];
    local finalBlock = self:createBlock();

    local nextBlock
    if statement.elsebody or #statement.elseifs > 0 then
        nextBlock = self:createBlock();
    else
        nextBlock = finalBlock;
    end
    local innerBlock = self:createBlock();


    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(scope, conditionReg), Ast.NumberExpression(innerBlock.id)), Ast.NumberExpression(nextBlock.id))), {self.POS_REGISTER}, {conditionReg}, false);

    self:freeRegister(conditionReg, false);

    self:setActiveBlock(innerBlock);
    scope = innerBlock.scope
    self:compileBlock(statement.body, funcDepth);
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(finalBlock.id)), {self.POS_REGISTER}, {}, false);

    for i, eif in ipairs(statement.elseifs) do
        self:setActiveBlock(nextBlock);
        conditionReg = self:compileExpression(eif.condition, funcDepth, 1)[1];
        local innerBlock = self:createBlock();
        if statement.elsebody or i < #statement.elseifs then
            nextBlock = self:createBlock();
        else
            nextBlock = finalBlock;
        end
        local scope = self.activeBlock.scope;

        self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(scope, conditionReg), Ast.NumberExpression(innerBlock.id)), Ast.NumberExpression(nextBlock.id))), {self.POS_REGISTER}, {conditionReg}, false);


        self:freeRegister(conditionReg, false);

        self:setActiveBlock(innerBlock);
        scope = innerBlock.scope;
        self:compileBlock(eif.body, funcDepth);
        self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(finalBlock.id)), {self.POS_REGISTER}, {}, false);
    end

    if statement.elsebody then
        self:setActiveBlock(nextBlock);
        self:compileBlock(statement.elsebody, funcDepth);
        self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(finalBlock.id)), {self.POS_REGISTER}, {}, false);
    end

    self:setActiveBlock(finalBlock);
end;


================================================
FILE: src/prometheus/compiler/statements/local_function_declaration.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- local_function_declaration.lua
--
-- This Script contains the statement handler for the LocalFunctionDeclaration

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;

    if(self:isUpvalue(statement.scope, statement.id)) then
        local varReg = self:getVarRegister(statement.scope, statement.id, funcDepth, nil);
        scope:addReferenceToHigherScope(self.scope, self.allocUpvalFunction);
        self:addStatement(self:setRegister(scope, varReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {})), {varReg}, {}, false);
        local retReg = self:compileFunction(statement, funcDepth);
        self:addStatement(self:setUpvalueMember(scope, self:register(scope, varReg), self:register(scope, retReg)), {}, {varReg, retReg}, true);
        self:freeRegister(retReg, false);
    else
        local retReg = self:compileFunction(statement, funcDepth);
        local varReg = self:getVarRegister(statement.scope, statement.id, funcDepth, retReg);

        self:addStatement(self:copyRegisters(scope, {varReg}, {retReg}), {varReg}, {retReg}, false);
        self:freeRegister(retReg, false);
    end
end;



================================================
FILE: src/prometheus/compiler/statements/local_variable_declaration.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- local_variable_declaration.lua
--
-- This Script contains the statement handler for the LocalVariableDeclaration

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local exprregs = {};
    for i, expr in ipairs(statement.expressions) do
        if(i == #statement.expressions and #statement.ids > #statement.expressions) then
            local regs = self:compileExpression(expr, funcDepth, #statement.ids - #statement.expressions + 1);
            for i, reg in ipairs(regs) do
                table.insert(exprregs, reg);
            end
        else
            if statement.ids[i] or expr.kind == AstKind.FunctionCallExpression or expr.kind == AstKind.PassSelfFunctionCallExpression then
                local reg = self:compileExpression(expr, funcDepth, 1)[1];
                table.insert(exprregs, reg);
            end
        end
    end

    if #exprregs == 0 then
        for _=1, #statement.ids do
            table.insert(exprregs, self:compileExpression(Ast.NilExpression(), funcDepth, 1)[1]);
        end
    end

    for i, id in ipairs(statement.ids) do
        if(exprregs[i]) then
            if(self:isUpvalue(statement.scope, id)) then
                local varreg = self:getVarRegister(statement.scope, id, funcDepth);
                local varReg = self:getVarRegister(statement.scope, id, funcDepth, nil);
                scope:addReferenceToHigherScope(self.scope, self.allocUpvalFunction);
                self:addStatement(self:setRegister(scope, varReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.allocUpvalFunction), {})), {varReg}, {}, false);
                self:addStatement(self:setUpvalueMember(scope, self:register(scope, varReg), self:register(scope, exprregs[i])), {}, {varReg, exprregs[i]}, true);
                self:freeRegister(exprregs[i], false);
            else
                local varreg = self:getVarRegister(statement.scope, id, funcDepth, exprregs[i]);
                self:addStatement(self:copyRegisters(scope, {varreg}, {exprregs[i]}), {varreg}, {exprregs[i]}, false);
                self:freeRegister(exprregs[i], false);
            end
        end
    end

    if not self.scopeFunctionDepths[statement.scope] then
        self.scopeFunctionDepths[statement.scope] = funcDepth;
    end
end;



================================================
FILE: src/prometheus/compiler/statements/pass_self_function_call.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- pass_self_function_call.lua
--
-- This Script contains the statement handler for the PassSelfFunctionCallStatement.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local baseReg = self:compileExpression(statement.base, funcDepth, 1)[1];
    local tmpReg = self:allocRegister(false);
    local args = { self:register(scope, baseReg) };
    local regs = { baseReg };

    for i, expr in ipairs(statement.args) do
        if i == #statement.args and (expr.kind == AstKind.FunctionCallExpression or expr.kind == AstKind.PassSelfFunctionCallExpression or expr.kind == AstKind.VarargExpression) then
            local reg = self:compileExpression(expr, funcDepth, self.RETURN_ALL)[1];
            table.insert(args, Ast.FunctionCallExpression(
                self:unpack(scope),
                {self:register(scope, reg)}));
            table.insert(regs, reg);
        else
            local reg = self:compileExpression(expr, funcDepth, 1)[1];
            table.insert(args, self:register(scope, reg));
            table.insert(regs, reg);
        end
    end
    self:addStatement(self:setRegister(scope, tmpReg, Ast.StringExpression(statement.passSelfFunctionName)), {tmpReg}, {}, false);
    self:addStatement(self:setRegister(scope, tmpReg, Ast.IndexExpression(self:register(scope, baseReg), self:register(scope, tmpReg))), {tmpReg}, {tmpReg, baseReg}, false);

    self:addStatement(self:setRegister(scope, tmpReg, Ast.FunctionCallExpression(self:register(scope, tmpReg), args)), {tmpReg}, {tmpReg, unpack(regs)}, true);

    self:freeRegister(tmpReg, false);
    for _, reg in ipairs(regs) do
        self:freeRegister(reg, false);
    end
end;



================================================
FILE: src/prometheus/compiler/statements/repeat_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- repeat_statement.lua
--
-- This Script contains the statement handler for the RepeatStatement.

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local innerBlock = self:createBlock();
    local finalBlock = self:createBlock();
    statement.__start_block = innerBlock;
    statement.__final_block = finalBlock;

    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.NumberExpression(innerBlock.id)), {self.POS_REGISTER}, {}, false);
    self:setActiveBlock(innerBlock);

    for _, stat in ipairs(statement.body.statements) do
        self:compileStatement(stat, funcDepth);
    end;

    local scope = self.activeBlock.scope;
    local conditionReg = (self:compileExpression(statement.condition, funcDepth, 1))[1];
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(scope, conditionReg), Ast.NumberExpression(finalBlock.id)), Ast.NumberExpression(innerBlock.id))), { self.POS_REGISTER }, { conditionReg }, false);
    self:freeRegister(conditionReg, false);

    for id, _ in ipairs(statement.body.scope.variables) do
        local varReg = self:getVarRegister(statement.body.scope, id, funcDepth, nil);
        if self:isUpvalue(statement.body.scope, id) then
            scope:addReferenceToHigherScope(self.scope, self.freeUpvalueFunc);
            self:addStatement(self:setRegister(scope, varReg, Ast.FunctionCallExpression(Ast.VariableExpression(self.scope, self.freeUpvalueFunc), { self:register(scope, varReg) })), { varReg }, { varReg }, false);
        else
            self:addStatement(self:setRegister(scope, varReg, Ast.NilExpression()), { varReg }, {}, false);
        end;
        self:freeRegister(varReg, true);
    end;

    self:setActiveBlock(finalBlock);
end;


================================================
FILE: src/prometheus/compiler/statements/return.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- return.lua
--
-- This Script contains the statement handler for the ReturnStatement.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local entries = {};
    local regs = {};

    for i, expr in ipairs(statement.args) do
        if i == #statement.args and (expr.kind == AstKind.FunctionCallExpression or expr.kind == AstKind.PassSelfFunctionCallExpression or expr.kind == AstKind.VarargExpression) then
            local reg = self:compileExpression(expr, funcDepth, self.RETURN_ALL)[1];
            table.insert(entries, Ast.TableEntry(Ast.FunctionCallExpression(
                self:unpack(scope),
                {self:register(scope, reg)})));
            table.insert(regs, reg);
        else
            local reg = self:compileExpression(expr, funcDepth, 1)[1];
            table.insert(entries, Ast.TableEntry(self:register(scope, reg)));
            table.insert(regs, reg);
        end
    end

    for _, reg in ipairs(regs) do
        self:freeRegister(reg, false);
    end

    self:addStatement(self:setReturn(scope, Ast.TableConstructorExpression(entries)), {self.RETURN_REGISTER}, regs, false);
    self:addStatement(self:setPos(self.activeBlock.scope, nil), {self.POS_REGISTER}, {}, false);
    self.activeBlock.advanceToNextBlock = false;
end;


================================================
FILE: src/prometheus/compiler/statements/while_statement.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- while_statement.lua
--
-- This Script contains the statement handler for the WhileStatement

local Ast = require("prometheus.ast");

return function(self, statement, funcDepth)
    local scope = self.activeBlock.scope;
    local innerBlock = self:createBlock();
    local finalBlock = self:createBlock();
    local checkBlock = self:createBlock();

    statement.__start_block = checkBlock;
    statement.__final_block = finalBlock;

    self:addStatement(self:setPos(scope, checkBlock.id), {self.POS_REGISTER}, {}, false);

    self:setActiveBlock(checkBlock);
    scope = self.activeBlock.scope;
    local conditionReg = self:compileExpression(statement.condition, funcDepth, 1)[1];
    self:addStatement(self:setRegister(scope, self.POS_REGISTER, Ast.OrExpression(Ast.AndExpression(self:register(scope, conditionReg), Ast.NumberExpression(innerBlock.id)), Ast.NumberExpression(finalBlock.id))), {self.POS_REGISTER}, {conditionReg}, false);
    self:freeRegister(conditionReg, false);

    self:setActiveBlock(innerBlock);
    local scope = self.activeBlock.scope;
    self:compileBlock(statement.body, funcDepth);
    self:addStatement(self:setPos(scope, checkBlock.id), {self.POS_REGISTER}, {}, false);
    self:setActiveBlock(finalBlock);
end;


================================================
FILE: src/prometheus/compiler/statements.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- statements.lua
--
-- This Script contains the statement handlers: exports handler table keyed by AstKind.

local Ast = require("prometheus.ast");
local AstKind = Ast.AstKind;

local handlers = {};
local statements = "prometheus.compiler.statements.";
local function requireStatement(name)
    return require(statements .. name);
end

handlers[AstKind.ReturnStatement] = requireStatement("return");
handlers[AstKind.LocalVariableDeclaration] = requireStatement("local_variable_declaration");
handlers[AstKind.FunctionCallStatement] = requireStatement("function_call");
handlers[AstKind.PassSelfFunctionCallStatement] = requireStatement("pass_self_function_call");
handlers[AstKind.LocalFunctionDeclaration] = requireStatement("local_function_declaration");
handlers[AstKind.FunctionDeclaration] = requireStatement("function_declaration");
handlers[AstKind.AssignmentStatement] = requireStatement("assignment");
handlers[AstKind.IfStatement] = requireStatement("if_statement");
handlers[AstKind.DoStatement] = requireStatement("do_statement");
handlers[AstKind.WhileStatement] = requireStatement("while_statement");
handlers[AstKind.RepeatStatement] = requireStatement("repeat_statement");
handlers[AstKind.ForStatement] = requireStatement("for_statement");
handlers[AstKind.ForInStatement] = requireStatement("for_in_statement");
handlers[AstKind.BreakStatement] = requireStatement("break_statement");
handlers[AstKind.ContinueStatement] = requireStatement("continue_statement");

-- Compound statements share one handler
local compoundHandler = requireStatement("compound");
handlers[AstKind.CompoundAddStatement] = compoundHandler;
handlers[AstKind.CompoundSubStatement] = compoundHandler;
handlers[AstKind.CompoundMulStatement] = compoundHandler;
handlers[AstKind.CompoundDivStatement] = compoundHandler;
handlers[AstKind.CompoundModStatement] = compoundHandler;
handlers[AstKind.CompoundPowStatement] = compoundHandler;
handlers[AstKind.CompoundConcatStatement] = compoundHandler;

return handlers;



================================================
FILE: src/prometheus/compiler/upvalue.lua
================================================
-- This Script is Part of the Prometheus Obfuscator by Levno_710
--
-- upvalue.lua
--
-- This Script contains the upvalue and GC management for the compiler.

local Ast = require("prometheus.ast");
local Scope = require("prometheus.scope");
local util = require("prometheus.util");

local unpack = unpack or table.unpack;

return function(Compiler)
    function Compiler:createUpvaluesGcFunc()
        local scope = Scope:new(self.scope);
        local selfVar = scope:addVariable();

        local iteratorVar = scope:addVariable();
        local valueVar = scope:addVariable();

        local whileScope = Scope:new(scope);
        whileScope:addReferenceToHigherScope(self.scope, self.upvaluesReferenceCountsTable, 3);
        whileScope:addReferenceToHigherScope(scope, valueVar, 3);
        whileScope:addReferenceToHigherScope(scope, iteratorVar, 3);

        local ifScope = Scope:new(whileScope);
        ifScope:addReferenceToHigherScope(self.scope, self.upvaluesReferenceCountsTable, 1);
        ifScope:addReferenceToHigherScope(self.scope, self.upvaluesTable, 1);

        return Ast.FunctionLiteralExpression({Ast.VariableExpression(scope, selfVar)}, Ast.Block({
            Ast.LocalVariableDeclaration(scope, {iteratorVar, valueVar}, {Ast.NumberExpression(1), Ast.IndexExpression(Ast.VariableExpression(scope, selfVar), Ast.NumberExpression(1))}),
            Ast.WhileStatement(Ast.Block({
                Ast.AssignmentStatement({
                    Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, valueVar)),
                    Ast.AssignmentVariable(scope, iteratorVar),
                }, {
                    Ast.SubExpression(Ast.IndexExpression(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, valueVar)), Ast.NumberExpression(1)),
                    Ast.AddExpression(unpack(util.shuffle{Ast.VariableExpression(scope, iteratorVar), Ast.NumberExpression(1)})),
                }),
                Ast.IfStatement(Ast.EqualsExpression(unpack(util.shuffle{Ast.IndexExpression(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, valueVar)), Ast.NumberExpression(0)})), Ast.Block({
                    Ast.AssignmentStatement({
                        Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, valueVar)),
                        Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesTable), Ast.VariableExpression(scope, valueVar)),
                    }, {
                        Ast.NilExpression(),
                        Ast.NilExpression(),
                    })
                }, ifScope), {}, nil),
                Ast.AssignmentStatement({
                    Ast.AssignmentVariable(scope, valueVar),
                }, {
                    Ast.IndexExpression(Ast.VariableExpression(scope, selfVar), Ast.VariableExpression(scope, iteratorVar)),
                }),
            }, whileScope), Ast.VariableExpression(scope, valueVar), scope);
        }, scope));
    end

    function Compiler:createFreeUpvalueFunc()
        local scope = Scope:new(self.scope);
        local argVar = scope:addVariable();
        local ifScope = Scope:new(scope);
        ifScope:addReferenceToHigherScope(scope, argVar, 3);
        scope:addReferenceToHigherScope(self.scope, self.upvaluesReferenceCountsTable, 2);
        return Ast.FunctionLiteralExpression({Ast.VariableExpression(scope, argVar)}, Ast.Block({
            Ast.AssignmentStatement({
                Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, argVar))
            }, {
                Ast.SubExpression(Ast.IndexExpression(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, argVar)), Ast.NumberExpression(1));
            }),
            Ast.IfStatement(Ast.EqualsExpression(unpack(util.shuffle{Ast.IndexExpression(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, argVar)), Ast.NumberExpression(0)})), Ast.Block({
                Ast.AssignmentStatement({
                    Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesReferenceCountsTable), Ast.VariableExpression(scope, argVar)),
                    Ast.AssignmentIndexing(Ast.VariableExpression(self.scope, self.upvaluesTable), Ast.VariableExpression(scope, argVar)),
                }, {
                    Ast.NilExpression(),
                
Download .txt
gitextract_h0mah7x0/

├── .editorconfig
├── .gitattributes
├── .gitbook.yaml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   └── workflows/
│       ├── Build.yml
│       └── Test.yml
├── .gitignore
├── LICENSE
├── benchmark.lua
├── cli.lua
├── doc/
│   ├── README.md
│   ├── SUMMARY.md
│   ├── advanced/
│   │   └── using-prometheus-in-your-lua-application.md
│   ├── getting-started/
│   │   ├── command-line-options.md
│   │   ├── installation.md
│   │   ├── obfuscating-your-first-script.md
│   │   ├── presets.md
│   │   ├── the-config-object.md
│   │   └── writing-a-custom-config-file.md
│   └── steps/
│       ├── anti-tamper.md
│       ├── constantarray.md
│       ├── encryptstrings.md
│       ├── proxifylocals.md
│       ├── splitstrings.md
│       ├── vmify.md
│       └── wrapinfunction.md
├── prometheus-main.lua
├── readme.md
├── src/
│   ├── cli.lua
│   ├── colors.lua
│   ├── highlightlua.lua
│   ├── logger.lua
│   ├── presets.lua
│   ├── prometheus/
│   │   ├── ast.lua
│   │   ├── compiler/
│   │   │   ├── block.lua
│   │   │   ├── compile_core.lua
│   │   │   ├── compile_top.lua
│   │   │   ├── compiler.lua
│   │   │   ├── constants.lua
│   │   │   ├── emit.lua
│   │   │   ├── expressions/
│   │   │   │   ├── and.lua
│   │   │   │   ├── binary.lua
│   │   │   │   ├── boolean.lua
│   │   │   │   ├── function_call.lua
│   │   │   │   ├── function_literal.lua
│   │   │   │   ├── index.lua
│   │   │   │   ├── len.lua
│   │   │   │   ├── negate.lua
│   │   │   │   ├── nil.lua
│   │   │   │   ├── not.lua
│   │   │   │   ├── number.lua
│   │   │   │   ├── or.lua
│   │   │   │   ├── pass_self_function_call.lua
│   │   │   │   ├── string.lua
│   │   │   │   ├── table_constructor.lua
│   │   │   │   ├── vararg.lua
│   │   │   │   └── variable.lua
│   │   │   ├── expressions.lua
│   │   │   ├── register.lua
│   │   │   ├── statements/
│   │   │   │   ├── assignment.lua
│   │   │   │   ├── break_statement.lua
│   │   │   │   ├── compound.lua
│   │   │   │   ├── continue_statement.lua
│   │   │   │   ├── do_statement.lua
│   │   │   │   ├── for_in_statement.lua
│   │   │   │   ├── for_statement.lua
│   │   │   │   ├── function_call.lua
│   │   │   │   ├── function_declaration.lua
│   │   │   │   ├── if_statement.lua
│   │   │   │   ├── local_function_declaration.lua
│   │   │   │   ├── local_variable_declaration.lua
│   │   │   │   ├── pass_self_function_call.lua
│   │   │   │   ├── repeat_statement.lua
│   │   │   │   ├── return.lua
│   │   │   │   └── while_statement.lua
│   │   │   ├── statements.lua
│   │   │   └── upvalue.lua
│   │   ├── enums.lua
│   │   ├── namegenerators/
│   │   │   ├── Il.lua
│   │   │   ├── confuse.lua
│   │   │   ├── mangled.lua
│   │   │   ├── mangled_shuffled.lua
│   │   │   └── number.lua
│   │   ├── namegenerators.lua
│   │   ├── parser.lua
│   │   ├── pipeline.lua
│   │   ├── randomLiterals.lua
│   │   ├── randomStrings.lua
│   │   ├── scope.lua
│   │   ├── step.lua
│   │   ├── steps/
│   │   │   ├── AddVararg.lua
│   │   │   ├── AntiTamper.lua
│   │   │   ├── ConstantArray.lua
│   │   │   ├── EncryptStrings.lua
│   │   │   ├── NumbersToExpressions.lua
│   │   │   ├── ProxifyLocals.lua
│   │   │   ├── SplitStrings.lua
│   │   │   ├── Vmify.lua
│   │   │   ├── Watermark.lua
│   │   │   ├── WatermarkCheck.lua
│   │   │   └── WrapInFunction.lua
│   │   ├── steps.lua
│   │   ├── tokenizer.lua
│   │   ├── unparser.lua
│   │   ├── util.lua
│   │   └── visitast.lua
│   └── prometheus.lua
├── tests/
│   ├── ambiguous-call.lua
│   ├── closures.lua
│   ├── coroutines.lua
│   ├── fibonacci.lua
│   ├── iterator.lua
│   ├── loops.lua
│   ├── matrix.lua
│   ├── metatables.lua
│   ├── multi-return.lua
│   ├── primes.lua
│   ├── repeat-test.lua
│   ├── state-machine.lua
│   ├── strings.lua
│   ├── syntax.lua
│   ├── table-merge.lua
│   └── upvalues.lua
└── tests.lua
Condensed preview — 124 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (436K chars).
[
  {
    "path": ".editorconfig",
    "chars": 60,
    "preview": "[*.lua]\nindent_style = tab\nindent_size = 4\nend_of_line = lf\n"
  },
  {
    "path": ".gitattributes",
    "chars": 29,
    "preview": "*.lua text=auto\n*.lua eol=lf\n"
  },
  {
    "path": ".gitbook.yaml",
    "chars": 13,
    "preview": "root: ./doc/\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 629,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"[BUG]\"\nlabels: bug\nassignees: ''\n\n---\n\n**Describe"
  },
  {
    "path": ".github/workflows/Build.yml",
    "chars": 1763,
    "preview": "name: Build\n\non:\n  push:\n    branches:\n      main\n\njobs:\n  build:\n    runs-on: windows-latest # gh-actions-lua doesn't w"
  },
  {
    "path": ".github/workflows/Test.yml",
    "chars": 373,
    "preview": "name: Test\non:  \n  push:\n  pull_request:\n    branches:\n      - master\n\njobs:\n  test-linux:\n    runs-on: ubuntu-latest\n  "
  },
  {
    "path": ".gitignore",
    "chars": 210,
    "preview": "# Ignore Vscode Folder\n.vscode\n\n# Ignore Lua Implementation and srlua\nlua51.dll\nluajit.exe\nsrlua\nluajit\nbuildnotes.txt\ns"
  },
  {
    "path": "LICENSE",
    "chars": 5376,
    "preview": "PROMETHEUS LICENSE\nCopyright (c) 2025 Elias Oelschner\nhttps://github.com/prometheus-lua/Prometheus\n\nPermission is hereby"
  },
  {
    "path": "benchmark.lua",
    "chars": 732,
    "preview": "print(\"PROMETHEUS Benchmark\")\nprint(\"Based On IronBrew Benchmark\")\nlocal Iterations = 100000\nprint(\"Iterations: \" .. tos"
  },
  {
    "path": "cli.lua",
    "chars": 388,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- cli.lua\n--\n-- This Script contains the Code for t"
  },
  {
    "path": "doc/README.md",
    "chars": 344,
    "preview": "---\ndescription: Prometheus is an Lua Obfuscator, that is written in pure Lua.\n---\n\n# Prometheus\n\nPrometheus can obfusca"
  },
  {
    "path": "doc/SUMMARY.md",
    "chars": 850,
    "preview": "# Table of contents\n\n* [Prometheus](README.md)\n\n## Getting Started\n\n* [Installation](getting-started/installation.md)\n* "
  },
  {
    "path": "doc/advanced/using-prometheus-in-your-lua-application.md",
    "chars": 1115,
    "preview": "# Using Prometheus in your Lua Application\n\nPrometheus can also be used as a library for your custom Lua Applications in"
  },
  {
    "path": "doc/getting-started/command-line-options.md",
    "chars": 966,
    "preview": "# Command Line Options\n\nThe following table provides a brief overview over the command line options:\n\n| Option          "
  },
  {
    "path": "doc/getting-started/installation.md",
    "chars": 458,
    "preview": "# Installation\n\nTo install Prometheus, simply clone the Github Repository using:\n\n```batch\ngit clone \"https://github.com"
  },
  {
    "path": "doc/getting-started/obfuscating-your-first-script.md",
    "chars": 1779,
    "preview": "# Obfuscating your first script\n\nNow that you have downloaded and Prometheus, you probably wonder how to use it. In this"
  },
  {
    "path": "doc/getting-started/presets.md",
    "chars": 250,
    "preview": "# Presets\n\nThe following table provides an overview over the presets\n\n| name   | size   | speed   |\n| ------ | ------ | "
  },
  {
    "path": "doc/getting-started/the-config-object.md",
    "chars": 2418,
    "preview": "# The Config Object\n\nPrometheus takes a configuration object. In this object there can be many properties applied.   \\\nT"
  },
  {
    "path": "doc/getting-started/writing-a-custom-config-file.md",
    "chars": 2196,
    "preview": "# Writing a custom Config File\n\nConfiguration Files for Prometheus are just lua modules, that return a single object, wh"
  },
  {
    "path": "doc/steps/anti-tamper.md",
    "chars": 503,
    "preview": "---\ndescription: This step provides an obfuscation step, that breaks the script, when someone tries to tamper with it.\n-"
  },
  {
    "path": "doc/steps/constantarray.md",
    "chars": 2637,
    "preview": "---\ndescription: >-\n  This Step will Extract all Constants and put them into an Array at the\n  beginning of the script\n-"
  },
  {
    "path": "doc/steps/encryptstrings.md",
    "chars": 1882,
    "preview": "---\ndescription: This Step will encrypt all String constants in your code\n---\n\n# EncryptStrings\n\n## Settings\n\nNone\n\n## E"
  },
  {
    "path": "doc/steps/proxifylocals.md",
    "chars": 1016,
    "preview": "---\ndescription: This Step wraps all locals into Proxy Objects\n---\n\n# ProxifyLocals\n\n### Settings\n\n| Name        | type "
  },
  {
    "path": "doc/steps/splitstrings.md",
    "chars": 2562,
    "preview": "---\ndescription: This Step splits Strings to a specific or random length\n---\n\n# SplitStrings\n\n### Settings\n\n| Name      "
  },
  {
    "path": "doc/steps/vmify.md",
    "chars": 109,
    "preview": "---\ndescription: This Step will Compile your script and run it within a VM.\n---\n\n# Vmify\n\n### Settings\n\nNone\n"
  },
  {
    "path": "doc/steps/wrapinfunction.md",
    "chars": 470,
    "preview": "---\ndescription: This Step Wraps the Entire Script into a Function\n---\n\n# WrapInFunction\n\n### Settings\n\n| Name       | t"
  },
  {
    "path": "prometheus-main.lua",
    "chars": 14,
    "preview": "require(\"cli\")"
  },
  {
    "path": "readme.md",
    "chars": 3071,
    "preview": "# :fire: Prometheus Lua Obfuscator\n[![Test](https://github.com/prometheus-lua/Prometheus/actions/workflows/Test.yml/badg"
  },
  {
    "path": "src/cli.lua",
    "chars": 4977,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- cli.lua\n--\n-- This Script contains the Code for t"
  },
  {
    "path": "src/colors.lua",
    "chars": 1126,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- colors.lua\n--\n-- This Script provides a simple me"
  },
  {
    "path": "src/highlightlua.lua",
    "chars": 1991,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- highlightlua.lua\n--\n-- This Script provides a sim"
  },
  {
    "path": "src/logger.lua",
    "chars": 1328,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- logger.lua\n--\n-- This Script provides a Logger fo"
  },
  {
    "path": "src/presets.lua",
    "chars": 2633,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- presets.lua\n--\n-- This Script provides the predef"
  },
  {
    "path": "src/prometheus/ast.lua",
    "chars": 17123,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- ast.lua\n--\n-- This Script provides the Abstract S"
  },
  {
    "path": "src/prometheus/compiler/block.lua",
    "chars": 1222,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- block.lua\n--\n-- Block management for the compiler"
  },
  {
    "path": "src/prometheus/compiler/compile_core.lua",
    "chars": 1236,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- compile_core.lua\n-- This Script contains the core"
  },
  {
    "path": "src/prometheus/compiler/compile_top.lua",
    "chars": 9404,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- compile_top.lua\n--\n-- This Script contains the co"
  },
  {
    "path": "src/prometheus/compiler/compiler.lua",
    "chars": 16971,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- compiler.lua\n--\n-- This Script is the main compil"
  },
  {
    "path": "src/prometheus/compiler/constants.lua",
    "chars": 213,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- constants.lua\n--\n-- This Script contains the comp"
  },
  {
    "path": "src/prometheus/compiler/emit.lua",
    "chars": 13079,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- emit.lua\n--\n-- This Script contains the container"
  },
  {
    "path": "src/prometheus/compiler/expressions/and.lua",
    "chars": 2666,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- and.lua\n--\n-- This Script contains the expression"
  },
  {
    "path": "src/prometheus/compiler/expressions/binary.lua",
    "chars": 1088,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- binary.lua\n--\n-- This Script contains the express"
  },
  {
    "path": "src/prometheus/compiler/expressions/boolean.lua",
    "chars": 1889,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- boolean.lua\n--\n-- This Script contains the expres"
  },
  {
    "path": "src/prometheus/compiler/expressions/function_call.lua",
    "chars": 2608,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- function_call.lua\n--\n-- This Script contains the "
  },
  {
    "path": "src/prometheus/compiler/expressions/function_literal.lua",
    "chars": 664,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- function_literal.lua\n--\n-- This Script contains t"
  },
  {
    "path": "src/prometheus/compiler/expressions/index.lua",
    "chars": 1032,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- index.lua\n--\n-- This Script contains the expressi"
  },
  {
    "path": "src/prometheus/compiler/expressions/len.lua",
    "chars": 840,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- len.lua\n--\n-- This Script contains the expression"
  },
  {
    "path": "src/prometheus/compiler/expressions/negate.lua",
    "chars": 850,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- negate.lua\n--\n-- This Script contains the express"
  },
  {
    "path": "src/prometheus/compiler/expressions/nil.lua",
    "chars": 517,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- nil.lua\n--\n-- This Script contains the expression"
  },
  {
    "path": "src/prometheus/compiler/expressions/not.lua",
    "chars": 842,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- not.lua\n--\n-- This Script contains the expression"
  },
  {
    "path": "src/prometheus/compiler/expressions/number.lua",
    "chars": 702,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- number.lua\n--\n-- This Script contains the express"
  },
  {
    "path": "src/prometheus/compiler/expressions/or.lua",
    "chars": 2671,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- or.lua\n--\n-- This Script contains the expression "
  },
  {
    "path": "src/prometheus/compiler/expressions/pass_self_function_call.lua",
    "chars": 3320,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- pass_self_function_call.lua\n--\n-- This Script con"
  },
  {
    "path": "src/prometheus/compiler/expressions/string.lua",
    "chars": 705,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- string.lua\n--\n-- This Script contains the express"
  },
  {
    "path": "src/prometheus/compiler/expressions/table_constructor.lua",
    "chars": 2400,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- table_constructor.lua\n--\n-- This Script contains "
  },
  {
    "path": "src/prometheus/compiler/expressions/vararg.lua",
    "chars": 687,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- vararg.lua\n--\n-- This Script contains the express"
  },
  {
    "path": "src/prometheus/compiler/expressions/variable.lua",
    "chars": 2390,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- variable.lua\n--\n-- This Script contains the expre"
  },
  {
    "path": "src/prometheus/compiler/expressions.lua",
    "chars": 2316,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- expressions.lua\n--\n-- This Script contains the ex"
  },
  {
    "path": "src/prometheus/compiler/register.lua",
    "chars": 9210,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- register.lua\n--\n-- This Script contains the regis"
  },
  {
    "path": "src/prometheus/compiler/statements/assignment.lua",
    "chars": 4614,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- assignment.lua\n--\n-- This Script contains the sta"
  },
  {
    "path": "src/prometheus/compiler/statements/break_statement.lua",
    "chars": 1480,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- break_statement.lua\n--\n-- This Script contains th"
  },
  {
    "path": "src/prometheus/compiler/statements/compound.lua",
    "chars": 3630,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- compound.lua\n--\n-- This Script contains the state"
  },
  {
    "path": "src/prometheus/compiler/statements/continue_statement.lua",
    "chars": 1483,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- continue_statement.lua\n--\n-- This Script contains"
  },
  {
    "path": "src/prometheus/compiler/statements/do_statement.lua",
    "chars": 259,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- do_statement.lua\n--\n-- This Script contains the s"
  },
  {
    "path": "src/prometheus/compiler/statements/for_in_statement.lua",
    "chars": 4022,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- for_in_statement.lua\n--\n-- This Script contains t"
  },
  {
    "path": "src/prometheus/compiler/statements/for_statement.lua",
    "chars": 6694,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- for_statement.lua\n--\n-- This Script contains the "
  },
  {
    "path": "src/prometheus/compiler/statements/function_call.lua",
    "chars": 1547,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- function_call.lua\n--\n-- This Script contains the "
  },
  {
    "path": "src/prometheus/compiler/statements/function_declaration.lua",
    "chars": 4745,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- function_declaration.lua\n--\n-- This Script contai"
  },
  {
    "path": "src/prometheus/compiler/statements/if_statement.lua",
    "chars": 2513,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- if_statement.lua\n--\n-- This Script contains the s"
  },
  {
    "path": "src/prometheus/compiler/statements/local_function_declaration.lua",
    "chars": 1296,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- local_function_declaration.lua\n--\n-- This Script "
  },
  {
    "path": "src/prometheus/compiler/statements/local_variable_declaration.lua",
    "chars": 2457,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- local_variable_declaration.lua\n--\n-- This Script "
  },
  {
    "path": "src/prometheus/compiler/statements/pass_self_function_call.lua",
    "chars": 1833,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- pass_self_function_call.lua\n--\n-- This Script con"
  },
  {
    "path": "src/prometheus/compiler/statements/repeat_statement.lua",
    "chars": 1913,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- repeat_statement.lua\n--\n-- This Script contains t"
  },
  {
    "path": "src/prometheus/compiler/statements/return.lua",
    "chars": 1446,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- return.lua\n--\n-- This Script contains the stateme"
  },
  {
    "path": "src/prometheus/compiler/statements/while_statement.lua",
    "chars": 1320,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- while_statement.lua\n--\n-- This Script contains th"
  },
  {
    "path": "src/prometheus/compiler/statements.lua",
    "chars": 2074,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- statements.lua\n--\n-- This Script contains the sta"
  },
  {
    "path": "src/prometheus/compiler/upvalue.lua",
    "chars": 10541,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- upvalue.lua\n--\n-- This Script contains the upvalu"
  },
  {
    "path": "src/prometheus/enums.lua",
    "chars": 2677,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- enums.lua\n--\n-- This Script provides some enums u"
  },
  {
    "path": "src/prometheus/namegenerators/Il.lua",
    "chars": 938,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- namegenerators/il.lua\n--\n-- This Script provides "
  },
  {
    "path": "src/prometheus/namegenerators/confuse.lua",
    "chars": 2614,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- namegenerators/confuse.lua\n--\n-- This Script prov"
  },
  {
    "path": "src/prometheus/namegenerators/mangled.lua",
    "chars": 697,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- namegenerators/mangled.lua\n--\n-- This Script prov"
  },
  {
    "path": "src/prometheus/namegenerators/mangled_shuffled.lua",
    "chars": 898,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- namegenerators/mangled_shuffled.lua\n--\n-- This Sc"
  },
  {
    "path": "src/prometheus/namegenerators/number.lua",
    "chars": 280,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- namegenerators/number.lua\n--\n-- This Script provi"
  },
  {
    "path": "src/prometheus/namegenerators.lua",
    "chars": 466,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- namegenerators.lua\n--\n-- This Script provides a c"
  },
  {
    "path": "src/prometheus/parser.lua",
    "chars": 27851,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- parser.lua\n-- Overview:\n-- This Script provides a"
  },
  {
    "path": "src/prometheus/pipeline.lua",
    "chars": 7920,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- pipeline.lua\n--\n-- This Script provides a configu"
  },
  {
    "path": "src/prometheus/randomLiterals.lua",
    "chars": 1136,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- randomLiterals.lua\n--\n-- This Script provides a l"
  },
  {
    "path": "src/prometheus/randomStrings.lua",
    "chars": 826,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- randomStrings.lua\n--\n-- This Script provides a li"
  },
  {
    "path": "src/prometheus/scope.lua",
    "chars": 8773,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- scope.lua\n--\n-- This Script provides a class for "
  },
  {
    "path": "src/prometheus/step.lua",
    "chars": 2127,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- step.lua\n--\n-- This Script provides the base clas"
  },
  {
    "path": "src/prometheus/steps/AddVararg.lua",
    "chars": 982,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- AddVararg.lua\n--\n-- This Script provides a Simple"
  },
  {
    "path": "src/prometheus/steps/AntiTamper.lua",
    "chars": 7703,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- AntiTamper.lua\n--\n-- This Script provides an Obfu"
  },
  {
    "path": "src/prometheus/steps/ConstantArray.lua",
    "chars": 23763,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- ConstantArray.lua\n--\n-- This Script provides a Si"
  },
  {
    "path": "src/prometheus/steps/EncryptStrings.lua",
    "chars": 6995,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- EncryptStrings.lua\n--\n-- This Script provides a S"
  },
  {
    "path": "src/prometheus/steps/NumbersToExpressions.lua",
    "chars": 4779,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- NumbersToExpressions.lua\n--\n-- This Script provid"
  },
  {
    "path": "src/prometheus/steps/ProxifyLocals.lua",
    "chars": 11879,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- ProxifyLocals.lua\n--\n-- This Script provides a Ob"
  },
  {
    "path": "src/prometheus/steps/SplitStrings.lua",
    "chars": 10472,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- SplitStrings.lua\n--\n-- This Script provides a Sim"
  },
  {
    "path": "src/prometheus/steps/Vmify.lua",
    "chars": 874,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- Vmify.lua\n--\n-- This Script provides a Complex Ob"
  },
  {
    "path": "src/prometheus/steps/Watermark.lua",
    "chars": 1766,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- Watermark.lua\n--\n-- This Script provides a Step t"
  },
  {
    "path": "src/prometheus/steps/WatermarkCheck.lua",
    "chars": 1697,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- WatermarkCheck.lua\n--\n-- This Script provides a S"
  },
  {
    "path": "src/prometheus/steps/WrapInFunction.lua",
    "chars": 1091,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- WrapInFunction.lua\n--\n-- This Script provides a S"
  },
  {
    "path": "src/prometheus/steps.lua",
    "chars": 742,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- steps.lua\n--\n-- This Script provides a collection"
  },
  {
    "path": "src/prometheus/tokenizer.lua",
    "chars": 15576,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- tokenizer.lua\n-- Overview:\n-- This Script provide"
  },
  {
    "path": "src/prometheus/unparser.lua",
    "chars": 23514,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- unparser.lua\n-- Overview:\n-- This Script provides"
  },
  {
    "path": "src/prometheus/util.lua",
    "chars": 2072,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- util.lua\n--\n-- This Script provides some utility "
  },
  {
    "path": "src/prometheus/visitast.lua",
    "chars": 9146,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- visitast.lua\n--\n-- This Script provides a utility"
  },
  {
    "path": "src/prometheus.lua",
    "chars": 1699,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- prometheus.lua\n--\n-- This file is the entrypoint "
  },
  {
    "path": "tests/ambiguous-call.lua",
    "chars": 326,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- ambiguous-call.lua\n--\n-- This Test demonstrates a r"
  },
  {
    "path": "tests/closures.lua",
    "chars": 297,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- closures.lua\n--\n-- This Test demonstrates determini"
  },
  {
    "path": "tests/coroutines.lua",
    "chars": 520,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- coroutines.lua\n--\n-- This Test demonstrates a deter"
  },
  {
    "path": "tests/fibonacci.lua",
    "chars": 284,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- fibonacci.lua\n--\n-- This Test demonstrates a simple"
  },
  {
    "path": "tests/iterator.lua",
    "chars": 444,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- iterator.lua\n--\n-- This Test demonstrates a custom "
  },
  {
    "path": "tests/loops.lua",
    "chars": 3335,
    "preview": "--============================================================\n-- Iteration Test Suite\n-- Target: General purpose\n-- Aut"
  },
  {
    "path": "tests/matrix.lua",
    "chars": 599,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- matrix.lua\n--\n-- This Test demonstrates a determini"
  },
  {
    "path": "tests/metatables.lua",
    "chars": 689,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- metatables.lua\n--\n-- This Test demonstrates a metam"
  },
  {
    "path": "tests/multi-return.lua",
    "chars": 2651,
    "preview": "--============================================================\n-- Multi-Return Test Suite\n-- Target: Compiler\n-- Author:"
  },
  {
    "path": "tests/primes.lua",
    "chars": 459,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- primes.lua\n--\n-- This Test demonstrates a determini"
  },
  {
    "path": "tests/repeat-test.lua",
    "chars": 5579,
    "preview": "--============================================================\n-- Repeat-Until Semantics Test Suite\n-- Target: Vmify\n-- "
  },
  {
    "path": "tests/state-machine.lua",
    "chars": 826,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- state-machine.lua\n--\n-- This Test demonstrates a "
  },
  {
    "path": "tests/strings.lua",
    "chars": 499,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- strings.lua\n--\n-- This Test demonstrates a determin"
  },
  {
    "path": "tests/syntax.lua",
    "chars": 987,
    "preview": "--============================================================\n-- Syntax Test Suite\n-- Target: Unparser\n-- Author: Spinn"
  },
  {
    "path": "tests/table-merge.lua",
    "chars": 644,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- table-merge.lua\n--\n-- This Test demonstrates a dete"
  },
  {
    "path": "tests/upvalues.lua",
    "chars": 1656,
    "preview": "-- This Test is Part of the Prometheus Obfuscator by Levno_710\n--\n-- upvalues.lua\n--\n-- This Test demonstrates a determi"
  },
  {
    "path": "tests.lua",
    "chars": 4786,
    "preview": "-- This Script is Part of the Prometheus Obfuscator by Levno_710\n--\n-- tests.lua\n--\n-- This Script will Perform tests us"
  }
]

About this extraction

This page contains the full source code of the prometheus-lua/Prometheus GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 124 files (391.9 KB), approximately 102.0k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!