Example #1
0
///
/// Primitive Comparing Method
bool Variant::Less(const Variant & rhs) const
{

	if (this->IsNumber() && rhs.IsNumber())
		{
			return ((this->GetFloat()) < (rhs.GetFloat()));
		}
	else if (this->IsString() && rhs.IsString())
	    { //If both are strings, compare them

            //Get copies of the strings.
            std::string  str1 = this->GetString();
            std::string  str2 = rhs.GetString();

            return str1 < str2;
	    }
	else if (this->IsFunction() && rhs.IsFunction())
        {
            //Get copies of the strings.

            std::string  str1 = this->GetFunctionName();
            std::string  str2 = rhs.GetFunctionName();

            return (str1 < str2);
        }
	    //This should be handled more elegantly.
	    return false;
}
Example #2
0
///
/// Assignment Operator (overloaded)
Variant Variant::operator = (const Variant & value)
{

    //First, clean up 'this' if it contains data on free store
    // (e.g., a Variable or a string)
    free_mData();

    mDataType=value.GetDataType();
    switch(mDataType)
        {
        case P_DATA_NUMBER_INTEGER:  // an integer
            mData.iNumber = value.GetInteger();
            break;

        case P_DATA_NUMBER_FLOAT:    // a float
            mData.fNumber = value.GetFloat();
            break;

        case P_DATA_STRING:
            mData.String = strdup(value.GetString().c_str());
            break;

        case P_DATA_LOCALVARIABLE:        // a char* variable name
        case P_DATA_GLOBALVARIABLE:        // a char* variable name
            mData.Variable = strdup(value.GetVariableName().c_str());
            break;

        case P_DATA_FUNCTION:
            mData.Function = strdup(value.GetFunctionName().c_str());
            break;

        case P_DATA_FUNCTION_POINTER:
            mData.pFunction = value.GetFunctionPointer();
            break;

        case P_DATA_STACK_SIGNAL:
            mData.Signal = value.GetSignal();
            break;

        case P_DATA_COMPLEXDATA:
            {
            PComplexData * tmp = value.GetComplexData();
            //tmp is a pointer to complex data, which
            //is just a holder for the object.  We want to make a 
            //copy of tmp
            mComplexData = new PComplexData(*tmp);
            break;
            }
        case P_DATA_UNDEFINED: // undefined, error
        default:
            PError::SignalFatalError( "Undefined Variant type in Variant::operator = (Variant).");
            break;
        }
    return (*this);
}
Example #3
0
Variant::Variant(const Variant &v):
    mComplexData(NULL)
{

    
    //This should behave differently depending on what type of variant v is
    mDataType = v.GetDataType();

    switch(mDataType)
        {

        case P_DATA_NUMBER_INTEGER:  // an integer
            mData.iNumber = v.GetInteger();
            break;

        case P_DATA_NUMBER_FLOAT:    // a float
            mData.fNumber = v.GetFloat();
            break;

        case P_DATA_STRING:
            //            cout << "testing case string:<" << v << ">"<<endl;
            mData.String = strdup(v.GetString().c_str());
            break;

        case P_DATA_LOCALVARIABLE:        // a variable name
        case P_DATA_GLOBALVARIABLE:        // a variable name
            mData.Variable = strdup(v.GetVariableName().c_str());
            break;

        case P_DATA_FUNCTION:
            //Memory problem here, diagnosed by efence:
            mData.Function = strdup(v.GetFunctionName().c_str());
            break;

        case P_DATA_FUNCTION_POINTER:
            mData.pFunction = v.GetFunctionPointer();
            break;


        case P_DATA_STACK_SIGNAL:
            mData.Signal = v.GetSignal();
            break;

            //This needs to  make a deep copy

        case P_DATA_COMPLEXDATA:
            {

                //cout<<"TYPE:" << v << endl;
                PComplexData * pcd = v.GetComplexData();

                if(pcd)
                    mComplexData  = new PComplexData(*pcd);
                else 
                    mComplexData = NULL;

            }
            break;

        case P_DATA_UNDEFINED: // undefined, not an error
            break;
        default:

            cerr << "Undefined Data Type in Variant copy constructor. Type: " << mDataType << endl;
            cerr << v << endl;
            PError::SignalFatalError("Undefined Data Type.");
        break;

        }

}
/// This method takes a PEBL_FUNCTION OpNode, which is comprised of
/// a P_DATA_FUNCTION DataNode on the left and a parameter list on
/// the right, Finds the function code in the FunctionMap, and 
/// Evaluates that code.
void Evaluator::CallFunction(const OpNode * node)
{


    // First get the right node (the argument list) and evaluate it.
    // This will end up with a list Variant on top of the stack. 
    const PNode *node1 = node->GetRight();
    
    Evaluate(node1);


    // The parameters for a function are in a list on the top of the stack.
    // A function should pull the list off the stack and push it onto
    // the stack of the new evaluator scope.

    //    cout << dynamic_cast<DataNode*>(node->GetLeft())->GetValue() << endl;
    //Get the name of the function.  
    Variant funcname =dynamic_cast<DataNode*>(node->GetLeft())->GetValue();


    const PNode * node2 = mFunctionMap.GetFunction(funcname);

 
#ifdef PEBL_DEBUG_PRINT
    cout << "Calling a function with argument list: " <<  endl;
#endif 
    

    //Now, node2 will either be a PEBL_LAMBDAFUNCTION or a PEBL_BUILTINFUNCTION
    //Lambda functions are just code blocks, but need to be executed in 
    //a new scope, so need their own evaluator.  A built-in function is precompiled
    //and doesn't need its own new scope, so don't create one in that case.
    



    switch(((OpNode*)node2)->GetOp())
        {
        case PEBL_LAMBDAFUNCTION:
            {   //Need to create a new scope to allow for variable declaration
                //within case statement

                //get the top item of the stack.
                Variant v = Pop();
                
                
                //Make a new evaluator for the function scope and v at the top of the stack.
                Evaluator  myEval(v,funcname.GetFunctionName());
                
                //The callstack just keeps track of the series of
                //evaluators for debugging purposes.
                
                //Evaluate the lambda function in new scope.

                
                myEval.Evaluate(node2);

                //Now that myEval is finished, take the
                //node off the callstack.
                //gCallStack.Pop();
                
                //If myEval has a stack depth of 1, it does not return anything.
                //If myEval has a stack depth of 2, it wants to return the top value.
                if(myEval.GetStackDepth() == 1)
                    {
                        //Add '1' to the stack as the default return value for a function (i.e., one without
                        //an explicit return value.)
                        cout << "Adding dummy value to end of null function\n";
                        Push(1);
                    }
                else if (myEval.GetStackDepth() == 2)
                    {
                        //Get the top of the function evaluator and push it onto the current evaluator.
                        //cout << "Adding real value of subfunction to end of null function\n";
                        Variant v1 = myEval.Pop();
                        Push(v1);
                    }
            }
            break;
            
        case PEBL_LIBRARYFUNCTION:
            Evaluate(node2);

            break;


        default:
            PError::SignalFatalError("Unknown Function Type in Evaluator::CallFunction");
            break;
                }

}