From fc1eb27e08bd502a163329a5d303a9393fb5ed44 Mon Sep 17 00:00:00 2001 From: Aymeric Wibo Date: Tue, 29 Oct 2024 16:54:54 +0100 Subject: [PATCH] static: Error when trying to access static values on instances --- flamingo/common.h | 3 ++ flamingo/flamingo.h | 5 +++ flamingo/grammar/access.h | 10 +++-- flamingo/grammar/function_declaration.h | 3 ++ flamingo/grammar/static.h | 59 ++++++++++++++----------- flamingo/grammar/var_decl.h | 2 + 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/flamingo/common.h b/flamingo/common.h index 926b9db..07c6b99 100644 --- a/flamingo/common.h +++ b/flamingo/common.h @@ -36,6 +36,9 @@ static inline int parse_import(flamingo_t* flamingo, TSNode node); static inline int parse_function_declaration(flamingo_t* flamingo, TSNode node, flamingo_fn_kind_t kind); static inline int parse_lambda(flamingo_t* flamingo, TSNode node, flamingo_val_t** val); +static inline bool check_is_static(flamingo_t* flamingo, TSNode node); +static inline int find_static_members_in_class(flamingo_t* flamingo, flamingo_scope_t* scope, TSNode body); + // Environment prototypes. static inline flamingo_env_t* env_alloc(void); diff --git a/flamingo/flamingo.h b/flamingo/flamingo.h index 9f063cc..07a3b42 100644 --- a/flamingo/flamingo.h +++ b/flamingo/flamingo.h @@ -46,6 +46,8 @@ struct flamingo_val_t { flamingo_val_kind_t kind; size_t ref_count; + // All the type-specific data. + union { struct { bool boolean; @@ -113,8 +115,11 @@ struct flamingo_val_t { struct flamingo_var_t { bool anonymous; + bool is_static; + char* key; size_t key_size; + flamingo_val_t* val; }; diff --git a/flamingo/grammar/access.h b/flamingo/grammar/access.h index ba23915..38aa4a8 100644 --- a/flamingo/grammar/access.h +++ b/flamingo/grammar/access.h @@ -50,14 +50,18 @@ static int access_find_var(flamingo_t* flamingo, TSNode node, flamingo_var_t** v flamingo_val_kind_t const kind = (*accessed_val)->kind; bool const is_inst = kind == FLAMINGO_VAL_KIND_INST; - bool const is_static = kind == FLAMINGO_VAL_KIND_FN && (*accessed_val)->fn.kind == FLAMINGO_FN_KIND_CLASS; + bool const is_static_access = kind == FLAMINGO_VAL_KIND_FN && (*accessed_val)->fn.kind == FLAMINGO_FN_KIND_CLASS; - if (is_inst || is_static) { + if (is_inst || is_static_access) { flamingo_scope_t* const scope = is_inst ? (*accessed_val)->inst.scope : (*accessed_val)->fn.scope; *var = scope_shallow_find_var(scope, accessor, size); if (*var == NULL) { - return error(flamingo, "member '%.*s' was never in declared", (int) size, accessor); + return error(flamingo, "%smember '%.*s' was never declared", is_static_access ? "static " : "", (int) size, accessor); + } + + if (is_inst && (*var)->is_static) { + return error(flamingo, "member '%.*s' is static and can't be accessed through an instance", (int) size, accessor); } return 0; diff --git a/flamingo/grammar/function_declaration.h b/flamingo/grammar/function_declaration.h index de4f93d..af51636 100644 --- a/flamingo/grammar/function_declaration.h +++ b/flamingo/grammar/function_declaration.h @@ -104,9 +104,12 @@ static int parse_function_declaration(flamingo_t* flamingo, TSNode node, flaming // Add function/class to scope. flamingo_var_t* const var = scope_add_var(cur_scope, name, size); + var->is_static = check_is_static(flamingo, node); + var_set_val(var, val_alloc()); var->val->kind = FLAMINGO_VAL_KIND_FN; + var->val->fn.kind = kind; var->val->fn.env = env_close_over(flamingo->env); var->val->fn.params = NULL; diff --git a/flamingo/grammar/static.h b/flamingo/grammar/static.h index 59f4881..d204081 100644 --- a/flamingo/grammar/static.h +++ b/flamingo/grammar/static.h @@ -4,8 +4,38 @@ #pragma once #include "../common.h" +#include "../env.h" #include "var_decl.h" +static inline bool check_is_static(flamingo_t* flamingo, TSNode node) { + TSNode const qualifiers = ts_node_child_by_field_name(node, "qualifiers", 10); + bool const has_qualifiers = !ts_node_is_null(qualifiers); + + if (!has_qualifiers) { + return false; + } + + assert(strcmp(ts_node_type(qualifiers), "qualifier_list") == 0); + + size_t const qualifier_count = ts_node_child_count(qualifiers); + + for (size_t i = 0; i < qualifier_count; i++) { + TSNode const qualifier = ts_node_child(qualifiers, i); + + size_t const start = ts_node_start_byte(qualifier); + size_t const end = ts_node_end_byte(qualifier); + + char const* const qualifier_name = flamingo->src + start; + size_t const size = end - start; + + if (strncmp(qualifier_name, "static", size) == 0) { + return true; + } + } + + return false; +} + static inline int find_static_members_in_class(flamingo_t* flamingo, flamingo_scope_t* scope, TSNode body) { assert(strcmp(ts_node_type(body), "block") == 0); @@ -24,34 +54,9 @@ static inline int find_static_members_in_class(flamingo_t* flamingo, flamingo_sc type = ts_node_type(node); } - // Check for static in qualifier list. - - TSNode const qualifiers = ts_node_child_by_field_name(node, "qualifiers", 10); - bool const has_qualifiers = !ts_node_is_null(qualifiers); - - if (!has_qualifiers) { - continue; - } - - assert(strcmp(ts_node_type(qualifiers), "qualifier_list") == 0); + // Check if static. - size_t const qualifier_count = ts_node_child_count(qualifiers); - bool is_static = false; - - for (size_t j = 0; j < qualifier_count; j++) { - TSNode const qualifier = ts_node_child(qualifiers, j); - - size_t const start = ts_node_start_byte(qualifier); - size_t const end = ts_node_end_byte(qualifier); - - char const* const qualifier_name = flamingo->src + start; - size_t const size = end - start; - - if (strncmp(qualifier_name, "static", size) == 0) { - is_static = true; - break; - } - } + bool const is_static = check_is_static(flamingo, node); if (!is_static) { continue; diff --git a/flamingo/grammar/var_decl.h b/flamingo/grammar/var_decl.h index df289ea..38f87e4 100644 --- a/flamingo/grammar/var_decl.h +++ b/flamingo/grammar/var_decl.h @@ -8,6 +8,7 @@ #include "../common.h" #include "../env.h" #include "../scope.h" +#include "static.h" static int parse_var_decl(flamingo_t* flamingo, TSNode node) { size_t const child_count = ts_node_named_child_count(node); @@ -67,6 +68,7 @@ static int parse_var_decl(flamingo_t* flamingo, TSNode node) { // Now, we can add our variable to the scope. flamingo_var_t* const var = scope_add_var(cur_scope, name, name_size); + var->is_static = check_is_static(flamingo, node); // And parse the initial expression if there is one to the variable's value.