Perfect language features

Member
Posts: 39
Joined: 2002.04
Post: #1
I've been working on a game oriented programming language for a while, I don't know if I'll ever have the time to implement it - it's still in the specification stage.
The recent thread about "The Perfect Game Programming Environment" has made wonder what kind of features people would like to see or would find useful.

Below is a preliminary list of design goals:
Code:
* Be useful for game development (and general programming).
* Speed (low level) - at C / C++ level when needed.
* Extensible - Simple system level access, it should be _very_ simple to interface
  with OS and 3rd party libs (primarily C/C++).
* Rapid development
    - Refactoring - it should be easy to change the code at need and support
      evolutionary requirement changes.
    - High level - small semantic gap between idea and code i.e. fast
      development.
    - Scaleable - it should be easy to write both small scripts as well as apps
      that use millions of lines of code and still be able to maintain the
      system.
    - Concurrency & networking - systems should scale well with a minimum of
      changes to run on larger systems - more than one CPU or distributed in a
      network environment.
    - Useful set of base libs, like:
        + math (physics, 3D, statistics)
        + Flexible string processing (lib or syntax ?) - useful for
          scripts ...
        + Constraint / search / AI problems - backtracking ... ?
* Safe  
    - No pointers(supply useful base types), no state management(use functional
      lang), no memory management (use GC) and loop constructs that don't
      suffer from looping one step to far or to short(use higher order funs).
    - Error handling.
    - Default behavior should always be safe rather than fast, speed is usually
      gained by the loss of safety and rapid development (by introducing more
      complex low level code).
* Maintainability
    - Comprehendible error messages, useful in debugging.
      - It should also be easy to understand code written by others i.e. use
      simple syntax and a minimal number of key concepts i.e. a small language.
      - Documentation should ideally be implicit in the code (preconditions and
      types) or close to it like comments that can be turned into external docs
      like in javadoc.
    - Tool support e.g. profiling and debugging.
    - Easy to interact with / patch / upgrade running system - dynamic code
      load.


Note: the compiler will generate C++ source (which in turn will be compiled) rather than binaries this is for portability reasons and to benefit from the optimization capabilities in gcc.
Quote this message in a reply
Moderator
Posts: 335
Joined: 2002.04
Post: #2
Quote:Originally posted by hokan

* Safe
- No pointers(supply useful base types), no state management(use functional
lang), no memory management (use GC) and loop constructs that don't
suffer from looping one step to far or to short(use higher order funs).
- Error handling.
- Default behavior should always be safe rather than fast, speed is usually
gained by the loss of safety and rapid development (by introducing more
complex low level code).


I'd go for the opposite in a game programming language, you want speed over safety. It's up to the developer to provide safety. Ideally though, you'd want to be able to test the code in an interepreted form before compilation (so you get both speed and safety). Don't set the capabilities of the language by those that don't want to learn to code properly.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
I agree with Hokan, I'd rather have safety than speed most of the time, and since one of his specific goals is that speed should be possible when required, I don't see what the problem here is. 90% of the code doesn't need to be fast, but if it's not safe it'll take 3 times as long to develop that 90% as it really needs to!

Anyway, it sounds a lot like Dylan. Functional, and therefore safe; efficient when necessary; compiles to C so relatively easy to integrate with existing C libraries.
Quote this message in a reply
Member
Posts: 39
Joined: 2002.04
Post: #4
Quote:Originally posted by Zwilnik
I'd go for the opposite in a game programming language, you want speed over safety. It's up to the developer to provide safety. Ideally though, you'd want to be able to test the code in an interepreted form before compilation (so you get both speed and safety). Don't set the capabilities of the language by those that don't want to learn to code properly.


Safety isn't purely a matter of performance it's also a feature of fast development, lets give an example:

Lets assume that we want to loop over an array and write a element n+1 beyond the the end (n = size of array).

* In C this might go unnoticed and result in a strange crash several thousands lines of code later when the overwritten data is used.

* In my case (in safe mode) it would be similar to java - the user would get a outOfBounds error and a stack trace that indicates where the error occurred.

* (unsafe mode) On the other hand when we know that the code works and it has been profiled and found to consume a lot of CPU time - then and only then is the time when it should be decided if we want to resort to compiler flags like "-no_array_bound_check" for that file or maybe even call/embed C code directly.

