summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-05-02 20:05:49 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-05-02 20:05:49 +0200
commit399c4acad3e4fc0306edfcd3320c61031fa90555 (patch)
tree7eb03fb4b4db057474a92069990ed2491fe5135c
parenta3651fe629769ee81acfd86d934a53866a688df0 (diff)
downloadcompilertests-399c4acad3e4fc0306edfcd3320c61031fa90555.tar.gz
compilertests-399c4acad3e4fc0306edfcd3320c61031fa90555.tar.bz2
implemented some type checks in assignments and expressions
-rw-r--r--ecomp-c/README2
-rw-r--r--ecomp-c/ec.c34
-rw-r--r--ecomp-c/test1.e2
-rwxr-xr-xecomp-c/tests/run_tests.sh6
-rw-r--r--ecomp-c/tests/type_check_assignment.e14
-rw-r--r--ecomp-c/tests/type_check_assignment.easm10
-rw-r--r--ecomp-c/tests/type_check_assignment.ecomp_err1
-rw-r--r--ecomp-c/tests/type_check_comparision.e16
-rw-r--r--ecomp-c/tests/type_check_comparision.easm15
-rw-r--r--ecomp-c/tests/type_check_comparision.ecomp_err1
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