<commit_before>use std::collections::HashMap;

pub struct MachineCode<'a> {
    instructions: Vec<Instruction<'a>>,
    label_locations: HashMap<&'a str, i32>
}

pub struct Instruction<'a> {
    label: &'a str,
    operation: &'a str,
    operands: Vec<&'a str>
}

pub fn parse_instruction<'a>(instruction: &'a str) -> Instruction<'a> {
    let mut instruction_iterator = instruction.split(" ");
    let instruction_vector = instruction_iterator.collect::<Vec<&str>>();

    let mut operands_iterator = instruction_vector[1].split(",");
    let operands_vector = operands_iterator.collect::<Vec<&str>>();

    Instruction {
        label: "",
        operation: instruction_vector[0],
        operands: operands_vector
    }
}

pub fn assemble<'a>(program: &'a str) -> Vec<Instruction<'a>> {
    let instruction_iterator = program.split("\n");
    let mut instructions: Vec<Instruction> = Vec::with_capacity(2);
    let mut label_locations = HashMap::new();

    for (index, line) in instruction_iterator.enumerate() {
        println!("{}", line);
        let instruction = parse_instruction(line);
        if (instruction.label != "") {
          label_locations.insert(instruction.label, index);
        }

        instructions.push(instruction);

    }
    instructions
}

#[test]
fn can_assemble() {
    let program = "ldi r0,$0f\ninc r0";
    let instructions = assemble(program);

    assert_eq!(instructions.len(), 2);

    let ldi = &instructions[0];
    assert_eq!("", ldi.label);
    assert_eq!("ldi", ldi.operation);
    assert_eq!(vec!["r0","$0f"], ldi.operands);

    let inc = &instructions[1];
    assert_eq!("", inc.label);
    assert_eq!("inc", inc.operation);
    assert_eq!(vec!["r0"], inc.operands);
}<commit_msg>assemble now keeps track of labels<commit_after>use std::collections::HashMap;

pub struct MachineCode<'a> {
    instructions: Vec<Instruction<'a>>,
    label_locations: HashMap<&'a str, usize>
}

pub struct Instruction<'a> {
    label: &'a str,
    operation: &'a str,
    operands: Vec<&'a str>
}

pub fn parse_instruction<'a>(instruction: &'a str) -> Instruction<'a> {
    let instruction_iterator = instruction.split(" ");
    let mut instruction_vector = instruction_iterator.collect::<Vec<&str>>();

    let operands_iterator = instruction_vector.pop().unwrap().split(",");
    let operands_vector = operands_iterator.collect::<Vec<&str>>();

    let operation = instruction_vector.pop().unwrap();
    let label = instruction_vector.pop().unwrap_or("");

    Instruction {
        label: label,
        operation: operation,
        operands: operands_vector
    }
}

pub fn assemble<'a>(program: &'a str) -> MachineCode<'a> {
    let instruction_iterator = program.split("\n");
    let mut instructions: Vec<Instruction> = Vec::with_capacity(2);
    let mut label_locations = HashMap::new();

    for (index, line) in instruction_iterator.enumerate() {
        println!("{}", line);
        let instruction = parse_instruction(line);
        if (instruction.label != "") {
          label_locations.insert(instruction.label, index);
        }

        instructions.push(instruction);

    }
    MachineCode {
      instructions: instructions,
      label_locations: label_locations
    }
}

#[test]
fn can_assemble() {
    let program = "ldi r0,$0f\nspecial inc r0";
    let machine_code = assemble(program);

    assert_eq!(machine_code.instructions.len(), 2);

    let ldi = &machine_code.instructions[0];
    assert_eq!("", ldi.label);
    assert_eq!("ldi", ldi.operation);
    assert_eq!(vec!["r0","$0f"], ldi.operands);

    let inc = &machine_code.instructions[1];
    assert_eq!("special", inc.label);
    assert_eq!("inc", inc.operation);
    assert_eq!(vec!["r0"], inc.operands);

    let labels = &machine_code.label_locations;
    assert_eq!(labels.get("special"), Some(&1usize));
}
{'fraction_non_alphanumeric': 0.15936358894105374, 'fraction_numerical': 0.006520605112154408, 'mean_word_length': 3.7639751552795033, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6055222', 'n_tokens_mistral': 1224, 'n_tokens_neox': 1222, 'n_words': 249}