* (safe and fast) There will also be compromise solutions like "foreach Array DoSomethingCode" or "forrange Range Array DoSomeThing" constructs that can be translated into regular loops, assuming that arrays contain their own length.
"foreach" doesn't need to do any bound checks and "forrange" would only need to do two bound checks rather than one for each "Array[i]=....".
The only limitation of these functions is that they are not as flexible as the regular loops (they can't do random acess).
Quote this message in a reply
Moderator
Posts: 916
Joined: 2002.10
Post: #5
I like pointers
I like memory handling
I like math
I dislike high level routines that slow down low level routines.
I like writing performance code
I dislike exception handling
I dislike bugs, therefore, I do not program them.
speed is ALWAYS better than "safety" you should never use bad programming practices and write sloppy code. and by sloppy code I don't mean you should write "structured" code or "classify your data"
I like fast graphics handlers
I dislike complex graphics handler
I like simple to use structure, CSK was not simple to use. *shudders in horror*
Quote this message in a reply
Moderator
Posts: 335
Joined: 2002.04
Post: #6
Quote:Originally posted by hokan

Lets assume that we want to loop over an array and write a element n+1 beyond the the end (n = size of array).

* In C this might go unnoticed and result in a strange crash several thousands lines of code later when the overwritten data is used.


That's what debuggers are for. don't compromise the speed of the code for sloppy programmers. give them error messages if it's something you can check for while compiling.

Speed is utterly essential for games. The faster all your routines run, the more things you can put in your game and the faster you can read the controls. Also, the faster the code runs, the lower the spec of the base machine for the game and the more money you can make. basically "Less Bloat = More Groat" Wink
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #7
Quote:I like pointers

Hokan's not proposing a lack of pointers, he's proposing a lack of explicit pointers. That means no pointer arithmetic, sure -- but it also means there's less can go wrong with them.

Quote:I like memory handling

I like software without memory leaks. Give me garbage collection any day! I don't like double frees, frees in the middle of allocated blocks, missing allocations, allocations that are too small.

No, I don't make those kinds of errors hugely often -- but I'd prefer to know that I haven't made any. And when I do make one, tracking it down usually takes a significant amount of time I could be using to add features.

Quote:I like math

Hokan specifically stated that his language's standard libraries would include large math libraries. What's your point here?

Quote:I dislike high level routines that slow down low level routines.

I've never seen one function cause another (that doesn't call it) to run slowly. What did you mean?

Quote:I like writing performance code

So do I, when the situation requires it. That's what Hokan's language will give you.

Quote:I dislike exception handling

Arbitrarily? Why? Have you ever used it?

Quote:I dislike bugs, therefore, I do not program them.

Then you're the best programmer in the world. How much do you earn?

Quote:speed is ALWAYS better than "safety" you should never use bad programming practices and write sloppy code. and by sloppy code I don't mean you should write "structured" code or "classify your data"

Safety is not about "sloppy code" or "bad programming practices". It's about productivity. It's about writing the 90% of the code where speed doesn't really matter in 10% of the time, instead of 50%.

Quote:I like fast graphics handlers

So does Hokan, that was one thing he mentioned his language/libraries would support.

Quote:I dislike complex graphics handler

So you'd like high-level language features which make this easier, rather than having to mess with pointers all over the place.

Quote:I like simple to use structure, CSK was not simple to use. *shudders in horror*


At least we agree on one thing Wink

Quote:That's what debuggers are for. don't compromise the speed of the code for sloppy programmers. give them error messages if it's something you can check for while compiling.

It's not for sloppy programmers, it's for the mistakes that all of us have made. Array overruns are probably the most subtle bug ever, because usually if they don't crash now, they won't crash until the implementation of malloc changes, at which point you've really got a tough job on your hands tracking them down.

And you're not sacrificing speed, either. If you don't want the bounds check, take it out. I'd rather write slightly slower code with bounds checking, then remove the bounds checking once I know it works, than make the mistake in the first place.

Quote:Speed is utterly essential for games. The faster all your routines run, the more things you can put in your game and the faster you can read the controls. Also, the faster the code runs, the lower the spec of the base machine for the game and the more money you can make. basically "Less Bloat = More Groat"


Speed is essential, but speed over all your code base is not. Realistically, most games have 90% of their time spent in 10% of their code. That's the 10% that needs to go fast. For the rest, it probably doesn't matter if you can double the speed of some routine, it's simply not getting called enough for the player to care.
Quote this message in a reply
Moderator
Posts: 916
Joined: 2002.10
Post: #8
Quote:Originally posted by OneSadCookie

I like software without memory leaks. Give me garbage collection any day! I don't like double frees, frees in the middle of allocated blocks, missing allocations, allocations that are too small.
memory allocation is fun... and should be dealt with carefullly and cautiously. They are a lot like dragons, beautiful, dangerous, and very powerful.

Quote:Hokan specifically stated that his language's standard libraries would include large math libraries. What's your point here?
I like stories [/simpsons quote]

Quote:I've never seen one function cause another (that doesn't call it) to run slowly. What did you mean?
the string class in C++ is humongous. MOST of the functions are not needed. It gives you a lot of bloat for an array of bytes

