www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Just for fun brainfuck'a'like textprocessor

reply Gregor Kopp <gk cutcopy.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hi, I've just written this small peace of thing.
Have fun with it.

I think everyone should read code from others, so I for myself want to 
provide you my code. If you have improvements: post it ;)
May 22 2007
next sibling parent reply janderson <askme me.com> writes:
Gregor Kopp wrote:
 Hi, I've just written this small peace of thing.
 Have fun with it.
 
 I think everyone should read code from others, so I for myself want to 
 provide you my code. If you have improvements: post it ;)
 
 

Nice work! BTW: did you see Gregor Richards compile time version? Gregor Richards ------------------------------------------------------------ ctbf.d: ------------------------------------------------------------ module ctbf; import std.cstream; import std.stdio; static char[] ctbf(char[] bf) { char[] code = ` byte[] mem; uint memptr = 0; mem.length = 1; void expand() { if (mem.length <= memptr) { mem.length = memptr + 1; } } `; foreach (c; bf) { switch (c) { case '>': code ~= "memptr++; expand();\n"; break; case '<': code ~= "memptr--;\n"; break; case '+': code ~= "mem[memptr]++;\n"; break; case '-': code ~= "mem[memptr]--;\n"; break; case '[': code ~= "while (mem[memptr]) {\n"; break; case ']': code ~= "}\n"; break; case '.': code ~= "dout.write(cast(char) mem[memptr]);\n"; break; case ',': code ~= "din.read(mem[memptr]);\n"; break; default: } } return code; } int main() { mixin(ctbf(import("helloworld.bf"))); return 0; }
May 22 2007
parent reply Gregor Kopp <gk cutcopy.com> writes:
janderson wrote:
 Nice work!

thank you! just for safety: change the part handling the case '[': to: case '[': klammernstack.push(kommandoindex); break; got braindamage yesterday... I tried to compile Gregor Richtards version with dmd 1.014 on windows xp, but it didn't work: D:\>dmd ctbf.d ctbf.d(62): Error: need -Jpath switch to import text file helloworld.bf ctbf.d(62): Error: cannot evaluate ctbf("") at compile time ctbf.d(62): Error: argument to mixin must be a string, not (ctbf("")) helloworld.bf did exist in the same directory with the following content: ,[.,] This brainfuck program should print what you type in, till you kill the brainfuck interpreter. I fiddled around with din, cget(stdin), getchar, fflush(stdin) and so on... but I didn't get managed, that a console program just read a keystroke and continues. It always wants a linebreak. I readed in several c-book, they say: fflush(stdin) isn't covered completely in ansi standard, so it's behaviour may change from system to system. Hm. difficulty to implement the , then...
May 23 2007
next sibling parent reply Gregor Kopp <gk cutcopy.com> writes:
Gregor Kopp wrote:
 helloworld.bf did exist in the same directory with the following content:
 
 ,[.,]

Sorry, change the testprogram to the following: ,[..,] it should print the entered key twice, till you kill the interpreter.
May 23 2007
parent reply davidb <ta-nospam-zz gmx.at> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

 Gregor Kopp wrote:

So, what about a kind of "official" RFC - please comment my code so I can improve my style? (just put "RFC ..." in the topic) This way, you could not only learn through your own code being commented upon, but also through watching other people's style & improvements! That said, I'll make a first try Gregor Kopp's code: 1) You'd definitely want a default case in your switch statement which btw. fits nicely with "other characters (which are ignored)" (http://en.wikipedia.org/wiki/Brainfuck) (currently it exits with an "Error: Switch Default ..." if it encounters any other symbol than the ones checked for) 2) Just personal preference, but I'd try not to put too much functionality in main(), makes code more clear and above all: easier reusable (okay, its a bf interpreter, no big reuse here ;-). 3) []-handling: not quite the specs implemented, but nicely done with a stack :-) 4) line 61: I don't quite see why you use char[] initialized with 1 for cells, but that's probably just me. 5) line 62: if "for (;;) ... " has only one statement(?), you don't need enclosing {} (just cosmetics, but hey - 2 chars less typing *g*) (or did you use it here as a means to show your intention more clearly?) 6) descriptive names in addition to clear indentation => very easily readable code, nice! Nice work Gregor Kopp! Considering the Stack class: I'm not quite sure about the use of "this.length" in the various contexts, could someone please explain it to me? NB: (because I saw it in Gergor Kopps' code) Just a little gem from the specs: "Integers can have embedded '_' characters, which are ignored. The embedded '_' are useful for formatting long literals, such as using them as a thousands separator" (http://www.digitalmars.com/d/lex.html#integerliteral) (e.g. 300_000, 1_925_200, ...) david and attached, also a little bf interpreter
May 23 2007
next sibling parent reply janderson <askme me.com> writes:
davidb wrote:
[snip]
 5) line 62:
    if "for (;;) ... " has only one statement(?), you don't need
    enclosing {} (just cosmetics, but hey - 2 chars less typing *g*)
    (or did you use it here as a means to show your intention
     more clearly?)

