diff options
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/main.c')
-rw-r--r-- | js/scripting-lang/baba-yaga-c/src/main.c | 514 |
1 files changed, 0 insertions, 514 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/main.c b/js/scripting-lang/baba-yaga-c/src/main.c deleted file mode 100644 index 30c9cbd..0000000 --- a/js/scripting-lang/baba-yaga-c/src/main.c +++ /dev/null @@ -1,514 +0,0 @@ -/** - * @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 <dirent.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; - 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, "hvrt:f:")) != -1) { - switch (opt) { - case 'h': - print_usage(argv[0]); - return EXIT_SUCCESS; - case 'v': - print_version(); - return EXIT_SUCCESS; - case 'r': - run_repl_mode = true; - break; - 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 (run_repl_mode) { - run_repl(interp); - } 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] != '-' && access(arg, F_OK) == 0) { - /* 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 { - /* No arguments - read from stdin (pipe-friendly) */ - char buffer[MAX_FILE_SIZE]; - size_t total_read = 0; - size_t bytes_read; - - /* Read all input from stdin */ - while ((bytes_read = fread(buffer + total_read, 1, - MAX_FILE_SIZE - total_read - 1, stdin)) > 0) { - total_read += bytes_read; - if (total_read >= MAX_FILE_SIZE - 1) { - fprintf(stderr, "Error: Input too large (max %d bytes)\n", MAX_FILE_SIZE); - baba_yaga_destroy(interp); - return EXIT_FAILURE; - } - } - - if (total_read > 0) { - buffer[total_read] = '\0'; - - /* Execute the input */ - value = baba_yaga_execute(interp, buffer, total_read, &result); - if (result == EXEC_SUCCESS) { - /* 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 { - /* No input from stdin and no arguments - show usage */ - print_usage(argv[0]); - } - } - - /* 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 Show this help message\n"); - printf(" -v Show version information\n"); - printf(" -r Start interactive REPL mode\n"); - printf(" -f FILE Execute source code from file\n"); - printf(" -t DIR Run tests from directory\n"); - printf("\nExamples:\n"); - printf(" %s # Execute from stdin (pipe-friendly)\n", program_name); - printf(" %s -r # Start interactive 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'; - - /* DEBUG: Print buffer info */ - DEBUG_DEBUG("File buffer length: %ld", file_size); - DEBUG_DEBUG("File buffer content (first 200 chars): %.*s", - (int)(file_size > 200 ? 200 : file_size), buffer); - - return buffer; -} - -/** - * @brief Run enhanced 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 Interactive REPL v%s\n", VERSION); - printf("Type 'help' for commands, 'exit' to quit\n"); - printf("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n\n"); - - while (1) { - printf("baba-yaga> "); - fflush(stdout); - - if (fgets(line, sizeof(line), stdin) == NULL) { - printf("\n"); - break; - } - - /* Remove newline */ - line[strcspn(line, "\n")] = '\0'; - - /* Check for special commands */ - if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) { - printf(" \n"); - break; - } - - if (strcmp(line, "help") == 0) { - printf("Available commands:\n"); - printf(" help - Show this help message\n"); - printf(" exit - Exit the REPL\n"); - printf(" clear - Clear the screen\n"); - printf("\nLanguage features:\n"); - printf(" Variables: x : 42\n"); - printf(" Functions: f : x -> x + 1\n"); - printf(" Output: ..out \"Hello World\"\n"); - printf(" Patterns: when x is 0 then \"zero\" _ then \"other\"\n"); - printf(" Tables: {a: 1, b: 2}\n"); - continue; - } - - if (strcmp(line, "clear") == 0) { - printf("\033[2J\033[H"); /* ANSI clear screen */ - continue; - } - - /* Skip empty lines */ - if (strlen(line) == 0) { - continue; - } - - /* Execute line */ - value = baba_yaga_execute(interp, line, strlen(line), &result); - if (result == EXEC_SUCCESS) { - /* 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); - } -} - -/** - * @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; - } - - DEBUG_DEBUG("About to execute source of length %zu", strlen(source)); - - /* Execute source */ - value = baba_yaga_execute(interp, source, strlen(source), &result); - DEBUG_DEBUG("Execution completed with result %d", result); - free(source); - - if (result == EXEC_SUCCESS) { - DEBUG_DEBUG("Execution successful, processing result"); - /* 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 { - DEBUG_DEBUG("Execution failed, getting error"); - 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"); - } - exit(EXIT_FAILURE); - } - - DEBUG_DEBUG("About to destroy value"); - baba_yaga_value_destroy(&value); - DEBUG_DEBUG("run_file completed successfully"); -} - -/** - * @brief Run tests from directory - * - * @param interp Interpreter instance - * @param test_dir Test directory - */ -static void run_tests(Interpreter* interp, const char* test_dir) { - printf("๐งช Baba Yaga Test Runner\n"); - printf("========================\n\n"); - - /* Check if directory exists */ - DIR* dir = opendir(test_dir); - if (dir == NULL) { - fprintf(stderr, "โ Error: Cannot open test directory '%s'\n", test_dir); - return; - } - - int total_tests = 0; - int passed_tests = 0; - int failed_tests = 0; - - struct dirent* entry; - char filepath[1024]; - - /* Read all .txt files in the directory */ - while ((entry = readdir(dir)) != NULL) { - /* Skip non-.txt files */ - if (strstr(entry->d_name, ".txt") == NULL) { - continue; - } - - /* Skip hidden files */ - if (entry->d_name[0] == '.') { - continue; - } - - total_tests++; - snprintf(filepath, sizeof(filepath), "%s/%s", test_dir, entry->d_name); - - printf("Running %s... ", entry->d_name); - fflush(stdout); - - /* Read test file */ - char* test_code = read_file(filepath); - if (test_code == NULL) { - printf("โ FAIL (cannot read file)\n"); - failed_tests++; - continue; - } - - /* Execute test code */ - ExecResult result; - Value value = baba_yaga_execute(interp, test_code, strlen(test_code), &result); - - if (result == EXEC_SUCCESS) { - printf("โ PASS\n"); - passed_tests++; - } else { - printf("โ FAIL\n"); - BabaYagaError* error = baba_yaga_get_error(interp); - if (error != NULL) { - printf(" Error: %s\n", error->message); - baba_yaga_error_destroy(error); - } - failed_tests++; - } - - baba_yaga_value_destroy(&value); - free(test_code); - } - - closedir(dir); - - /* Print summary */ - printf("\n๐ Test Summary\n"); - printf("===============\n"); - printf("Total tests: %d\n", total_tests); - printf("Passed: %d\n", passed_tests); - printf("Failed: %d\n", failed_tests); - - if (failed_tests == 0) { - printf("๐ All tests passed!\n"); - } else { - printf("โ %d test(s) failed\n", failed_tests); - } -} |