CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    May 2010
    Posts
    19

    Using stored class names in script interpreter

    I've been trying to make a small, very simple scripting language (interpreted at runtime by a C++ program/parser), for my own use, more as an experiment than as anything practical. I don't want to use Flex, Bison, Yacc, Boost::Spirit, or other tools. I'd just like to make something that can take a script-based text file and essentially call and use existing C++ functions and classes from it.

    The first brick wall I keep coming up against (next up: argument lists) is turning string-stored class names into C++ types usable in code. For example, take this simple scope class, which assumes created objects of Test1 and Test2 will descend from the base class Interpretable:

    Code:
    class Scope
    {
    	public:
    		~Scope()
    		{
    			for(map<string,Interpretable*>::iterator it = vars.begin(); it != vars.end(); ++it)
    			{
    				delete it->second;
    				it->second = 0;
    			}
    		}
    		
    		void AddVariable(const string& varName, const string& className)
    		{
    			if(className == "Test1")
    				vars.insert(vars.end(), pair<string,Interpretable*>(varName, new Test1));
    			else if(className == "Test2")
    				vars.insert(vars.end(), pair<string,Interpretable*>(varName, new Test2));
    			else
    				throw "Invalid type";
    		}
    		
    		Interpretable* FindVariable(const string& varName)
    		{
    			map<string,Interpretable*>::iterator it = vars.find(varName);
    			if(it == vars.end())
    				return 0;
    			else
    				return it->second;
    		}
    	
    	private:
    		map<string,Interpretable*> vars;
    };
    As you can see, it's missing one critical component: It doesn't (maybe can't) call some function or macro to analyze className and produce the actual type of the class for the code, so I have to do a check and refer to Test1 directly. Plus, later on when I actually access the object, the same problem applies when finding out what to cast the Interpretable* to: even if I'm using RTTI to get Test1's name, I can't get access to a #defined or something C++ token that means "Test1" -- and that's probably a problem that pokes a huge hole in this whole methodology.

    Obviously, this type of checking, particularly with many classes and in many places throughout the code, is pretty ugly. My ideal is to be able to define some class (say Test1) and follow it with some blanket MAKE_INTERPRETABLE(Test1, "Test1") macro, requiring no later modification to, say, the Scope class to make Test1 universally supported... I just have no idea how to make that work, or, after much searching, if it's even possible.

    Similar problems exist when trying to call functions when you only have a string containing their name.

    Any ideas, or is this just misguided and hopeless?
    Last edited by jtanama; March 16th, 2011 at 09:14 AM.

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Using stored class names in script interpreter

    The key thing to understand here is that class names and function names only exist at compile time, not at run-time. However, the script is unknown at compile time. Hence, you need to program the translation. I.e. if your script language allows to define variables of a specified type, then you need to program something to translate the type name to a C++ class. If your script language allows to call a member function on a variable, then you need to program something that will translate the member function name, name of the variable the function is called on and function arguments to a function call in C++.

    To instantiate an object of a type that is specified at run-time, you can use a factory function quite like what you've show above.
    Code:
    Interpretable* CreateVariable(const std::string& typeName);
    Once you have such an object, you can use inheritance to do other things. E.g. calling a member function (in the script) can be part of the base class interface.
    Code:
    class Interpretable
    {
    public:
        virtual Interpretable* CallMemberFunction(const std::string& functionName, const std::vector<Interpretable*>& arguments) = 0;
    };
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured