| 11-17-2006, 10:16 PM | #1 |
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. |
| 11-18-2006, 10:53 AM | #2 |
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 |
Great, I need to try this asap. |
| 05-02-2007, 02:54 AM | #4 |
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 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: 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 |
