summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-08-16 15:56:59 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-08-16 15:56:59 +0200
commitfdaf9ebf7daa1c98d420ff8eff4633e8ed277b13 (patch)
tree2425428e12874e9943c19007f17991d4b3af4169
parent2f57b93442e14d586684c584c1edf5ee29f3d0bb (diff)
downloadcompilertests-fdaf9ebf7daa1c98d420ff8eff4633e8ed277b13.tar.gz
compilertests-fdaf9ebf7daa1c98d420ff8eff4633e8ed277b13.tar.bz2
working on parameter checking
-rw-r--r--ecomp-c/ec.c84
-rwxr-xr-xecomp-c/test.sh1
-rw-r--r--ecomp-c/tests/procedure_call_too_many_parameters.e20
-rw-r--r--ecomp-c/tests/procedure_call_too_many_parameters.easm48
-rw-r--r--ecomp-c/tests/procedure_call_too_many_parameters.ecomp_err1
5 files changed, 140 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 );
}
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