Jump to content

  • Log In with Google      Sign In   
  • Create Account


- - - - -

Opinion: AngelScript 2.0 operators


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
25 replies to this topic

#1 Andreas Jonsson   Moderators   -  Reputation: 3241

Like
0Likes
Like

Posted 19 November 2004 - 09:44 AM

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

Sponsor:

#2 Andreas Jonsson   Moderators   -  Reputation: 3241

Like
0Likes
Like

Posted 19 November 2004 - 10:05 AM

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 variable
obj a = new obj();

// assign reference
b = a;

// copy object value
b = new obj(a);
b = a.clone();
b.copy(a);

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

// Add two objects
a + b;

// Compare the value of the objects
a == 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

#3 twanvl   Members   -  Reputation: 512

Like
0Likes
Like

Posted 19 November 2004 - 10:13 AM

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.

#4 Licu   Members   -  Reputation: 128

Like
0Likes
Like

Posted 19 November 2004 - 11:31 PM

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.


#5 desertcube   Members   -  Reputation: 514

Like
0Likes
Like

Posted 20 November 2004 - 03:07 AM

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 variable
obj a();

// assign/copy object
b = a;

//b.ModifyValue();
//now a != b!

// make them point to the same thing
b = &a;

// comparison of the two references
a.Is(b);
//a is b; //Looks nicer, but harder to implement
//usage:
//if (a is b)

// Add two objects
a + b;

// Compare the value of the objects
a == 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.

#6 Mortal   Members   -  Reputation: 132

Like
0Likes
Like

Posted 20 November 2004 - 08:53 AM

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.

#7 Gyrbo   Members   -  Reputation: 187

Like
0Likes
Like

Posted 20 November 2004 - 11:11 AM

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.

#8 Deyja   Members   -  Reputation: 920

Like
0Likes
Like

Posted 20 November 2004 - 12:18 PM

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

#9 Mortal   Members   -  Reputation: 132

Like
0Likes
Like

