Skip to main content
GameDev.net gamedev.net
🔒 Locked

LinderScript virtual machine: feedback wanted

Started by _Sergey_ Sep 8, 2006 at 4:25 AM 22 replies 6.6k views
Original Post
_Sergey_
_Sergey_
For some time i've been working on a virtual machine integrated into my engine (http://www.linderdaum.com) capable of such features as: 0) UnrealScript-looking object model 1) inherit script classes from native C++ classes 2) allow mixed classes (part of the classe's methods are written in C++, part in script) 3) allow transparent usage of scripted classes in C++ code 4) allow fast methods invokation 5*) latent functions - this one is still been discussed and under construction The scripting system is called LinderScript and it is part of the Linderdaum Engine. It has far more advanced features than usual standalone scripting systems could provide. The LinderScript Run-Time is the heart of the Linderdaum Engine and provides a metaclasses management facilities. Well, it is inseparable from the engine, but as a plus we have a bunch of features which any standalone scripting system is unable to provide: purely object-oriented solution where one can derive scripted classes from native C++ ones, there is no difference for the engine if some class contains scripted methods or not, in derived classes you can override some methods with LinderScript or leave them as inherited C++ methods at your own will. All this stuff is handled at the lowest level inside the engine so any engine’s class could be extended or rewritten using LinderScript. At the same time the performance of the LinderScript is comparable to Python. Could you have a look at it and maybe recommend some future extensions, point to the pitfalls and so on ;) Source code FAQ Doxygen-generated documentation [Edited by - _Sergey_ on September 26, 2006 2:19:36 AM]
--Sergey K. Linderdaum Project Coordinator http://www.linderdaum.comsupport@linderdaum.com
cypherx
cypherx
Do you have any sort of info on the VM except the source? A design doc or something?
_Sergey_
_Sergey_
No special documentation, except the one autogenerated by Doxygen (http://www.linderdaum.com/Docs/HTML/index.html)
--Sergey K. Linderdaum Project Coordinator http://www.linderdaum.comsupport@linderdaum.com
_Sergey_
_Sergey_
Nobody interested in such kind of things? Or everybody silently downloaded the source... ;)
--Sergey K. Linderdaum Project Coordinator http://www.linderdaum.comsupport@linderdaum.com
JasonHise
JasonHise
I suspect many people do not have time to read and conceptualize the source... you will probably get more responses if you ask specific questions about smaller aspects of your design (after describing how you implemented them), rather than asking for general comments about a huge chunk of your code.
_Sergey_
_Sergey_
Now for me one of the most important things is - how typesafe is this code and what is possible to improve:

#include <memory>#include <vector>class iParameter;typedef std::vector<iParameter*>    clParametersList;class iParameter{public:   iParameter() {};   virtual ~iParameter() {};   //   // iParameter   //   virtual LString  GetParamType() const = 0;   virtual int      GetParamSize() const = 0;   virtual void     ReadValue(const void* UntypedNativeBlock) = 0;   virtual void*    GetNativeBlock() = 0;   virtual void     PushToStack(iStack* Stack) const = 0;   virtual void     PopFromStack(iStack* Stack) = 0;};class clStringParameter: public iParameter{public:   //   // iParameter interface   //   virtual LString  GetParamType() const { return "STRING"; } ;   virtual int      GetParamSize() const { return sizeof(LStringBuffer); };   virtual void     ReadValue(const void* UntypedNativeBlock)   {      FString = *reinterpret_cast<const LString*>(UntypedNativeBlock);   }   virtual void*    GetNativeBlock()   {      return &FString   }   virtual void     PushToStack(iStack* Stack) const   {      LStringBuffer Buffer = FString.GetStringBuffer();      Stack->Push( Buffer );   }   virtual void     PopFromStack(iStack* Stack)   {      LStringBuffer Buffer = Stack->Pop<LStringBuffer>();      FString = LString( Buffer );   }private:   LString    FString;};class clScriptedPODParameter: public iParameter{public:   clScriptedPODParameter(int Size):FSize(Size), FParameter( malloc(Size) ) {};   virtual ~clScriptedPODParameter() { free(FParameter); };   //   // iParameter interface   //   virtual LString  GetParamType() const { return "SCRIPTED_POD"; } ;   virtual int      GetParamSize() const { return FSize; };   virtual void     ReadValue(const void* UntypedNativeBlock)   {      memcpy( FParameter, UntypedNativeBlock, FSize );   }   virtual void*    GetNativeBlock()   {      return FParameter;   }   virtual void     PushToStack(iStack* Stack) const   {      Stack->PushBytes( FSize, FParameter );   }   virtual void     PopFromStack(iStack* Stack)   {      Stack->PopBytes( FSize, FParameter );         }private:   int      FSize;   void*    FParameter;};template <class T> class clPODParameter: public clScriptedPODParameter{public:   clPODParameter():clScriptedPODParameter( sizeof(T) ) {};};template <typename T> class clPointerParameter: public iParameter{public:   clPointerParameter():FPointer(NULL) {};   //   // iParameter interface   //   virtual LString  GetParamType() const { return "PTR"; } ;   virtual int      GetParamSize() const { return sizeof(T*); };   virtual void     ReadValue(const void* UntypedNativeBlock)   {       FPointer = *reinterpret_cast<T**>( const_cast<void*>( UntypedNativeBlock ) );   }   virtual void*    GetNativeBlock()   {      return &FPointer   }   virtual void     PushToStack(iStack* Stack) const   {      Stack->Push<T*>( FPointer );   }   virtual void     PopFromStack(iStack* Stack)   {      FPointer = Stack->Pop<T*>();   }private:   T*   FPointer;};#define PARAMETER( selector, type ) typename SelectType<                                        TypeTraits<T>::selector, type,#define PTR_TRAITS typename ::LEngine::Utils::TypeTraits<T>::PointeeType#define REF_TRAITS typename ::LEngine::Utils::TypeTraits<T>::ReferredTypeusing namespace ::LEngine::Utils;template <class T>struct ParameterType{   typedef    PARAMETER( IsString,         clStringParameter              )   PARAMETER( IsReference,      clPODParameter<REF_TRAITS>     )   PARAMETER( IsPointer,        clPointerParameter<PTR_TRAITS> )   PARAMETER( IsFundamental,    clPODParameter<T>              )   // defaule   clPODParameter<T>   >::Result   >::Result   >::Result    >::Result    Type;};template <class T> inline iParameter* CreateNativeParameter(){   return new (typename ParameterType<T>::Type);}template <class T> inline iParameter* CreateInvokeParameter(T P){   iParameter* Param = CreateNativeParameter<T>();   Param->ReadValue( &P );   return Param;}



