PenUltima Online

It is currently Thu Aug 28, 2008 3:36 pm

All times are UTC - 8 hours




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Whats the best structure for the include files
PostPosted: Sat Nov 04, 2006 10:27 am 
Offline

Joined: Fri Sep 08, 2006 10:41 pm
Posts: 7
Im having trouble with include files when i declare 1 include in more then 1 script,ex: include"include/classes"; its saying that i already have declare the constants of that include file in another script....
whats the best include files structure?
plz give me a example of how to create include files and not have this problem....


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 2:58 pm 
Offline

Joined: Sat Feb 04, 2006 5:49 pm
Posts: 744
Location: Chicago, IL USA
Best way to prevent that is to:

A: Make sure you don't have duplicate constant names.
B: Don't include inside of includes.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 3:26 pm 
CWO's A: is right on the mark; You should -never- declare the same constants in multiple files. Unfortunately, not all scripters have done this; specifically, many scripters will purposefully declare a constant in one file to avoid having to include another file. Personally, I think that's missing the point of includes and constants in the first place (to have 'magic' values set in one, central location so that you can change the values but only need to do so in one place)

You can avoid declaring the same const twice using one of two methods:

1) Declare the const only ever in one file, and include that file in ALL scripts that need that constant, no matter if a single constant is the only thing you are using from that include. eCompile completely ignores any code which is not used in an include when compiling, so you are NOT increasing the size of your compiled scripts by doing this. However, if you frequently find yourself including a file merely to get a couple constant values, and not for any other functions, you should consider splitting your constants into a separate include.

2) Slightly alter the name of the constant in 'secondary' declarations of it. Say, for example, you really, really, really want to avoid having to include client.inc just to get FONT_NORMAL. Do NOT declare a 'FONT_NORMAL' in your script. Instead, declare, [SCRIPTNAME]_FONT_NORMAL. This way, even if you later do decide to include client.inc, your constant will not collide.

I much prefer the first solution, because it avoids unnecessarily declaring constants that have already been declared elsewhere.



If you avoid ever declaring constants with the same name in multiple files, you should not need to worry so much about CWO's B:. Of course, in order for that to be true, you should also use the same principle with function names: Never use the same function names in multiple include files... NEVER! Again, if you have a function that you need, just include the file it's in. Making a separate copy of it just to avoid including a file is avoiding the whole point of includes in the first place. And, again, eCompile is able to optimize these includes - it does NOT include code that it has no calls for. You can verify this by having a validly declared function that nevertheless has some syntax error in it... if that function is not called anywhere at all, eCompile won't complain, because it's not even reading the body of that function.


I would actually go so far as to suggest that it may be very, very difficult, and probably not particularly useful, to try to actually never have includes included from within other includes. As long as you avoid variable, constant and function name collisions, there is no reason at all you can't have all the cross-including you want. Note that unlike compilers for other languages, eCompile will recognize when a file has been included more than once, and will not attempt to do so again.

