add dictionaries
This commit is contained in:
@@ -35,7 +35,8 @@ typedef enum {
|
||||
__number__,
|
||||
field_length,
|
||||
__getattribute__,
|
||||
__set_attr__,
|
||||
__setattr__,
|
||||
__setitem__,
|
||||
__hash__,
|
||||
__repr__,
|
||||
|
||||
|
||||
@@ -84,12 +84,22 @@ ParsedValueReturn parse_assign(char *file, DArray *tokens,
|
||||
return (ParsedValueReturn){err, NULL};
|
||||
}
|
||||
(*index)++;
|
||||
ArErr err = error_if_finished(file, tokens, index);
|
||||
if (err.exists) {
|
||||
free_parsed(assign_to);
|
||||
free(assign_to);
|
||||
return (ParsedValueReturn){err, NULL};
|
||||
}
|
||||
token = darray_get(tokens, *index);
|
||||
ParsedValueReturn from = parse_token(file, tokens, index, true);
|
||||
if (from.err.exists) {
|
||||
free_parsed(assign_to);
|
||||
free(assign_to);
|
||||
return from;
|
||||
}
|
||||
if (!from.value) {
|
||||
free_parsed(assign_to);
|
||||
free(assign_to);
|
||||
return (ParsedValueReturn){create_err(token->line, token->column,
|
||||
token->length, file, "Syntax Error",
|
||||
"expected body"),
|
||||
@@ -110,12 +120,6 @@ ParsedValueReturn parse_assign(char *file, DArray *tokens,
|
||||
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
||||
parsedValue->type = AST_ASSIGN;
|
||||
parsedValue->data = assign;
|
||||
ArErr err = error_if_finished(file, tokens, index);
|
||||
if (err.exists) {
|
||||
free_parsed(parsedValue);
|
||||
free(parsedValue);
|
||||
return (ParsedValueReturn){err, NULL};
|
||||
}
|
||||
assign->from = from.value;
|
||||
return (ParsedValueReturn){no_err, parsedValue};
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ ParsedValueReturn parse_parentheses(char *file, DArray *tokens, size_t *index) {
|
||||
"Syntax Error", "expected comma"),
|
||||
NULL};
|
||||
}
|
||||
(*index)++;
|
||||
skip_newlines_and_indents(tokens, index);
|
||||
err = error_if_finished(file, tokens, index);
|
||||
if (err.exists) {
|
||||
|
||||
@@ -132,36 +132,58 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
|
||||
new_string_object(key.data, key.length, 0, hash), value,
|
||||
0);
|
||||
}
|
||||
StackFrame new_stackFrame = {
|
||||
{object->value.argon_fn->translated.registerCount,
|
||||
object->value.argon_fn->translated.registerAssignment,
|
||||
NULL,
|
||||
{object->value.argon_fn->bytecode, sizeof(uint8_t),
|
||||
object->value.argon_fn->bytecode_length,
|
||||
object->value.argon_fn->bytecode_length, false},
|
||||
object->value.argon_fn->translated.constants,
|
||||
object->value.argon_fn->translated.path},
|
||||
{ar_alloc(object->value.argon_fn->translated.registerCount *
|
||||
sizeof(ArgonObject *)),
|
||||
0,
|
||||
object->value.argon_fn->translated.path,
|
||||
NULL,
|
||||
state->currentStackFramePointer,
|
||||
{},
|
||||
{}},
|
||||
scope,
|
||||
*state->currentStackFramePointer,
|
||||
(*state->currentStackFramePointer)->depth + 1};
|
||||
for (size_t i = 0; i < new_stackFrame.translated.registerCount; i++) {
|
||||
new_stackFrame.state.registers[i] = NULL;
|
||||
}
|
||||
if (CStackFrame) {
|
||||
StackFrame new_stackFrame = {
|
||||
{object->value.argon_fn->translated.registerCount,
|
||||
object->value.argon_fn->translated.registerAssignment,
|
||||
NULL,
|
||||
{object->value.argon_fn->bytecode, sizeof(uint8_t),
|
||||
object->value.argon_fn->bytecode_length,
|
||||
object->value.argon_fn->bytecode_length, false},
|
||||
object->value.argon_fn->translated.constants,
|
||||
object->value.argon_fn->translated.path},
|
||||
{ar_alloc(object->value.argon_fn->translated.registerCount *
|
||||
sizeof(ArgonObject *)),
|
||||
0,
|
||||
object->value.argon_fn->translated.path,
|
||||
NULL,
|
||||
state->currentStackFramePointer,
|
||||
{},
|
||||
{}},
|
||||
scope,
|
||||
*state->currentStackFramePointer,
|
||||
(*state->currentStackFramePointer)->depth + 1};
|
||||
for (size_t i = 0; i < new_stackFrame.translated.registerCount; i++) {
|
||||
new_stackFrame.state.registers[i] = NULL;
|
||||
}
|
||||
runtime(new_stackFrame.translated, new_stackFrame.state,
|
||||
new_stackFrame.stack, err);
|
||||
state->registers[0] = new_stackFrame.state.registers[0];
|
||||
} else {
|
||||
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
|
||||
*currentStackFrame = new_stackFrame;
|
||||
*currentStackFrame = (StackFrame){
|
||||
{object->value.argon_fn->translated.registerCount,
|
||||
object->value.argon_fn->translated.registerAssignment,
|
||||
NULL,
|
||||
{object->value.argon_fn->bytecode, sizeof(uint8_t),
|
||||
object->value.argon_fn->bytecode_length,
|
||||
object->value.argon_fn->bytecode_length, false},
|
||||
object->value.argon_fn->translated.constants,
|
||||
object->value.argon_fn->translated.path},
|
||||
{ar_alloc(object->value.argon_fn->translated.registerCount *
|
||||
sizeof(ArgonObject *)),
|
||||
0,
|
||||
object->value.argon_fn->translated.path,
|
||||
NULL,
|
||||
state->currentStackFramePointer,
|
||||
{},
|
||||
{}},
|
||||
scope,
|
||||
*state->currentStackFramePointer,
|
||||
(*state->currentStackFramePointer)->depth + 1};
|
||||
for (size_t i = 0; i < (*currentStackFrame).translated.registerCount; i++) {
|
||||
(*currentStackFrame).state.registers[i] = NULL;
|
||||
}
|
||||
*state->currentStackFramePointer = currentStackFrame;
|
||||
if ((*state->currentStackFramePointer)->depth >= 10000) {
|
||||
double logval =
|
||||
|
||||
@@ -146,14 +146,36 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___get_attr__(size_t argc,
|
||||
}
|
||||
|
||||
|
||||
ArgonObject *create_ARGON_DICTIONARY_TYPE___set_attr__(size_t argc,
|
||||
ArgonObject *create_ARGON_DICTIONARY_TYPE___setattr__(size_t argc,
|
||||
ArgonObject **argv,
|
||||
ArErr *err,
|
||||
RuntimeState *state) {
|
||||
(void)state;
|
||||
if (argc != 3) {
|
||||
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||
"__set_attr__ expects 2 argument, got %" PRIu64, argc);
|
||||
"__setattr__ expects 2 argument, got %" PRIu64, argc);
|
||||
return ARGON_NULL;
|
||||
}
|
||||
ArgonObject *object = argv[0];
|
||||
ArgonObject *key = argv[1];
|
||||
ArgonObject *value = argv[2];
|
||||
int64_t hash = hash_object(key, err, state);
|
||||
if (err->exists) {
|
||||
return ARGON_NULL;
|
||||
}
|
||||
hashmap_insert_GC(object->value.as_hashmap, hash, key, value, 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
ArgonObject *create_ARGON_DICTIONARY_TYPE___setitem__(size_t argc,
|
||||
ArgonObject **argv,
|
||||
ArErr *err,
|
||||
RuntimeState *state) {
|
||||
(void)state;
|
||||
if (argc != 3) {
|
||||
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||
"__setitem__ expects 2 argument, got %" PRIu64, argc);
|
||||
return ARGON_NULL;
|
||||
}
|
||||
ArgonObject *object = argv[0];
|
||||
@@ -179,9 +201,13 @@ void create_ARGON_DICTIONARY_TYPE() {
|
||||
create_argon_native_function("__get_attr__",
|
||||
create_ARGON_DICTIONARY_TYPE___get_attr__));
|
||||
add_builtin_field(
|
||||
ARGON_DICTIONARY_TYPE, __set_attr__,
|
||||
create_argon_native_function("__set_attr__",
|
||||
create_ARGON_DICTIONARY_TYPE___set_attr__));
|
||||
ARGON_DICTIONARY_TYPE, __setattr__,
|
||||
create_argon_native_function("__setattr__",
|
||||
create_ARGON_DICTIONARY_TYPE___setattr__));
|
||||
add_builtin_field(
|
||||
ARGON_DICTIONARY_TYPE, __setitem__,
|
||||
create_argon_native_function("__setitem__",
|
||||
create_ARGON_DICTIONARY_TYPE___setitem__));
|
||||
add_builtin_field(ARGON_DICTIONARY_TYPE, __string__,
|
||||
create_argon_native_function(
|
||||
"__string__", create_ARGON_DICTIONARY_TYPE___string__));
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
ArgonObject *ARGON_NUMBER_TYPE;
|
||||
|
||||
@@ -268,6 +269,64 @@ ArgonObject *ARGON_NUMBER_TYPE___multiply__(size_t argc, ArgonObject **argv,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline uint64_t mix64(uint64_t x) {
|
||||
x ^= x >> 33;
|
||||
x *= 0xff51afd7ed558ccdULL;
|
||||
x ^= x >> 33;
|
||||
x *= 0xc4ceb9fe1a85ec53ULL;
|
||||
x ^= x >> 33;
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t hash_mpz(const mpz_t z) {
|
||||
// Export to raw bytes (big-endian for consistency)
|
||||
size_t count;
|
||||
unsigned char *data = mpz_export(NULL, &count, 1, 1, 1, 0, z);
|
||||
|
||||
// FNV-1a over bytes
|
||||
uint64_t h = 1469598103934665603ULL;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
h ^= data[i];
|
||||
h *= 1099511628211ULL;
|
||||
}
|
||||
|
||||
// Include sign bit
|
||||
if (mpz_sgn(z) < 0)
|
||||
h = ~h;
|
||||
|
||||
// Free the temporary buffer allocated by mpz_export
|
||||
free(data);
|
||||
|
||||
return mix64(h);
|
||||
}
|
||||
|
||||
uint64_t hash_mpq(mpq_t q) {
|
||||
uint64_t h_num = hash_mpz(mpq_numref(q));
|
||||
uint64_t h_den = hash_mpz(mpq_denref(q));
|
||||
|
||||
// Combine using a standard 64-bit hash mix (boost-style)
|
||||
uint64_t h = h_num ^ (h_den + 0x9e3779b97f4a7c15ULL + (h_num << 6) + (h_num >> 2));
|
||||
return mix64(h);
|
||||
}
|
||||
|
||||
ArgonObject *ARGON_NUMBER_TYPE___hash__(size_t argc, ArgonObject **argv,
|
||||
ArErr *err, RuntimeState *state) {
|
||||
(void)state;
|
||||
if (argc != 1) {
|
||||
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||
"__hash__ expects 1 arguments, got %" PRIu64, argc);
|
||||
}
|
||||
uint64_t hash;
|
||||
if (argv[0]->value.as_number->is_int64) {
|
||||
hash = mix64(argv[0]->value.as_number->n.i64);
|
||||
} else {
|
||||
hash = hash_mpq(*argv[0]->value.as_number->n.mpq);
|
||||
}
|
||||
return new_number_object_from_int64(hash);
|
||||
}
|
||||
|
||||
ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv,
|
||||
ArErr *err, RuntimeState *state) {
|
||||
(void)state;
|
||||
@@ -497,7 +556,6 @@ void init_small_ints() {
|
||||
for (int64_t i = 0; i <= small_ints_max - small_ints_min; i++) {
|
||||
int64_t n = i + small_ints_min;
|
||||
small_ints[i].type = TYPE_NUMBER;
|
||||
small_ints[i].built_in_slot_length = 0;
|
||||
small_ints[i].dict = NULL;
|
||||
small_ints[i].value.as_number = &small_ints_as_number[i];
|
||||
add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE);
|
||||
@@ -520,6 +578,9 @@ void create_ARGON_NUMBER_TYPE() {
|
||||
add_builtin_field(
|
||||
ARGON_NUMBER_TYPE, __number__,
|
||||
create_argon_native_function("__number__", ARGON_NUMBER_TYPE___number__));
|
||||
add_builtin_field(
|
||||
ARGON_NUMBER_TYPE, __hash__,
|
||||
create_argon_native_function("__hash__", ARGON_NUMBER_TYPE___hash__));
|
||||
add_builtin_field(ARGON_NUMBER_TYPE, __boolean__,
|
||||
create_argon_native_function(
|
||||
"__boolean__", ARGON_NUMBER_TYPE___boolean__));
|
||||
|
||||
@@ -41,7 +41,7 @@ const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = {
|
||||
"__string__",
|
||||
"__subtract__",
|
||||
"__multiply__",
|
||||
"__divide__",
|
||||
"__divide__",
|
||||
"__new__",
|
||||
"__init__",
|
||||
"__boolean__",
|
||||
@@ -51,7 +51,8 @@ const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = {
|
||||
"__number__",
|
||||
"length",
|
||||
"__getattribute__",
|
||||
"__set_attr__",
|
||||
"__setattr__",
|
||||
"__setitem__",
|
||||
"__hash__",
|
||||
"__repr__"};
|
||||
|
||||
@@ -77,9 +78,7 @@ int64_t hash_object(ArgonObject *object, ArErr *err, RuntimeState *state) {
|
||||
ArgonObject *hash_function = get_builtin_field_for_class(
|
||||
get_builtin_field(object, __class__), __hash__, object);
|
||||
if (!hash_function) {
|
||||
*err = create_err(err->line, err->column, err->length, err->path,
|
||||
"Hash Error", "objects class has no __hash__ method");
|
||||
return 0;
|
||||
return (int64_t)object;
|
||||
}
|
||||
ArgonObject *hash_result = argon_call(hash_function, 0, NULL, err, state);
|
||||
if (hash_result->type != TYPE_NUMBER ||
|
||||
|
||||
@@ -285,12 +285,12 @@ ArgonObject *BASE_CLASS___init__(size_t argc, ArgonObject **argv, ArErr *err,
|
||||
return ARGON_NULL;
|
||||
}
|
||||
|
||||
ArgonObject *BASE_CLASS___set_attr__(size_t argc, ArgonObject **argv, ArErr *err,
|
||||
ArgonObject *BASE_CLASS___setattr__(size_t argc, ArgonObject **argv, ArErr *err,
|
||||
RuntimeState *state) {
|
||||
(void)state;
|
||||
if (argc != 3) {
|
||||
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||
"__set_attr__ expects 3 argument, got %" PRIu64, argc);
|
||||
"__setattr__ expects 3 argument, got %" PRIu64, argc);
|
||||
}
|
||||
if (!argv[1]->value.as_str->hash)
|
||||
argv[1]->value.as_str->hash =
|
||||
@@ -691,13 +691,14 @@ void bootstrap_types() {
|
||||
create_argon_native_function("__getattribute__",
|
||||
BASE_CLASS___getattribute__));
|
||||
add_builtin_field(
|
||||
BASE_CLASS, __set_attr__,
|
||||
create_argon_native_function("__set_attr__", BASE_CLASS___set_attr__));
|
||||
BASE_CLASS, __setattr__,
|
||||
create_argon_native_function("__setattr__", BASE_CLASS___setattr__));
|
||||
create_ARGON_DICTIONARY_TYPE();
|
||||
create_ARGON_NUMBER_TYPE();
|
||||
}
|
||||
|
||||
void add_to_hashmap(struct hashmap_GC *hashmap, char *name, ArgonObject *value) {
|
||||
void add_to_hashmap(struct hashmap_GC *hashmap, char *name,
|
||||
ArgonObject *value) {
|
||||
size_t length = strlen(name);
|
||||
uint64_t hash = siphash64_bytes(name, length, siphash_key);
|
||||
ArgonObject *key = new_string_object(name, length, 0, hash);
|
||||
@@ -719,51 +720,53 @@ void bootstrap_globals() {
|
||||
|
||||
struct hashmap_GC *argon_term = createHashmap_GC();
|
||||
add_to_hashmap(argon_term, "log",
|
||||
create_argon_native_function("log", term_log));
|
||||
create_argon_native_function("log", term_log));
|
||||
add_to_scope(Global_Scope, "term", create_dictionary(argon_term));
|
||||
|
||||
|
||||
struct hashmap_GC *environment_variables = createHashmap_GC();
|
||||
#if defined(_WIN32)
|
||||
// Windows: use WinAPI
|
||||
LPCH env = GetEnvironmentStringsA();
|
||||
if (!env) return;
|
||||
#if defined(_WIN32)
|
||||
// Windows: use WinAPI
|
||||
LPCH env = GetEnvironmentStringsA();
|
||||
if (!env)
|
||||
return;
|
||||
|
||||
for (LPCH var = env; *var; var += strlen(var) + 1) {
|
||||
// Each string is like "KEY=VALUE"
|
||||
const char *equals = strchr(var, '=');
|
||||
if (equals) {
|
||||
size_t key_len = equals - var;
|
||||
char key[256];
|
||||
if (key_len >= sizeof(key))
|
||||
key_len = sizeof(key) - 1;
|
||||
strncpy(key, var, key_len);
|
||||
key[key_len] = '\0';
|
||||
for (LPCH var = env; *var; var += strlen(var) + 1) {
|
||||
// Each string is like "KEY=VALUE"
|
||||
const char *equals = strchr(var, '=');
|
||||
if (equals) {
|
||||
size_t key_len = equals - var;
|
||||
char key[256];
|
||||
if (key_len >= sizeof(key))
|
||||
key_len = sizeof(key) - 1;
|
||||
strncpy(key, var, key_len);
|
||||
key[key_len] = '\0';
|
||||
|
||||
const char *value = getenv(key);
|
||||
add_to_hashmap(environment_variables, key,
|
||||
value?new_string_object_null_terminated((char *)value):ARGON_NULL);
|
||||
}
|
||||
const char *value = getenv(key);
|
||||
add_to_hashmap(environment_variables, key,
|
||||
value ? new_string_object_null_terminated((char *)value)
|
||||
: ARGON_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
FreeEnvironmentStringsA(env);
|
||||
FreeEnvironmentStringsA(env);
|
||||
#else
|
||||
// POSIX systems: use environ
|
||||
for (char **env = environ; *env != NULL; env++) {
|
||||
const char *equals = strchr(*env, '=');
|
||||
if (equals) {
|
||||
size_t key_len = equals - *env;
|
||||
char key[256];
|
||||
if (key_len >= sizeof(key))
|
||||
key_len = sizeof(key) - 1;
|
||||
strncpy(key, *env, key_len);
|
||||
key[key_len] = '\0';
|
||||
// POSIX systems: use environ
|
||||
for (char **env = environ; *env != NULL; env++) {
|
||||
const char *equals = strchr(*env, '=');
|
||||
if (equals) {
|
||||
size_t key_len = equals - *env;
|
||||
char key[256];
|
||||
if (key_len >= sizeof(key))
|
||||
key_len = sizeof(key) - 1;
|
||||
strncpy(key, *env, key_len);
|
||||
key[key_len] = '\0';
|
||||
|
||||
const char *value = getenv(key);
|
||||
add_to_hashmap(environment_variables, key,
|
||||
value?new_string_object_null_terminated((char *)value):ARGON_NULL);
|
||||
}
|
||||
const char *value = getenv(key);
|
||||
add_to_hashmap(environment_variables, key,
|
||||
value ? new_string_object_null_terminated((char *)value)
|
||||
: ARGON_NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
add_to_scope(Global_Scope, "env", create_dictionary(environment_variables));
|
||||
@@ -885,7 +888,9 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
|
||||
[OP_MULTIPLICATION] = &&DO_MULTIPLICATION,
|
||||
[OP_DIVISION] = &&DO_DIVISION,
|
||||
[OP_NOT] = &&DO_NOT,
|
||||
[OP_LOAD_SETATTR_METHOD] = &&DO_LOAD_SETATTR_METHOD};
|
||||
[OP_LOAD_SETATTR_METHOD] = &&DO_LOAD_SETATTR_METHOD,
|
||||
[OP_CREATE_DICTIONARY] = &&DO_CREATE_DICTIONARY,
|
||||
[OP_LOAD_SETITEM_METHOD] = &&DO_LOAD_SETITEM_METHOD};
|
||||
_state.head = 0;
|
||||
|
||||
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
|
||||
@@ -1257,13 +1262,29 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
|
||||
}
|
||||
DO_LOAD_SETATTR_METHOD: {
|
||||
state->registers[0] = get_builtin_field_for_class(
|
||||
get_builtin_field(state->registers[0], __class__), __set_attr__,
|
||||
get_builtin_field(state->registers[0], __class__), __setattr__,
|
||||
state->registers[0]);
|
||||
if (!state->registers[0]) {
|
||||
*err = create_err(
|
||||
state->source_location.line, state->source_location.column,
|
||||
state->source_location.length, state->path, "Runtime Error",
|
||||
"unable to get __set_attr__ from objects class");
|
||||
"unable to get __setattr__ from objects class");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
DO_CREATE_DICTIONARY: {
|
||||
state->registers[0] = create_dictionary(createHashmap_GC());
|
||||
continue;
|
||||
}
|
||||
DO_LOAD_SETITEM_METHOD: {
|
||||
state->registers[0] = get_builtin_field_for_class(
|
||||
get_builtin_field(state->registers[0], __class__), __setitem__,
|
||||
state->registers[0]);
|
||||
if (!state->registers[0]) {
|
||||
*err = create_err(
|
||||
state->source_location.line, state->source_location.column,
|
||||
state->source_location.length, state->path, "Runtime Error",
|
||||
"unable to get __setitem__ from objects class");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -122,11 +122,11 @@ sets the source location onto the runtime
|
||||
|
||||
## OP_LOAD_GETATTRIBUTE_METHOD
|
||||
|
||||
loads the \_\_getattribute\_\_ method from the objects class in register 1 and put it into register 1
|
||||
loads the \_\_getattribute\_\_ method from the objects class in register 0 and put it into register 0
|
||||
|
||||
## OP_LOAD_BOOL
|
||||
|
||||
loads a boolean into register 1
|
||||
loads a boolean into register 0
|
||||
|
||||
1. byte representing true or false (1 or 0) *
|
||||
|
||||
@@ -187,4 +187,12 @@ inverts the boolean value in register 0.
|
||||
|
||||
## OP_LOAD_SETATTR_METHOD
|
||||
|
||||
loads the \_\_setattr\_\_ method from the objects class in register 1 and put it into register 1
|
||||
loads the \_\_setattr\_\_ method from the objects class in register 0 and put it into register 0
|
||||
|
||||
## OP_CREATE_DICTIONARY
|
||||
|
||||
create a dictionary object into register 0.
|
||||
|
||||
## OP_LOAD_SETITEM_METHOD
|
||||
|
||||
loads the \_\_setitem\_\_ method from the objects class in register 0 and put it into register 0
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "translator.h"
|
||||
#include "../hash_data/hash_data.h"
|
||||
#include "../parser/dictionary/dictionary.h"
|
||||
#include "../parser/not/not.h"
|
||||
#include "access/access.h"
|
||||
#include "assignment/assignment.h"
|
||||
@@ -176,6 +177,66 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue,
|
||||
push_instruction_byte(translated, OP_NOT);
|
||||
return first;
|
||||
}
|
||||
case AST_DICTIONARY: {
|
||||
DArray *dictionaryDarray = parsedValue->data;
|
||||
|
||||
size_t first = push_instruction_byte(translated, OP_CREATE_DICTIONARY);
|
||||
uint8_t dictionaryRegister = translated->registerAssignment++;
|
||||
|
||||
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||
push_instruction_byte(translated, 0);
|
||||
push_instruction_byte(translated, dictionaryRegister);
|
||||
|
||||
push_instruction_byte(translated, OP_LOAD_SETITEM_METHOD);
|
||||
uint8_t setitemRegister = translated->registerAssignment++;
|
||||
|
||||
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||
push_instruction_byte(translated, 0);
|
||||
push_instruction_byte(translated, setitemRegister);
|
||||
|
||||
for (size_t i = 0; i < dictionaryDarray->size; i++) {
|
||||
ParsedDictionaryEntry *entry = darray_get(dictionaryDarray, i);
|
||||
if (i != 0) {
|
||||
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||
push_instruction_byte(translated, setitemRegister);
|
||||
push_instruction_byte(translated, 0);
|
||||
}
|
||||
push_instruction_byte(translated, OP_INIT_CALL);
|
||||
push_instruction_code(translated, 2);
|
||||
|
||||
translate_parsed(translated, entry->key, err);
|
||||
if (err->exists)
|
||||
return first;
|
||||
|
||||
push_instruction_byte(translated, OP_INSERT_ARG);
|
||||
push_instruction_code(translated, 0);
|
||||
|
||||
translate_parsed(translated, entry->value, err);
|
||||
if (err->exists)
|
||||
return first;
|
||||
|
||||
push_instruction_byte(translated, OP_INSERT_ARG);
|
||||
push_instruction_code(translated, 1);
|
||||
|
||||
push_instruction_byte(translated, OP_CALL);
|
||||
}
|
||||
|
||||
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||
push_instruction_byte(translated, dictionaryRegister);
|
||||
push_instruction_byte(translated, 0);
|
||||
|
||||
push_instruction_byte(translated, OP_LOAD_NULL);
|
||||
push_instruction_byte(translated, dictionaryRegister);
|
||||
|
||||
push_instruction_byte(translated, OP_LOAD_NULL);
|
||||
push_instruction_byte(translated, setitemRegister);
|
||||
|
||||
translated->registerAssignment-=2;
|
||||
return first;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "panic: undefined translation\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,9 @@ typedef enum {
|
||||
OP_MULTIPLICATION,
|
||||
OP_DIVISION,
|
||||
OP_NOT,
|
||||
OP_LOAD_SETATTR_METHOD
|
||||
OP_LOAD_SETATTR_METHOD,
|
||||
OP_CREATE_DICTIONARY,
|
||||
OP_LOAD_SETITEM_METHOD
|
||||
} OperationType;
|
||||
|
||||
void arena_resize(ConstantArena *arena, size_t new_size);
|
||||
|
||||
Reference in New Issue
Block a user