Crates.io | cambridge-asm |
lib.rs | cambridge-asm |
version | 0.21.0 |
source | src |
created_at | 2021-04-29 07:09:42.77477 |
updated_at | 2024-11-21 05:25:01.692769 |
description | Run pseudoassembly from Cambridge International syllabus 9618 |
homepage | |
repository | https://github.com/SaadiSave/cambridge-asm |
max_upload_size | |
id | 390939 |
size | 103,724 |
#[macro_use]
extern crate cambridge_asm;
// Import `Core` instruction set
use cambridge_asm::parse::Core;
// Custom instruction
inst! {
ext (ctx) {
// I/O accessed with ctx.io
// Output is ctx.io.write
// Use with write! or writeln! macros
writeln!(ctx.io.write, "This is a custom instruction").unwrap();
// Set r0 to detect custom instruction call
ctx.gprs[0] = 20;
}
}
// Extend `Core` instruction set
extend! {
Ext extends Core {
EXT => ext,
}
}
// Import `Core` instruction set
use cambridge_asm::parse::Core;
// Imports of essential types
use cambridge_asm::{
exec::{Context, ExecFunc, PasmResult},
inst::{InstSet, Op},
};
pub fn ext(ctx: &mut Context, _: &Op) -> PasmResult {
// I/O accessed with ctx.io
// Output is ctx.io.write
// Use with write! or writeln! macros
writeln!(ctx.io.write, "This is a custom instruction").unwrap();
// Set r0 to detect custom instruction call
ctx.gprs[0] = 20;
// Return Ok
Ok(())
}
enum Ext {
EXT,
Parent(Core),
}
impl std::str::FromStr for Ext {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_uppercase().as_str() {
"EXT" => Ok(Self::EXT),
s => Ok(Self::Parent(s.parse::<Core>()?)),
}
}
}
impl std::fmt::Display for Ext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::EXT => f.write_str("EXT"),
Self::Parent(p) => write!(f, "{}", p),
}
}
}
impl InstSet for Ext {
fn as_func_ptr(&self) -> ExecFunc {
match self {
Self::EXT => ext,
Self::Parent(p) => p.as_func_ptr(),
}
}
fn from_func_ptr(f: ExecFunc) -> Result<Self, String> {
const EXT: ExecFunc = ext;
match f {
EXT => Ok(Self::EXT),
f => Ok(Self::Parent(Core::from_func_ptr(f)?)),
}
}
}
fn main() {
use cambridge_asm::{exec::Io, parse::jit};
const PROG: &str = r#"EXT
END
NONE:
"#;
let out = TestStdout::new(vec![]);
let mut e = jit::<Ext>(PROG, Io::default()).unwrap();
e.exec::<Ext>();
// Check if r0 == 20
assert_eq!(e.ctx.gprs[0], 20);
}
Refer to src/parse.rs to see how the Extended
instruction set is made using the macro
#[macro_use]
extern crate cambridge_asm;
inst! {
h (ctx) {
write!(ctx.io.write, "H").unwrap();
}
}
inst! {
e (ctx) {
write!(ctx.io.write, "E").unwrap();
}
}
inst! {
l (ctx) {
write!(ctx.io.write, "L").unwrap();
}
}
inst! {
o (ctx) {
write!(ctx.io.write, "O").unwrap();
}
}
// Define a new instruction set
inst_set! {
Custom {
H => h,
E => e,
L => l,
O => o,
END => cambridge_asm::exec::io::end,
}
}
// Using it
fn main() {
use cambridge_asm::{exec::Io, parse::jit};
// Outputs "HELLO"
const PROG: &str = r#"H
E
L
L
O
END
NONE:
"#;
let out = TestStdout::new(vec![]);
let mut e = jit::<Custom>(PROG, Io::default()).unwrap();
e.exec::<Custom>();
}