mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Code refactor to aid development
This commit is contained in:
+336
-266
@@ -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);
|
ExprKind check_type_assertion(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
|
||||||
kind = check_expr_base(c, o, pe->expr, type_hint);
|
ExprKind kind = Expr_Expr;
|
||||||
node->viral_state_flags |= pe->expr->viral_state_flags;
|
ast_node(ta, TypeAssertion, node);
|
||||||
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);
|
|
||||||
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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user