Skip to content

Commit

Permalink
static: Error when trying to access static values on instances
Browse files Browse the repository at this point in the history
  • Loading branch information
obiwac committed Oct 29, 2024
1 parent 76b6ece commit fc1eb27
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 30 deletions.
3 changes: 3 additions & 0 deletions flamingo/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions flamingo/flamingo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
};

Expand Down
10 changes: 7 additions & 3 deletions flamingo/grammar/access.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions flamingo/grammar/function_declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
59 changes: 32 additions & 27 deletions flamingo/grammar/static.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions flamingo/grammar/var_decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.

Expand Down

0 comments on commit fc1eb27

Please sign in to comment.