@@ -23,6 +23,55 @@ Env* env_create(Env* parent) {
2323 return env ;
2424}
2525
26+ // Forward declaration for lookup helper used below
27+ static EnvEntry * env_find_local (Env * env , const char * name );
28+
29+ bool env_set_alias (Env * env , const char * name , const char * target_name , DeclType type , bool declare_if_missing ) {
30+ if (!env || !name || !target_name ) return false;
31+ // Ensure the target exists
32+ EnvEntry * target = env_get_entry (env , target_name );
33+ if (!target ) return false;
34+
35+ // Resolve final target through alias chain and ensure no cycle to 'name'
36+ EnvEntry * cur = target ;
37+ int depth = 0 ;
38+ while (cur && cur -> alias_target ) {
39+ if (depth ++ > 256 ) return false;
40+ if (strcmp (cur -> alias_target , name ) == 0 ) return false; // would create cycle
41+ cur = env_get_entry (env , cur -> alias_target );
42+ }
43+ if (!cur ) return false;
44+
45+ // Disallow aliasing to frozen/permafrozen target
46+ if (cur -> frozen || cur -> permafrozen ) return false;
47+
48+ // Find or create local entry
49+ EnvEntry * entry = env_find_local (env , name );
50+ if (!entry ) {
51+ if (!declare_if_missing ) return false;
52+ if (!env_define (env , name , type )) return false;
53+ entry = env_find_local (env , name );
54+ }
55+
56+ // Respect frozen state on the entry itself
57+ if (entry -> frozen || entry -> permafrozen ) return false;
58+
59+ // Type compatibility
60+ if (type != TYPE_UNKNOWN && type != cur -> decl_type ) return false;
61+ entry -> decl_type = cur -> decl_type ;
62+
63+ // Clear any stored value and set alias
64+ if (entry -> initialized ) {
65+ value_free (entry -> value );
66+ entry -> initialized = false;
67+ entry -> value = value_null ();
68+ }
69+ if (entry -> alias_target ) { free (entry -> alias_target ); entry -> alias_target = NULL ; }
70+ entry -> alias_target = strdup (cur -> name );
71+ entry -> initialized = true; // alias is considered an initialized binding
72+ return true;
73+ }
74+
2675void env_free (Env * env ) {
2776 if (!env ) return ;
2877 for (size_t i = 0 ; i < env -> count ; i ++ ) {
@@ -69,6 +118,7 @@ bool env_define(Env* env, const char* name, DeclType type) {
69118 entry -> initialized = false;
70119 entry -> frozen = false;
71120 entry -> permafrozen = false;
121+ entry -> alias_target = NULL ;
72122 entry -> value = value_null ();
73123 return true;
74124}
@@ -77,10 +127,26 @@ bool env_assign(Env* env, const char* name, Value value, DeclType type, bool dec
77127 for (Env * e = env ; e != NULL ; e = e -> parent ) {
78128 EnvEntry * entry = env_find_local (e , name );
79129 if (entry ) {
80- // Respect frozen/permanent-frozen bindings
130+ // If this binding is an alias, route assignment to the alias target
131+ if (entry -> alias_target ) {
132+ const char * target_name = entry -> alias_target ;
133+ if (!target_name ) return false;
134+ EnvEntry * target = env_get_entry (env , target_name );
135+ if (!target ) return false;
136+ // Respect freezing on the target
137+ if (target -> frozen || target -> permafrozen ) return false;
138+ if (target -> initialized ) value_free (target -> value );
139+ target -> value = value_copy (value );
140+ target -> initialized = true;
141+ return true;
142+ }
143+
144+ // Respect frozen/permanent-frozen bindings for normal assignments
81145 if (entry -> frozen || entry -> permafrozen ) {
82146 return false;
83147 }
148+
149+ // Normal assignment: respect frozen/permafrozen bindings
84150 if (entry -> initialized ) {
85151 value_free (entry -> value );
86152 }
@@ -101,9 +167,17 @@ bool env_get(Env* env, const char* name, Value* out_value, DeclType* out_type, b
101167 for (Env * e = env ; e != NULL ; e = e -> parent ) {
102168 EnvEntry * entry = env_find_local (e , name );
103169 if (entry ) {
104- if (out_value ) * out_value = value_copy (entry -> value );
105- if (out_type ) * out_type = entry -> decl_type ;
106- if (out_initialized ) * out_initialized = entry -> initialized ;
170+ // If this entry is an alias, follow chain to final target
171+ EnvEntry * cur = entry ;
172+ int depth = 0 ;
173+ while (cur && cur -> alias_target ) {
174+ if (depth ++ > 256 ) return false; // cycle or too deep
175+ cur = env_get_entry (env , cur -> alias_target );
176+ }
177+ if (!cur ) return false;
178+ if (out_value ) * out_value = value_copy (cur -> value );
179+ if (out_type ) * out_type = cur -> decl_type ;
180+ if (out_initialized ) * out_initialized = cur -> initialized ;
107181 return true;
108182 }
109183 }
@@ -121,6 +195,7 @@ bool env_delete(Env* env, const char* name) {
121195 if (entry -> initialized ) {
122196 value_free (entry -> value );
123197 }
198+ if (entry -> alias_target ) { free (entry -> alias_target ); entry -> alias_target = NULL ; }
124199 entry -> initialized = false;
125200 entry -> value = value_null ();
126201 return true;
@@ -166,10 +241,31 @@ int env_permafrozen(Env* env, const char* name) {
166241 return entry -> permafrozen ? 1 : 0 ;
167242}
168243
244+ // EnvEntry accessors
245+ bool env_entry_initialized (EnvEntry * entry ) {
246+ if (!entry ) return false;
247+ return entry -> initialized ;
248+ }
249+
250+ Value env_entry_value_copy (EnvEntry * entry ) {
251+ if (!entry ) return value_null ();
252+ return value_copy (entry -> value );
253+ }
254+
255+ int env_entry_frozen_state_local (EnvEntry * entry ) {
256+ if (!entry ) return 0 ;
257+ if (entry -> permafrozen ) return -1 ;
258+ if (entry -> frozen ) return 1 ;
259+ return 0 ;
260+ }
261+
169262bool env_exists (Env * env , const char * name ) {
170263 for (Env * e = env ; e != NULL ; e = e -> parent ) {
171264 EnvEntry * entry = env_find_local (e , name );
172265 if (entry && entry -> initialized ) return true;
173266 }
174267 return false;
175- }
268+ }
269+
270+ // Forward declaration for local lookup helper (defined later)
271+ static EnvEntry * env_find_local (Env * env , const char * name );
0 commit comments