Some internal optimzations and helpers. (0.41.14)
This commit is contained in:
parent
3a838ae3d5
commit
0d6685abcd
4 changed files with 62 additions and 1 deletions
|
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(fun VERSION 0.41.13 LANGUAGES C)
|
||||
project(fun VERSION 0.41.14 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
|
|
|||
36
src/map.c
36
src/map.c
|
|
@ -99,6 +99,42 @@ int map_set(Value *vm, const char *key, Value v) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert or replace a key in the map with a copy of the provided value.
|
||||
*
|
||||
* Unlike map_set(), this function does NOT take ownership of @p v. The value is
|
||||
* copied according to copy_value() semantics, and the caller retains ownership
|
||||
* of the original.
|
||||
*
|
||||
* @param vm Target Value of type VAL_MAP.
|
||||
* @param key NUL-terminated key string (copied into the map).
|
||||
* @param v Pointer to Value to copy from; not consumed.
|
||||
* @return 1 on success, 0 on error (type mismatch, OOM, or NULL params).
|
||||
*/
|
||||
int map_set_copy(Value *vm, const char *key, const Value *v) {
|
||||
if (!vm || vm->type != VAL_MAP || !vm->map || !key || !v) {
|
||||
return 0;
|
||||
}
|
||||
/* make a defensive copy first so we can reuse map_set path semantics */
|
||||
Value cv = copy_value(v);
|
||||
Map *m = (Map *)vm->map;
|
||||
for (int i = 0; i < m->count; ++i) {
|
||||
if (strcmp(m->keys[i], key) == 0) {
|
||||
free_value(m->vals[i]);
|
||||
m->vals[i] = cv;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!map_ensure_cap(m, m->count + 1)) {
|
||||
free_value(cv);
|
||||
return 0;
|
||||
}
|
||||
m->keys[m->count] = strdup(key);
|
||||
m->vals[m->count] = cv;
|
||||
m->count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Look up a key and copy the stored value into out.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ Value array_concat(const Value *a, const Value *b);
|
|||
Value make_map_empty(void);
|
||||
/** Set key to v (takes ownership); returns 1 on success. */
|
||||
int map_set(Value *m, const char *key, Value v);
|
||||
/** Set key to a copy of v (caller retains ownership); returns 1 on success. */
|
||||
int map_set_copy(Value *m, const char *key, const Value *v);
|
||||
/** Lookup key; returns 1 and copies value to out on success. */
|
||||
int map_get_copy(const Value *m, const char *key, Value *out);
|
||||
/** Test if key exists; returns 1/0. */
|
||||
|
|
|
|||
23
src/vm.c
23
src/vm.c
|
|
@ -546,6 +546,22 @@ void vm_debug_request_continue(VM *vm) {
|
|||
vm->debug_stop_requested = 0;
|
||||
}
|
||||
|
||||
/* --- Centralized operand stack safety helpers --- */
|
||||
/** Return current number of values on the stack. */
|
||||
static inline int vm_stack_count(const VM *vm) { return vm->sp + 1; }
|
||||
|
||||
/** Return available space left on the stack (in Values). */
|
||||
static inline int vm_stack_space(const VM *vm) { return STACK_SIZE - (vm->sp + 1); }
|
||||
|
||||
/** Ensure at least n values are available to pop; aborts on underflow. */
|
||||
static inline void vm_require_stack(VM *vm, int n) {
|
||||
if (n < 0) n = 0;
|
||||
if (vm_stack_count(vm) < n) {
|
||||
fprintf(stderr, "Runtime error: stack underflow (need %d, have %d)\n", n, vm_stack_count(vm));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Push a Value onto the VM operand stack.
|
||||
*
|
||||
|
|
@ -868,6 +884,13 @@ void vm_run(VM *vm, Bytecode *entry) {
|
|||
Instruction inst = f->fn->instructions[f->ip++];
|
||||
vm->instr_count++; /* count each executed instruction */
|
||||
|
||||
/* Validate opcode defensively */
|
||||
if (!opcode_is_valid(inst.op)) {
|
||||
fprintf(stderr, "Runtime error: invalid opcode %d at ip=%d\n", inst.op, f->ip - 1);
|
||||
vm_raise_error(vm, "Invalid opcode");
|
||||
break;
|
||||
}
|
||||
|
||||
if (vm->trace_enabled) {
|
||||
const char *opname = (inst.op >= 0 && inst.op < (int)(sizeof(opcode_names) / sizeof(opcode_names[0])))
|
||||
? opcode_names[inst.op]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue