Read-only archive of the Armageddon Games Forums Archive (2000–2026) · About this archive

AngelScript: The Revenge

114 replies · 56,127 views · Started 17 January 2017

Tamamo wrote:Oh no I'm very serious, one project that has done incredible things with lua is Starbound which also uses JSON along with it and was created to be moddable from the bottom up. This is the sort of approach we need to take when implementing a new language, in fact I'd rather just rewrite zc from scratch. But ya'll too damn lazy for that.

Well, this is what I have suggested as the proper course of action, post-2.6, several times; and nobody even responds to it. :/

SUCCESSOR wrote:Lua is gross, though. What advantage would it have over AS? Atleast AS is somewhat similar to ZScript. I think that is a big factor in it being the right choice. Most people who script in ZC aren't programmers. They only learn what they need of ZScript and would probably be scared off by something so ... different.

Ah, so I'm not the only one that finds Lua to be a bit awful? Really, it's one of the main reasons that I haven't made a Solarus quest--every flipping thing is coded in Lua. You can't do a blasted thing, without coding it as a Lua block, other than place graphics, which are read form a text file listing all of them, into the Lua engine.

I haven't used AS, but I like the look of it. And it weirdness, like it's handling of references, I could get used to and I understand why they are that way.

I also kind of hate Lua and Python; just can't stand them.

My personal coding style produces mainly small but easily caught (most at compile-time) and easily fixable errors that are usually obvious at a first debugging pass in the case something doesn't work. For me functional languages actually mean dysfunctional--I don't need or want dynamically typed code that just silently fails and doesn't help you where it seems to matter.

Gleeok wrote:I also kind of hate Lua and Python; just can't stand them.

My personal coding style produces mainly small but easily caught (most at compile-time) and easily fixable errors that are usually obvious at a first debugging pass in the case something doesn't work. For me functional languages actually mean dysfunctional--I don't need or want dynamically typed code that just silently fails and doesn't help you where it seems to matter.

I'm personally not a huge fan of forced indentation scoping. It's easy to copy/paste through some medium, lose your indentation, and be entirely #^#%ed.

This is one of the things that Ruby did right. That, and a lot of other things, but that's a topic for another day, and as I have no practical application for anything outside of cpp at present, ...

The funny thing, is that I was once accustomed to indentation coping, and now, I can't stand it, because braces do not suffer the loss of tabbing issue.

Gleeok wrote:I also kind of hate Lua and Python; just can't stand them.

My personal coding style produces mainly small but easily caught (most at compile-time) and easily fixable errors that are usually obvious at a first debugging pass in the case something doesn't work. For me functional languages actually mean dysfunctional--I don't need or want dynamically typed code that just silently fails and doesn't help you where it seems to matter.

I'm not sure why you brought up functional languages (and I wouldn't really consider python as one), and then instead complained about dynamic typing?

I generally view it as a tradeoff. I mean, it's nice being able to detect a certain class of errors ahead of time, but for most of those you'll quickly detect them during runtime. And if you're doing a big project, you shouldn't be relying on the compiler for correctness anyway. So, it's at the point where I can't clearly say that one is better than the other.

Grayswandir wrote:I'm not sure why you brought up functional languages (and I wouldn't really consider python as one), and then instead complained about dynamic typing?

I generally view it as a tradeoff. I mean, it's nice being able to detect a certain class of errors ahead of time, but for most of those you'll quickly detect them during runtime. And if you're doing a big project, you shouldn't be relying on the compiler for correctness anyway. So, it's at the point where I can't clearly say that one is better than the other.

Because both Python and Lua boast to be "multi-paradigm" and let you write functional code. Both Lua and Python are also dynamically-typed languages and claim to be. Not even my words, but theirs.

You missed my point. For my personal style, most of my stupid errors (bugs in dynamic languages, if you will) are caught at compile time meaning that I don't even have to run the thing to find out I messed up some parameter or whatever. Therefore, I prefer to work with statically-typed code. That's just my preference. 😊

Let's talk about the AS syntax really quick.


//note: code is gibberish, it doesn't do anything.

//HANDLES
void Foo(Ref@ ref) //option A:
{
@ref = @Ref.Create(); //points to a new thingy.
ref = otherRef; // now it value copies other thingy. whoops.
}

// confused yet? ...well then:

void Foo(Ref ref) //option B:
{
ref = Ref.Create(); //points to a new thingy.
ref = otherRef; // now it POINTS to other thingy instead.
}

