#Feedback On Brainfuck interpreter

297 messages · Page 1 of 1 (latest)

shell trench
#

I am new to this.. (might as well say im new to programming as a whole). want some feedback on either how I can improve or if im on the right path and should continue!


struct Interpeter {
    memory: Vec<u8>,
    input: String,
    current: usize,
}

impl Interpeter {
    fn new(input: String) -> Self {
        Interpeter { memory: vec![0; 30_000], input, current: 0 }
    }

    pub fn run(&mut self) {
        let mut it = self.input.chars().peekable();

        while let Some(token) = it.peek() {
            match token {
                '>' => {
                    self.current += 1;
                    it.next().unwrap();
                    while let Some(next) = it.peek() {
                        match next {
                            '+' => {

                                self.memory[self.current] += 1;
                                println!("{:?}", self.memory[self.current]);
                                it.next().unwrap();
                            }

                            '>' => {
                                self.current += 1;
                            }

                            _=> {
                                break;
                            }
                        }
                    }
                }

                _=> {
                    it.next().unwrap();
                    break;
                }
            }
        }
    }
}


fn main() {
    let mut interpeter = Interpeter::new(">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]
>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++
.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.".to_string());


    interpeter.run();
}
warm kernel
#

The trouble you'll run into with using an iterator is that you need to jump around for loops

shell trench
warm kernel
#

Since brainfuck only uses ASCII characters, it's okay to index this as bytes, like this:

let tokens = self.input.as_bytes();

if tokens[2] == b'>' { ... }

That would be the most efficient (and in my opinion, easiest) way

#

(well... if a user types in non-English characters, their encodings may happen to contain bytes corresponding to bf instructions, so be wary about using multilingual comments in the interpreter if you do this)

shell trench
#

okay yeah that okay, why do you do tokens[2]? or just an example?

warm kernel
#

Just an example, 2 would be whatever instruction you're executing

shell trench
#

the*

#

could I do a for loop or?

shell trench
warm kernel
#

You'd keep a counter much like the one for </>, except you increment it after each instruction

#
struct Interpreter {
    instruction: usize,
    // ...
}

while self.instruction < tokens.len() {
    let token = tokens[self.instruction];

    match token { ... }
}
shell trench
#

I see, would have never thought to do it this way

quartz beacon
#

Or the possibly more rusty way:

while let Some(token) = tokens.get(self.instruction) {
    // ...
}
shell trench
#

so this is okay?

while let Some(token) = tokens.get(self.instruction) {
            match token {
                b'>' => {
                    self.current += 1;
                    self.instruction += 1;
                }

                b'+' => {
                    self.instruction += 1;

                    self.memory[self.current] += 1;

                    println!("{:?}", self.memory[self.current]);
                }


                _=> {

                }
            }
        }
#

anything else I need to know?

warm kernel
#

I'd probably put self.instruction += 1 after the match, since it happens in each arm, so there's no point in duplicating it each time

warm kernel
#

Feel free to ping me if you want more help, though I may not be online

shell trench
#

putting self.instruction +=1 makes my code do weird stuff

#

at the end

#

it used to increment till 9 and then pause now it increments from 1 - 14 till the end

#

maybe since I do not handle every character

#

i will fix

#

yeah its cuz I dont handle every character

warm kernel
#

Yes, because before you weren't incrementing when you were on a character you didn't recognize, so it'd get stuck on ones you hadn't handled yet

shell trench
#

right makes sense thank you!

shell trench
#

once I know how to handle everything I will change that

#

perfection:

Current val: 65
Current val: 66
Current val: 67
Current val: 68
Current val: 69
Current val: 70
Current val: 71
Current val: 72
Increased pointer
Memory: [72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

<.

And the diagram:

memory blocks
-------------
[72][0][0][0][0][0]...
^
memory pointer

call the print function. and 'H' is printed to the console.

Wow...that was a lot of freaking work just to print one single character. Why you may ask would you want to waste your time programming is this horribly inefficient programming language?!? Well, because some of us hackers that actually like to do fun and challenging things to expand our minds and make us think and aren't just out to hax0r up a gibson or two to show everyone who's teh 1337. Anyways, carrying on...

If we were to write that in C, it would be like:```
#

Im looking at a tutorial that shows how to write programs in brainfuck and im using that to learn brainfuck + write the interpreter

#

im on the right track since I took this hello world program and my output looks just like what he describes!

#

@warm kernel

#

whats the '.' in brainfuck mean / do?

#

Ah okay no I got it

#

It just means output byte at the data pointer

fierce schooner
static bear
#

how would rayon help here?

shell trench
#

@warm kernel brain fuck only accepts one char when it ask for input correct?

#

with the ','

fierce schooner
static bear
fierce schooner
forest tusk
fierce schooner
hasty sail
#

parallelism wouldn't help, but compiling instructions together might 🙂 for example you can group a consecutive string of +s into one instruction that adds by a delta

#

that would involve some sort of tokenization though

#

also you might want to use Vec<Wrapping<u8>> instead of Vec<u8> if you expect + and - to be overflow-safe

fiery vergeBOT
#

Simple work-stealing parallelism for Rust

Version

1.10.0

Downloads

138 326 808

#

Simple work-stealing parallelism for Rust

Version

1.10.0

Downloads

138 326 808

#

Simple work-stealing parallelism for Rust

Version

1.10.0

Downloads

138 326 808

#

A generic serialization/deserialization framework

Version

1.0.210

Downloads

375 053 950

shell trench
#

My memory:

Mem: [50, 0, 48, 0, 1, 0, 0, 0, 0, 0]

onlien interpeter memory: 50 0 45 0 1 0 0 0 0
on this particular program, my interpeter consistently has 3 more digits to the third memory location that this one
what im using to compare:

https://minond.xyz/brainfuck/

the reason this is so odd is because... no where else does it do this
lmaoo
as in, its only the 3rd location

#

@warm kernel

#
,[>>+>+<<<-]>>>[<<<+>>>-]>+<<[-----[>]>>[<<<+++>>>[-]]
#

this is the program, and for some reason only in this program my memory in the third memory location is always 3 digits higher than the online interpeter

#

the thing is, if this fundamental problem, Programs that print out stuff, like hello world, wouldn't work because I'd be off by a few digits and print the wrong ascii character, but I don't...

warm kernel
#

Also, do you have a github repository I can see?

shell trench
glass epoch
#

I'm guessing you have some error in the jump logic. Maybe you forgot that [ can actually jump forward or something

#

cause that's something I often forget

shell trench
forest tusk
#

the actual semantics of the loop indicates that on [, you check if it is zero then if yes, jump to the corresponding ]

glass epoch
#

this has tripped me up a couple of times

shell trench
#

Thanks for that honestly

#

Both of you

#

Jesus

glass epoch
#

it's very useful for conditional code execution, but people always assume it's just for loops

forest tusk
#

my prev impl of loops does it wrongly actually. but i think it still works lol

glass epoch
#

my handwritten tests always work, because I obviously forget about this when writing them

#

and then my Interpreter inexplicably fails when I copy random code from the internet

shell trench
#

And whatever idea I’m cooking up is atrocious and I’d prefer a solution that’s tried and true

forest tusk
#

maybe use ur AST

shell trench
forest tusk
#

whoops lol

shell trench
#

I’m only parsing and interpreting right now

forest tusk
#

if you are parsing why dont you have an AST yet

shell trench
#

I just didn’t make one I guess..

shell trench
#

Maybe

#

Idk

#

Don’t know a single thing about any of this stuff

#

Just a thought

forest tusk
#
enum Ast {
    Op(Token),
    Loop(Vec<Ast>)
}

enum Token {
    Plus, Minus, Dot, Comma,
    Less, Greater, LeftBracket, RightBracket, 
}
shell trench
#

Interesting okay., i guess I’ll just delete what I have and start from scratch

#

Whenever I’m done remaking the interpreter I’ll send you a GitHub link

#

@warm kernel

warm kernel
#

I'd think you could do the same thing for opening braces as for closing ones, right? How do you implement your looping?

glass epoch
#

In my mind there's two ways to implement a brain fuck interpreter:

  • Small/simple: Interpret char by char; when you hit a [ (and the value is zero) , just skip until after the matching [
  • Faster: Parse it into blocks (group +, match [])
shell trench
#

Skip the [ and match it correctly especially if it’s nested

forest tusk
#

i'd probably just do recursive descent

warm kernel
#

I don't think that's remotely necessary?

#

I'd just go through and make a list of pairs, if you're trying to get fancy without tokenizing; otherwise, if you're not too worried about perf, just scan until you find the right match

glass epoch
#

yeah when you find a [ you just

  • set depth to 1
  • increment your position
    • if you find a [ increment your depth
    • if you find a ] decrement your depth
  • if your depth reaches 0, you're done
shell trench
#

That’s pretty smart

#

Thanks

#

I wasn’t sure how I was gonna do this

glass epoch
#

i think the order is slightly wrong, it should be:

  • set depth to 0
  • repeat:
    • check symbol
      • if [ increment depth
      • if ] decrement depth
    • increment position
    • if depth 0, done
#

but that's small details

shell trench
#

Got it okay thank you!

shell trench
glass epoch
#

I've written brainfuck interpreters before, that's about it for this

shell trench
glass epoch
#

it's been years since I last did this, but honestly, just do it by hand and then think about how you did it and reimplement it in code

hoary fable
warm kernel
fluid glacier
#

valid ASCII here means the characters that are part of brainfuck
if you have a simple loop over bytes of value UTF-8 (which you do if you use String) then you are guaranteed that any b'+' you see is definitely a plus and not part of another character

shell trench
#

@warm kernel

#

my repo

#

and yes I know I can put self.instruction += 1 outside of the match statement instead of calling it in each arm, I just haven't gotten around to it

warm kernel
#

I like the loop stack, but like the others were saying, you also need to skip the loop when you enter one at 0. I'd do this by having a depth counter at 0, and incrementing it whenever you hit a [ you're not entering. Then, before the match statement, check first if the depth is greater than 0; if it is, then use a different match statement that skips any characters but [ and ], which add and subtract to the depth. Immediately after this new match, continue so you don't enter the other one

shell trench
#

Since if loop stack is empty it means we have not entered any loop yet, thus we are at depth 0 and are entering a loop?

#

then if loop stack is not empty and we encounter a [ I increment depth because we are deeper inside now?

#

am I understanding or?

#

I may be a bit confused

warm kernel
#

Sorry, I wasn't quite sure how to word it, so it is confusing

#

I mean you'd have a depth variable, and each loop:

If depth is greater than zero:

  • If you're on a [, increment depth
  • If you're on a ], decrement depth
  • Else, skip the current token

If depth is zero, and you're on a [, and the current cell on the tape is 0:

  • Increment depth by 1
#

Oh, and in that first block there, you continue after incrementing or decrementing depth

shell trench
#

even on ] increment depth?

#

you mean decrement i assume

warm kernel
#

No, I just caught that, that was autocorrect

#

Fixed now

shell trench
#

I see okay np thank you for clarifying this to me its easier to understand now

shell trench
warm kernel
#

Yes, you keep everything you've got, just add what's above before it all

shell trench
#

okay got it

#

@warm kernel you say else skip the current token so self.instruction += 1

b'[' => {
                    if self.depth > 0 {
                        self.depth += 1;
                    } else {
                        match self.memory[self.current] {
                            0 => {
                                self.depth += 1;
                            }

                            _=> {
                                continue;
                            }
                        }
                    }
                    self.loop_stack.push(self.instruction + 1);
                    self.instruction += 1;
                }


#

this is what ive got

warm kernel
#

Did you add anything before the match statement?

shell trench
#

you mean before the match token?

warm kernel
#

Yeah

#

That's where the first set of things I mentioned should go

shell trench
#

bottom match is the other match statement

warm kernel
#

Yes, that's great, though I didn't make it clear you need to also continue if it's a []

shell trench
#

oh so add continue after incrementing, got it

#

or decrementing

shell trench
#

sorry if im being stupid today lol

warm kernel
#

No, I'm the one having trouble, I'm on mobile and still waking up lol

#

But yes, that's correct

shell trench
#

We are both having troubles wholesquadlaughing

#

okay got it thank you so let me show you once more to make sure

#
while let Some(token) = self.tokens.get(self.instruction) {
            if self.depth > 0 {
                match token {
                    b'[' => {
                        self.depth += 1;
                        continue;
                    }

                    b']' => {
                        self.depth -= 1;
                        continue;
                    }

                    _=> {
                        continue;
                    }
                }
            }
         
#

or what i had before was fine?

warm kernel
#

Nope, that looks correct; I'd test it out now and see

shell trench
#

havent put this part yet, is thhis inside the other match statement?

If depth is zero, and you're on a [, and the current cell on the tape is 0:
Increment depth by 1

#

or is this outside of it like the self.depth >0

warm kernel
#

I think you already showed that part, didn't you?

shell trench
#
pub fn run(&mut self) -> Result<(), BrainFuckError> {
        while let Some(token) = self.tokens.get(self.instruction) {
            if self.depth > 0 {
                match token {
                    b'[' => {
                        self.depth += 1;
                        continue;
                    }

                    b']' => {
                        self.depth -= 1;
                        continue;
                    }

                    _=> {
                        continue;
                    }
                }
            }
            match token {
                b'>' => {
                    self.instruction += 1;
                    self.current += 1;
                }

                b'<' => {
                    self.instruction += 1;
                    self.current -= 1; 
                }

                b'+' => {
                    self.instruction += 1;


                    self.memory[self.current] = self.memory[self.current].wrapping_add(1);
                }

                b'-' => {
                    self.instruction += 1;
                    self.memory[self.current] = self.memory[self.current].wrapping_sub(1);
                }

                b'[' => {
                    if self.depth > 0 {
                        self.depth += 1;
                    } else {
                        match self.memory[self.current] {
                            0 => {
                                self.depth += 1;
                            }

                            _=> {
                                continue;
                            }
                        }
                    }
                    self.loop_stack.push(self.instruction + 1);
                    self.instruction += 1;
                }

                b'.' => {
                    self.instruction += 1;
                    print!("{}", self.memory[self.current] as char);
                }

                b',' => {
                    self.instruction += 1;
                    let mut buf = String::new();
                    io::stdin().read_line(&mut buf).unwrap();

                    let input = buf.chars().next().unwrap();
                    self.memory[self.current] = input as u8;

                }

     
#

like this?

#

if thats correct, it seems to get stuck now

warm kernel
#

Mmm, you need to remove that continue in the match block arm

shell trench
#

okay so it was because of the continue; but when I put break it completely messes up the memory output even worse than before so just leave it with nothing inside?

#

okay leaving it with nothing acts like the continue

warm kernel
#

Yeah, instead it goes in the other arm, when the current cell is 0

shell trench
#

when its empty same thing happens like with continue

#

it must be my logic, but it seems everything acts normal if I remove that and leave the other 2 statements, but ofc the output of the memory is still wrong

warm kernel
#

Okay, on desktop now, I should be able to help better

shell trench
#

Nice!

warm kernel
#

Here's the problem snippet:

if self.depth > 0 {
    self.depth += 1;
} else {
    match self.memory[self.current] {
        0 => {
            self.depth += 1;
        }

        _=> {
            continue;
        }
    }
}

First, that if self.depth > 0 isn't necessary, since if it were > 0, it'd have been caught be the if-statement before, right?

if self.depth > 0 {
    match token {
        b'[' => {
            self.depth += 1;
            continue;
        }

        b']' => {
            self.depth -= 1;
            continue;
        }

        _=> {
            continue;
        }
    }
}

So here:

match self.memory[self.current] {
    0 => {
        self.depth += 1;
    }
  
    _=> {
        continue;
    }
}

What you want is:

  • If the current cell is 0, skip this loop (self.depth += 1 accomplishes half of this, but you also need self.instruction += 1), and don't put this on the loop stack (continue) (since you're not looping)
  • If it's not 0, push this onto the loop stack and increment self.instruction

What you have is:

  • If the current cell is 0, skip this loop (self.depth += 1), and since there's no continue after that, you also push it onto the loop stack (which means you'll see weird results)
  • If its not, you do nothing (continue), so you stay on this one token forever
#

If you want I can write out the full statement for you, but hopefully that's more helpful than my vague statements before?

shell trench
#
b'[' => {
                        match self.memory[self.current] {
                            0 => {
                                self.depth += 1;
                                self.instruction += 1;
                            }

                            _=> {
                               self.loop_stack.push(self.instruction + 1);
                               self.instruction +=1 ;
                            }
                        }
                }
warm kernel
#

Yes, that appears to be perfect

#

Does it run?

shell trench
#

I just tested it, however it still clogs / is stuck like the last one

warm kernel
#

Hmm, can I see the example input?

shell trench
#

I put continue on the 0 arm still same thing

#

sure

#

5

warm kernel
#

Oh, I mean the example bf code

shell trench
#

oh haha got it

#

,[>>+>+<<<-]>>>[<<<+>>>-]>+<<[-----[>]>>[<<<+++>>>[-]]

#

things lile hello world still run so its not entirely broken

#

just anything with intricate looping ofc lmao

warm kernel
#

I double-checked, and I don't believe that's valid

#

?eval

let s1 = ",[>>+>+<<<-]>>>[<<<+>>>-]>+<<[-----[>]>>[<<<+++>>>[-]]".chars();
let s2 = s1.clone();

(s1.filter(|ch| *ch == '[').count(), s2.filter(|ch| *ch == ']').count())
fiery vergeBOT
#
(6, 5)```
warm kernel
#

Yeah, you've got unbalanced loops, that won't do anything in any bf interpreter

#

Idk where you got it, but you could try double-checking that what you've got matches what they had?

shell trench
#

you sure? It seems to work on another interpreter

#

sure I will double check

warm kernel
#

That interpreter could be written poorly, but strictly speaking, an interpreter isn't even supposed to allow unbalanced loops

shell trench
#

interesting

#

so was my code still incomplete or was I dealing with faulty brainfuck the whole time

#

I meanI still needed to account for depth

#

but let me find anothe rbrain fuck program

warm kernel
#

Well, your code was still incomplete, but the brainfuck was faulty too

shell trench
#

okay found some code my interpeter wont run

++++[>+++++<-]>[<+++++>-]+<+[
>[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]+
>>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<]
<<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<-
]

#

is it faulty?

#

its suppose to output the square numbers from 0 to 10000

warm kernel
#

Yeah, that's what it does in my interpreter, so it seems valid

#

Is your github up-to-date with your newest changes?

shell trench
#

okay and mine just gets stuck

#

no I will push it right now

warm kernel
#

Okay ty, I'll take a look at it then

#

It's probably my fault for giving bad instructions somewhere, sorry ferrisBut

shell trench
#

I appreciate your help regardless

warm kernel
#

No, that's not true, if it were you wouldn't have gotten this far at all; it was probably the conflicting, confusing advice we've all been giving

warm kernel
shell trench
#

pushed!

shell trench
#

but I understand how this works so

warm kernel
#

Oh, I'm silly, sorry;

if self.depth > 0 {
    // ADDED: this needs to be here, otherwise it'll loop forever
    self.instruction += 1;

    match token {
        b'[' => {
            self.depth += 1;
            continue;
        }

        b']' => {
            self.depth -= 1;
            continue;
        }

        _=> {
            continue;
        }
    }
}
shell trench
#

no way

warm kernel
shell trench
#

lol that was funny

#

it now works fine

#

even the invalid loop

warm kernel
#

That's great, sorry for missing that this whole time

shell trench
#

I too apologize for being oblivious to my own code haha

warm kernel
#

No that's alright lol, it's the little things that we always take for granted, and therefore miss

shell trench
#

indeed lol earlier I forgot to do interpeter.run(), a fun and embarrassing 40 minutes trying to figure out why rust compiles fine but the code doesnt run lmao

warm kernel
# shell trench Sure I would appreciate that a lot, but I must admit my head is not in the right...

So:

When you need to skip a loop (you're on [ and self.memory[self.current] == 0), you need to skip all tokens until the matching ]. So, you could just loop until you find a ]... but there could be other loops inside, like so:

its at zero here [ so now you need to skip all this [ including these [sub] [loops] ] ] you need to skip all the way to here

The easiest way to do that is to just count how many you've loops gone into:

skip from here depth=0 [ depth=1 [ depth=2 [ depth=3 ] depth=2 [ depth=3 ] depth=2 ] depth=1 ] depth=0 skip to here

depth here, means "I've gone into depth loops since I started skipping, which means I need to exit depth loops before I can stop skipping", if that makes sense?

#

And did you understand the loop stack, or would you like clarification there, too?

shell trench
shell trench
warm kernel
#

Awesome, seems like things are going well, then! Just double check that cargo clippy is happy

shell trench
#

And then I understand that if we are entering a loop, and the current memory is 0, then we must skip that entire loop, so we increase the depth and set instruction += 1, otherwise increment instruction and push to the loop stack cuz it’s a loop we need to account for

shell trench
#

Yay my first real project!

warm kernel
#

Gotcha, and good luck!

shell trench
#

I’m happy, couldn’t have done it without you or the others

#

Thanks you all

warm kernel
#

We all need help, I'm just glad to give it!

shell trench
# warm kernel We all need help, I'm just glad to give it!

You will probably see another thread here for me soon, as Im going to attempt to make a memory alloactor in rust, first by following a tutorial about it in C to absorb the concepts, then implementing global alloc, ill probably make a free list since thats the easiest then MAYBE buddy allocator after, but this seems like a long term project so I might find another shorter project in the mean time

#

maybe you have suggestions for a newbie like me?

warm kernel
#

I don't really; a memory allocator will require a lot of low-level knowledge (which a tutorial may or may not introduce), but aside from that it's not that hard

shell trench
#

I know I’ll get better with that in time but, especially for stuff like memory allocator it scares me because it all looks like magic

warm kernel
#

I think most tutorials give code, the trickier part would be translating those concepts to Rust

warm kernel
#

Things like "how does the brk syscall work? (or rather, how does the brk libc call work?)", "how can I just materialize an address", etc.

shell trench
warm kernel
#

I think if you ignore the Rust-specific allocator API, and just focus on translating it, it should work... the hardest part would probably be getting the sbrk function, since in C that's "just there"

shell trench
#

Is this sbrk or no

shell trench
warm kernel
shell trench
#

I am on Linux!

#

I switched to it when I started programming

warm kernel
#

Ah, nice! So then you'll probably use sbrk when writing your allocator

shell trench
#

Okay great!

warm kernel
#

This tutorial looks promising...?

shell trench
#

Okay looks good, shorter than the one I had in mind

warm kernel
#

That's for "advanced engineers", meaning it won't be explaining as many concepts, and what it does explain, it'll explain in "academic language" (that is, it'll be verbose and confusing)

#

You could always try it though, and see how it goes

shell trench
#

Will follow your tutorial

#

Malloc is quite simple, obviously the actual malloc is wayyyyyyy more complicated but yeah

#

However I heard someone say mmap is better to use

warm kernel
#

It is, but probably more complicated (I've never tried)

shell trench
warm kernel
#

The allocator API is unstable, so I wouldn't worry about it; but it's mainly just wrapping up functions like malloc, calloc, free into a nice trait

shell trench
warm kernel
#

The tricky thing is layouts, idk if the tutorial I linked bothers with alignment

#

It doesn't seem like it... hmm, it'll require a bit more trickery

#

Also, it uses cursed union shenanigans ferrisAware

shell trench
#

Oh lord

warm kernel
#

If you don't like the idea of figuring out those details, you might want to try something else

shell trench
#

Yeah I don’t like that idea not while I’m a noob

shell trench
#

Will oook through it at home

warm kernel
#

Gotcha, and good luck

shell trench
#

Like I see a tutorial for making a IP stack

#

In C

#

But what if I were to just use the RFC

#

🤣🤣

warm kernel
#

Depends, the IP stack specifically is extremely convoluted

#

So it's a matter of how much patience you have for understanding weird specifications

shell trench
warm kernel
#

Pick one that seems easier, I guess

shell trench
shell trench