diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-23 14:19:54 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-23 14:19:54 +0200 |
commit | 35eaad923d3ef598d6f9ed6925fd65c6a311896b (patch) | |
tree | 2b448435c15f9e014a59134312887c6e1a1a9c94 /src | |
parent | b9397e53034b08dd9ffb69c94b5283dc46863d33 (diff) | |
download | bdl-35eaad923d3ef598d6f9ed6925fd65c6a311896b.tar.gz bdl-35eaad923d3ef598d6f9ed6925fd65c6a311896b.zip |
Implement basic type inference for numbers and symbols
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 76 |
1 files changed, 48 insertions, 28 deletions
@@ -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 | ||
58 | typedef struct Type { | 58 | typedef Str Type; |
59 | Str name; | ||
60 | sz size; | ||
61 | } Type; | ||
62 | 59 | ||
63 | typedef struct Symbol { | 60 | typedef 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 | ||
188 | void | ||
189 | emit_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 | |||
185 | Type | 193 | Type |
186 | type_inference(Analyzer *a, Node *node, Scope *scope) { | 194 | type_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[] = { |