summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-09-18 20:48:13 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-09-18 20:48:13 +0200
commit6c6fe33b224dc3342d8d8fc5fc2d27777eb55b89 (patch)
tree727a88701e4ddeb743cfc458fbc1d2cc29589755
parent0eb3f28ec1faf8dc35d2f47fd982838af4d89d77 (diff)
downloadcompilertests-6c6fe33b224dc3342d8d8fc5fc2d27777eb55b89.tar.gz
compilertests-6c6fe33b224dc3342d8d8fc5fc2d27777eb55b89.tar.bz2
some work on functions
-rw-r--r--ecomp-c/ec.c112
-rw-r--r--ecomp-c/minie.ebnf9
-rw-r--r--ecomp-c/test1.e29
3 files changed, 120 insertions, 30 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 );
}
diff --git a/ecomp-c/minie.ebnf b/ecomp-c/minie.ebnf
index be68ba8..2bf9708 100644
--- a/ecomp-c/minie.ebnf
+++ b/ecomp-c/minie.ebnf
@@ -9,7 +9,7 @@ Character = "'" Digit | Letter | Special | "'" .
String = """" { Character } """" .
# parser
-Factor = Number | Character | String | Identifier [ "[" Expression "]" ] | "(" Expression ")" | "not" Factor .
+Factor = Number | Character | String | Identifier [ "[" Expression "]" | ParameterList ] | "(" Expression ")" | "not" Factor .
Term = Factor { ( "*" | "/" | "mod" | "and" ) Factor } .
SimpleExpression = Term { ( "+" | "-" | "or" ) Term } .
RelationalOperator = "=" | "<>" | "<" | ">" | "<=" | ">=" .
@@ -21,7 +21,6 @@ ParameterList = "(" Expression { "," Expression } ")" .
ProcedureCall = Identifier [ ParameterList ] .
Statement = Assignment | IfStatement | WhileStatement | ProcedureCall .
StatementSequence = Statement { ";" Statement } .
-StatementBlock = "begin" StatementSequence "end" .
SimpleType = Identifier .
ArrayType = "array" [ ConstExpression ] "of" Type .
Type = SimpleType | ArrayType .
@@ -31,9 +30,9 @@ ConstBlock = "const" { ConstDeclaration ";" } .
VariableDeclaration = Identifier { "," Identifier } ":" Type [ ":=" ConstExpression ] .
VariableBlock = "var" { VariableDeclaration ";" } .
ParameterDeclaration = Identifier ":" Type .
-ParamaterDeclarationList = "(" ParameterDeclaration { "," ParameterDeclaration } ")" .
-ProcedureDeclaration = "procedure" Identifier [ ParamaterDeclarationList ] ";" ProcedureDeclarationBlock StatementBlock .
+ParamaterDeclarationList = "(" ParameterDeclaration { "," ParameterDeclaration } ")" [ ":" Type ] .
+ProcedureDeclaration = [ "procedure" | "function" ] Identifier [ ParamaterDeclarationList ] ";" ProcedureDeclarationBlock "begin" StatementSequence [ "return" Type ] "end" .
ProcedureDeclarationBlock = [ ConstBlock ] [ VariableBlock ] .
ProcedureBlock = { ProcedureDeclaration } .
DeclarationBlock = [ ConstBlock ] [ VariableBlock ] [ ProcedureBlock ] .
-Module = "module" Identifier ";" DeclarationBlock StatementBlock .
+Module = "module" Identifier ";" DeclarationBlock "begin" StatementSequence "end" .
diff --git a/ecomp-c/test1.e b/ecomp-c/test1.e
index 80d9586..9300793 100644
--- a/ecomp-c/test1.e
+++ b/ecomp-c/test1.e
@@ -32,7 +32,7 @@ var
s2 : array 10 of character := "hello";
a1 : array 10 of integer;
-procedure B( n : integer, m : integer );
+procedure B( n : integer, m : integer, f : boolean );
procedure A;
const
@@ -44,16 +44,28 @@ var
begin
a1[5] := 43;
s[0] := 'L';
- B( a1[5], 7 );
+ B( a1[5], 7, true );
end
-procedure B( n : integer, m : integer );
+procedure B( n : integer, m : integer, f : boolean );
var
x : integer;
begin
- x := n - m;
- a1[4] := x;
+ if f do
+ x := n - m;
+ a1[4] := x;
+ end
+end
+
+function iszero( c : character ) : boolean;
+var
+ res : boolean := false;
+begin
+ if c = '0' do
+ res := true
+ end
+ return res;
end
begin
@@ -98,5 +110,10 @@ begin
a1[3] := 42;
s2[a1[2]] := 'Z';
A;
- B( 2, 1 );
+ B( 2, 1, false );
+ if iszero( '0' ) do
+ i := 1
+ else
+ i := 2
+ end
end