Skip to content

Commit

Permalink
class: Add static members to static scope and be able to access them
Browse files Browse the repository at this point in the history
  • Loading branch information
obiwac committed Oct 3, 2024
1 parent b3fb2bb commit 237da1a
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 91 deletions.
5 changes: 5 additions & 0 deletions flamingo/flamingo.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ struct flamingo_val_t {
// Only used for primitive type members.

flamingo_ptm_cb_t ptm_cb;

// The class' static environment.
// This works quite similarly to instances.

flamingo_scope_t* scope;
} fn;

struct {
Expand Down
12 changes: 5 additions & 7 deletions flamingo/grammar/access.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ static int access_find_var(flamingo_t* flamingo, TSNode node, flamingo_var_t** v
}

// Actually access.
// XXX For now only instances and things with PTM's are accessible, but in the future I'm going to want to be able to access static members on classes directly too.

*var = NULL;
flamingo_val_kind_t const kind = (*accessed_val)->kind;

if (kind == FLAMINGO_VAL_KIND_INST) {
flamingo_scope_t* const scope = (*accessed_val)->inst.scope;
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;

if (is_inst || is_static) {
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) {
Expand All @@ -61,10 +63,6 @@ static int access_find_var(flamingo_t* flamingo, TSNode node, flamingo_var_t** v
return 0;
}

if (kind == FLAMINGO_VAL_KIND_FN && (*accessed_val)->fn.kind == FLAMINGO_FN_KIND_CLASS) {
return error(flamingo, "static access");
}

// Is PTM access.

size_t const count = flamingo->primitive_type_members[kind].count;
Expand Down
90 changes: 6 additions & 84 deletions flamingo/grammar/function_declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,95 +4,14 @@
#pragma once

#include "params.h"
#include "static.h"
#include "var_decl.h"
#include <common.h>
#include <env.h>
#include <scope.h>
#include <val.h>
#include <var.h>

static int find_static_members_in_class(flamingo_t* flamingo, TSNode body) {
assert(strcmp(ts_node_type(body), "block") == 0);

size_t const n = ts_node_named_child_count(body);

for (size_t i = 0; i < n; i++) {
TSNode const node = ts_node_named_child(body, i);
char const* const type = ts_node_type(node);

bool const is_var_decl = strcmp(type, "var_decl") == 0;
bool const is_fn_decl = strcmp(type, "function_declaration") == 0;
bool const is_class_decl = strcmp(type, "class_declaration") == 0;

if (!is_var_decl && !is_fn_decl && !is_class_decl) {
continue;
}

// 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);

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;
}
}

if (!is_static) {
continue;
}

// Parse static member.

if (is_fn_decl) {
if (parse_function_declaration(flamingo, node, FLAMINGO_FN_KIND_FUNCTION) < 0) {
return -1;
}

return 0;
}

if (is_var_decl) {
if (parse_var_decl(flamingo, node) < 0) {
return -1;
}

return 0;
}

if (is_class_decl) {
if (parse_function_declaration(flamingo, node, FLAMINGO_FN_KIND_CLASS) < 0) {
return -1;
}

return 0;
}

assert(false);
}

return 0;
}

static int parse_function_declaration(flamingo_t* flamingo, TSNode node, flamingo_fn_kind_t kind) {
size_t const child_count = ts_node_child_count(node);
assert(child_count >= 4 || child_count <= 6);
Expand Down Expand Up @@ -207,10 +126,13 @@ static int parse_function_declaration(flamingo_t* flamingo, TSNode node, flaming
memcpy(var->val->fn.body, &body, sizeof body);
}

// If class, look for any static members.
// If class, create static environment and look for any static members.

if (kind == FLAMINGO_FN_KIND_CLASS) {
if (find_static_members_in_class(flamingo, body) < 0) {
flamingo_scope_t* const scope = scope_alloc();
var->val->fn.scope = scope;

if (find_static_members_in_class(flamingo, scope, body) < 0) {
return -1;
}
}
Expand Down
100 changes: 100 additions & 0 deletions flamingo/grammar/static.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// This Source Form is subject to the terms of the AQUA Software License,
// v. 1.0. Copyright (c) 2024 Aymeric Wibo

#pragma once

#include "var_decl.h"
#include <common.h>

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);

size_t const n = ts_node_named_child_count(body);
env_gently_attach_scope(flamingo->env, scope);

for (size_t i = 0; i < n; i++) {
TSNode node = ts_node_named_child(body, i);
char const* type = ts_node_type(node);

// If node is wrapped in a statement, unwrap it.
// This is the case for line-sensitive nodes, like 'var_decl'.

if (strcmp(type, "statement") == 0) {
node = ts_node_child(node, 0);
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);

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;
}
}

if (!is_static) {
continue;
}

// Parse static member.

if (strcmp(type, "var_decl") == 0) {
if (parse_var_decl(flamingo, node) < 0) {
return -1;
}

continue;
}

if (strcmp(type, "function_declaration") == 0) {
if (parse_function_declaration(flamingo, node, FLAMINGO_FN_KIND_FUNCTION) < 0) {
return -1;
}

continue;
}

if (strcmp(type, "class_declaration") == 0) {
if (parse_function_declaration(flamingo, node, FLAMINGO_FN_KIND_CLASS) < 0) {
return -1;
}

continue;
}

if (strcmp(type, "extern_declaration") == 0) {
if (parse_function_declaration(flamingo, node, FLAMINGO_FN_KIND_EXTERN) < 0) {
return -1;
}

continue;
}

return error(flamingo, "static qualifier applied to %s, which can't have the static qualifier applied to it", type);
}

env_gently_detach_scope(flamingo->env);

return 0;
}

0 comments on commit 237da1a

Please sign in to comment.