Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

discuss: ASM as a subset of an existing language #802

Open
0xaatif opened this issue Nov 18, 2024 · 2 comments
Open

discuss: ASM as a subset of an existing language #802

0xaatif opened this issue Nov 18, 2024 · 2 comments

Comments

@0xaatif
Copy link
Contributor

0xaatif commented Nov 18, 2024

between #801 and #299, have we considered using a subset of an existing language our ASM code in?

  • C (I think we need something with tuples in its type system)
  • Rust
  • Typescript
  • Forth
  • Python
@0xaatif
Copy link
Contributor Author

0xaatif commented Nov 18, 2024

Here's a sketch of what this could look like:

use std::{iter, ops::Add};

use tuplez::{ops::Poppable, Tuple}; // 0.14.15

pub trait Load {
    fn load(it: impl Iterator<Item = u8>) -> Self;
}
pub trait Store {
    fn store(&self) -> impl Iterator<Item = u8> + '_;
}
impl Load for u8 {
    fn load(mut it: impl Iterator<Item = u8>) -> Self {
        it.next().unwrap()
    }
}
impl Store for u8 {
    fn store(&self) -> impl Iterator<Item = u8> + '_ {
        iter::once(*self)
    }
}

fn pop<T: Poppable>(t: T) -> (T::PopFrontOutput, T::PopFrontElement) {
    tuplez::TupleLike::pop_front(t)
}

#[derive(Clone)]
pub struct Pointer(usize);
pub struct Memory(Vec<u8>);

pub fn mload_general<Stack0, Stack1, T>(memory: &Memory, stack0: Stack0) -> Tuple<T, Stack1>
where
    Stack0: Poppable<PopFrontElement = Pointer, PopFrontOutput = Stack1>,
    T: Load,
{
    let (stack1, Pointer(ix)) = pop(stack0);
    let t = T::load(memory.0[ix..].iter().copied());
    push(stack1, t)
}

pub fn mstore_general<Stack0, Stack1, Stack2, T>(memory: &mut Memory, stack0: Stack0) -> Stack2
where
    Stack0: Poppable<PopFrontElement = T, PopFrontOutput = Stack1>,
    Stack1: Poppable<PopFrontElement = Pointer, PopFrontOutput = Stack2>,
    T: Store,
{
    let (stack1, t) = pop(stack0);
    let (stack2, Pointer(ix)) = pop(stack1);
    let storeme = t.store().collect::<Vec<_>>();
    memory.0.splice(ix..(ix + storeme.len()), storeme);
    stack2
}

pub fn add<Stack0, Stack1, Stack2, LeftT, RightT, ResultT>(stack0: Stack0) -> Tuple<ResultT, Stack2>
where
    Stack0: Poppable<PopFrontElement = RightT, PopFrontOutput = Stack1>,
    Stack1: Poppable<PopFrontElement = LeftT, PopFrontOutput = Stack2>,
    LeftT: Add<RightT, Output = ResultT>,
{
    let (stack1, right) = pop(stack0);
    let (stack2, left) = pop(stack1);
    let add = left + right;
    push(stack2, add)
}

pub fn push<Stack0, T>(stack0: Stack0, t: T) -> Tuple<T, Stack0> {
    Tuple(t, stack0)
}

pub fn increment_mem<Stack0>(memory: &mut Memory, address: Pointer, stack0: Stack0) -> Stack0
where
    Stack0: Poppable, // this shouldn't be needed
{
    let stack1 = push(stack0, address.clone()); // dest
    let stack2 = push(stack1, address); // src
    let stack3 = mload_general::<_, _, u8>(memory, stack2);
    let stack4 = push(stack3, 1u8);
    let stack5 = add(stack4);
    mstore_general(memory, stack5)
}

#[test]
fn test() {
    let stack = tuplez::Unit;
    let mut memory = Memory(vec![42]);
    let stack = push(stack, ()); // this shouldn't be needed
    let stack = increment_mem(&mut memory, Pointer(0), stack);
    let Tuple((), tuplez::Unit) = stack;
    assert_eq!(memory.0, [43]);
}

@4l0n50
Copy link
Contributor

4l0n50 commented Nov 18, 2024

And the idea would be to compile the .asm files into something like the body of test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
Development

No branches or pull requests

2 participants