Пример #1
0
void Parser::FNSyntax_DeleteExpression(ExprNode *node)
{
    ExprNode *temp = NULL;

    for(ExprNode *i = node; i != NULL; i = i->next)
    {
        if(temp != NULL)
        {
            POV_FREE(temp);
        }

        FNSyntax_DeleteExpression(i->child);

        if((i->op == OP_VARIABLE) || (i->op == OP_MEMBER))
        {
            POV_FREE(i->variable);
        }
        else if(i->op == OP_CALL)
        {
            if((i->call.token == FUNCT_ID_TOKEN) || (i->call.token == VECTFUNCT_ID_TOKEN))
                dynamic_cast<FunctionVM*>(sceneData->functionContextFactory)->RemoveFunction(i->call.fn);
            POV_FREE(i->call.name);
        }

        temp = i;
    }

    if(temp != NULL)
    {
        POV_FREE(temp);
    }
}
Пример #2
0
void FNSyntax_DeleteExpression(ExprNode *node)
{
	ExprNode *temp = NULL;

	for(ExprNode *i = node; i != NULL; i = i->next)
	{
		if(temp != NULL)
		{
			POV_FREE(temp);
		}

		FNSyntax_DeleteExpression(i->child);

		if((i->op == OP_VARIABLE) || (i->op == OP_MEMBER))
		{
			POV_FREE(i->variable);
		}
		else if(i->op == OP_CALL)
		{
			if((i->call.token == FUNCT_ID_TOKEN) || (i->call.token == VECTFUNCT_ID_TOKEN))
				POVFPU_RemoveFunction(i->call.fn);
			POV_FREE(i->call.name);
		}

		temp = i;
	}

	if(temp != NULL)
	{
		POV_FREE(temp);
	}
}
Пример #3
0
FUNCTION_PTR Parser::Parse_FunctionContent(void)
{
	FUNCTION_PTR ptr = (FUNCTION_PTR)POV_MALLOC(sizeof(FUNCTION), "Function ID");
	ExprNode *expression = NULL;
	FunctionCode function;

	FNCode f(this, &function, false, NULL);

	expression = FNSyntax_ParseExpression();
	f.Compile(expression);
	FNSyntax_DeleteExpression(expression);

	*ptr = sceneData->functionVM->AddFunction(&function);

	return ptr;
}
Пример #4
0
void Parser::optimise_expr(ExprNode *node)
{
    ExprNode *left,*right,*ptr,*temp;
    DBL result;
    bool have_result;
    int op,cnt;

    if(node == NULL)
        return;

    if(node->op == OP_CALL)
    {
        if(node->call.token == POW_TOKEN)
        {
            node->op = OP_FIRST;
            POV_FREE(node->call.name);
            if(node->child != NULL)
            {
                node->child->op = OP_LEFTMOST;
                if(node->child->next != NULL)
                {
                    node->child->next->op = OP_POW;
                    node->child->next->prev = node->child;
                }
            }
        }
    }

    if(node->op < OP_FIRST) // using switch statement might be better [trf]
    {
        ptr = node->next;
        if(ptr != NULL)
        {
            if(ptr->op == OP_NEG)
            {
                op = ptr->op;
                cnt = 0;
                for(ptr = node->next; ptr != NULL; ptr = ptr->next)
                {
                    cnt++;
                    if(ptr->child != NULL)
                        break;
                }

                if(ptr != NULL)
                {
                    optimise_expr(ptr->child);
                    if(ptr->child != NULL)
                    {
                        left = ptr->child;
                        if(left->op == OP_CONSTANT)
                        {
                            ptr->child = NULL;

                            if(node->next != NULL)
                                FNSyntax_DeleteExpression(node->next);

                            if(op == OP_NEG)
                            {
                                if((cnt % 2) == 0)
                                    node->number = (left->number);
                                else
                                    node->number = -(left->number);
                            }
                            POV_FREE(left);
                            node->op = OP_CONSTANT;
                            node->child = NULL;
                            node->prev = NULL;
                            node->next = NULL;
                            return; // early exit
                        }
                    }
                }
            }
        }

        optimise_expr(node->child);
        for(ptr = node->next; ptr != NULL; ptr = ptr->next)
        {
            left = ptr->prev->child;
            right = ptr->child;

            if((right != NULL) && (ptr->op == OP_SUB))
            {
                if(right->op == OP_CONSTANT)
                {
                    ptr->op = OP_ADD;
                    right->number = -right->number;
                }
            }

            optimise_expr(right);

            if((left != NULL) && (right != NULL) &&
               (((ptr->op != OP_MUL) && (ptr->op != OP_DIV)) ||
                !left_subtree_has_variable_expr(ptr)))
            {
                if((left->op == OP_CONSTANT) && (right->op == OP_CONSTANT))
                {
                    have_result = true;

                    switch(ptr->op)
                    {
                        case OP_CMP_EQ:
                            result = (left->number == right->number);
                            break;
                        case OP_CMP_NE:
                            result = (left->number != right->number);
                            break;
                        case OP_CMP_LT:
                            result = (left->number < right->number);
                            break;
                        case OP_CMP_LE:
                            result = (left->number <= right->number);
                            break;
                        case OP_CMP_GT:
                            result = (left->number > right->number);
                            break;
                        case OP_CMP_GE:
                            result = (left->number >= right->number);
                            break;
                        case OP_ADD:
                            result = (left->number + right->number);
                            break;
                        case OP_SUB:
                            result = (left->number - right->number);
                            break;
                        case OP_OR:
                            result = (DBL)(((DBL)((((DBL)(left->number != 0)) + ((DBL)(right->number != 0))))) != 0); // match VM code
                            break;
                        case OP_MUL:
                            result = (left->number * right->number);
                            break;
                        case OP_DIV:
                            result = (left->number / right->number);
                            break;
                        case OP_AND:
                            result = (DBL)((((DBL)(left->number != 0)) * ((DBL)(right->number != 0)))); // match VM code
                            break;
                        case OP_POW:
                            result = pow(left->number, right->number);
                            break;
                        default:
                            have_result = false;
                            break;
                    }

                    if(have_result == true)
                    {
                        temp = ptr;
                        ptr->prev->next = ptr->next;
                        if(ptr->next != NULL)
                            ptr->next->prev = ptr->prev;
                        ptr = ptr->prev;
                        POV_FREE(temp->child);
                        POV_FREE(temp);
                        left->number = result;
                    }
                }
            }
        }
        if((node->next == NULL) && (node->child != NULL) && (node->op < OP_FIRST))
        {
            if((node->child->op == OP_CONSTANT) && (node->child->next == NULL))
            {
                node->number = left->number;
                node->op = OP_CONSTANT;
                POV_FREE(node->child);
                node->child = NULL;
            }
        }
    }
    else
    {
        optimise_expr(node->child);

        optimise_call(node);

        if((node->child != NULL) && (node->op < OP_FIRST))
        {
            if((node->child->op == OP_CONSTANT) && (node->child->next == NULL))
            {
                node->number = node->child->number;
                POV_FREE(node->child);
                node->child = NULL;
                node->op = OP_CONSTANT;
            }
        }
    }
}
Пример #5
0
FUNCTION_PTR Parser::Parse_DeclareFunction(int *token_id, const char *fn_name, bool is_local)
{
	FUNCTION_PTR ptr = (FUNCTION_PTR)POV_MALLOC(sizeof(FUNCTION), "Function ID");
	ExprNode *expression = NULL;
	FunctionCode function;

	// default type is float function
	*token_id = FUNCT_ID_TOKEN;

	FNCode f(this, &function, is_local, fn_name);
	f.Parameter();

	Parse_Begin();

	Get_Token();
	if(Token.Token_Id == INTERNAL_TOKEN)
	{
		GET(LEFT_PAREN_TOKEN);

		Get_Token();
		if(Token.Function_Id != FLOAT_TOKEN)
			Expectation_Error("internal function identifier");
		expression = FNSyntax_GetTrapExpression((unsigned int)(Token.Token_Float));

		function.flags = FN_INLINE_FLAG;

		GET(RIGHT_PAREN_TOKEN);
	}
	else if(Token.Token_Id == TRANSFORM_TOKEN)
	{
		if(function.parameter_cnt != 0)
			Error("Function parameters for transform functions are not allowed.");

		expression = FNSyntax_GetTrapExpression(1); // 1 refers to POVFPU_TrapSTable[1] = f_transform [trf]

		function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Transform;
		function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Transform;

		function.private_data = reinterpret_cast<void *>(Parse_Transform_Block());

		function.return_size = 3; // returns a 3d vector!!!

		// function type is vector function
		*token_id = VECTFUNCT_ID_TOKEN;
	}
	else if(Token.Token_Id == SPLINE_TOKEN)
	{
		if(function.parameter_cnt != 0)
			Error("Function parameters for spline functions are not allowed.");

		Experimental_Flag |= EF_SPLINE;

		expression = FNSyntax_GetTrapExpression(2); // 2 refers to POVFPU_TrapSTable[2] = f_spline [trf]

		function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Spline;
		function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Spline;

		Parse_Begin();
		function.private_data = reinterpret_cast<void *>(Parse_Spline());
		Parse_End();

		function.return_size = (reinterpret_cast<SPLINE *>(function.private_data))->Terms; // returns a 2d, 3d, 4d or 5d vector!!!

		// function type is vector function
		*token_id = VECTFUNCT_ID_TOKEN;
	}
	else if(Token.Token_Id == PIGMENT_TOKEN)
	{
		if(function.parameter_cnt != 0)
			Error("Function parameters for pigment functions are not allowed.");

		expression = FNSyntax_GetTrapExpression(0); // 0 refers to POVFPU_TrapSTable[0] = f_pigment [trf]

		function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Pigment;
		function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Pigment;

		Parse_Begin();
		function.private_data = reinterpret_cast<void *>(Create_Pigment());
		Parse_Pigment(reinterpret_cast<PIGMENT **>(&function.private_data));
		Parse_End();
		Post_Pigment(reinterpret_cast<PIGMENT *>(function.private_data));

		function.return_size = 5; // returns a color!!!

		// function type is vector function
		*token_id = VECTFUNCT_ID_TOKEN;
	}
	else if(Token.Token_Id == PATTERN_TOKEN)
	{
		if(function.parameter_cnt != 0)
			Error("Function parameters for pattern functions are not allowed.");

		expression = FNSyntax_GetTrapExpression(77); // 77 refers to POVFPU_TrapTable[77] = f_pattern [trf]

		function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Pigment;
		function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Pigment;

		Parse_Begin();
		function.private_data = reinterpret_cast<void *>(Create_Pigment()); // Yes, this is a pigment! [trf]
		Parse_PatternFunction(reinterpret_cast<TPATTERN *>(function.private_data));
		Parse_End();
		Post_Pigment(reinterpret_cast<PIGMENT *>(function.private_data));
	}
	else if(Token.Token_Id == STRING_LITERAL_TOKEN)
	{
		f.SetFlag(2, Token.Token_String);
		Get_Token();
		if(Token.Token_Id == COMMA_TOKEN)
		{
			Get_Token();
			if(Token.Token_Id != STRING_LITERAL_TOKEN)
				Expectation_Error("valid function expression");
			f.SetFlag(1, Token.Token_String);
		}
		else
		{
			Unget_Token();
			expression = FNSyntax_ParseExpression();
		}
	}
	else
	{
		Unget_Token();
		expression = FNSyntax_ParseExpression();
	}

	f.Compile(expression);
	FNSyntax_DeleteExpression(expression);

	Parse_End();

	*ptr = sceneData->functionVM->AddFunction(&function);

	return ptr;
}