Would a "higher level" AGI compiler be useful?

Mokalus_of_Borg I was just wondering about my next project after AGI2SCI - does anyone think that it's time we could write code for AGI in a higher-level language? Coding in this assembly-like language is bound to be a pain (I've never actually done it myself), and I'm sure it would make AGI development more accessible. Also, I'd be fairly confident in betting that the original development system didn't require coding the way we do.
The proposed compiler would natively support more data structures, like the arrays discussed elsewhere on this board, but as for the larger-scale syntax and so forth, I'd need the input of experienced AGI programmers. So here's your chance: go nuts! Tell me everything you'd wish from your ideal AGI-HLL compiler. Eventually, I'll get around to working it up, either between AGI2SCI components or afterwards.

Mokalus of Borg

PS - Unless this has been done already?
PPS - I really think this will be a Good Thing.
Joel The big problem with a higher level language for AGI is the limited resources. How would the compiler manage them? Would the user be able to specify that the compiler may use variables in a certain range as temporaries and that it must leave the rest alone? To add the ability to evaluate expressions into the AGI language, they'd either have to be limited in form, or the complexity of the expression would be limited by how many temporary variables are allocated to the compiler. I may be mistaken, because I haven't worked this out a great deal, but I believe that evaluating nested parentheses requires a stack, and there's nowhere to put the thing except in the var area of memory. I'm not saying that it wouldn't still be useful, but it's something to take into consideration. I definitely think AGI should be able to handle expressions like v1 = v2 + v3 + v4;, but when you get into expressions like v1 = v2 + (v3 + (v4 + (v5 + (v6 + v7) * v8) + v9) * v10) + v11; it gets a little ugly.

Array syntax becomes problematic, as well, especially when you get into multidimensional arrays.

There are some additions/changes I'd like to see to the AGI syntax, though. For example:

the ability to print out vars by name, as in something like
#define vTemp v202
print("%vTemp");

switch statements

more C++ like syntax, where function names don't have dots in them (for example AddToPic() instead of add.to.pic()), and along with this I think it would be good if we could have object.method style syntax where appropriate;

for example,
#define ego o0
#define oSomeOtherObject o1

instead of
animate.obj(o0);
animate.obj(o1);
set.view(o0, 0);
set.view(o1, 10);
draw(o0);
draw(o1);

something like
ego.Animate();
oSomeOtherObject.Animate();
ego.SetView(0);
oSomeOtherObject.SetView(10);
ego.Draw();
oSomeOtherObject.Draw();

There are probably other things I could think of, but that's all I can for right now.
eidolon On the spur of the moment I think this sounds like a fabulous idea!
The first things that cross my mind are:

- Control statements: switch, advanced if..else if, for, while, break...

- Recursive expressions: v59 = ( v122 + 16 ) * 4;

- Boolean type parsing:  v44 = ( v99 > v22 ); if( v44 )...

- Function definitions ( with parameters and return values )


Even wilder ideas:

- Other datatypes: 16 and 32 bit integers

- Objectoriented syntax

- Point & Click programming through a specially designed application suited for beginners. With a highly flexible GUI, game developers could create anything from room descriptions to motion patterns for monsters.


However, it all comes down to this - what you gain on abstraction you lose on precision. And implementing all this into the code would certainly eat resources. AGI is such a limited system that programming it almost feels like doing demos on the C64 in machinecode. Furthermore, care for details is not far from inevitable when it comes to optimizations, and I think that is one of the actual pleasures of this retro craze.
sonneveld I think I tried suggesting some of these things in the older agi board but not as many people were receptive.
Andrew_Baker Two cents...

- User-defined functions could just be macros, either defined in defines.txt or some other file.  Of course, it would be beneficial if this could be accessed from the AGIStudio environment.

- Since arrays are stored linearly on any computer system, then interpreting and handling them could just be a matter of making a macro-type command that accepts arguments and is compiled into interpreter data by the Studio.  The same with referencing them (because it would be absolutely necessary to be able to reference arrays by both integer values as well as vars.).  Not to say this would be easy, though...  but I don't think anyone would need arrays of more than two dimensions for an adventure game, no matter how advanced.

- Also, if there are going to be any improvements to AGI coding, I think most of them could be done in AGIStudio.  Nailhead has done a great job on his version, but there are still bits missing (Like sound, tricky, tricky, tricky).  I think that a lot of problems like room and logic generation could just be integrated into the studio, but I'm the kind of nerd who likes to hand-craft code (f'rinstance, a monster's motion pattern could be defined as a series of loops.  Plotting a square motion pattern would be like 4 nested loops, I think.  I know I could write it in AGI, but I'm not sure I would trust an automated logic generator to do it for me.).  Still, I think if there was a way to add new third-party development tools to the main Studio environment without having to rewrite the Studio every time someone released a new tool, I would actually weep with joy.

- For loops, for loops, for loops!