int e = Enum::Value;
int i = A::B::Value;
int v = this.Value;
int x = Object.Value;
Link::X = x;

..confused again?

int e = Enum.Value;
int i = A.B.Value;
int v = this.Value;
int x = Object.Value;
Link.X = x;

// Current annoyance... but unlikely as part of the ZC script API. ...idk
void Foo(const int &in a, int &out b, Object &c)
{
}

//unless we allow unsafe references only "out&" or "&inout" is really useful.

Script language reference: http://www.angelcode.com/angelscript/sdk/docs/manual/doc_script.html
Other issues?

Gleeok wrote:Let's talk about the AS syntax really quick.


//note: code is gibberish, it doesn't do anything.

//HANDLES
void Foo(Ref@ ref) //option A:
{
@ref = @Ref.Create(); //points to a new thingy.
ref = otherRef; // now it value copies other thingy. whoops.
}

// confused yet? ...well then:

void Foo(Ref ref) //option B:
{
ref = Ref.Create(); //points to a new thingy.
ref = otherRef; // now it POINTS to other thingy instead.
}

int e = Enum::Value;
int i = A::B::Value;
int v = this.Value;
int x = Object.Value;
Link::X = x;

..confused again?

int e = Enum.Value;
int i = A.B.Value;
int v = this.Value;
int x = Object.Value;
Link.X = x;

// Current annoyance... but unlikely as part of the ZC script API. ...idk
void Foo(const int &in a, int &out b, Object &c)
{
}

//unless we allow unsafe references only "out&" or "&inout" is really useful.

Script language reference: http://www.angelcode.com/angelscript/sdk/docs/manual/doc_script.html
Other issues?

Looking at that syntax makes me feel like I'm looking through the source code, just to do a little scripting. I'm not entirely sure how this will help people learn the language?

Dimentio wrote:Looking at that syntax makes me feel like I'm looking through the source code, just to do a little scripting. I'm not entirely sure how this will help people learn the language?

It's not. We have to set up how we want scripts to behave, and set up compiler options accordingly; perhaps even have some form of code standard. Have you ever been to an eye doctor and they asked you "A or B?" Well that's what we have to figure out. That code is purposely ugly for this purpose.

Gleeok wrote:It's not. We have to set up how we want scripts to behave, and set up compiler options accordingly; perhaps even have some form of code standard. Have you ever been to an eye doctor and they asked you "A or B?" Well that's what we have to figure out. That code is purposely ugly for this purpose.

Ah. I vote on making it as close to ZScript as possible, without it's limitations.

Well, there are limitations of the language itself and limitations of the implementation. In ZScript's case, there are plenty of each. Whatever else might be said about them, AngelScript, Lua, and Python all have a lot fewer of the former.

Dimentio wrote:Ah. I vote on making it as close to ZScript as possible, without it's limitations.

Actually, that syntax is like ZScript. The reason you haven;t seen some of that, is because the parser doesn't handle all of the available C syntax that it could. There has been some improvement in that area. There's very little proper C syntax that it could not handle--or really, handle without a lot of work. It could theoretically do anything that a full C parser could do. Cpp syntax is something else, as it continually morphs with each new revision. There are things that cpp allows that I didn't know about until recently, and not all compilers may support them (read, CPP11), and yet others that it does not support, but compilers may (e.g. variable array declaration, supported by gcc).

How the hell would array pointers translate? That's a fundamental question, and concern.

Dimentio wrote:Ah. I vote on making it as close to ZScript as possible, without it's limitations.

Probably the best possible answer. 😉 I will do that.

Sure. Right now I've got the parser and compiler working and can create and call scripts. The first test scripts should be forthcoming this week.

I'm going to experiment with the compiler options to see if I can get rid of handles or not. The docs are not clear on this. ("handles" are the Class@ c; @c = @something; Foo(@c); stuff)
[EDIT] This unfortunately produces weird compiler errors. "Normal" scripts and all engine declared things will not force scripts to use them, however if you write classes and want to communicate custom classes with each other then in those cases you will have to use them as parameters. It's likely most normal scripts won't ever need them... I think...

There's no ZC bindings for the time being until everything is tested fully, but I can put in a math library for collisions and vector math stuff. It is important to implement these c++ side to get all the performance benefits of c++ compiled code and have scripts use that directly with no intermediate layer. What I'm going for is at least a 20x performance increase over ZScript for common tasks. We'll see what happens.

