unlab-gpu 0.1.0

Micro scripting language for neural networks that uses unmtx-gpu.
Documentation
//
// Copyright (c) 2025-2026 Ɓukasz Szpakowski
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::exit;
use std::sync::Arc;
use std::sync::RwLock;
use clap::Parser;
use unlab_gpu::Home;
use unlab_gpu::ModNode;
use unlab_gpu::Value;
use unlab_gpu::add_std_builtin_funs;
use unlab_gpu::finalize_backend;
use unlab_gpu::initialize_backend;
use unlab_gpu::main_loop;

#[derive(Parser, Debug)]
#[command(version)]
struct Args
{
    /// Unlab-gpu home directory
    #[arg(short = 'H', long)]
    home_dir: Option<String>,
    /// Binary path
    #[arg(short = 'B', long)]
    bin_path: Option<String>,
    /// Library path
    #[arg(short = 'L', long)]
    lib_path: Option<String>,
    /// Documentation path
    #[arg(short = 'D', long)]
    doc_path: Option<String>,
    /// Add directory to binary path
    #[arg(short, long)]
    bin_dir: Vec<String>,
    /// Add directory to library path
    #[arg(short, long)]
    lib_dir: Vec<String>,
    /// Add directory to documentation path
    #[arg(short, long)]
    doc_dir: Vec<String>,
    /// Don't handle CTRL-C
    #[arg(short, long)]
    no_ctrl_c: bool,
    /// Don't show plotter windows
    #[arg(short = 'p', long)]
    no_plotter_windows: bool,
    /// Script file
    script_file: Option<String>,
    /// Arguments
    args: Vec<String>,
}

fn main()
{
    let args = Args::parse();
    let mut home = match Home::new(&args.home_dir, &args.bin_path, &args.lib_path, &args.doc_path, false) {
        Some(tmp_home) => tmp_home,
        None => {
            eprintln!("no unlab-gpu home directory");
            exit(1);
        },
    };
    match home.add_dirs_to_bin_path(args.bin_dir.as_slice()) {
        Ok(()) => (),
        Err(err) => {
            eprintln!("{}", err);
            exit(1);
        },
    }
    match home.add_dirs_to_lib_path(args.lib_dir.as_slice()) {
        Ok(()) => (),
        Err(err) => {
            eprintln!("{}", err);
            exit(1);
        },
    }
    match home.add_dirs_to_doc_path(args.doc_dir.as_slice()) {
        Ok(()) => (),
        Err(err) => {
            eprintln!("{}", err);
            exit(1);
        },
    }
    match initialize_backend(home.backend_config_file()) {
        Ok(()) => (),
        Err(err) => {
            eprintln!("{}", err);
            exit(1);
        },
    }
    let exit_code = {
        let mut root_mod: ModNode<Value, ()> = ModNode::new(());
        add_std_builtin_funs(&mut root_mod);
        let root_mod_arc = Arc::new(RwLock::new(root_mod));
        main_loop(args.script_file.clone(), args.args.clone(), PathBuf::from(home.history_file()), root_mod_arc, OsString::from(home.lib_path()), OsString::from(home.doc_path()), !args.no_ctrl_c, !args.no_plotter_windows)
    };
    match finalize_backend() {
        Ok(()) => (),
        Err(err) => {
            eprintln!("{}", err);
            exit(1);
        },
    }
    match exit_code {
        Some(exit_code) => exit(exit_code),
        None => (),
    }
}