diff --git a/libkc3/env.c b/libkc3/env.c
index de4c878..2364634 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -998,7 +998,7 @@ bool env_eval_equal_tag (s_env *env, bool macro, const s_tag *a,
tag_init_copy(dest, b);
else
env_eval_tag(env, b, dest);
- frame_binding_new_copy(env->frame->next, a->data.ident.sym, dest);
+ frame_replace(env->frame->next, a->data.ident.sym, dest);
return true;
}
if (is_unbound_b) {
@@ -1006,7 +1006,7 @@ bool env_eval_equal_tag (s_env *env, bool macro, const s_tag *a,
tag_init_copy(dest, a);
else
env_eval_tag(env, a, dest);
- frame_binding_new_copy(env->frame->next, b->data.ident.sym, dest);
+ frame_replace(env->frame->next, b->data.ident.sym, dest);
return true;
}
if (! macro &&
@@ -2169,8 +2169,9 @@ s_tag * env_let (s_env *env, const s_tag *tag, const s_block *block,
assert(! "env_let: binding key is not a symbol");
return NULL;
}
- if (! frame_binding_new_copy(env->frame, map->key[i].data.sym,
- map->value + i)) {
+ if (! frame_binding_new_copy(env->frame,
+ map->key[i].data.sym,
+ map->value + i)) {
tag_clean(&tmp);
return NULL;
}
diff --git a/libkc3/frame.c b/libkc3/frame.c
index 7da3b5f..373a6ea 100644
--- a/libkc3/frame.c
+++ b/libkc3/frame.c
@@ -27,7 +27,8 @@ s_tag * frame_binding_new (s_frame *frame, const s_sym *name)
return &b->value;
}
-s_frame * frame_binding_new_copy (s_frame *frame, const s_sym *name, const s_tag *value)
+s_frame * frame_binding_new_copy (s_frame *frame, const s_sym *name,
+ const s_tag *value)
{
s_tag *tag;
frame_binding_new(frame, name);
@@ -54,6 +55,36 @@ s_frame * frame_binding_delete (s_frame *frame, const s_sym *name)
return frame;
}
+s_frame * frame_binding_replace (s_frame *frame, const s_sym *name,
+ const s_tag *value)
+{
+ s_tag *tag;
+ tag = binding_get_w(frame->bindings, name);
+ if (tag) {
+ tag_clean(tag);
+ if (! tag_init_copy(tag, value)) {
+ err_puts("frame_binding_new_copy: tag_init_copy 1");
+ assert(! "frame_binding_new_copy: tag_init_copy 1");
+ return NULL;
+ }
+ return frame;
+ }
+ frame_binding_new(frame, name);
+ tag = binding_get_w(frame->bindings, name);
+ if (! tag) {
+ err_puts("frame_binding_new_copy: binding new");
+ assert(! "frame_binding_new_copy: binding new");
+ return NULL;
+ }
+ if (! tag_init_copy(tag, value)) {
+ err_puts("frame_binding_new_copy: tag_init_copy 2");
+ assert(! "frame_binding_new_copy: tag_init_copy 2");
+ frame = frame_binding_delete(frame, name);
+ return NULL;
+ }
+ return frame;
+}
+
s_frame * frame_clean (s_frame *frame)
{
s_frame *next;
@@ -132,3 +163,22 @@ s_frame * frame_new (s_frame *next)
}
return frame;
}
+
+s_frame * frame_replace (s_frame *frame, const s_sym *sym,
+ const s_tag *value)
+{
+ s_frame *f;
+ s_tag *result;
+ assert(sym);
+ f = frame;
+ while (f) {
+ result = binding_get_w(f->bindings, sym);
+ if (result) {
+ tag_clean(result);
+ tag_init_copy(result, value);
+ return frame;
+ }
+ f = f->next;
+ }
+ return frame_binding_new_copy(frame, sym, value);
+}
diff --git a/libkc3/frame.h b/libkc3/frame.h
index 9702c0f..5a97cac 100644
--- a/libkc3/frame.h
+++ b/libkc3/frame.h
@@ -28,9 +28,14 @@ void frame_delete_all (s_frame *frame);
/* Operators. */
s_tag * frame_binding_new (s_frame *frame, const s_sym *name);
-s_frame * frame_binding_new_copy (s_frame *frame, const s_sym *name, const s_tag *value);
+s_frame * frame_binding_new_copy (s_frame *frame, const s_sym *name,
+ const s_tag *value);
s_frame * frame_binding_delete (s_frame *frame, const s_sym *name);
+s_frame * frame_binding_replace (s_frame *frame, const s_sym *name,
+ const s_tag *value);
s_tag * frame_get_w (s_frame *frame, const s_sym *sym);
+s_frame * frame_replace (s_frame *frame, const s_sym *sym,
+ const s_tag *value);
/* Observers. */
const s_tag * frame_get (const s_frame *frame, const s_sym *sym);