- Ultimately, I would support an upgrade to the compiler in any way I can (which probably wouldn't be much, but...), but part of the charm of AGI for me is making a good chunk of code using a difficult language with limited resources.

I wish y'all luck, you beautiful monsters!
sonneveld I just think a separate compiler that's called by AGI Studio would be easier to replace.  I was also thinking that Joel's logic template generator could be added as well (i know they borrowed it for linux agi studio I believe).  The template generator could be integrated with the pic/view code, so you could manually place views on the picture background itself.

- Nick
Joel I would also like to see conditional compilation. Ya know,

#if defined(DEBUG)

log("whatever");

#endif

that kind of stuff. I'm more supportive of changes that are mostly just rearrangements or trivial additions to the original syntax. Although I'd like to see syntax such as ego.StopCycling(), I see no reason why the same compiler couldn't continue to handle stop.cycling(ego); Switch statements can essentially compile down to if statements as a simple implementation.

But especially in a limited resource environment, with the addition of expressions and array syntax and function calls, this higher-level compiler wouldn't just be a compiler. It would require a code optimizer. And if the user doesn't have control over which variables the compiler is allowed to use for temporaries, then the compiler has to manage all the memory for the entire game.

Function calls are probably possible, but they require temporary space for parameters at best and entire activation records at worst (and more likely, especially if functions can call other functions). AGI has no "call" command for labels as far as I know, so if functions can call other functions, then the compiler has to keep track of the location where the function call was made, and when the function returns, it has to jump back to that location. If you have a 5x5 two dimensional array, you've knocked out 25 of your memory locations right there. Add in expression evaluation, you've got an unknown number of temporaries necessary (you don't even have to have parentheses to need temporaries...e.g., v1 = 2 + 3 * 7;) Function calls just create more of a headache.

States wouldn't necessarily help in this regard. It's standard optimization to reuse variables that are no longer needed, but you don't have an expression-evaluating state or a function-calling state, and either of those can require an arbitrary amount of memory. Another potential problem, because what if you start calling too many functions from functions and you start overwriting your game data?
sonneveld The states would be useful if the programmer didn't want to have to manually figure out which variables he could overwrite..  If the compiler had control over the assignment of variables, it could set aside some for spare variables in arithmetic.

we could define similar "object orientated" function names for the menu, screen, script, input.. to help separate them into groups.

I'd actually like the compiler to manage the memory for the entire game.  Considering how some people don't use defines and then forget that they're already using a variable in other logics, it would make things a lot simpler.

AGI does have save.scan.start and restore.scan.start.. but it's not recursive.  AGI doesn't have functions, but you can call other logics and then return back from them.. so it's not a stretch to set a variable to define a function, call a logic containing lots of functions and goto the specific function.. (via a switch, if implemented).

- Nick
df if you cant write it in logic, you cant do it in a higher level compiler. The agi logic itself is what is lacking here... What really needs to happen is say, replace the logic with 8051 or 6502 code (something nice, small and easily interpreted!)...

replace logic with cpu emulation. have a logic-to-code convert then you can write your AGI game in C or whatever, or just beef up existing logic code.

Mokalus_of_Borg Okay, so it sounds like the extreme position of a whole new, very high-level, optimising, super-happy-magic compiler is out, but we'd like some better control structures and syntax in the compilers we currently use. So, is the source code available for either AGIC or MATS? If not, are there any other AGI compilers around, with source, that I can get my greasy paws onto?
And the conditional compilation could be fairly easily done with a C preprocessor.

Mokalus of Borg

PS - I don't know when I'll start this.
PPS - I'm still busy with AGI2SCI and work and study...
sonneveld if there's any chance, I'd like to help with the compiler too..  are you planning on writing in C or python?

I we think we should define the correct syntax first before doing any recoding.  We should check out the feasibility of any of the suggestions (macros and #ifdef's should definately be in.. also with "%v"varname"")

How about the way we define variables.. does anybody have any ideas about that?  should we still manually define every variable in defines.txt?

- Nick
Joel That depends on what you mean...I changed all the defines in my defines.txt so that they're more consistent with my own coding style (I don't like using underscores to separate words in variable names; I also corrected the misspelled "input_recieved"). It's fine, I guess, if the compiler recognizes the define names from the template game without them being explicitly defined, as long as I can also change the names if I want to. On the other hand, you don't want to be breaking people's current code by flagging a redefinition error or anything if they continue to use defines.txt.
sonneveld I was thinking more, associate a variable number with your definations (for system/template or other variables) and let the compiler organise the rest..  as soon as you do that, you need to change the msg handling as well to support var names..

so are we planning on having backwards compatible with older source too?  how about a header to define the script version?

- Nick
sonneveld I knocked up a summary of this discussion.. it explains the basics of the logic format and all the suggestions so far in a list..

Compiler Discussion Summary

I've put up links to the AGIC page, and downloads for AGIC and MATS (they both have source)..

- Nick
Mokalus_of_Borg I'd rather write in Python, but it's probably not fast enough. Maybe I could write the basis in Python and have someone else who's much more C-savvy translate it.
That's if we start from scratch. We already have two fully-functional compilers available, and it might be enough to just add a bit to them.
Now, if we have all variables defined in advance (perhaps with separate scopes for game-wide and room-specific), we'd know how much space we have to spare for expression evaluation and data structures. I think it can be done.
Overall, I envisage a source code format that reflects the structure of the game more clearly, is easier to understand and use, and gives more power to the programmer.

Mokalus of Borg

PS - I promise at least to work up a grammar over the next two days.
PPS - You spelled my name wrong on that page: "Mokulus".
sonneveld sorry about the spelling mistake.. you'll notice I spelled it correctly the second time :)

how about this for grammar..

global
{
 v55 var_that_has_to_be_55;
 var any_var;
 var timer;
}

room toilet
{
 flag toilet_flushed;

 if (isset(new_room))
 {
   ..
 }

 ..
}

room postoffice
{
 var people_timer;
 pic postoffice_bg;
 // or
 pic bg postoffice_bg;

 if (isset(new_room))
 {
   ..

   load_pic(postoffice_bg);
   // or
   load_pic(room_no);  // pic is associated with room ??
 }
 ..

 if (..)
 {
    new.room(toilet);
 }
}


- Nick
sonneveld PS this format would be nice because you wouldn't have to have rooms in separate logics
PPS plus you could associate names with your rooms
PPPS do you do this all the time? :)
eidolon Nick: I wasn't serious about the 32 bit integers. :)
However, I contend that such abstractions are in no way unfeasible, just very exhausting.

I take it we don't need values beyond 255 anyway.


I also want to cast a vote for your proposed scripting format!


And now a word about functions:
Functions would not need to be very different to room definitions. They could be inlined and their parameters could be treated just like any temporary variable. If a parameter is not modified by the function, its original variable could just as well be used directly.

df on the fly translation of logic to z80! :> hehehehe
Joel inlining of functions could work, but again functions couldn't call other functions without a stack.

as for backward compatibility: not trying to discourage you guys from doing this, but if it's not 100% backwardly compatible I probably just won't use it. With the script as you wrote it, what if I write some code that looks like that but I also have a line that says

#define vCounter v200

instead of
v200 vCounter;

Will the compiler be able to recognize that v200 is already in use?

also, something to mention, that pic data type in the script you wrote would also require a temporary variable, because load.pic(), etc., take var arguments.

How would you implement it such that rooms didn't have to be declared in separate logics? That sounds like more temporary variables to me.

My feelings on this whole issue:
if I can keep my source code exactly as it is right now and the compiler will compile my code and generate absolutely no temporary variables of its own or anything like that, then it's fine if there are extensions that do generate temporaries. However, extensions such as for loops, while loops, switch statements, and object.method syntax would not require temporaries and so they should not generate them. I can understand it if an expression such as 2 + 3 * 7 or v1 = 2 + 2 + v1 generates temporaries, but expressions that are already supported by AGI syntax without temporaries should not generate temporaries. Neither should simple expressions such as v1 = 2 + 2 + 8 + v2. I shouldn't have to give up precise control over what variables are used for what just to use the extensions that I think would be useful. If I did, the new compiler would have no value to me.

By the way, AGIC was written with lex and yacc. If it was well-written, it shouldn't, in theory, be too terribly difficult to modify that. I haven't really taken a good look at it, though.
sonneveld eidolon: I just think the abstraction helps with creating a game, instead of worrying about resource management.  It depends on what features you use, most wouldn't complicate things.  

functions could work inline, but remember that some agi commands only accept a number constant, not a var number.

The scripting format's just an idea.. I think it might need some work.  I want to take into consideration logics that aren't associated with rooms and other things.

joel: The lack of stack does restrict things..

Should we stick with the same format as before?  We could have a header to tell the compiler it's a new format.. we could make the compiler accept logics without a room definition, and just use a number supplied in the filename or command line.

If we use a separate preprocessor, we wouldn't be able to parse the #defines.. the least you would have to do is replace all of them with a global{} (if we decide to use such a thing)

btw, I realised the picture problem while I quickly wrote that script idea.  The plan was for "pic bg postoffice_bg" to make sure that the picture had the same number as the logic.  If we wanted another pic, then we'd have to use a temp var anyway.

I meant logic scripts sorry.. ie, define a group of small rooms in the same script, and the compiler would manually separate them into their own logics with different numbers.

Basically, I don't think we can use temporaries with the original code unless we read them all in, parse the defines, and then create temporaries around that.  How will the compiler know that var 50 in the first room isn't going to be used in the last room too?  We could add while's and things like that to the original syntax but we would be limited if we couldn't use temps.

why do you want precise control over the use of variables?  what sort of "algorithm" do you use to make sure that a variable isn't used anymore later in the game so you can use it in a later room?  We could apply the same sort of concept to the compiler  somehow to do that same concept.

- Nick
df use variables like a stack. you have 255 of them.
have a low order one (20?) whatever, be a base pointer.

when you go into a room, you know you are using 5 vars,
do push/pop's. (inc/dec on stack pointer) to get the variable.
starting at 255, would be a piece of cake!

sonneveld The problem Joel was pointing out is if you're got pre-written scripts that #define those particular variables..

- Nick
Joel What I do to separate my variables is I reserve all variables below 200 for global use. All variables 200-255 are for local use. I have no problem with the use of temporaries defined by the compiler if I can say, "use v200-v255 for temporaries but don't use v199 and below for them". Other people might want fewer or more temporaries. I think that there should be a way to tell the compiler which variables it is allowed to use.

I guess this is actually more of an issue with flags, since I so far have only 2 global vars in my game and about 11 global flags. Temporary flags I guess would only be used with the evaluation of boolean expressions, but I still want the ability to say which vars and flags the compiler can use for temporaries and which are off-limits.

As for determining when global vars can be recycled, that's more or less determined on a variable by variable basis, but it could be handled by a state system.

The main issue I want to avoid is having to rewrite my code. If it were absolutely necessary, I guess I could rewrite my defines for the new declaration method, but rewriting should be kept to a minimum.

The thing is, if the new compiler forbids #define vCounter v200, then will it also forbid v200 = 2; ? I think, as much as possible, the new AGI compiler should be able to handle old logic syntax the way C++ compilers can handle C syntax. C++ has a few additional restrictions, but for the most part any C program is also a C++ program. Unfortunately, using the preprocessor for variable naming I can see is a problem. Getting the define names into the compiler's symbol table as if they were var declarations would be tricky at best.
sonneveld joel:
I'm thinking more of a variable definition system where the programmer will only have to define variable numbers for the system variables.

The whole script syntax that we're using was made by fans, I don't see why we can't create a new one.  Backwards compatibility is a problem.  The original syntax is very simple, and working around it would seem like a kludge.. what's wrong with clean slate?  C/C++ at least handled variables the same way, I'm trying to propose a different way of handling them.

If we add a decent preprocessor to the compiler, we could share it between two languages.. the original and the new syntax.  I don't know if it would be possible for a game to use both types of syntax in their logic though.

- Nick
Joel There's nothing wrong with it, but unless this new compiler comes out very, very soon then there wouldn't be much chance of me using it, because by that time I would have a whole lot of code to rewrite to make the move to the new compiler, and I doubt I'd be willing to do it unless the new compiler was just really, really something.

This issue with temporary variables is not something that can just be abstracted away, though. Programmers shouldn't have to actually WRITE the temporary stuff, but they will have to be AWARE of it for the simple fact that AGI is a limited resource system. It's a very real possibility that adding a global var declaration could break code throughout the game, and then the programmer would suddenly have to understand that the compiler needs temporaries to evaluate expressions, array syntax, etc. That's why I think it would be helpful in this regard if a programmer could say, "I don't really care WHICH variables you use for what, but only use variables in THIS set of variables".
sonneveld The way I'm planning it is that variable numbers don't get assigned until linking stage.  Global variables will get assigned numbers, and they will only be used for globals..  then you define "chapter" states.. rooms could associate with a certain state, so rooms using vars in one state would share the var numbers with another.  The idea being that the player progresses through the states and can't go backwards.

Programmers shouldn't have to write the temporary stuff, that's why I want the compiler to handle it.  I don't see how adding a new global will break the game though.. the compiler would just set aside a variable number for that global variable.  All variable numbers should be assigned when all compiled logics are linked together.

I don't know how soon a workable compiler will be working though.. we still need to figure out the new syntax.

- Nick
sonneveld I want the programmer to say "I've got variables called this.. I don't care what actual number they have but make sure they're available to me, some all the time, some when the player is at a certain stage of the game.. if there's any left over, use those for temporaries."

- Nick
Joel The "if there's any left over" part is how adding a global declaration could break existing code. In the best case, the compiler would catch the problem at link time and say it can't find any way to link the logic; at worst, the compiler's temporaries could start overwriting global data.
sonneveld I think I understand now..  if the linker can't assign enough variable spaces for temps because they're taken up.. then it would just quit with an error..  The programmer would have to use less variables or share them across the game.  I don't see how the linker break down and start using other variables..  It wouldn't break code, it just wouldn't compile.

It would be the same if you manually #defined the vars and you needed another global but all the vars were taken up.  At least the linker would have the possibility of allocating vars efficiently.

- Nick
Mokalus_of_Borg Nick, that format looks very similar to what I had in mind. Seems like we're on the same page.
Also, everyone, the idea here was either to add some nice new features to the existing language, which would be backwardly compatible, or to create a whole new language, which abstracts away much of the machine-level detail we have to worry about now. This would mean giving up backwards compatibility. The second path is really intended for brand-new projects, and attracting games programmers to AGI.

Mokalus of Borg

PS - Whether or not existing projects use it, it'll happen.
PPS - Yes, Nick, I do this all the time. :D
sonneveld Joel's right though.. agi coding is time consuming and all of those projects currently in development aren't going to swap over to the new format overnight (and that's if it works properly to begin with!) so it might be more effective to add some backwards compatible additions to the original syntax (better preprocessor, control structures, varnames in Strings) and then develop a more up to date syntax.

- Nick
Joel I think creating backwardly-compatible extensions first and then maybe a new syntax would be a better idea (although more work).

As for the compiler producing code where its temporaries started overwriting global data, that wouldn't happen if the linker were written well enough that it caught the error. I was just saying what could happen in a worst-case.

You're right in saying that the situation is no different from using #define -- if there's no more variables, then you're out of luck. But when you have to manually allocate all the vars, then you are very much aware of the fact that you're running out of vars well before you ever do. With the new syntax, it's entirely conceivable that somebody could start declaring away and only after a significant amount of work find out that AGI is incapable of handling the game they want to make (and, in fact, the only way to avoid this for sure is for the programmer to keep careful track of how many variables are still available, which the programmer doesn't even know because the compiler is allocating temporaries by itself).
sonneveld I think that sounds like the plan...

I just thought if we were going to write a new syntax/compiler/linker to help allocate the scarce resources, we'd at least check if we had enough too. :)

The point you made about a coder not knowing they're running out of variables is a good one.  What did the old dos compilers do when the compiler discovers that you'll need a larger memory model?  I think the best way would be to have some statistics at the end of the linking:

number of variables used
number of variables in each state (global, "chapters", rooms)
number of variables shared
number left...

the same could be used for flags, views, pics, sounds, assuming none of them gets assigned a number until link time.  a warning could be displayed when the number free gets below a certain range.

If we really wanted to get speccy, we could have some sort of pre-link when the coder is writing the logic code to check the number of variables :)  I doubt this sophistication would happen though.. I'm not trying to promote vapourware here.