The purpose of this is to allow typesafe parameters transfer from native methods into scripted and back.
--Sergey K. Linderdaum Project Coordinator http://www.linderdaum.comsupport@linderdaum.com
_Sergey_
_Sergey_
Original post by Anonymous Poster
Quote:
Original post by 0xCHAOS
VERY few people are likely to spend any significant amount of time

Does this mean, that most people will more likely use any ready out-of-the-box solution instead of trying to learn and create there own one? Seems so from my experience...

--Sergey K. Linderdaum Project Coordinator http://www.linderdaum.comsupport@linderdaum.com
_Sergey_
_Sergey_
And what kind of information do you think would be the most interesting and useful?
--Sergey K. Linderdaum Project Coordinator http://www.linderdaum.comsupport@linderdaum.com
pammatt
pammatt
Yeah, no offense, but if I am not intending to use the code (I choose a different scripting route) but would be happy to give feedback on your "design", I am not going to parse source code in order to do that. I read your topic assuming you would be presenting designs, not source code.

Btw, isn't it a little late in the process to be requesting feedback on your "design". What is the design, how are your modules interfacing with each other, ect. I see your provided yourself with a basic list of features. Did you also write up any requirements or produce any sort of design docs or diagrams?

Again no offence intended, but when some asks me to give feedback on their design, they usually hand me a design document of sorts and possible a list of requirements that their design is supposed to support.

Good luck! How's the VM working out for you?
_Sergey_
_Sergey_
So, thank you for recomendations about the question structure. I've updated the original post, so it could be a little bit more informative. And here're the answers to your questions:

