add sema
This commit is contained in:
parent
48587d47de
commit
d43dc3539d
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
larpcc: main.c lex.c preproc.c collection.c parse.c ast_print.c resolve.c
|
larpcc: main.c lex.c preproc.c collection.c parse.c ast_print.c resolve.c sema.c
|
||||||
gcc $^ -o $@ -std=c23 -pedantic -Wall -Wextra -g -fsanitize=address -Werror=switch
|
gcc $^ -o $@ -std=c23 -pedantic -Wall -Wextra -g -fsanitize=address -Werror=switch
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include "not_stdio.h"
|
#include "not_stdio.h"
|
||||||
|
|
||||||
int main()
|
int main(void)
|
||||||
{
|
{
|
||||||
puts("hello world");
|
puts("hello world");
|
||||||
}
|
}
|
||||||
|
|||||||
2
lex.c
2
lex.c
@ -86,6 +86,8 @@ const char* tokty_str(TokTy ty)
|
|||||||
return "KwChar";
|
return "KwChar";
|
||||||
case Tok_KwConst:
|
case Tok_KwConst:
|
||||||
return "KwConst";
|
return "KwConst";
|
||||||
|
case Tok_KwVoid:
|
||||||
|
return "KwVoid";
|
||||||
case Tok_EndOfMacroInvocation:
|
case Tok_EndOfMacroInvocation:
|
||||||
return "EndOfMacroInvocation";
|
return "EndOfMacroInvocation";
|
||||||
}
|
}
|
||||||
|
|||||||
21
main.c
21
main.c
@ -2,6 +2,7 @@
|
|||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "resolve.h"
|
#include "resolve.h"
|
||||||
|
#include "sema.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -71,16 +72,18 @@ int main(int argc, char* argv[])
|
|||||||
TokStream tokstream;
|
TokStream tokstream;
|
||||||
tokstream_init(&tokstream, preproc, &tok_arena);
|
tokstream_init(&tokstream, preproc, &tok_arena);
|
||||||
|
|
||||||
|
Sema* sema = sema_new();
|
||||||
|
|
||||||
Arena ast_arena;
|
Arena ast_arena;
|
||||||
arena_init(&ast_arena, 4096);
|
arena_init(&ast_arena, 4096);
|
||||||
|
|
||||||
printf("--- ast ---\n");
|
printf("--- ast ---\n");
|
||||||
|
|
||||||
Parser* parser = parser_new(&tokstream, &ast_arena);
|
Parser* parser = parser_new(&tokstream, sema, &ast_arena);
|
||||||
|
|
||||||
Arena sym_arena;
|
// Arena sym_arena;
|
||||||
arena_init(&sym_arena, 4096);
|
// arena_init(&sym_arena, 4096);
|
||||||
Resolver* resolver = resolver_new(&sym_arena);
|
// Resolver* resolver = resolver_new(&sym_arena);
|
||||||
|
|
||||||
AstStmt* stmt;
|
AstStmt* stmt;
|
||||||
while (!parser_done(parser)) {
|
while (!parser_done(parser)) {
|
||||||
@ -90,16 +93,18 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
resolver_resolve_top_stmt(resolver, stmt);
|
// resolver_resolve_top_stmt(resolver, stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolver_free(resolver);
|
// resolver_free(resolver);
|
||||||
|
|
||||||
parser_free(parser);
|
parser_free(parser);
|
||||||
|
|
||||||
preproc_free(preproc);
|
preproc_free(preproc);
|
||||||
arena_deinit(&tok_arena);
|
arena_deinit(&tok_arena);
|
||||||
|
|
||||||
arena_deinit(&ast_arena);
|
arena_deinit(&ast_arena);
|
||||||
arena_deinit(&sym_arena);
|
// arena_deinit(&sym_arena);
|
||||||
|
|
||||||
|
sema_free(sema);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
parse.c
35
parse.c
@ -2,6 +2,7 @@
|
|||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
#include "resolve.h"
|
#include "resolve.h"
|
||||||
|
#include "sema.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -115,6 +116,7 @@ static void kwmatcher_init(KwMatcher* m, TokStream* tokstream)
|
|||||||
{ Tok_KwInt, "int" },
|
{ Tok_KwInt, "int" },
|
||||||
{ Tok_KwChar, "char" },
|
{ Tok_KwChar, "char" },
|
||||||
{ Tok_KwConst, "const" },
|
{ Tok_KwConst, "const" },
|
||||||
|
{ Tok_KwVoid, "void" },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(kws) / sizeof(kws[0]); ++i) {
|
for (size_t i = 0; i < sizeof(kws) / sizeof(kws[0]); ++i) {
|
||||||
@ -150,6 +152,7 @@ typedef enum : unsigned int {
|
|||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
KwMatcher kwmatcher;
|
KwMatcher kwmatcher;
|
||||||
|
Sema* sema;
|
||||||
Arena* arena;
|
Arena* arena;
|
||||||
Arena sym_arena;
|
Arena sym_arena;
|
||||||
|
|
||||||
@ -160,12 +163,13 @@ struct Parser {
|
|||||||
ParserFlags flags;
|
ParserFlags flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser* parser_new(TokStream* tokstream, Arena* arena)
|
Parser* parser_new(TokStream* tokstream, Sema* sema, Arena* arena)
|
||||||
{
|
{
|
||||||
Parser* p = malloc(sizeof(Parser));
|
Parser* p = malloc(sizeof(Parser));
|
||||||
|
|
||||||
*p = (Parser) {
|
*p = (Parser) {
|
||||||
.kwmatcher = { },
|
.kwmatcher = { },
|
||||||
|
.sema = sema,
|
||||||
.arena = arena,
|
.arena = arena,
|
||||||
.sym_arena = { },
|
.sym_arena = { },
|
||||||
|
|
||||||
@ -194,20 +198,21 @@ static void step(Parser* p)
|
|||||||
p->curr = kwmatcher_next(&p->kwmatcher);
|
p->curr = kwmatcher_next(&p->kwmatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_NEW(TYPE, FN_NAME) \
|
#define DEFINE_NEW(TYPE, FN_NAME, POST) \
|
||||||
[[maybe_unused]] static TYPE* new_##FN_NAME(Parser* p, TYPE init) \
|
[[maybe_unused]] static TYPE* new_##FN_NAME(Parser* p, TYPE init) \
|
||||||
{ \
|
{ \
|
||||||
TYPE* val = arena_alloc(p->arena, sizeof(TYPE)); \
|
TYPE* val = arena_alloc(p->arena, sizeof(TYPE)); \
|
||||||
*val = init; \
|
*val = init; \
|
||||||
|
POST; \
|
||||||
return val; \
|
return val; \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_NEW(AstStmt, stmt)
|
DEFINE_NEW(AstStmt, stmt, { sema_visit_stmt(p->sema, val); })
|
||||||
DEFINE_NEW(AstDecl, decl)
|
DEFINE_NEW(AstDecl, decl, { })
|
||||||
DEFINE_NEW(AstDeclar, declar)
|
DEFINE_NEW(AstDeclar, declar, { })
|
||||||
DEFINE_NEW(AstExpr, expr)
|
DEFINE_NEW(AstExpr, expr, { sema_visit_expr(p->sema, val); })
|
||||||
|
|
||||||
DEFINE_NEW(AstStmtBlock, stmt_block)
|
DEFINE_NEW(AstStmtBlock, stmt_block, { })
|
||||||
|
|
||||||
static AstStmtBlock* parse_stmt_block(Parser* p);
|
static AstStmtBlock* parse_stmt_block(Parser* p);
|
||||||
static AstStmt* parse_stmt(Parser* p);
|
static AstStmt* parse_stmt(Parser* p);
|
||||||
@ -260,8 +265,8 @@ static bool is_defty_ident(Parser* p, Tok tok)
|
|||||||
{
|
{
|
||||||
if (tok.ty != Tok_Ident)
|
if (tok.ty != Tok_Ident)
|
||||||
return false;
|
return false;
|
||||||
Sym* sym = syms_get(p->syms, tok.text);
|
OldSym* sym = syms_get(p->syms, tok.text);
|
||||||
return sym && sym->ty == Sym_Typedef;
|
return sym && sym->ty == OldSym_Typedef;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AstStmt* parse_stmt(Parser* p)
|
static AstStmt* parse_stmt(Parser* p)
|
||||||
@ -322,7 +327,11 @@ static AstDecl* parse_decl(Parser* p, bool is_param)
|
|||||||
bool multi_allowed = !is_param;
|
bool multi_allowed = !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]);
|
||||||
function_body = parse_stmt_block(p);
|
function_body = parse_stmt_block(p);
|
||||||
|
sema_function_leave(p->sema);
|
||||||
|
|
||||||
multi_allowed = false;
|
multi_allowed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +441,9 @@ static AstDeclar* parse_declar_l3(Parser* p)
|
|||||||
|
|
||||||
ARRAY_VAR(AstDecl*, params);
|
ARRAY_VAR(AstDecl*, params);
|
||||||
|
|
||||||
if (p->curr.ty != Tok_Eof && p->curr.ty != ')') {
|
if (p->curr.ty == Tok_KwVoid) {
|
||||||
|
step(p);
|
||||||
|
} else if (p->curr.ty != Tok_Eof && p->curr.ty != ')') {
|
||||||
AstDecl* d = parse_decl(p, true);
|
AstDecl* d = parse_decl(p, true);
|
||||||
ARENA_ARRAY_VAR_PUSH(p->arena, params, &d);
|
ARENA_ARRAY_VAR_PUSH(p->arena, params, &d);
|
||||||
|
|
||||||
@ -509,8 +520,8 @@ static AstSpec parse_decl_spec(Parser* p)
|
|||||||
while (true) {
|
while (true) {
|
||||||
switch (p->curr.ty) {
|
switch (p->curr.ty) {
|
||||||
case Tok_Ident: {
|
case Tok_Ident: {
|
||||||
Sym* sym = syms_get(p->syms, p->curr.text);
|
OldSym* sym = syms_get(p->syms, p->curr.text);
|
||||||
if (!sym || sym->ty != Sym_Typedef)
|
if (!sym || sym->ty != OldSym_Typedef)
|
||||||
break;
|
break;
|
||||||
spec |= AstSpec_DefTy;
|
spec |= AstSpec_DefTy;
|
||||||
step(p);
|
step(p);
|
||||||
|
|||||||
8
parse.h
8
parse.h
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
|
#include "sema.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
char* read_textfile(const char* filename);
|
char* read_textfile(const char* filename);
|
||||||
@ -47,6 +48,7 @@ typedef enum {
|
|||||||
Tok_Char,
|
Tok_Char,
|
||||||
Tok_Whitespace,
|
Tok_Whitespace,
|
||||||
Tok_HeaderName,
|
Tok_HeaderName,
|
||||||
|
|
||||||
Tok_Eol = '\n', // NOTE: has value 10
|
Tok_Eol = '\n', // NOTE: has value 10
|
||||||
Tok_Semicolon = ';',
|
Tok_Semicolon = ';',
|
||||||
Tok_LParen = '(',
|
Tok_LParen = '(',
|
||||||
@ -57,12 +59,14 @@ typedef enum {
|
|||||||
Tok_Asterisk = '*',
|
Tok_Asterisk = '*',
|
||||||
Tok_Hashtag = '#',
|
Tok_Hashtag = '#',
|
||||||
|
|
||||||
Tok_KwInt,
|
Tok_KwInt = 256,
|
||||||
Tok_KwChar,
|
Tok_KwChar,
|
||||||
Tok_KwConst,
|
Tok_KwConst,
|
||||||
|
Tok_KwVoid,
|
||||||
|
|
||||||
// used internally in preprocessor
|
// used internally in preprocessor
|
||||||
Tok_EndOfMacroInvocation,
|
Tok_EndOfMacroInvocation,
|
||||||
|
|
||||||
} TokTy;
|
} TokTy;
|
||||||
|
|
||||||
const char* tokty_str(TokTy ty);
|
const char* tokty_str(TokTy ty);
|
||||||
@ -105,7 +109,7 @@ Tok tokstream_next(TokStream* s);
|
|||||||
|
|
||||||
typedef struct Parser Parser;
|
typedef struct Parser Parser;
|
||||||
|
|
||||||
Parser* parser_new(TokStream* tokstream, Arena* arena);
|
Parser* parser_new(TokStream* tokstream, Sema* sema, Arena* arena);
|
||||||
void parser_free(Parser* p);
|
void parser_free(Parser* p);
|
||||||
AstStmt* parser_parse_stmt(Parser* p);
|
AstStmt* parser_parse_stmt(Parser* p);
|
||||||
bool parser_done(Parser* p);
|
bool parser_done(Parser* p);
|
||||||
|
|||||||
62
resolve.c
62
resolve.c
@ -17,7 +17,7 @@ Syms* syms_new()
|
|||||||
};
|
};
|
||||||
|
|
||||||
ARRAY_FIELD_PUSH(s, maps, &(Hashmap) { });
|
ARRAY_FIELD_PUSH(s, maps, &(Hashmap) { });
|
||||||
hashmap_init(&s->maps[0], sizeof(Sym*));
|
hashmap_init(&s->maps[0], sizeof(OldSym*));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ void syms_free(Syms* s)
|
|||||||
void syms_push_scope(Syms* s)
|
void syms_push_scope(Syms* s)
|
||||||
{
|
{
|
||||||
ARRAY_FIELD_PUSH(s, maps, &(Hashmap) { });
|
ARRAY_FIELD_PUSH(s, maps, &(Hashmap) { });
|
||||||
hashmap_init(&s->maps[s->maps_size - 1], sizeof(Sym*));
|
hashmap_init(&s->maps[s->maps_size - 1], sizeof(OldSym*));
|
||||||
}
|
}
|
||||||
|
|
||||||
void syms_pop_scope(Syms* s)
|
void syms_pop_scope(Syms* s)
|
||||||
@ -43,60 +43,21 @@ void syms_pop_scope(Syms* s)
|
|||||||
s->maps_size -= 1;
|
s->maps_size -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void syms_define(Syms* s, const char* ident, Sym* sym)
|
void syms_define(Syms* s, const char* ident, OldSym* sym)
|
||||||
{
|
{
|
||||||
Hashmap* m = &s->maps[s->maps_size - 1];
|
Hashmap* m = &s->maps[s->maps_size - 1];
|
||||||
hashmap_set(m, ident, &sym);
|
hashmap_set(m, ident, &sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sym* syms_get(Syms* s, const char* ident)
|
OldSym* syms_get(Syms* s, const char* ident)
|
||||||
{
|
{
|
||||||
Sym** res;
|
OldSym** res;
|
||||||
for (size_t i = 0; i < s->maps_size; ++i)
|
for (size_t i = 0; i < s->maps_size; ++i)
|
||||||
if ((res = hashmap_get(&s->maps[s->maps_size - i - 1], ident)))
|
if ((res = hashmap_get(&s->maps[s->maps_size - i - 1], ident)))
|
||||||
return *res;
|
return *res;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_sym(Sym* s)
|
|
||||||
{
|
|
||||||
switch (s->ty) {
|
|
||||||
case Sym_Typedef:
|
|
||||||
printf("Typedef");
|
|
||||||
break;
|
|
||||||
case Sym_Declarator:
|
|
||||||
printf("Declarator");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SymPrinter {
|
|
||||||
int depth;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void print_sym_hashmap(void* self, const char* key, void* val)
|
|
||||||
{
|
|
||||||
struct SymPrinter* p = self;
|
|
||||||
Sym* sym = *(Sym**)val;
|
|
||||||
|
|
||||||
printf(" ");
|
|
||||||
for (int i = 0; i < p->depth; ++i)
|
|
||||||
printf(" ");
|
|
||||||
printf("'%s' -> ", key);
|
|
||||||
print_sym(sym);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void syms_print(Syms* s)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < s->maps_size; ++i) {
|
|
||||||
struct SymPrinter p = {
|
|
||||||
.depth = i,
|
|
||||||
};
|
|
||||||
hashmap_for_each(&s->maps[i], print_sym_hashmap, &p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum : unsigned int {
|
typedef enum : unsigned int {
|
||||||
ResolverFlags_InTypedef,
|
ResolverFlags_InTypedef,
|
||||||
} ResolverFlags;
|
} ResolverFlags;
|
||||||
@ -130,7 +91,7 @@ Resolver* resolver_new(Arena* arena)
|
|||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
keymap_init(&r->resol_map, sizeof(Sym*));
|
keymap_init(&r->resol_map, sizeof(OldSym*));
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -226,9 +187,9 @@ static AstVisitorResult visit_declar(AstVisitor* v, AstDeclar* node)
|
|||||||
if (node->ty == AstDeclar_Ident) {
|
if (node->ty == AstDeclar_Ident) {
|
||||||
assert(r->current_decl_stmt);
|
assert(r->current_decl_stmt);
|
||||||
|
|
||||||
Sym* sym = arena_alloc(r->arena, sizeof(Sym));
|
OldSym* sym = arena_alloc(r->arena, sizeof(OldSym));
|
||||||
*sym = (Sym) {
|
*sym = (OldSym) {
|
||||||
.ty = Sym_Declarator,
|
.ty = OldSym_Declarator,
|
||||||
.declarator = {
|
.declarator = {
|
||||||
.stmt = r->current_decl_stmt,
|
.stmt = r->current_decl_stmt,
|
||||||
.declar = node,
|
.declar = node,
|
||||||
@ -247,15 +208,12 @@ static AstVisitorResult visit_expr(AstVisitor* v, AstExpr* node)
|
|||||||
|
|
||||||
if (node->ty == AstExpr_Ident) {
|
if (node->ty == AstExpr_Ident) {
|
||||||
|
|
||||||
Sym* sym = syms_get(r->ord_syms, node->ident);
|
OldSym* sym = syms_get(r->ord_syms, node->ident);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"error: use of undeclared '%s' on line %d\n",
|
"error: use of undeclared '%s' on line %d\n",
|
||||||
node->ident,
|
node->ident,
|
||||||
node->loc.line);
|
node->loc.line);
|
||||||
|
|
||||||
syms_print(r->ord_syms);
|
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
resolve.h
14
resolve.h
@ -5,19 +5,19 @@
|
|||||||
#include "collection.h"
|
#include "collection.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
Sym_Typedef,
|
OldSym_Typedef,
|
||||||
Sym_Declarator,
|
OldSym_Declarator,
|
||||||
} SymTy;
|
} OldSymTy;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SymTy ty;
|
OldSymTy ty;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
AstStmt* stmt;
|
AstStmt* stmt;
|
||||||
AstDeclar* declar;
|
AstDeclar* declar;
|
||||||
} declarator;
|
} declarator;
|
||||||
};
|
};
|
||||||
} Sym;
|
} OldSym;
|
||||||
|
|
||||||
typedef struct Syms Syms;
|
typedef struct Syms Syms;
|
||||||
|
|
||||||
@ -27,8 +27,8 @@ void syms_free(Syms* s);
|
|||||||
void syms_push_scope(Syms* s);
|
void syms_push_scope(Syms* s);
|
||||||
void syms_pop_scope(Syms* s);
|
void syms_pop_scope(Syms* s);
|
||||||
|
|
||||||
void syms_define(Syms* s, const char* ident, Sym* sym);
|
void syms_define(Syms* s, const char* ident, OldSym* sym);
|
||||||
Sym* syms_get(Syms* s, const char* ident);
|
OldSym* syms_get(Syms* s, const char* ident);
|
||||||
|
|
||||||
typedef struct Resolver Resolver;
|
typedef struct Resolver Resolver;
|
||||||
|
|
||||||
|
|||||||
106
sema.c
Normal file
106
sema.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include "sema.h"
|
||||||
|
#include "ast.h"
|
||||||
|
#include "collection.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Hashmap ord_syms;
|
||||||
|
Hashmap tag_syms;
|
||||||
|
} Rib;
|
||||||
|
|
||||||
|
static void rib_init(Rib* r)
|
||||||
|
{
|
||||||
|
*r = (Rib) {
|
||||||
|
.ord_syms = { },
|
||||||
|
.tag_syms = { },
|
||||||
|
};
|
||||||
|
hashmap_init(&r->ord_syms, sizeof(Sym*));
|
||||||
|
hashmap_init(&r->tag_syms, sizeof(Sym*));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rib_deinit(Rib* r)
|
||||||
|
{
|
||||||
|
hashmap_deinit(&r->ord_syms);
|
||||||
|
hashmap_deinit(&r->tag_syms);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Sema {
|
||||||
|
Arena sym_arena;
|
||||||
|
ARRAY_FIELD(Rib, ribs);
|
||||||
|
Hashmap labels;
|
||||||
|
};
|
||||||
|
|
||||||
|
Sema* sema_new(void)
|
||||||
|
{
|
||||||
|
Sema* s = malloc(sizeof(Sema));
|
||||||
|
*s = (Sema) {
|
||||||
|
.sym_arena = { },
|
||||||
|
ARRAY_FIELD_INIT(ribs),
|
||||||
|
.labels = { },
|
||||||
|
};
|
||||||
|
|
||||||
|
arena_init(&s->sym_arena, 1024);
|
||||||
|
|
||||||
|
ARRAY_FIELD_PUSH(s, ribs, (&(Rib) { }));
|
||||||
|
rib_init(&s->ribs[0]);
|
||||||
|
|
||||||
|
hashmap_init(&s->labels, sizeof(LabelSym*));
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_free(Sema* s)
|
||||||
|
{
|
||||||
|
arena_deinit(&s->sym_arena);
|
||||||
|
for (size_t i = 0; i < s->ribs_size; ++i)
|
||||||
|
rib_deinit(&s->ribs[i]);
|
||||||
|
if (s->ribs)
|
||||||
|
free(s->ribs);
|
||||||
|
hashmap_deinit(&s->labels);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_scope_enter(Sema* s)
|
||||||
|
{
|
||||||
|
ARRAY_FIELD_PUSH(s, ribs, (&(Rib) { }));
|
||||||
|
rib_init(&s->ribs[s->ribs_size - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_scope_leave(Sema* s)
|
||||||
|
{
|
||||||
|
assert(s->ribs_size > 0);
|
||||||
|
rib_deinit(&s->ribs[s->ribs_size - 1]);
|
||||||
|
s->ribs_size -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_function_enter(Sema* s, AstDeclar* declar)
|
||||||
|
{
|
||||||
|
assert(declar->ty == AstDeclar_Function);
|
||||||
|
|
||||||
|
// clear label map
|
||||||
|
hashmap_deinit(&s->labels);
|
||||||
|
hashmap_init(&s->labels, sizeof(LabelSym*));
|
||||||
|
|
||||||
|
sema_scope_enter(s);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < declar->function.params_size; ++i) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_function_leave(Sema* s)
|
||||||
|
{
|
||||||
|
sema_scope_leave(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_visit_function_declar(Sema* s, AstDeclar* declar)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_visit_stmt(Sema* s, AstStmt* stmt)
|
||||||
|
{
|
||||||
|
if (stmt->ty == AstStmt_Decl) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
void sema_visit_expr(Sema* s, AstExpr* expr)
|
||||||
|
{
|
||||||
|
}
|
||||||
31
sema.h
Normal file
31
sema.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef SEMA_H
|
||||||
|
#define SEMA_H
|
||||||
|
|
||||||
|
#include "ast.h"
|
||||||
|
typedef enum {
|
||||||
|
Sym_Declar,
|
||||||
|
} SymTy;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SymTy ty;
|
||||||
|
} Sym;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int _;
|
||||||
|
} LabelSym;
|
||||||
|
|
||||||
|
typedef struct Sema Sema;
|
||||||
|
|
||||||
|
Sema* sema_new(void);
|
||||||
|
void sema_free(Sema* s);
|
||||||
|
|
||||||
|
void sema_scope_enter(Sema* s);
|
||||||
|
void sema_scope_leave(Sema* s);
|
||||||
|
|
||||||
|
void sema_function_enter(Sema* s, AstDeclar* declar);
|
||||||
|
void sema_function_leave(Sema* s);
|
||||||
|
|
||||||
|
void sema_visit_stmt(Sema* s, AstStmt* stmt);
|
||||||
|
void sema_visit_expr(Sema* s, AstExpr* expr);
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
x
Reference in New Issue
Block a user