summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-05-23 20:36:24 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-05-23 20:36:24 +0200
commit58a041e920116d7f06100a588172b4719e32a40b (patch)
tree64ace16ad16e3261699e735480153f06c0fae8d8
parentb35ee46072e2a98de06d722ad8db33306e95944c (diff)
downloadcompilertests-58a041e920116d7f06100a588172b4719e32a40b.tar.gz
compilertests-58a041e920116d7f06100a588172b4719e32a40b.tar.bz2
added character type
multi-typed values for constants and variables (all symbols) adapted tests to better output of debug code in assembly
-rw-r--r--ecomp-c/ec.c237
-rw-r--r--ecomp-c/minie.ebnf1
-rw-r--r--ecomp-c/test1.e5
-rw-r--r--ecomp-c/tests/boolean_variable.easm2
-rw-r--r--ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm2
-rw-r--r--ecomp-c/tests/const_assignment_from_unknown_constant.easm2
-rw-r--r--ecomp-c/tests/type_check_assignment.easm2
-rw-r--r--ecomp-c/tests/type_check_comparision.easm4
-rw-r--r--ecomp-c/tests/variable_initialization.easm2
9 files changed, 205 insertions, 52 deletions
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c
index 9bd2ca2..65c5fad 100644
--- a/ecomp-c/ec.c
+++ b/ecomp-c/ec.c
@@ -23,6 +23,7 @@ static int DEBUG_SCANNER = 0;
typedef enum {
S_ident = 0,
S_number,
+ S_char,
S_module,
S_begin,
S_end,
@@ -58,6 +59,7 @@ typedef enum {
static char *symname[S_eof+1] = {
"ident",
"number",
+ "char",
"module",
"begin",
"end",
@@ -98,6 +100,7 @@ static S_Symbol sym;
static char ident[MAX_IDENT_LEN+1];
static int num;
+static int ch;
static void Err( char *s, va_list args )
{
@@ -209,6 +212,23 @@ static void number( void )
}
}
+static void character( void )
+{
+ if( look == '\'' ) {
+ look = getChar( );
+ if( isDigit( look ) || isAlpha( look ) ) {
+ ch = look;
+ } else {
+ Abort( "Expecting a character as character literal" );
+ }
+ look = getChar( );
+ if( look != '\'' ) {
+ Abort( "Unterminated character literal" );
+ }
+ look = getChar( );
+ }
+}
+
static void identifier( void )
{
int n = 0;
@@ -406,7 +426,11 @@ static S_Symbol getSym( void )
case 'Y':
case 'Z':
identifier( );
- s = S_ident;
+ s = S_ident;
+ break;
+ case '\'':
+ character( );
+ s = S_char;
break;
case ':':
look = getChar( );
@@ -548,12 +572,18 @@ typedef struct Symbol {
struct Symbol *next;
struct Symbol *type;
/* constant */
- int value;
+ int integer_value;
+ char boolean_value;
+ int character_value;
/* variable */
int initialized;
int size;
} Symbol;
+static Symbol *integer_type;
+static Symbol *boolean_type;
+static Symbol *character_type;
+
typedef struct Scope {
char *name;
int label_no;
@@ -676,7 +706,9 @@ typedef struct ExpressionNode {
ExpressionNodeType type;
S_Symbol op;
struct ExpressionNode *left, *right;
- int number;
+ int integer_value;
+ int boolean_value;
+ int character_value;
Symbol *symbol;
Symbol *actual_type;
} ExpressionNode;
@@ -705,7 +737,21 @@ static void generate_expression_comment( ExpressionNode *node )
{
switch( node->type ) {
case EXPRESSION_NODE_TYPE_CONST:
- Emit( "%d ", node->number );
+ if( node->actual_type == integer_type ) {
+ Emit( "%d ", node->integer_value );
+ } else if( node->actual_type == boolean_type ) {
+ if( node->boolean_value == 0 ) {
+ Emit( "false " );
+ } else if( node->boolean_value == 1 ) {
+ Emit( "true " );
+ } else {
+ Abort( "Internal representation problem of a boolean (is '%d')", node->boolean_value );
+ }
+ } else if( node->actual_type == character_type ) {
+ Emit( "'%c' ", node->character_value );
+ } else {
+ Abort( "Unhandled basic type '%s' in assembly comment generation", node->actual_type->name );
+ }
break;
case EXPRESSION_NODE_TYPE_VAR:
@@ -780,7 +826,15 @@ static void emit_expression_code( ExpressionNode *node, Scope *scope )
{
switch( node->type ) {
case EXPRESSION_NODE_TYPE_CONST:
- Emit( "mov eax, %d\n", node->number );
+ if( node->actual_type == integer_type ) {
+ Emit( "mov eax, %d\n", node->integer_value );
+ } else if( node->actual_type == boolean_type ) {
+ Emit( "mov eax, %d\n", node->boolean_value );
+ } else if( node->actual_type == character_type ) {
+ Emit( "mov eax, %d\n", node->character_value );
+ } else {
+ Abort( "Missing expression node code generation handling for type '%s'", node->actual_type->name );
+ }
Emit( "push eax\n" );
break;
@@ -920,8 +974,14 @@ static ExpressionNode *parseFactor( void )
if( sym == S_number ) {
node = create_expression_node( );
node->type = EXPRESSION_NODE_TYPE_CONST;
- node->number = num;
- node->actual_type = get_symbol( current_scope, "integer" );
+ node->integer_value = num;
+ node->actual_type = integer_type;
+ sym = getSym( );
+ } else if( sym == S_char ) {
+ node = create_expression_node( );
+ node->type = EXPRESSION_NODE_TYPE_CONST;
+ node->character_value = ch;
+ node->actual_type = character_type;
sym = getSym( );
} else if( sym == S_ident ) {
symbol = get_symbol( current_scope, ident );
@@ -934,8 +994,16 @@ static ExpressionNode *parseFactor( void )
if( symbol->class == SYMBOL_CLASS_CONSTANT ) {
node = create_expression_node( );
node->type = EXPRESSION_NODE_TYPE_CONST;
- node->number = symbol->value;
node->actual_type = symbol->type;
+ if( node->actual_type == integer_type ) {
+ node->integer_value = symbol->integer_value;
+ } else if( node->actual_type == boolean_type ) {
+ node->boolean_value = symbol->boolean_value;
+ } else if( node->actual_type == character_type ) {
+ node->character_value = symbol->character_value;
+ } else {
+ Abort( "Unhandled expression assignment from identifier with type '%s'", node->actual_type->name );
+ }
}
if( symbol->class == SYMBOL_CLASS_VARIABLE ) {
if( !symbol->initialized ) {
@@ -1207,8 +1275,13 @@ static ExpressionNode *parseConstExpression( void )
if( sym == S_number ) {
node->type = EXPRESSION_NODE_TYPE_CONST;
- node->number = num;
- node->actual_type = get_symbol( current_scope, "integer" );
+ node->integer_value = num;
+ node->actual_type = integer_type;
+ sym = getSym( );
+ } else if( sym == S_char ) {
+ node->type = EXPRESSION_NODE_TYPE_CONST;
+ node->character_value = ch;
+ node->actual_type = character_type;
sym = getSym( );
} else if( sym == S_ident ) {
Symbol *symbol = get_symbol( current_scope, ident );
@@ -1229,6 +1302,74 @@ static ExpressionNode *parseConstExpression( void )
return node;
}
+static void generate_symbol_comment( char *mode, Symbol *constant )
+{
+ Emit( "; %s %s -> %s, ", mode, constant->name, constant->type->name );
+ if( constant->type == integer_type ) {
+ Emit( "%d", constant->integer_value );
+ } else if( constant->type == boolean_type ) {
+ if( constant->boolean_value == 0 ) {
+ Emit( "false" );
+ } else if( constant->boolean_value == 1 ) {
+ Emit( "true" );
+ } else {
+ Abort( "Wrong internal value '%d' of a boolean when printing constant comment", constant->boolean_value );
+ }
+ } else if( constant->type == character_type ) {
+ Emit( "'%c'", constant->character_value );
+ } else {
+ Abort( "Unhandled symbol (%s) comment case for type '%s'", mode, constant->type->name );
+ }
+ Emit( "\n" );
+}
+
+static void generate_constant_comment( Symbol *variable )
+{
+ generate_symbol_comment( "CONST", variable );
+}
+
+static void generate_variable_comment( Symbol *variable )
+{
+ generate_symbol_comment( "DECL", variable );
+}
+
+static void symbol_copy_value( Symbol *from, Symbol *to )
+{
+
+ if( from->type != to->type ) {
+ Abort( "type mismatch when copying symbol value (from: '%s', to: '%s')",
+ from->type->name, to->type->name );
+ }
+
+ if( from->type == integer_type ) {
+ to->integer_value = from->integer_value;
+ } else if( from->type == boolean_type ) {
+ to->boolean_value = from->boolean_value;
+ } else if( from->type == character_type ) {
+ to->character_value = from->character_value;
+ } else {
+ Abort( "Unhandled case for type '%s' when copying value of symbol", from->type->name );
+ }
+}
+
+static void symbol_copy_node_value( ExpressionNode *from, Symbol *to )
+{
+ if( from->actual_type != to->type ) {
+ Abort( "type mismatch when copying node to symbol value (from: '%s', to: '%s')",
+ from->actual_type->name, to->type->name );
+ }
+
+ if( from->actual_type == integer_type ) {
+ to->integer_value = from->integer_value;
+ } else if( from->actual_type == boolean_type ) {
+ to->boolean_value = from->boolean_value;
+ } else if( from->actual_type == character_type ) {
+ to->character_value = from->character_value;
+ } else {
+ Abort( "Unhandled case for type '%s' when copying value of symbol from expression node", from->actual_type->name );
+ }
+}
+
static void parseConstDeclaration( void )
{
int nof_constants = 0;
@@ -1268,19 +1409,23 @@ static void parseConstDeclaration( void )
Abort( "Assigning a constant of type '%s' from an expression of type '%s'",
type->name, node->actual_type->name );
}
+
if( node->type == EXPRESSION_NODE_TYPE_CONST ) {
for( i = 0; i < nof_constants; i++ ) {
- constant[i]->value = node->number;
constant[i]->type = node->actual_type;
- Emit( "; CONST %s -> %s, %d\n", constant[i]->name, constant[i]->type->name, constant[i]->value );
+ symbol_copy_node_value( node, constant[i] );
}
} else if( node->type == EXPRESSION_NODE_TYPE_VAR ) {
for( i = 0; i < nof_constants; i++ ) {
- constant[i]->value = node->symbol->value;
constant[i]->type = node->symbol->type;
- Emit( "; CONST %s -> %s, %d\n", constant[i]->name, constant[i]->type->name, constant[i]->value );
+ symbol_copy_value( node->symbol, constant[i] );
}
}
+
+ for( i = 0; i < nof_constants; i++ ) {
+ generate_constant_comment( constant[i] );
+ }
+
free_expression_node( node );
}
@@ -1339,27 +1484,30 @@ static void parseVariableDeclaration( void )
Abort( "Assigning a variable of type '%s' from an expression of type '%s'",
type->name, node->actual_type->name );
}
+
if( node->type == EXPRESSION_NODE_TYPE_CONST ) {
for( i = 0; i < nof_variables; i++ ) {
- variable[i]->value = node->number;
variable[i]->type = node->actual_type;
+ symbol_copy_node_value( node, variable[i] );
}
} else if( node->type == EXPRESSION_NODE_TYPE_VAR ) {
for( i = 0; i < nof_variables; i++ ) {
- variable[i]->value = node->symbol->value;
variable[i]->type = node->symbol->type;
+ symbol_copy_value( node->symbol, variable[i] );
}
}
free_expression_node( node );
} else {
for( i = 0; i < nof_variables; i++ ) {
- variable[i]->value = 0;
+ variable[i]->integer_value = 0;
+ variable[i]->boolean_value = 0; /* false */
+ variable[i]->character_value = 0; /* NUL */
variable[i]->type = type;
}
}
for( i = 0; i < nof_variables; i++ ) {
- Emit( "; DECL %s -> %s, %d\n", variable[i]->name, variable[i]->type->name, variable[i]->value );
+ generate_variable_comment( variable[i] );
}
}
@@ -1403,24 +1551,24 @@ static void parseModule( void )
static void register_internal_types( Scope *scope )
{
- Symbol *type_symbol, *const_symbol;
-
- type_symbol = insert_symbol( current_scope, "integer", SYMBOL_CLASS_TYPE );
- type_symbol->size = 4;
+ Symbol *const_symbol;
+
+ integer_type = insert_symbol( current_scope, "integer", SYMBOL_CLASS_TYPE );
+ integer_type->size = 4;
- type_symbol = insert_symbol( current_scope, "boolean", SYMBOL_CLASS_TYPE );
- type_symbol->size = 1;
+ boolean_type = insert_symbol( current_scope, "boolean", SYMBOL_CLASS_TYPE );
+ boolean_type->size = 1;
const_symbol = insert_symbol( current_scope, "false", SYMBOL_CLASS_CONSTANT );
- const_symbol->type = type_symbol;
- const_symbol->value = 0;
+ const_symbol->type = boolean_type;
+ const_symbol->boolean_value = 0;
const_symbol = insert_symbol( current_scope, "true", SYMBOL_CLASS_CONSTANT );
- const_symbol->type = type_symbol;
- const_symbol->value = 1;
+ const_symbol->type = boolean_type;
+ const_symbol->boolean_value = 1;
- type_symbol = insert_symbol( current_scope, "char", SYMBOL_CLASS_TYPE );
- type_symbol->size = 1;
+ character_type = insert_symbol( current_scope, "character", SYMBOL_CLASS_TYPE );
+ character_type->size = 1;
}
static void init( void )
@@ -1453,20 +1601,21 @@ static void epilogue( void )
symbol = current_scope->symbol;
while( symbol != NULL ) {
if( symbol->class == SYMBOL_CLASS_VARIABLE ) {
- switch( symbol->type->size ) {
- case 4:
- Emit( "%s: dd $", symbol->name );
- Emit_DD( symbol->value );
- Emit( "\n" );
- break;
- case 1:
- Emit( "%s: db $", symbol->name );
- Emit_Hexbyte( symbol->value );
- Emit( "\n" );
- break;
- default:
- Abort( "Unhandled size of type '%s' in variable '%s'",
- symbol->type->name, symbol->name );
+ if( symbol->type == integer_type ) {
+ Emit( "%s: dd $", symbol->name );
+ Emit_DD( symbol->integer_value );
+ Emit( "\n" );
+ } else if( symbol->type == boolean_type ) {
+ Emit( "%s: db $", symbol->name );
+ Emit_Hexbyte( symbol->boolean_value );
+ Emit( "\n" );
+ } else if( symbol->type == character_type ) {
+ Emit( "%s: db $", symbol->name );
+ Emit_Hexbyte( symbol->character_value );
+ Emit( "\n" );
+ } else {
+ Abort( "Unhandled variable space reservation and initializiation for type '%s' in variable '%s'",
+ symbol->type->name, symbol->name );
}
}
symbol = symbol->next;
diff --git a/ecomp-c/minie.ebnf b/ecomp-c/minie.ebnf
index be82d9e..a0558b6 100644
--- a/ecomp-c/minie.ebnf
+++ b/ecomp-c/minie.ebnf
@@ -4,6 +4,7 @@ Letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L"
Special = "_" .
Identifier = Letter { Letter | Digit | Special } .
Number = Digit { Digit } .
+Character = "'" Digit | Letter "'" .
Factor = Number | Identifier | "(" Expression ")" | "not" Factor .
Term = Factor { ( "*" | "/" | "mod" | "and" ) Factor } .
diff --git a/ecomp-c/test1.e b/ecomp-c/test1.e
index 28d2516..5648c9f 100644
--- a/ecomp-c/test1.e
+++ b/ecomp-c/test1.e
@@ -8,6 +8,7 @@ const
// integer constant
N, M : integer = 20;
O : integer = N;
+ C : character = 'a';
// boolean constant
INIT_STATE : boolean = true;
@@ -22,7 +23,7 @@ var
d, e, f : integer;
flag : boolean;
i : integer;
- j : char;
+ j : character := C;
begin
a := 1;
@@ -51,4 +52,6 @@ begin
while ( i < 10 ) and not flag do
i := i + 1;
end;
+
+ j := 'b';
end
diff --git a/ecomp-c/tests/boolean_variable.easm b/ecomp-c/tests/boolean_variable.easm
index d76a31d..4f9c733 100644
--- a/ecomp-c/tests/boolean_variable.easm
+++ b/ecomp-c/tests/boolean_variable.easm
@@ -3,7 +3,7 @@ use32
org $1000000
; DECL a -> integer, 0
; DECL b -> integer, 0
-; DECL flag -> boolean, 0
+; DECL flag -> boolean, false
; LET a <- 573785173
mov eax, 573785173
push eax
diff --git a/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm b/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm
index 266ad15..f969c36 100644
--- a/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm
+++ b/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm
@@ -2,4 +2,4 @@ format binary
use32
org $1000000
; CONST N -> integer, 20
-; CONST B -> boolean, 0
+; CONST B -> boolean, false
diff --git a/ecomp-c/tests/const_assignment_from_unknown_constant.easm b/ecomp-c/tests/const_assignment_from_unknown_constant.easm
index 266ad15..f969c36 100644
--- a/ecomp-c/tests/const_assignment_from_unknown_constant.easm
+++ b/ecomp-c/tests/const_assignment_from_unknown_constant.easm
@@ -2,4 +2,4 @@ format binary
use32
org $1000000
; CONST N -> integer, 20
-; CONST B -> boolean, 0
+; CONST B -> boolean, false
diff --git a/ecomp-c/tests/type_check_assignment.easm b/ecomp-c/tests/type_check_assignment.easm
index 73e7972..03888c0 100644
--- a/ecomp-c/tests/type_check_assignment.easm
+++ b/ecomp-c/tests/type_check_assignment.easm
@@ -2,7 +2,7 @@ format binary
use32
org $1000000
; DECL i -> integer, 0
-; DECL b -> boolean, 0
+; DECL b -> boolean, false
; LET i <- 1
mov eax, 1
push eax
diff --git a/ecomp-c/tests/type_check_comparision.easm b/ecomp-c/tests/type_check_comparision.easm
index ab28b5b..e8fd0ee 100644
--- a/ecomp-c/tests/type_check_comparision.easm
+++ b/ecomp-c/tests/type_check_comparision.easm
@@ -2,13 +2,13 @@ format binary
use32
org $1000000
; DECL i -> integer, 0
-; DECL b -> boolean, 0
+; DECL b -> boolean, false
; LET i <- 1
mov eax, 1
push eax
pop eax
mov [i], eax
-; LET b <- 0
+; LET b <- false
mov eax, 0
push eax
pop eax
diff --git a/ecomp-c/tests/variable_initialization.easm b/ecomp-c/tests/variable_initialization.easm
index d3aac22..369b049 100644
--- a/ecomp-c/tests/variable_initialization.easm
+++ b/ecomp-c/tests/variable_initialization.easm
@@ -5,7 +5,7 @@ org $1000000
; DECL a -> integer, 0
; DECL b -> integer, 1
; DECL c -> integer, 0
-; DECL d -> boolean, 1
+; DECL d -> boolean, true
; LET c <- 2
mov eax, 2
push eax