Created
August 2, 2014 07:39
-
-
Save keiya/5788a526dc46ea85fff5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // BrainFsck Ruby Extension by Keiya CHINEN <[email protected]> | |
| // C extension and Ruby src was written by Keiya CHINEN <[email protected]> | |
| // Original version (Pure-C): https://github.com/keiya/brainfuck | |
| #include "ruby.h" | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| char *prog; | |
| int ary[30000]; | |
| int *ptr = ary; | |
| int idx; | |
| int stack[100]; | |
| int stack_flag[100]; | |
| int stack_idx = 0; | |
| void brainfsck(); | |
| void | |
| init() | |
| { | |
| int i; | |
| for (i=0;i<100;i++) { | |
| stack[i] = 0; | |
| stack_flag[i] = 0; | |
| } | |
| } | |
| void | |
| push(int val,int flag) | |
| { | |
| if (stack_idx < 100) { | |
| stack[stack_idx++] = val; | |
| stack_flag[stack_idx] = flag; | |
| } | |
| else { | |
| fprintf(stderr,"stack overflow"); | |
| exit(EXIT_FAILURE); | |
| } | |
| } | |
| int | |
| pop() | |
| { | |
| if (stack_idx > 0) { | |
| int tmp = stack[--stack_idx]; | |
| return tmp; | |
| } | |
| else { | |
| fprintf(stderr,"stack underflow"); | |
| exit(EXIT_FAILURE); | |
| } | |
| } | |
| int | |
| check() | |
| { | |
| int i; | |
| return stack_flag[stack_idx]; | |
| } | |
| int | |
| interpret(int startidx) | |
| { | |
| int ch = prog[idx]; | |
| switch (ch) { | |
| case '>': | |
| idx++; | |
| if (check()) break; | |
| ptr++; | |
| break; | |
| case '<': | |
| idx++; | |
| if (check()) break; | |
| ptr--; | |
| break; | |
| case '+': | |
| idx++; | |
| if (check()) break; | |
| (*ptr)++; | |
| break; | |
| case '-': | |
| idx++; | |
| if (check()) break; | |
| (*ptr)--; | |
| break; | |
| case '.': | |
| idx++; | |
| if (check()) break; | |
| //putchar(*ptr); | |
| rb_funcall(rb_mKernel, rb_intern("print"),1, rb_str_new_cstr(ptr)); | |
| fflush(stdout); | |
| break; | |
| case ',': | |
| idx++; | |
| if (check()) break; | |
| //*ptr = getchar(); | |
| VALUE str = rb_funcall(rb_stdin, rb_intern("getc"),0); | |
| strncpy(ptr, StringValueCStr(str), 1); | |
| //*ptr = StringValueCStr(str); | |
| break; | |
| case '[': | |
| if (*ptr == 0) { | |
| push(idx,1); | |
| idx++; | |
| } | |
| else { | |
| push(idx,0); | |
| idx++; | |
| } | |
| break; | |
| case ']': | |
| if (check() != 1) { | |
| idx = pop(); | |
| } | |
| else { | |
| pop(); | |
| idx++; | |
| } | |
| break; | |
| case '\0': | |
| return 0; | |
| default: | |
| idx++; | |
| break; | |
| } | |
| return 1; | |
| } | |
| VALUE exec(VALUE self, VALUE bf) | |
| { | |
| char *str = StringValueCStr(bf); | |
| init(); | |
| unsigned long sz = strlen(str); | |
| int i; | |
| for (i=0; i<30000; i++) | |
| ary[i] = 0; | |
| if (NULL == (prog = (char *)malloc(sz))) { | |
| fprintf(stdout,"malloc\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| strcpy(prog,str); | |
| fflush(stdin); | |
| idx = 0; | |
| while(interpret(0)) { | |
| } | |
| return Qnil; | |
| } | |
| void Init_brainfsck(void){ | |
| VALUE rb_cBf; | |
| rb_cBf = rb_define_class("BrainFsck", rb_cObject); | |
| rb_define_method(rb_cBf, "exec", exec, 1); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # BrainFsck | |
| # C extension and Ruby src was written by Keiya CHINEN <[email protected]> | |
| # brainf*ck test code by http://www.kmonos.net/alang/etc/brainfuck.php | |
| require_relative "brainfsck.bundle" | |
| bf = BrainFsck.new | |
| # Hello World! | |
| d = bf.exec(">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+.[-]++++++++++.") | |
| puts() | |
| # Hoge | |
| bf.exec("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.+++++++.--------.--.") | |
| puts() | |
| # Hoge (uses loop) | |
| bf.exec("++++++++++[>++++++++++<-]>++++.+++++++.--------.--."); | |
| puts() | |
| # Hello World! (alternative way) | |
| bf.exec("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.") | |
| puts() | |
| # Multiply | |
| puts("4*2=") | |
| bf.exec("++++>++><<[- >[->>+<<] >>[-<+<+>>] <<<]>>++++++++++++++++++++++++++++++++++++++++++++++++.") | |
| puts() | |
| # conditional test (uppercase to lowercase) | |
| puts("Upper Case to Lower Case. please input :") | |
| bf.exec(<<-eos | |
| ### init: ################################## | |
| >>++++++++[->++++++++<]> # {3} = 0x40 | |
| >>>+++++++++[->++++++++++<]> # {7} = 0x5A ptr=7 | |
| ### main: ################################## | |
| [<<, # {5} = getchar() | |
| ## 00 00 00 40 00 *ch 00 5A 00 00 00 | |
| [->+<<+<<+>>>] # {2:4:6} = !{5} | |
| <<<[->>>+<<<]>>> # {5} = !{2} | |
| ## 00 00 00 40 ch *ch ch 5A 00 00 00 | |
| >>[->+>>+<<<]> # {8:10} = !{7} | |
| ## 00 00 00 40 ch ch ch 00 *5A 00 5A | |
| [ # while( {8} ) do | |
| <<[->+>>+<<<]>> # {7:9} = !{6} | |
| >[-<<<+>>>]< # {6} = !{9} | |
| <[[-]<->]> # if({7}) then decr{6} | |
| - # decr {8} | |
| ] # end | |
| >>[-<<<+>>>]<<<<< # {7} = !{10} | |
| ## 00 00 00 40 ch *ch ans1 5A 00 00 00 | |
| ## ans1 = 0 iff input le 5A | |
| <<[-<+<<+>>>]< # {0:2} = !{3} | |
| ## 40 00 *40 00 ch ch ans1 5A 00 00 00 | |
| [ # while( {2} ) do | |
| >>[-<+<<+>>>]<< # {1:3} = !{4} | |
| <[->>>+<<<]> # {4} = !{1} | |
| >[[-]>-<]< # if({3}) then decr{4} | |
| - # decr {2} | |
| ] # end | |
| <<[->>>+<<<]>>>>> # {3} = !{0} | |
| ## 00 00 00 40 ans2 *ch ans1 5A 00 00 00 | |
| ## ans2 = 0 iff input le 40 | |
| # if(ans2) if(not ans1) {5} add 0x20 | |
| <[[-] # if( {4} ) then do | |
| >++++++++++++++++++++++++++++++++ # {5} add 0x20 | |
| >[[-] # if( !{6} ) then do | |
| <--------------------------------> # {5} sub 0x20 | |
| ]<< # end | |
| ]>>[-]< # end; !{6} | |
| ## 00 00 00 40 00 *ch 00 5A 00 00 00 | |
| .>>] # putchar {5} | |
| eos | |
| ) | |
| # echo (gets from STDIN => puts to STDOUT) | |
| #bf.exec("+[>,.<]") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'mkmf' | |
| create_makefile('brainfsck') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment