Generate a user manual.
All checks were successful
per-push tests / build (push) Successful in 1m11s
per-push tests / test-frontend (push) Successful in 1m3s
per-push tests / test-utility (push) Successful in 1m3s
per-push tests / test-backend (push) Successful in 58s
per-push tests / timed-decomposer-parse (push) Successful in 1m3s

This commit extends the documentation held in instructions.toml into a
full description of the hyphaeVM design and capabilities. Additionally,
instructions.toml is renamed to vm.toml. Finally, the build script
outputs a text file (hyphae_manual.txt) that provides a comprehensive
manual on the use and effects of HyphaeVM.

fixes: #37

Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
Ava Apples Affine 2025-08-14 07:20:03 +00:00
parent f48867db42
commit 0f85292e6f
5 changed files with 1016 additions and 414 deletions

View file

@ -4,18 +4,74 @@ use std::io::{BufWriter, Write};
use std::path::Path;
use serde::Deserialize;
const DOCUMENTATION_TITLE: &str = r"
";
const DOCUMENTATION_MODES: &str = r"
";
const DOCUMENTATION_REGS: &str = r"
";
const DOCUMENTATION_DTS: &str = r"
";
const DOCUMENTATION_INSTRS: &str = r"
";
#[derive(Deserialize)]
struct Document {
pub instructions: Vec<Instruction>,
pub description: String,
pub datum: String,
pub error_handling: String,
pub sym_table: String,
pub traps: String,
pub registers: Vec<Description>,
pub data_types: Vec<Description>,
pub instructions: Vec<Instruction>,
pub addressing_modes: Vec<AddressingMode>,
}
#[derive(Deserialize)]
struct Description {
pub name: String,
pub description: String,
}
#[derive(Deserialize)]
struct AddressingMode {
pub name: String,
pub mutable: bool,
pub symbol: String,
pub example: String,
pub description: String,
}
// dont warn about unused fields in json instruction struct
#[allow(dead_code)]
#[derive(Deserialize)]
struct Instruction {
pub name: String,
pub args: Vec<String>,
pub output: String,
pub name: String,
pub args: Vec<String>,
pub output: String,
pub description: String,
}
@ -23,12 +79,16 @@ fn main() {
let mut peak = 0;
let output_path = Path::new(&env::var("OUT_DIR").unwrap())
.join("hyphae_instr.rs");
let input = fs::read_to_string("instructions.toml")
let doc_path = Path::new(&env::var("OUT_DIR").unwrap())
.join("hyphae_manual.txt");
let input = fs::read_to_string("vm.toml")
.unwrap();
let mut output_file =
BufWriter::new(File::create(&output_path).unwrap());
let mut manual_file =
BufWriter::new(File::create(&doc_path).unwrap());
let instruction_table: Document =
let doc: Document =
toml::from_str(&input)
.expect("hyphae: failed to parse instructions.toml");
@ -56,7 +116,7 @@ fn main() {
isa_num_args += " pub fn num_args(&self) -> Result<u8, &'static str> {\n";
isa_num_args += " match self.0 {\n";
instruction_table.instructions.iter()
doc.instructions.iter()
.enumerate()
.for_each(|(idx, instr)| {
let const_name = instr.name.to_ascii_uppercase();
@ -109,6 +169,104 @@ fn main() {
write!(&mut output_file, "{}", isa).unwrap();
write!(&mut output_file, "\n\npub const TOTAL_INSTRUCTIONS: usize = {};", peak)
.unwrap();
let separator = "----------------------------\n";
let section_end = "\n\n\n";
let mut documentation = String::from("");
documentation += DOCUMENTATION_TITLE;
documentation += separator;
documentation += &doc.description;
documentation += section_end;
documentation += "Datum\n";
documentation += separator;
documentation += &doc.datum;
documentation += section_end;
documentation += "Error Handling\n";
documentation += separator;
documentation += &doc.error_handling;
documentation += section_end;
documentation += "Symbol Table\n";
documentation += separator;
documentation += &doc.sym_table;
documentation += section_end;
documentation += "Traps\n";
documentation += separator;
documentation += &doc.traps;
documentation += section_end;
documentation += DOCUMENTATION_MODES;
documentation += "\n\n";
doc.addressing_modes.iter()
.for_each(|i| {
documentation += &i.name;
documentation += "\n";
documentation += separator;
if i.mutable {
documentation += "Provides mutable access.\n\n";
}
documentation += "symbol: ";
documentation += &i.symbol;
documentation += "\nexample: ";
documentation += &i.example;
documentation += "\n\n";
documentation += &i.description;
documentation += section_end;
});
documentation += "\n";
documentation += DOCUMENTATION_DTS;
documentation += "\n\n";
doc.data_types.iter()
.for_each(|i| {
documentation += "> ";
documentation += &i.name;
documentation += "\n";
documentation += &i.description;
documentation += section_end;
});
documentation += DOCUMENTATION_REGS;
documentation += "\n\n";
doc.registers.iter()
.for_each(|i| {
documentation += "> ";
documentation += &i.name;
documentation += "\n";
documentation += &i.description;
documentation += section_end;
});
documentation += DOCUMENTATION_INSTRS;
documentation += "\n\n";
doc.instructions.iter()
.for_each(|i| {
documentation += &i.name;
documentation += "\n";
documentation += separator;
documentation += "Arguments:";
i.args.iter().for_each(|j| {
documentation += " ";
documentation += j;
});
documentation += "\n";
documentation += "Sets expression register to: ";
documentation += if !i.output.is_empty() {
&i.output
} else {
"<doesn't write expression register>"
};
documentation += "\n\n";
documentation += &i.description;
documentation += section_end;
});
write!(manual_file, "{}", documentation).unwrap();
println!("cargo::rerun-if-changed=build.rs");
println!("cargo::rerun-if-changed=instructions.json");
println!("cargo::rerun-if-changed=vm.toml");
}