1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
//! # Manchester Small-Scale Experimental Machine "Baby" Emulator Library
//!
//! [](https://crates.io/crates/baby-emulator)
//! [](https://docs.rs/baby-emulator)
//! [](./LICENCE)
//!
//! This library provides a collections of types and methods for emulating & assembling code for
//! the [Machester Baby](https://www.scienceandindustrymuseum.org.uk/objects-and-stories/baby-and-modern-computing), the first program stored
//! computer.
//!
//! ## Explaination
//!
//! The Manchester "Baby" was the first computer to store both its program
//! code and data in a common randomly-accessible memory, it is for this
//! reason the Baby is considered the first machine to run "true" software,
//! providing a familiar (abeit, primitive) programming environment to anyone
//! familiar with assembly, this library can be included in a variety of
//! software and platforms allowing emulation functionality of this historic machine.
//!
//! This library provides an interface for emulating the Baby as a bytecode
//! interpreter ([baby_emulator::core][crate::core]), and also a library for assembling
//! asm using both modern and original asm notations into a format that
//! can be ran by the emulator ([baby_emulator::assmebler][crate::assembler]).
//!
//! Please log any questions or issues to the [GitHub repo](https://github.com/jasonalexander-ja/SSEMBabyEmulator).
//!
//! ## Installation
//!
//! Command line:
//! ```text
//! cargo add baby-emulator
//! ```
//!
//! Cargo.toml:
//! ```text
//! baby-emulator = "0.1.7"
//! ```
//!
//! ## Example
//!
//! This shows a few short examples of what this library is capable of, designed to be a
//! starting point allowing further experimentation by the "user".
//! See [baby_emulator::core][crate::core] and [baby_emulator::assembler][crate::assembler]
//! for further examples and info.
//!
//! ### Bytecode Interpreter Emulation
//!
//! The core of this library is [baby_emulator::core::BabyModel][crate::core::BabyModel],
//! this struct has fields representing all of the Baby's internal
//! registers and 32 word memory, you can initialise this struct with
//! an array of `[i32; 32]`, this array can contain the program code
//! instructions starting at position 0.
//!
//! This example runs an example program that adds 5 to 5 and stores
//! the result in the accumulator. Running here is done with the [BabyModel::run_loop][crate::core::BabyModel::run_loop]
//! method, this method will simply execute sucessive instructions until
//! either an error is thrown (like a stop instruction), or the number
//! os iterations exceeds the specified limmit.
//!
//! ```rust
//! use baby_emulator::core::BabyModel;
//! use baby_emulator::core::errors::BabyErrors;
//! use baby_emulator::core::errors::BabyError;
//!
//! let model = BabyModel::new_example_program();
//! match model.run_loop(100) {
//! (model, BabyErrors::Stop(_)) => println!("{}", model.core_dump()),
//! (_, err) => println!("{}", err.get_descriptor())
//! }
//! ```
//!
//! You can also single set through an emulation, executing a single
//! instruction at a time using the `execute` method and seeing the
//! direct result.
//!
//! ```rust
//! use baby_emulator::core::BabyModel;
//! use baby_emulator::core::errors::BabyError;
//!
//! let model = BabyModel::new_example_program();
//! match model.execute() {
//! Ok(m) => println!("{}", m.core_dump()),
//! Err(e) => println!("Error {}", e.get_descriptor())
//! }
//! ```
//!
//! ### Assembly
//!
//! Here is an example of assembling a Baby asm string using
//! modern notation, then running the resultant program,
//! see the [baby_emulator::assembler][crate::assembler] docs for more information:
//!
//! ```rust
//! use baby_emulator::assembler::assemble;
//! use baby_emulator::core::{BabyModel, instructions::BabyInstruction};
//!
//!
//! const ASM: &str =
//! "
//! ldn $start_value ; Loads 10 into the accumulator
//!
//! :loop_start_value ; The memory address the loop should return to
//! sub $subtract_val ; Subtract 1 from the accumulator
//! cmp ; Skip the next jump instruction if the accumulator is negative
//! jmp $loop_start ; Jump to the start of the loop
//! stp ; Program stops when the accumulator is negative
//!
//! :loop_start ; Pointer to the memory address the loop should return to
//! abs $loop_start_value
//!
//! :subtract_val ; Value to be subtracted
//! abs 0d1
//!
//! :start_value ; Value to start in the accumulator
//! abs 0d-10
//! ";
//!
//! fn main() {
//! let instructions = match assemble(&String::from(ASM), false) {
//! Ok(v) => v,
//! Err(e) => { println!("{}", e.describe(true)); return; }
//! };
//! let main_store = BabyInstruction::to_numbers(instructions);
//!
//! let mut model = BabyModel::new_with_program(main_store);
//! loop {
//! model = match model.execute() {
//! Ok(m) => m,
//! Err(_) => break
//! };
//! }
//! println!("{}", model.core_dump());
//! }
//! ```
//!
/// Contains the core models and emulation functionality.
pub mod core;
/// Contains types and functionality for assembling Baby asm.
pub mod assembler;