Gleeok wrote:Probably the best possible answer. 😉 I will do that.

Sure. Right now I've got the parser and compiler working and can create and call scripts. The first test scripts should be forthcoming this week.

I'm going to experiment with the compiler options to see if I can get rid of handles or not. The docs are not clear on this. ("handles" are the Class@ c; @c = @something; Foo(@c); stuff)
[EDIT] This unfortunately produces weird compiler errors. "Normal" scripts and all engine declared things will not force scripts to use them, however if you write classes and want to communicate custom classes with each other then in those cases you will have to use them as parameters. It's likely most normal scripts won't ever need them... I think...

There's no ZC bindings for the time being until everything is tested fully, but I can put in a math library for collisions and vector math stuff. It is important to implement these c++ side to get all the performance benefits of c++ compiled code and have scripts use that directly with no intermediate layer. What I'm going for is at least a 20x performance increase over ZScript for common tasks. We'll see what happens.

Why would you get rid of handles?

Gleeok, please tell me you're joking for once. I really want my callback functions this time around.

Joking you say?! I never joke. 🙄

SUCCESSOR wrote:Why would you get rid of handles?

They're not needed since the compiler should be able to know all the types at compile. I remember years ago (2011?) Andreas said that for AS ver. 3.0 he wanted to revamp the language to allow this. There's a few options for this but it's not complete. There's no real reason other than simplifying the syntax for scripters to be closer to something more familiar like ZScript or CS.

[MENTION=42714]Gleeok[/MENTION]
Just cause your compiler know the types, doesn't mean it knows the scope of it's functions and such. We need function callbacks and message handlers for that sole reason. Since you seem to be so set and determine on simplifying the syntax; which is something i have been completely against since the start of this discussion. This is for several reasons. First I hate the simplification of C to ZScript, Second people need to learn to adapt. I'm not even a programmer, I'm a freaking artist and I can learn a programming language easily if I put my mind to it. Anyways will simply move on from this project. And start dedicating my fulltime to other projects. Adios Amigos

Tamamo wrote:[MENTION=42714]Gleeok[/MENTION]
Just cause your compiler know the types, doesn't mean it knows the scope of it's functions and such. We need function callbacks and message handlers for that sole reason. Since you seem to be so set and determine on simplifying the syntax; which is something i have been completely against since the start of this discussion. This is for several reasons. First I hate the simplification of C to ZScript, Second people need to learn to adapt. I'm not even a programmer, I'm a freaking artist and I can learn a programming language easily if I put my mind to it. Anyways will simply move on from this project. And start dedicating my fulltime to other projects. Adios Amigos

Not sure I understand what you mean? I'm talking about the angelscrit compiler and the author of the language. I'm not talking about removing any functionality of the language. Anyways, that functionality is not complete so it's kind of moot.

Callbacks ARE being put in, that's kind of a main point.

I think it's important to keep in mind a separation between the semantics we want, and the details of the syntax.

Moving to message handlers is a big change in semantics and it's important that we hash out the details of how we want scripts to interact with the game engine and with each other using this system.

Syntax is important, especially for easing the transition from other languages to AS, but much less urgent to argue about right now since it is easier to change (by modifying AS, or preprocessing) than core semantics.

Yep, it should be fine once I figure out how to split the dang asTT_Scope token type into forwards and backwards tokens. :/