Posted 20 November 2004 - 01:27 PM

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][b][c], and want to start calling stuff from an object in it, so you do Object temp = complexarray[a][b][c]; If temp was just a copy or clone, modifying it would mean nothing - complexarray[a][b][c] would remain unmodified. The solution in C++ is to do Object *temp = &(complexarray[a][b][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.

#10 Gyrbo   Members   -  Reputation: 187

Like
0Likes
Like

Posted 21 November 2004 - 01:35 AM

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.

#11 Andreas Jonsson   Moderators   -  Reputation: 3241

Like
0Likes
Like

Posted 21 November 2004 - 02:48 AM

I'll have to agree with that having the assignment operator do a reference assignment by default can be confusing. As I want the script language to be as easy to use as possible, I'll avoid that.

Still at times it is good to have a reference assignment. Maybe I'll go with:

a = &b; // a references b

or perhaps simply use

obj &a = b; // Initialization of reference, further assignment affects b.

I also agree with that the fact that objects are stored by reference should be transparent.

I would also prefer not to add new operators to the language, as it is already quite full of them. I will have to add an operator for comparing references though, or maybe a built in function like C++'s sizeof().

Thanks for the feedback everyone. It's been really helpful. If you have some more suggestions or ideas, please let me know.

---------

I feel I need to explain some of my decisions as well.

I decided to remove pointers from AS2.0 because they complicated matters, and since the language didn't allow manipulation of the pointers anyway, they weren't all that useful.

I also decided to store all objects by reference in the script engine, because it allows me to identify the type at run-time, which makes it a lot easier to do exception handling and context serialization, etc. It should also be quite easy to do dynamic casting of objects with inheritance using this model.

AngelScript won't be exactly like C++, but I'll try to keep as close to it as possible.

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

#12 Gyrbo   Members   -  Reputation: 187

Like
0Likes
Like

Posted 22 November 2004 - 04:43 AM

I think that you should support both methods of refference assignment, but that's just my opinion.

As for comparing references, you should make that as transparant as possible. Some things that I feel are acceptable are:

a == &b
&a == &b
a is b
isref(a, b) //or other name



Some things that I would preffer not to use:

a === b
a.isref(b)
a &== b //Could work, but only if you really don't have anything else
a =&= b //some variation of the above
a !&! b




#13 Mortal   Members   -  Reputation: 132

Like
0Likes
Like

Posted 22 November 2004 - 04:24 PM

I definitely agree with Gyrbo, on both accounts. I prefer the first type of reference assignments over the second, but having both shouldn't be too much trouble I would think.

Some thoughts,
a == &b looks like it would be an overloaded bool operator==(Object * obj), implemented in the class that a belongs to, not dealing with a's reference.
&a == &b is a lot more natural for C++ programmers, and I feel the best way to compare references since it reads 'reference a has the same numeric value as reference b' or close enough :P
I also like a is b, though with this it'd make sense to also provide 'a is <class>' that checks if a is a subtype of <class>.
isref(a,b) I would honestly put in the second list of don't do's :P But that's just me

#14 jetro   Members   -  Reputation: 144

Like
0Likes
Like

Posted 24 November 2004 - 11:27 AM

Generally I like how Java implements things.. in this case, when you do "a = b;" it's reference assignment, and a real copy is done by other means, e.g. via a method (for new copies there's the clone-method). Comparison is through a method as well - "a.equals(b);"

When everything is done via references I think that's pretty clean way to solve the problem. It'll still require user to know and understand that they are working with references. But the other ways to do it, e.g. making "=" to a real copy operator, having "===" for reference comparison etc. sound to me like they really aren't easier to understand at all.

Since AS is heavily C++ influenced, and becoming a bit more Java influenced as well, my personal opinion is that I'd like it to implement things in Java way when possible, and if not, then do it like C++ does it. (that is, avoid adding custom operators with syntax like ":=", "===" etc)
--Jetro Lauha - tonic - http://jet.ro

#15 Sly   Members   -  Reputation: 128

Like
0Likes
Like

Posted 24 November 2004 - 03:17 PM

I agree with jetro. Make it clean and clear to the user what they are doing. The different obscure operators that I have seen suggested in this thread are just going to cause issues through confusion, all because people want to type the least number of keys possible to get something done.

b = a; // Both reference same object instance
b.Copy(a); // b is a separate identical object instance to a

So I would strongly endorse alternative #1.

#16 Andreas Jonsson   Moderators   -  Reputation: 3241

Like
0Likes
Like

Posted 25 November 2004 - 01:32 AM

OK. It seems that everyone agrees that no new operators should be added if at all possible. I agree with that.

What still remains is if an assignment should create a copy of the object, or simply a new reference to the object. There seems to be different opinions here.

Having the assignment do a reference assignment by default would be the same as if all your C++ objects were stored by pointers, so this is in fact very similar to how C++ does it as well. The difference is that the pointer is an implicit smart pointer, that will make sure that the object is freed once all references to it are released.

It may be a little less confusing to a script writer when reference assignments are done. But I think that is only if he didn't read the manual for the script language. On the other hand I believe almost all scripting languages that deal with objects are actually doing reference assignments, think javascript, VBScript, Lua, etc. Why should AngelScript be different? Besides, a reference assignment is a lot faster than making a copy of the object.

Regardless of the decision taken on the question of assignments. AngelScript will continue to support overloading of operators like +, -, etc, as I believe it make the code much easier to read. I believe the comparison operators should also be overloadable operators, comparing the value of the objects and not the reference.

I'm currently leaning towards doing reference assignments. A ref comparison would then be made with the 'is' operator (it's a new operator, I know, but at least it is not obscure [wink]).


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

#17 desertcube   Members   -  Reputation: 514

Like
0Likes
Like

Posted 25 November 2004 - 07:23 AM

Quote:
Original post by WitchLord
Having the assignment do a reference assignment by default would be the same as if all your C++ objects were stored by pointers, so this is in fact very similar to how C++ does it as well. The difference is that the pointer is an implicit smart pointer, that will make sure that the object is freed once all references to it are released.