- Nick
sonneveld btw.. was the compiler summary page useful?  if so, I'll move it to my dingoblue server at least until the agidev server is stable (easter!).  adding the one suggested syntax and other comments would be good too..  just want to know if it was useful first.

- Nick
sonneveld Another thing.. (sorry about all the comments).. does anybody have any ideas on refering to variables defined in an external logic.. should we follow C's method of using headers/extern prototypes or should the linker just do it automatically by reading in all the objects at once?

it might help programmers because then they'll know they're refering to a global variable that exists, it would stop variables with the same name too.. but I just want to know if there's a better way than C's

course, we'd have to worry about scope too...

- Nick
Joel I think reporting the statistics every time the program is linked would be a good idea. There is still a problem with function calls, however. With temporaries, the compiler can keep its own internal stack (a compile-time stack, more or less) and the game doesn't even need to know about it. With functions however, if they can call each other, you need a run-time stack. A run-time stack can, of course, be done, but the amount of information needed for function calls might make the ability to call functions from functions infeasible. For one thing, in order to return from a function call, you need to be able to jump back to the exact location from which the function was called, which means you need a record of the the next instruction that should execute after the function returns. If functions are not implemented as a separate logic invoked with a call() command, then going back through the call stack would be complicated at best, because goto commands take 2-byte values and all the vars are 1 byte. It may not even be possible. Also, the functions could presumably be defined to take different numbers of arguments (I won't even discuss different types, which would add even further to the complication), in which case you'd need an environment pointer variable and an environment pointer field in the activation record for a function (i.e., more variables not available for the game), so that you'd know where the previous activation record starts on the stack.

