about summary refs log tree commit diff stats
path: root/js/scripting-lang/baba-yaga-c/src/scope.c
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/scope.c')
-rw-r--r--js/scripting-lang/baba-yaga-c/src/scope.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/scope.c b/js/scripting-lang/baba-yaga-c/src/scope.c
new file mode 100644
index 0000000..d546989
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/scope.c
@@ -0,0 +1,307 @@
+/**
+ * @file scope.c
+ * @brief Scope management implementation for Baba Yaga
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file implements scope management for the Baba Yaga language.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Scope Entry Structure
+ * ============================================================================ */
+
+typedef struct ScopeEntry {
+    char* name;
+    Value value;
+    bool is_constant;
+    struct ScopeEntry* next;
+} ScopeEntry;
+
+/* ============================================================================
+ * Scope Structure
+ * ============================================================================ */
+
+struct Scope {
+    struct Scope* parent;
+    ScopeEntry* entries;
+    int entry_count;
+    int capacity;
+};
+
+/* ============================================================================
+ * Scope Management Functions
+ * ============================================================================ */
+
+/**
+ * @brief Create a new scope
+ * 
+ * @param parent Parent scope, or NULL for global scope
+ * @return New scope instance, or NULL on failure
+ */
+Scope* scope_create(Scope* parent) {
+    Scope* scope = malloc(sizeof(Scope));
+    if (scope == NULL) {
+        return NULL;
+    }
+    
+    scope->parent = parent;
+    scope->entries = NULL;
+    scope->entry_count = 0;
+    scope->capacity = 0;
+    
+    return scope;
+}
+
+/**
+ * @brief Destroy a scope and all its entries
+ * 
+ * @param scope Scope to destroy
+ */
+void scope_destroy(Scope* scope) {
+    if (scope == NULL) {
+        return;
+    }
+    
+    /* Free all entries */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        ScopeEntry* next = entry->next;
+        
+        /* Destroy the value */
+        baba_yaga_value_destroy(&entry->value);
+        
+        /* Free the entry */
+        free(entry->name);
+        free(entry);
+        
+        entry = next;
+    }
+    
+    free(scope);
+}
+
+/**
+ * @brief Find an entry in the scope chain
+ * 
+ * @param scope Starting scope
+ * @param name Variable name to find
+ * @return Scope entry if found, NULL otherwise
+ */
+static ScopeEntry* scope_find_entry(Scope* scope, const char* name) {
+    while (scope != NULL) {
+        ScopeEntry* entry = scope->entries;
+        while (entry != NULL) {
+            if (strcmp(entry->name, name) == 0) {
+                return entry;
+            }
+            entry = entry->next;
+        }
+        scope = scope->parent;
+    }
+    return NULL;
+}
+
+/**
+ * @brief Get a value from the scope chain
+ * 
+ * @param scope Starting scope
+ * @param name Variable name
+ * @return Value if found, nil otherwise
+ */
+Value scope_get(Scope* scope, const char* name) {
+    if (scope == NULL || name == NULL) {
+        return baba_yaga_value_nil();
+    }
+    
+    ScopeEntry* entry = scope_find_entry(scope, name);
+    if (entry == NULL) {
+        return baba_yaga_value_nil();
+    }
+    
+    /* Return a copy of the value */
+    return baba_yaga_value_copy(&entry->value);
+}
+
+/**
+ * @brief Set a value in the current scope (creates if doesn't exist)
+ * 
+ * @param scope Current scope
+ * @param name Variable name
+ * @param value Value to set
+ * @return true on success, false on failure
+ */
+bool scope_set(Scope* scope, const char* name, Value value) {
+    if (scope == NULL || name == NULL) {
+        return false;
+    }
+    
+    /* Look for existing entry in current scope only */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        if (strcmp(entry->name, name) == 0) {
+            /* Update existing entry */
+            baba_yaga_value_destroy(&entry->value);
+            entry->value = baba_yaga_value_copy(&value);
+            return true;
+        }
+        entry = entry->next;
+    }
+    
+    /* Create new entry */
+    entry = malloc(sizeof(ScopeEntry));
+    if (entry == NULL) {
+        return false;
+    }
+    
+    entry->name = strdup(name);
+    if (entry->name == NULL) {
+        free(entry);
+        return false;
+    }
+    
+    entry->value = baba_yaga_value_copy(&value);
+    entry->is_constant = false;
+    entry->next = scope->entries;
+    scope->entries = entry;
+    scope->entry_count++;
+    
+    return true;
+}
+
+/**
+ * @brief Define a new variable in the current scope
+ * 
+ * @param scope Current scope
+ * @param name Variable name
+ * @param value Initial value
+ * @param is_constant Whether the variable is constant
+ * @return true on success, false on failure
+ */
+bool scope_define(Scope* scope, const char* name, Value value, bool is_constant) {
+    if (scope == NULL || name == NULL) {
+        return false;
+    }
+    
+    /* Check if variable already exists in current scope */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        if (strcmp(entry->name, name) == 0) {
+            /* Variable already exists */
+            return false;
+        }
+        entry = entry->next;
+    }
+    
+    /* Create new entry */
+    entry = malloc(sizeof(ScopeEntry));
+    if (entry == NULL) {
+        return false;
+    }
+    
+    entry->name = strdup(name);
+    if (entry->name == NULL) {
+        free(entry);
+        return false;
+    }
+    
+    entry->value = baba_yaga_value_copy(&value);
+    entry->is_constant = is_constant;
+    entry->next = scope->entries;
+    scope->entries = entry;
+    scope->entry_count++;
+    
+    return true;
+}
+
+/**
+ * @brief Check if a variable exists in the scope chain
+ * 
+ * @param scope Starting scope
+ * @param name Variable name
+ * @return true if variable exists, false otherwise
+ */
+bool scope_has(Scope* scope, const char* name) {
+    if (scope == NULL || name == NULL) {
+        return false;
+    }
+    
+    return scope_find_entry(scope, name) != NULL;
+}
+
+/**
+ * @brief Get all variable names in the current scope
+ * 
+ * @param scope Current scope
+ * @param names Output array for variable names
+ * @param max_names Maximum number of names to return
+ * @return Number of names returned
+ */
+int scope_get_names(Scope* scope, char** names, int max_names) {
+    if (scope == NULL || names == NULL || max_names <= 0) {
+        return 0;
+    }
+    
+    int count = 0;
+    ScopeEntry* entry = scope->entries;
+    
+    while (entry != NULL && count < max_names) {
+        names[count] = strdup(entry->name);
+        count++;
+        entry = entry->next;
+    }
+    
+    return count;
+}
+
+/**
+ * @brief Print scope contents for debugging
+ * 
+ * @param scope Scope to print
+ * @param indent Indentation level
+ */
+void scope_print(Scope* scope, int indent) {
+    if (scope == NULL) {
+        return;
+    }
+    
+    /* Print indentation */
+    for (int i = 0; i < indent; i++) {
+        printf("  ");
+    }
+    
+    printf("Scope (entries: %d):\n", scope->entry_count);
+    
+    /* Print entries */
+    ScopeEntry* entry = scope->entries;
+    while (entry != NULL) {
+        for (int i = 0; i < indent + 1; i++) {
+            printf("  ");
+        }
+        
+        char* value_str = baba_yaga_value_to_string(&entry->value);
+        printf("%s%s = %s\n", 
+               entry->is_constant ? "const " : "",
+               entry->name, 
+               value_str);
+        free(value_str);
+        
+        entry = entry->next;
+    }
+    
+    /* Print parent scope */
+    if (scope->parent != NULL) {
+        for (int i = 0; i < indent; i++) {
+            printf("  ");
+        }
+        printf("Parent scope:\n");
+        scope_print(scope->parent, indent + 1);
+    }
+}