#include "eval.h"


// eval:
//	Evaluate a node in the specified environment.
void eval( struct lisa_node *node, struct lisa_environment *env )
{
	switch ( node->type )
	{
		case LISA_TYPE_CONDITION:
		{
			evalCondition( node->args, env );
			break;
		}
		case LISA_TYPE_DIRECTIVE:
		{
			evalDirective( node, env );
			break;
		}
		case LISA_TYPE_EXPRESSION:
		{
			evalExpression( node, env );
			break;
		}
		case LISA_TYPE_KEYWORD:
		{
			evalKeyword( node, env );
			break;
		}
		case LISA_TYPE_NUMBER:
		{
			evalNumber( node, env );
			break;
		}
		case LISA_TYPE_STRING:
		{
			evalString( node, env );
			break;
		}
		case LISA_TYPE_TAGKEYWORD:
		{
			evalTAGKeyword( node, env );
			break;
		}
		default:
		{
			evalError( "unimplemented token type evaluation", node );
		}
	}
}//eval





// evalArray:
//	Evaluate an array value or identifier in the specified environment.
void evalArray( struct lisa_node *node, struct lisa_environment *env )
{
	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			evalIdentifier( node, env );
//			printf( "$%s", node->element );
			if ( node->args )
			{
				printf( "[ " );
				evalCondition( node->args, env );
				printf( " ]" );
			}
			break;
		}
	}
}//evalArray





// evalBlock:
//	Evaluate a sub-block of statements in a child of the specified environment.
void evalBlock( struct lisa_node *node, struct lisa_environment *env )
{
	struct lisa_node        *tmp;
	struct lisa_environment *e;

	// creating a child environment...
	e = childEnvironment( env );

	// write start of block...
	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			printf( "{\n" );
			break;
		}
	}

	tmp = node;
	while ( tmp )
	{
		eval( tmp, e );
		tmp = tmp->next;
	}

	// write stop of block...
	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			printf( "}\n" );
			break;
		}
	}

	// destroying the child environment...
	destroyEnvironment( e );

}//evalBlock





// evalCondition:
//	Evaluate a condition in the specified environment.
void evalCondition( struct lisa_node *node, struct lisa_environment *env )
{
	struct lisa_node *tmp;

	tmp = node;
	while( tmp )
	{
		switch ( tmp->type )
		{
			case LISA_TYPE_ARRAY:
			{
				evalArray( tmp, env );
				break;
			}
			case LISA_TYPE_FUNCTION:
			{
				evalFunction( tmp, env );
				break;
			}
			case LISA_TYPE_IDENTIFIER:
			{
				evalIdentifier( tmp, env );
				break;
			}
			case LISA_TYPE_NUMBER:
			{
				evalNumber( tmp, env );
				break;
			}
			case LISA_TYPE_OPERATOR:
			{
				evalOperator( tmp, env );
				break;
			}
			case LISA_TYPE_STRING:
			{
				evalString( tmp, env );
				break;
			}
		}
		tmp = tmp->next;
	}

}//evalCondition





// evalDirective:
//	Evaluate a directive node in the specified environment.
void evalDirective( struct lisa_node *node, struct lisa_environment *env )
{
	struct lisa_node        *tmp;

	if ( strcmp( node->element, "#include" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				if ( node->args->type == LISA_TYPE_STRING )
				{
					// including a general file...
					printf( "include( " );
					evalString( node->args, env );
					printf( " );\n" );
				}
				else
				{
					// including a module...
					printf( "require( '%s.php' );\n", node->args->element );
				}
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "#php" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				tmp = node->args;
				while ( tmp )
				{
					printf( "%s\n", tmp->element );
					tmp = tmp->args;
				}
				break;
			}
		}
		return;
	}

	evalError( "unimplemented directive evaluation", node );
}//evalDirective





// evalError:
//	Display an error message for the specified node
//	and exit from evaluation.
void evalError( char *msg, struct lisa_node *node )
{
	fprintf( stderr, "\nOn token '%s' (type %d) at line %d:\n\t", node->element, node->type, node->line );
	error( msg );
}//evalError





// evalExpression:
//	Evaluate an expression in the specified environment.
void evalExpression( struct lisa_node *node, struct lisa_environment *env )
{
	// NOTE: (2002-06-28 Gabriele Budelacci)
	//	An EXPRESSION is equivalent to a CONDITION, followed by a
	//	SEMICOLON ';' (lisa language). So, I will evaluate firsts
	//	the condition, then I will write the terminal character,
	//	depending wich target language is compiling to.

	// evaluating the condition firsts...
	evalCondition( node->args, env );

	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			printf( ";\n" );
			break;
		}
	}
}//evalExpression