Quote:Arbitrarily? Why? Have you ever used it?
I find taking care of the problem right then and there much better. exception handling is ugly looking code. It is bloated in that you have classes made for printing messages. it's just... bad. if(would cause bad case) printf error message, exit (or return depending on the operation and severity)

Quote:Then you're the best programmer in the world. How much do you earn?
nobody will pay me for my far superior and excellent skills Sad

Quote:Safety is not about "sloppy code" or "bad programming practices". It's about productivity. It's about writing the 90% of the code where speed doesn't really matter in 10% of the time, instead of 50%.
true, writing most of the "non speed" code should take less time, but even non speed code should be fast. even if the code is only run once every 10 minutes, it should be fast enough not to bug the user.
Quote:So you'd like high-level language features which make this easier, rather than having to mess with pointers all over the place.
nothing wrong with pointers, and yes I would like high level graphics libraries that can do insanely complex things, still being fast, but be really simple to use. I believe THAT is the holy grail of game programming.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #9
Quote:memory allocation is fun... and should be dealt with carefullly and cautiously. They are a lot like dragons, beautiful, dangerous, and very powerful.

You lose no expressive power by letting the language handle it. You lose a small amount of efficiency (which you seldom get with nicely-written C++ anyway), and a lot of potential for bugs.

Quote:the string class in C++ is humongous. MOST of the functions are not needed. It gives you a lot of bloat for an array of bytes

The C++ STL is pretty much bloat. So what?

a) you don't have to use it
b) if you want a complex container like a map, there's already one written. Rapid development! If it's not fast enough, you can replace it easily enough later...
c) why are you manipulating std::strings in performance-critical code? Call c_str() and length() outside your performance-critical areas and pass that information round. Then they're no less efficient than C strings.

Quote:I find taking care of the problem right then and there much better. exception handling is ugly looking code. It is bloated in that you have classes made for printing messages. it's just... bad. if(would cause bad case) printf error message, exit (or return depending on the operation and severity)

That's appropriate for many parts of a game, where an error is not recoverable, and should either be ignored or be fatal. However, at load time (missing or corrupt files, for example, where recovery is almost certainly possible) exceptions can be a clean way to structure your code for the rare errors.

Have you ever (for example) tried to write something that uses QuickTime's graphic importers? Virtually every line of code can potentially generate an error. That means that every line of code is followed by an if statement passing you off to an error handler of some sort. If you don't want those errors to be fatal, you'll either find yourself using exceptions or goto -- and I know which I'm voting for!

Quote:true, writing most of the "non speed" code should take less time, but even non speed code should be fast. even if the code is only run once every 10 minutes, it should be fast enough not to bug the user.

Sure, but why make your life difficult while programming it on the assumption that it will be too slow? Why not wait until you know it's too slow, then apply the standard optimization techniques you're going to need for the other performance-sensitive parts? Far too often, you don't know in advance what's going to be the slow bit. I'd rather have easy development, have a profiler tell me what's slow, and have focused optimization, than have to deal with things that a language is perfectly capable of dealing with all the time!

Quote:nothing wrong with pointers, and yes I would like high level graphics libraries that can do insanely complex things, still being fast, but be really simple to use. I believe THAT is the holy grail of game programming.


Isn't that what Hokan said?
Quote this message in a reply
Member
Posts: 145
Joined: 2002.06
Post: #10
I'm pretty happy with C++ as it is now, but there's a couple things I'd love to see added to the language:

- object states. Classes can define "states". Each state replaces some or all of the default constants and virtual methods with different versions for that state. This is really useful for game programming. The only language I've seen do this is UnrealScript.
- interfaces. Multiple inheritance adds non-trivial overhead. I'd like to see interfaces like other languages have.
- bitwise rotate and overlay operators built into the language.
- implicit "inherited" class in methods (obviously not for classes with multiple inheritance) so you could have
Code:
class newclass : oldclass{
    virtual void thinger() { // inherited virtual too
        dostuff();
        inherited::thinger();
    }
}
Might also be cool to have inherited(); as a shortcut for "the current method in the scope of the parent class"
- more control over when v-table setup takes place during object construction. I'd like to be able to tell the compiler that for descendants of some class, the v-table should be set up before the parent constructor is called. Likewise I'd like to be able to have v-table teardown after parent destruction (effectively never).
- hinted branches and loops. I'd like syntax to indicate to the compiler what the probability of various flow options is so that it can take advantage of those estimates in optimization. For example if(foo):0.2{...} to indicate an if that will be taken 20% of the time or for(foo;bar;baz):50{...} to indicate the loop will repeat on average 50 times.
- hinted dynamic casts. I'd like to be able to tell the compiler that I'm going to be dynamic casting one specific class to another very frequently, so it should store information to make that dynamic cast as fast as possible.
- explicitly non-volatile pointers. I'd like to be able to specify struct/class members and local pointers as explicitly non-volatile so that they'd be held in registers as much as possible and only written back to or read from memory when absolutely necessary.
- output-only pass-by-reference. (effectively multiple return values).

