how to implement objects for toy language? - c++

I am trying to make a toy language in c++. I have used boost spirit for the grammar, and hopefully for parser/lexer. The idea is a toy language where 'everything is an object' like javascript and some implementation of prototype based inheritance. I want to know how to implement the 'object' type for the language in c++. I saw source codes of engine spidermonkey but mostly it is done using structures, also getting more complex at later stages. As structures are more or less equivalent to classes in C++, I hope I could manage with the stdlib itself. All I want is a solid idea of how the basic object has to be implemented and how properties are created/modified/destroyed. I tried to take a look at V8, but its really confusing me a lot!

Have each class have pointers to parent classes and implement properties and methods in STL containers like <string,pointer_fun> so that you can add/remove dynamically methods.
Then you could just lookup a method in an obj, if there isn't then follow the ptr to parent and lookup there till you find one or fail non-existant method.
For properties you could have a template to wrap them in the STL container so that they share a common ancestor and you can store pointers like <string,property<type>* > where property makes created type inherit from common type.
With this approach and some runtime checks you can support dynamically anything, just need to have clear which are the lookup rules for a method when you call it in an object.
So essentially every obj instance in your system could be:
class obj{
type_class parent*;
string type;
std::map<string,pointer_fun> methods;
std::map<string,property_parent_class> properties;
}
And have constructors/destructor be normal methods with special names.
Then in obj creation you could just lookup for type_name in type_objs and copy the member and properties from the type to the impl obj.
EDIT:
About function objects, you can use functors inheriting from a common one to use the container_of_pointers approach.
For lists I'd create a simple class object that implements metods like __add__() or __len__() or __get__() like in python for example, then when you parse the language you'd substitute list_obj[3] for your_list_obj.method['__get__'] after checking that it exists of course.

Related

C++ Class References

