more sema
This commit is contained in:
parent
d43dc3539d
commit
8309384c0b
1
ast.h
1
ast.h
@ -45,6 +45,7 @@ struct AstStmt {
|
|||||||
typedef enum : unsigned int {
|
typedef enum : unsigned int {
|
||||||
AstSpec_Int = 1 << 0,
|
AstSpec_Int = 1 << 0,
|
||||||
AstSpec_Char = 1 << 1,
|
AstSpec_Char = 1 << 1,
|
||||||
|
AstSpec_Void = 1 << 2,
|
||||||
AstSpec_DefTy = 1 << 6,
|
AstSpec_DefTy = 1 << 6,
|
||||||
AstSpec_Unsigned = 1 << 7,
|
AstSpec_Unsigned = 1 << 7,
|
||||||
AstSpec_Static = 1 << 8,
|
AstSpec_Static = 1 << 8,
|
||||||
|
|||||||
@ -262,7 +262,7 @@ void ast_expr_print(FILE* f, const AstExpr* node, int depth)
|
|||||||
}
|
}
|
||||||
indent(f, depth + 1);
|
indent(f, depth + 1);
|
||||||
}
|
}
|
||||||
fprintf(f, ",]\n");
|
fprintf(f, "],\n");
|
||||||
|
|
||||||
indent(f, depth);
|
indent(f, depth);
|
||||||
fprintf(f, "}");
|
fprintf(f, "}");
|
||||||
|
|||||||
2
parse.c
2
parse.c
@ -328,7 +328,7 @@ static AstDecl* parse_decl(Parser* p, bool is_param)
|
|||||||
|
|
||||||
if (!is_param && first->ty == AstDeclar_Function && p->curr.ty == '{') {
|
if (!is_param && first->ty == AstDeclar_Function && p->curr.ty == '{') {
|
||||||
|
|
||||||
sema_function_enter(p->sema, declars[0]);
|
sema_function_enter(p->sema, spec, declars[0]);
|
||||||
function_body = parse_stmt_block(p);
|
function_body = parse_stmt_block(p);
|
||||||
sema_function_leave(p->sema);
|
sema_function_leave(p->sema);
|
||||||
|
|
||||||
|
|||||||
352
sema.c
352
sema.c
@ -2,8 +2,68 @@
|
|||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static void type_spec_print(FILE* file, TypeSpec spec)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct {
|
||||||
|
TypeSpec spec;
|
||||||
|
const char* ident;
|
||||||
|
} spec_idents[] = {
|
||||||
|
{ TypeSpec_Const, "const" },
|
||||||
|
{ TypeSpec_Short, "short" },
|
||||||
|
{ TypeSpec_Long, "long" },
|
||||||
|
{ TypeSpec_Long2, "long" },
|
||||||
|
{ TypeSpec_Unsigned, "unsigned" },
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t spec_idents_size = sizeof(spec_idents) / sizeof(spec_idents[0]);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < spec_idents_size; ++i) {
|
||||||
|
if (spec & spec_idents[i].spec) {
|
||||||
|
fprintf(file, "%s ", spec_idents[i].ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void type_print(FILE* file, const Type* type)
|
||||||
|
{
|
||||||
|
type_spec_print(file, type->spec);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
TypeTy ty;
|
||||||
|
const char* ident;
|
||||||
|
} ty_idents[] = {
|
||||||
|
{ Type_Int, "int" },
|
||||||
|
{ Type_Char, "char" },
|
||||||
|
{ Type_Float, "float" },
|
||||||
|
{ Type_Double, "double" },
|
||||||
|
{ Type_Bool, "bool" },
|
||||||
|
{ Type_Void, "void" },
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t ty_idents_size = sizeof(ty_idents) / sizeof(ty_idents[0]);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ty_idents_size; ++i) {
|
||||||
|
if (type->ty == ty_idents[i].ty) {
|
||||||
|
fprintf(file, "%s", ty_idents[i].ident);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type->ty == Type_Pointer) {
|
||||||
|
fprintf(file, " * ");
|
||||||
|
type_spec_print(file, type->pointer.spec);
|
||||||
|
type_print(file, type->pointer.inner);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false && "not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Hashmap ord_syms;
|
Hashmap ord_syms;
|
||||||
Hashmap tag_syms;
|
Hashmap tag_syms;
|
||||||
@ -27,8 +87,10 @@ static void rib_deinit(Rib* r)
|
|||||||
|
|
||||||
struct Sema {
|
struct Sema {
|
||||||
Arena sym_arena;
|
Arena sym_arena;
|
||||||
|
Arena type_arena;
|
||||||
ARRAY_FIELD(Rib, ribs);
|
ARRAY_FIELD(Rib, ribs);
|
||||||
Hashmap labels;
|
Hashmap labels;
|
||||||
|
Keymap expr_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
Sema* sema_new(void)
|
Sema* sema_new(void)
|
||||||
@ -36,16 +98,20 @@ Sema* sema_new(void)
|
|||||||
Sema* s = malloc(sizeof(Sema));
|
Sema* s = malloc(sizeof(Sema));
|
||||||
*s = (Sema) {
|
*s = (Sema) {
|
||||||
.sym_arena = { },
|
.sym_arena = { },
|
||||||
|
.type_arena = { },
|
||||||
ARRAY_FIELD_INIT(ribs),
|
ARRAY_FIELD_INIT(ribs),
|
||||||
.labels = { },
|
.labels = { },
|
||||||
|
.expr_types = { },
|
||||||
};
|
};
|
||||||
|
|
||||||
arena_init(&s->sym_arena, 1024);
|
arena_init(&s->sym_arena, 1024);
|
||||||
|
arena_init(&s->type_arena, 1024);
|
||||||
|
|
||||||
ARRAY_FIELD_PUSH(s, ribs, (&(Rib) { }));
|
ARRAY_FIELD_PUSH(s, ribs, (&(Rib) { }));
|
||||||
rib_init(&s->ribs[0]);
|
rib_init(&s->ribs[0]);
|
||||||
|
|
||||||
hashmap_init(&s->labels, sizeof(LabelSym*));
|
hashmap_init(&s->labels, sizeof(LabelSym*));
|
||||||
|
keymap_init(&s->expr_types, sizeof(Type*));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -53,11 +119,13 @@ Sema* sema_new(void)
|
|||||||
void sema_free(Sema* s)
|
void sema_free(Sema* s)
|
||||||
{
|
{
|
||||||
arena_deinit(&s->sym_arena);
|
arena_deinit(&s->sym_arena);
|
||||||
|
arena_deinit(&s->type_arena);
|
||||||
for (size_t i = 0; i < s->ribs_size; ++i)
|
for (size_t i = 0; i < s->ribs_size; ++i)
|
||||||
rib_deinit(&s->ribs[i]);
|
rib_deinit(&s->ribs[i]);
|
||||||
if (s->ribs)
|
if (s->ribs)
|
||||||
free(s->ribs);
|
free(s->ribs);
|
||||||
hashmap_deinit(&s->labels);
|
hashmap_deinit(&s->labels);
|
||||||
|
keymap_deinit(&s->expr_types);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +142,162 @@ void sema_scope_leave(Sema* s)
|
|||||||
s->ribs_size -= 1;
|
s->ribs_size -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sema_function_enter(Sema* s, AstDeclar* declar)
|
static Sym* get_ord_sym(Sema* s, const char* ident)
|
||||||
|
{
|
||||||
|
Sym* sym = nullptr;
|
||||||
|
for (size_t i = 0; i < s->ribs_size; ++i)
|
||||||
|
if ((sym = hashmap_get(&s->ribs[s->ribs_size - i - 1].ord_syms, ident)))
|
||||||
|
break;
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void error_if_multi_spec(
|
||||||
|
bool type_specced, Loc loc, const Type* first, TypeTy second_ty)
|
||||||
|
{
|
||||||
|
if (type_specced) {
|
||||||
|
fprintf(stderr, "error: cannot combine type '");
|
||||||
|
type_print(stderr, &(Type) { .ty = second_ty });
|
||||||
|
fprintf(stderr, "' with type '");
|
||||||
|
type_print(stderr, first);
|
||||||
|
fprintf(stderr, "' on line %d\n", loc.line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_decl_spec(Type* type, AstSpec as, Loc loc)
|
||||||
|
{
|
||||||
|
bool type_specced = false;
|
||||||
|
|
||||||
|
if (as & AstSpec_Int) {
|
||||||
|
error_if_multi_spec(type_specced, loc, type, Type_Char);
|
||||||
|
type_specced = true;
|
||||||
|
|
||||||
|
type->ty = Type_Int;
|
||||||
|
}
|
||||||
|
if (as & AstSpec_Char) {
|
||||||
|
error_if_multi_spec(type_specced, loc, type, Type_Char);
|
||||||
|
type_specced = true;
|
||||||
|
|
||||||
|
type->ty = Type_Char;
|
||||||
|
}
|
||||||
|
if (as & AstSpec_Void) {
|
||||||
|
error_if_multi_spec(type_specced, loc, type, Type_Void);
|
||||||
|
type_specced = true;
|
||||||
|
|
||||||
|
type->ty = Type_Void;
|
||||||
|
}
|
||||||
|
if (as & (AstSpec_Enum | AstSpec_Struct | AstSpec_Union)) {
|
||||||
|
assert(false && "not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (as & AstSpec_Unsigned) {
|
||||||
|
type->spec |= TypeSpec_Unsigned;
|
||||||
|
}
|
||||||
|
if (as & AstSpec_Const) {
|
||||||
|
type->spec |= TypeSpec_Const;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Type* check_decl_type(Sema* s, AstDecl* decl)
|
||||||
|
{
|
||||||
|
Type* type = arena_alloc(&s->type_arena, sizeof(Type));
|
||||||
|
*type = (Type) { };
|
||||||
|
|
||||||
|
decode_decl_spec(type, decl->spec, decl->loc);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void error_if_redefinition(Hashmap* map, const char* ident, Loc loc)
|
||||||
|
{
|
||||||
|
Sym* sym;
|
||||||
|
if ((sym = hashmap_get(map, ident))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"error: redefinition of '%s' on line %d\n",
|
||||||
|
ident,
|
||||||
|
loc.line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_declar(Sema* s,
|
||||||
|
AstDeclar* declar,
|
||||||
|
Type* type,
|
||||||
|
Type** out_declar_type,
|
||||||
|
const char** out_declar_ident)
|
||||||
|
{
|
||||||
|
switch (declar->ty) {
|
||||||
|
case AstDeclar_Ident: {
|
||||||
|
*out_declar_type = type;
|
||||||
|
*out_declar_ident = declar->ident;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case AstDeclar_Pointer: {
|
||||||
|
Type* new_type = arena_alloc(&s->type_arena, sizeof(Type));
|
||||||
|
*new_type = (Type) {
|
||||||
|
.ty = Type_Pointer,
|
||||||
|
.spec = 0,
|
||||||
|
.pointer = {
|
||||||
|
.inner = type,
|
||||||
|
.spec = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
decode_decl_spec(new_type, declar->pointer.spec, declar->loc);
|
||||||
|
check_declar(s,
|
||||||
|
declar->pointer.declar,
|
||||||
|
new_type,
|
||||||
|
out_declar_type,
|
||||||
|
out_declar_ident);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case AstDeclar_Array: {
|
||||||
|
assert(false && "not implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AstDeclar_Function: {
|
||||||
|
Type* new_type = arena_alloc(&s->type_arena, sizeof(Type));
|
||||||
|
*new_type = (Type) {
|
||||||
|
.ty = Type_Function,
|
||||||
|
.spec = 0,
|
||||||
|
.function = {
|
||||||
|
.return_type = type,
|
||||||
|
ARRAY_FIELD_INIT(params),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < declar->function.params_size; ++i) {
|
||||||
|
AstDecl* param_decl = declar->function.params[i];
|
||||||
|
|
||||||
|
assert(param_decl->declars_size == 1);
|
||||||
|
AstDeclar* param_declar = param_decl->declars[0];
|
||||||
|
|
||||||
|
Type* decl_type = check_decl_type(s, param_decl);
|
||||||
|
|
||||||
|
const char* declar_ident;
|
||||||
|
Type* declar_type;
|
||||||
|
check_declar(
|
||||||
|
s, param_declar, decl_type, &declar_type, &declar_ident);
|
||||||
|
|
||||||
|
(void)declar_ident;
|
||||||
|
|
||||||
|
ARENA_ARRAY_FIELD_PUSH(
|
||||||
|
&s->type_arena, &new_type->function, params, &declar_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle forward declarations
|
||||||
|
|
||||||
|
check_declar(s,
|
||||||
|
declar->pointer.declar,
|
||||||
|
new_type,
|
||||||
|
out_declar_type,
|
||||||
|
out_declar_ident);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(false && "unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_function_enter(Sema* s, AstSpec spec, AstDeclar* declar)
|
||||||
{
|
{
|
||||||
assert(declar->ty == AstDeclar_Function);
|
assert(declar->ty == AstDeclar_Function);
|
||||||
|
|
||||||
@ -82,9 +305,49 @@ void sema_function_enter(Sema* s, AstDeclar* declar)
|
|||||||
hashmap_deinit(&s->labels);
|
hashmap_deinit(&s->labels);
|
||||||
hashmap_init(&s->labels, sizeof(LabelSym*));
|
hashmap_init(&s->labels, sizeof(LabelSym*));
|
||||||
|
|
||||||
|
Type* type = arena_alloc(&s->type_arena, sizeof(Type));
|
||||||
|
*type = (Type) { };
|
||||||
|
decode_decl_spec(type, spec, declar->loc);
|
||||||
|
|
||||||
|
Rib* rib = &s->ribs[s->ribs_size - 1];
|
||||||
|
error_if_redefinition(&rib->ord_syms, declar->ident, declar->loc);
|
||||||
|
|
||||||
|
Sym* sym = arena_alloc(&s->sym_arena, sizeof(Sym));
|
||||||
|
*sym = (Sym) {
|
||||||
|
.ty = Sym_Declar,
|
||||||
|
.declar = {
|
||||||
|
.type = type,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
hashmap_set(&rib->ord_syms, declar->ident, &sym);
|
||||||
|
|
||||||
sema_scope_enter(s);
|
sema_scope_enter(s);
|
||||||
|
|
||||||
for (size_t i = 0; i < declar->function.params_size; ++i) { }
|
for (size_t i = 0; i < declar->function.params_size; ++i) {
|
||||||
|
AstDecl* param_decl = declar->function.params[i];
|
||||||
|
|
||||||
|
assert(param_decl->declars_size == 1);
|
||||||
|
AstDeclar* param_declar = param_decl->declars[0];
|
||||||
|
|
||||||
|
Type* decl_type = check_decl_type(s, param_decl);
|
||||||
|
|
||||||
|
const char* declar_ident;
|
||||||
|
Type* declar_type;
|
||||||
|
check_declar(s, param_declar, decl_type, &declar_type, &declar_ident);
|
||||||
|
|
||||||
|
Rib* rib = &s->ribs[s->ribs_size - 1];
|
||||||
|
error_if_redefinition(&rib->ord_syms, declar->ident, declar->loc);
|
||||||
|
|
||||||
|
Sym* sym = arena_alloc(&s->sym_arena, sizeof(Sym));
|
||||||
|
*sym = (Sym) {
|
||||||
|
.ty = Sym_Param,
|
||||||
|
.param = {
|
||||||
|
.type = declar_type,
|
||||||
|
.idx = i,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
hashmap_set(&rib->ord_syms, declar_ident, &sym);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sema_function_leave(Sema* s)
|
void sema_function_leave(Sema* s)
|
||||||
@ -92,15 +355,90 @@ void sema_function_leave(Sema* s)
|
|||||||
sema_scope_leave(s);
|
sema_scope_leave(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sema_visit_function_declar(Sema* s, AstDeclar* declar)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void sema_visit_stmt(Sema* s, AstStmt* stmt)
|
void sema_visit_stmt(Sema* s, AstStmt* stmt)
|
||||||
{
|
{
|
||||||
if (stmt->ty == AstStmt_Decl) { }
|
if (stmt->ty == AstStmt_Decl) {
|
||||||
|
Type* type = check_decl_type(s, stmt->decl);
|
||||||
|
|
||||||
|
if (stmt->decl->function_body) {
|
||||||
|
// assume already handled
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < stmt->decl->declars_size; ++i) {
|
||||||
|
AstDeclar* declar = stmt->decl->declars[i];
|
||||||
|
|
||||||
|
Type* declar_type;
|
||||||
|
const char* declar_ident;
|
||||||
|
check_declar(s, declar, type, &declar_type, &declar_ident);
|
||||||
|
|
||||||
|
Rib* rib = &s->ribs[s->ribs_size - 1];
|
||||||
|
error_if_redefinition(&rib->ord_syms, declar->ident, declar->loc);
|
||||||
|
|
||||||
|
Sym* sym = arena_alloc(&s->sym_arena, sizeof(Sym));
|
||||||
|
*sym = (Sym) {
|
||||||
|
.ty = Sym_Declar,
|
||||||
|
.declar = {
|
||||||
|
.type = declar_type,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
hashmap_set(&rib->ord_syms, declar_ident, &sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sema_visit_expr(Sema* s, AstExpr* expr)
|
void sema_visit_expr(Sema* s, AstExpr* expr)
|
||||||
{
|
{
|
||||||
|
Type* type = nullptr;
|
||||||
|
|
||||||
|
switch (expr->ty) {
|
||||||
|
case AstExpr_Ident: {
|
||||||
|
Sym* sym;
|
||||||
|
if ((sym = get_ord_sym(s, expr->ident)) == nullptr) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"error: undefined identifier '%s' on line %d\n",
|
||||||
|
expr->ident,
|
||||||
|
expr->loc.line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sym->ty) {
|
||||||
|
case Sym_Declar:
|
||||||
|
type = sym->declar.type;
|
||||||
|
break;
|
||||||
|
case Sym_Param:
|
||||||
|
type = sym->param.type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AstExpr_Str: {
|
||||||
|
Type* inner_type = arena_alloc(&s->type_arena, sizeof(Type));
|
||||||
|
*inner_type = (Type) {
|
||||||
|
.ty = Type_Char,
|
||||||
|
.spec = TypeSpec_Const,
|
||||||
|
};
|
||||||
|
|
||||||
|
type = arena_alloc(&s->type_arena, sizeof(Type));
|
||||||
|
*type = (Type) {
|
||||||
|
.ty = Type_Pointer,
|
||||||
|
.pointer = {
|
||||||
|
.inner = inner_type,
|
||||||
|
.spec = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case AstExpr_Call: {
|
||||||
|
Type* inner_type
|
||||||
|
= keymap_get(&s->expr_types, (size_t)expr->call.expr);
|
||||||
|
assert(inner_type);
|
||||||
|
printf("inner_type->ty == %d\n", inner_type->ty);
|
||||||
|
assert(inner_type->ty == Type_Function);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keymap_set(&s->expr_types, (KeymapKey)expr, &type);
|
||||||
}
|
}
|
||||||
|
|||||||
55
sema.h
55
sema.h
@ -2,12 +2,65 @@
|
|||||||
#define SEMA_H
|
#define SEMA_H
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
|
#include "collection.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Type_None,
|
||||||
|
Type_Int,
|
||||||
|
Type_Char,
|
||||||
|
Type_Float,
|
||||||
|
Type_Double,
|
||||||
|
Type_Bool,
|
||||||
|
Type_Void,
|
||||||
|
Type_Pointer,
|
||||||
|
Type_Function,
|
||||||
|
} TypeTy;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TypeSpec_Const = 1 << 0,
|
||||||
|
TypeSpec_Short = 1 << 1,
|
||||||
|
TypeSpec_Long = 1 << 2,
|
||||||
|
TypeSpec_Long2 = 1 << 3,
|
||||||
|
TypeSpec_Unsigned = 1 << 4,
|
||||||
|
} TypeSpec;
|
||||||
|
|
||||||
|
typedef struct Type Type;
|
||||||
|
|
||||||
|
struct Type {
|
||||||
|
TypeTy ty;
|
||||||
|
TypeSpec spec;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
Type* inner;
|
||||||
|
TypeSpec spec;
|
||||||
|
} pointer;
|
||||||
|
struct {
|
||||||
|
Type* return_type;
|
||||||
|
ARRAY_FIELD(Type*, params);
|
||||||
|
} function;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void type_print(FILE* file, const Type* type);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
Sym_Declar,
|
Sym_Declar,
|
||||||
|
Sym_Param,
|
||||||
} SymTy;
|
} SymTy;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SymTy ty;
|
SymTy ty;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
Type* type;
|
||||||
|
} declar;
|
||||||
|
struct {
|
||||||
|
Type* type;
|
||||||
|
size_t idx;
|
||||||
|
} param;
|
||||||
|
};
|
||||||
} Sym;
|
} Sym;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -22,7 +75,7 @@ void sema_free(Sema* s);
|
|||||||
void sema_scope_enter(Sema* s);
|
void sema_scope_enter(Sema* s);
|
||||||
void sema_scope_leave(Sema* s);
|
void sema_scope_leave(Sema* s);
|
||||||
|
|
||||||
void sema_function_enter(Sema* s, AstDeclar* declar);
|
void sema_function_enter(Sema* s, AstSpec spec, AstDeclar* declar);
|
||||||
void sema_function_leave(Sema* s);
|
void sema_function_leave(Sema* s);
|
||||||
|
|
||||||
void sema_visit_stmt(Sema* s, AstStmt* stmt);
|
void sema_visit_stmt(Sema* s, AstStmt* stmt);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user