compiler features:
- pass-by-reference of primitives in registers.
- more efficient and complete register usage. Optimize register saving/restoring around and in leaf procedures. Would require two-pass compiling to figure out how many/which registers a leaf procedure needs/used.
- pass-by-reference of structs in registers. If a procedure only uses a small set of the elements of a struct/class, make the the responsiblity of the caller to load/store those. This would also require two-pass compiling to figure out which elements of a struct each procedure needes.
- transparent "safe pointers" for debugging.

Basically, I'm happy with the language, I'd just like more control over, and be able to give hints to, the optimizer.

"He who breaks a thing to find out what it is, has left the path of wisdom."
- Gandalf the Gray-Hat

Bring Alistair Cooke's America to DVD!
Quote this message in a reply
Member
Posts: 39
Joined: 2002.04
Post: #11
OneSadCookie has essentially summed up my point of view so I only want to point out some minor points:

- We would still write assembler if speed would be the only thing that matters.

- Each level of abstraction (and simplification of coding) consumes some performance but reduces dev time e.g. assembler is faster than C, C is faster than C++ and so forth.

- What I'm trying to do is to allow the programmer to access the lower levels in a simple manner when needed, just like some C++ code may be pure C or some app might include some assembler code.

- There are plenty of cases where programming convenience or flexibility is more important than performance e.g. - scripting languages are often interpreted, this makes it easy to load custom scripts without affecting the main application, libraries like OpenGL or TCP/IP give portability in exchange of performance loss (speed, memory use, bandwidth).

- Also consider that coding and debugging time saved can be used to implement new features or better algorithms for performance critical sections. This can be especially important if you have a limited amount of manpower.

So hopefully we can conclude this argument and agree on that there is trade off between speed of development and application performance. I'm essentially aiming for a simple way to control this balance and get as much performance as possible for as little work as possible.
Quote this message in a reply
Member
Posts: 39
Joined: 2002.04
Post: #12
Quote:Originally posted by inio
I'm pretty happy with C++ as it is now, but there's a couple things I'd love to see added to the language:

....

Basically, I'm happy with the language, I'd just like more control over, and be able to give hints to, the optimizer.


Optimzer hints are interesting but as I will not generate the CPU specific executable code myself, there will naturaly be some limitations to which extent I'll be able to do anything about it.
Quote this message in a reply
Moderator
Posts: 335
Joined: 2002.04
Post: #13
The quickest (?) and easiest solution to an easy development language would be to write a C interpreter that can error check while running.

You'd run your game through the interpreter first and iron out any obvious bugs, then compile for full results.

I've used interpreted C languages before, such as Poco Script in AniPro ( An old PC Animation/Drawing package) and they're rather good for quick early development.

A note to the 'speed isn't absolutely required everywhere' people. It is, even if the bit of code that's only being called 10% of the time is running 50% slower than it should, that's a 5% CPU overhead, that could be the difference between the right number of enemies at a critical point in the game and (the right number - 1) enemies. Don't optimise too early, but don't cripple your game with bloat from your developer environment.
Quote this message in a reply
henryj
Unregistered
 
Post: #14
Quote:that could be the difference between the right number of enemies at a critical point in the game and (the right number - 1) enemies.


What has the speed a function executes got to do with the result that it gives?

Plus your maths is flawed. For a function that executes 10% percent of the time to use 5% of the cpu (on average) it will have to use 50% of the cpu when in does.

Now, lets be slightly more realistic and say that our target function uses 1% of the runtime (which is still a lot). So you optimise it and say it takes you 4 hours to double it's speed which is a pretty good return on your time. Now to get your 'money' back your program will have to run for 4 * 200 hours or 33 days before your optimisation is paying for itself.

I'm sure there are better things you could have done with your time.
Quote this message in a reply
Moderator
Posts: 335
Joined: 2002.04
Post: #15
If that 1% of bloat stops your game running at the required frame rate (even more critical in console games), then you have to sacrifice functionality (ie numbers of enemies on screen at once or detail of models) to get the game to the desired frame rate. Again, this could also be the difference between running acceptably on a slower machine or not as that 1% could just throw it into unusability.

If I needed to spend 4 hours optimising a routine just because the compiler output slow code, I'd be pretty annoyed. I'd rather have the compiler let me make mistakes (and abuse the language to get better results) and have faster code to start with.

I'm not saying you shouldn't have 'protective' code, just that it shouldn't be in the compiler only in the interpreter.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  ALT: The Perfect Game Programming Enviroment henryj 19 8,905 Nov 29, 2002 11:53 PM
Last Post: OneSadCookie