Actually, the more I think about it, the more I'd say that functions should not be able to call other functions. It would be too easy to fill up the stack, so the feature would be practically useless.

A run-time stack would also be dangerous for overwriting data(although, again, writing the compiler well would prevent it from going on unchecked). The thing is that any time a function was called, the compiler would need to make sure there was enough space available on the run-time stack (which could only be done at run-time, obviously) for the activation record. If not, the game might as well crash, because it's unlikely that the function call can just be ignored with proper results.
sonneveld Considering the limitations of the variables, if you're going to spend all those resources to initialise and use a stack just to call a few functions, it might just be better off to make these functions inline or just macros...

- Nick
Andrew_Baker I know that macros that could take arguments would be good enough for me...  just the ability to reuse code without having to copy and paste would make me fall to my knees and cry with joy.
sonneveld I've been thinking about other shortcuts:

room postoffice
{
 var people_timer;
 pic postoffice_bg;

 NewRoom()
 {
 }

 TouchLeft()
 {
    new.room(toilet)
 }
}

defining NewRoom() and TouchLeft to be standard if(isset(newroom)) or if (touch border)

- Nick
Joel Sorry, accidently submitted that last one early.

That stuff's not an issue if functions can't call other functions, so inline expansion would be fine as an alternative (it wouldn't work for functions calling other functions), although there are some issues to work out. For example, what happens in the following case:

var SomeFunction(var v)
{
   if (v > 100)
   {
       v = 100;
   }

   return v;
}

later...

if (SomeFunction(vSomeVar) < vSomeVar))
{
// do something here
}

