Three things before I’ll get to the relevant details.

  1. Brainfuck is a esoteric languages which uses 8 characters. I’ll leave details here - https://en.wikipedia.org/wiki/Brainfuck
  2. G’MIC is a language largely inspired by bash languages and one other shell scripting language, and partly inspired by C++ for JIT compilation. It’s two languages in one as in one outside of JIT and one inside of JIT. It’s main purpose is image processing, and it can do 3D things too, basically image-related things. It’s turing-complete, so making files has been done with it. Even making a executable compiled program is possible in practice (but, I would point to doing C++ and compile there instead).
  3. I am a G’MIC filters developer.

Anyways, I taken some time to code up a Brainfuck interpreter within G’MIC. It wasn’t that hard to do once I understood what Brainfuck is as a language. I did one earlier than this, but I had to have users define inputs beforehand. Recently, I created rep_cin command to relieve users of doing that, and that is the closest to input() within Python or std::cin via C++.

Anyways, here’s the code to my Brainfuck interpreter:

#@cli run_brainfuck_it: brainfuck_file,'_enforce_numbers_input={ 0=false | 1=true },_size_of_array>0
#@cli : Interprets Brainfuck code file within G'MIC brainfuck_interpreter.
#@cli : Default values: ,'_enforce_numbers_input=0','_size_of_array=512'
run_brainfuck_it:
    skip ${2=0},${3=512}
    it $1
    _brainfuck_interpreter $2,$3
    um run_brainfuck_it,run_brainfuck,_brainfuck_interpreter,_brainfuck_interpreter_byte_input
#@cli run_brainfuck: brainfuck_code,'_enforce_numbers_input={ 0=false | 1=true },_size_of_array>0
#@cli : Interprets Brainfuck code within G'MIC brainfuck_interpreter.
#@cli : Default values: ,'_enforce_numbers_input=0','_size_of_array=512'
run_brainfuck:
    skip ${2=0},${3=512}
    ('$1')
    _brainfuck_interpreter $2,$3
    um run_brainfuck_it,run_brainfuck,_brainfuck_interpreter,_brainfuck_interpreter_byte_input