If anyone with some 1337 c++ macro skills wants to try their hand at generating about 100x the classes that this one currently does feel free to go crazy show me up. (It only generates a 38kb script file ATM which isn't near enough for serious performance or memory allocation testing.)

https://github.com/ArmageddonGames/ZeldaClassic/blob/master/src/experimental/Scripts/TestCompileTime.h

If you remove handlers the callbacks are going to be a bitch to work with [MENTION=42714]Gleeok[/MENTION], there I spelled it out fo you.

just popping in to say it's starting to look good. 😊 Not saying zc script types will be done very soon but...

Tamamo wrote:If you remove handlers the callbacks are going to be a bitch to work with [MENTION=42714]Gleeok[/MENTION], there I spelled it out fo you.

I meant the syntax, not the actual handles. That would require rewriting the entire script library; that's just crazy sauce. 😉

Gleeok wrote:I meant the syntax, not the actual handles. That would require rewriting the entire script library; that's just crazy sauce. 😉

Okay first what the fuckall you talking about, zscript syntax doesn't even have function handles. Second enlighten me.

Tamamo wrote:Okay first what the fuckall you talking about, zscript syntax doesn't even have function handles. Second enlighten me.

This is Angelscript not ZScript. Declaring and using "handles" means typing the "@" @at @symbols @everywhere @in @the @scripts. @The @person @who @wrote @the l@anguage @and a@ll t@he @code @had s@implifying @this @on @his @todo@ list@ for @AS 3.0. @But it @seems @it @hasn't @happened @yet.

Also, sure thing:

User posted image

Are you enlightened now?

Gleeok wrote:This is Angelscript not ZScript. Declaring and using "handles" means typing the "@" @at @symbols @everywhere @in @the @scripts. @The @person @who @wrote @the l@anguage @and a@ll t@he @code @had s@implifying @this @on @his @todo@ list@ for @AS 3.0. @But it @seems @it @hasn't @happened @yet.

Also, sure thing:

User posted image

Are you enlightened now?

Another reason i dont like angelscript. It's implementation of callbacks and handles is just plain stupid.

Tamamo wrote:Another reason i dont like angelscript. It's implementation of callbacks and handles is just plain stupid.

Is it really that different to using *pointer ? I suppose you could always change the preprocessing and lexing side to use *handle?

Here's a question that has been bothering me: Is this parser that you are making still going to use the present ffscript code? If so, and it is just a drop-in replacement for flex-bison, then I would be willing to help test, and possibly work on it, but it it means rewriting ffscript, and all the functions... Hell, will it be using ri->D[] and similar? How will it change stack calls? As far as I can see, it requires rewriting the whole damned engine, which is why I'm not interested in working on it.

ZoriaRPG wrote:Is it really that different to using *pointer ? I suppose you could always change the preprocessing and lexing side to use *handle?

Here's a question that has been bothering me: Is this parser that you are making still going to use the present ffscript code? If so, and it is just a drop-in replacement for flex-bison, then I would be willing to help test, and possibly work on it, but it it means rewriting ffscript, and all the functions... Hell, will it be using ri->D[] and similar? How will it change stack calls? As far as I can see, it requires rewriting the whole damned engine, which is why I'm not interested in working on it.

Nope. 18-bit zscript fixed types are an atrocity. No more divide or multiply by 10000 stuff. There, I said it. :P
It is also not compatible with the current ZScript parser, which is actually a good thing.

Let me fill you in on what is done really quick. -(Keep in mind I did all this in one week, by myself; like I said last year: if we move away from ZScript then productivity will increase by a huge margin and people will be able to work with it much easier)

~We have a fully standards compliant c/c++ preprocessor that scripts /and engine/ may use.
~As per above, script logging, asserts, and exceptions are only compiled with the "DEBUG" flag set. This means no commenting in/out Trace(..) functions, and script errors give detailed info and even a callstack.
~The compiler/preprocessor is separate from ZQuest and ZC, (and serialization support for edit/continue is planned). This means you will be able to recompile/write/test scripts directly while you test them in ZC.
~Compilation is currently blazing fast compared to the ZScript parser: A 120 KB script file compiles and builds in 0.2 seconds and I have not even optimized anything (But if you know me you know I will!). :P
~Math library built in is already 10x the usefulness of ZScript. We have vector math and utility types that are all c++ code so scripts will be very fast as they just call directly into an c++ function. Parts of std.zh will be put in c++ as well so huge speed improvements all around are planned.
~Delegates and callbacks are basically in already (see other thread on messaging).
~No limit (currently 2048) on scripts. RAM usage seems to be very low so I don't see why not.

What's going in this week:
~Maybe DMap, Map, Screen, and Global Scripts. (Whatever I feel like basically)
~Any script can be created at any time by any other script. For example:


class ChildrenOfTheCorn
{
int Children;
int Corn;
void MakeSequel(bool blood) {...}

//stuff (like an ffc script kinda)
}

void OnSomeCallback(...) //called by the engine
{
foreach(...)
{
Script@ globalScript = zc.CreateScript(GLOBAL, "ChildrenOfTheCorn"😉;
globalScript.Children = 212;
globalScript.Corn = lots;
globalScript.MakeSequel(true);
}
}

It's not all fun though. The bindings to existing ZScript things are going to take the longest. Although comparatively speaking each built-in function is much easier to add to AS than ZScript, they don't exist yet.

Gleeok wrote:Nope. 18-bit zscript fixed types are an atrocity. No more divide or multiply by 10000 stuff. There, I said it. :P
It is also not compatible with the current ZScript parser, which is actually a good thing.

Let me fill you in on what is done really quick. -(Keep in mind I did all this in one week, by myself; like I said last year: if we move away from ZScript then productivity will increase by a huge margin and people will be able to work with it much easier)

~We have a fully standards compliant c/c++ preprocessor that scripts /and engine/ may use.
~As per above, script logging, asserts, and exceptions are only compiled with the "DEBUG" flag set. This means no commenting in/out Trace(..) functions, and script errors give detailed info and even a callstack.
~The compiler/preprocessor is separate from ZQuest and ZC, (and serialization support for edit/continue is planned). This means you will be able to recompile/write/test scripts directly while you test them in ZC.
~Compilation is currently blazing fast compared to the ZScript parser: A 120 KB script file compiles and builds in 0.2 seconds and I have not even optimized anything (But if you know me you know I will!). :P
~Math library built in is already 10x the usefulness of ZScript. We have vector math and utility types that are all c++ code so scripts will be very fast as they just call directly into an c++ function. Parts of std.zh will be put in c++ as well so huge speed improvements all around are planned.
~Delegates and callbacks are basically in already (see other thread on messaging).
~No limit (currently 2048) on scripts. RAM usage seems to be very low so I don't see why not.

What's going in this week:
~Maybe DMap, Map, Screen, and Global Scripts. (Whatever I feel like basically)
~Any script can be created at any time by any other script. For example:


class ChildrenOfTheCorn
{
int Children;
int Corn;
void MakeSequel(bool blood) {...}

//stuff (like an ffc script kinda)
}

void OnSomeCallback(...) //called by the engine
{
foreach(...)
{
Script@ globalScript = zc.CreateScript(GLOBAL, "ChildrenOfTheCorn"😉;
globalScript.Children = 212;
globalScript.Corn = lots;
globalScript.MakeSequel(true);
}
}

It's not all fun though. The bindings to existing ZScript things are going to take the longest. Although comparatively speaking each built-in function is much easier to add to AS than ZScript, they don't exist yet.

What are you planning to do to convert all of the existing types? What type are the existing int and float declarations from script code using?

You didn't ever answer my concern about zscript object, and array pointers; given that AS doesn't have pointers at all, I need to know how that syntax would cross, if at all.

Is it going to be able to utilise the ZASM labels and registers, by removing the division and multiplication factors? Are you just implementing zscript INT and FLOAT as real floating pint with four points of precision? Isn't that going to cause hell with typecasting, given that ZASM stuff expects longs and ints (and occasionally fixed values), and the ZC engine needs fixed values regularly?

I would just have added a type for fixed to it, and parsed the old scripts to that. I'm still unconvinced about compatibility here, because none of these issues have ever been addressed, so, let me know.

I would absolutely need to see how you convert ZASM functions across, and such.

I don't read/write from ZASM bytecode at all. It's all separated. ZScript is only 32 bit integers, so this best maps to int by default. Having AS to be responsible for maintaining legacy zscript bytecode was never a goal, and I suspect never will be, but even though I'm not going to do it, maybe someone else will.

AS can work with native types easily, this includes pointers, primitives, and structs. ZScript can only handle one type: long.

You're thinking about it the wrong way:
The truth is nobody really wants (or has enough experience) to work with the ZC code because the reality of breaking computability is such a huge burden that most people are crushed by it instantly when they realize how difficult simple refactoring or other trivial things could become. In addition, we're basically running out of useful things to add to it due to complexity of working with the old systems. I'm not going to be able to get to a ZC 3.0, the best I can do is clean up some of the allegro stuff and replace it one thing at a time. You guys are pretty much the only new people who are working on ZC right now. Surely you realized by now that it's way more complicated than it needs to be, and that for all the cool stuff and good work you guys have done on 2.5x the amount of time spent for very minor improvements is sort of disproportional. If the next-gen of ZC developers want to do things differently, or even the same, then they should have that option, and I'll support them. Saffith has moved on, and the truth is I never really came back. I'm still semi-retired, and will probably stay that way for a while; I just have too many other things to do. At least Dark Dragon is currently around for the time being.

AS is something that is documented, works well, an anybody can work with without too much trouble. It's more for the future of ZC rather than the past, to put it one way. We won't even add it until 2.6 so it doesn't interfere with 2.5+.