<commit_before>use super::{Memory, VectorMemory, Stack, VectorStack, PC, Result, Gas};
use ::account::Account;

pub type VectorMachine<'p> = Machine<'p, VectorMemory, VectorStack>;

pub struct Machine<'p, M, S> {
    available_gas: Gas,
    pub pc: PC<'p>,
    pub memory: M, // Contains i
    pub stack: S,
    pub account: Account,
}

impl<'p, M, S> Machine<'p, M, S> where M: Memory, S: Stack {
    pub fn new(code: &'p [u8], data: &[u8], available_gas: Gas) -> Self {
        Self {
            available_gas: available_gas,
            pc: PC::new(code),
            memory: M::new(),
            stack: S::new(),
            account: Account::default(),
        }
    }

    pub fn available_gas(&self) -> Gas {
        self.available_gas
    }

    pub fn step(&mut self) -> bool {
        if self.pc.is_stopped() || !self.available_gas.is_valid() {
            return false;
        }

        let opcode = self.pc.read_opcode();
        self.available_gas -= opcode.gas_cost_before(self);
        opcode.run(self);
        self.available_gas -= opcode.gas_cost_after(self);

        true
    }
<commit_msg>Problem: Machine generics makes it hard to append new types to it Solution: (WIP) use associate types<commit_after>use super::{Memory, VectorMemory, Stack, VectorStack, PC, Result, Gas};
use account::{Account, FakeAccount};

pub type VectorMachine<'p> = Machine<'p, VectorMemory, VectorStack, FakeAccount>;

pub trait Machine {
    type P: PC;
    type M: Memory;
    type Sta: Stack;
    type Sto: Storage;
    type T: Transaction;
    type B: Block;
    type Bc: Blockchain;

    fn pc(&self) -> &P;
    fn pc_mut(&mut self) -> &mut P;
    fn memory(&self) -> &M;
    fn memory_mut(&mut self) -> &mut M;
    fn stack(&self) -> &Sta;
    fn stack_mut(&mut self) -> &mut Sta;
    fn storage(&self) -> &Sto;
    fn storage_mut(&mut self) -> &mut Sto;

    fn transaction(&self) -> &T;
    fn block(&self) -> &B;
    fn blockchain(&self) -> &Bc;
    fn available_gas(&self) -> Gas;
}

pub struct VectorMachine {
    pc: VectorPC,
    memory: VectorMemory,
    stack: VectorStack,
    storage: FakeStorage,
    transaction: FakeTransaction,
    block: FakeBlock,
    blockchain: FakeBlockchain,
    available_gas: Gas,
}

impl VectorMachine {
    pub fn new(code: &[u8], data: &[u8], available_gas: Gas) -> VectorMachine {
        VectorMachine {
            pc: VectorPC::new(code),
            memory: VectorMemory::new(),
            stack: VectorStack::new(),
            storage: FakeStorage::new(),
            transaction: FakeTransaction::message_call(U256::zero(), data),
            block: FakeBlock,
            blockchain: FakeBlockchain,
            available_gas: available_gas,
        }
    }
}

impl Machine for VectorMachine {
    type P = VectorPC;
    type M = VectorMemory;
    type Sta = VectorStack;
    type Sto = FakeStorage;
    type T = FakeTransaction;
    type B = FakeBlock;
    type Bc = FakeBlockchain;

    fn pc(&self) -> &P {
        &self.pc
    }

    fn pc_mut(&mut self) -> &mut P {
        &mut self.pc
    }

    fn memory(&self) -> &M {
        &self.memory
    }

    fn memory_mut(&mut self) -> &mut M {
        &mut self.memory
    }

    fn stack(&self) -> &Sta {
        &self.stack
    }

    fn stack_mut(&mut self) -> &mut Sta {
        &mut self.stack
    }

    fn storage(&self) -> &Sto
}

impl<'p, M, S, A> Machine<'p, M, S, A> where M: Memory, S: Stack, A: Account {
    pub fn available_gas(&self) -> Gas {
        self.available_gas
    }

    pub fn step(&mut self) -> bool {
        if self.pc.is_stopped() || !self.available_gas.is_valid() {
            return false;
        }

        let opcode = self.pc.read_opcode();
        self.available_gas -= opcode.gas_cost_before(self);
        opcode.run(self);
        self.available_gas -= opcode.gas_cost_after(self);

        true
    }

{'fraction_non_alphanumeric': 0.13756476683937824, 'fraction_numerical': 0.0018134715025906736, 'mean_word_length': 2.3255813953488373, 'pattern_counts': {'":': 0, '<': 13, '<?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': '7175220', 'n_tokens_mistral': 1271, 'n_tokens_neox': 1260, 'n_words': 343}