(There is an except with eCompile for 095, but unless someone asks, I won't clutter up this post with that info!)


Top
  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 3:36 pm 
Umm... I just realized; this IS the 095 help forum! So, let me explain that caveat to the above!

There are two (maybe three) different ways that eCompile can find your include files, based on how you write the include statement. One is the :package:file format, and the other is simply the normal directory/filename format. For example:

Code:
include ":mypackage:myinclude";
include "../pkg/mypackage/myinclude";


If you did that in a script/include, eCompile would actually think those are two different files, and it would include them 'both', resulting in name collisions on every single item in that file. Of course, you wouldn't include the file twice in the same file! But you might include it once one way in your script, and once another way in another include.

I said there might be three ways; I'm not sure if eCompile treats the simple 'file name' include method differently or not. That is:

Code:
include "myinclude";


Anyway, on 095, you should do your best to make sure that each individual include file is always included using the same syntax wherever it may be included, so that eCompile is able to recognize the multiple includes as pointing to the same file.

For instance, if you had an include file /pkg/mypkg/myinc.inc
Code:
const MY_COOL_CONST := 1;


You could actually put this line in -every single script and include- on your shard, and everything would work fine:

Code:
include ":mypkg:myinc";


But if you have one include somewhere that does this instead:

Code:
include "../pkg/mypkg/myinc";


You will get trouble with collisions on the name.


Finally, the current 096 and 097 cores' eCompiles no longer have this problem; they will recognize when you are including the same file, even if you do so by different methods. However, I still recommend always using the same method (and the method I recommend is the :package:file format, now)


Top
  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 9:47 pm 
Offline

Joined: Fri Sep 08, 2006 10:41 pm
Posts: 7
Thanks a lot !!! nice tutorial :cool:


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 10:42 pm 
Offline

Joined: Sat Feb 04, 2006 5:49 pm
Posts: 744
Location: Chicago, IL USA
Another cool thing that you can do with constants and includes is using the pre-processing done by eCompile using constants and conditional (if) statements. I'm actually doing this in my AI since AI is mostly the same but has different settings. Something like this:

Code:

const ENABLETHIS := 1;

program myscript(params)
  if (ENABLETHIS)
    DoThisFunction(params);
  endif
endprogram



Doing that, yes ENABLETHIS has a value so DoThisFunction will be compiled in the script. But if you did this:

Code:

const ENABLETHIS := 0;

program myscript(params)
  if (ENABLETHIS)
    DoThisFunction(params);
  endif
endprogram



This script will actually basically compile empty. eCompile looks for conditions like this to see if its including that function code or not. This is invaluable to do something like AI since you can have code and functions within a universally used function but enable/disable blocks of it by constants which will be put there or eliminated by eCompile itself. Even the IF statement isnt compiled with it if its false so your server never has to even run over that conditional statement and figure out where its jumping because its false.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 05, 2006 4:26 pm 
Yup! Put another way, constants which are tested ALONE in a conditional can serve as conditional compilation.

For instance, you could use it to have debug information printed for your combat system, but only when your const TESTING == 1. To publish your code to production, simply change the constant and recompile.

It's important that if you do this, the only thing being tested in your IF() is the constant value... if anything else is involved in the test condition, eCompile can not know the result, and must include all the code.

But as long as that is ALL you are testing in your conditional statements, eCompile will leave anything out when you test for a const that is 0, such as:

Code:
use uo;
const TESTING := 0;
program test(who)
   var what := 1;
   if (TESTING)
      what := 2;
   endif
   print(what);
endprogram


With the code above, since TESTING == 0, the whole "if (testing) what:=2; endif might as well not be there at all. Here's the 'lst' contents of compiling the above:
Code:
d:\pol\scripts\textcmd\coun\const0.src, Line 5
program test(who)
const TESTING := 0;
0: get arg 'who'
var what := 1;
1: decl local #1
2: 1L
3: :=
4: #
print(what);
5: local #1
6: Func(1,0): print
7: #
8: leave block(2)
9: progend

There is absolutely no hint at all of the IF (TESTING) or the what:=2 there.

Now if we just remove the const stuff entirely, as we might otherwise in a 'testing' situation, we might have this code:
Code:
use uo;
program test(who)
   var what := 1;
   print(what);
endprogram


This code produces the following lst: Note that it is almost exactly the same as the above!
Code:
d:\pol\scripts\textcmd\coun\empty.src, Line 3
program test(who)
use uo;
0: get arg 'who'
var what := 1;
1: decl local #1
2: 1L
3: :=
4: #
print(what);
5: local #1
6: Func(1,0): print
7: #
8: leave block(2)
9: progend


It's essentially exactly the same as the code with the TESTING == 0. What if TESTING==1? This is the resulting lst:
Code:
d:\pol\scripts\textcmd\coun\const1.src, Line 5
program test(who)
const TESTING := 1;
0: get arg 'who'
var what := 1;
1: decl local #1
2: 1L
3: :=
4: #
what := 2;
5: 2L
6: local1 :=
print(what);
7: local #1
8: Func(1,0): print
9: #
10: leave block(2)
11: progend

See the additional code there, where it sets what:=2? But you might notice something missing... What if we had TESTING as a VAR, instead of a CONST? This is the resulting lst:
Code:
d:\pol\scripts\textcmd\coun\var1.src, Line 3
var TESTING := 1;
0: decl global #0
1: 1L
2: :=
3: #
d:\pol\scripts\textcmd\coun\var1.src, Line 5
program test(who)
4: get arg 'who'
var what := 1;
5: decl local #1
6: 1L
7: :=
8: #
if (TESTING)
9: global #0
10: if false goto 13
what := 2;
11: 2L
12: local1 :=
print(what);
13: local #1
14: Func(1,0): print
15: #
16: leave block(2)
17: progend


Note: Now you can see the IF(TESTING) conditional that it has to keep in the code. Keep in mind all three of the above code are exactly the same, except for the value of 'TESTING', and whether it is a VAR or a CONST.

Clearly, eCompile itself is evaluating IF statements against a CONST, and conditionally compiling based on that. It completely leaves out code that would never run anyway, and it actually even leaves out the conditional itself from the code. If the const evaluates to 'true', it simply outputs the appropriate code into the compiled ecl, as if there was no conditional at all. (That is, exactly like 'conditional compilation' through pre-processor directives would do).


There is one caveat to this, however; You cannot declare a variable within the 'block' of code inside any of those conditionals, on the assumption that eCompile is just removing those blocks. It -IS- removing those blocks, however, it still does not permit the code to compile. An example. Say we adjusted the above example to this:

Code:
use uo;

const TESTING := 0;

program test(who)
   var what;
   if (TESTING)
      what := 2;
   else
      what := 0;
   endif
   print(what);
endprogram

This compiles and runs fine. Since TESTING==0, the whole 'testing' IF is left out, and the code that sets what:=0 is simply run. Here's the lst:
Code:
d:\pol\scripts\textcmd\coun\const0.src, Line 5
program test(who)
const TESTING := 0;
0: get arg 'who'
var what;
1: decl local #1
2: #
what := 0;
3: 0L
4: local1 :=
print(what);
5: local #1
6: Func(1,0): print
7: #
8: leave block(2)
9: progend

So, you might be tempted to think; Well, if eCompile is not creating a code block for the IF test, can I just declare the WHAT var within those blocks, like so?
Code:
use uo;
const TESTING := 0;
program test(who)
   if (TESTING)
      var what := 2;
   else
      var what := 0;
   endif
   print(what);
endprogram


This looks like it won't work, and you are right. It won't work:
Code:
Variable what has not been declared on line 11.


Even though eCompile does collapse that block, it apparently does not do that until AFTER it has checked to be sure all the variables are in proper scope in the blocks and such. This makes sense, since eCompile probably has to examine a lot of the structure of a function before it can be sure that conditionals testing a const are ONLY testing a const, and not somewhere down the line testing a variable or function return value, also. So, the above has to be written as originally.


Top
  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: Google [Bot] and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Style based on FI Subice by phpBBservice.nl