should the parameter map to a temporary or should it alter the value of vSomeVar? Will there be a sort of pass-by-reference mechanism?

Those new room a touch left things are ok, but how about if they looked like event handlers instead. For example:

room SomeRoom
{
   OnNewRoom
   {
   }

   OnTouchLeftEdge
   {
   }
}
sonneveld we'd probably have to define the parameters as "pass by reference"...
Mokalus_of_Borg That does sound useful, Nick. Go to it. I'll keep reading up on the current format.

Mokalus of Borg

PS - I think for now, to ease production of games already started, we should look at adding to an existing compiler.
PPS - After that, we can start with a clean slate.
sonneveld ok.. one more thing we could add are easy to use timers..  we could have room timers (for intros, animations) and then global timers (timed puzzles.. meeting at a certain time)

basically, you init the timer, and the compiler adds in code to count up.  Then you could have sections of a room that are only called when the timer reaches a certain number.  The compiler could use two-three variables if necessary to use counts with high numbers...

- Nick
sonneveld ok, added plan of action, tools available, more comments for ideas, syntax suggestions and compile process.

Compiler Discussion Summary

if people have trouble accessing it, I'll move it to my dingoblue server.

- Nick
eidolon How would the compiler choose logic number for rooms?
sonneveld I thought first come first served would be best.  You'd have to make sure logic.0 was logic 0 but the rest it wouldn't matter as much.

