Kaguya
Kaguya is an implementation of Brainf**k by Ruby.
This implementation consits of following elements,
- Tiny parser
- Tiny compiler
- Tiny virtual stack machine
Installation
$ gem install kaguya
Usage
$ kaguya helloworld.bf
An option --debug
helps you to see AST and instruction sequence.
$ kaguya --debug helloworld.bf
Technical components
Parser
https://github.com/mozamimy/kaguya/blob/master/lib/kaguya/parser.rb
The parser parses a BF script one charactor at a time. Errors can be raised by the parser if the script contains invalid corresponding of [
and ]
or invalid charactors.
Only the root node and while
nodes have children.
Virtual machine
https://github.com/mozamimy/kaguya/blob/master/lib/kaguya/vm.rb
Kaguya VM has a two stacks (left_stack, right_stack) and has following 9 instructions,
forward
: Forward stack, if right_stack is empty then push 0 to left_stack else move top of right_stack to left_stack.backward
: Backward stack, top data of left_stack is poped and pushed to right_stack.increment
: Increment top of left_stack.decrement
: Decrement top of left_stack.output
: Output top of left_stack to standard I/O.input
: Input a value from standard I/O and push it to left_stack.branch_ifzero N
: Jump to an instruction atPC - N
if top of left_stack is 0.branch_unlesszero N
: Jump to an instruction atPC - N
unless top of left_stack is 0.leave
: Exit
Compiler
https://github.com/mozamimy/kaguya/blob/master/lib/kaguya/compiler.rb
Kaguya compiler compiles an AST generated by the parser to an instruction sequence for Kaguya VM.
Example
[20:17:51]mozamimy@queen:kaguya (master) (-'x'-).oO(
> cat example/useless.bf
>>+[<>[+-]]
[20:17:53]mozamimy@queen:kaguya (master) (-'x'-).oO(
> be exe/kaguya --debug example/useless.bf
=== AST ===
#<Kaguya::AST::Node:0x007fd755a3f8c0
@children=
[#<Kaguya::AST::Node:0x007fd755a3f780
@children=[],
@parent=#<Kaguya::AST::Node:0x007fd755a3f8c0 ...>,
@type=:forward>,
#<Kaguya::AST::Node:0x007fd755a3f500
@children=[],
@parent=#<Kaguya::AST::Node:0x007fd755a3f8c0 ...>,
@type=:forward>,
#<Kaguya::AST::Node:0x007fd755a3f230
@children=[],
@parent=#<Kaguya::AST::Node:0x007fd755a3f8c0 ...>,
@type=:increment>,
#<Kaguya::AST::Node:0x007fd755a3f028
@children=
[#<Kaguya::AST::Node:0x007fd755a3edd0
@children=[],
@parent=#<Kaguya::AST::Node:0x007fd755a3f028 ...>,
@type=:backward>,
#<Kaguya::AST::Node:0x007fd755a3e7e0
@children=[],
@parent=#<Kaguya::AST::Node:0x007fd755a3f028 ...>,
@type=:forward>,
#<Kaguya::AST::Node:0x007fd755a3e5b0
@children=
[#<Kaguya::AST::Node:0x007fd755a3e3f8
@children=[],
@parent=#<Kaguya::AST::Node:0x007fd755a3e5b0 ...>,
@type=:increment>,
#<Kaguya::AST::Node:0x007fd755a3e1f0
@children=[],
@parent=#<Kaguya::AST::Node:0x007fd755a3e5b0 ...>,
@type=:decrement>],
@parent=#<Kaguya::AST::Node:0x007fd755a3f028 ...>,
@type=:while>],
@parent=#<Kaguya::AST::Node:0x007fd755a3f8c0 ...>,
@type=:while>],
@parent=nil,
@type=:root>
=== ISEQ ===
[[:forward, nil],
[:forward, nil],
[:increment, nil],
[:branch_ifzero, 8],
[:backward, nil],
[:forward, nil],
[:branch_ifzero, 4],
[:increment, nil],
[:decrement, nil],
[:branch_unlesszero, -2],
[:branch_unlesszero, -6],
[:leave, nil]]
=== RUN ===
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/mozamimy/kaguya.
License
The gem is available as open source under the terms of the MIT License.