// evalFunction:
//	Evaluate a function node in the specified environment.
void evalFunction( struct lisa_node *node, struct lisa_environment *env )
{
	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			// NOTE: (2002-07-03 Gabriele Budelacci)
			//	Functions compiled have the same name as specified
			//	in lisa source, undercased and preceased by an
			//	underscore ('_').
			printf( "_%s(", node->element );
			if ( ! emptyNode( node->args ) )
			{
				printf( " " );
				evalCondition( node->args->args, env );
				printf( " " );
			}
			printf( ")" );
			break;
		}
	}
}//evalFunction





// evalIdentifier:
//	Evaluate a identifier node in the specified environment.
void evalIdentifier( struct lisa_node *node, struct lisa_environment *env )
{
	if ( ! findNodeByElement( node->element, env->declared ) )
		evalError( "undeclared variable", node );

	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			if ( findNodeByElement( node->element, env->globals ) )
				printf( "$SESSION['$%s']", node->element );
			else
				printf( "$%s", node->element );
			break;
		}
	}
}//evalIdentifier





// evalKeyword:
//	Evaluate a keyword node in the specified environment.
void evalKeyword( struct lisa_node *node, struct lisa_environment *env )
{
	struct lisa_node *tmp, *next;

	if ( strcmp( node->element, "array" ) == 0 )
	{
		// firsts, check if there is another identifiers declared...
		next = node->args;
		while ( next )
		{
			// search the node in declared list...
			tmp = findNodeByElement( next->element, env->declared );
			// if not exists, append a new identifier...
			if ( tmp == NULL )
			{
				tmp = cloneNode( next );
				// NOTE: (2002-07-12 Gabriele Budelacci)
				//	When a new variable is declared whithin a block,
				//	then the type is negated.
				tmp->type = -LISA_TYPE_ARRAY;		// please note minus '-' sign
				appendNode( tmp, env->declared );
			}
			else
			{
				// The identifier is already declared...
				// If the type is positive, the identifier can be redeclared...
				if ( tmp->type < 0 )
				{
					evalError( "variable already declared", tmp );
				}
				tmp->type = -LISA_TYPE_ARRAY;
			}
			// process next element
			next = next->next;
		}

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				// NOTE: (2002-06-27 Gabriele Budelacci)
				// In PHP language, declaration of variants
				// can be omitted.
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "break" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( "break;\n" );
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "continue" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( "continue;\n" );
				break;
			}
		}
		return;
	}

			//
			//                    foreach
			//                      / |
			//  array-set-identifier   ...
			//             /  |
			//        block  { identifier }
			//
	if ( strcmp( node->element, "foreach" ) == 0 )
	{
		int type;
		struct lisa_environment *e;

		// check if identifier is declared...
		tmp = findNodeByElement( node->args->element, env->declared );
		if ( tmp == NULL )
			evalError( "undeclared variable", node->args );

		// get the identifier type...
		type = tmp->type;
		if ( type < 0 ) type = -type;

		// switch on array or set
		switch ( type )
		{
			case LISA_TYPE_ARRAY:
			{
				switch ( env->language )
				{
					case LISA_LANG_PHP:
					{
						printf( "foreach ( $%s as ", node->args->element );
						e = childEnvironment( env );

							// declaring the identifiers as variants...
							next = node->args->next;
							while ( next )
							{
								// search the node in declared list...
								tmp = findNodeByElement( next->element, env->declared );
								// if not exists, append a new identifier...
								if ( tmp == NULL )
								{
									tmp = cloneNode( next );
									// NOTE: (2002-07-12 Gabriele Budelacci)
									//	When a new variable is declared whithin a block,
									//	then the type is negated.
									tmp->type = -LISA_TYPE_VARIANT;		// please note minus '-' sign
									appendNode( tmp, env->declared );
								}
								else
								{
									// The identifier is already declared...
									// If the type is positive, the identifier can be redeclared...
									if ( tmp->type < 0 )
									{
										evalError( "variable already declared", tmp );
									}
									tmp->type = -LISA_TYPE_VARIANT;
								}
								// process next element
								next = next->next;
							}

							// eval the identifier list...
							next = node->args->next;
							printf( "$%s", next->element );
							if ( next->next )
								evalError( "no more than one variable allowed while processing an array", next );

							printf( " )\n" );
							evalBlock( node->args->args, env );
						destroyEnvironment( e );
						break;
					}
				}
				break;
			}

			case LISA_TYPE_SET:
			{
				switch ( env->language )
				{
					case LISA_LANG_PHP:
					{
						evalError( "unimplemented evaluation", node );
						break;
					}
				}
				break;
			}

			default:
			{
				evalError( "wrong type variable", node->args );
			}
		}
		return;
	}

	if ( strcmp( node->element, "function" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( "function _%s ( ", node->args->element );
				// NOTE: (2002-07-13 Gabriele Budelacci)
				//	I can't evaluate the parameters list as a condition,
				//	because lots of 'undeclared variable' errors are raised.
				tmp = node->args->next;
				while ( tmp )
				{
					switch ( tmp->type )
					{
						case LISA_TYPE_ARRAY:
						case LISA_TYPE_IDENTIFIER:
							printf( "$%s", tmp->element );
							break;
						case LISA_TYPE_OPERATOR:
							printf( ", " );
							break;
						default:
							evalError( "bad APT", tmp );
					}
					tmp = tmp->next;
				}
				printf( " )\n" );
				evalBlock( node->args->args, env );
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "global" ) == 0 )
	{
		// append the variants to the global list...
		appendNode( cloneNode( node->args->args ), env->globals );
		// NOTE: ( 2002-07-01 Gabriele Budelacci )
		//	The code above may be made better in future...

		// firsts, check if there is another identifiers declared...
		next = node->args->args;
		while ( next )
		{
			// search the node in declared list...
			tmp = findNodeByElement( next->element, env->declared );
			// if not exists, append a new identifier...
			if ( tmp == NULL )
			{
				tmp = cloneNode( next );
				// NOTE: (2002-07-12 Gabriele Budelacci)
				//	When a new variable is declared whithin a block,
				//	then the type is negated.
				tmp->type = -LISA_TYPE_VARIANT;		// please note minus '-' sign
				appendNode( tmp, env->declared );
			}
			else
			{
				// The identifier is already declared...
				// If the type is positive, the identifier can be redeclared...
				if ( tmp->type < 0 )
				{
					evalError( "variable already declared", tmp );
				}
				tmp->type = -LISA_TYPE_VARIANT;
			}
			// process next element
			next = next->next;
		}

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				// NOTE: (2002-07-01 Gabriele Budelacci)
				// In PHP language, declaration of variant
				// can be omitted.
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "if" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( "if ( " );
				evalCondition( node->args->args, env );
				printf( " )\n" );
				evalBlock( node->args->next->args, env );
				if ( node->args->next->next )
				{
					printf( "else\n" );
					evalBlock( node->args->next->next, env );
				}
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "parameter" ) == 0 )
	{
		// append the variants to the parameter list...
		appendNode( cloneNode( node->args->args ), env->parameters );

		// firsts, check if there is another identifiers declared...
		next = node->args->args;
		while ( next )
		{
			// search the node in declared list...
			tmp = findNodeByElement( next->element, env->declared );
			// if not exists, append a new identifier...
			if ( tmp == NULL )
			{
				tmp = copyNode( next );
				tmp->args = NULL;
				tmp->next = NULL;
				// NOTE: (2002-07-12 Gabriele Budelacci)
				//	When a new variable is declared whithin a block,
				//	then the type is negated.
				tmp->type = -LISA_TYPE_VARIANT;		// please note minus '-' sign
				appendNode( tmp, env->declared );
			}
			else
			{
				// The identifier is already declared...
				// If the type is positive, the identifier can be redeclared...
				if ( tmp->type < 0 )
				{
					evalError( "variable already declared", tmp );
				}
				tmp->type = -LISA_TYPE_VARIANT;
			}
			// process next element
			next = next->next;
		}

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				// each parameter must be set empty if not defined...
				next = node->args->args;
				while ( next )
				{
					printf( "$%s = ( empty( $%s ) ? '' : $%s );\n", next->element, next->element, next->element );
					next = next->next;
				}
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "return" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( "return " );
				if ( node->args )
				{
					evalCondition( node->args, env );
					printf( ";\n" );
				}
				else
				{
					printf( "0;\n" );
				}
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "set" ) == 0 )
	{
		// firsts, check if there is another identifiers declared...
		next = node->args;
		while ( next )
		{
			// search the node in declared list...
			tmp = findNodeByElement( next->element, env->declared );
			// if not exists, append a new identifier...
			if ( tmp == NULL )
			{
				tmp = cloneNode( next );
				// NOTE: (2002-07-12 Gabriele Budelacci)
				//	When a new variable is declared whithin a block,
				//	then the type is negated.
				tmp->type = -LISA_TYPE_SET;		// please note minus '-' sign
				appendNode( tmp, env->declared );
			}
			else
			{
				// The identifier is already declared...
				// If the type is positive, the identifier can be redeclared...
				if ( tmp->type < 0 )
				{
					evalError( "variable already declared", tmp );
				}
				tmp->type = -LISA_TYPE_SET;
			}
			// process next element
			next = next->next;
		}

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				// NOTE: (2002-06-27 Gabriele Budelacci)
				// In PHP language, declaration of set
				// can be omitted.
				break;
			}
		}
		return;
	}

	//
	//                        switch
	//                        /  |
	//                   empty
	//                   /  |
	//          condition  { case }
	//                      /   |
	//                 value   [ default ]
	//                  /        /
	//             block    block
	//
	if ( strcmp( node->element, "switch" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( "switch ( " );
				evalCondition( node->args->args, env );
				printf( " )\n" );
				printf( "{\n" );
				// eval case and default statements...
				next = node->args->next;
				while ( next )
				{
					if ( strcmp( next->element, "case" ) == 0 )
					{
						// evaluating 'case' statement...
						printf( "case " );
						eval( next->args, env );
						printf( ":\n" );
						if ( ! emptyNode( next->args->args ) )
							eval( next->args->args, env );
					}
					else
					{
						// else, evaluating 'default' statement...
						printf( "default:\n" );
						if ( ! emptyNode( next->args ) )
							eval( next->args, env );
					}
					// processing next statement...
					next = next->next;
				}
				printf( "}\n" );
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "var" ) == 0 )
	{
		// firsts, check if there is another identifiers declared...
		next = node->args;
		while ( next )
		{
			// search the node in declared list...
			tmp = findNodeByElement( next->element, env->declared );
			// if not exists, append a new identifier...
			if ( tmp == NULL )
			{
				tmp = cloneNode( next );
				// NOTE: (2002-07-12 Gabriele Budelacci)
				//	When a new variable is declared whithin a block,
				//	then the type is negated.
				tmp->type = -LISA_TYPE_VARIANT;		// please note minus '-' sign
				appendNode( tmp, env->declared );
			}
			else
			{
				// The identifier is already declared...
				// If the type is positive, the identifier can be redeclared...
				if ( tmp->type < 0 )
				{
					evalError( "variable already declared", tmp );
				}
				tmp->type = -LISA_TYPE_VARIANT;
			}
			// process next element
			next = next->next;
		}

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				// NOTE: (2002-06-27 Gabriele Budelacci)
				// In PHP language, declaration of variant
				// can be omitted.
				break;
			}
		}
		return;
	}

	//
	//                     while
	//                      / |
	//                 empty
	//                 /   |
	//        condition     statement
	//
	if ( strcmp( node->element, "while" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( "while ( " );
				evalCondition( node->args->args, env );
				printf( " )\n" );
				evalBlock( node->args->next, env );
				break;
			}
		}
		return;
	}

	evalError( "unimplemented keyword evaluation", node );
}//evalKeyword





