Added $include.

This commit is contained in:
Christoffer Lerno
2022-12-29 16:12:03 +01:00
parent f122d290f1
commit ef7365224f
16 changed files with 118 additions and 9 deletions

View File

@@ -97,6 +97,7 @@ Decl *decl_new_with_type(const char *name, SourceSpan loc, DeclKind decl_type, V
case DECL_INITIALIZE:
case DECL_FINALIZE:
case DECL_CT_ECHO:
case DECL_CT_INCLUDE:
UNREACHABLE
}
Type *type = type_new(kind, name ? name : "$anon");
@@ -172,6 +173,8 @@ const char *decl_to_a_name(Decl *decl)
return "a static initializer";
case DECL_FINALIZE:
return "a static finalizer";
case DECL_CT_INCLUDE:
return "an include";
case DECL_VAR:
switch (decl->var.kind)
{

View File

@@ -76,7 +76,9 @@ static void compiler_lex(void)
VECEACH(global_context.sources, i)
{
bool loaded = false;
File *file = source_file_load(global_context.sources[i], &loaded);
const char *error;
File *file = source_file_load(global_context.sources[i], &loaded, &error);
if (!file) error_exit(error);
if (loaded) continue;
Lexer lexer = { .file = file };
lexer_init(&lexer);
@@ -97,7 +99,9 @@ void compiler_parse(void)
VECEACH(global_context.sources, i)
{
bool loaded = false;
File *file = source_file_load(global_context.sources[i], &loaded);
const char *error;
File *file = source_file_load(global_context.sources[i], &loaded, &error);
if (!file) error_exit(error);
if (loaded) continue;
global_context_clear_errors();

View File

@@ -393,6 +393,12 @@ typedef struct
Module *module;
} ImportDecl;
typedef struct
{
File *file;
Decl **decls;
} IncludeDecl;
typedef struct
{
TypeSize size;
@@ -696,6 +702,7 @@ typedef struct Decl_
BitStructDecl bitstruct;
};
};
IncludeDecl include;
Decl** body_params;
ImportDecl import;
VarDecl var;
@@ -2231,7 +2238,7 @@ void sema_shadow_error(Decl *decl, Decl *old);
bool sema_type_error_on_binop(Expr *expr);
File *source_file_by_id(FileId file);
File *source_file_load(const char *filename, bool *already_loaded);
File *source_file_load(const char *filename, bool *already_loaded, const char **error);
#define RANGE_EXTEND_PREV(x) do { (x)->span = extend_span_with_token((x)->span, c->prev_span); } while (0)

View File

@@ -148,6 +148,7 @@ void decl_register(Decl *decl)
case DECL_LABEL:
case DECL_DECLARRAY:
case DECL_BODYPARAM:
case DECL_CT_INCLUDE:
UNREACHABLE
case DECL_ATTRIBUTE:
case DECL_BITSTRUCT:
@@ -262,6 +263,7 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl)
UNREACHABLE
case DECL_CT_IF:
case DECL_CT_SWITCH:
case DECL_CT_INCLUDE:
vec_add(unit->ct_ifs, decl);
return;
case DECL_CT_ECHO:

View File

@@ -784,6 +784,8 @@ Decl *copy_decl(CopyStruct *c, Decl *decl)
{
case DECL_POISONED:
break;
case DECL_CT_INCLUDE:
break;
case DECL_INITIALIZE:
case DECL_FINALIZE:
MACRO_COPY_ASTID(copy->xxlizer.init);

View File

@@ -157,6 +157,7 @@ typedef enum
DECL_FINALIZE,
DECL_GENERIC,
DECL_IMPORT,
DECL_CT_INCLUDE,
DECL_LABEL,
DECL_MACRO,
DECL_STRUCT,
@@ -171,7 +172,7 @@ typedef enum
case DECL_DECLARRAY: case DECL_CT_IF: case DECL_CT_ELSE: case DECL_CT_ELIF: \
case DECL_CT_SWITCH: case DECL_CT_CASE: case DECL_ATTRIBUTE: case DECL_LABEL: \
case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_GENERIC: case DECL_INITIALIZE: \
case DECL_FINALIZE: case DECL_CT_ECHO
case DECL_FINALIZE: case DECL_CT_ECHO: case DECL_CT_INCLUDE
#define NON_RUNTIME_EXPR EXPR_DESIGNATOR: case EXPR_POISONED: \
case EXPR_TYPEINFO: case EXPR_CT_IDENT: case EXPR_HASH_IDENT: \

View File

@@ -1000,6 +1000,7 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
case DECL_FINALIZE:
case DECL_BODYPARAM:
case DECL_CT_ECHO:
case DECL_CT_INCLUDE:
UNREACHABLE;
}
UNREACHABLE

