libeval_compiler: initial support for multiple (>1) function/method arguments
This commit is contained in:
parent
6578a76b72
commit
5023d9a780
|
@ -24,6 +24,7 @@
|
|||
%type nt {LIBEVAL::TREE_NODE*}
|
||||
|
||||
%nonassoc G_IDENTIFIER G_ASSIGN G_SEMCOL.
|
||||
%left G_COMMA.
|
||||
%left G_BOOL_AND.
|
||||
%left G_BOOL_OR.
|
||||
%left G_BOOL_XOR.
|
||||
|
@ -78,6 +79,13 @@ nt(A) ::= G_IDENTIFIER(B).
|
|||
A = newNode( pEval, TR_IDENTIFIER, B.value );
|
||||
}
|
||||
|
||||
nt(A) ::= nt(B) G_COMMA nt(C).
|
||||
{
|
||||
A = newNode( pEval, TR_ARG_LIST );
|
||||
A->leaf[0] = B;
|
||||
A->leaf[1] = C;
|
||||
}
|
||||
|
||||
nt(A) ::= nt(B) G_LESS_THAN nt(C).
|
||||
{
|
||||
A = newNode( pEval, TR_OP_LESS );
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <cstdarg>
|
||||
|
@ -518,6 +519,8 @@ bool COMPILER::lexDefault( T_TOKEN& aToken )
|
|||
case ')': retval.token = G_PARENR; break;
|
||||
case ';': retval.token = G_SEMCOL; break;
|
||||
case '.': retval.token = G_STRUCT_REF; break;
|
||||
case ',': retval.token = G_COMMA; break;
|
||||
|
||||
|
||||
default:
|
||||
reportError( CST_PARSE, wxString::Format( _( "Unrecognized character '%c'" ), (char) ch ) );
|
||||
|
@ -569,6 +572,17 @@ void dumpNode( wxString& buf, TREE_NODE* tok, int depth = 0 )
|
|||
|
||||
break;
|
||||
|
||||
case TR_ARG_LIST:
|
||||
buf += "ARG_LIST: ";
|
||||
buf += formatNode( tok );
|
||||
|
||||
if( tok->leaf[0] )
|
||||
dumpNode( buf, tok->leaf[0], depth + 1 );
|
||||
if( tok->leaf[1] )
|
||||
dumpNode( buf, tok->leaf[1], depth + 1 );
|
||||
|
||||
break;
|
||||
|
||||
case TR_STRING:
|
||||
buf += "STRING: ";
|
||||
buf += formatNode( tok );
|
||||
|
@ -698,6 +712,44 @@ static void prepareTree( LIBEVAL::TREE_NODE *node )
|
|||
prepareTree( node->leaf[1] );
|
||||
}
|
||||
|
||||
static std::vector<TREE_NODE*> squashParamList( TREE_NODE* root )
|
||||
{
|
||||
std::vector<TREE_NODE*> args;
|
||||
|
||||
if( !root )
|
||||
{
|
||||
return args;
|
||||
}
|
||||
|
||||
if( root->op != TR_ARG_LIST && root->op != TR_NULL )
|
||||
{
|
||||
args.push_back( root );
|
||||
}
|
||||
else
|
||||
{
|
||||
TREE_NODE *n = root;
|
||||
do
|
||||
{
|
||||
if( n->leaf[1] )
|
||||
args.push_back(n->leaf[1]);
|
||||
|
||||
n = n->leaf[0];
|
||||
} while ( n && n->op == TR_ARG_LIST );
|
||||
|
||||
if( n )
|
||||
{
|
||||
args.push_back(n);
|
||||
}
|
||||
}
|
||||
|
||||
std::reverse( args.begin(), args.end() );
|
||||
|
||||
for(int i = 0; i < args.size(); i++ )
|
||||
libeval_dbg(10, "squash arg%d: %s\n", i, (const char*) *args[i]->value.str );
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
||||
{
|
||||
|
@ -800,6 +852,7 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
|
||||
wxString functionName = *node->leaf[1]->leaf[0]->value.str;
|
||||
auto func = aCode->CreateFuncCall( functionName );
|
||||
std::vector<TREE_NODE*> params = squashParamList( node->leaf[1]->leaf[1] );
|
||||
|
||||
libeval_dbg( 10, "emit func call: %s\n", functionName );
|
||||
|
||||
|
@ -812,22 +865,18 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
if( func )
|
||||
{
|
||||
// Preflight the function call
|
||||
auto argsLeaf = node->leaf[1]->leaf[1];
|
||||
wxString paramStr;
|
||||
|
||||
if( argsLeaf->op != TR_NULL ) // function has an argument
|
||||
for( auto pnode : params )
|
||||
{
|
||||
paramStr = *node->leaf[1]->leaf[1]->value.str;
|
||||
VALUE* param = aPreflightContext->AllocValue();
|
||||
|
||||
param->Set( paramStr );
|
||||
param->Set( *pnode->value.str );
|
||||
aPreflightContext->Push( param );
|
||||
}
|
||||
|
||||
aPreflightContext->SetErrorCallback(
|
||||
[&]( const wxString& aMessage, int aOffset )
|
||||
{
|
||||
size_t loc = node->leaf[1]->leaf[1]->srcPos- paramStr.Length();
|
||||
size_t loc = node->leaf[1]->leaf[1]->srcPos;
|
||||
reportError( CST_CODEGEN, aMessage, (int) loc - 1 );
|
||||
} );
|
||||
|
||||
|
@ -851,7 +900,10 @@ bool COMPILER::generateUCode( UCODE* aCode, CONTEXT* aPreflightContext )
|
|||
// a TR_OP_FUNC_CALL and its function parameter
|
||||
stack.pop_back();
|
||||
stack.push_back( node->leaf[1] );
|
||||
stack.push_back( node->leaf[1]->leaf[1] );
|
||||
for( auto pnode : params )
|
||||
{
|
||||
stack.push_back( pnode );
|
||||
}
|
||||
|
||||
node->leaf[1]->SetUop( TR_OP_METHOD_CALL, func, std::move( vref ) );
|
||||
node->isTerminal = false;
|
||||
|
|
|
@ -95,7 +95,8 @@ enum TOKEN_TYPE_T
|
|||
TR_STRUCT_REF = 4,
|
||||
TR_STRING = 5,
|
||||
TR_UNIT = 6,
|
||||
TR_NULL = 7
|
||||
TR_ARG_LIST = 7,
|
||||
TR_NULL = 8
|
||||
};
|
||||
|
||||
class UOP;
|
||||
|
|
Loading…
Reference in New Issue