/*
 This file is part of the Strada Language (https://github.com/mjflick/strada-lang).
 Copyright (c) 2026 Michael J. Flickinger
 
 This program is free software: you can redistribute it and/or modify  
 it under the terms of the GNU General Public License as published by  
 the Free Software Foundation, version 2.

 This program is distributed in the hope that it will be useful, but 
 WITHOUT ANY WARRANTY; without even the implied warranty of 
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 General Public License for more details.

 You should have received a copy of the GNU General Public License 
 along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* Generated by Strada Self-Hosting Compiler */
/* Package: math_lib */
#include "strada_runtime.h"
#include <string.h>
#include <stdint.h>
#include <stdbool.h>

/* External globals from main module */
extern StradaValue *ARGV;
extern StradaValue *ARGC;

StradaValue* add(StradaValue* a, StradaValue* b);
StradaValue* multiply(StradaValue* a, StradaValue* b);
StradaValue* subtract(StradaValue* a, StradaValue* b);
StradaValue* greet(StradaValue* name);
StradaValue* sum_array(StradaValue* arr);
StradaValue* get_numbers(void);
StradaValue* get_person(void);
StradaValue* describe_person(StradaValue* person);

StradaValue* add(StradaValue* a, StradaValue* b) {
    return strada_new_num(strada_to_num(a) + strada_to_num(b));
}

StradaValue* multiply(StradaValue* a, StradaValue* b) {
    return strada_new_num(strada_to_num(a) * strada_to_num(b));
}

StradaValue* subtract(StradaValue* a, StradaValue* b) {
    return strada_new_num(strada_to_num(a) - strada_to_num(b));
}

StradaValue* greet(StradaValue* name) {
    return strada_new_str(strada_concat(strada_to_str(strada_new_str(strada_concat(strada_to_str(strada_new_str("Hello, ")), strada_to_str(name)))), strada_to_str(strada_new_str("!"))));
}

StradaValue* sum_array(StradaValue* arr) {
    StradaValue *total = strada_new_int(0);
    StradaValue *len = strada_new_int(strada_length(strada_to_str(arr)));
    StradaValue *i = strada_new_int(0);
    while (strada_to_bool(strada_new_int(strada_to_num(i) < strada_to_num(len)))) {
        total = strada_new_num(strada_to_num(total) + strada_to_num(strada_array_get(strada_deref_array(arr), strada_to_int(i))));
        i = strada_new_num(strada_to_num(i) + strada_to_num(strada_new_int(1)));
    }
    return total;
}

StradaValue* get_numbers(void) {
    StradaValue *nums = strada_anon_array(5, strada_new_int(10), strada_new_int(20), strada_new_int(30), strada_new_int(40), strada_new_int(50));
    return nums;
}

StradaValue* get_person(void) {
    StradaValue *person = strada_new_hash();
    strada_hash_set(person->value.hv, strada_to_str(strada_new_str("name")), strada_new_str("Alice"));
    strada_hash_set(person->value.hv, strada_to_str(strada_new_str("age")), strada_new_int(30));
    strada_hash_set(person->value.hv, strada_to_str(strada_new_str("city")), strada_new_str("Boston"));
    return person;
}

StradaValue* describe_person(StradaValue* person) {
    StradaValue *name = strada_hash_get(strada_deref_hash(person), strada_to_str(strada_new_str("name")));
    StradaValue *age = strada_hash_get(strada_deref_hash(person), strada_to_str(strada_new_str("age")));
    return strada_new_str(strada_concat(strada_to_str(strada_new_str(strada_concat(strada_to_str(strada_new_str(strada_concat(strada_to_str(name), strada_to_str(strada_new_str(" is "))))), strada_to_str(age)))), strada_to_str(strada_new_str(" years old"))));
}

/* Qualified name aliases for package math_lib */
StradaValue* math_lib__add(StradaValue* a, StradaValue* b) { return add(a, b); }
StradaValue* math_lib__multiply(StradaValue* a, StradaValue* b) { return multiply(a, b); }
StradaValue* math_lib__subtract(StradaValue* a, StradaValue* b) { return subtract(a, b); }
StradaValue* math_lib__greet(StradaValue* name) { return greet(name); }
StradaValue* math_lib__sum_array(StradaValue* arr) { return sum_array(arr); }
StradaValue* math_lib__get_numbers(void) { return get_numbers(); }
StradaValue* math_lib__get_person(void) { return get_person(); }
StradaValue* math_lib__describe_person(StradaValue* person) { return describe_person(person); }

