Simplify code by making name := use ... a Use AST instead of a Declare

This commit is contained in:
Bruce Hill 2024-09-27 14:56:24 -04:00
parent 9b15799e73
commit ca93e6f3cb
5 changed files with 24 additions and 34 deletions

2
ast.c
View File

@ -156,7 +156,7 @@ CORD ast_to_xml(ast_t *ast)
T(Optional, "<Optional>%r</Optional>", ast_to_xml(data.value))
T(NonOptional, "<NonOptional>%r</NonOptional>", ast_to_xml(data.value))
T(DocTest, "<DocTest>%r<output>%r</output></DocTest>", optional_tagged("expression", data.expr), xml_escape(data.output))
T(Use, "<Use>%r</Use>", xml_escape(data.path))
T(Use, "<Use>%r%r</Use>", optional_tagged("var", data.var), xml_escape(data.path))
T(InlineCCode, "<InlineCode>%r</InlineCode>", xml_escape(data.code))
default: return "???";
#undef T

1
ast.h
View File

@ -311,6 +311,7 @@ struct ast_s {
bool skip_source:1;
} DocTest;
struct {
ast_t *var;
const char *path;
enum { USE_LOCAL, USE_MODULE, USE_SHARED_OBJECT, USE_HEADER, USE_C_CODE, USE_ASM } what;
} Use;

View File

@ -569,9 +569,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
}
case Declare: {
auto decl = Match(ast, Declare);
if (decl->value->tag == Use) {
return compile_statement(env, decl->value);
} else if (streq(Match(decl->var, Var)->name, "_")) { // Explicit discard
if (streq(Match(decl->var, Var)->name, "_")) { // Explicit discard
return CORD_all("(void)", compile(env, decl->value), ";");
} else {
type_t *t = get_type(env, decl->value);
@ -3584,7 +3582,7 @@ CORD compile_file(env_t *env, ast_t *ast)
type_t *t = get_type(env, decl->value);
if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType)
code_err(stmt->ast, "You can't declare a variable with a %T value", t);
if (!(decl->value->tag == Use || is_constant(env, decl->value))) {
if (!is_constant(env, decl->value)) {
CORD val_code = compile_maybe_incref(env, decl->value);
if (t->tag == FunctionType) {
assert(promote(env, &val_code, t, Type(ClosureType, t)));
@ -3609,9 +3607,7 @@ CORD compile_file(env_t *env, ast_t *ast)
CORD full_name = CORD_all(namespace_prefix(env, env->namespace), decl_name);
bool is_private = (decl_name[0] == '_');
type_t *t = get_type(env, decl->value);
if (decl->value->tag == Use) {
assert(compile_statement(env, stmt->ast) == CORD_EMPTY);
} else if (!is_constant(env, decl->value)) {
if (!is_constant(env, decl->value)) {
env->code->staticdefs = CORD_all(
env->code->staticdefs,
"static bool ", full_name, "$initialized = false;\n",
@ -3665,9 +3661,6 @@ CORD compile_statement_header(env_t *env, ast_t *ast)
switch (ast->tag) {
case Declare: {
auto decl = Match(ast, Declare);
if (decl->value->tag == Use)
return compile_statement_header(env, decl->value);
const char *decl_name = Match(decl->var, Var)->name;
bool is_private = (decl_name[0] == '_');
if (is_private)

28
parse.c
View File

@ -133,7 +133,6 @@ static PARSER(parse_table);
static PARSER(parse_term);
static PARSER(parse_term_no_suffix);
static PARSER(parse_text);
static PARSER(parse_top_declaration);
static PARSER(parse_update);
static PARSER(parse_use);
static PARSER(parse_var);
@ -1750,20 +1749,6 @@ PARSER(parse_declaration) {
return NewAST(ctx->file, start, pos, Declare, .var=var, .value=val);
}
PARSER(parse_top_declaration) {
const char *start = pos;
ast_t *var = parse_var(ctx, pos);
if (!var) return NULL;
pos = var->end;
spaces(&pos);
if (!match(&pos, ":=")) return NULL;
spaces(&pos);
ast_t *val = optional(ctx, &pos, parse_use);
if (!val) val = optional(ctx, &pos, parse_extended_expr);
if (!val) parser_err(ctx, pos, strchrnul(pos, '\n'), "This declaration value didn't parse");
return NewAST(ctx->file, start, pos, Declare, .var=var, .value=val);
}
PARSER(parse_update) {
const char *start = pos;
ast_t *lhs = optional(ctx, &pos, parse_expr);
@ -1980,7 +1965,7 @@ PARSER(parse_file_body) {
||(stmt=optional(ctx, &pos, parse_use))
||(stmt=optional(ctx, &pos, parse_extern))
||(stmt=optional(ctx, &pos, parse_inline_c))
||(stmt=optional(ctx, &pos, parse_top_declaration)))
||(stmt=optional(ctx, &pos, parse_declaration)))
{
statements = new(ast_list_t, .ast=stmt, .next=statements);
pos = stmt->end;
@ -2348,6 +2333,15 @@ PARSER(parse_say) {
PARSER(parse_use) {
const char *start = pos;
ast_t *var = parse_var(ctx, pos);
if (var) {
pos = var->end;
spaces(&pos);
if (!match(&pos, ":=")) return NULL;
spaces(&pos);
}
if (!match_word(&pos, "use")) return NULL;
spaces(&pos);
size_t name_len = strcspn(pos, " \t\r\n;");
@ -2384,7 +2378,7 @@ PARSER(parse_use) {
name = hash;
}
}
return NewAST(ctx->file, start, pos, Use, .path=name, .what=what);
return NewAST(ctx->file, start, pos, Use, .var=var, .path=name, .what=what);
}
ast_t *parse_file(const char *path, jmp_buf *on_err) {

View File

@ -255,11 +255,7 @@ void bind_statement(env_t *env, ast_t *statement)
return;
if (get_binding(env, name))
code_err(decl->var, "A %T called '%s' has already been defined", get_binding(env, name)->type, name);
if (decl->value->tag == Use) {
(void)load_module(env, decl->value);
} else {
bind_statement(env, decl->value);
}
bind_statement(env, decl->value);
type_t *type = get_type(env, decl->value);
if (!type)
code_err(decl->value, "I couldn't figure out the type of this value");
@ -394,9 +390,15 @@ void bind_statement(env_t *env, ast_t *statement)
if (Table$str_get(*env->types, entry->name))
continue;
//code_err(statement, "This module imports a type called '%s', which would clobber another type", entry->name);
Table$str_set(env->types, entry->name, entry->type);
}
ast_t *var = Match(statement, Use)->var;
if (var) {
type_t *type = get_type(env, statement);
assert(type);
set_binding(env, Match(var, Var)->name, new(binding_t, .type=type));
}
break;
}
case Extern: {