- Joined
- Mar 14, 2019
- Messages
- 8
Recently, I’ve been working on a long-term refactoring project: JassHelper Remake.
The performance of the legacy JassHelper is honestly quite poor. Even without using T, compiling my roughly 7 million characters / 150,000 lines of JASS code with the old JassHelper takes about 2–3 minutes per build.
I searched extensively but couldn’t find any modern replacement JassHelper compiler, and I didn’t dig into the original JassHelper source code either. Of course, Lua can be used for map scripting—and it’s not necessarily harder than JASS—but I’ve already built too many existing libraries around JASS, so migrating away from it isn’t realistic for me.
The goal of this project is to reimplement the classic JassHelper using modern C++20, compiling vJASS / Zinc into standard JASS (war3map.j), while addressing the old tool’s shortcomings in parallel compilation, maintainability, and static analysis.
Core positioning:
Compatible with both vJASS and Zinc syntax, supporting syntax mode switching within the same file.
Compilation architecture:
Preprocessor → Lexer → Parser → AST → SymbolTable → CodeGen, with a fully modular pipeline.
Performance direction:
File-level multithreaded parsing + multi-phase parallel validation.
At the moment, performance is already very impressive: JassHelper takes 2–3 minutes to compile my project once, while my compiler finishes the same project in about 1 second.
Code generation:
Implements struct-to-array modeling, method dispatch, a function pointer system, and main/config template injection.
Engineering setup:
Built with CMake + MSBuild, directly buildable on Windows and integrable into the map import workflow.
Key feature: Desync static analysis (annotation-driven)
This is a highly practical feature. During development, we generally understand how desync occurs—but it’s nearly impossible to eliminate it completely. Once it happens, tracking down the root cause can take weeks and hundreds of test games. (Of course, this is unlikely to happen with T.)
My approach is based on a taint-propagation algorithm:
If you believe the compiler warning is a false positive, you can write:
//@ desync safe
This causes the next line to skip desync detection.
The compiler also supports set null detection. As we all know, in JASS, if you don’t set a handle variable to null at the end of a function, that handle will never be properly released.
Additionally, several modern language features are supported, such as:
If you’re working on Warcraft 3 map development or JASS/vJASS toolchains, feel free to share test cases and edge-case syntax scenarios—let’s refine this compiler together and make it more robust.
PS: The compiler currently does not support anything related to T—not even map regions, camera objects, global variables, or JASS written directly in the editor. I may not plan to support T compatibility in the future either.
The performance of the legacy JassHelper is honestly quite poor. Even without using T, compiling my roughly 7 million characters / 150,000 lines of JASS code with the old JassHelper takes about 2–3 minutes per build.
I searched extensively but couldn’t find any modern replacement JassHelper compiler, and I didn’t dig into the original JassHelper source code either. Of course, Lua can be used for map scripting—and it’s not necessarily harder than JASS—but I’ve already built too many existing libraries around JASS, so migrating away from it isn’t realistic for me.
The goal of this project is to reimplement the classic JassHelper using modern C++20, compiling vJASS / Zinc into standard JASS (war3map.j), while addressing the old tool’s shortcomings in parallel compilation, maintainability, and static analysis.
Core positioning:
Compatible with both vJASS and Zinc syntax, supporting syntax mode switching within the same file.
Compilation architecture:
Preprocessor → Lexer → Parser → AST → SymbolTable → CodeGen, with a fully modular pipeline.
Performance direction:
File-level multithreaded parsing + multi-phase parallel validation.
At the moment, performance is already very impressive: JassHelper takes 2–3 minutes to compile my project once, while my compiler finishes the same project in about 1 second.
Code generation:
Implements struct-to-array modeling, method dispatch, a function pointer system, and main/config template injection.
Engineering setup:
Built with CMake + MSBuild, directly buildable on Windows and integrable into the map import workflow.
Key feature: Desync static analysis (annotation-driven)
This is a highly practical feature. During development, we generally understand how desync occurs—but it’s nearly impossible to eliminate it completely. Once it happens, tracking down the root cause can take weeks and hundreds of test games. (Of course, this is unlikely to happen with T.)
My approach is based on a taint-propagation algorithm:
- When you use a dangerous function (e.g., GetLocalPlayer), any variable, branch, assignment, or hashtable entry derived from its return value is marked as “tainted” (unreliable).
- If a tainted value is later used inside a handle-operation function, or participates in a conditional that leads to a handle operation, the compiler emits a warning.
JASS:
//@ desync handle-op 3
native GetRandomInt takes integer lowBound, integer highBound returns integer
native GetRandomReal takes real lowBound, real highBound returns real
JASS:
//@ desync danger 17
constant native GetCameraBoundMinX takes nothing returns real
constant native GetCameraBoundMinY takes nothing returns real
constant native GetCameraBoundMaxX takes nothing returns real
constant native GetCameraBoundMaxY takes nothing returns real
constant native GetCameraField takes camerafield whichField returns real
constant native GetCameraTargetPositionX takes nothing returns real
constant native GetCameraTargetPositionY takes nothing returns real
constant native GetCameraTargetPositionZ takes nothing returns real
If you believe the compiler warning is a false positive, you can write:
//@ desync safe
This causes the next line to skip desync detection.
The compiler also supports set null detection. As we all know, in JASS, if you don’t set a handle variable to null at the end of a function, that handle will never be properly released.
Additionally, several modern language features are supported, such as:
- Ternary expressions
- Removing the restriction that variables must be declared at the top of a function
- Default parameter values
- A complete for loop syntax
If you’re working on Warcraft 3 map development or JASS/vJASS toolchains, feel free to share test cases and edge-case syntax scenarios—let’s refine this compiler together and make it more robust.
PS: The compiler currently does not support anything related to T—not even map regions, camera objects, global variables, or JASS written directly in the editor. I may not plan to support T compatibility in the future either.
