1use eyre::{eyre, Result};
2
3use crate::lgp::op::{Op, Opcode, Operand};
4
5fn lgp_asm_op(s: &str) -> Result<Op> {
6 let mut tokens = s.split_whitespace();
7 let mut data = [0, 0, 0];
8 let op = match tokens.next().ok_or_else(|| eyre!("missing token"))? {
9 "nop" => Opcode::Nop,
10 "add" => Opcode::Add,
11 "sub" => Opcode::Sub,
12 "mul" => Opcode::Mul,
13 "div" => Opcode::Div,
14 "abs" => Opcode::Abs,
15 "neg" => Opcode::Neg,
16 "pow" => Opcode::Pow,
17 "ln" => Opcode::Log,
18 "load" => Opcode::Load,
19 "mov" => Opcode::IndirectCopy,
20 "jlt" => Opcode::Jlt,
21 "jle" => Opcode::Jle,
22 "jeq" => Opcode::Jeq,
23 _ => return Err(eyre!("unknown instruction format")),
24 };
25 let mut idx = 0;
26 for i in 0..data.len() {
27 match op.operand(i) {
28 Operand::None => {}
29 Operand::Register => {
30 let tok = tokens.next().ok_or_else(|| eyre!("missing register"))?;
31 data[idx] = tok.replace(&[',', '[', ']'][..], "")[1..].parse()?;
32 idx += 1;
33 }
34 Operand::Immediate => {
35 let tok = tokens.next().ok_or_else(|| eyre!("missing immediate for {:?}", op))?;
36 let tok = tok.parse::<f64>()?;
37 data[idx] = (tok.fract() * 256.0).floor() as u8;
38 idx += 1;
39 data[idx] = tok.floor() as u8;
40 return Ok(Op::new(op, data));
42 }
43 Operand::Relative => {
44 let tok = tokens.next().ok_or_else(|| eyre!("missing relative jump immediate"))?;
45 data[idx] = tok.parse::<i8>()? as u8;
46 idx += 1;
47 }
48 }
49 }
50 Ok(Op::new(op, data))
51}
52
53pub fn lgp_asm(s: &str) -> Result<Vec<Op>> {
54 let mut ops = Vec::new();
55 for line in s.lines() {
56 ops.push(lgp_asm_op(line)?);
57 }
58 Ok(ops)
59}