Code refactor to aid development

This commit is contained in:
gingerBill
2022-02-05 15:17:47 +00:00
parent 67ce0ec29f
commit c6ab8f82c8
+333 -263
View File
@@ -7086,109 +7086,11 @@ void add_to_seen_map(CheckerContext *ctx, SeenMap *seen, Operand const &x) {
add_constant_switch_case(ctx, seen, x); add_constant_switch_case(ctx, seen, x);
} }
ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ast_node(bd, BasicDirective, node);
ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { ExprKind kind = Expr_Expr;
u32 prev_state_flags = c->state_flags;
defer (c->state_flags = prev_state_flags);
if (node->state_flags != 0) {
u32 in = node->state_flags;
u32 out = c->state_flags;
if (in & StateFlag_no_bounds_check) {
out |= StateFlag_no_bounds_check;
out &= ~StateFlag_bounds_check;
} else if (in & StateFlag_bounds_check) {
out |= StateFlag_bounds_check;
out &= ~StateFlag_no_bounds_check;
}
if (in & StateFlag_no_type_assert) {
out |= StateFlag_no_type_assert;
out &= ~StateFlag_type_assert;
} else if (in & StateFlag_type_assert) {
out |= StateFlag_type_assert;
out &= ~StateFlag_no_type_assert;
}
c->state_flags = out;
}
ExprKind kind = Expr_Stmt;
o->mode = Addressing_Invalid;
o->type = t_invalid;
switch (node->kind) {
default:
return kind;
case_ast_node(be, BadExpr, node)
return kind;
case_end;
case_ast_node(i, Implicit, node)
switch (i->kind) {
case Token_context:
{
if (c->proc_name.len == 0 && c->curr_proc_sig == nullptr) {
error(node, "'context' is only allowed within procedures %p", c->curr_proc_decl);
return kind;
}
if (unparen_expr(c->assignment_lhs_hint) == node) {
c->scope->flags |= ScopeFlag_ContextDefined;
}
if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
error(node, "'context' has not been defined within this scope");
// Continue with value
}
init_core_context(c->checker);
o->mode = Addressing_Context;
o->type = t_context;
}
break;
default:
error(node, "Illegal implicit name '%.*s'", LIT(i->string));
return kind;
}
case_end;
case_ast_node(i, Ident, node);
check_ident(c, o, node, nullptr, type_hint, false);
case_end;
case_ast_node(u, Undef, node);
o->mode = Addressing_Value;
o->type = t_untyped_undef;
case_end;
case_ast_node(bl, BasicLit, node);
Type *t = t_invalid;
switch (node->tav.value.kind) {
case ExactValue_String: t = t_untyped_string; break;
case ExactValue_Float: t = t_untyped_float; break;
case ExactValue_Complex: t = t_untyped_complex; break;
case ExactValue_Quaternion: t = t_untyped_quaternion; break;
case ExactValue_Integer:
t = t_untyped_integer;
if (bl->token.kind == Token_Rune) {
t = t_untyped_rune;
}
break;
default:
GB_PANIC("Unhandled value type for basic literal");
break;
}
o->mode = Addressing_Constant;
o->type = t;
o->value = node->tav.value;
case_end;
case_ast_node(bd, BasicDirective, node);
o->mode = Addressing_Constant; o->mode = Addressing_Constant;
String name = bd->name.string; String name = bd->name.string;
if (name == "file") { if (name == "file") {
@@ -7235,55 +7137,13 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
} }
} }
case_end;
case_ast_node(pg, ProcGroup, node);
error(node, "Illegal use of a procedure group");
o->mode = Addressing_Invalid;
case_end;
case_ast_node(pl, ProcLit, node);
CheckerContext ctx = *c;
DeclInfo *decl = nullptr;
Type *type = alloc_type(Type_Proc);
check_open_scope(&ctx, pl->type);
{
decl = make_decl_info(ctx.scope, ctx.decl);
decl->proc_lit = node;
ctx.decl = decl;
defer (ctx.decl = ctx.decl->parent);
if (pl->tags != 0) {
error(node, "A procedure literal cannot have tags");
pl->tags = 0; // TODO(bill): Should I zero this?!
}
check_procedure_type(&ctx, type, pl->type);
if (!is_type_proc(type)) {
gbString str = expr_to_string(node);
error(node, "Invalid procedure literal '%s'", str);
gb_string_free(str);
check_close_scope(&ctx);
return kind; return kind;
} }
if (pl->body == nullptr) { ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
error(node, "A procedure literal must have a body"); ExprKind kind = Expr_Expr;
return kind;
}
pl->decl = decl;
check_procedure_later(&ctx, ctx.file, empty_token, decl, type, pl->body, pl->tags);
}
check_close_scope(&ctx);
o->mode = Addressing_Value;
o->type = type;
case_end;
case_ast_node(te, TernaryIfExpr, node);
Operand cond = {Addressing_Invalid}; Operand cond = {Addressing_Invalid};
ast_node(te, TernaryIfExpr, node);
check_expr(c, &cond, te->cond); check_expr(c, &cond, te->cond);
node->viral_state_flags |= te->cond->viral_state_flags; node->viral_state_flags |= te->cond->viral_state_flags;
@@ -7342,10 +7202,13 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
update_untyped_expr_type(c, node, type_hint, !is_type_untyped(type_hint)); update_untyped_expr_type(c, node, type_hint, !is_type_untyped(type_hint));
} }
} }
case_end; return kind;
}
case_ast_node(te, TernaryWhenExpr, node); ExprKind check_ternary_when_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr;
Operand cond = {}; Operand cond = {};
ast_node(te, TernaryWhenExpr, node);
check_expr(c, &cond, te->cond); check_expr(c, &cond, te->cond);
node->viral_state_flags |= te->cond->viral_state_flags; node->viral_state_flags |= te->cond->viral_state_flags;
@@ -7366,9 +7229,12 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
return kind; return kind;
} }
} }
case_end; return kind;
}
ExprKind check_or_else_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ast_node(oe, OrElseExpr, node);
case_ast_node(oe, OrElseExpr, node);
String name = oe->token.string; String name = oe->token.string;
Ast *arg = oe->x; Ast *arg = oe->x;
Ast *default_value = oe->y; Ast *default_value = oe->y;
@@ -7410,9 +7276,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->type = left_type; o->type = left_type;
o->expr = node; o->expr = node;
return Expr_Expr; return Expr_Expr;
case_end; }
ExprKind check_or_return_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ast_node(re, OrReturnExpr, node);
case_ast_node(re, OrReturnExpr, node);
String name = re->token.string; String name = re->token.string;
Operand x = {}; Operand x = {};
check_multi_expr_with_type_hint(c, &x, re->expr, type_hint); check_multi_expr_with_type_hint(c, &x, re->expr, type_hint);
@@ -7487,9 +7355,12 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
} }
return Expr_Expr; return Expr_Expr;
case_end; }
ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr;
ast_node(cl, CompoundLit, node);
case_ast_node(cl, CompoundLit, node);
Type *type = type_hint; Type *type = type_hint;
if (type != nullptr && is_type_untyped(type)) { if (type != nullptr && is_type_untyped(type)) {
type = nullptr; type = nullptr;
@@ -8442,25 +8313,12 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->mode = Addressing_Value; o->mode = Addressing_Value;
} }
o->type = type; o->type = type;
case_end; return kind;
case_ast_node(pe, ParenExpr, node);
kind = check_expr_base(c, o, pe->expr, type_hint);
node->viral_state_flags |= pe->expr->viral_state_flags;
o->expr = node;
case_end;
case_ast_node(te, TagExpr, node);
String name = te->name.string;
error(node, "Unknown tag expression, #%.*s", LIT(name));
if (te->expr) {
kind = check_expr_base(c, o, te->expr, type_hint);
node->viral_state_flags |= te->expr->viral_state_flags;
} }
o->expr = node;
case_end;
case_ast_node(ta, TypeAssertion, node); ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr;
ast_node(ta, TypeAssertion, node);
check_expr(c, o, ta->expr); check_expr(c, o, ta->expr);
node->viral_state_flags |= ta->expr->viral_state_flags; node->viral_state_flags |= ta->expr->viral_state_flags;
@@ -8580,95 +8438,15 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
} }
} }
if ((c->state_flags & StateFlag_no_type_assert) == 0) {
add_package_dependency(c, "runtime", "type_assertion_check"); add_package_dependency(c, "runtime", "type_assertion_check");
add_package_dependency(c, "runtime", "type_assertion_check2"); add_package_dependency(c, "runtime", "type_assertion_check2");
case_end;
case_ast_node(tc, TypeCast, node);
check_expr_or_type(c, o, tc->type);
if (o->mode != Addressing_Type) {
gbString str = expr_to_string(tc->type);
error(tc->type, "Expected a type, got %s", str);
gb_string_free(str);
o->mode = Addressing_Invalid;
} }
if (o->mode == Addressing_Invalid) {
o->expr = node;
return kind; return kind;
} }
Type *type = o->type;
check_expr_base(c, o, tc->expr, type);
node->viral_state_flags |= tc->expr->viral_state_flags;
if (o->mode != Addressing_Invalid) { ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
switch (tc->token.kind) { ast_node(se, SelectorCallExpr, node);
case Token_transmute:
check_transmute(c, node, o, type);
break;
case Token_cast:
check_cast(c, o, type);
break;
default:
error(node, "Invalid AST: Invalid casting expression");
o->mode = Addressing_Invalid;
break;
}
}
return Expr_Expr;
case_end;
case_ast_node(ac, AutoCast, node);
check_expr_base(c, o, ac->expr, type_hint);
node->viral_state_flags |= ac->expr->viral_state_flags;
if (o->mode == Addressing_Invalid) {
o->expr = node;
return kind;
}
if (type_hint) {
Type *type = type_of_expr(ac->expr);
check_cast(c, o, type_hint);
if (is_type_typed(type) && are_types_identical(type, type_hint)) {
if (build_context.vet_extra) {
error(node, "Redundant 'auto_cast' applied to expression");
}
}
}
o->expr = node;
return Expr_Expr;
case_end;
case_ast_node(ue, UnaryExpr, node);
Type *th = type_hint;
if (ue->op.kind == Token_And) {
th = type_deref(th);
}
check_expr_base(c, o, ue->expr, th);
node->viral_state_flags |= ue->expr->viral_state_flags;
if (o->mode != Addressing_Invalid) {
check_unary_expr(c, o, ue->op, node);
}
o->expr = node;
return kind;
case_end;
case_ast_node(be, BinaryExpr, node);
check_binary_expr(c, o, node, type_hint, true);
if (o->mode == Addressing_Invalid) {
o->expr = node;
return kind;
}
case_end;
case_ast_node(se, SelectorExpr, node);
check_selector(c, o, node, type_hint);
node->viral_state_flags |= se->expr->viral_state_flags;
case_end;
case_ast_node(se, SelectorCallExpr, node);
// IMPORTANT NOTE(bill, 2020-05-22): This is a complete hack to get a shorthand which is extremely useful for vtables // IMPORTANT NOTE(bill, 2020-05-22): This is a complete hack to get a shorthand which is extremely useful for vtables
// COM APIs is a great example of where this kind of thing is extremely useful // COM APIs is a great example of where this kind of thing is extremely useful
// General idea: // General idea:
@@ -8806,14 +8584,12 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->expr = node; o->expr = node;
return Expr_Expr; return Expr_Expr;
case_end; }
case_ast_node(ise, ImplicitSelectorExpr, node); ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
return check_implicit_selector_expr(c, o, node, type_hint); ExprKind kind = Expr_Expr;
case_end; ast_node(ie, IndexExpr, node);
case_ast_node(ie, IndexExpr, node);
check_expr(c, o, ie->expr); check_expr(c, o, ie->expr);
node->viral_state_flags |= ie->expr->viral_state_flags; node->viral_state_flags |= ie->expr->viral_state_flags;
if (o->mode == Addressing_Invalid) { if (o->mode == Addressing_Invalid) {
@@ -8932,10 +8708,12 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
// TODO(bill): allow matrix columns to be assignable to other types which are the same internally // TODO(bill): allow matrix columns to be assignable to other types which are the same internally
// if a type hint exists // if a type hint exists
} }
return kind;
}
case_end; ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Stmt;
case_ast_node(se, SliceExpr, node); ast_node(se, SliceExpr, node);
check_expr(c, o, se->expr); check_expr(c, o, se->expr);
node->viral_state_flags |= se->expr->viral_state_flags; node->viral_state_flags |= se->expr->viral_state_flags;
@@ -9105,7 +8883,297 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
o->type = t; o->type = t;
o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1])); o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1]));
} }
return kind;
}
ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
u32 prev_state_flags = c->state_flags;
defer (c->state_flags = prev_state_flags);
if (node->state_flags != 0) {
u32 in = node->state_flags;
u32 out = c->state_flags;
if (in & StateFlag_no_bounds_check) {
out |= StateFlag_no_bounds_check;
out &= ~StateFlag_bounds_check;
} else if (in & StateFlag_bounds_check) {
out |= StateFlag_bounds_check;
out &= ~StateFlag_no_bounds_check;
}
if (in & StateFlag_no_type_assert) {
out |= StateFlag_no_type_assert;
out &= ~StateFlag_type_assert;
} else if (in & StateFlag_type_assert) {
out |= StateFlag_type_assert;
out &= ~StateFlag_no_type_assert;
}
c->state_flags = out;
}
ExprKind kind = Expr_Stmt;
o->mode = Addressing_Invalid;
o->type = t_invalid;
switch (node->kind) {
default:
return kind;
case_ast_node(be, BadExpr, node)
return kind;
case_end;
case_ast_node(i, Implicit, node)
switch (i->kind) {
case Token_context:
{
if (c->proc_name.len == 0 && c->curr_proc_sig == nullptr) {
error(node, "'context' is only allowed within procedures %p", c->curr_proc_decl);
return kind;
}
if (unparen_expr(c->assignment_lhs_hint) == node) {
c->scope->flags |= ScopeFlag_ContextDefined;
}
if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
error(node, "'context' has not been defined within this scope");
// Continue with value
}
init_core_context(c->checker);
o->mode = Addressing_Context;
o->type = t_context;
}
break;
default:
error(node, "Illegal implicit name '%.*s'", LIT(i->string));
return kind;
}
case_end;
case_ast_node(i, Ident, node);
check_ident(c, o, node, nullptr, type_hint, false);
case_end;
case_ast_node(u, Undef, node);
o->mode = Addressing_Value;
o->type = t_untyped_undef;
case_end;
case_ast_node(bl, BasicLit, node);
Type *t = t_invalid;
switch (node->tav.value.kind) {
case ExactValue_String: t = t_untyped_string; break;
case ExactValue_Float: t = t_untyped_float; break;
case ExactValue_Complex: t = t_untyped_complex; break;
case ExactValue_Quaternion: t = t_untyped_quaternion; break;
case ExactValue_Integer:
t = t_untyped_integer;
if (bl->token.kind == Token_Rune) {
t = t_untyped_rune;
}
break;
default:
GB_PANIC("Unhandled value type for basic literal");
break;
}
o->mode = Addressing_Constant;
o->type = t;
o->value = node->tav.value;
case_end;
case_ast_node(bd, BasicDirective, node);
kind = check_basic_directive_expr(c, o, node, type_hint);
case_end;
case_ast_node(pg, ProcGroup, node);
error(node, "Illegal use of a procedure group");
o->mode = Addressing_Invalid;
case_end;
case_ast_node(pl, ProcLit, node);
CheckerContext ctx = *c;
DeclInfo *decl = nullptr;
Type *type = alloc_type(Type_Proc);
check_open_scope(&ctx, pl->type);
{
decl = make_decl_info(ctx.scope, ctx.decl);
decl->proc_lit = node;
ctx.decl = decl;
defer (ctx.decl = ctx.decl->parent);
if (pl->tags != 0) {
error(node, "A procedure literal cannot have tags");
pl->tags = 0; // TODO(bill): Should I zero this?!
}
check_procedure_type(&ctx, type, pl->type);
if (!is_type_proc(type)) {
gbString str = expr_to_string(node);
error(node, "Invalid procedure literal '%s'", str);
gb_string_free(str);
check_close_scope(&ctx);
return kind;
}
if (pl->body == nullptr) {
error(node, "A procedure literal must have a body");
return kind;
}
pl->decl = decl;
check_procedure_later(&ctx, ctx.file, empty_token, decl, type, pl->body, pl->tags);
}
check_close_scope(&ctx);
o->mode = Addressing_Value;
o->type = type;
case_end;
case_ast_node(te, TernaryIfExpr, node);
kind = check_ternary_if_expr(c, o, node, type_hint);
case_end;
case_ast_node(te, TernaryWhenExpr, node);
kind = check_ternary_when_expr(c, o, node, type_hint);
case_end;
case_ast_node(oe, OrElseExpr, node);
return check_or_else_expr(c, o, node, type_hint);
case_end;
case_ast_node(re, OrReturnExpr, node);
return check_or_return_expr(c, o, node, type_hint);
case_end;
case_ast_node(cl, CompoundLit, node);
kind = check_compound_literal(c, o, node, type_hint);
case_end;
case_ast_node(pe, ParenExpr, node);
kind = check_expr_base(c, o, pe->expr, type_hint);
node->viral_state_flags |= pe->expr->viral_state_flags;
o->expr = node;
case_end;
case_ast_node(te, TagExpr, node);
String name = te->name.string;
error(node, "Unknown tag expression, #%.*s", LIT(name));
if (te->expr) {
kind = check_expr_base(c, o, te->expr, type_hint);
node->viral_state_flags |= te->expr->viral_state_flags;
}
o->expr = node;
case_end;
case_ast_node(ta, TypeAssertion, node);
kind = check_type_assertion(c, o, node, type_hint);
case_end;
case_ast_node(tc, TypeCast, node);
check_expr_or_type(c, o, tc->type);
if (o->mode != Addressing_Type) {
gbString str = expr_to_string(tc->type);
error(tc->type, "Expected a type, got %s", str);
gb_string_free(str);
o->mode = Addressing_Invalid;
}
if (o->mode == Addressing_Invalid) {
o->expr = node;
return kind;
}
Type *type = o->type;
check_expr_base(c, o, tc->expr, type);
node->viral_state_flags |= tc->expr->viral_state_flags;
if (o->mode != Addressing_Invalid) {
switch (tc->token.kind) {
case Token_transmute:
check_transmute(c, node, o, type);
break;
case Token_cast:
check_cast(c, o, type);
break;
default:
error(node, "Invalid AST: Invalid casting expression");
o->mode = Addressing_Invalid;
break;
}
}
return Expr_Expr;
case_end;
case_ast_node(ac, AutoCast, node);
check_expr_base(c, o, ac->expr, type_hint);
node->viral_state_flags |= ac->expr->viral_state_flags;
if (o->mode == Addressing_Invalid) {
o->expr = node;
return kind;
}
if (type_hint) {
Type *type = type_of_expr(ac->expr);
check_cast(c, o, type_hint);
if (is_type_typed(type) && are_types_identical(type, type_hint)) {
if (build_context.vet_extra) {
error(node, "Redundant 'auto_cast' applied to expression");
}
}
}
o->expr = node;
return Expr_Expr;
case_end;
case_ast_node(ue, UnaryExpr, node);
Type *th = type_hint;
if (ue->op.kind == Token_And) {
th = type_deref(th);
}
check_expr_base(c, o, ue->expr, th);
node->viral_state_flags |= ue->expr->viral_state_flags;
if (o->mode != Addressing_Invalid) {
check_unary_expr(c, o, ue->op, node);
}
o->expr = node;
return kind;
case_end;
case_ast_node(be, BinaryExpr, node);
check_binary_expr(c, o, node, type_hint, true);
if (o->mode == Addressing_Invalid) {
o->expr = node;
return kind;
}
case_end;
case_ast_node(se, SelectorExpr, node);
check_selector(c, o, node, type_hint);
node->viral_state_flags |= se->expr->viral_state_flags;
case_end;
case_ast_node(se, SelectorCallExpr, node);
return check_selector_call_expr(c, o, node, type_hint);
case_end;
case_ast_node(ise, ImplicitSelectorExpr, node);
return check_implicit_selector_expr(c, o, node, type_hint);
case_end;
case_ast_node(ie, IndexExpr, node);
kind = check_index_expr(c, o, node, type_hint);
case_end;
case_ast_node(se, SliceExpr, node);
kind = check_slice_expr(c, o, node, type_hint);
case_end; case_end;
case_ast_node(mie, MatrixIndexExpr, node); case_ast_node(mie, MatrixIndexExpr, node);
@@ -9230,6 +9298,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
return kind; return kind;
} }
ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { ExprKind check_expr_base(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = check_expr_base_internal(c, o, node, type_hint); ExprKind kind = check_expr_base_internal(c, o, node, type_hint);
if (o->type != nullptr && core_type(o->type) == nullptr) { if (o->type != nullptr && core_type(o->type) == nullptr) {