_brainfuck_interpreter:
    # 1. Convert image into dynamic image
    resize 1,{whd#-1},1,1,-1 ({h}) append y # Convert string images into dynamic image
    name[-1] brainfuck_code                 # Name image into brainfuck_code

    # 2. Remove unused characters
    eval "
        const brainfuck_code=$brainfuck_code;
        for(p=h#brainfuck_code-2,p>-1,--p,
            char=i[#brainfuck_code,p];
            if(!(inrange(char,_'+',_'.',1,1)||(find('<>[]',char,0,1)!=-1)),
                da_remove(#brainfuck_code,p);
            );
        );
        if(!da_size(#brainfuck_code),
            run('error inval_code');
        );
        da_freeze(#brainfuck_code);
        "

    # 3. Evaluate brackets
    eval[brainfuck_code] >"
        begin(level=0;);
        i==_'['?++level:
        i==_']'?--level;
        if(level<0,run('error inv_bracks'););
        end(if(level,run('error inv_bracks');););"

    1x2  # Create 2 images of 1x1x1x1. One image is for storing print out characters, and the other is to allow inputs.
    _arg_level=1

    # 4. Create JIT code for executing brainfuck code.
    repeat h#$brainfuck_code {
        idx:=i[#0,$>]

        if $idx==_',' code_str.=run('$0_byte_input[-2]\ $1');ind_list[ind]=i#-2;                continue fi
        if $idx==_'.' code_str.=da_push(#-1,ind_list[ind]);                                     continue fi
        if $idx==_'+' code_str.=ind_list[ind]++;ind_list[ind]%=256;                             continue fi
        if $idx==_'-' code_str.=ind_list[ind]--;ind_list[ind]%=256;                             continue fi
        if $idx==_'<' code_str.=if(!inrange(--ind,0,$2,1,0),run("'error out_of_bound'"););      continue fi
        if $idx==_'>' code_str.=if(!inrange(++ind,0,$2,1,0),run("'error out_of_bound'"););      continue fi
        if $idx==_'[' code_str.=repeat(inf,if(!ind_list[ind],break(););                         continue fi
        if $idx==_']' code_str.=);                                                                       fi
    }

    # 5. Execute created JIT code. v + and v - is used to change verbosity level, not part of JIT execution. e[] is used to print into console.
    v +
    eval >begin(ind=0;ind_list=vector$2(););$code_str;end(da_freeze(#-1););
    v -

    # 6. Print out executed code result
    v + e[$^] "Brainfuck Output: "{t} v -
    remove
_brainfuck_interpreter_byte_input:
    repeat inf {
        wait         # For some reason, I had to add this to make this code work!

        if $> rep_cin "Brainfuck Interpreter - Wrong Input! Insert Integer for Argument#"$_arg_level": "
        else  rep_cin "Brainfuck Interpreter - Enter Argument#"$_arg_level" (Integers Only): "
        fi

        if $1 input:=(${}%208)+_'0'
        else  input=${}
        fi

        if isint($input) break fi
    }

    if $1 
        v + e[$^] "Brainfuck Interpreter Inserted Argument#"$_arg_level": "{$input-_'0'} v -
    else
        input%=256
        v + e[$^] "Brainfuck Interpreter Inserted Argument#"$_arg_level": "$input" :: "{`$input`} v -
    fi

    _arg_level+=1
    f[-1] $input

And the CLI test:

C:\Users\User\Documents\G'MIC\Brainfuck Interpreter>gmic "brainfuck_interpreter.gmic" run_brainfuck \">,>,<<++++++[>-------->--------<<-]>[>[>+>+<<-]>[<+>-]<<-]>[-]>+>>++++++++++<[->-[>>>]++++++++++<<+[<<<]>>>>]<-<++++++++++>>>[-<<<->>>]<<<<++++++[>++++++++>[++++++++>]<[<]>-]>>[.<<]<[<<]>>.\",1
[gmic]./ Start G'MIC interpreter (v.3.3.3).
[gmic]./ Input custom command file 'brainfuck_interpreter.gmic' (4 new, total: 4806).
[gmic]./ Brainfuck Interpreter Inserted Argument#1: 31
[gmic]./ Brainfuck Interpreter Inserted Argument#2: 3
[gmic]./ Brainfuck Output: 93
[gmic]./ End G'MIC interpreter.
4 points

Brain fucked.

At least mine.

permalink
report
reply
2 points

pain

permalink
report
reply

Shell Scripting

!shell@programming.dev

Create post

From Ash, Bash and Csh to Xonsh, Ysh and Zsh; all shell languages are welcome here!

Rules:
  1. Follow Lemmy rules!
  2. Posts must relate to shell scripting. (See bottom of sidebar for more information.)
  3. Only make helpful replies to questions. This is not the place for low effort joke answers.
  4. No discussion about piracy or hacking.
  5. If you find a solution to your problem by other means, please take your time to write down the steps you used to solve your problem in the original post. You can potentially help others having the same problem!
  6. These rules will change as the community grows.

Keep posts about shell scripting! Here are some guidelines to help:

  • Allowed: Release Announcement of a command-line program designed for scripted use (e.g. bash, bats, awk, jq, coreutils/moreutils)
  • Allowed: Tutorials on using shell languages or supplementary tools designed for scripted use
  • Allowed: Code review/help requests for shell languages or supplementary tools designed for scripted use
  • NOT Allowed: Announcement of a CLI or TUI program that is not designed for scripted use (Yes, your fancy Zsh plugin which pretty-prints the date and time using only builtins is very cool, but unless you actually want to discuss the code itself, please check out !commandline instead!)
  • NOT Allowed: Domain-specific tutorials that do not involve shell scripting as a core component (e.g. docker-compose, ansible, nix). If you really love one of these, I’m sure there’s a community out there ready to talk about them!
  • NOT Allowed: Code review requests for non-shell programming languages and configuration languages (e.g. Python, Yaml)

In general, if your submission text is primarily shell code, then it is welcome here!

Community stats

  • 17

    Monthly active users

  • 40

    Posts

  • 132

    Comments