diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-02 20:05:49 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-02 20:05:49 +0200 |
commit | 399c4acad3e4fc0306edfcd3320c61031fa90555 (patch) | |
tree | 7eb03fb4b4db057474a92069990ed2491fe5135c | |
parent | a3651fe629769ee81acfd86d934a53866a688df0 (diff) | |
download | compilertests-399c4acad3e4fc0306edfcd3320c61031fa90555.tar.gz compilertests-399c4acad3e4fc0306edfcd3320c61031fa90555.tar.bz2 |
implemented some type checks in assignments and expressions
-rw-r--r-- | ecomp-c/README | 2 | ||||
-rw-r--r-- | ecomp-c/ec.c | 34 | ||||
-rw-r--r-- | ecomp-c/test1.e | 2 | ||||
-rwxr-xr-x | ecomp-c/tests/run_tests.sh | 6 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_assignment.e | 14 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_assignment.easm | 10 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_assignment.ecomp_err | 1 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_comparision.e | 16 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_comparision.easm | 15 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_comparision.ecomp_err | 1 |
10 files changed, 97 insertions, 4 deletions
diff --git a/ecomp-c/README b/ecomp-c/README index e13b90e..58bf2db 100644 --- a/ecomp-c/README +++ b/ecomp-c/README @@ -79,7 +79,7 @@ inner-nested functions/procedures don't do automatic type promotion, maybe something like uint8, int8, etc. no recursion, well, we might need that -3:21:00 video Hjalfi writes an assembler +4:09:00 video Hjalfi writes an assembler no frees as things are freed in the end, well, we don't obey that rule, compiler/assember should be embedable and they have local scopes which diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c index e095dc0..f560d6b 100644 --- a/ecomp-c/ec.c +++ b/ecomp-c/ec.c @@ -658,6 +658,7 @@ typedef struct ExpressionNode { struct ExpressionNode *left, *right; int number; Symbol *symbol; + Symbol *actual_type; } ExpressionNode; static ExpressionNode *create_expression_node( void ) @@ -878,6 +879,7 @@ static ExpressionNode *parseFactor( void ) node = create_expression_node( ); node->type = EXPRESSION_NODE_TYPE_CONST; node->number = num; + node->actual_type = get_symbol( current_scope, "integer" ); sym = getSym( ); } else if( sym == S_ident ) { symbol = get_symbol( current_scope, ident ); @@ -891,6 +893,7 @@ static ExpressionNode *parseFactor( void ) node = create_expression_node( ); node->type = EXPRESSION_NODE_TYPE_CONST; node->number = symbol->value; + node->actual_type = symbol->type; } if( symbol->class == SYMBOL_CLASS_VARIABLE ) { if( !symbol->initialized ) { @@ -899,6 +902,7 @@ static ExpressionNode *parseFactor( void ) node = create_expression_node( ); node->type = EXPRESSION_NODE_TYPE_VAR; node->symbol = symbol; + node->actual_type = symbol->type; } sym = getSym( ); } else if( sym == S_lparen ) { @@ -911,6 +915,7 @@ static ExpressionNode *parseFactor( void ) node->op = sym; sym = getSym( ); node->left = parseFactor( ); + node->actual_type = node->left->actual_type; } else { Abort( "Expected a literal, a variable or a constant." ); } @@ -931,6 +936,13 @@ static ExpressionNode *parseTerm( void ) sym = getSym( ); node->left = tmp; node->right = parseFactor( ); + + if( node->left->actual_type == node->right->actual_type ) { + node->actual_type = node->left->actual_type; + } else { + Abort( "Incompatible types in expression: '%s' on the left, '%s' on the right", + node->left->actual_type->name, node->right->actual_type->name ); + } } return node; @@ -949,6 +961,13 @@ static ExpressionNode *parseSimpleExpression( void ) sym = getSym( ); node->left = tmp; node->right = parseTerm( ); + + if( node->left->actual_type == node->right->actual_type ) { + node->actual_type = node->left->actual_type; + } else { + Abort( "Incompatible types in expression: '%s' on the left, '%s' on the right", + node->left->actual_type->name, node->right->actual_type->name ); + } } return node; @@ -981,6 +1000,13 @@ static ExpressionNode *parseExpression( void ) sym = getSym( ); node->left = tmp; node->right = parseSimpleExpression( ); + + if( node->left->actual_type == node->right->actual_type ) { + node->actual_type = get_symbol( current_scope, "boolean" ); + } else { + Abort( "Incompatible types in expression: '%s' on the left, '%s' on the right", + node->left->actual_type->name, node->right->actual_type->name ); + } } return node; @@ -1005,9 +1031,13 @@ static void parseAssignment( Scope *scope ) Expect( S_assign ); - /* TODO: RHS is an expression tree, must be a) interpreted, - * b) simplified c) generate code */ node = parseExpression( ); + + if( symbol->type != node->actual_type ) { + Abort( "Incompatible assignment of expression of type '%s' to variable '%s' of type '%s'", + node->actual_type->name, symbol->name, symbol->type->name ); + } + Emit( "; LET %s <- ", symbol->name ); generate_expression_comment( node ); Emit( "\n" ); diff --git a/ecomp-c/test1.e b/ecomp-c/test1.e index 88a6d26..2836091 100644 --- a/ecomp-c/test1.e +++ b/ecomp-c/test1.e @@ -47,7 +47,7 @@ begin end; i := 0; - while ( i < 10 ) and not flag do + while ( i < 10 ) and ( not flag ) do i := i + 1; end; end diff --git a/ecomp-c/tests/run_tests.sh b/ecomp-c/tests/run_tests.sh index 884821c..e40b4d9 100755 --- a/ecomp-c/tests/run_tests.sh +++ b/ecomp-c/tests/run_tests.sh @@ -17,6 +17,8 @@ variable_assign_from_expression boolean_variable if_statement bool_conditions +type_check_assignment +type_check_comparision while_statement example_divisors " @@ -25,6 +27,10 @@ run_test( ) { TEST=$1 echo -n "$TEST" + if test ! -f "$TEST.e"; then + echo " SKIP (not found)" + return + fi ../ec < $TEST.e > $TEST.asm 2> _tmp COMPILATION_RES=$? grep -v '^Total ' _tmp | grep -v '^Arena' | grep -v 'bytes.*=' | grep -v 'max mmap' > $TEST.comp_err diff --git a/ecomp-c/tests/type_check_assignment.e b/ecomp-c/tests/type_check_assignment.e new file mode 100644 index 0000000..d030525 --- /dev/null +++ b/ecomp-c/tests/type_check_assignment.e @@ -0,0 +1,14 @@ +/* + * make sure assignment from illegal types throws an error + */ + +module bool_conditions; + +var + i : integer; + b : boolean; + +begin + i := 1; + b := i; +end diff --git a/ecomp-c/tests/type_check_assignment.easm b/ecomp-c/tests/type_check_assignment.easm new file mode 100644 index 0000000..5c13f33 --- /dev/null +++ b/ecomp-c/tests/type_check_assignment.easm @@ -0,0 +1,10 @@ +format binary +use32 +org $1000000 +; DECL i -> integer +; DECL b -> boolean +; LET i <- 1 +mov eax, 1 +push eax +pop eax +mov [i], eax diff --git a/ecomp-c/tests/type_check_assignment.ecomp_err b/ecomp-c/tests/type_check_assignment.ecomp_err new file mode 100644 index 0000000..9daaf6d --- /dev/null +++ b/ecomp-c/tests/type_check_assignment.ecomp_err @@ -0,0 +1 @@ +Error line 14, pos 1: Incompatible assignment of expression of type 'integer' to variable 'b' of type 'boolean' diff --git a/ecomp-c/tests/type_check_comparision.e b/ecomp-c/tests/type_check_comparision.e new file mode 100644 index 0000000..ceaa9ef --- /dev/null +++ b/ecomp-c/tests/type_check_comparision.e @@ -0,0 +1,16 @@ +/* + * make sure assignment from illegal types throws an error + */ + +module bool_conditions; + +var + i : integer; + b : boolean; + +begin + i := 1; + b := false; + if i = 2 and false do + end; +end diff --git a/ecomp-c/tests/type_check_comparision.easm b/ecomp-c/tests/type_check_comparision.easm new file mode 100644 index 0000000..2441f17 --- /dev/null +++ b/ecomp-c/tests/type_check_comparision.easm @@ -0,0 +1,15 @@ +format binary +use32 +org $1000000 +; DECL i -> integer +; DECL b -> boolean +; LET i <- 1 +mov eax, 1 +push eax +pop eax +mov [i], eax +; LET b <- 0 +mov eax, 0 +push eax +pop eax +mov [b], eax diff --git a/ecomp-c/tests/type_check_comparision.ecomp_err b/ecomp-c/tests/type_check_comparision.ecomp_err new file mode 100644 index 0000000..a772c01 --- /dev/null +++ b/ecomp-c/tests/type_check_comparision.ecomp_err @@ -0,0 +1 @@ +Error line 15, pos 1: Incompatible types in expression: 'integer' on the left, 'boolean' on the right |