diff options
Diffstat (limited to 'ecomp-c/ec.c')
-rw-r--r-- | ecomp-c/ec.c | 84 |
1 files changed, 70 insertions, 14 deletions
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c index f6e1926..2ab0fb1 100644 --- a/ecomp-c/ec.c +++ b/ecomp-c/ec.c @@ -831,7 +831,7 @@ typedef enum ExpressionNodeType { typedef struct ExpressionNode { ExpressionNodeType type; S_Symbol op; - struct ExpressionNode *left, *right; + struct ExpressionNode *left, *right, *next; int integer_value; int boolean_value; char character_value; @@ -846,6 +846,7 @@ static ExpressionNode *create_expression_node( void ) ExpressionNode *node = Allocate( sizeof( ExpressionNode ) ); node->left = NULL; node->right = NULL; + node->next = NULL; node->string_value = NULL; node->intarr_value = NULL; @@ -860,6 +861,9 @@ static void free_expression_node( ExpressionNode *node ) if( node->right != NULL ) { free_expression_node( node->right ); } + if( node->next != NULL ) { + free_expression_node( node->next ); + } if( node->string_value != NULL ) { free( node->string_value ); } @@ -1543,37 +1547,89 @@ static void parseWhileStatement( Scope *scope ) free( jump_label1 ); } -static void parseParameterList( Scope *scope ) +static ExpressionNode *parseParameterList( Scope *scope ) { - ExpressionNode *node; + ExpressionNode *head, *tail, *node; Expect( S_lparen ); - Emit( "( " ); + head = NULL; + tail = NULL; do { node = parseExpression( scope ); - generate_expression_comment( node ); + if( head == NULL && tail == NULL ) { + head = node; + tail = node; + } else { + node->next = head; + head = node; + } if( sym == S_comma ) { sym = getSym( ); } } while( sym != S_rparen ); Expect( S_rparen ); - - Emit( ")\n" ); - - emit_expression_code( node, scope ); + + return node; } static void parseProcedureCall( Scope *scope ) { - Symbol *symbol; + Symbol *symbol, *param; + int nof_expected_params; + int nof_actual_params; + ExpressionNode *head, *node; symbol = get_symbol( scope, ident ); + + nof_expected_params = 0; + param = symbol->scope->symbol; + while( param != NULL ) { + if( param->offset < 0 ) { + nof_expected_params++; + } + param = param->next; + } + + nof_actual_params = 0; + if( sym == S_lparen ) { + head = parseParameterList( scope ); + node = head; + while( node != NULL ) { + nof_actual_params++; + node = node->next; + } + } + + /* TODO: check parameter list types, not only cardinality + */ + if( nof_actual_params != nof_expected_params ) { + Abort( "procedure '%s' expects %d parameter(s), but %d were given", symbol->name, nof_expected_params, nof_actual_params ); + } + + /* emit assembly comments */ Emit( "; CALL %s", symbol->label ); - if( sym == S_lparen ) { - parseParameterList( scope ); - } else { - Emit( "\n" ); + if( nof_actual_params > 0 ) { + Emit( "( " ); + node = head; + while( node != NULL ) { + generate_expression_comment( node ); + node = node->next; + } + Emit( ")" ); + } + Emit( "\n" ); + + /* emit assembly to push parameters onto stack and call procedure */ + if( nof_actual_params > 0 ) { + node = head; + while( node != NULL ) { + emit_expression_code( node, scope ); + node = node->next; + } + + free_expression_node( head ); + } Emit( "call %s\n", symbol->label ); } |