Opinion: AngelScript 2.0 operators

Started by
24 comments, last by WitchLord 19 years, 4 months ago
Hi, everyone! As I'm working on AngelScript 2.0 I'm finding it necessary to take certain decisions, some are easier than others. Right now I've come upon one that is not so easy to take on my own. With AS 2.0 every object is stored by reference (sort of like a smart-pointer). Thus if you assign an object variable to another both variables will hold references to the same object. My doubt is what I should do with the operators for objects. Alternative 1 will have operators for assigning and comparing object references, but will not allow overloading of operators to make it easier to use objects in expressions. Advantages: Simpler language hence smaller library, and easier interface. Disadvantages: Clumsier to write code with many operations on objects. Function calls instead of operators.

// Declare object variable
obj a = new obj();  

// assign reference 
b = a; 

// copy object value
b.Copy(a);

// comparison of the reference
a == b; 

// Add two objects
a.Add(b);  

// Compare the value of the objects
a.Compare(b); 

Alternative 2 will have special operators for assigning and comparing references, and will allow overloading of operators for normal objects. Advantages: Cleaner syntax where objects are included in expressions. Disadvantages: More complex language, and more complex library and interface.

// Declare object variable
obj a := new obj();  

// assign reference 
b := a; 

// copy object value
b = a;

// comparison of the reference
a === b; 

// Add two objects
a + b;  

// Compare the value of the objects
a == b; 

I also have a third alternative. Which would allow the application to register primitive objects. Primitive objects are classes that only hold primitive values, i.e. it doesn't need a destructor or special assignment operators to manage resources. These primitive object could be stored by value instead of by reference, just like normal primitives like int, float, etc. The library could allow operator overloading only for this type of object. It would then be easy to write special datatypes like Vector3, Point2D, that allows use of operators in expressions. Other objects that need the special management are passed around by reference and don't allow overloaded operators. Advantages: Allows the creation of new primitive types in the language, while still allowing the use of references. The language will still be easy to use. Disadvantages: More complex library. Let me hear what you think. And if you have suggestions for other alternatives I'm also interested in hearing those. Personally I'm leaning towards alternative 2.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement
Giving it some more thought I came up with a 4th alternative:

Normal binary and unary operators will be overloadable, but the assignment operator (including compound assignment) is not overloadable.

// The object has the + operator overloaded// Declare object variableobj a = new obj();  // assign reference b = a; // copy object valueb = new obj(a);b = a.clone();b.copy(a);// comparison of the referencea === b; a !== b;// Add two objectsa + b;  // Compare the value of the objectsa == b; a != b;


A compound assignment would unlike C++ be only a faster way of writing the operator followed by the assignment, i.e:

a += b;

is the same as

a = a + b;

(In C++ this is not necessarily true as += is a special operator)

I believe this will be the way I'll implement AS 2.0, unless you find any arguments that makes me change my mind.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I would prefer alternative 2, but I find := not a really logical choice for the 'assign reference operator', maybe '= &' like in PHP? You could have a 'make a reference' operator that returns a reference to an object, then you can assign that reference to a variable.

EDIT: I have always found it very confusing that = means copy assignment for primitives, and reference assignment for objects in for example Java. If = becomes assign reference; you should not make an exception for buildin primitive types.
I would prefer to be as close to C++ as possible. IMO usage of references to objects is okay as long as it doesn't add new strange operators to the language, like === or := (Pascal :( style). Many of us choose AngelScript because it was close to C++ (now is fast too :)

So for objects I would suggest going with references as default in operators and when values are needed the object name could be used (for one of the members):

Obj a = new Obj(), b;
// Reference assigment
b = a;
// Value assigment
b = Obj(a); // or Obj(b) = Obj(a)
// Reference comparison
b != a
// Value comparison
Obj(b) != Obj(a)

Overloading of operators are only for value operators (why should I overload a reference comparison ?).

Another alternative would be usage of &:

// Reference assigment
&b = &a
// Value assigment (error if b is not pointing to a valid object)
b = a;
// Reference comparison
&b != &a
// Value comparison
b != a

