loiol-practice 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/ruby/practice.rb +7 -0
- data/lib/ruby/practice/brainfuck.rb +15 -0
- data/lib/ruby/practice/implementation/interpreter.rb +130 -0
- data/lib/ruby/practice/version.rb +6 -0
- metadata +90 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 01f46e5cbce39ef6097dff5c1c1717f0bea03b20
|
|
4
|
+
data.tar.gz: 1dd1aea379c9cf7b574729f3d75163a4852f4ee3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: dfae7be278d115a826a64c76b4ef007c600246b7c7439c9ebea9993e13c22e532e3d0f21890654a1a0b9e7a3fc20b12f157278112110112bfa7424d6db65509d
|
|
7
|
+
data.tar.gz: 92e2be9dcc132fa044a38e755952df79bddf59cb06a78cee8b8bf58472443a9f92c4b489ce7508491f5111d6e0c5c66282abc3e2bf89dfa242e4480168c38aae
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# The practice module.
|
|
2
|
+
module Practice
|
|
3
|
+
# The brainfuck class.
|
|
4
|
+
class Brainfuck
|
|
5
|
+
# Initialize.
|
|
6
|
+
def initialize(source)
|
|
7
|
+
@interpreter = Implementation::Interpreter.new(source)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# To evaluate the source code.
|
|
11
|
+
def evaluate(context)
|
|
12
|
+
@interpreter.evaluate(context)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# The Practice module
|
|
2
|
+
module Practice
|
|
3
|
+
# The Implementation module
|
|
4
|
+
module Implementation
|
|
5
|
+
# Brainfuck interpreter written in Ruby.
|
|
6
|
+
class Interpreter
|
|
7
|
+
# The Brainfuck command.
|
|
8
|
+
Command = Struct.new(:symbol)
|
|
9
|
+
|
|
10
|
+
# Increment the data pointer (to point to the next cell to the right).
|
|
11
|
+
@lshift = Command.new('<')
|
|
12
|
+
def @lshift.process(cxt, _)
|
|
13
|
+
cxt.cursor -= 1
|
|
14
|
+
raise ArgumentError.new('Subscript out of range') if cxt.cursor < 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Decrement the data pointer (to point to the next cell to the left).
|
|
18
|
+
@rshift = Command.new('>')
|
|
19
|
+
def @rshift.process(cxt, _)
|
|
20
|
+
cxt.cursor += 1
|
|
21
|
+
cxt.memory << 0 if cxt.cursor == cxt.memory.length
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Increment (increase by one) the byte at the data pointer.
|
|
25
|
+
@plus = Command.new('+')
|
|
26
|
+
def @plus.process(cxt, _)
|
|
27
|
+
value = cxt.memory[cxt.cursor] + 1
|
|
28
|
+
cxt.memory[cxt.cursor] = value > 255 ? 0 : value
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Decrement (decrease by one) the byte at the data pointer.
|
|
32
|
+
@minus = Command.new('-')
|
|
33
|
+
def @minus.process(cxt, _)
|
|
34
|
+
value = cxt.memory[cxt.cursor] - 1
|
|
35
|
+
cxt.memory[cxt.cursor] = value < 0 ? 255 : value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Output the byte at the data pointer.
|
|
39
|
+
@dot = Command.new('.')
|
|
40
|
+
def @dot.process(cxt, _)
|
|
41
|
+
value = cxt.memory[cxt.cursor]
|
|
42
|
+
cxt.output(value.chr)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Accept one byte of input,
|
|
46
|
+
# storing its value in the byte at the data pointer.
|
|
47
|
+
@comma = Command.new(',')
|
|
48
|
+
def @comma.process(cxt, _)
|
|
49
|
+
value = cxt.input
|
|
50
|
+
cxt.memory[cxt.cursor] = value.ord
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# If the byte at the data pointer is zero,
|
|
54
|
+
# then instead of moving the instruction pointer
|
|
55
|
+
# forward to the next command,
|
|
56
|
+
# jump it forward to the command after the matching ] command.
|
|
57
|
+
@lbracket = Command.new('[')
|
|
58
|
+
def @lbracket.process(cxt, bracemap)
|
|
59
|
+
cxt.counter = bracemap[cxt.counter] if cxt.memory[cxt.cursor] == 0
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# If the byte at the data pointer is nonzero,
|
|
63
|
+
# then instead of moving the instruction pointer
|
|
64
|
+
# forward to the next command,
|
|
65
|
+
# jump it back to the command after the matching [ command.
|
|
66
|
+
@rbracket = Command.new(']')
|
|
67
|
+
def @rbracket.process(cxt, bracemap)
|
|
68
|
+
cxt.counter = bracemap[cxt.counter] if cxt.memory[cxt.cursor] != 0
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
@symbols = %i(
|
|
72
|
+
lshift rshift plus minus dot comma lbracket rbracket
|
|
73
|
+
).reduce({}) do |symbols, name|
|
|
74
|
+
command = instance_variable_get("@#{name}")
|
|
75
|
+
symbols[command.symbol] = command
|
|
76
|
+
symbols
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Initialize.
|
|
80
|
+
def initialize(source)
|
|
81
|
+
syms = Interpreter.symbols
|
|
82
|
+
tokens = source.each_char.map { |c| c }.select { |c| syms.include?(c) }
|
|
83
|
+
@commands = tokens.map { |c| Interpreter.command(c) }
|
|
84
|
+
@bracemap = parse(@commands)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# To evaluate the source code.
|
|
88
|
+
def evaluate(cxt)
|
|
89
|
+
while cxt.counter < @commands.length
|
|
90
|
+
command = @commands[cxt.counter]
|
|
91
|
+
command.process(cxt, @bracemap)
|
|
92
|
+
cxt.counter += 1
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
# Parse to brainfuck code.
|
|
99
|
+
def parse(commands)
|
|
100
|
+
bracestack, bracemap = [], {}
|
|
101
|
+
commands.each_with_index do |command, index|
|
|
102
|
+
if command.symbol == '['
|
|
103
|
+
bracestack << index
|
|
104
|
+
elsif command.symbol == ']'
|
|
105
|
+
message = "syntax error, unexpected ']'"
|
|
106
|
+
raise ArgumentError.new message if bracestack.empty?
|
|
107
|
+
bracepos = bracestack.pop
|
|
108
|
+
bracemap[bracepos] = index
|
|
109
|
+
bracemap[index] = bracepos
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
message = "syntax error, unexpected '['"
|
|
114
|
+
raise ArgumentError.new message unless bracestack.empty?
|
|
115
|
+
bracemap
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class << self
|
|
119
|
+
# Get brainfuck symbols
|
|
120
|
+
def symbols
|
|
121
|
+
@symbols.keys
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def command(c)
|
|
125
|
+
@symbols[c]
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: loiol-practice
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- loiol
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-08-27 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.11'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.11'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.0'
|
|
55
|
+
description: Brainfuck interpreter writen in Ruby
|
|
56
|
+
email:
|
|
57
|
+
- develop.loiol@gmail.com
|
|
58
|
+
executables: []
|
|
59
|
+
extensions: []
|
|
60
|
+
extra_rdoc_files: []
|
|
61
|
+
files:
|
|
62
|
+
- lib/ruby/practice.rb
|
|
63
|
+
- lib/ruby/practice/brainfuck.rb
|
|
64
|
+
- lib/ruby/practice/implementation/interpreter.rb
|
|
65
|
+
- lib/ruby/practice/version.rb
|
|
66
|
+
homepage: https://github.com/loiol/practice
|
|
67
|
+
licenses:
|
|
68
|
+
- MIT
|
|
69
|
+
metadata: {}
|
|
70
|
+
post_install_message:
|
|
71
|
+
rdoc_options: []
|
|
72
|
+
require_paths:
|
|
73
|
+
- lib/ruby
|
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: 2.0.0
|
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '0'
|
|
84
|
+
requirements: []
|
|
85
|
+
rubyforge_project:
|
|
86
|
+
rubygems_version: 2.5.1
|
|
87
|
+
signing_key:
|
|
88
|
+
specification_version: 4
|
|
89
|
+
summary: Brainfuck interpreter writen in Ruby
|
|
90
|
+
test_files: []
|