logics that represent rooms could have a picture associated with it, so the picture has the same number as the logic.

- Nick
eidolon In the proposed syntax, how would OnNewRoom{} etc work?

Would they simply replace the equivalent if statement?

Would they be more like function definitions? If so, in what order would they be called?
Could this potential arbitrariness cause problems or bugs?

sonneveld That's a good point and I've been thinking about it..

we could
1) call it like functions from the main code
2) compiler does it automatically (ie, replace the equiv if statements)

I like 2 because it makes the room definition less kludgey but with 1 you could say when anything is called.  In the definition of the syntax, it could be said that OnNewRoom is checked first.. with OnTouchLeft, TimerUpdate, all that left for last..

it's just an idea.. if everybody feels it would be better just to have it as functions as not part of the room defintion.. that would be cool.

- Nick
Joel I'd lean more toward compiling them to normal if statements, as well.

In compiling functions, you'd have to look out for mutual recursion as well as regular recursion. With inlining, functions calling functions will technically work (as long as you watch out for mutual recursion), but it could very easily produce some massively bloated code. Although I understand the aim is to produce a high-level syntax, I think efficient implementation is an absolute requirement. If it's not efficiently implementable, then maybe it shouldn't be included at all.
Joel By the way, I know that the syntax listed in the discussion isn't supposed to be final, but unless there's some reason to have those parentheses after the OnNewRoom, etc., then I think it would be better to just leave them off.

You could, I guess, also have a way to define new event handlers; for example:

room r
{
 event OnTimerExpire (vCounter == 50);

 OnTimerExpire
 {
 }

}

which could then compile to a simple

if (vCounter == 50)
{
}
sonneveld I thought the brackets would help consistancy.

here's how I thought a timer could work..  some people don't use a timer just for one thing..

room r
{
/* what about a multipler?.. do we want it to follow the number of game loops or every second loop? */
 Timer t;
/* should we define the variable used for t or not? */

 Main
 {
   if (said("hello"))
   {
   // inline "function'
   t.init(0);  // 0 in case you want to start later for debugging
   }

   // this is a problem though.
   print("timer=%v(t)")
 }

 // when timer reaches ten
 OnTimer(10)
 {
 }

 // for large numbers, the timer could use two vars, it would just update two on the game loop.
 OnTimer(1024)
 {
 }

}

One thing I would also like is the ability to have a one line if statement without using scope brackets.

- Nick
Joel If the parentheses will be used for some of the event handlers than it would be better for all of them to have them. I just hadn't seen any that used them.

I wasn't really talking about timers specifically. I was really talking about something more general, such as

room r
{
 event OnPlayerStandingInTheRightSpot(posn(ego,1,2,3,4));

 OnPlayerStandingInTheRightSpot
 {
 }

}

basically:

event event-name (condition that triggers the event);

I don't necessarily mean that as a syntax suggestion. I'm just suggesting the possibility of user-defined events.
Joel What do you mean by a one-line if statement? Do you mean

if (f3)
 v1 = 2;

kind of thing? I would like to see that, but only because I want to be able to say

if (f3)
{
}
else if (f4)
{
}
else if (f5)
{
}
sonneveld yes, sorry.. that's what I meant.

