parser.c \
symbol_table.c \
token.c \
- type.c
+ type.c \
+ type_hash.c
OBJECTS = $(SOURCES:%.c=build/%.o)
#include "lexer_t.h"
#include "token_t.h"
+#include "type_hash.h"
#include "parser.h"
#if 0
init_symbol_table();
init_tokens();
init_lexer();
+ init_types();
+ init_typehash();
init_ast();
init_parser();
exit_parser();
exit_ast();
+ exit_typehash();
+ exit_types();
exit_lexer();
exit_tokens();
exit_symbol_table();
#include "lexer_t.h"
#include "token_t.h"
#include "type_t.h"
+#include "type_hash.h"
#include "ast_t.h"
#include "adt/bitfiddle.h"
#include "adt/error.h"
} \
next_token();
+#define expect_void(expected) \
+ if(UNLIKELY(token.type != (expected))) { \
+ parse_error_expected(NULL, (expected), 0); \
+ eat_until_semi(); \
+ return; \
+ } \
+ next_token();
+
+
typedef enum {
SPECIFIER_SIGNED = 1 << 0,
SPECIFIER_UNSIGNED = 1 << 1,
#endif
} specifiers_t;
-typedef enum {
- TYPE_QUALIFIER_CONST = 1 << 0,
- TYPE_QUALIFIER_RESTRICT = 1 << 1,
- TYPE_QUALIFIER_VOLATILE = 1 << 2,
- TYPE_QUALIFIER_INLINE = 1 << 3,
-} type_qualifier_t;
-
typedef enum {
STORAGE_CLASS_NONE,
STORAGE_CLASS_TYPEDEF,
typedef struct declaration_specifiers_t declaration_specifiers_t;
struct declaration_specifiers_t {
storage_class_t storage_class;
- int type_qualifiers;
+ type_t *type;
};
static
{
type_type_t type_type = TYPE_INVALID;
atomic_type_type_t atomic_type = ATOMIC_TYPE_INVALID;
+ unsigned type_qualifiers = 0;
unsigned type_specifiers = 0;
while(1) {
/* type qualifiers */
#define MATCH_TYPE_QUALIFIER(token, qualifier) \
case token: \
- specifiers->type_qualifiers |= qualifier; \
+ type_qualifiers |= qualifier; \
next_token(); \
break;
/* function specifier */
default:
- return;;
+ goto finish_specifiers;
}
}
+finish_specifiers:
if(type_type == TYPE_INVALID) {
/* match valid basic types */
switch(type_specifiers) {
} else {
parse_error("multiple datatypes in declaration");
}
+ atomic_type = ATOMIC_TYPE_INVALID;
+ }
+
+ atomic_type_t *type = obstack_alloc(type_obst, sizeof(type[0]));
+ memset(type, 0, sizeof(type[0]));
+ type->type.type = TYPE_ATOMIC;
+ type->type.qualifiers = type_qualifiers;
+ type->atype = atomic_type;
+
+ type_t *result = typehash_insert((type_t*) type);
+ if(result != (type_t*) type) {
+ obstack_free(type_obst, type);
}
+
+ specifiers->type = result;
+
+ fprintf(stderr, "Specifiers type: ");
+ print_type(stderr, result);
+ fprintf(stderr, "\n");
} else {
if(type_specifiers != 0) {
parse_error("multiple datatypes in declaration");
}
}
-typedef struct declarator_t declarator_t;
-struct declarator_t {
- /* pointer stuff... */
- symbol_t *symbol;
+static
+unsigned parse_type_qualifiers()
+{
+ unsigned type_qualifiers = 0;
- declarator_t *next;
-};
+ while(1) {
+ switch(token.type) {
+ /* type qualifiers */
+ MATCH_TYPE_QUALIFIER(T_const, TYPE_QUALIFIER_CONST);
+ MATCH_TYPE_QUALIFIER(T_restrict, TYPE_QUALIFIER_RESTRICT);
+ MATCH_TYPE_QUALIFIER(T_volatile, TYPE_QUALIFIER_VOLATILE);
+ MATCH_TYPE_QUALIFIER(T_inline, TYPE_QUALIFIER_INLINE);
+
+ default:
+ return type_qualifiers;
+ }
+ }
+}
-declarator_t *parse_declarator(void)
+static
+void parse_declarator(const declaration_specifiers_t *specifiers)
{
+ type_t *type = specifiers->type;
+
while(token.type == '*') {
/* pointer */
next_token();
- //parse_type_qualifiers();
- }
- declarator_t *declarator;
+ pointer_type_t *pointer_type
+ = obstack_alloc(type_obst, sizeof(pointer_type[0]));
+ memset(pointer_type, 0, sizeof(pointer_type[0]));
+ pointer_type->type.type = TYPE_POINTER;
+ pointer_type->points_to = type;
+
+ pointer_type->type.qualifiers = parse_type_qualifiers();
+
+ type_t *result = typehash_insert((type_t*) pointer_type);
+ if(result != (type_t*) pointer_type) {
+ obstack_free(type_obst, pointer_type);
+ }
+
+ type = result;
+ }
switch(token.type) {
case T_IDENTIFIER:
- declarator = allocate_ast_zero(sizeof(declarator[0]));
- declarator->symbol = token.v.symbol;
+ (void) token.v.symbol;
next_token();
- return declarator;
+ break;
case '(':
next_token();
- declarator = parse_declarator();
- expect(')')
- return declarator;
+ parse_declarator(specifiers);
+ expect_void(')');
+ return;
default:
parse_error("problem while parsing declarator");
}
/* parse parameter-type-list or identifier-list */
- expect(')');
+ expect_void(')');
} else if(token.type == '[') {
next_token();
/* assignment_expression or '*' or nothing */
- expect(']');
+ expect_void(']');
}
- return declarator;
+ fprintf(stderr, "Declarator type: ");
+ print_type(stderr, type);
+ fprintf(stderr, "\n");
}
void parse_init_declarators(const declaration_specifiers_t *specifiers)
{
- (void) specifiers;
- declarator_t *declarator = parse_declarator();
+ parse_declarator(specifiers);
if(token.type == '=') {
next_token();
//parse_initialize();
}
- (void) declarator;
}
-typedef struct declaration_t declaration_t;
-struct declaration_t {
- declaration_specifiers_t specifiers;
- declaration_t *declarators;
-};
-
void parse_declaration(void)
{
declaration_specifiers_t specifiers;
parse_init_declarators(&specifiers);
}
-#if 0
-namespace_t *parse(FILE *in, const char *input_name)
-{
- namespace_t *namespace = parse_namespace();
-
- return namespace;
-}
-#endif
-
static
static
void parse_translation_unit(void)
{
+ /*
declaration_specifiers_t specifiers;
memset(&specifiers, 0, sizeof(specifiers));
parse_declaration_specifiers(&specifiers);
+ */
while(token.type != T_EOF) {
if(token.type == '{') {
static struct obstack _type_obst;
struct obstack *type_obst = &_type_obst;
-void init_type_module()
+void init_types()
{
obstack_init(type_obst);
}
-void exit_type_module()
+void exit_types()
{
obstack_free(type_obst, NULL);
}
+static
+void print_type_qualifiers(FILE *out, const type_t *type)
+{
+ unsigned qualifiers = type->qualifiers;
+ if(qualifiers & TYPE_QUALIFIER_CONST) {
+ fputs("const ", out);
+ }
+ if(qualifiers & TYPE_QUALIFIER_VOLATILE) {
+ fputs("volatile ", out);
+ }
+ if(qualifiers & TYPE_QUALIFIER_RESTRICT) {
+ fputs("restrict ", out);
+ }
+ if(qualifiers & TYPE_QUALIFIER_INLINE) {
+ fputs("inline ", out);
+ }
+}
+
static
void print_atomic_type(FILE *out, const atomic_type_t *type)
{
+ print_type_qualifiers(out, & type->type);
+
switch(type->atype) {
case ATOMIC_TYPE_INVALID: fputs("INVALIDATOMIC", out); break;
case ATOMIC_TYPE_BOOL: fputs("bool", out); break;
static
void print_method_type(FILE *out, const method_type_t *type)
{
+ print_type_qualifiers(out, & type->type);
+
fputs("<", out);
print_type(out, type->result_type);
fputs(" ", out);
{
print_type(out, type->points_to);
fputs("*", out);
+ print_type_qualifiers(out, &type->type);
}
void print_type(FILE *out, const type_t *type)
fputs("invalid", out);
return;
case TYPE_ENUM:
- case TYPE_TYPEDEF:
+ print_type_qualifiers(out, type);
fputs("TODO", out);
return;
case TYPE_ATOMIC:
return;
case TYPE_COMPOUND_STRUCT:
case TYPE_COMPOUND_UNION:
+ print_type_qualifiers(out, type);
fprintf(out, "%s", ((const compound_type_t*) type)->symbol->string);
return;
case TYPE_METHOD:
typedef struct method_type_t method_type_t;
typedef struct compound_entry_t compound_entry_t;
typedef struct compound_type_t compound_type_t;
+typedef struct enum_type_t enum_type_t;
-void init_type_module(void);
-void exit_type_module(void);
+void init_types(void);
+void exit_types(void);
/**
* prints a human readable form of @p type to a stream
--- /dev/null
+#include <config.h>
+
+#include "type_hash.h"
+
+#include "adt/error.h"
+#include "type_t.h"
+
+#include <assert.h>
+
+#define HashSet type_hash_t
+#define HashSetIterator type_hash_iterator_t
+#define ValueType type_t*
+#include "adt/hashset.h"
+#undef ValueType
+#undef HashSetIterator
+#undef HashSet
+
+static
+unsigned hash_ptr(const void *ptr)
+{
+ unsigned ptr_int = (ptr - NULL);
+ return ptr_int >> 3;
+}
+
+static
+unsigned hash_atomic_type(const atomic_type_t *type)
+{
+ unsigned some_prime = 27644437;
+
+ return type->atype * some_prime;
+}
+
+static
+unsigned hash_pointer_type(const pointer_type_t *type)
+{
+ return hash_ptr(type->points_to);
+}
+
+static
+unsigned hash_compound_type(const compound_type_t *type)
+{
+ unsigned result = hash_ptr(type->symbol);
+
+ return result;
+}
+
+static
+unsigned hash_type(const type_t *type);
+
+static
+unsigned hash_method_type(const method_type_t *type)
+{
+ unsigned result = hash_ptr(type->result_type);
+
+ method_parameter_type_t *parameter = type->parameter_types;
+ while(parameter != NULL) {
+ result ^= hash_ptr(parameter->type);
+ parameter = parameter->next;
+ }
+ result ^= hash_ptr(type->abi_style);
+
+ return result;
+}
+
+static
+unsigned hash_enum_type(const enum_type_t *type)
+{
+ unsigned result = hash_ptr(type->symbol);
+
+ /* TODO */
+
+ return result;
+}
+
+static
+unsigned hash_type(const type_t *type)
+{
+ unsigned hash;
+
+ switch(type->type) {
+ case TYPE_INVALID:
+ panic("internalizing void or invalid types not possible");
+ return 0;
+ case TYPE_ATOMIC:
+ hash = hash_atomic_type((const atomic_type_t*) type);
+ break;
+ case TYPE_ENUM:
+ hash = hash_enum_type((const enum_type_t*) type);
+ break;
+ case TYPE_COMPOUND_STRUCT:
+ case TYPE_COMPOUND_UNION:
+ hash = hash_compound_type((const compound_type_t*) type);
+ break;
+ case TYPE_METHOD:
+ hash = hash_method_type((const method_type_t*) type);
+ break;
+ case TYPE_POINTER:
+ hash = hash_pointer_type((const pointer_type_t*) type);
+ break;
+ }
+
+ unsigned some_prime = 99991;
+ hash ^= some_prime * type->qualifiers;
+
+ return hash;
+}
+
+static
+int atomic_types_equal(const atomic_type_t *type1, const atomic_type_t *type2)
+{
+ return type1->atype == type2->atype;
+}
+
+static
+int compound_types_equal(const compound_type_t *type1,
+ const compound_type_t *type2)
+{
+ if(type1->symbol != type2->symbol)
+ return 0;
+
+#if 0
+ struct_entry_t *entry1 = type1->entries;
+ struct_entry_t *entry2 = type2->entries;
+
+ while(entry1 != NULL && entry2 != NULL) {
+ if(entry1->type != entry2->type)
+ return 0;
+ entry1 = entry1->next;
+ entry2 = entry2->next;
+ }
+ if(entry1 != NULL || entry2 != NULL)
+ return 0;
+#endif
+
+ return 1;
+}
+
+static
+int method_types_equal(const method_type_t *type1, const method_type_t *type2)
+{
+ if(type1->result_type != type2->result_type)
+ return 0;
+
+ if(type1->abi_style != type2->abi_style)
+ return 0;
+
+ method_parameter_type_t *param1 = type1->parameter_types;
+ method_parameter_type_t *param2 = type2->parameter_types;
+ while(param1 != NULL && param2 != NULL) {
+ if(param1->type != param2->type)
+ return 0;
+ param1 = param1->next;
+ param2 = param2->next;
+ }
+ if(param1 != NULL || param2 != NULL)
+ return 0;
+
+ return 1;
+}
+
+static
+int pointer_types_equal(const pointer_type_t *type1,
+ const pointer_type_t *type2)
+{
+ return type1->points_to == type2->points_to;
+}
+
+static
+int enum_types_equal(const enum_type_t *type1, const enum_type_t *type2)
+{
+ /* TODO */
+ return type1->symbol == type2->symbol;
+}
+
+static
+int types_equal(const type_t *type1, const type_t *type2)
+{
+ if(type1 == type2)
+ return 1;
+ if(type1->type != type2->type)
+ return 0;
+ if(type1->qualifiers != type2->qualifiers)
+ return 0;
+
+ switch(type1->type) {
+ case TYPE_INVALID:
+ return 0;
+ case TYPE_ATOMIC:
+ return atomic_types_equal((const atomic_type_t*) type1,
+ (const atomic_type_t*) type2);
+ case TYPE_COMPOUND_STRUCT:
+ case TYPE_COMPOUND_UNION:
+ return compound_types_equal((const compound_type_t*) type1,
+ (const compound_type_t*) type2);
+ case TYPE_ENUM:
+ return enum_types_equal((const enum_type_t*) type1,
+ (const enum_type_t*) type2);
+ case TYPE_METHOD:
+ return method_types_equal((const method_type_t*) type1,
+ (const method_type_t*) type2);
+ case TYPE_POINTER:
+ return pointer_types_equal((const pointer_type_t*) type1,
+ (const pointer_type_t*) type2);
+ }
+
+ abort();
+}
+
+#define HashSet type_hash_t
+#define HashSetIterator type_hash_iterator_t
+#define ValueType type_t*
+#define NullValue NULL
+#define DeletedValue ((type_t*)-1)
+#define Hash(this, key) hash_type(key)
+#define KeysEqual(this,key1,key2) types_equal(key1, key2)
+#define SetRangeEmpty(ptr,size) memset(ptr, 0, (size) * sizeof(*(ptr)))
+
+#define hashset_init _typehash_init
+#define hashset_init_size _typehash_init_size
+#define hashset_destroy _typehash_destroy
+#define hashset_insert _typehash_insert
+#define hashset_remove typehash_remove
+#define hashset_find typehash_find
+#define hashset_size typehash_size
+#define hashset_iterator_init typehash_iterator_init
+#define hashset_iterator_next typehash_iterator_next
+#define hashset_remove_iterator typehash_remove_iterator
+
+#include "adt/hashset.c"
+
+static type_hash_t typehash;
+
+void init_typehash(void)
+{
+ _typehash_init(&typehash);
+}
+
+void exit_typehash(void)
+{
+ _typehash_destroy(&typehash);
+}
+
+type_t *typehash_insert(type_t *type)
+{
+ return _typehash_insert(&typehash, type);
+}
--- /dev/null
+#ifndef TYPE_HASH_H
+#define TYPE_HASH_H
+
+#include "type.h"
+
+void init_typehash(void);
+void exit_typehash(void);
+
+type_t *typehash_insert(type_t *type);
+int typehash_contains(type_t *type);
+
+#endif
TYPE_COMPOUND_STRUCT,
TYPE_COMPOUND_UNION,
TYPE_ENUM,
- TYPE_TYPEDEF,
TYPE_METHOD,
TYPE_POINTER
} type_type_t;
#endif
} atomic_type_type_t;
+typedef enum {
+ TYPE_QUALIFIER_CONST = 1 << 0,
+ TYPE_QUALIFIER_RESTRICT = 1 << 1,
+ TYPE_QUALIFIER_VOLATILE = 1 << 2,
+ TYPE_QUALIFIER_INLINE = 1 << 3,
+} type_qualifier_t;
+
struct type_t {
type_type_t type;
+ unsigned qualifiers;
};
struct atomic_type_t {
source_position_t source_position;
};
+struct enum_type_t {
+ /* todo */
+ symbol_t *symbol;
+ source_position_t source_position;
+};
+
#endif