- what is it?
Very simply: it is an object oriented scripting system ;)
- what is it good for?
It is good for rapid development of game logic/custom GUI logic/tweaking of different game parameters.
- on what platforms/compilers is it supported?
The supported compilers are: MSVC 2005, GCC 3.4+, IC 8. The only supported platform for now is Win32. Win64 is upcoming as soon as i will have a Windows Vista 64 on my machine up and running ;)
- how is it different from existing approaches/products?
It is intended to be an open-source implementation of an UnrealScript-looking object model. There are no such kind of systems available in the market for free.
- how is it licensed/what does it cost?
It is free for any commercial and non-commercial use. Also a credit would be appriciated ;)
- what requirements/dependencies does it have?
It depends much on Linderdaum Engine simply as been part of it. Third party dependencies include: Intel JPEG Library, OpenGL, OpenAL. But none of these are directly connected with the scripting.
- what are the major architectural pillars of the product?
The key idea is to handle nicely inter language calls, like native-to-script and script-to-native. This was the most challanging to implement. For this purpose there're some preprocessing steps: you should build so called LinderScript Database containing all runtime types information necessary to run the scripting engine, but this is done automaticaly and directly from the C++ source code.
- what's the coolest thing about it?
Well, the coolest technical things, as was mentioned in the original post, are:
1) ability to inherit script classes from the native C++ classes
2) ability to have mixed classes (part of the classe's methods are written in C++, part in LinderScript)
3) allow transparent usage of scripted classes in C++ code - this means that you just call a method of the class and you don't care if it is implemented in C++ or in LinderScript - everything is handled behind the scenes.
- what are its known technical limitations?
This scripting model has support only for single inheritance.
- major strengths/weaknesses?
The major strenght is: one could rewrite any class (except some low-level core classes) in LinderScript.
The major weekness is: a script developer should be aware of object-oriented programming.
- how is it used?
Now i'm experimenting with complete implementation of GUI controls with the script.
- what overhead does it have?
The most overhead it brings is located in the method invokations code then the execution flow crosses the border between native and sripted code. The linear execution speed of the script is comparable to Lua and overall performance is comparable to Python.
- are there real-life applications using it?
Not yet.
- why was it developed/is it likely to continue being developed?
It was started 1 year ago to get undestanging what is going on inside UnrealScript. Then almost functioning system was integrated into the Linderdaum Engine and now it is evolving together with it.
- how well is it maintained?
I'm always very responsive to any e-mails regarding bugs/suggestions and improvments in the code.
- that is: can individual components be used in different settings, without requiring all sort of deps?
- how long does it take to compile on an average machine?
On my ASUS W3J laptop with Intel Core Duo 1.8 GHz and 1Gb of RAM on board it takes about 5 minutes to compile the whole engine (in debug mode).
- how is it called (why)?
It it called LinderScript. This came from LINDERdaum engine SCRIPTing system. ;)


Some remarks about your CONS guesses:

CONS:
- apparently rather limited platform support (only Win32 right now?)
Right now only Win32 is tested, but Win64 is on the way.
- heavy hardware requirements (OpenGL 2.0)
One shouldn't consider this heavy, since much depends on what kind of shaders you are using. GeForce6 series is 2 year old hardware anyway.
- hardly an implementation details available, certainly not for "LinderScript"
I think a good tutorial how to use it is better than deep technical explanation how it works. The technical tutorials are usualy intended for people who are going to implement similiar system of their own. This is not my goal. But the source code is free, so if one wants to implement his own OO-script he will have to work for it a little bit ;)
- hardly any details available for the various other components
In the near future i will provide more small examples and tutorials on how to use all these stuff.
- apparently pretty monolithic design, scripting engine doesn't appear to be available standalone or information is lacking
All high-level subsystems could be dropped (like rendering, GUI, resources manager, etc).
- source code on webpage isn't syntax-highlighted, or at least differently formatted: makes reading unnecessarily hard
I will fix this as soon as i find a tool!


Thanks for your interest!

[Edited by - _Sergey_ on September 26, 2006 2:03:44 AM]
--Sergey K. Linderdaum Project Coordinator http://www.linderdaum.comsupport@linderdaum.com
Netsurfer
Netsurfer
Nobody interested?
Netsurfer
Netsurfer
In using this engine in their own projects :)
JamesKilton
JamesKilton
Next question is:

Why would we want to use this over, say, Ruby, Python, Lua, or any other scripting language already in use?
Netsurfer
Netsurfer
It depends much on your language preferences, but neither Lua nor Pithon or Ruby gives you these of features (and even LuaBind dosn't). Or don't you like UnrealScript-like solutions in general? ;)
JamesKilton
JamesKilton
To be honest, the only aspect of UnrealScript I liked was the state construct, otherwise I found it a crippled language were it ever used outside of the Unreal environment.

I love Ruby, the majority of people here seem to use Lua in their games, with the next most use language being Python (and boost;:python). What's happening here is that _Sergey_ doesn't know how to sell his language. He hasn't give a list of features or much less a reason to use this, and from what I've seen on his website, it comes across that using LinderScript outside of the Linderdaum engine would be just as difficult as UnrealScript outside of the Unreal engine.

So yeah, nothing I've seen has made me even remotely interested in this scripting language.
BAH_Strike
BAH_Strike
not going to take the time to check it out first hand right now but sounds very impressive; i commend you :D

edit: i admit i am really intrigued by the idea of being able to override class methods; in script!

having written a C-style script interpreter (albeit not a VM) i certainly appreciate the efforts you've put into something like this.

i guess my only question is when will we learn to be more creative?
UnrealScript, LinderScript, LunarScript (mine), etc..
;)
Lunar project page will be available shortly... Need .. programming .. job ..

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.