That statement is very true, but I thought that the use of references was ment to be a "behind the scenes" change i.e. the script writer should more or less be unaware of the change.

The only argument that I have is when exactly in C++ do you actually do this:


int a = 10;
int & b = a;
b = 20; //Now a == 20

RandomClass myClass;
int & c = myClass.subclass.member;





The last case is about the only time I would personally use a reference; not just for performance, but for ease and readability. However, most the time I do assignments it's because I want to chnage the value. E.g:


//start is an int passed into the function
for (int current = start; current < end; ++current)
//access some array

if (start == current) //we didn't move through the array, perhaps some condition was met and it terminated early
//Do stuff

int offset = current - start; //Now wtf happens?





Now what happens in the above code? Using references, everytime current is advanced, it will advance start!? So the final if statement will always be true! Also, what happens in the last line, will offset be a regular int, or will it be a reference to a random bit of memory?

Admitadly, this is a silly example, but you get the idea.

BTW, I see you like my 'is' operator idea [embarrass] But by no new operators, do you mean that literally i.e. you wont be doing:


int a = new int;


#18 Gyrbo   Members   -  Reputation: 187

Like
0Likes
Like

Posted 25 November 2004 - 07:57 AM

I've already voice my opinion, but I like doing so, so I'm doing it again :p.

I have to agree with desertcube here. Most of the time when you do assignment, you actually need the new variable to contain a copy. I personally highly dislike something like Class newvar = oldvar.Copy(), especially when you have to do it a lot. Class newvar = *oldvar; is still acceptable IMHO, but since you probably use it most often, it should be the default. (See desertcube's example)
Furthermore, it would be unlogical IMO to have all operators except the assignment work on the value. Even new += old would change the value, whereas new = new + old wouldn't.
The only instance when assignment would default to reference assignment would be if the new variable is explicitly declared as reference.

About new operators: I don't really mind them as long as they're logical and unambiguous. Textual operators are usually clearer than symbolic ones.

#19 Andreas Jonsson   Moderators   -  Reputation: 3241

Like
0Likes
Like

Posted 25 November 2004 - 09:06 AM

Reference variables to primitive types won't be allowed, as it would allow a function to store a pointer to some memory that could later be freed, making the reference variable point to illegal memory.

I've already implemented AS 2.0 to do assignment by reference because it was easier, but this doesn't mean it is set in stone. I will leave it like this for WIP 1, because I want to get everything back up and running soon. Afterwards I'll take the decision if I will convert it to do assignment by copy.

I see no problem with having all operators except assignment work with the value. An addition takes two objects, computes their sum, and returns a new object with the result. a += b will just be a shorter way of writing a = a + b; It will not be a separate operator as it is in C++.

The 'new' operator will work like it does in C++. It will allocate an object and return it already initialized. Object a = new Object();




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

#20 desertcube   Members   -  Reputation: 514

Like
0Likes
Like

Posted 25 November 2004 - 09:27 AM

Quote:
Original post by WitchLord
The 'new' operator will work like it does in C++. It will allocate an object and return it already initialized. Object a = new Object();


Fair enoiugh about the reference thingy, but I'm still confused about the need for the 'new' operator. To declare a primative, such as an int, I just do this:

int myInt;

But, if I want to create a custom object, I have to do this:

SomeClass myClass = new SomeClass();

I'm not sure why I need to do this though! What is the purpose of the 'new' operator? Surley it would be nicer to do this:

SomeClass myClass(); //Create an object
SomeCladd myClass; //Same as the above, the default constructor is called

The point I'm trying to make is I'm not sure angelscript needs the operator 'new', as everything you create will infact be a smart pointer, why complicate things. Perhaps I'm missing something, but I don't like the way in C# you have to use new unless it's a primative or struct (in C# there is a difference between classes and structs), but if it is a struct, you can still use new if you want. Since C# has garbage collection (AS kinda does, as the scri[pt takes care of all the memory), I've never really understood the need to declare somethings with new, but otherthings don't need it.

I hope that makes sense, my question is basically why do we need operator 'new'?

Thanks for your time.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS