Skip to content

Commit

Permalink
index: Indexing vectors
Browse files Browse the repository at this point in the history
  • Loading branch information
obiwac committed Oct 1, 2024
1 parent 0f6a153 commit 8f9339b
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 2 deletions.
1 change: 1 addition & 0 deletions flamingo/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ static inline int parse_expr(flamingo_t* flamingo, TSNode node, flamingo_val_t**
static inline int parse_binary_expr(flamingo_t* flamingo, TSNode node, flamingo_val_t** val);
static inline int access_find_var(flamingo_t* flamingo, TSNode node, flamingo_var_t** var, flamingo_val_t** accessed_val);
static inline int parse_access(flamingo_t* flamingo, TSNode node, flamingo_val_t** val, flamingo_val_t** accessed_val);
static inline int parse_index(flamingo_t* flamingo, TSNode node, flamingo_val_t** val);
static inline int parse_statement(flamingo_t* flamingo, TSNode node);
static inline int parse_block(flamingo_t* flamingo, TSNode node, flamingo_scope_t** inner_scope);
static inline int parse_print(flamingo_t* flamingo, TSNode node);
Expand Down
5 changes: 5 additions & 0 deletions flamingo/grammar/expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "identifier.h"
#include "literal.h"
#include "vec.h"
#include "index.h"

static int parse_expr(flamingo_t* flamingo, TSNode node, flamingo_val_t** val, flamingo_val_t** accessed_val_ref) {
assert(strcmp(ts_node_type(node), "expression") == 0);
Expand Down Expand Up @@ -51,5 +52,9 @@ static int parse_expr(flamingo_t* flamingo, TSNode node, flamingo_val_t** val, f
return parse_access(flamingo, child, val, accessed_val_ref);
}

if (strcmp(type, "index") == 0) {
return parse_index(flamingo, child, val);
}

return error(flamingo, "unknown expression type: %s", type);
}
92 changes: 92 additions & 0 deletions flamingo/grammar/index.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// This Source Form is subject to the terms of the AQUA Software License,
// v. 1.0. Copyright (c) 2024 Aymeric Wibo

#pragma once

#include "expr.h"

#include <common.h>
#include <scope.h>

static int parse_index(flamingo_t* flamingo, TSNode node, flamingo_val_t** val) {
assert(strcmp(ts_node_type(node), "index") == 0);

// Get indexed expression.

TSNode const indexed_node = ts_node_child_by_field_name(node, "indexed", 7);
char const* const indexed_type = ts_node_type(indexed_node);

if (strcmp(indexed_type, "expression") != 0) {
return error(flamingo, "expected expression for indexed, got %s", indexed_type);
}

// Get index expression.

TSNode const index_node = ts_node_child_by_field_name(node, "index", 5);
char const* const index_type = ts_node_type(index_node);

if (strcmp(index_type, "expression") != 0) {
return error(flamingo, "expected expression for index, got %s", index_type);
}

// Evaluate indexed expression.
// Make sure it is indexable in the first place.

flamingo_val_t* indexed_val = NULL;

if (parse_expr(flamingo, indexed_node, &indexed_val, NULL) < 0) {
return -1;
}

if (indexed_val->kind != FLAMINGO_VAL_KIND_VEC) {
return error(flamingo, "can only index vectors, got %s", val_type_str(indexed_val));
}

size_t const indexed_count = indexed_val->vec.count;
flamingo_val_t** const indexed_elems = indexed_val->vec.elems;

// Evaluate index expression.
// Make sure it can be used as an index.

flamingo_val_t* index_val = NULL;

if (parse_expr(flamingo, index_node, &index_val, NULL) < 0) {
return -1;
}

if (index_val->kind != FLAMINGO_VAL_KIND_INT) {
return error(flamingo, "can only use integers as indices, got %s", val_type_str(index_val));
}

int64_t const index = index_val->integer.integer;

// Check bounds.

if (index >= 0 && (size_t) index >= indexed_count) {
return error(flamingo, "index %" PRId64 " is out of bounds for vector of size %zu", index, indexed_count);
}

if (index < 0 && (size_t) -index > indexed_count) {
return error(flamingo, "index %" PRId64 " is out of bounds for vector of size %zu", index, indexed_count);
}

// Actually index vector.

if (val == NULL) {
return 0;
}

assert(*val == NULL);

if (index >= 0) {
*val = indexed_elems[index];
val_incref(*val);
}

else {
*val = indexed_elems[indexed_count + index];
val_incref(*val);
}

return 0;
}
4 changes: 2 additions & 2 deletions flamingo/grammar/print.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static int repr(flamingo_t* flamingo, flamingo_val_t* val, char** res, bool inne
return -1;
}

char* buf = strdup(*res);
char* const buf = strdup(*res);
assert(buf != NULL);
asprintf(res, "%s%s%s", buf, i == 0 ? "" : ", ", elem_repr);
assert(*res != NULL);
Expand All @@ -53,7 +53,7 @@ static int repr(flamingo_t* flamingo, flamingo_val_t* val, char** res, bool inne
free(elem_repr);
}

char* buf = strdup(*res);
char* const buf = strdup(*res);
assert(buf != NULL);
asprintf(res, "%s]", buf);
free(buf);
Expand Down

0 comments on commit 8f9339b

Please sign in to comment.