I know this is mainly a style thing however I've seen many bugs caused by people who leave the scope brakes of the loop.
May 24 2007
parent reply janderson <askme me.com> writes:
Henning Hasemann wrote:
 On Thu, 24 May 2007 02:45:05 -0700
 janderson <askme me.com> wrote:
 
 davidb wrote:
 [snip]
 5) line 62:
    if "for (;;) ... " has only one statement(?), you don't need
    enclosing {} (just cosmetics, but hey - 2 chars less typing *g*)
    (or did you use it here as a means to show your intention
     more clearly?)

I know this is mainly a style thing however I've seen many bugs caused by people who leave the scope brakes of the loop.

Ack, I also have only *very* few cases where I do not put brackets (also because I come from python so if I'm not concentrated I fear it might happen to me to rely on indentation) Henning

I've seen: - People don't search-replace and removing a particular statement (it will then run the second line) - People using them with macros (that haven't been properly scoped) - People adding a statement that is really 2. - People with a load of nested ifs, remove one and then the else statement relates to something else. - Particularly in nested situations, people get the scope confused when writing the code and end up putting a statement in the wrong scope. Its not that common, however these bugs can be a significant time sink when they occur. I think its more time consuming to avoid putting them in. Also, for me as a style thing its less typing to have brackets because they are auto generated as I type. I can then easily expand the statement without having to go back and add {}.
May 24 2007
parent janderson <askme me.com> writes:
janderson wrote:
 Henning Hasemann wrote:
 On Thu, 24 May 2007 02:45:05 -0700
 janderson <askme me.com> wrote:

 davidb wrote:
 [snip]
 5) line 62:
    if "for (;;) ... " has only one statement(?), you don't need
    enclosing {} (just cosmetics, but hey - 2 chars less typing *g*)
    (or did you use it here as a means to show your intention
     more clearly?)

I know this is mainly a style thing however I've seen many bugs caused by people who leave the scope brakes of the loop.

Ack, I also have only *very* few cases where I do not put brackets (also because I come from python so if I'm not concentrated I fear it might happen to me to rely on indentation) Henning

I've seen: - People don't search-replace and removing a particular statement (it will then run the second line) - People using them with macros (that haven't been properly scoped) - People adding a statement that is really 2. - People with a load of nested ifs, remove one and then the else statement relates to something else. - Particularly in nested situations, people get the scope confused when writing the code and end up putting a statement in the wrong scope. Its not that common, however these bugs can be a significant time sink when they occur. I think its more time consuming to avoid putting them in. Also, for me as a style thing its less typing to have brackets because they are auto generated as I type. I can then easily expand the statement without having to go back and add {}.

I should add, that I'm not a style Nazi. I was just trying to demonstrate the other side of the fence on this one. -Joel
May 25 2007
prev sibling parent reply davidb <ta-nospam-zz gmx.at> writes:
Gregor Kopp wrote:
 Considering the Stack class:
 I'm not quite sure about the use of "this.length" in the various
 contexts, could someone please explain it to me?

I used the length of my stack outside other programs. I wanted to know the elements nested inside my stack in other programs. My future plan is to write a small ide for the bf interpreter. So I have to rewrite the whole thing.

I meant this.size of course. Note to self: first read, then post. I mistook this.size for a kind of special (template) class property, where it was just a function without the ()... I don't know if the compiler optimizes it automatically, but if you use e.g. data[this.size - 1] = element; it will call this.size() to determine data.length, whereas data[$-1] = element; would just look it up from the array (no function call overhead). david
May 24 2007
parent Gregor Kopp <gk cutcopy.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

I just worked out a new version attached to this posting.
It contains several improvements, based on your suggestions.

I want to implement 2 features till its ready to use:

1. fileusage instead of parameter (or both, like your version)
2. handling of invalid cell-size like the original bf-interpreter did

I hope you all like this version ;)
May 24 2007
prev sibling next sibling parent janderson <askme me.com> writes:
Gregor Kopp wrote:
 janderson wrote:
 Nice work!

thank you! just for safety: change the part handling the case '[': to: case '[': klammernstack.push(kommandoindex); break; got braindamage yesterday... I tried to compile Gregor Richtards version with dmd 1.014 on windows xp, but it didn't work: D:\>dmd ctbf.d ctbf.d(62): Error: need -Jpath switch to import text file helloworld.bf

From spec http://www.digitalmars.com/d/dcompiler.html " -Jpath where to look for files for ImportExpressions. This switch is required in order to use ImportExpressions. path is a ; separated list of paths. Multiple -J's can be used, and the paths are searched in the same order. " You need to say where the helloworld.bf lives since it writes the brainfucked program at compile time. (ie the outputted binary is the compiled helloworld.bf).
 ctbf.d(62): Error: cannot evaluate ctbf("") at compile time
 ctbf.d(62): Error: argument to mixin must be a string, not (ctbf(""))

Probably related to the first error.
 
 helloworld.bf did exist in the same directory with the following content:
 
 ,[.,]
 

I hope that helped.
May 23 2007
prev sibling parent reply Daniel Cristofani <cristofd hevanet.com> writes:
Don't worry about the line-buffering. That's very common behavior, and shouldn't
break any interesting programs. People will NOT be surprised or disturbed if
,[.,]
reads and outputs one line at a time.
Jun 02 2007
parent Gregor Kopp <gk cutcopy.com> writes:
Daniel Cristofani wrote:
 Don't worry about the line-buffering. That's very common behavior, and
shouldn't
 break any interesting programs. People will NOT be surprised or disturbed if
,[.,]
 reads and outputs one line at a time.

Thats true, for sure. My play instinct is forcing me to do it so, that it works at least on my own system.
Jun 11 2007
prev sibling next sibling parent Gregor Kopp <gregor.kopp chello.at> writes:
Hi davidb, thank you for your improvements, and hitting me to the ',' issue ;)

 So, what about a kind of "official" RFC - please comment my code
 so I can improve my style? (just put "RFC ..." in the topic)

Okay.
 This way, you could not only learn through your own code
 being commented upon, but also through watching other people's
 style & improvements!

That was my intention for posting it here ;)
 That said, I'll make a first try  Gregor Kopp's code:
 1) You'd definitely want a default case in your switch statement
     which btw. fits nicely with "other characters (which are ignored)"
     (http://en.wikipedia.org/wiki/Brainfuck)
     (currently it exits with an "Error: Switch Default ..."
      if it encounters any other symbol than the ones checked for)

Your right, I started this small program to learn about the d, so I've learned several things, but as I see, not enough ;)
 2) Just personal preference, but I'd try not to put too much
     functionality in main(), makes code more clear and above all:
     easier reusable
     (okay, its a bf interpreter, no big reuse here ;-).

