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
use std::ops::Deref;

use crate::deserialize_field_name;
use crate::field::Field;
use crate::parser::YamlElement;

#[derive(Debug)]
pub enum Chip<R: CodeRunner + Default> {
    None,
    Memory(MemoryChip),
    Yolol(YololChip<R>),
}

impl<R: CodeRunner + Default> Chip<R> {
    pub fn new(chip_type: String, yaml: &YamlElement) -> Self {
        match chip_type.as_str() {
            "!memory_chip" => Self::Memory(MemoryChip::default()),
            "!yolol_chip" => {
                let mut chip = YololChip {
                    path: yaml["script"].as_str().map(|s| s.to_string()),
                    ..YololChip::default()
                };
                deserialize_field_name!(chip, chip_wait, yaml);
                Self::Yolol(chip)
            }
            _ => Self::None,
        }
    }

    pub fn load(&mut self) {
        if let Self::Yolol(chip) = self {
            if let Some(path) = chip.path.clone() {
                let mut runner = R::default();
                if runner.parse(&path).is_some() {
                    chip.runner = Some(runner);
                } else {
                    println!("cannot find file {}", path);
                }
            }
        }
    }

    pub fn step(&mut self) {
        if let Self::Yolol(chip) = self {
            if chip.chip_wait.deref().into() {
                if let Some(runner) = &mut chip.runner {
                    runner.step()
                }
            }
        }
    }

    pub fn update_globals(&mut self, globals: Vec<Field>) {
        if let Self::Yolol(chip) = self {
            if let Some(runner) = &mut chip.runner {
                runner.update_globals(globals)
            }
        }
    }

    pub fn get_global(&self) -> Vec<Field> {
        if let Self::Yolol(chip) = self {
            if let Some(runner) = &chip.runner {
                return runner.get_global();
            }
        }
        vec![]
    }
}

#[derive(Debug, Default)]
pub struct MemoryChip {}

#[derive(Debug, Default)]
pub struct YololChip<R: CodeRunner + Default> {
    chip_wait: Field,
    path: Option<String>,
    runner: Option<R>,
}

impl<'a, R: CodeRunner + Default> Default for Chip<R> {
    fn default() -> Self {
        Self::None
    }
}

pub trait CodeRunner: Default {
    fn parse(&mut self, path: &str) -> Option<()>;
    fn step(&mut self);
    fn update_globals(&mut self, globals: Vec<Field>);
    fn get_global(&self) -> Vec<Field>;
}

#[derive(Default, Debug)]
pub struct NoneRunner;
impl CodeRunner for NoneRunner {
    fn parse(&mut self, _: &str) -> Option<()> {
        None
    }
    fn step(&mut self) {}

    fn update_globals(&mut self, _: Vec<Field>) {}

    fn get_global(&self) -> Vec<Field> {
        vec![]
    }
}