// evalNumber:
//	Evaluate a number node in the specified environment.
void evalNumber( struct lisa_node *node, struct lisa_environment *env )
{
	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			printf( "%s", node->element );
			break;
		}
	}
}//evalNumber





// evalOperator:
//	Evaluate an operator node in the specified environment.
void evalOperator( struct lisa_node *node, struct lisa_environment *env )
{
	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			printf( " %s ", node->element );
			break;
		}
	}
}//evalOperator





// evalString:
//	Evaluate a string node in the specified environment.
void evalString( struct lisa_node *node, struct lisa_environment *env )
{
	switch ( env->language )
	{
		case LISA_LANG_PHP:
		{
			printf( "\"%s\"", node->element );
			break;
		}
	}
}//evalString





// evalTAGKeyword:
//	Evaluate a TAG keyword node in the specified environment.
void evalTAGKeyword( struct lisa_node *node, struct lisa_environment *env )
{
	struct lisa_environment *e;
	struct lisa_node        *tmp, *next;

	if ( strcmp( node->element, "case" ) == 0 )
	{
		// replace the parent environment...
		e = env->parent;
		destroyEnvironment( global_env );
		global_env = e;

		// create a child environment...
		global_env = childEnvironment( global_env );

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " case " );
				eval( node->args, env );
				printf( ": " );
				break;
			}
		}

		return;
	}

	if ( strcmp( node->element, "default" ) == 0 )
	{
		// replace the parent environment...
		e = env->parent;
		destroyEnvironment( global_env );
		global_env = e;

		// create a child environment...
		global_env = childEnvironment( global_env );

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " default: " );
				break;
			}
		}

		return;
	}

	if ( strcmp( node->element, "else" ) == 0 )
	{
		// replace the parent environment...
		e = env->parent;
		destroyEnvironment( global_env );
		global_env = e;

		// create a child environment...
		global_env = childEnvironment( global_env );

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " else: " );
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "endif" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " endif; " );
				break;
			}
		}
		// replace the parent environment...
		e = env->parent;
		destroyEnvironment( global_env );
		global_env = e;

		return;
	}

	if ( ( strcmp( node->element, "endforeach" ) == 0 ) ||
		 ( strcmp( node->element, "next" ) == 0 ) )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " endforeach; " );
				break;
			}
		}

		// replace the parent environment...
		e = env->parent;
		destroyEnvironment( global_env );
		global_env = e;

		return;
	}

	if ( strcmp( node->element, "endswitch" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " endswitch; " );
				break;
			}
		}
		// replace the parent environment...
		e = env->parent;
		destroyEnvironment( global_env );
		global_env = e;

		return;
	}

	if ( strcmp( node->element, "endwhile" ) == 0 )
	{
		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " endwhile; " );
				break;
			}
		}
		// replace the parent environment...
		e = env->parent;
		destroyEnvironment( global_env );
		global_env = e;

		return;
	}

	if ( strcmp( node->element, "foreach" ) == 0 )
	{
		int type;

		// check if the identifier is declared...
		tmp = findNodeByElement( node->args->element, env->declared );
		if ( tmp == NULL )
			evalError( "undeclared variable", node->args );

		// get the identifier type...
		type = tmp->type;
		if ( type < 0 ) type = -type;

		// create a child environment...
		global_env = childEnvironment( env );

		// switch on array or set
		switch ( type )
		{
			case LISA_TYPE_ARRAY:
			{
				switch ( env->language )
				{
					case LISA_LANG_PHP:
					{
						printf( " foreach ( $%s as ", node->args->element );

						// declaring the identifiers as variants...
						next = node->args->next;
						while ( next )
						{
							// search the node in declared list...
							tmp = findNodeByElement( next->element, env->declared );
							// if not exists, append a new identifier...
							if ( tmp == NULL )
							{
								tmp = cloneNode( next );
								// NOTE: (2002-07-12 Gabriele Budelacci)
								//	When a new variable is declared whithin a block,
								//	then the type is negated.
								tmp->type = -LISA_TYPE_VARIANT;		// please note minus '-' sign
								appendNode( tmp, env->declared );
							}
							else
							{
								// The identifier is already declared...
								// If the type is positive, the identifier can be redeclared...
								if ( tmp->type < 0 )
								{
									evalError( "variable already declared", tmp );
								}
								tmp->type = -LISA_TYPE_VARIANT;
							}
							// process next element
							next = next->next;
						}

						// eval the identifier list...
						next = node->args->next;
						printf( "$%s", next->element );
						if ( next->next )
							evalError( "no more than one variable allowed while processing an array", next );

						printf( " ): " );
						break;
					}
				}
				break;
			}

			case LISA_TYPE_SET:
			{
				switch ( env->language )
				{
					case LISA_LANG_PHP:
					{
						evalError( "unimplemented evaluation", node );
						break;
					}
				}
				break;
			}

			default:
			{
				evalError( "wrong type variable", node->args );
			}
		}
		return;
	}

	if ( strcmp( node->element, "if" ) == 0 )
	{
		// create a child environment...
		global_env = childEnvironment( env );

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " if ( " );
				evalCondition( node->args->args, env );
				printf( " ): " );
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "switch" ) == 0 )
	{
		// create a child environment...
		global_env = childEnvironment( env );

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " while ( " );
				evalCondition( node->args->args, env );
				printf( " ): " );
				break;
			}
		}
		return;
	}

	if ( strcmp( node->element, "while" ) == 0 )
	{
		// create a child environment...
		global_env = childEnvironment( env );

		switch ( env->language )
		{
			case LISA_LANG_PHP:
			{
				printf( " while ( " );
				evalCondition( node->args->args, env );
				printf( " ): " );
				break;
			}
		}
		return;
	}

	evalError( "unimplemented TAG keyword evaluation", node );
}//evalTAGKeyword


