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.c112
1 files changed, 93 insertions, 19 deletions
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c
index 1fc0dd6..5ec97cc 100644
--- a/ecomp-c/ec.c
+++ b/ecomp-c/ec.c
@@ -17,7 +17,7 @@ enum {
};
static int DEBUG_GETCHAR = 0;
-static int DEBUG_SCANNER = 0;
+static int DEBUG_SCANNER = 1;
typedef enum {
BINARY_FORMAT_EMUL = 0,
@@ -45,6 +45,8 @@ typedef enum {
S_else,
S_while,
S_procedure,
+ S_function,
+ S_return,
S_div,
S_mod,
S_not,
@@ -88,6 +90,8 @@ static char *symname[S_eof+1] = {
"else",
"while",
"procedure",
+ "function",
+ "return",
"div",
"mod",
"not",
@@ -405,6 +409,14 @@ static S_Symbol getSym( void )
s = S_ident;
}
break;
+ case 'f':
+ identifier( );
+ if( strcmp( ident, "function" ) == 0 ) {
+ s = S_function;
+ } else {
+ s = S_ident;
+ }
+ break;
case 'i':
identifier( );
if( strcmp( ident, "if" ) == 0 ) {
@@ -449,6 +461,14 @@ static S_Symbol getSym( void )
s = S_ident;
}
break;
+ case 'r':
+ identifier( );
+ if( strcmp( ident, "return" ) == 0 ) {
+ s = S_return;
+ } else {
+ s = S_ident;
+ }
+ break;
case 'v':
identifier( );
if( strcmp( ident, "var" ) == 0 ) {
@@ -465,14 +485,12 @@ static S_Symbol getSym( void )
s = S_ident;
}
break;
- case 'f':
case 'g':
case 'h':
case 'j':
case 'k':
case 'l':
case 'q':
- case 'r':
case 's':
case 't':
case 'u':
@@ -678,10 +696,12 @@ typedef struct Symbol {
int offset;
/* array type */
int dim;
- /* procedure type */
+ /* procedure/function type */
char *label;
struct Scope *scope;
struct Symbol *param;
+ int is_func;
+ struct Symbol *return_type;
} Symbol;
static Symbol *integer_type;
@@ -805,6 +825,8 @@ static Symbol *create_symbol( char *name, SymbolClass class )
symbol->type = NULL;
symbol->label = NULL;
symbol->param = NULL;
+ symbol->is_func = 0;
+ symbol->return_type = NULL;
return symbol;
}
@@ -1235,6 +1257,7 @@ static void emit_expression_code( ExpressionNode *node, Scope *scope )
}
static ExpressionNode *parseExpression( Scope *scope );
+static void parseParameterList( Scope *scope, ExpressionNodeList *list );
static ExpressionNode *parseFactor( Scope *scope )
{
@@ -1292,6 +1315,16 @@ static ExpressionNode *parseFactor( Scope *scope )
node->symbol = symbol;
node->actual_type = symbol->type;
}
+ } else if( symbol->class == SYMBOL_CLASS_PROCEDURE_TYPE ) {
+ sym = getSym( );
+ if( !symbol->is_func ) {
+ Abort( "Expecting function and not procedure" );
+ }
+ /* TODO: parse parameters as in a procedure call
+ parseProcedureCall
+ then add result into expression, problem here is
+ we generate code directly in parseProcedureCall and
+ not an ADT before, must refactor */
} else {
Abort( "'%s' is the name for a type and not a constant or variable as expected", ident );
}
@@ -1634,7 +1667,7 @@ static void parseProcedureCall( Scope *scope )
}
nof_actual_params = 0;
- if( sym == S_lparen ) {
+ if( sym == S_lparen ) {
parseParameterList( scope, &list );
node = list.head;
@@ -1726,20 +1759,13 @@ static void parseStatementSequence( Scope *scope )
}
while( sym == S_semicolon ) {
sym = getSym( );
- if( sym == S_end || sym == S_else ) {
+ if( sym == S_end || sym == S_else || sym == S_return ) {
return;
}
parseStatement( scope );
}
}
-static void parseStatementBlock( Scope *scope )
-{
- Expect( S_begin );
- parseStatementSequence( scope );
- Expect( S_end );
-}
-
/* TODO: implement simple expression and later complex expression */
static ExpressionNode *parseConstExpression( Scope *scope )
{
@@ -2171,10 +2197,11 @@ static void parseProcedureDeclaration( Scope *scope )
Symbol *symbol;
int size_locals;
int size_params = 0;
-
- Expect( S_procedure );
+ S_Symbol proc_sym = sym;
+
+ sym = getSym( );
if( sym != S_ident ) {
- Abort( "Expecting name of a procedure after 'procedure'" );
+ Abort( "Expecting name of a procedure or function after '%s'", symname[proc_sym] );
}
symbol = get_symbol( scope, ident );
@@ -2183,6 +2210,11 @@ static void parseProcedureDeclaration( Scope *scope )
procedure_label = get_scoped_label( scope, ident );
symbol->label = AllocateAndCopyStr( procedure_label );
free( procedure_label );
+ if( proc_sym == S_procedure ) {
+ symbol->is_func = 0;
+ } else if( proc_sym == S_function ) {
+ symbol->is_func = 1;
+ }
} else if( symbol->class == SYMBOL_CLASS_PROCEDURE_TYPE ) {
/* TODO: check, if parameter lists and return values match */
}
@@ -2201,6 +2233,16 @@ static void parseProcedureDeclaration( Scope *scope )
int offset;
parseParameterDeclarationList( symbol->scope );
+
+ if( sym == S_colon ) {
+ if( symbol->is_func ) {
+ symbol->return_type = parseType( scope );
+ sym = getSym( );
+ } else {
+ Abort( "A procedure cannot have a return type" );
+ }
+ }
+
if( sym == S_semicolon ) {
/* forward declaration */
sym = getSym( );
@@ -2216,6 +2258,10 @@ static void parseProcedureDeclaration( Scope *scope )
while( param != NULL ) {
if( param->class == SYMBOL_CLASS_VARIABLE ) {
int size = get_size( param );
+ if( size < 4 ) {
+ /* parameters on stack are always 4 bytes */
+ size = 4;
+ }
size_params += size;
param->offset = offset - size;
Emit( "; param %s, offset: %d, size: %d\n",
@@ -2269,10 +2315,20 @@ static void parseProcedureDeclaration( Scope *scope )
}
param = param->next;
}
+ }
+ } else if( sym == S_colon ) {
+ if( symbol->is_func ) {
+ symbol->return_type = parseType( scope );
+ } else {
+ Abort( "A procedure cannot have a return type" );
}
} else {
Abort( "Semicolon expected" );
}
+
+ if( symbol->is_func && symbol->return_type == NULL ) {
+ Abort( "A function must have a return type" );
+ }
/* procedure body */
if( sym == S_const || sym == S_var || sym == S_begin ) {
@@ -2363,7 +2419,23 @@ static void parseProcedureDeclaration( Scope *scope )
/* TODO: assign symbols to relative addresses (base pointer) */
/* TODO: initialize local variables */
- parseStatementBlock( symbol->scope );
+ Expect( S_begin );
+ parseStatementSequence( symbol->scope );
+ if( symbol->is_func ) {
+ ExpressionNode *node = NULL;
+ Expect( S_return );
+ node = parseExpression( symbol->scope );
+ if( sym == S_semicolon ) {
+ sym = getSym( );
+ }
+ (void)node;
+ /* TODO: add parsing return with local here, emit code
+ * for returning function value (what convention are
+ * we going to apply? stack? register?
+ */
+ }
+ Expect( S_end );
+
/* discard locals, restore base pointer, discard params */
if( size_locals > 0 ) {
@@ -2387,7 +2459,7 @@ static void parseProcedureDeclaration( Scope *scope )
static void parseProcedureBlock( Scope *scope )
{
- while( sym == S_procedure ) {
+ while( sym == S_procedure || sym == S_function ) {
parseProcedureDeclaration( scope );
}
}
@@ -2423,7 +2495,9 @@ static void parseModule( Scope *scope )
parseDeclarationBlock( scope );
Emit( "%s:\n", entry_label );
- parseStatementBlock( scope );
+ Expect( S_begin );
+ parseStatementSequence( scope );
+ Expect( S_end );
free( entry_label );
}