From fdaf9ebf7daa1c98d420ff8eff4633e8ed277b13 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 16 Aug 2020 15:56:59 +0200 Subject: working on parameter checking --- ecomp-c/ec.c | 84 ++++++++++++++++++---- ecomp-c/test.sh | 1 + ecomp-c/tests/procedure_call_too_many_parameters.e | 20 ++++++ .../tests/procedure_call_too_many_parameters.easm | 48 +++++++++++++ .../procedure_call_too_many_parameters.ecomp_err | 1 + 5 files changed, 140 insertions(+), 14 deletions(-) create mode 100644 ecomp-c/tests/procedure_call_too_many_parameters.e create mode 100644 ecomp-c/tests/procedure_call_too_many_parameters.easm create mode 100644 ecomp-c/tests/procedure_call_too_many_parameters.ecomp_err 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 ); } diff --git a/ecomp-c/test.sh b/ecomp-c/test.sh index 6030462..fbcc2b6 100755 --- a/ecomp-c/test.sh +++ b/ecomp-c/test.sh @@ -27,6 +27,7 @@ procedure_forward_declaration procedure_local_variables procedure_scoping procedure_call_value_parameters +procedure_call_too_many_parameters example_divisors example_divisors_array_result example_reverse_array diff --git a/ecomp-c/tests/procedure_call_too_many_parameters.e b/ecomp-c/tests/procedure_call_too_many_parameters.e new file mode 100644 index 0000000..bbbe12e --- /dev/null +++ b/ecomp-c/tests/procedure_call_too_many_parameters.e @@ -0,0 +1,20 @@ +/* + * procedure call with wrong number of parameters + */ + +module procedure_call_value_parameters; + +var + i : integer := 1; + +procedure proc( x : integer ); +var + l : integer; +begin + l := x; + i := l; +end + +begin + proc( 42, 77 ); +end diff --git a/ecomp-c/tests/procedure_call_too_many_parameters.easm b/ecomp-c/tests/procedure_call_too_many_parameters.easm new file mode 100644 index 0000000..d7fb8b4 --- /dev/null +++ b/ecomp-c/tests/procedure_call_too_many_parameters.easm @@ -0,0 +1,48 @@ +format binary +use32 +org $1000000 +jmp __global_0 +; DECL i -> integer, 1 +; param x, offset: -8, size: 4 +; PROC proc +__global_proc: +push ebp +push esp +pop ebp +; DECL l -> integer, 0 +; local l, offset: 4, size: 4 +mov eax, 4 +sub esp, eax +push ebp +pop ebx +mov eax, 4 +sub ebx, eax +mov eax, 0 +mov [ebx], eax +; LET l <- x +push ebp +pop ebx +mov eax, -8 +sub ebx, eax +mov eax, [ebx] +push eax +push ebp +pop ebx +mov eax, 4 +sub ebx, eax +pop eax +mov [ebx], eax +; LET i <- l +push ebp +pop ebx +mov eax, 4 +sub ebx, eax +mov eax, [ebx] +push eax +pop eax +mov [i], eax +mov eax, 4 +add esp, eax +pop ebp +ret 4 +__global_0: diff --git a/ecomp-c/tests/procedure_call_too_many_parameters.ecomp_err b/ecomp-c/tests/procedure_call_too_many_parameters.ecomp_err new file mode 100644 index 0000000..a638b17 --- /dev/null +++ b/ecomp-c/tests/procedure_call_too_many_parameters.ecomp_err @@ -0,0 +1 @@ +Error line 20, pos 1: procedure 'proc' expects 1 parameter(s), but 2 were given -- cgit v1.2.3-54-g00ecf