about summary refs log tree commit diff stats
path: root/js/scripting-lang/baba-yaga-c/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/main.c')
-rw-r--r--js/scripting-lang/baba-yaga-c/src/main.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/main.c b/js/scripting-lang/baba-yaga-c/src/main.c
new file mode 100644
index 0000000..84bbb56
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/src/main.c
@@ -0,0 +1,343 @@
+/**
+ * @file main.c
+ * @brief Main entry point for Baba Yaga interpreter
+ * @author eli_oat
+ * @version 0.0.1
+ * @date 2025
+ * 
+ * This file contains the main entry point and command-line interface
+ * for the Baba Yaga scripting language implementation.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "baba_yaga.h"
+
+/* ============================================================================
+ * Constants
+ * ============================================================================ */
+
+#define VERSION "0.0.1"
+#define MAX_LINE_LENGTH 4096
+#define MAX_FILE_SIZE (1024 * 1024) /* 1MB */
+
+/* ============================================================================
+ * Function Declarations
+ * ============================================================================ */
+
+static void print_usage(const char* program_name);
+static void print_version(void);
+static void print_error(const char* message);
+static char* read_file(const char* filename);
+static void run_repl(Interpreter* interp);
+static void run_file(Interpreter* interp, const char* filename);
+static void run_tests(Interpreter* interp, const char* test_dir);
+
+/* ============================================================================
+ * Main Function
+ * ============================================================================ */
+
+/**
+ * @brief Main entry point
+ * 
+ * @param argc Argument count
+ * @param argv Argument vector
+ * @return Exit status
+ */
+int main(int argc, char* argv[]) {
+    Interpreter* interp = NULL;
+    int opt;
+    bool run_repl_mode = false;
+    (void)run_repl_mode; /* TODO: Use run_repl_mode variable */
+    bool run_test_mode = false;
+    char* filename = NULL;
+    char* test_dir = NULL;
+    ExecResult result;
+    Value value;
+
+    /* Parse command line options */
+    while ((opt = getopt(argc, argv, "hvt:f:")) != -1) {
+        switch (opt) {
+        case 'h':
+            print_usage(argv[0]);
+            return EXIT_SUCCESS;
+        case 'v':
+            print_version();
+            return EXIT_SUCCESS;
+        case 't':
+            run_test_mode = true;
+            test_dir = optarg;
+            break;
+        case 'f':
+            filename = optarg;
+            break;
+        default:
+            print_usage(argv[0]);
+            return EXIT_FAILURE;
+        }
+    }
+
+    /* Create interpreter */
+    interp = baba_yaga_create();
+    if (interp == NULL) {
+        print_error("Failed to create interpreter");
+        return EXIT_FAILURE;
+    }
+    
+    /* Set debug level from environment */
+    const char* debug_env = getenv("DEBUG");
+    if (debug_env != NULL) {
+        int debug_level = atoi(debug_env);
+        if (debug_level >= 0 && debug_level <= 5) {
+            baba_yaga_set_debug_level((DebugLevel)debug_level);
+        }
+    }
+
+    /* Execute based on mode */
+    if (run_test_mode) {
+        run_tests(interp, test_dir);
+    } else if (filename != NULL) {
+        run_file(interp, filename);
+    } else if (optind < argc) {
+        /* Check if the argument looks like a file (not starting with -) */
+        char* arg = argv[optind];
+        if (arg[0] != '-' && strchr(arg, ' ') == NULL && strchr(arg, ';') == NULL) {
+            /* Treat as file */
+            run_file(interp, arg);
+        } else {
+            /* Execute source code from command line */
+            char* source = arg;
+            value = baba_yaga_execute(interp, source, strlen(source), &result);
+            if (result == EXEC_SUCCESS) {
+            /* Print result using value_to_string for consistent formatting */
+            /* Don't print special IO return value */
+            if (value.type != VAL_NUMBER || value.data.number != -999999) {
+                char* str = baba_yaga_value_to_string(&value);
+                printf("%s\n", str);
+                free(str);
+            }
+        } else {
+            BabaYagaError* error = baba_yaga_get_error(interp);
+            if (error != NULL) {
+                fprintf(stderr, "Error: %s\n", error->message);
+                baba_yaga_error_destroy(error);
+            } else {
+                fprintf(stderr, "Error: Execution failed\n");
+            }
+        }
+        baba_yaga_value_destroy(&value);
+        }
+    } else {
+        run_repl(interp);
+    }
+
+    /* Cleanup */
+    baba_yaga_destroy(interp);
+    return EXIT_SUCCESS;
+}
+
+/* ============================================================================
+ * Helper Functions
+ * ============================================================================ */
+
+/**
+ * @brief Print usage information
+ * 
+ * @param program_name Name of the program
+ */
+static void print_usage(const char* program_name) {
+    printf("Baba Yaga C Implementation v%s\n", VERSION);
+    printf("Usage: %s [OPTIONS] [SOURCE_CODE]\n", program_name);
+    printf("\nOptions:\n");
+    printf("  -h, --help     Show this help message\n");
+    printf("  -v, --version  Show version information\n");
+    printf("  -f FILE        Execute source code from file\n");
+    printf("  -t DIR         Run tests from directory\n");
+    printf("\nExamples:\n");
+    printf("  %s                    # Start REPL\n", program_name);
+    printf("  %s -f script.txt      # Execute file\n", program_name);
+    printf("  %s 'x : 42; ..out x'  # Execute code\n", program_name);
+    printf("  %s -t tests/          # Run tests\n", program_name);
+}
+
+/**
+ * @brief Print version information
+ */
+static void print_version(void) {
+    printf("Baba Yaga C Implementation v%s\n", VERSION);
+    printf("Copyright (c) 2025 eli_oat\n");
+    printf("License: Custom - see LICENSE file\n");
+}
+
+/**
+ * @brief Print error message
+ * 
+ * @param message Error message
+ */
+static void print_error(const char* message) {
+    fprintf(stderr, "Error: %s\n", message);
+}
+
+/**
+ * @brief Read entire file into memory
+ * 
+ * @param filename Name of file to read
+ * @return File contents (must be freed by caller)
+ */
+static char* read_file(const char* filename) {
+    FILE* file;
+    char* buffer;
+    long file_size;
+    size_t bytes_read;
+
+    /* Open file */
+    file = fopen(filename, "rb");
+    if (file == NULL) {
+        print_error("Failed to open file");
+        return NULL;
+    }
+
+    /* Get file size */
+    if (fseek(file, 0, SEEK_END) != 0) {
+        fclose(file);
+        print_error("Failed to seek to end of file");
+        return NULL;
+    }
+
+    file_size = ftell(file);
+    if (file_size < 0) {
+        fclose(file);
+        print_error("Failed to get file size");
+        return NULL;
+    }
+
+    if (file_size > MAX_FILE_SIZE) {
+        fclose(file);
+        print_error("File too large");
+        return NULL;
+    }
+
+    /* Allocate buffer */
+    buffer = malloc(file_size + 1);
+    if (buffer == NULL) {
+        fclose(file);
+        print_error("Failed to allocate memory");
+        return NULL;
+    }
+
+    /* Read file */
+    rewind(file);
+    bytes_read = fread(buffer, 1, file_size, file);
+    fclose(file);
+
+    if (bytes_read != (size_t)file_size) {
+        free(buffer);
+        print_error("Failed to read file");
+        return NULL;
+    }
+
+    buffer[file_size] = '\0';
+    return buffer;
+}
+
+/**
+ * @brief Run REPL (Read-Eval-Print Loop)
+ * 
+ * @param interp Interpreter instance
+ */
+static void run_repl(Interpreter* interp) {
+    char line[MAX_LINE_LENGTH];
+    ExecResult result;
+    Value value;
+
+    printf("Baba Yaga C Implementation v%s\n", VERSION);
+    printf("Type 'exit' to quit\n\n");
+
+    while (1) {
+        printf("baba-yaga> ");
+        fflush(stdout);
+
+        if (fgets(line, sizeof(line), stdin) == NULL) {
+            break;
+        }
+
+        /* Remove newline */
+        line[strcspn(line, "\n")] = '\0';
+
+        /* Check for exit command */
+        if (strcmp(line, "exit") == 0) {
+            break;
+        }
+
+        /* Skip empty lines */
+        if (strlen(line) == 0) {
+            continue;
+        }
+
+        /* Execute line */
+        value = baba_yaga_execute(interp, line, 0, &result);
+        if (result == EXEC_SUCCESS) {
+            char* str = baba_yaga_value_to_string(&value);
+            printf("%s\n", str);
+            free(str);
+        } else {
+            BabaYagaError* error = baba_yaga_get_error(interp);
+            if (error != NULL) {
+                fprintf(stderr, "Error: %s\n", error->message);
+                baba_yaga_error_destroy(error);
+            }
+        }
+        baba_yaga_value_destroy(&value);
+    }
+}
+
+/**
+ * @brief Execute source code from file
+ * 
+ * @param interp Interpreter instance
+ * @param filename Name of file to execute
+ */
+static void run_file(Interpreter* interp, const char* filename) {
+    char* source;
+    ExecResult result;
+    Value value;
+
+    /* Read file */
+    source = read_file(filename);
+    if (source == NULL) {
+        return;
+    }
+
+    /* Execute source */
+    value = baba_yaga_execute(interp, source, strlen(source), &result);
+    free(source);
+
+    if (result != EXEC_SUCCESS) {
+        BabaYagaError* error = baba_yaga_get_error(interp);
+        if (error != NULL) {
+            fprintf(stderr, "Error: %s\n", error->message);
+            baba_yaga_error_destroy(error);
+        }
+        exit(EXIT_FAILURE);
+    }
+
+    baba_yaga_value_destroy(&value);
+}
+
+/**
+ * @brief Run tests from directory
+ * 
+ * @param interp Interpreter instance
+ * @param test_dir Test directory
+ */
+static void run_tests(Interpreter* interp, const char* test_dir) {
+    (void)interp; /* TODO: Use interp parameter */
+    (void)test_dir; /* TODO: Use test_dir parameter */
+    /* TODO: Implement test runner */
+    printf("Test runner not yet implemented\n");
+    printf("Test directory: %s\n", test_dir);
+}