Normally I split up my code more modular, but here, its only about 100 loc.
 3) []-handling: not quite the specs implemented, but nicely done with
     a stack :-)

I just wanted to demonstrate the stack, I know it could also be done with pointers and other technics.
 4) line 61:
     I don't quite see why you use char[] initialized with 1 for cells,
     but that's probably just me.

Here i have to think about it again how to improve this.
 5) line 62:
     if "for (;;) ... " has only one statement(?), you don't need
     enclosing {} (just cosmetics, but hey - 2 chars less typing *g*)
     (or did you use it here as a means to show your intention
      more clearly?)

Normally I do it like you described it. I also put private, public and so on in front of every type and variable, just to say: I mean it that way. I'm curious.
 6) descriptive names in addition to clear indentation
     => very easily readable code, nice!

I want to be capable reading my code years after. My Ruby programs are looking also that way and are "written", not obfuscated. My intetion behind is also, that others can read my code without hurting there eyes.
 Considering the Stack class:
 I'm not quite sure about the use of "this.length" in the various
 contexts, could someone please explain it to me?

I used the length of my stack outside other programs. I wanted to know the elements nested inside my stack in other programs. My future plan is to write a small ide for the bf interpreter. So I have to rewrite the whole thing.
 and attached, also a little bf interpreter

Thank you for that, I will study it.
May 23 2007
prev sibling parent Henning Hasemann <hhasemann web.de> writes:
On Thu, 24 May 2007 02:45:05 -0700
janderson <askme me.com> wrote:

 davidb wrote:
 [snip]
 5) line 62:
    if "for (;;) ... " has only one statement(?), you don't need
    enclosing {} (just cosmetics, but hey - 2 chars less typing *g*)
    (or did you use it here as a means to show your intention
     more clearly?)

I know this is mainly a style thing however I've seen many bugs caused by people who leave the scope brakes of the loop.

Ack, I also have only *very* few cases where I do not put brackets (also because I come from python so if I'm not concentrated I fear it might happen to me to rely on indentation) Henning -- GPG Public Key: http://keyserver.veridis.com:11371/search?q=0x41911851 Fingerprint: 344F 4072 F038 BB9E B35D E6AB DDD6 D36D 4191 1851
May 24 2007