Coming from Delphi, I'm used to using class references (metaclasses) like this:
type
TClass = class of TForm;
var
x: TClass;
f: TForm;
begin
x := TForm;
f := x.Create();
f.ShowModal();
f.Free;
end;
Actually, every class X derived from TObject have a method called ClassType that returns a TClass that can be used to create instances of X.
Is there anything like that in C++?
Metaclasses do not exist in C++. Part of why is because metaclasses require virtual constructors and most-derived-to-base creation order, which are two things C++ does not have, but Delphi does.
However, in C++Builder specifically, there is limited support for Delphi metaclasses. The C++ compiler has a __classid() and __typeinfo() extension for retrieving a Delphi-compatible TMetaClass* pointer for any class derived from TObject. That pointer can be passed as-is to Delphi code (you can use Delphi .pas files in a C++Builder project).
The TApplication::CreateForm() method is implemented in Delphi and has a TMetaClass* parameter in C++ (despite its name, it can actually instantiate any class that derives from TComponent, if you do not mind the TApplication object being assigned as the Owner), for example:
TForm *f;
Application->CreateForm(__classid(TForm), &f);
f->ShowModal();
delete f;
Or you can write your own custom Delphi code if you need more control over the constructor call:
unit CreateAFormUnit;
interface
uses
Classes, Forms;
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
implementation
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
begin
Result := AClass.Create(AOwner);
end;
end.
#include "CreateAFormUnit.hpp"
TForm *f = CreateAForm(__classid(TForm), SomeOwner);
f->ShowModal();
delete f;
Apparently modern Delphi supports metaclasses in much the same way as original Smalltalk.
There is nothing like that in C++.
One main problem with emulating that feature in C++, having run-time dynamic assignment of values that represent type, and being able to create instances from such values, is that in C++ it's necessary to statically know the constructors of a type in order to instantiate.
Probably you can achieve much of the same high-level goal by using C++ static polymorphism, which includes function overloading and the template mechanism, instead of extreme runtime polymorphism with metaclasses.
However, one way to emulate the effect with C++, is to use cloneable exemplar-objects, and/or almost the same idea, polymorphic object factory objects. The former is quite unusual, the latter can be encountered now and then (mostly the difference is where the parameterization occurs: with the examplar-object it's that object's state, while with the object factory it's arguments to the creation function). Personally I would stay away from that, because C++ is designed for static typing, and this idea is about cajoling C++ into emulating a language with very different characteristics and programming style etc.
Type information does not exist at runtime with C++. (Except when enabling RTTI but it is still different than what you need)
A common idiom is to create a virtual clone() method that obviously clones the object which is usually in some prototypical state. It is similar to a constructor, but the concrete type is resolved at runtime.
class Object
{
public:
virtual Object* clone() const = 0;
};
If you don't mind spending some time examining foreign sources, you can take a look at how a project does it: https://github.com/rheit/zdoom/blob/master/src/dobjtype.h (note: this is a quite big and evolving source port of Doom, so be advised even just reading will take quite some time). Look at PClass and related types. I don't know what is done here exactly, but from my limited knowledge they construct a structure with necessary metatable for each class and use some preprocessor magic in form of defines for readability (or something else). Their approach allows seamlessly create usual C++ classes, but adds support for PClass::FindClass("SomeClass") to get the class reference and use that as needed, for example to create an instance of the class. It also can check inheritance, create new classes on the fly and replace classes by others, i. e. you can replace CDoesntWorksUnderWinXP by CWorksEverywhere (as an example, they use it differently of course). I had a quick research back then, their approach isn't exceptional, it was explained on some sites but since I had only so much interest I don't remember details.

Module and Class in OCaml

What are the differences between Module and Class in OCaml.
From my searching, I found this:
Both provide mechanisms for abstraction and encapsulation, for
subtyping (by omitting methods in objects, and omitting fields in
modules), and for inheritance (objects use inherit; modules use
include). However, the two systems are not comparable.
On the one hand, objects have an advantage: objects are first-class
values, and modules are not—in other words, modules do not support
dynamic lookup. On the other hand, modules have an advantage: modules
can contain type definitions, and objects cannot.
First, I don't understand what does "Modules do not support dynamic lookup" mean. From my part, abstraction and polymorphism do mean parent pointer can refer to a child instance. Is that the "dynamic lookup"? If not, what actually dynamic lookup means?
In practical, when do we choose to use Module and when Class?
The main difference between Module and Class is that you don't instantiate a module.
A module is basically just a "drawer" where you can put types, functions, other modules, etc... It is just here to order your code. This drawer is however really powerful thanks to functors.
A class, on the other hand, exists to be instantiated. They contains variables and methods. You can create an object from a class, and each object contains its own variable and methods (as defined in the class).
In practice, using a module will be a good solution most of the time. A class can be useful when you need inheritance (widgets for example).
From a practical perspective dynamic lookup lets you have different objects with the same method without specifying to which class/module it belongs. It helps you when using inheritance.
For example, let's use two data structures: SingleList and DoubleLinkedList, which, both, inherit from List and have the method pop. Each class has its own implementation of the method (because of the 'override').
So, when you want to call it, the lookup of the method is done at runtime (a.k.a. dynamically) when you do a list#pop.
If you were using modules you would have to use SingleList.pop list or DoubleLinkedList.pop list.
EDIT: As #Majestic12 said, most of the time, OCaml users tend to use modules over classes. Using the second when they need inheritance or instances (check his answer).
I wanted to make the description practical as you seem new to OCaml.
Hope it can help you.

C++, avoid RTTI and the visitor pattern, is it possible?

I've been looking at some related threads but still don't find anything that answers the following question.
Let's say I have a hierarchy of classes (e.g. Widgets, HTML element) that form a tree structure. When I walk through the tree or look for a concrete element based on its ID I get a pointer to the base class (the tree algorithms only know about the base class).
Then, based on the type (the base class has a field that identifies the type) I perform a dynamic_cast in order to get a pointer to the concrete type. I've been thinking about ways to avoid this. The only thing that comes to my mind is the visitor pattern. But don't like very much this pattern.
Are there other ways/patterns to search/iterate nodes and get a pointer to the concrete class without using RTTI nor the visitor pattern?
Your approach doesn't sound like a good idea. Mostly because you have to do all the considerations before the runtime.
What you want to do is basically have the specific properties of a object listed and accessible. With dynamic casting this is possible but hardly elegant - since you have to write a trainload of switches and hardcode each and every possibility in advance so you can use it at runtime.
The solution I'd recommend as usual is the Qt framework. You can list the properties for each object at runtime, access a specific property by its name string or index and even attach properties during the runtime that don't exist in the code. And all this is type agnostic, you don't need to know an object's type to know its properties, and lastly - Qt offers a significantly faster qobject_cast for QObject derived classes instead of dynamic_cast.
The meta system allows you to know the class name, the base class name, methods, enums, constructors and pretty much everything, so besides properties, it is a good source for accessing all the functionality, available to an instance.
It really depends on the implementation of the visitor pattern. Using dynamic_cast<> is one way, another might be to use a handcrafted RTTI by defining a virtual GetType() function which can be implemented in all the subclasses. Depending on the result of that function you can do different things.

Game entity type allocation

I am migrating a tile based 2D game to C++, because I am really not a fan of Java (some features are nice, but I just can't get used to it). I am using TMX tiled maps. This question is concerning how to translate the object definitions into actual game entities. In Java, I used reflection to allocate an object of the specified type (given that it derived from the basic game entity).
This worked fine, but this feature is not available in C++ (I understand why, and I'm not complaining. I find reflection messy, and I was hesitant to use it in Java, haha). I was just wondering what the best way was to translate this data. My idea was a base class from which all entities could derive from (this seems pretty standard), then have the loader allocate the derived types based on the 'type' value from the TMX map. I have thought of two ways to do this.
A giant switch-case block. Lengthy and disgusting. I'm doubtful that anyone would suggest this (but it is the obvious).
Use a std::map, which would map arbitrary type names to a function to allocate said classes corresponding to said type names.
Lastly, I had thought of making entities of one base class, and using scripting for different entity types. The scripts themselves would register their entity type with the system, although the game would need to load said entity type scripts upon loading (this could be done via one main entity type declaration script, which would bring the number of edits per entity down to 2: entity creation, and entity registration).
while option two looks pretty good, I don't like having to change 3 pieces of code for each type (defining the entity class, defining an allocate function, and adding the function to the std::map). Option 3 sounds great except for two things in my mind: I'm afraid of the speed of purely script driven entities. Also, I know that adding scripting to my engine is going to be a big project in itself (adding all the helper functions for interfacing with the library will be interesting).
Does anyone know of a better solution? Maybe not better, but just cleaner. With less code edits per entity type.
You can reduce the number of code changes in solution 2, if you use a self registration to a factory. The drawback is that the entities know this factory (self registration) and this factory has to be a global (e.g. a singleton) instance. If tis is no problem to you, this pattern can be very nice. Each new type requires only compilation an linking of one new file.
You can implement self registration like this:
// foo.cpp
namespace
{
bool dummy = FactoryInstance().Register("FooKey", FooCreator);
}
Abstract Factory, Template Style, by Jim Hyslop and Herb Sutter

Treating classes as first-class objects

I was reading the GoF book and in the beginning of the prototype section I read this:
This benefit applies primarily to
languages like C++ that don't treat
classes as first class objects.
I've never used C++ but I do have a pretty good understanding of OO programming, yet, this doesn't really make any sense to me. Can anyone out there elaborate on this (I have used\use: C, Python, Java, SQL if that helps.)
For a class to be a first class object, the language needs to support doing things like allowing functions to take classes (not instances) as parameters, be able to hold classes in containers, and be able to return classes from functions.
For an example of a language with first class classes, consider Java. Any object is an instance of its class. That class is itself an instance of java.lang.Class.
For everybody else, heres the full quote:
"Reduced subclassing. Factory Method
(107) often produces a hierarchy of
Creator classes that parallels the
product class hierarchy. The Prototype
pattern lets you clone a prototype
instead of asking a factory method to
make a new object. Hence you don't
need a Creator class hierarchy at all.
This benefit applies primarily to
languages like C++ that don't treat
classes as first-class objects.
Languages that do, like Smalltalk and
Objective C, derive less benefit,
since you can always use a class
object as a creator. Class objects
already act like prototypes in these
languages." - GoF, page 120.
As Steve puts it,
I found it subtle in so much as one
might have understood it as implying
that /instances/ of classes are not
treated a first class objects in C++.
If the same words used by GoF appeared
in a less formal setting, they may
well have intended /instances/ rather
than classes. The distinction may not
seem subtle to /you/. /I/, however,
did have to give it some thought.
I do believe the distinction is
important. If I'm not mistaken, there
is no requirement than a compiled C++
program preserve any artifact by which
the class from which an object is
created could be reconstructed. IOW,
to use Java terminology, there is no
/Class/ object.
In Java, every class is an object in and of itself, derived from java.lang.Class, that lets you access information about that class, its methods etc. from within the program. C++ isn't like that; classes (as opposed to objects thereof) aren't really accessible at runtime. There's a facility called RTTI (Run-time Type Information) that lets you do some things along those lines, but it's pretty limited and I believe has performance costs.
You've used python, which is a language with first-class classes. You can pass a class to a function, store it in a list, etc. In the example below, the function new_instance() returns a new instance of the class it is passed.
class Klass1:
pass
class Klass2:
pass
def new_instance(k):
return k()
instance_k1 = new_instance(Klass1)
instance_k2 = new_instance(Klass2)
print type(instance_k1), instance_k1.__class__
print type(instance_k2), instance_k2.__class__
C# and Java programs can be aware of their own classes because both .NET and Java runtimes provide reflection, which, in general, lets a program have information about its own structure (in both .NET and Java, this structure happens to be in terms of classes).
There's no way you can afford reflection without relying upon a runtime environment, because a program cannot be self-aware by itself*. But if the execution of your program is managed by a runtime, then the program can have information about itself from the runtime. Since C++ is compiled to native, unmanaged code, there's no way you can afford reflection in C++**.
...
* Well, there's no reason why a program couldn't read its own machine code and "try to make conclusions" about itself. But I think that's something nobody would like to do.
** Not strictly accurate. Using horrible macro-based hacks, you can achieve something similar to reflection as long as your class hierarchy has a single root. MFC is an example of this.
Template metaprogramming has offered C++ more ways to play with classes, but to be honest I don't think the current system allows the full range of operations people may want to do (mainly, there is no standard way to discover all the methods available to a class or object). That's not an oversight, it is by design.