View File

@@ -6,6 +6,7 @@ static Decl *parse_const_declaration(ParseContext *c, Visibility visibility);
static inline Decl *parse_func_definition(ParseContext *c, Visibility visibility, AstId docs, bool is_interface);
static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl);
static inline Decl *parse_static_top_level(ParseContext *c);
static Decl *parse_include(ParseContext *c);
#define DECL_VAR_NEW(type__, var__, visible__) decl_new_var(symstr(c), c->span, type__, var__, visible__);
@@ -2531,6 +2532,68 @@ static bool parse_docs(ParseContext *c, AstId *docs_ref)
}
}
static Decl *parse_include(ParseContext *c)
{
SourceSpan loc = c->span;
Decl *decl = decl_new(DECL_CT_INCLUDE, NULL, loc, VISIBLE_LOCAL);
advance_and_verify(c, TOKEN_CT_INCLUDE);
CONSUME_OR_RET(TOKEN_LPAREN, poisoned_decl);
const char *str = symstr(c);
CONSUME_OR_RET(TOKEN_STRING, poisoned_decl);
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_decl);
CONSUME_EOS_OR_RET(poisoned_decl);
bool loaded;
const char *error;
char *path;
char *name;
if (file_namesplit(c->unit->file->full_path, &name, &path))
{
str = file_append_path(path, str);
}
File *file = source_file_load(str, &loaded, &error);
if (!file)
{
sema_error_at(loc, "Failed to load file %s: %s", str, error);
return poisoned_decl;
}
decl->include.file = file;
if (global_context.errors_found) return poisoned_decl;
Lexer current_lexer = c->lexer;
File *current_file = c->unit->file;
TokenType old_tok = c->tok;
TokenData old_data = c->data;
SourceSpan old_prev = c->prev_span;
SourceSpan old_span = c->span;
c->lexer = (Lexer){ .file = decl->include.file, .context = c };
lexer_init(&c->lexer);
// Prime everything
advance(c);
advance(c);
Decl **list = NULL;
while (!tok_is(c, TOKEN_EOF))
{
Decl *inner = parse_top_level_statement(c, &c);
if (!decl) continue;
if (!decl_ok(decl))
{
decl_poison(decl);
goto END;
}
vec_add(list, inner);
}
decl->include.decls = list;
END:
c->lexer = current_lexer;
c->tok = old_tok;
c->data = old_data;
c->prev_span = old_prev;
c->span = old_span;
c->unit->file = current_file;
return decl;
}
/**
* top_level_statement ::= visibility? top_level
*
@@ -2690,6 +2753,15 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref)
}
break;
}
case TOKEN_CT_INCLUDE:
if (!check_no_visibility_before(c, visibility)) return poisoned_decl;
if (docs)
{
SEMA_ERROR(astptr(docs), "Unexpected doc comment before $include, did you mean to use a regular comment?");
return poisoned_decl;
}
ASSIGN_DECL_OR_RET(decl, parse_include(c), poisoned_decl);
break;
case TOKEN_BITSTRUCT:
{
ASSIGN_DECL_OR_RET(decl, parse_bitstruct_declaration(c, visibility), poisoned_decl);

View File

@@ -5,6 +5,7 @@
#include "compiler_internal.h"
#include "parser_internal.h"
// --- Parser base methods
/**
@@ -55,6 +56,8 @@ bool consume(ParseContext *c, TokenType type, const char *message, ...)
// --- Extern functions
static bool parse_include(ParseContext *c, Decl *decl);
/**
* module? imports top_level_statement*
* @param c
@@ -79,6 +82,7 @@ static inline void parse_translation_unit(ParseContext *c)
}
}
/**
* Parse a file, generating a default context for it.
* More contexts may be created on demand during parsing.

View File

@@ -2901,6 +2901,7 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl)
case DECL_FAULTVALUE:
case DECL_DECLARRAY:
case DECL_BODYPARAM:
case DECL_CT_INCLUDE:
UNREACHABLE
}
decl->resolve_status = RESOLVE_DONE;

View File

@@ -547,6 +547,7 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
case DECL_BODYPARAM:
case DECL_INITIALIZE:
case DECL_FINALIZE:
case DECL_CT_INCLUDE:
UNREACHABLE
case DECL_POISONED:
return expr_poison(expr);

View File

@@ -182,6 +182,7 @@ static inline bool sema_analyse_top_level_if(SemaContext *context, Decl *ct_if)
return true;
}
static inline bool sema_analyse_top_level_switch(SemaContext *context, Decl *ct_switch)
{
Expr *cond = ct_switch->ct_switch_decl.expr;
@@ -303,6 +304,10 @@ void sema_analysis_pass_conditional_compilation(Module *module)
case DECL_CT_SWITCH:
success = sema_analyse_top_level_switch(&context, decl);
break;
case DECL_CT_INCLUDE:
sema_append_decls(context.unit, decl->include.decls);
success = true;
break;
default:
UNREACHABLE
}

View File

@@ -243,6 +243,7 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
case DECL_CT_ECHO:
case DECL_DECLARRAY:
case DECL_BODYPARAM:
case DECL_CT_INCLUDE:
UNREACHABLE
}
UNREACHABLE

View File

@@ -182,6 +182,7 @@ static void register_generic_decls(CompilationUnit *unit, Decl **decls)
case DECL_CT_ELIF:
case DECL_CT_ELSE:
case DECL_BODYPARAM:
case DECL_CT_INCLUDE:
UNREACHABLE
case DECL_MACRO:
case DECL_DEFINE:
@@ -242,7 +243,9 @@ void sema_analysis_run(void)
VECEACH(global_context.sources, i)
{
bool loaded = false;
File *file = source_file_load(global_context.sources[i], &loaded);
const char *error;
File *file = source_file_load(global_context.sources[i], &loaded, &error);
if (!file) error_exit(error);
if (loaded) continue;
if (!parse_file(file)) has_error = true;
}

View File

@@ -22,7 +22,7 @@ File *source_file_by_id(FileId file)
return global_context.loaded_sources[file];
}
File *source_file_load(const char *filename, bool *already_loaded)
File *source_file_load(const char *filename, bool *already_loaded, const char **error)
{
if (already_loaded) *already_loaded = false;
if (!global_context.loaded_sources) global_context.loaded_sources = VECNEW(File*, LEXER_FILES_START_CAPACITY);
@@ -31,7 +31,8 @@ File *source_file_load(const char *filename, bool *already_loaded)
if (!realpath(filename, full_path))
{
error_exit("Failed to resolve %s", filename);
*error = str_printf("Failed to resolve %s", filename);
return NULL;
}
VECEACH(global_context.loaded_sources, index)
@@ -44,7 +45,8 @@ File *source_file_load(const char *filename, bool *already_loaded)
}
if (vec_size(global_context.loaded_sources) == MAX_FILES)
{
error_exit("Exceeded max number of files %d", MAX_FILES);
*error = str_printf("Exceeded max number of files %d", MAX_FILES);
return NULL;
}
size_t size;

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.127"
#define COMPILER_VERSION "0.3.128"