summaryrefslogtreecommitdiff
path: root/minie
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2019-03-09 21:39:05 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2019-03-09 21:39:05 +0100
commit27e108db73c9c8d89fc5d15df73396abd7fa6a50 (patch)
tree7330b8ef14ff1e1753b4c3c0c260353a0db9e319 /minie
parent0abefa3cdee7b821c49c2eab28b2c7b2b34a88e7 (diff)
downloadcompilertests-27e108db73c9c8d89fc5d15df73396abd7fa6a50.tar.gz
compilertests-27e108db73c9c8d89fc5d15df73396abd7fa6a50.tar.bz2
introducing better symbol table.. work in progress
Diffstat (limited to 'minie')
-rw-r--r--minie/TODOS35
-rw-r--r--minie/e2c.c514
2 files changed, 362 insertions, 187 deletions
diff --git a/minie/TODOS b/minie/TODOS
index edae44a..d06e971 100644
--- a/minie/TODOS
+++ b/minie/TODOS
@@ -244,6 +244,41 @@ point to types.
This also means we usually get a global namespace this way, so a variable
'a', a type 'a' and a procedure 'a' cannot co-exist.
+procdure types
+
+type
+ Func = procdure( x : integer, y : integer ) : char;
+var
+ f : func;
+begin
+ f := nil;
+
+this is a pointer to a function, so is 'pointer to procdure' better as
+in a pointer to a procedure implementing that inteface? also, the 'x'
+and 'y' don't really have a semantic meaning in the type declaration
+as I can assign also a matching function 'f2':
+
+procdure f2( a : integer, b : integer ) : char;
+begin
+ ...
+end
+
+f := f2;
+
+nil should most likely end in an exception. but this means we have to
+check a special condition on every function call.
+
+e2c or C-transpiler questions
+
+Symbol for scanner and Symbol for symbol table clash, we should use modules
+and different names. And why are we insisting on having no preprocessor
+and only one e2c.c?
+
+set/bitset/enum
+
+set: mutually exclusive
+bitset: usable as switches, flags
+
links
-----
diff --git a/minie/e2c.c b/minie/e2c.c
index d20098b..920c130 100644
--- a/minie/e2c.c
+++ b/minie/e2c.c
@@ -12,9 +12,8 @@ enum {
MAX_ERRMSG_LEN = 64,
MAX_STRING_LEN = 64,
MAX_SYMBOLS = 64,
- MAX_RECORD_MEMBERS = 8,
- MAX_PARAMETERS = 4,
- MAX_TYPE_DATA_SIZE = 2048
+ MAX_RECORD_MEMBERS = 4,
+ MAX_PARAMETERS = 4
};
/* scanner */
@@ -70,7 +69,7 @@ typedef enum {
S_more,
S_not_equals,
S_eof
-} Symbol;
+} Scanner_Symbol;
char *symname[S_eof+1] = {
"char",
@@ -118,7 +117,7 @@ char *symname[S_eof+1] = {
"eof"
};
-static Symbol sym;
+static Scanner_Symbol sym;
static void Err( char *s, va_list args )
{
@@ -279,7 +278,7 @@ cont:
look = getChar( );
}
-static Symbol getSym( void )
+static Scanner_Symbol getSym( void )
{
next:
skipWhite( );
@@ -512,82 +511,94 @@ next:
/* symbol table */
typedef enum {
- TYPE_UNKNOWN,
- TYPE_INTEGER,
- TYPE_BOOLEAN,
- TYPE_BYTE,
- TYPE_CHAR,
+ SYMBOL_TYPE = 1,
+ SYMBOL_VARIABLE = 2,
+ SYMBOL_CONSTANT = 4,
+ SYMBOL_PROCEDURE = 8,
+ SYMBOL_MODULE = 16
+} SymbolKind;
+
+static const SymbolKind SYMBOL_ANY = SYMBOL_TYPE | SYMBOL_VARIABLE | SYMBOL_CONSTANT | SYMBOL_PROCEDURE | SYMBOL_MODULE;
+
+typedef enum {
+ TYPE_BASIC,
TYPE_ARRAY,
TYPE_RECORD,
- TYPE_FUNCTION,
- TYPE_CONSTANT,
- TYPE_NONE
-} BasicType;
+ TYPE_PROCEDURE,
+ TYPE_NONE,
+ TYPE_ANY
+} TypeKind;
-static BasicType strToBasicType( char *name )
-{
- if( strcmp( name, "integer" ) == 0 ) {
- return TYPE_INTEGER;
- } else if( strcmp( name, "boolean" ) == 0 ) {
- return TYPE_BOOLEAN;
- } else if( strcmp( name, "byte" ) == 0 ) {
- return TYPE_BYTE;
- } else if( strcmp( name, "char" ) == 0 ) {
- return TYPE_CHAR;
- } else {
- Abort( "Unknown type '%s'", name );
- }
- return TYPE_UNKNOWN;
-}
+typedef struct Symbol Symbol;
typedef struct Type Type;
typedef struct ArrayType {
- char data[MAX_TYPE_DATA_SIZE];
Type *type;
int len;
} ArrayType;
typedef struct RecordType {
- char data[MAX_TYPE_DATA_SIZE*MAX_RECORD_MEMBERS];
- struct Type *type[MAX_RECORD_MEMBERS];
+ Type *type[MAX_RECORD_MEMBERS];
int len;
} RecordType;
-typedef struct FunctionType {
- char data[MAX_TYPE_DATA_SIZE*MAX_PARAMETERS];
- struct Type *params[MAX_PARAMETERS];
- struct Type *return_value;
+typedef struct Procedure {
+ Type *params[MAX_PARAMETERS];
+ Type *return_value;
int len;
- int internal;
-} FunctionType;
+ /* TODO: later origin, module
+ int internal;*/
+} Procedure;
+
+typedef enum BasicType {
+ TYPE_INTEGER,
+ TYPE_BOOLEAN,
+ TYPE_CHAR,
+ TYPE_BYTE
+} BasicType;
+
+struct Type {
+ TypeKind kind;
+ union {
+ BasicType basic;
+ ArrayType array;
+ RecordType *record;
+ Procedure *procedure;
+ } type;
+};
+
+typedef struct Variable {
+ Type *type;
+} Variable;
-typedef struct ConstantType {
- BasicType type;
+/* TODO: constants are only possible to define from basic types currently */
+typedef struct Constant {
+ Type *type;
union {
int boolean;
int integer;
- char byte;
char character;
+ char byte;
} value;
-} ConstantType;
+} Constant;
-struct Type {
- BasicType type;
+struct Symbol {
+ SymbolKind kind;
char name[MAX_IDENT_LEN];
union {
- ArrayType array;
- RecordType record;
- FunctionType function;
- ConstantType constant;
- } details;
+ Type type;
+ Variable variable;
+ Constant constant;
+ Procedure procedure;
+ } symbol;
};
typedef struct SymbolTable SymbolTable;
struct SymbolTable {
int nof_symbols;
- Type symbols[MAX_SYMBOLS];
+ Symbol symbols[MAX_SYMBOLS];
SymbolTable *parent;
};
@@ -600,39 +611,67 @@ static void init_symboltable( SymbolTable *table, SymbolTable *parent )
table->parent = parent;
}
-static void insert_symbol( SymbolTable *table, Type type, char *name )
+static Symbol *insert_symbol( SymbolTable *table, char *name )
{
if( table->nof_symbols >= MAX_SYMBOLS ) {
Abort( "Symbol table exhausted, increase MAX_SYMBOLS and recompile e2c" );
}
-
- table->symbols[table->nof_symbols] = type;
+
strncpy( table->symbols[table->nof_symbols].name, name, MAX_IDENT_LEN );
+ table->symbols[table->nof_symbols].name[MAX_IDENT_LEN-1] = '\0';
table->nof_symbols++;
+
+ return &table->symbols[table->nof_symbols-1];
}
-static Type get_symbol_type( SymbolTable *table, char *name )
+/* TODO: this is inefficient and should be a search tree of sorts */
+static Symbol *get_symbol( SymbolTable *table, char *name, SymbolKind kind )
{
int i;
/* search in table of currect scope */
for( i = 0; i < table->nof_symbols; i++ ) {
- if( strcmp( table->symbols[i].name, name ) == 0 ) {
- return table->symbols[i];
+ if( strcmp( table->symbols[i].name, name ) == 0 && ( table->symbols[i].kind == kind ) ) {
+ return &table->symbols[i];
}
}
/* traverse stack of parent symbol tables */
if( table->parent != NULL ) {
- return get_symbol_type( table->parent, name );
+ return get_symbol( table->parent, name, kind );
+ }
+
+ return NULL;
+}
+
+static Type *get_type_symbol( SymbolTable *table, char *name )
+{
+ Symbol *symbol = get_symbol( table, name, SYMBOL_TYPE );
+
+ if( symbol->kind != SYMBOL_TYPE ) {
+ Abort( "Expected name of a type for '%s'", name );
}
- Abort( "Unknown symbol '%s'", name );
+ return &symbol->symbol.type;
}
+#if 0
+/* done with symbol table now */
+static Type *strToBasicType( SymbolTable *table, char *name )
+{
+ Type *type = get_type_symbol( table, name );
+
+ if( type == NULL || type->kind != TYPE_BASIC ) {
+ Abort( "'%s' is not a basic type as expected", name );
+ }
+
+ return type;
+}
+#endif
+
static char *basicTypeToCType( BasicType type )
-{
+{
switch( type ) {
case TYPE_INTEGER:
return "signed int";
@@ -653,10 +692,18 @@ static char *typeToCType( Type *type )
{
static char s[MAX_IDENT_LEN];
- if( type->type == TYPE_ARRAY ) {
- sprintf( s, "%s*", basicTypeToCType( type->details.array.type->type ) );
+ if( type->kind == TYPE_ARRAY ) {
+ Type *subType = type->type.array.type;
+ /* TODO: must be a basic type for now */
+ if( subType->kind == TYPE_BASIC ) {
+ sprintf( s, "%s*", basicTypeToCType( subType->type.basic ) );
+ } else {
+ Abort( "Arrays are currently only possible for basic types" );
+ }
+ } else if( type->kind == TYPE_BASIC ) {
+ sprintf( s, "%s ", basicTypeToCType( type->type.basic ) );
} else {
- sprintf( s, "%s ", basicTypeToCType( type->type ) );
+ Abort( "Unknown complex type to C mapping" );
}
return s;
@@ -666,11 +713,11 @@ static char *typeToCType( Type *type )
static int length( char *name )
{
- Type type;
+ Type *type;
- type = get_symbol_type( current_scope, name );
- if( type.type == TYPE_ARRAY ) {
- return type.details.array.len;
+ type = get_type_symbol( current_scope, name );
+ if( type != NULL && type->kind == TYPE_ARRAY ) {
+ return type->type.array.len;
} else {
Abort( "length called on non-array variable '%s'", name );
}
@@ -680,10 +727,9 @@ static int length( char *name )
static char moduleName[MAX_IDENT_LEN+1];
static char varName[MAX_IDENT_LEN+1];
-static Type lastType;
static char procName[MAX_IDENT_LEN+1];
-static void Expect( Symbol expect )
+static void Expect( Scanner_Symbol expect )
{
if( sym == expect ) {
sym = getSym( );
@@ -711,61 +757,102 @@ static void emit( char *s, ... )
fflush( stdout );
}
-static void register_internal_functions( void )
+static void register_internal_types( void )
{
- Type type;
+ Symbol *symbol;
- /* register compiler-internal functions */
- type.type = TYPE_FUNCTION;
- type.details.function.len = 1;
- type.details.function.params[0] = (Type *)type.details.function.data;
- type.details.function.params[0]->type = TYPE_ARRAY;
- type.details.function.return_value = (Type *)( type.details.function.data + sizeof( Type ) );
- type.details.function.return_value->type = TYPE_INTEGER;
- type.details.function.internal = 1;
- insert_symbol( &symbols, type, "length" );
+ /* basic types */
+ symbol = insert_symbol( &symbols, "integer" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_BASIC;
+
+ symbol = insert_symbol( &symbols, "boolean" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_BASIC;
+
+ symbol = insert_symbol( &symbols, "char" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_BASIC;
+
+ symbol = insert_symbol( &symbols, "byte" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_BASIC;
- /* constructor for char type */
- type.type = TYPE_FUNCTION;
- type.details.function.len = 1;
- type.details.function.params[0] = (Type *)type.details.function.data;
- type.details.function.params[0]->type = TYPE_INTEGER;
- type.details.function.return_value = (Type *)( type.details.function.data + sizeof( Type ) );
- type.details.function.return_value->type = TYPE_CHAR;
- type.details.function.internal = 1;
- insert_symbol( &symbols, type, "char" );
-
- /* TODO: register functions in module system, should be outside in the stage-1 compiler */
+ /* the any type (for the type in the array for length) */
+ symbol = insert_symbol( &symbols, "__any" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_ANY;
+
+ /* the null type (for procedures not returning a type) */
+ symbol = insert_symbol( &symbols, "__void" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_NONE;
+
+ /* array of any type (for length) */
+ symbol = insert_symbol( &symbols, "__gen_array_of_any" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_ARRAY;
+ symbol->symbol.type.type.array.len = 0;
+ symbol->symbol.type.type.array.type = get_type_symbol( &symbols, "__any" );
- type.type = TYPE_FUNCTION;
- type.details.function.len = 0;
- type.details.function.return_value = (Type *)type.details.function.data;
- type.details.function.return_value->type = TYPE_CHAR;
- type.details.function.internal = 1;
- insert_symbol( &symbols, type, "system.readchar" );
-
- type.type = TYPE_FUNCTION;
- type.details.function.len = 1;
- type.details.function.params[0] = (Type *)type.details.function.data;
- type.details.function.params[0]->type = TYPE_ARRAY;
- type.details.function.return_value = (Type *)type.details.function.data;
- type.details.function.return_value->type = TYPE_NONE;
- type.details.function.internal = 1;
- insert_symbol( &symbols, type, "system.readline" );
+ /* array of any size of char (string, for system.readline) */
+ symbol = insert_symbol( &symbols, "__gen_array_of_char" );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_ARRAY;
+ symbol->symbol.type.type.array.len = 0;
+ symbol->symbol.type.type.array.type = get_type_symbol( &symbols, "char" );
}
static void register_internal_constants( void )
{
- Type type;
+ Symbol *symbol;
- type.type = TYPE_CONSTANT;
- type.details.constant.type = TYPE_BOOLEAN;
- type.details.constant.value.boolean = 1;
- insert_symbol( &symbols, type, "true" );
+ symbol = insert_symbol( &symbols, "true" );
+ symbol->kind = SYMBOL_CONSTANT;
+ symbol->symbol.constant.type = get_type_symbol( &symbols, "boolean" );
+ symbol->symbol.constant.value.boolean = 1;
+
+ symbol = insert_symbol( &symbols, "false" );
+ symbol->kind = SYMBOL_CONSTANT;
+ symbol->symbol.constant.type = get_type_symbol( &symbols, "boolean" );
+ symbol->symbol.constant.value.boolean = 0;
+}
+
+static void register_internal_functions( void )
+{
+ Symbol *symbol;
- type.details.constant.type = TYPE_BOOLEAN;
- type.details.constant.value.boolean = 0;
- insert_symbol( &symbols, type, "false" );
+ /* internal compiler functions, are always internal to the compiler as they need
+ * special treatment */
+
+ /* get length of any array */
+ symbol = insert_symbol( &symbols, "length" );
+ symbol->kind = SYMBOL_PROCEDURE;
+ symbol->symbol.procedure.return_value = get_type_symbol( &symbols, "integer" );
+ symbol->symbol.procedure.len = 1;
+ symbol->symbol.procedure.params[0] = get_type_symbol( &symbols, "__gen_array_of_any" );
+
+ /* constructor for char type (from type integer) */
+ symbol = insert_symbol( &symbols, "char" );
+ symbol->kind = SYMBOL_PROCEDURE;
+ symbol->symbol.procedure.return_value = get_type_symbol( &symbols, "char" );
+ symbol->symbol.procedure.len = 1;
+ symbol->symbol.procedure.params[0] = get_type_symbol( &symbols, "integer" );
+
+ /* TODO: register functions in module system, should be outside in the stage-1 compiler,
+ * should also add a system module symbol first and attach all procedures to it
+ * needs a rewrite of the qualifier matching code, so later..
+ */
+ symbol = insert_symbol( &symbols, "system.readchar" );
+ symbol->kind = SYMBOL_PROCEDURE;
+ symbol->symbol.procedure.return_value = get_type_symbol( &symbols, "char" );
+ symbol->symbol.procedure.len = 0;
+
+ symbol = insert_symbol( &symbols, "system.readline" );
+ symbol->kind = SYMBOL_PROCEDURE;
+ symbol->symbol.procedure.return_value = get_type_symbol( &symbols, "__void" );
+ symbol->symbol.procedure.len = 1;
+ symbol->symbol.procedure.params[0] = get_type_symbol( &symbols, "__gen_array_of_char" );
}
static void init( void )
@@ -799,9 +886,10 @@ static void prologue( void )
"}" );
init_symboltable( &symbols, NULL );
-
- register_internal_functions( );
+
+ register_internal_types( );
register_internal_constants( );
+ register_internal_functions( );
}
static void epilogue( void )
@@ -847,7 +935,7 @@ static void parameterList( void );
static void factor( void )
{
- Type type;
+ Symbol *symbol;
if( sym == S_plus ) {
sym = getSym( );
@@ -866,16 +954,31 @@ static void factor( void )
sym = getSym( );
} else if( sym == S_ident ) {
qualident( );
- type = get_symbol_type( current_scope, varName );
- if( type.type == TYPE_FUNCTION ) {
+ symbol = get_symbol( current_scope, varName, SYMBOL_ANY );
+ if( symbol->kind == SYMBOL_TYPE && symbol->symbol.type.kind == TYPE_PROCEDURE ) {
parameterList( );
- } else if( type.type == TYPE_CONSTANT ) {
- if( type.details.constant.type == TYPE_BOOLEAN || type.details.constant.type == TYPE_INTEGER ) {
- emit( "%d", type.details.constant.value );
+ } else if( symbol->kind == SYMBOL_CONSTANT ) {
+ if( symbol->symbol.constant.type->kind == TYPE_BASIC ) {
+ switch( symbol->symbol.constant.type->type.basic ) {
+ case TYPE_BOOLEAN:
+ emit( "%d", symbol->symbol.constant.value.boolean );
+ break;
+ case TYPE_INTEGER:
+ emit( "%d", symbol->symbol.constant.value.integer );
+ break;
+ case TYPE_CHAR:
+ emit( "%c", symbol->symbol.constant.value.character );
+ break;
+ case TYPE_BYTE:
+ emit( "%d", symbol->symbol.constant.value.byte );
+ break;
+ default:
+ Abort( "Unknown basic type constant '%s'", varName );
+ }
} else {
- Abort( "Unknown constant '%s'", varName );
+ Abort( "Unknown complex constant '%s'", varName );
}
- } else if( type.type == TYPE_ARRAY ) {
+ } else if( symbol->kind == SYMBOL_TYPE && symbol->symbol.type.kind == TYPE_ARRAY ) {
if( sym == S_lbracket ) {
sym = getSym( );
emit( "%s[", varName );
@@ -885,8 +988,10 @@ static void factor( void )
} else {
emit( "%s", varName );
}
- } else {
+ } else if( symbol->kind == SYMBOL_VARIABLE ) {
emit( "%s", varName );
+ } else {
+ Abort( "Unkown factor symbol '%s'", varName );
}
} else if( sym == S_lparen ) {
emit( "(" );
@@ -923,7 +1028,7 @@ static void simpleExpression( void )
}
}
-static int isRelationalOperator( Symbol sym )
+static int isRelationalOperator( Scanner_Symbol sym )
{
if( sym == S_less || sym == S_less_or_equals ||
sym == S_equals || sym == S_more ||
@@ -965,13 +1070,13 @@ static int selected_array;
static void selector( void )
{
- Type type;
+ Type *type;
selected_array = 0;
if( sym == S_lbracket ) {
Expect( S_lbracket );
- type = get_symbol_type( current_scope, varName );
- if( type.type != TYPE_ARRAY ) {
+ type = get_type_symbol( current_scope, varName );
+ if( type != NULL && type->kind != TYPE_ARRAY ) {
Abort( "Selecting element of non-array" );
}
selected_array = 1;
@@ -986,12 +1091,15 @@ static void selector( void )
static void assignment( void )
{
- Type type;
+ Type *type;
/* left hand side */
/* precondition: qualident has been already parsed outside */
selector( );
- type = get_symbol_type( current_scope, varName );
+ type = get_type_symbol( current_scope, varName );
+ if( type == NULL ) {
+ Abort( "Unknown type for variable '%s'", varName );
+ }
/* x := ( a+ b )- 3; -> x = (a+b)-3;
* s1 := s2; -> strncpy( s2, s1, length( s2 ) );
@@ -1003,7 +1111,8 @@ static void assignment( void )
* way without an AST in-between
*/
- if( type.type == TYPE_ARRAY && type.details.array.type->type == TYPE_CHAR ) {
+ if( type->kind != TYPE_ARRAY && type->type.array.type->kind == TYPE_BASIC
+ && type->type.array.type->type.basic == TYPE_CHAR ) {
emit( "strncpy( %s, ", varName );
} else {
if( selected_array ) {
@@ -1019,9 +1128,10 @@ static void assignment( void )
/* right hand side, any expression */
expression( );
- if( type.type == TYPE_ARRAY && type.details.array.type->type == TYPE_CHAR ) {
- emit( ", %d ); ", type.details.array.len );
- emit( "%s[%d-1] = '\\0'", varName, type.details.array.len );
+ if( type->kind != TYPE_ARRAY && type->type.array.type->kind == TYPE_BASIC
+ && type->type.array.type->type.basic == TYPE_CHAR ) {
+ emit( ", %d ); ", type->type.array.len );
+ emit( "%s[%d-1] = '\\0'", varName, type->type.array.len );
}
emitLn( ";" );
}
@@ -1198,13 +1308,15 @@ static void statement( void )
parameterList( );
emitLn( ";" );
} else {
- Type type = get_symbol_type( current_scope, varName );
- if( type.type == TYPE_FUNCTION ) {
+ Symbol *symbol = get_symbol( current_scope, varName, SYMBOL_ANY );
+ if( symbol->kind == SYMBOL_PROCEDURE ) {
/* procedure call without parameter */
/* TODO: check number of parameter and return value to be 0 */
emitLn( "%s( );", varName );
- } else {
+ } else if( symbol->kind == SYMBOL_VARIABLE ) {
assignment( );
+ } else {
+ Abort( "Expected variable for assignment or a procedure for a procedure call for '%s'", varName );
}
}
} else {
@@ -1233,31 +1345,26 @@ static void statementBlock( void )
Expect( S_end );
}
-static void type( void );
+static Type *doType( void );
-static void simpleType( void )
+static Type *simpleType( void )
{
- /* TODO: handle build-in types in init, register them in
- type table */
- if( strcmp( ident, "integer" ) == 0 ) {
- lastType.type = TYPE_INTEGER;
- sym = getSym( );
- } else if( strcmp( ident, "boolean" ) == 0 ) {
- lastType.type = TYPE_BOOLEAN;
- sym = getSym( );
- } else if( strcmp( ident, "char" ) == 0 ) {
- lastType.type = TYPE_CHAR;
+ Type *type;
+ type = get_type_symbol( current_scope, ident );
+ if( type != NULL && type->kind == TYPE_BASIC ) {
sym = getSym( );
- } else if( strcmp( ident, "byte" ) == 0 ) {
- lastType.type = TYPE_BYTE;
- sym = getSym( );
+ return type;
} else {
Abort( "Unknown type '%s'", ident );
}
}
-static void arrayType( void )
+static Type *arrayType( void )
{
+ char typeName[MAX_STRING_LEN];
+ Type *type;
+ Type *basicType;
+
sym = getSym( );
Expect( S_lbracket );
/* TODO: should be a const expression */
@@ -1270,24 +1377,31 @@ static void arrayType( void )
/* array size is in num */
if( sym == S_of ) {
sym = getSym( );
- type( );
- /* type is in ident */
- lastType.type = TYPE_ARRAY;
- lastType.details.array.type = (Type *)&lastType.details.array.data;
- lastType.details.array.type->type = strToBasicType( ident );
- lastType.details.array.len = num;
+ basicType = doType( );
+ /* TODO here: this is an anonymous type of an array of len and basic type */
+ sprintf( typeName, "__array_%d_of_%s", num, ident );
+ type = get_type_symbol( current_scope, typeName );
+ if( type == NULL ) {
+ Symbol *symbol = insert_symbol( current_scope, typeName );
+ symbol->kind = SYMBOL_TYPE;
+ symbol->symbol.type.kind = TYPE_ARRAY;
+ symbol->symbol.type.type.array.len = num;
+ symbol->symbol.type.type.array.type = basicType;
+ type = &symbol->symbol.type;
+ }
+ return type;
} else {
Abort( "of' expected in array definition" );
}
}
-static void type( void )
+static Type *doType( )
{
identifier( );
if( sym == S_ident ) {
- simpleType( );
+ return simpleType( );
} else if( sym == S_array ) {
- arrayType( );
+ return arrayType( );
}
}
static void constDeclaration( void )
@@ -1298,13 +1412,14 @@ static void constDeclaration( void )
Expect( S_equals );
/* TODO: ConstExpression requires an interpreter */
if( sym == S_number ) {
- Type type;
+ Symbol *symbol;
number( );
sym = getSym( );
- type.type = TYPE_CONSTANT;
- type.details.constant.type = TYPE_INTEGER;
- type.details.constant.value.integer = num;
- insert_symbol( current_scope, type, varName );
+ symbol = insert_symbol( &symbols, varName );
+ symbol->kind = SYMBOL_CONSTANT;
+ /* TODO: deduce type from value (byte/integer)? */
+ symbol->symbol.constant.type = get_type_symbol( &symbols, "integer" );
+ symbol->symbol.constant.value.integer = num;
} else {
Abort( "Supporting numeric constants only" );
}
@@ -1327,20 +1442,33 @@ static void constBlock( void )
static void variableDeclaration( void )
{
+ Type *type;
+ Symbol *symbol;
+
variableName( );
sym = getSym( );
Expect( S_colon );
- type( );
- insert_symbol( current_scope, lastType, varName );
- if( lastType.type == TYPE_ARRAY ) {
- /* TODO: this works for now, though it's not correct */
- emitLn( "static %s %s[%d];",
- basicTypeToCType( lastType.details.array.type->type ),
- varName, num );
+ type = doType( );
+ symbol = insert_symbol( current_scope, varName );
+ symbol->kind = SYMBOL_VARIABLE;
+ symbol->symbol.variable.type = type;
+ if( type->kind == TYPE_ARRAY ) {
+ if( type->type.array.type->kind == TYPE_BASIC ) {
+ /* TODO: this works for now, though it's not correct */
+ emitLn( "static %s %s[%d];",
+ basicTypeToCType( type->type.array.type->type.basic ),
+ varName, num );
+ } else {
+ Abort( "Declaring an array '%s' with no basic type is not supported", varName );
+ }
} else {
- emitLn( "static %s %s;",
- basicTypeToCType( lastType.type ),
- varName );
+ if( type->type.array.type->kind == TYPE_BASIC ) {
+ emitLn( "static %s %s;",
+ basicTypeToCType( type->type.array.type->type.basic ),
+ varName );
+ } else {
+ Abort( "User defined types not supported" );
+ }
}
}
@@ -1371,27 +1499,39 @@ static void procedureName( void )
static void procedureDeclaration( void )
{
char return_type[MAX_IDENT_LEN];
- Type funcType;
+ Symbol *symbol;
+ Type *funcType;
SymbolTable locals;
init_symboltable( &locals, current_scope );
-
- funcType.type = TYPE_FUNCTION;
- funcType.details.function.internal = 0;
- funcType.details.function.len = 0;
-
+
Expect( S_procedure );
procedureName( );
+
+ symbol = insert_symbol( &locals, procName );
+ symbol->kind = TYPE_PROCEDURE;
+ symbol->symbol.procedure.len = 0;
+
+#if 0
+ //~ symbol->symbol.procedure.return_value = get_type_symbol( &symbols, "integer" );
+ //~ symbol->symbol.procedure.params[0] = get_type_symbol( &symbols, "__gen_array_of_any" );
+#endif
+
sym = getSym( );
if( sym == S_lparen ) {
sym = getSym( );
/* TODO: || S_var later */
if( sym == S_ident ) {
do {
- if( funcType.details.function.len >= MAX_PARAMETERS ) {
+ if( symbol->symbol.procedure.len >= MAX_PARAMETERS ) {
Abort( "Too many parameters in definition of procedure" );
}
identifier( );
+ /* TODO from here */
+ /* lookup types, define local variables as parameters */
+ symbol->symbol.procedure.params[symbol->symbol.procedure.len]
+
+
funcType.details.function.params[funcType.details.function.len] = (Type *)( &funcType.details.function.data + sizeof( Type ) * funcType.details.function.len );
strncpy( funcType.details.function.params[funcType.details.function.len]->name, ident, MAX_IDENT_LEN );
funcType.details.function.params[funcType.details.function.len]->name[MAX_IDENT_LEN-1] = '\0';
@@ -1400,13 +1540,13 @@ static void procedureDeclaration( void )
if( sym == S_array ) {
sym = getSym( );
Expect( S_of );
- type( );
+ doType( );
funcType.details.function.params[funcType.details.function.len]->type = TYPE_ARRAY;
funcType.details.function.params[funcType.details.function.len]->details.array.len = 0;
funcType.details.function.params[funcType.details.function.len]->details.array.type = (Type *)&funcType.details.function.params[funcType.details.function.len]->details.array.data;
funcType.details.function.params[funcType.details.function.len]->details.array.type->type = lastType.type;
} else {
- type( );
+ doType( );
funcType.details.function.params[funcType.details.function.len]->type = lastType.type;
}
insert_symbol( &locals, *funcType.details.function.params[funcType.details.function.len],