- Nick
sonneveld how would we define the order that the events are checked however?  you might want to define a said("eat", "ham') event before a said("anyword"). or one OnObjInBox before another if they overlap..

should it just fall on the order they are defined?  but make sure that the OnNewRoom event is checked before any other.

- Nick
Joel I wouldn't say that it would be necessarily be a good idea to completely substitute events for if statements even though in many cases they could more or less be considered the same thing. There are cases such as:

if (said("look", "tree"))
{
 if (vDayNumber == 1)
 {
   print("The tree is nice.");
 }

}
Joel Ok, I gotta stop writing code in these boxes. I keep forgetting that the tab key moves you to the Post button.

I wouldn't say that it would be necessarily be a good idea to completely substitute events for if statements even though in many cases they could more or less be considered the same thing. There are cases such as:

if (said("look", "tree"))
{
 if (vDayNumber == 1)
 {
   print("The tree is nice.");
 }
 else
 {
   print("The tree was cut down yesterday.");
 }
}

That example was really meant to illustrate an if statement inside something that could be considered an event, but I also just realized that any time you want to have an else branch might be problematic with that event syntax.

OnNewRoom
{
}
else
{
}

seems pretty awkward to me. Otherwise, I'm thinking that the entire room should be executed the same way that logics are executed currently, with a Main section not being required, so something like the following could be said:

var vSomeVar = 0;

room r
{
 

 OnNewRoom()
 {
 }

 vSomeVar++;

 // I know this isn't necessary for this example,
 // but there might be some situation where
 // it is cleaner

 OnNewRoom()
 {
   print("You've visited this room %vSomeVar times.");
 }

 // the following section optional
 Main
 {
 }
}
Joel Well, actually, that code in my last example was bad, anyway. It wouldn't give the correct answer, but the point was that there might be something that you want to execute before an event handler is invoked that might be awkward to put inside Main and there might (possibly) be a case where you want an event handler executed twice in the same interpreter cycle.

I think, ultimately, statements such as if (fNewRoom) should still be legal. That would make the new syntax fairly flexible. User defined events may not be easy to work with, so it may be better not to have them. I was just thinking consistency.
sonneveld The problem is that people code event's in other languages assuming that they don't know when it's going to occur.  In AGI we actually can define when they check for events..

I thought it was a nice idea..  perhaps we should just do what you suggest.. remove the Main() distinction (although I'd like to keep it if we decide to add something else) then use macro's for

OnNewRoom()

to

if (isset(newroom))

- Nick
eidolon AGI is already very straightforward. Fancy stuff like Main(), timers, and event types would only confuse me. Please keep it simple and short.

I would be very happy if I could write like this:


room parlour:50
{
Joel I tend to agree with the keep it simple philosophy. Unless we really need these event things (and I don't think we do), it would probably add confusion, especially because events are typically nondeterministic, which is generally confusing enough, but making events that are entirely deterministic would probably be worse, because it goes against the norm.

Also, the more data types that are added, the more difficult it may be for a beginner to grasp the limited nature of AGI. They have to learn, "the sum total of all logics and rooms must not exceed 256" and "The sum total of all vars, pics, temporary variables, and timers must not exceed 256."

The main thing I'd say goes against the idea of event syntax is basically that if statements are practically identical (and in fact are identical if we just treat them as macros). If the preprocessor is good enough, anyone who wanted to do things like that could define a macro themselves:

#define OnNewRoom if (new_room)

or

#define OnTimer(val) if (vTimer == (val))

But I don't think it should necessarily be forced on beginners. It's important to make sure that, in defining this new syntax, that it is actually easier for beginners to understand than the (as eidolon said) already pretty straightforward syntax of AGI. The biggest failure of AGI syntax as it is right now I think is the awkwardness of certain structures such as if else if's

if ()
{
}
else
{
 if ()
{
}
}

and the lack of easier-to-write structures such as switches.
sonneveld I know Mokalus has been working on ARVO amongst other things but I've decided to look into an actual compiler.

The plan is to make a backwards compatible compiler which means less frilly bits like complex expressions. The next step is to somehow incorporate it into agi studio.

...and then start on whatever crazy higher level compiler syntax we feel like. :)

I'm using lex to pick out the tokens, yacc to hopefully check it's syntax. I'm thinking about using m4 (macro preprocessor) to remove comments, expand defintions and include files. The good thing about this is that you can define proper macros hopefully. The only bad thing is that I don't know if I can support the #message syntax.

Anyway.. that's what I'm doing..

The plan is for this new compiler to also generate some sort of map file so nagi can trace through code with line numbers 'n everything.

any suggestions? Right now I'm playing around with LEX and I can get it to detect most tokens.. hopefully YACC won't be too much trickier.

- Nick
Randy Call me crazy, but I'd like to see "if...else if" loops! :)
sonneveld I'd like switch myself.. along with if's without brackets (i think logic doesn't have those)

- Nick
blacki I know you guys have been putting a lot of time and work into this, but does AGI really need improvement? It's about 15 years old and is still being used, that say's something doesn't it?

I just thought if you wanted to improve somthing you could make a compiler/decomiler for SCIV if it isn't already being worked on?

Just an idea.
Brian_Provinciano A good higher level AGI compiler would slow things down, so the games would probably not run on XTs and such (but who needs that). However, by targeting the compiler for games to run on faster computers, you could go all the way, and add compiler generated code that handles pushing and popping variables so to speak, kind of like how some compilers generate code for 16 bit number support on 8 bit machines, or emulated coprocessor stuff, etc.
sonneveld Yes, true.. but I think most people have to be pretty dedicated to work on AGI. If there's SCI and AGS and everything else to compete with it, it will have to move with the times a bit.

Take C, that was developed years ago but they still release new versions of that (there's C99 which is the latest I think)

And why not? If we don't have to spend as much time wrestling with the simple logic, it will actually a HIGH-LEVEL compiler instead of a glorified assembler.

I'm pretty sure SCIV already has a compiler in the guise of SCI Studio.. it's the other bits 'n pieces that need working on. I'm more interested in AGI anyway.. I won't be moving onto sci development.

- Nick
Brian_Provinciano I was thinking about this, and remembered that there are AGI commands which can jump and execute code in any script at any offset. With this feature, you could easily set up your compiler with a library script, which could handle everything you need, such as 16 bit integer emulation, etc.

Also, you could easily modify my SCI compiler to generate AGI code. The kernel calls would be command calls, for example. I know you said you're not interested in SCI, however, if this was the case, then we could easily write SCI procedures in the scripts to emulate AGI commands. If the compiler was modified to keep the syntax, but generate AGI code, and the regular SCI version was used with the AGI command emulation procs, then it would be possible to write AGI code which could be compiled for AGI and SCI.

It's a bit of a wacky idea, but it would work.
Brian_Provinciano I didn't notice that post by Blacki. SCI Studio includes everything except a sound editor, including a compiler. SCIV is SCI0 (EGA). SCIDHUV is SCI1 (VGA). I have built the compiler to work on both (though the one with SCI Studio is only set up for SCI0).

Nick, stick with what you love, there's no need to move to SCI if you don't want. However, my suggested idea in the previous post is very AGI related, so give it a read.
sonneveld I think the SCI2AGI logic would be something that Mokalus of Borg would love to try. :) It sounds good though.. I wonder how much of the syntax you could port over to agi.

A library would be cool (standard agi library.. heh).. actually, when you think about it, the current games all have a standard library.. there's the debug library and the main logic library.. they're just easy to play around with.

there's that along with proper symbols for variables but the original syntax didn't really allow for this and expected the preprocessor to handle that.

Unfortunately, adding that sort of stuff will probably break a lot of code.. that's why I'm starting with a backwards compatible compiler. Even expressions that would require an extra variable is a no no.. where would you get that variable from? how do you know it wasn't used in another logic?

- Nick
sonneveld Another thing is parsing strings. AGI has variable names within strings.. which need to be parsed but I'm pretty sure they don't.. most preprocessors skip strings so I might need to handle that separately.

- Nick
df i'd still like to on the fly convert logic bytecode to z80 :) hehehehe. wrap 'commands' as system calls..
sonneveld Has anybody ever looked into that funky new Amiga interpreter? Apparently you can use as many registers as you want.. which makes sense since it's all interpreted anyway.

- Nick
Mokalus_of_Borg I believe that AGI, as an engine, has a lot to gain from an easier-to-learn and faster-to-use programming language. That's why I started this discussion in the first place. But I found that my skills and time were not too productive in this particular area.

Mokalus of Borg

PS - I'll be interested to see what you come up with, Nick.
PPS - Maybe, just maybe, after AGI2SCI is complete, I might think about SCI2AGI. But don't count on it. :P
sonneveld I'm getting there.. I'm chewing through the "dragon book" (Compilers: Principles, Techniques and Tools) which is apparently pretty good. It's easier to understand than the other book I own on compilers (Compilers for Java.. not the best thing if you want to make one in C) :)

The problem isn't just implementing a compiler for the current syntax.. it's implementing it and keeping room for a new syntax as well.

I think the steps to go are:
- compiler for current syntax
- compiler for new syntax
- implement new commands, extra variable space..

or maybe the other way round.. implement commands for sorely needed features and then the new syntax.

- Nick
Brian_Provinciano Creating my SCI compiler:

I practiced by making some test assemblers and such before making the SCI compiler (it's always good to do drafts and it got me farmiliar with the file format). When it came time to make the final SCI compiler for SCI Studio, I planned it out on regular lined paper for a couple weeks before sitting down and coding it. By the time I was done planning and pseudocoding, I started the actual coding, and it came along quite easily and quickly. I've also been able to greatly expand it to not only support much more language and features, but also target mutiple SCI versions (all from planning).

I've learned over the years that just like writing a good adventure game, building a large or complex program invlovles full planning first as well.

Just as a note, I think it works best to do the planning by hand on paper rather than on the computer in notepad or Word. That way, it's quicker, easier, and any chance I can get to rest my eyes from the computer screen and neck from the chair, yet still be working on SCI Studio is ideal!
sonneveld don't worry, I understand the value of design before leaping into programming. A lot of NAGI was designed that way. I've still got sheets of paper where I wrote down some quick notes or drafted how it worked. You can draw big meaty lines between functions.. very tricky to do on a computer unless you're using publisher.

I don't think any major project can be written without some preplanning. Even if you do manage without it, it might be a mess or had to extend later on.

Believe it or not, an assembler for agi logic exists. The Russian AGDS group hacked together a version of MASM to generate the code.

- Nick
df I had one in nasm. hard coded opcodes done. each opcode was a macro, so it calced jumps and loops correctly :) hard to debug ;) but it worked!! just more crap never recovered from the hd crash that nearly killed yggdrasil v0.something... heh... :)