This will match all arguments and discard them. This makes the bytecode for simple functions easier and will make it easier to construct simple function programmatically.
179 lines
4.6 KiB
C
179 lines
4.6 KiB
C
#ifndef APFL_VALUE_H
|
|
#define APFL_VALUE_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
|
|
#include "apfl.h"
|
|
|
|
#include "bytecode.h"
|
|
#include "gc.h"
|
|
|
|
#include "hashmap.h"
|
|
|
|
enum value_type {
|
|
VALUE_NIL,
|
|
VALUE_BOOLEAN,
|
|
VALUE_NUMBER,
|
|
VALUE_STRING,
|
|
VALUE_CONST_STRING,
|
|
VALUE_LIST,
|
|
VALUE_DICT,
|
|
VALUE_FUNC,
|
|
VALUE_CFUNC,
|
|
VALUE_USERDATA,
|
|
VALUE_NATIVE_OBJECT,
|
|
};
|
|
|
|
struct list_header {
|
|
struct apfl_value *items;
|
|
size_t len;
|
|
size_t cap;
|
|
bool copy_on_write;
|
|
};
|
|
|
|
struct dict_header {
|
|
struct apfl_hashmap map;
|
|
bool copy_on_write;
|
|
};
|
|
|
|
struct subfunction {
|
|
struct matcher *matcher; // Can be NULL, in which case all arguments are accepted but discarded
|
|
struct instruction_list *body;
|
|
};
|
|
|
|
struct function {
|
|
struct subfunction *subfunctions;
|
|
size_t subfunctions_len;
|
|
size_t subfunctions_cap;
|
|
struct scope *scope;
|
|
struct apfl_string *name;
|
|
int line_defined;
|
|
struct apfl_string *filename;
|
|
};
|
|
|
|
struct cfunction {
|
|
apfl_cfunc func;
|
|
struct apfl_value **slots;
|
|
size_t slots_len;
|
|
struct apfl_string *name;
|
|
};
|
|
|
|
typedef struct dict_header *apfl_dict;
|
|
|
|
struct native_object {
|
|
void *memory;
|
|
const struct apfl_native_object_type *type;
|
|
};
|
|
|
|
struct apfl_value {
|
|
enum value_type type;
|
|
union {
|
|
bool boolean;
|
|
apfl_number number;
|
|
struct apfl_string *string;
|
|
struct apfl_string_view const_string;
|
|
struct list_header *list;
|
|
struct dict_header *dict;
|
|
struct function *func;
|
|
struct cfunction *cfunc;
|
|
void *userdata;
|
|
struct native_object *native_object;
|
|
};
|
|
};
|
|
|
|
enum apfl_value_type apfl_value_type_to_abstract_type(enum value_type);
|
|
|
|
#define VALUE_IS_A(v, t) (apfl_value_type_to_abstract_type((v).type) == (t))
|
|
|
|
bool apfl_value_eq(const struct apfl_value, const struct apfl_value);
|
|
struct apfl_value apfl_value_move(struct apfl_value *src);
|
|
bool apfl_value_format(struct apfl_value, struct apfl_io_writer);
|
|
bool apfl_value_print(struct apfl_value, struct apfl_io_writer);
|
|
apfl_hash apfl_value_hash(const struct apfl_value);
|
|
|
|
enum comparison_result {
|
|
CMP_LT,
|
|
CMP_EQ,
|
|
CMP_GT,
|
|
CMP_UNCOMPARABLE,
|
|
CMP_INCOMPATIBLE_TYPES,
|
|
};
|
|
|
|
enum comparison_result apfl_value_cmp(const struct apfl_value a, const struct apfl_value b);
|
|
|
|
enum get_item_result {
|
|
GET_ITEM_OK,
|
|
GET_ITEM_KEY_DOESNT_EXIST,
|
|
GET_ITEM_NOT_A_CONTAINER,
|
|
GET_ITEM_WRONG_KEY_TYPE,
|
|
};
|
|
|
|
enum get_item_result apfl_value_get_item(struct apfl_value container, struct apfl_value key, struct apfl_value *out);
|
|
|
|
// Set the Copy On Write flag of a value (if it's a value with such a flag).
|
|
// Returns the same value again.
|
|
struct apfl_value apfl_value_set_cow_flag(struct apfl_value);
|
|
|
|
struct list_header *apfl_list_new(struct gc *, size_t initial_cap);
|
|
|
|
size_t apfl_list_len(struct list_header *);
|
|
void apfl_list_deinit(struct apfl_allocator, struct list_header *);
|
|
|
|
bool
|
|
apfl_list_splice(
|
|
struct gc *gc,
|
|
struct list_header **dst_ptr,
|
|
size_t cut_start,
|
|
size_t cut_len,
|
|
const struct apfl_value *other,
|
|
size_t other_len
|
|
);
|
|
|
|
struct dict_header *apfl_dict_new(struct gc *);
|
|
bool apfl_dict_set_raw(
|
|
struct gc *gc,
|
|
struct dict_header **_dict,
|
|
struct apfl_value k,
|
|
struct apfl_value v
|
|
);
|
|
size_t apfl_dict_len(struct dict_header *);
|
|
void apfl_dict_deinit(struct dict_header *);
|
|
|
|
struct function *apfl_func_new(
|
|
struct gc *,
|
|
size_t cap,
|
|
struct scope *,
|
|
int line_defined,
|
|
struct apfl_string *filename
|
|
);
|
|
bool apfl_func_add_subfunc(struct function *, struct instruction_list *, struct matcher *);
|
|
bool apfl_func_get_name(struct function *, struct apfl_string_view *name);
|
|
void apfl_func_set_name(struct function *, struct apfl_string *name);
|
|
void apfl_function_deinit(struct apfl_allocator, struct function *);
|
|
|
|
struct cfunction *apfl_cfunc_new(struct gc *, apfl_cfunc, size_t nslots);
|
|
void apfl_cfunction_deinit(struct apfl_allocator, struct cfunction *);
|
|
|
|
struct native_object *apfl_native_object_new(struct gc *, const struct apfl_native_object_type *);
|
|
void apfl_native_object_deinit(struct apfl_allocator, struct native_object *);
|
|
|
|
// Functions for garbage collection
|
|
struct gc_object *apfl_value_get_gc_object(struct apfl_value);
|
|
void apfl_value_visit_gc_object(struct apfl_value value, gc_visitor cb, void *opaque);
|
|
bool apfl_value_add_as_tmproot(struct gc *, struct apfl_value);
|
|
void apfl_gc_list_traverse(struct list_header *, gc_visitor, void *);
|
|
void apfl_gc_dict_traverse(struct dict_header *, gc_visitor, void *);
|
|
void apfl_gc_func_traverse(struct function*, gc_visitor, void *);
|
|
void apfl_gc_cfunc_traverse(struct cfunction*, gc_visitor, void *);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|