From ff133551b35e4e79ae51bda494df3a21c25f251e Mon Sep 17 00:00:00 2001
From: Ben Bridle <ben@derelict.engineering>
Date: Sat, 1 Mar 2025 09:23:55 +1300
Subject: Change binary name to tq

---
 src/bin/tq.rs | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib.rs    |  13 ++++
 src/main.rs   | 187 ----------------------------------------------------------
 3 files changed, 189 insertions(+), 187 deletions(-)
 create mode 100644 src/bin/tq.rs
 create mode 100644 src/lib.rs
 delete mode 100644 src/main.rs

(limited to 'src')

diff --git a/src/bin/tq.rs b/src/bin/tq.rs
new file mode 100644
index 0000000..f22bd14
--- /dev/null
+++ b/src/bin/tq.rs
@@ -0,0 +1,176 @@
+use torque_asm::*;
+
+use log::{info, fatal};
+use switchboard::{Switchboard, SwitchQuery};
+
+use std::io::{Read, Write};
+use std::str::FromStr;
+
+
+fn print_version() -> ! {
+    let version = env!("CARGO_PKG_VERSION");
+    eprintln!("torque assembler, version {version}");
+    eprintln!("written by ben bridle");
+    std::process::exit(0);
+}
+
+fn main() {
+    let mut args = Switchboard::from_env();
+    if args.named("version").as_bool() {
+        print_version();
+    }
+    if args.named("verbose").short('v').as_bool() {
+        log::set_log_level(log::LogLevel::Info);
+    }
+    let source_path = args.positional("source").as_path_opt().map(
+        |p| p.canonicalize().unwrap_or_else(|e| fatal!("{p:?}: {e:?}")));
+    let destination_path = args.positional("destination").as_path_opt();
+    let extension = args.named("ext").default("tq").as_string();
+
+    let no_libs = args.named("no-libs").as_bool();
+    let no_project_libs = args.named("no-project-libs").as_bool();
+    let no_environment_libs = args.named("no-env-libs").as_bool();
+
+    let format = args.named("format").default("debug").as_string();
+    let print_tree = args.named("tree").as_bool();
+    let dry_run = args.named("dry-run").short('n').as_bool();
+
+    let Ok(format) = Format::from_str(format.as_str()) else {
+        fatal!("Unknown format '{format}', expected 'debug', 'inhx', 'inhx32', 'raw', or 'source'. ");
+    };
+
+    // -----------------------------------------------------------------------
+
+    let mut compiler = if let Some(path) = &source_path {
+        info!("Reading program source from {path:?}");
+        Compiler::from_path(path).unwrap_or_else(|err| match err {
+            FileError::InvalidExtension => fatal!(
+                "File {path:?} has invalid extension, must be '.{extension}'"),
+            FileError::NotFound => fatal!(
+                "File {path:?} was not found"),
+            FileError::InvalidUtf8 => fatal!(
+                "File {path:?} does not contain valid UTF-8 text"),
+            FileError::NotReadable => fatal!(
+                "File {path:?} is not readable"),
+            FileError::IsADirectory => fatal!(
+                "File {path:?} is a directory"),
+            FileError::Unknown => fatal!(
+                "Unknown error while attempting to read from {path:?}")
+        })
+    } else {
+        let mut source_code = String::new();
+        info!("Reading program source from standard input");
+        if let Err(err) = std::io::stdin().read_to_string(&mut source_code) {
+            fatal!("Could not read from standard input\n{err:?}");
+        }
+        Compiler::from_string(source_code, "<standard input>")
+    };
+    if compiler.error().is_some() && !no_libs && !no_project_libs {
+        compiler.include_libs_from_parent(&extension);
+    }
+    if compiler.error().is_some() && !no_libs && !no_environment_libs {
+        compiler.include_libs_from_path_variable("TORQUE_LIBS", &extension);
+    }
+
+    if print_tree {
+        compiler.resolver.hierarchy().report()
+    }
+
+    if let Some(error) = compiler.error() {
+        error.report();
+        std::process::exit(1);
+    }
+
+    let merged_source = compiler.get_compiled_source().unwrap_or_else(|error| {
+        error.report();
+        std::process::exit(1);
+    });
+    if format == Format::Source && !dry_run {
+        write_bytes_and_exit(merged_source.as_bytes(), destination_path.as_ref());
+    }
+
+    // -----------------------------------------------------------------------
+
+    // Parse syntactic tokens from merged source code.
+    let path = Some("<merged source>");
+    let syntactic_tokens = SyntacticParser::new(&merged_source, path).parse();
+    report_syntactic_errors(&syntactic_tokens, &merged_source);
+
+    let program = SemanticParser::new(syntactic_tokens).parse();
+    report_semantic_errors(&program, &merged_source);
+
+    // program.print_definitions();
+    let assembled_tokens = program.assemble();
+    report_assembler_errors(&assembled_tokens, &merged_source);
+
+    let bytecode = BytecodeGenerator::new(&assembled_tokens).generate();
+    report_bytecode_errors(&bytecode, &merged_source);
+
+    if !dry_run {
+        match format {
+            Format::Debug => {
+                let mut output = String::new();
+                for word in &bytecode.words {
+                    output.push_str(&word.to_string());
+                    output.push('\n');
+                }
+                write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
+            }
+            Format::Inhx => {
+                let output = format_inhx(&bytecode.words);
+                write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
+            }
+            Format::Inhx32 => {
+                let output = format_inhx32(&bytecode.words);
+                write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
+            }
+            Format::Raw => {
+                let mut output = Vec::new();
+                for word in &bytecode.words {
+                    let value = word.value as u16;
+                    output.extend(value.to_be_bytes());
+                }
+                write_bytes_and_exit(&output, destination_path.as_ref());
+            }
+            Format::Source => unreachable!(),
+        }
+    }
+}
+
+
+fn write_bytes_and_exit<P: AsRef<Path>>(bytes: &[u8], path: Option<&P>) -> ! {
+    match path {
+        Some(path) => match std::fs::write(path, bytes) {
+            Ok(_) => info!("Wrote output to path {:?}", path.as_ref()),
+            Err(err) => fatal!("Could not write to path {:?}\n{err:?}", path.as_ref()),
+        }
+        None => match std::io::stdout().write_all(bytes) {
+            Ok(_) => info!("Wrote output to standard output"),
+            Err(err) => fatal!("Could not write to standard output\n{err:?}"),
+        }
+    }
+    std::process::exit(0);
+}
+
+#[derive(PartialEq)]
+enum Format {
+    Debug,
+    Inhx,
+    Inhx32,
+    Raw,
+    Source,
+}
+
+impl FromStr for Format {
+    type Err = ();
+    fn from_str(string: &str) -> Result<Self, ()> {
+        match string {
+            "debug" => Ok(Self::Debug),
+            "inhx" => Ok(Self::Inhx),
+            "inhx32" => Ok(Self::Inhx32),
+            "raw" => Ok(Self::Raw),
+            "source" => Ok(Self::Source),
+            _ => Err(()),
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d572185
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,13 @@
+mod compiler;
+mod parsers;
+mod report;
+mod tokens;
+mod formats;
+
+pub use compiler::*;
+pub use parsers::*;
+pub use report::*;
+pub use tokens::*;
+pub use formats::*;
+
+pub use assembler::*;
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index f271bcd..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,187 +0,0 @@
-mod compiler;
-mod parsers;
-mod report;
-mod tokens;
-mod formats;
-
-pub use compiler::*;
-pub use parsers::*;
-pub use report::*;
-pub use tokens::*;
-pub use formats::*;
-
-pub use assembler::*;
-use log::{info, fatal};
-use switchboard::{Switchboard, SwitchQuery};
-
-use std::io::{Read, Write};
-use std::str::FromStr;
-
-
-fn print_version() -> ! {
-    let version = env!("CARGO_PKG_VERSION");
-    eprintln!("torque assembler, version {version}");
-    eprintln!("written by ben bridle");
-    std::process::exit(0);
-}
-
-fn main() {
-    let mut args = Switchboard::from_env();
-    if args.named("version").as_bool() {
-        print_version();
-    }
-    if args.named("verbose").short('v').as_bool() {
-        log::set_log_level(log::LogLevel::Info);
-    }
-    let source_path = args.positional("source").as_path_opt().map(
-        |p| p.canonicalize().unwrap_or_else(|e| fatal!("{p:?}: {e:?}")));
-    let destination_path = args.positional("destination").as_path_opt();
-    let extension = args.named("ext").default("tq").as_string();
-
-    let no_libs = args.named("no-libs").as_bool();
-    let no_project_libs = args.named("no-project-libs").as_bool();
-    let no_environment_libs = args.named("no-env-libs").as_bool();
-
-    let format = args.named("format").default("debug").as_string();
-    let print_tree = args.named("tree").as_bool();
-    let dry_run = args.named("dry-run").short('n').as_bool();
-
-    let Ok(format) = Format::from_str(format.as_str()) else {
-        fatal!("Unknown format '{format}', expected 'debug', 'inhx', 'inhx32', 'raw', or 'source'. ");
-    };
-
-    // -----------------------------------------------------------------------
-
-    let mut compiler = if let Some(path) = &source_path {
-        info!("Reading program source from {path:?}");
-        Compiler::from_path(path).unwrap_or_else(|err| match err {
-            FileError::InvalidExtension => fatal!(
-                "File {path:?} has invalid extension, must be '.{extension}'"),
-            FileError::NotFound => fatal!(
-                "File {path:?} was not found"),
-            FileError::InvalidUtf8 => fatal!(
-                "File {path:?} does not contain valid UTF-8 text"),
-            FileError::NotReadable => fatal!(
-                "File {path:?} is not readable"),
-            FileError::IsADirectory => fatal!(
-                "File {path:?} is a directory"),
-            FileError::Unknown => fatal!(
-                "Unknown error while attempting to read from {path:?}")
-        })
-    } else {
-        let mut source_code = String::new();
-        info!("Reading program source from standard input");
-        if let Err(err) = std::io::stdin().read_to_string(&mut source_code) {
-            fatal!("Could not read from standard input\n{err:?}");
-        }
-        Compiler::from_string(source_code, "<standard input>")
-    };
-    if compiler.error().is_some() && !no_libs && !no_project_libs {
-        compiler.include_libs_from_parent(&extension);
-    }
-    if compiler.error().is_some() && !no_libs && !no_environment_libs {
-        compiler.include_libs_from_path_variable("TORQUE_LIBS", &extension);
-    }
-
-    if print_tree {
-        compiler.resolver.hierarchy().report()
-    }
-
-    if let Some(error) = compiler.error() {
-        error.report();
-        std::process::exit(1);
-    }
-
-    let merged_source = compiler.get_compiled_source().unwrap_or_else(|error| {
-        error.report();
-        std::process::exit(1);
-    });
-    if format == Format::Source && !dry_run {
-        write_bytes_and_exit(merged_source.as_bytes(), destination_path.as_ref());
-    }
-
-    // -----------------------------------------------------------------------
-
-    // Parse syntactic tokens from merged source code.
-    let path = Some("<merged source>");
-    let syntactic_tokens = SyntacticParser::new(&merged_source, path).parse();
-    report_syntactic_errors(&syntactic_tokens, &merged_source);
-
-    let program = SemanticParser::new(syntactic_tokens).parse();
-    report_semantic_errors(&program, &merged_source);
-
-    // program.print_definitions();
-    let assembled_tokens = program.assemble();
-    report_assembler_errors(&assembled_tokens, &merged_source);
-
-    let bytecode = BytecodeGenerator::new(&assembled_tokens).generate();
-    report_bytecode_errors(&bytecode, &merged_source);
-
-    if !dry_run {
-        match format {
-            Format::Debug => {
-                let mut output = String::new();
-                for word in &bytecode.words {
-                    output.push_str(&word.to_string());
-                    output.push('\n');
-                }
-                write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
-            }
-            Format::Inhx => {
-                let output = format_inhx(&bytecode.words);
-                write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
-            }
-            Format::Inhx32 => {
-                let output = format_inhx32(&bytecode.words);
-                write_bytes_and_exit(output.as_bytes(), destination_path.as_ref());
-            }
-            Format::Raw => {
-                let mut output = Vec::new();
-                for word in &bytecode.words {
-                    let value = word.value as u16;
-                    output.extend(value.to_be_bytes());
-                }
-                write_bytes_and_exit(&output, destination_path.as_ref());
-            }
-            Format::Source => unreachable!(),
-        }
-    }
-}
-
-
-fn write_bytes_and_exit<P: AsRef<Path>>(bytes: &[u8], path: Option<&P>) -> ! {
-    match path {
-        Some(path) => match std::fs::write(path, bytes) {
-            Ok(_) => info!("Wrote output to path {:?}", path.as_ref()),
-            Err(err) => fatal!("Could not write to path {:?}\n{err:?}", path.as_ref()),
-        }
-        None => match std::io::stdout().write_all(bytes) {
-            Ok(_) => info!("Wrote output to standard output"),
-            Err(err) => fatal!("Could not write to standard output\n{err:?}"),
-        }
-    }
-    std::process::exit(0);
-}
-
-#[derive(PartialEq)]
-enum Format {
-    Debug,
-    Inhx,
-    Inhx32,
-    Raw,
-    Source,
-}
-
-impl FromStr for Format {
-    type Err = ();
-    fn from_str(string: &str) -> Result<Self, ()> {
-        match string {
-            "debug" => Ok(Self::Debug),
-            "inhx" => Ok(Self::Inhx),
-            "inhx32" => Ok(Self::Inhx32),
-            "raw" => Ok(Self::Raw),
-            "source" => Ok(Self::Source),
-            _ => Err(()),
-        }
-    }
-}
-- 
cgit v1.2.3-70-g09d2