| 07-05-2009, 09:32 PM | #1 |
I promised Anitarf to add optional/conditional code before I rewrite the structs phase. It is something we all really need I think. I for one would like for example to have both TimerUtils at once. Not to mention both Itemdex in the same script, etc, etc... Basic: optional requires JASS:library A requires B, optional C // A will be added after B and C. // If library C does not exist, requirement gets ignored. // If library B does not exist, error appears. endlibrary Now, on how to have optional code, you'll have to pick A or B, if there are better suggestions than these, I'll really appreciate it. A. define Simple, we mimic C++ defines, forbid the whole macro stuff and using it as a replacement for constants, just use it for ifdef. JASS://! define MEH // ... somewhere later: function xxx takes nothing returns nothing //! ifdef MEH call BJDebugMsg("ooo") //! else call BJDebugMsg("aaa") //! endif endfunction Disadvantages are the //! syntax and the fact that for this to work sanely, I will have to compile these things AFTER the library phase. This means that things like: JASS://! if ERR library A requires B //! else library A_a requires B //! endif //! could be an advantage as we are doing things from the preprocessing world here... B. static ifs! These would only work inside functions/methods: JASS:globals constant integer a = 4 constant integer b = 5 endglobals function xxx takes nothing returns nothing static if (a+b) then call BJDebugMsg("ooo") else call BJDebugMsg("aaa") endif endfunction static ifs are evaluted at compile time and remove the code that is not used. |
| 07-05-2009, 09:57 PM | #2 |
I would go with C preprocessor. Full C preprocessor, macros included. So you could just throw away that stupid runtextmacro syntax. |
| 07-05-2009, 10:01 PM | #3 |
Maybe slightly off topic, but can the compiler detect what kind of syntax error occurred? My most common error seems to be forgetting the call keyword. I spent 15 minutes writing an AI script confused why nothing was working only to finally realize I had forgotten it again. Why would you want an optional class/library? There are no incredibly powerful debuggers for Warcraft 3. My most complicated map at times got difficult to debug because there were so many systems working in parallel and adding inheritance complexity would only complicate matters. Often times the equivalent of #define is all that's necessary and limiting it to simple variable defines (avoiding the whole macro system allowed by C) is all that I've ever needed as far as pre-processing code goes. I dearly missed the whole thing working in .NET and would laugh pretty hard if Blizzard included such a thing in Galaxy (Starcraft 2's language). Option A would probably be more powerful if you could process them before the normal compiler like the C preprocessor. I assume this is for the vJass compiler and I don't know much about its compiling stages. |
| 07-05-2009, 10:38 PM | #4 | |
Quote:
|
| 07-05-2009, 11:44 PM | #5 |
I'm assuming you meant static if (a+b) == 9 then. Static ifs look prettier and will be just as functional as ifdef. JASS:library Main requires optional Addon function DoStuff takes nothing returns nothing static if Addon_Exists then call DoAddonStuff() endif //Do normal stuff. endfunction endlibrary //============================== library Addon globals public constant boolean Exists = true endglobals function DoAddonStuff takes nothing returns nothing //... endfunction endlibrary |
| 07-06-2009, 12:22 AM | #6 |
What kind of situation would there be in which requiring a library would be optional? Wouldn't you put libraries in your map with the intention of using them? Maybe I'm not understand how/why this works/is needed... |
| 07-06-2009, 12:26 AM | #7 | |
Quote:
|
| 07-06-2009, 03:06 AM | #8 | |
Quote:
For that feature to be complete, there must be a keyword to check whether library is defined or not; something similar to static ifs. While //! define can be used for that purpose, it is not a standard part of the library. Means it is not guaranteed to work. |
| 07-06-2009, 04:39 AM | #9 |
I just realized that my previously posted code wouldn't even work. Here's the issue: If the addon library isn't in the map, Addon_Exists can't be evaluated by the static if. It will just throw an error message for a non-existent variable. Therefore, this "Addon_Exists" global would need to be in the Main library. And you can't make the addon library alter the value of the "Addon_Exists" variable because it has to be constant. Therefore, the user will have to manually change the "Addon_Exists" boolean in the config section to specify whether the addon is being used or not. So there are 2 ways to solve this: 1.) Use //! ifdef. This way is ugly, but it works. 2.) Provide a new syntax to explicitly check whether a library exists or not: static if AddonLibrary.exists then |
| 07-07-2009, 08:40 AM | #10 |
Why do you want to add that static keyword there? If you are able to evaluate constant expressions then you can do it with every if-block so the static keyword would be unnecessary (and it would also optimize some older code). To make it possible to check for errors in code which gets removed by static ifs you could add some special symbol (@) which one places in front of every optional function call. Example: JASS:library Main requires optional Addon function DoStuff takes nothing returns nothing if LibraryExists("Addon") then set i = i 1 //causes an syntax error even if Addon does not exist call @DoAddonStuff() //no error here because it has @ in front of the function //would give an error iff Addon exists but has no function named DoAddonStuff else //some workaround endif //Do normal stuff. endfunction endlibrary |
| 07-07-2009, 09:00 AM | #11 |
if you go with peq's solution, there should also be some block-syntax for the @-operator, such as @begin and @end(pascal-style ;)), or sth like @{/@} or @[/]@ |
| 07-07-2009, 09:05 AM | #12 |
I would more care about nested Scopes JASS:scope spells initializer init scope HolyLight initializer init private function init takes nothing returns nothing debug call BJDebugMsg("Holy Light initialized") endfunction endscope private function init takes nothing returns nothing debug call BJDebugMsg("Spells initialized") endfunction endscope Comment: Parse through all scopes, then the child scopes, then those etc. Idc about linking to optional code. |
| 07-07-2009, 09:36 AM | #13 |
i like peq's solution... |
| 07-07-2009, 09:44 AM | #14 | |
Quote:
|
| 07-07-2009, 10:47 AM | #15 |
peq's suggestion gave me an idea: if you use a special character like that, why bother with static ifs or anything of the sorts? You could simply make it so that lines with that special character at the start get deleted if there is a compile error on them instead of the compile error getting reported. That would effectively make it conditional code, if the optional library isn't there then you'd get a "no function with that name exists" error and the line would get deleted when compiling. I realize now static ifs let you do more than that, since you might have legal code in them that you still don't want to run if another library isn't present. Nevermind then. |
