summaryrefslogtreecommitdiff
path: root/ecomp-c/ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-c/ec.c')
-rw-r--r--ecomp-c/ec.c170
1 files changed, 130 insertions, 40 deletions
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c
index 5b72bfc..5d42355 100644
--- a/ecomp-c/ec.c
+++ b/ecomp-c/ec.c
@@ -692,7 +692,7 @@ typedef struct Scope {
int label_no;
struct Symbol *symbol;
struct Scope *parent;
- int size_locals;
+ int nof_symbols;
} Scope;
static Scope *global_scope;
@@ -706,6 +706,7 @@ static Scope *create_scope( Scope *parent, char *name )
scope->symbol = NULL;
scope->parent = parent;
scope->label_no = 0;
+ scope->nof_symbols = 0;
return scope;
}
@@ -805,6 +806,7 @@ static Symbol *insert_symbol( Scope *scope, char *name, SymbolClass class )
sym->intarr_value = NULL;
sym->label = NULL;
scope->symbol = sym;
+ scope->nof_symbols++;
return sym;
}
@@ -1541,6 +1543,22 @@ static void parseWhileStatement( Scope *scope )
free( jump_label1 );
}
+static void parseParameterList( Scope *scope )
+{
+ ExpressionNode *node;
+
+ Expect( S_lparen );
+ do {
+ node = parseExpression( scope );
+ if( sym == S_comma ) {
+ sym = getSym( );
+ }
+ } while( sym != S_rparen );
+ Expect( S_rparen );
+
+ (void)node;
+}
+
static void parseStatement( Scope *scope )
{
Symbol *symbol;
@@ -1558,6 +1576,9 @@ static void parseStatement( Scope *scope )
Abort( "Unknown indentifier '%s'", ident );
}
if( symbol->class == SYMBOL_CLASS_PROCEDURE_TYPE ) {
+ if( sym == S_lparen ) {
+ parseParameterList( scope );
+ }
Emit( "call %s\n", symbol->label );
} else {
parseAssignment( scope );
@@ -1990,10 +2011,42 @@ static void parseProcedureDeclarationBlock( Scope *scope )
}
}
-static void parseProcedureBlock( Scope *scope )
+static void parseParameterDeclaration( Scope *scope )
+{
+ Symbol *symbol;
+
+ Expect( S_ident );
+ symbol = insert_symbol( scope, ident, SYMBOL_CLASS_VARIABLE );
+
+ /* TODO: allocate size for parameters on stack, make sure they
+ * are allocated on the other side of the stack
+ */
+
+ Expect( S_colon );
+
+ symbol->type = parseType( scope );
+}
+
+static void parseParameterDeclarationList( Scope *scope )
+{
+ Expect( S_lparen );
+ do {
+ if( sym == S_ident ) {
+ parseParameterDeclaration( scope );
+ if( sym == S_comma ) {
+ sym = getSym( );
+ }
+ }
+ } while( sym != S_rparen );
+ Expect( S_rparen );
+}
+
+static void parseProcedureDeclaration( Scope *scope )
{
char *procedure_label;
Symbol *symbol;
+ int size_locals;
+ int size_params;
Expect( S_procedure );
Expect( S_ident );
@@ -2008,11 +2061,45 @@ static void parseProcedureBlock( Scope *scope )
/* TODO: check, if parameter lists and return values match */
}
- Expect( S_semicolon );
+ /* local scope holding all local defitions */
+ symbol->scope = create_scope( scope, symbol->name );
+ if( sym == S_semicolon ) {
+ /* no parameters */
+ sym = getSym( );
+ size_params = 0;
+ } else if( sym == S_lparen ) {
+
+ Symbol *param;
+ int offset;
+
+ parseParameterDeclarationList( symbol->scope );
+ if( sym == S_semicolon ) {
+ /* forward declaration */
+ sym = getSym( );
+ }
+
+ param = symbol->scope->symbol;
+
+ size_params = 0;
+ offset = 0;
+ while( param != NULL ) {
+ if( param->class == SYMBOL_CLASS_VARIABLE ) {
+ int size = get_size( param );
+ size_params += size;
+ param->offset = offset - size;
+ Emit( "; param %s, offset: %d, size: %d\n",
+ param->name, param->offset, size );
+ offset -= size;
+ }
+ param = param->next;
+ }
+ }
+
+ /* procedure body */
if( sym == S_const || sym == S_var || sym == S_begin ) {
- Symbol *sym;
+ Symbol *local, *param_or_local;
int offset;
Emit( "; PROC %s\n", symbol->name );
@@ -2023,9 +2110,6 @@ static void parseProcedureBlock( Scope *scope )
Emit( "push ebp\n" );
Emit( "push esp\n" );
Emit( "pop ebp\n" );
-
- /* local scope holding all local defitions */
- symbol->scope = create_scope( scope, symbol->name );
/* TODO: parse parameters, assign parameter values to
* local variables (when passed by value) or set
@@ -2034,66 +2118,66 @@ static void parseProcedureBlock( Scope *scope )
parseProcedureDeclarationBlock( symbol->scope );
/* compute sizes of all locals */
+ size_locals = 0;
offset = 0;
- scope->size_locals = 0;
- sym = symbol->scope->symbol;
- while( sym != NULL ) {
- if( sym->class == SYMBOL_CLASS_VARIABLE ) {
- int size = get_size( sym );
- scope->size_locals += size;
- sym->offset = offset + size;
+ local = symbol->scope->symbol;
+ while( local != NULL ) {
+ if( local->class == SYMBOL_CLASS_VARIABLE && local->offset == 0 ) {
+ int size = get_size( local );
+ size_locals += size;
+ local->offset = offset + size;
Emit( "; local %s, offset: %d, size: %d\n",
- sym->name, sym->offset, size );
+ local->name, local->offset, size );
offset += size;
}
- sym = sym->next;
+ local = local->next;
}
- /* reserve space on stack */
- if( scope->size_locals > 0 ) {
- Emit( "mov eax, %d\n", scope->size_locals );
+ /* reserve space on stack for locals */
+ if( size_locals > 0 ) {
+ Emit( "mov eax, %d\n", size_locals );
Emit( "sub esp, eax\n" );
}
/* initialize local variables (sort of reserve_initialize_local)
* at runtime (every time the stack is created for that procedure) */
- sym = symbol->scope->symbol;
- while( sym != NULL ) {
- if( sym->class == SYMBOL_CLASS_VARIABLE ) {
+ param_or_local = symbol->scope->symbol;
+ while( param_or_local != NULL ) {
+ if( param_or_local->class == SYMBOL_CLASS_VARIABLE ) {
/* TODO: use type here! */
- int size = get_size( sym );
- if( sym->type == integer_type || sym->type == boolean_type ) {
+ int size = get_size( param_or_local );
+ if( param_or_local->type == integer_type || param_or_local->type == boolean_type ) {
switch( size ) {
case 4:
/* TODO: cleanup local global variable access */
Emit( "push ebp\n" );
Emit( "pop ebx\n" );
- Emit( "mov eax, %d\n", sym->offset );
+ Emit( "mov eax, %d\n", param_or_local->offset );
Emit( "sub ebx, eax\n" );
- Emit( "mov eax, %d\n", sym->integer_value );
+ Emit( "mov eax, %d\n", param_or_local->integer_value );
Emit( "mov [ebx], eax\n" );
break;
case 1:
/* TODO: cleanup local global variable access */
Emit( "push ebp\n" );
Emit( "pop ebx\n" );
- Emit( "mov eax, %d\n", sym->offset );
+ Emit( "mov eax, %d\n", param_or_local->offset );
Emit( "sub ebx, eax\n" );
- Emit( "mov eax, %d\n", sym->boolean_value );
+ Emit( "mov eax, %d\n", param_or_local->boolean_value );
Emit( "mov [ebx], al\n" );
break;
default:
- Abort( "Unhandled case when initializing local variable '%s' of primitive type on stack", sym->name );
+ Abort( "Unhandled case when initializing local variable '%s' of primitive type on stack", param_or_local->name );
}
- } else if( sym->type->class == SYMBOL_CLASS_ARRAY_TYPE ) {
+ } else if( param_or_local->type->class == SYMBOL_CLASS_ARRAY_TYPE ) {
/* TODO: we would need an internal memset here
* memset( ebp + offset, get_size, 0 )
*/
} else {
- Abort( "Unhandled case when initializing local variable '%s' of complex type on stack", sym->name );
+ Abort( "Unhandled case when initializing local variable '%s' of complex type on stack", param_or_local->name );
}
}
- sym = sym->next;
+ param_or_local = param_or_local->next;
}
/* TODO: allocate space on stack for local variables (and
@@ -2103,19 +2187,25 @@ static void parseProcedureBlock( Scope *scope )
parseStatementBlock( symbol->scope );
- /* discard locals, reset base pointer */
-
- if( scope->size_locals > 0 ) {
- Emit( "mov eax, %d\n", scope->size_locals );
+ /* discard locals, discard params, reset base pointer */
+ if( size_locals + size_params > 0 ) {
+ Emit( "mov eax, %d\n", size_locals + size_params );
Emit( "add esp, eax\n" );
}
- free_scope( symbol->scope );
-
Emit( "pop ebp\n" );
Emit( "ret\n" );
}
+
+ free_scope( symbol->scope );
+}
+
+static void parseProcedureBlock( Scope *scope )
+{
+ while( sym == S_procedure ) {
+ parseProcedureDeclaration( scope );
+ }
}
static void parseDeclarationBlock( Scope *scope )
@@ -2126,10 +2216,10 @@ static void parseDeclarationBlock( Scope *scope )
if( sym == S_var ) {
parseVariableBlock( scope );
}
- while( sym == S_procedure ) {
+ if( sym == S_procedure ) {
parseProcedureBlock( scope );
}
-}
+}
static void parseModule( Scope *scope )
{