aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-23 14:19:54 +0200
committerBad Diode <bd@badd10de.dev>2024-06-23 14:19:54 +0200
commit35eaad923d3ef598d6f9ed6925fd65c6a311896b (patch)
tree2b448435c15f9e014a59134312887c6e1a1a9c94 /src
parentb9397e53034b08dd9ffb69c94b5283dc46863d33 (diff)
downloadbdl-35eaad923d3ef598d6f9ed6925fd65c6a311896b.tar.gz
bdl-35eaad923d3ef598d6f9ed6925fd65c6a311896b.zip
Implement basic type inference for numbers and symbols
Diffstat (limited to 'src')
-rw-r--r--src/main.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/src/main.c b/src/main.c
index d244d37..3614e56 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,10 +55,7 @@ Str sym_kind_str[] = {
55 [SYM_STRUCT_FIELD] = cstr("STRUCT FIELD "), 55 [SYM_STRUCT_FIELD] = cstr("STRUCT FIELD "),
56}; 56};
57 57
58typedef struct Type { 58typedef Str Type;
59 Str name;
60 sz size;
61} Type;
62 59
63typedef struct Symbol { 60typedef struct Symbol {
64 SymbolKind kind; 61 SymbolKind kind;
@@ -129,15 +126,21 @@ graph_scope(Scope *scope, Arena a) {
129 print( 126 print(
130 "%d[shape=\"none\" label=<\ 127 "%d[shape=\"none\" label=<\
131<TABLE ALIGN=\"left\" STYLE=\"rounded\" BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"6\" COLUMNS=\"*\">\ 128<TABLE ALIGN=\"left\" STYLE=\"rounded\" BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"6\" COLUMNS=\"*\">\
132 <TR style=\"rounded\" ><TD COLSPAN=\"2\">ID: %d</TD></TR>", 129 <TR style=\"rounded\" ><TD COLSPAN=\"3\">ID: %d</TD></TR>",
133 scope->id, scope->id); 130 scope->id, scope->id);
134 print( 131 print(
135 "<TR ><TD ALIGN=\"left\" > NAME</TD><TD ALIGN=\"left\" > " 132 "<TR ><TD ALIGN=\"left\" > NAME </TD><TD ALIGN=\"left\" > KIND "
136 "KIND</TD></TR>"); 133 "</TD><TD ALIGN=\"left\" > TYPE </TD></TR>");
137 while (sym) { 134 while (sym) {
135 Str type_name = cstr("nil");
136 TypeMap *type = find_type(scope, sym->val.name);
137 if (type) {
138 type_name = type->val;
139 }
138 print( 140 print(
139 "<TR><TD ALIGN=\"left\"> %s </TD><TD ALIGN=\"left\"> %s </TD></TR>", 141 "<TR><TD ALIGN=\"left\"> %s </TD><TD ALIGN=\"left\"> %s </TD><TD "
140 sym->val.name, sym_kind_str[sym->val.kind]); 142 "ALIGN=\"left\"> %s </TD></TR>",
143 sym->val.name, sym_kind_str[sym->val.kind], type_name);
141 SymbolMapIter field_iter = symmap_iterator(sym->val.fields, &a); 144 SymbolMapIter field_iter = symmap_iterator(sym->val.fields, &a);
142 SymbolMap *field = symmap_next(&field_iter, &a); 145 SymbolMap *field = symmap_next(&field_iter, &a);
143 while (field) { 146 while (field) {
@@ -182,8 +185,32 @@ graph_symbols(Scope **scopes, Arena a) {
182 println("}"); 185 println("}");
183} 186}
184 187
188void
189emit_semantic_error(Analyzer *a, Node *n, Str msg) {
190 eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg);
191}
192
185Type 193Type
186type_inference(Analyzer *a, Node *node, Scope *scope) { 194type_inference(Analyzer *a, Node *node, Scope *scope) {
195 assert(a);
196 assert(scope);
197 assert(node);
198 switch (node->kind) {
199 case NODE_NUM_UINT: return cstr("uint"); break;
200 case NODE_NUM_INT: return cstr("int"); break;
201 case NODE_NUM_FLOAT: return cstr("f64"); break;
202 case NODE_SYMBOL: {
203 TypeMap *type = find_type(scope, node->value.str);
204 if (type) {
205 return type->val;
206 }
207 } break;
208 default: {
209 emit_semantic_error(a, node,
210 cstr("type inference not implemented for this "
211 "kind of expression"));
212 } break;
213 }
187 return (Type){0}; 214 return (Type){0};
188} 215}
189 216
@@ -398,11 +425,17 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) {
398 return; 425 return;
399 } 426 }
400 typemap_insert(&scope->types, symbol, type->val, a->storage); 427 typemap_insert(&scope->types, symbol, type->val, a->storage);
428 // TODO: Typecheck the expression if we have it.
429 // if (node->var_val) ...
401 return; 430 return;
402 } 431 }
403 // We don't know the type for this symbol, perform inference.
404 type_inference(a, node->var_val, scope);
405 432
433 // We don't know the type for this symbol, perform inference.
434 Type type = type_inference(a, node->var_val, scope);
435 if (type.size) {
436 typemap_insert(&scope->types, symbol, type, a->storage);
437 node->var_name->type = type;
438 }
406 } break; 439 } break;
407 // Binary ops 440 // Binary ops
408 case NODE_ADD: 441 case NODE_ADD:
@@ -451,26 +484,13 @@ symbolic_analysis(Analyzer *a, Parser *parser) {
451 484
452 // Fill builtin types. 485 // Fill builtin types.
453 Type builtin_types[] = { 486 Type builtin_types[] = {
454 {cstr("u8"), 1}, 487 cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), cstr("u32"),
455 {cstr("s8"), 1}, 488 cstr("s32"), cstr("u64"), cstr("s64"), cstr("f32"), cstr("f64"),
456 {cstr("u16"), 2}, 489 cstr("ptr"), cstr("int"), cstr("uint"), cstr("str"),
457 {cstr("s16"), 2},
458 {cstr("u32"), 4},
459 {cstr("s32"), 4},
460 {cstr("u64"), 8},
461 {cstr("s64"), 8},
462 {cstr("f32"), 4},
463 {cstr("f64"), 8},
464 // TODO: down here is machine dependant, we could insert 0 for now and
465 // fill it up later maybe? Dunno.
466 {cstr("ptr"), 8},
467 {cstr("int"), 8},
468 {cstr("uint"), 8},
469 {cstr("str"), 8 + 8}, // (u8*, sz)
470 }; 490 };
471 for (sz i = 0; i < LEN(builtin_types); i++) { 491 for (sz i = 0; i < LEN(builtin_types); i++) {
472 Type type = builtin_types[i]; 492 Type type = builtin_types[i];
473 typemap_insert(&scope->types, type.name, type, a->storage); 493 typemap_insert(&scope->types, type, type, a->storage);
474 } 494 }
475 495
476 // Str valid_int_types[] = { 496 // Str valid_int_types[] = {