HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

JAST

11-17-2006, 10:16 PM#1
PipeDream
This is a framework I'm hoping will help people working on JASS extensions. It parses JASS using lex/yacc like PJASS but instead of checking the syntax it constructs a tree for the program. It's written in ocaml. I recommend this tutorial if you want to play around with it.
It's a lot easier and faster to implement transformations on the source once it's in tree form. Demonstrated in jast.ml are a few primitive optimizations: Dead code elimination of if/elseif/else constructions, arithmetic/boolean/string expression simplification and constant var/very simple function propagations.

It's prealpha at the moment and I'm not exactly sure what I'm going to do with it. The functionality is mostly orthogonal to existing tools like PJASS, Vex's opt and WeWarlock. It could replace PJASS if a type checking tree walker were added.

Bugs/Limitations:
- Doesn't handle ' ' style integers correctly
- Is mostly ignorant of types
- Tosses out information vex's optimizer needs such as constant keywords for functions.
- Probably destroys any real map
- Probably doesn't handle escaped strings correctly

Source: svn://w3jdebug.no-ip.org/jast

Anyway, I hope to generate some interest and figure out something useful to turn this into.
Attached Files
File type: 7zjast.7z (67.8 KB)
11-18-2006, 10:53 AM#2
karukef
Yeah, if there weren't already a bunch of preprocessors made already, then it would be obvious what to do with this one. That's why my first thought was "improved optimizations", because that is if nothing else an area that certainly has potential for further improvement.

In any case I'm interested to see what comes out of this.
11-20-2006, 06:27 PM#3
PitzerMike
Great, I need to try this asap.
05-02-2007, 02:54 AM#4
PipeDream
Updated
Added an experiment in static analysis. Right now if you run it on a stream of JASS, it checks each function for variables which could be used uninitialized. It seems to handle most of JASS now, i.e. 'xxxx' codes and strings properly.
Run ./jast.exe < Blizzard.j and it will find one potential problem:
Code:
function PerformStockUpdate: pickedItemType
Meaning pickedItemType could possibly be used uninitialized.
Give it a try on your war3map.j's, see if it turns anything up...

note: Doesn't check globals at the moment.

---
Updated again, to support windows line enders so that it can run on your average extracted map. Example run on an old iawrpg.j:
Code:
function Codemaker_AskString_Child: r
function Codemaker_SetCharmap: EXITTHREAD
function UnitMoveToAsProjectileAnySpeed_Move: z2
function UnitMoveToAsProjectileAnySpeed_Move: y2
function UnitMoveToAsProjectileAnySpeed_Move: x2
function InputMsg: result
function InitHero: int
function InitHero: str
function InitHero: agi
function InitHero: spellbook
function InitHero: trainer
function PrintItemStrings: dis
function LoadCodeItemRare: whichItem
function LoadCodeItemUncommon: whichItem
function EquipItem: slot
function StackAdd: highcount
function CheckPartyRanges: g
function PartyQuit: uu
function Trig_Ice_Armor_Actions: udg_RealVar2
function Trig_Ice_Blast_Actions: udg_RealVar2
function Trig_Execute_Actions: udg_fx1
function Trig_Cobra_Bite_Actions: udg_fx1
function Trig_Impale_Damage_Actions: udg_fx1
function Trig_Backstab_Actions: udg_fx1
function Trig_Recharge_Actions: udg_RealVar2
function Trig_Spirit_Blast_Actions: udg_RealVar2
function Trig_Healing_Ritual_Actions: udg_RealVar2
function AddProgressBarUnit: t
function Trig_Set_Can_Wield_Actions: abilToRem
function Trig_Set_Can_Wield_Actions: abilToRem2
function Trig_MW3_Actions: npc
function Trig_Select_Any_Class_Actions: class

Picking out PartyQuit: uu:
Collapse JASS:
function PartyQuit takes unit u returns nothing
    local player p=GetOwningPlayer(u)
    local group party=GetHandleGroup(u,"party")
    local unit uu

    if party==null then
        call GameError(p,"You are not in a party.")
        return
    endif
    call PartyInfo(party,GetPlayerName(p)+" has left the party.")
    call GroupRemoveUnit(party,u)
    call SetHandleHandle(u,"party",null)

    if CountUnitsInGroup(party)==1 then
        call DestroyParty(party)
        call GameInfo(GetOwningPlayer(uu),"Your group has been disbanded.")
        set party=null
        set uu=null
        return
    endif

    if GetHandleUnit(party,"leader")==u then

        if CheckPartyRanges(party)then
            call PartyInfo(party,"Party ranges are too high, group disbanded.")
            call DestroyParty(party)
        else
            set uu=GroupPickRandomUnit(party)
            call SetHandleHandle(party,"leader",uu)
            call PartyInfo(party,GetPlayerName(GetOwningPlayer(uu))+" is now the leader of the group.")
        endif
    endif
    set party=null
    set uu=null
endfunction
And indeed call GameInfo(GetOwningPlayer(uu),"Your group has been disbanded.") uses uu before initialization.