Or maybe * to dereference:

// Reference assigment
b = a;
// Value assigment (error if b is not pointing to a valid object)
*b = *a;
// Reference comparison
b != a
// Value comparison
*b != *a

If this is not possible (maybe would complicate the syntax as pointers do) I would go with alternative 1 which is closer to C++ syntax.
Personally, I think that passing by references should be "behind the scenes" and as transparent as possible. Therefore, when you assign a = b, a should be a copy of b, so that modifying b will not affect a.

Here's what I think should happen (also note that I don't like the use of new, it confuses the hell outof me in c# how you can use new on some objects, but some of them don't need it!?)

// Declare object variableobj a();  // assign/copy objectb = a;//b.ModifyValue();//now a != b!// make them point to the same thingb = &a;// comparison of the two referencesa.Is(b);//a is b; //Looks nicer, but harder to implement//usage://if (a is b)// Add two objectsa + b;// Compare the value of the objectsa == b;


Note, to make the two object point to the same thing (so modifying b will change a), i used &object as I believe it looks like c++ and forces you to think, do I want both object pointing to the same thing? I don't think the & operator should return anything, it should just be used by the compiler.

Just though I'd give you some more ideas.
IMO, if you're going to be adapting the way Java does objects, it would make more sense to follow Java's syntax instead of ignoring the time Sun spent on designing it.

Though I think keeping with the C++ syntax of using & to assign references then letting = be overloadable would be best, I'm guessing parsing the & would add to the compile time.

Otherwise, I like alternative 4 the most, aside from the === and !==. Perhaps something like ref(a) == ref(b) would work if & couldn't be used. I feel it depends a lot on how often people will need to use the reference of an object in comparison tests.

I've probably just said I like all the different ways, but what I mean is that if keeping the language as much like C++ as possible and be more familiar with C++ coders is higher priority, then go with that route, but I personally would prefer to code using alternative #4.

Just my two cents.
Right now, I think Licu's first idea is the cleanest. I do like the syntax of the second better, though.

desertcube also has some nice ideas with the "is" operator. To the parser, it shouldn't really matter if it uses == or is. I recall that the binary operators were first in words (xor, or, not, ...).

I personally think that assignment should make a copy by default, as this is the most logical reason for using that operator. I can't really think of any instances where you wouldn't want to make a copy. So in short, operators should reffer to the value by default. The refference should be used if a special operator is used, like &.

I'm really against using special operators like := and ===, they confuse the heck out of me.
I know what's going to happen to me. I'll become helplessly lost, and generate tons of bugs, wondering 'I set a to b... if I change a, won't b change?? Oh spat!'.

But I've already decided I won't be going to AS2.0 for this project so :P
In response to Gyrbo, the reason you'd want to assign things by reference is speed. You don't want to copy objects all the time, that's why C++ has pointers. In Java, they do it by having everything be references.

Say you're going through some array, like complexarray[a][c], and want to start calling stuff from an object in it, so you do Object temp = complexarray[a][c]; If temp was just a copy or clone, modifying it would mean nothing - complexarray[a][c] would remain unmodified. The solution in C++ is to do Object *temp = &(complexarray[a][c]); or similar (I forget order of op. with &).

I believe AngelScript 1 already does this the C++ way, but WitchLord wanted to have 2.0 to be similar to Java where the variables are references (At least that's what I understand) and so it would make little sense to have the assignment operator do cloning.

Hopefully that makes some sense.
Mortal, thanks for explaining that. I already understood the concept of refferences, but I only used them for functions before.

I still think that copy by default is the most desirable. If you make a copy instead of a refference, there will be less cases of error. Otherwise you might have people wondering why changing a also modifies b.

I don't have a java background, so I'm basing myself on PHP here. I like the refference system they use (in PHP 4 at least, I heard it changed in version 5). You simply use the & operator if you want to create a refference, both in functions and in assignment.

I'm not sure if this is feasable(sp?), but having a special refference type might be useful if copying is the default behaviour. The reason this might not get adding is because this looks a lot like the pointers WitchLord was trying to remove.

This topic is closed to new replies.

Advertisement