esolang 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/esolang.rb +65 -0
- data/lib/interpreters/base_interpreter.rb +108 -0
- data/lib/interpreters/boolfuck_interpreter.rb +73 -0
- data/lib/interpreters/brainfuck_interpreter.rb +81 -0
- data/lib/interpreters/ook_interpreter.rb +70 -0
- data/lib/interpreters/paintfuck_interpreter.rb +102 -0
- data/lib/interpreters/smallfuck_interpreter.rb +57 -0
- data/lib/refinements/refinements.rb +58 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 48161d9cd63a90d101a9f5936464c053d2295b9ef7b500c95ad3cb2ff3049dc7
|
4
|
+
data.tar.gz: 4c570f8ff4b1de1c7c115572e1d3ab06a8d84015936a82ecfdcd98396b7fea24
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8777ec08eac7ae40588d31fb178b9ebee874f12fd9847eba36c52132312e9c96db43113e970fa0632be4c70bac9569b0d4bd6c5d96cd33093f1a5b3812e21bf9
|
7
|
+
data.tar.gz: e9033263c0ea899c52be1a33c968c2b3ca667bf3f6a35b14f70a6cb7e457b7a0e95e018b6cda2beed83b198f743adf735bde5bd0cb6742d367d2adbf10eead89
|
data/lib/esolang.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../lib/interpreters/boolfuck_interpreter.rb'
|
4
|
+
require_relative '../lib/interpreters/smallfuck_interpreter.rb'
|
5
|
+
require_relative '../lib/interpreters/paintfuck_interpreter.rb'
|
6
|
+
require_relative '../lib/interpreters/brainfuck_interpreter.rb'
|
7
|
+
require_relative '../lib/interpreters/ook_interpreter.rb'
|
8
|
+
|
9
|
+
require_relative '../lib/refinements/refinements.rb'
|
10
|
+
|
11
|
+
# The Esolang module provides methods to interpret esoteric programming languages.
|
12
|
+
#
|
13
|
+
# To use it you need to:
|
14
|
+
#
|
15
|
+
# ```ruby
|
16
|
+
# using Esolang::Refinements
|
17
|
+
# ```
|
18
|
+
module Esolang
|
19
|
+
# Interprets Boolfuck code.
|
20
|
+
#
|
21
|
+
# @param code [String] The Boolfuck code to interpret.
|
22
|
+
# @param input [String] The input for the Boolfuck program (optional).
|
23
|
+
# @return [String] The result of the Boolfuck interpretation.
|
24
|
+
def self.boolfuck(code, input = '')
|
25
|
+
Interpreters::Boolfuck.new(code, input).run
|
26
|
+
end
|
27
|
+
|
28
|
+
# Interprets Smallfuck code.
|
29
|
+
#
|
30
|
+
# @param code [String] The Smallfuck code to interpret.
|
31
|
+
# @param tape [String] The initial tape state for the Smallfuck program.
|
32
|
+
# @return [String] The result of the Smallfuck interpretation.
|
33
|
+
def self.smallfuck(code, tape)
|
34
|
+
Interpreters::Smallfuck.new(code, tape).run
|
35
|
+
end
|
36
|
+
|
37
|
+
# Interprets Paintfuck code.
|
38
|
+
#
|
39
|
+
# @param code [String] The Paintfuck code to interpret.
|
40
|
+
# @param iterations [Integer] The number of iterations for the Paintfuck program.
|
41
|
+
# @param width [Integer] The width of the Paintfuck canvas.
|
42
|
+
# @param height [Integer] The height of the Paintfuck canvas.
|
43
|
+
# @return [String] The result of the Paintfuck interpretation.
|
44
|
+
def self.paintfuck(code, iterations, width, height)
|
45
|
+
Interpreters::Paintfuck.new(code, iterations, width, height).run
|
46
|
+
end
|
47
|
+
|
48
|
+
# Interprets Brainfuck code.
|
49
|
+
#
|
50
|
+
# @param code [String] The Brainfuck code to interpret.
|
51
|
+
# @param input [String] The input for the Brainfuck program (optional).
|
52
|
+
# @return [String] The result of the Brainfuck interpretation.
|
53
|
+
def self.brainfuck(code, input = '')
|
54
|
+
Interpreters::Brainfuck.new(code, input).run
|
55
|
+
end
|
56
|
+
|
57
|
+
# Interprets Ook! code.
|
58
|
+
#
|
59
|
+
# @param code [String] The Ook! code to interpret.
|
60
|
+
# @param input [String] The input for the Ook! program (optional).
|
61
|
+
# @return [String] The result of the Ook! interpretation.
|
62
|
+
def self.ook(code, input = '')
|
63
|
+
Interpreters::Ook.new(code, input).run
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esolang
|
4
|
+
module Interpreters
|
5
|
+
# The BaseInterpreter class provides a common interface and basic functionality for
|
6
|
+
# interpreting esoteric programming languages.
|
7
|
+
class BaseInterpreter
|
8
|
+
# Initializes a new instance of the BaseInterpreter class.
|
9
|
+
#
|
10
|
+
# @param code [String] The code to interpret.
|
11
|
+
def initialize(code)
|
12
|
+
@code = code.chars
|
13
|
+
@code_pointer = 0
|
14
|
+
@loop_map = create_loop_map
|
15
|
+
@tape_pointer = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
# Executes the interpretation of the code. Subclasses must implement this method.
|
19
|
+
#
|
20
|
+
# @abstract Subclasses must implement the run method.
|
21
|
+
# @raise [NotImplementedError] Raised if the method is not implemented by subclasses.
|
22
|
+
def run
|
23
|
+
raise NotImplementedError, 'Subclasses must implement the run method'
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Moves the tape pointer to the right.
|
29
|
+
def move_right
|
30
|
+
@tape_pointer += 1
|
31
|
+
end
|
32
|
+
|
33
|
+
# Moves the tape pointer to the left.
|
34
|
+
def move_left
|
35
|
+
@tape_pointer -= 1
|
36
|
+
end
|
37
|
+
|
38
|
+
# Reads input and writes it to the tape.
|
39
|
+
def input_to_tape
|
40
|
+
@input.empty? ? current_bit(0) : current_bit(@input.shift)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Reads the tape and appends the current bit to the output array.
|
44
|
+
def tape_to_output_array
|
45
|
+
@output << current_bit
|
46
|
+
end
|
47
|
+
|
48
|
+
# Creates a map of loop indices for efficient loop navigation.
|
49
|
+
def create_loop_map
|
50
|
+
map = {}
|
51
|
+
stack = []
|
52
|
+
|
53
|
+
@code.each_with_index do |command, index|
|
54
|
+
case command
|
55
|
+
when '[' then stack << index
|
56
|
+
when ']'
|
57
|
+
if stack.empty?
|
58
|
+
raise StandardError, "Invalid code: No matching '[' for ']' at index #{index}"
|
59
|
+
else
|
60
|
+
map[stack.pop] = index
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
raise StandardError, "Invalid code: No matching ']' for '[' at index #{stack.last}" unless stack.empty?
|
66
|
+
|
67
|
+
map
|
68
|
+
end
|
69
|
+
|
70
|
+
# Jumps to the matching ']' if the current bit is zero.
|
71
|
+
def loop_begin
|
72
|
+
return unless current_bit.zero?
|
73
|
+
|
74
|
+
@code_pointer = @loop_map[@code_pointer]
|
75
|
+
end
|
76
|
+
|
77
|
+
# Jumps back to the matching '[' if the current bit is non-zero.
|
78
|
+
def loop_end
|
79
|
+
return if current_bit.zero?
|
80
|
+
|
81
|
+
@code_pointer = @loop_map.key(@code_pointer)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Flips the current bit.
|
85
|
+
def flip
|
86
|
+
current_bit(current_bit ^ 1)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Retrieves the value of the current bit. Subclasses must implement this method.
|
90
|
+
#
|
91
|
+
# @abstract Subclasses must implement the current_bit method.
|
92
|
+
# @raise [NotImplementedError] Raised if the method is not implemented by subclasses.
|
93
|
+
def current_bit
|
94
|
+
raise NotImplementedError, 'Subclasses must implement the current_bit method'
|
95
|
+
end
|
96
|
+
|
97
|
+
# Checks if the interpreter is still running (code execution is not completed).
|
98
|
+
def running?
|
99
|
+
@code_pointer < @code.length
|
100
|
+
end
|
101
|
+
|
102
|
+
# Retrieves the current command in the code.
|
103
|
+
def command
|
104
|
+
@code[@code_pointer]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_interpreter'
|
4
|
+
|
5
|
+
module Esolang
|
6
|
+
module Interpreters
|
7
|
+
# The Boolfuck class represents an interpreter for the Boolfuck esoteric programming language.
|
8
|
+
class Boolfuck < BaseInterpreter
|
9
|
+
# Initializes a new instance of the Boolfuck interpreter.
|
10
|
+
#
|
11
|
+
# @param code [String] The Boolfuck code to interpret.
|
12
|
+
# @param input [String] The input for the Boolfuck program (optional).
|
13
|
+
def initialize(code, input = '')
|
14
|
+
super(code.gsub(/[^,\.;<>\+\[\]]/, ''))
|
15
|
+
@input = chars_to_bits(input)
|
16
|
+
@output = []
|
17
|
+
@tape = Hash.new(0)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Executes the interpretation of the Boolfuck code.
|
21
|
+
#
|
22
|
+
# @return [String] The result of the Boolfuck interpretation.
|
23
|
+
def run
|
24
|
+
while running? do
|
25
|
+
case command
|
26
|
+
when ',' then input_to_tape
|
27
|
+
when ';' then tape_to_output_array
|
28
|
+
when '>' then move_right
|
29
|
+
when '<' then move_left
|
30
|
+
when '+' then flip
|
31
|
+
when '[' then loop_begin
|
32
|
+
when ']' then loop_end
|
33
|
+
end
|
34
|
+
|
35
|
+
@code_pointer += 1
|
36
|
+
end
|
37
|
+
|
38
|
+
translate_output_bits_to_chars
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Converts characters to bits (0 or 1).
|
44
|
+
#
|
45
|
+
# @param chars [String] The characters to convert.
|
46
|
+
# @return [Array<Integer>] The array of bits.
|
47
|
+
def chars_to_bits(chars)
|
48
|
+
chars.chars.map { |char| [char.ord].pack("C*").unpack("b*")[0] }.join.chars.map(&:to_i)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Retrieves or updates the value of the current bit on the tape.
|
52
|
+
#
|
53
|
+
# @param new_value [Integer] The new value for the current bit (optional).
|
54
|
+
# @return [Integer] The value of the current bit.
|
55
|
+
def current_bit(new_value = nil)
|
56
|
+
@tape[@tape_pointer] = new_value unless new_value.nil?
|
57
|
+
|
58
|
+
@tape[@tape_pointer]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Translates the bits in the output array to characters.
|
62
|
+
#
|
63
|
+
# @return [String] The translated characters.
|
64
|
+
def translate_output_bits_to_chars
|
65
|
+
zeros_count_to_fill = (@output.length % 8).zero? ? 0 : 8 - (@output.length % 8)
|
66
|
+
|
67
|
+
@output.fill(0, @output.length, zeros_count_to_fill).each_slice(8).map do |byte|
|
68
|
+
byte.join.reverse.to_i(2).chr
|
69
|
+
end.join
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_interpreter'
|
4
|
+
|
5
|
+
module Esolang
|
6
|
+
module Interpreters
|
7
|
+
# The Brainfuck class represents an interpreter for the Brainfuck esoteric programming language.
|
8
|
+
class Brainfuck < BaseInterpreter
|
9
|
+
# Initializes a new instance of the Brainfuck interpreter.
|
10
|
+
#
|
11
|
+
# @param code [String] The Brainfuck code to interpret.
|
12
|
+
# @param input [String] The input for the Brainfuck program (optional).
|
13
|
+
def initialize(code, input = '')
|
14
|
+
# Added ? to valid chars for compatibility with Ook! But don't parse ? in Brainfuck
|
15
|
+
super(code.gsub(/[^\?,\.<>\+-\[\]]/, ''))
|
16
|
+
@input = chars_to_bytes(input)
|
17
|
+
@output = []
|
18
|
+
@tape = Hash.new(0)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Executes the interpretation of the Brainfuck code.
|
22
|
+
#
|
23
|
+
# @return [String] The result of the Brainfuck interpretation.
|
24
|
+
def run
|
25
|
+
while running? do
|
26
|
+
case command
|
27
|
+
when ',' then input_to_tape
|
28
|
+
when '.' then tape_to_output_array
|
29
|
+
when '>' then move_right
|
30
|
+
when '<' then move_left
|
31
|
+
when '+' then increment
|
32
|
+
when '-' then decrement
|
33
|
+
when '[' then loop_begin
|
34
|
+
when ']' then loop_end
|
35
|
+
end
|
36
|
+
|
37
|
+
@code_pointer += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
translate_output_bytes_to_chars
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Increments the value of the current bit on the tape.
|
46
|
+
def increment
|
47
|
+
current_bit((current_bit + 1) % 256)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Decrements the value of the current bit on the tape.
|
51
|
+
def decrement
|
52
|
+
current_bit((current_bit - 1) % 256)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Converts characters to byte values.
|
56
|
+
#
|
57
|
+
# @param chars [String] The characters to convert.
|
58
|
+
# @return [Array<Integer>] The array of byte values.
|
59
|
+
def chars_to_bytes(chars)
|
60
|
+
chars.chars.map { |char| char.ord }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Retrieves or updates the value of the current bit on the tape.
|
64
|
+
#
|
65
|
+
# @param new_value [Integer] The new value for the current bit (optional).
|
66
|
+
# @return [Integer] The value of the current bit.
|
67
|
+
def current_bit(new_value = nil)
|
68
|
+
@tape[@tape_pointer] = new_value unless new_value.nil?
|
69
|
+
|
70
|
+
@tape[@tape_pointer]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Translates the byte values in the output array to characters.
|
74
|
+
#
|
75
|
+
# @return [String] The translated characters.
|
76
|
+
def translate_output_bytes_to_chars
|
77
|
+
@output.map { |char| char.chr }.join
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'brainfuck_interpreter'
|
4
|
+
|
5
|
+
module Esolang
|
6
|
+
module Interpreters
|
7
|
+
# The Ook class represents an interpreter for the Ook! esoteric programming language,
|
8
|
+
# which is translated to Brainfuck for execution.
|
9
|
+
class Ook < Brainfuck
|
10
|
+
# Initializes a new instance of the Ook interpreter.
|
11
|
+
#
|
12
|
+
# @param code [String] The Ook code to interpret.
|
13
|
+
# @param input [String] The input for the Ook program (optional).
|
14
|
+
def initialize(code, input = '')
|
15
|
+
super(translate_to_brainfuck(code), input)
|
16
|
+
@input = input
|
17
|
+
end
|
18
|
+
|
19
|
+
# Executes the interpretation of the Ook code.
|
20
|
+
#
|
21
|
+
# @return [String] The result of the Ook interpretation.
|
22
|
+
def run
|
23
|
+
while running? do
|
24
|
+
case command
|
25
|
+
when ',' then input_to_tape
|
26
|
+
when '.' then tape_to_output_array
|
27
|
+
when '>' then move_right
|
28
|
+
when '<' then move_left
|
29
|
+
when '+' then increment
|
30
|
+
when '-' then decrement
|
31
|
+
when '[' then loop_begin
|
32
|
+
when ']' then loop_end
|
33
|
+
when '?' then banana
|
34
|
+
end
|
35
|
+
|
36
|
+
@code_pointer += 1
|
37
|
+
end
|
38
|
+
|
39
|
+
translate_output_bytes_to_chars
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Translates Ook! code to Brainfuck code.
|
45
|
+
#
|
46
|
+
# @param code [String] The Ook code to translate.
|
47
|
+
# @return [String] The translated Brainfuck code.
|
48
|
+
def translate_to_brainfuck(code)
|
49
|
+
code.gsub(/[^\.\!\?]/, '').chars.each_slice(2).map do |command|
|
50
|
+
case command.join
|
51
|
+
when ".?" then ">"
|
52
|
+
when "?." then "<"
|
53
|
+
when ".." then "+"
|
54
|
+
when "!!" then "-"
|
55
|
+
when "!." then "."
|
56
|
+
when ".!" then ","
|
57
|
+
when "!?" then "["
|
58
|
+
when "?!" then "]"
|
59
|
+
when "??" then "?"
|
60
|
+
end
|
61
|
+
end.join
|
62
|
+
end
|
63
|
+
|
64
|
+
# Prints a message indicating that the memory pointer got a banana.
|
65
|
+
def banana
|
66
|
+
puts "The memory pointer got a banana"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_interpreter'
|
4
|
+
|
5
|
+
module Esolang
|
6
|
+
module Interpreters
|
7
|
+
# The Paintfuck class represents an interpreter for the Paintfuck esoteric programming language.
|
8
|
+
class Paintfuck < BaseInterpreter
|
9
|
+
# Initializes a new instance of the Paintfuck interpreter.
|
10
|
+
#
|
11
|
+
# @param code [String] The Paintfuck code to interpret.
|
12
|
+
# @param iterations [Integer] The number of iterations for the Paintfuck program.
|
13
|
+
# @param width [Integer] The width of the Paintfuck canvas.
|
14
|
+
# @param height [Integer] The height of the Paintfuck canvas.
|
15
|
+
def initialize(code, iterations, width, height)
|
16
|
+
super(code.gsub(/[^nesw\*\[\]]/, ''))
|
17
|
+
@iterations = iterations
|
18
|
+
@width = width
|
19
|
+
@height = height
|
20
|
+
@data_grid = generate_zero_grid
|
21
|
+
@grid_pointer = [0, 0]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Executes the interpretation of the Paintfuck code.
|
25
|
+
#
|
26
|
+
# @return [String] The result of the Paintfuck interpretation.
|
27
|
+
def run
|
28
|
+
while running? do
|
29
|
+
case command
|
30
|
+
when 'n' then move_up
|
31
|
+
when 'e' then move_right
|
32
|
+
when 's' then move_down
|
33
|
+
when 'w' then move_left
|
34
|
+
when '*' then flip
|
35
|
+
when '[' then loop_begin
|
36
|
+
when ']' then loop_end
|
37
|
+
end
|
38
|
+
|
39
|
+
@code_pointer += 1
|
40
|
+
@iterations -= 1
|
41
|
+
end
|
42
|
+
|
43
|
+
output
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Moves the grid pointer up.
|
49
|
+
def move_up
|
50
|
+
@grid_pointer[0] = (@grid_pointer.first - 1 + @height) % @height
|
51
|
+
end
|
52
|
+
|
53
|
+
# Moves the grid pointer down.
|
54
|
+
def move_down
|
55
|
+
@grid_pointer[0] = (@grid_pointer.first + 1 + @height) % @height
|
56
|
+
end
|
57
|
+
|
58
|
+
# Moves the grid pointer right.
|
59
|
+
def move_right
|
60
|
+
@grid_pointer[1] = (@grid_pointer.last + 1 + @width) % @width
|
61
|
+
end
|
62
|
+
|
63
|
+
# Moves the grid pointer left.
|
64
|
+
def move_left
|
65
|
+
@grid_pointer[1] = (@grid_pointer.last - 1 + @width) % @width
|
66
|
+
end
|
67
|
+
|
68
|
+
# Retrieves or updates the value of the current bit on the Paintfuck canvas.
|
69
|
+
#
|
70
|
+
# @param new_value [Integer] The new value for the current bit (optional).
|
71
|
+
# @return [Integer] The value of the current bit.
|
72
|
+
def current_bit(new_value = nil)
|
73
|
+
@data_grid[@grid_pointer.first][@grid_pointer.last] = new_value unless new_value.nil?
|
74
|
+
|
75
|
+
@data_grid[@grid_pointer.first][@grid_pointer.last]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Retrieves the output of the Paintfuck program.
|
79
|
+
#
|
80
|
+
# @return [String] The Paintfuck canvas as a string.
|
81
|
+
def output
|
82
|
+
@data_grid
|
83
|
+
.map { |row| row.join }
|
84
|
+
.join("\r\n")
|
85
|
+
end
|
86
|
+
|
87
|
+
# Generates a canvas grid filled with zeros.
|
88
|
+
#
|
89
|
+
# @return [Array<Array<Integer>>] The zero-filled grid.
|
90
|
+
def generate_zero_grid
|
91
|
+
(1..@height).map { [0] * @width }
|
92
|
+
end
|
93
|
+
|
94
|
+
# Checks if the interpreter is still running (code execution is not completed).
|
95
|
+
#
|
96
|
+
# @return [Boolean] Returns true if the interpreter is still running, otherwise false.
|
97
|
+
def running?
|
98
|
+
@iterations.positive? && super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_interpreter'
|
4
|
+
|
5
|
+
module Esolang
|
6
|
+
module Interpreters
|
7
|
+
# The Smallfuck class represents an interpreter for the Smallfuck esoteric programming language.
|
8
|
+
class Smallfuck < BaseInterpreter
|
9
|
+
# Initializes a new instance of the Smallfuck interpreter.
|
10
|
+
#
|
11
|
+
# @param code [String] The Smallfuck code to interpret.
|
12
|
+
# @param tape [String] The initial tape state for the Smallfuck program.
|
13
|
+
def initialize(code, tape)
|
14
|
+
super(code.gsub(/[^<>\*\[\]]/, ''))
|
15
|
+
@tape = tape.chars.map(&:to_i)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Executes the interpretation of the Smallfuck code.
|
19
|
+
#
|
20
|
+
# @return [String] The result of the Smallfuck interpretation.
|
21
|
+
def run
|
22
|
+
while running? do
|
23
|
+
case command
|
24
|
+
when '>' then move_right
|
25
|
+
when '<' then move_left
|
26
|
+
when '*' then flip
|
27
|
+
when '[' then loop_begin
|
28
|
+
when ']' then loop_end
|
29
|
+
end
|
30
|
+
@code_pointer += 1
|
31
|
+
end
|
32
|
+
@tape.join
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Checks if the interpreter is still running (code execution is not completed).
|
38
|
+
#
|
39
|
+
# @return [Boolean] Returns true if the interpreter is still running, otherwise false.
|
40
|
+
def running?
|
41
|
+
@tape_pointer < @tape.length &&
|
42
|
+
@tape_pointer >= 0 &&
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
# Retrieves or updates the value of the current bit on the tape.
|
47
|
+
#
|
48
|
+
# @param new_value [Integer] The new value for the current bit (optional).
|
49
|
+
# @return [Integer] The value of the current bit.
|
50
|
+
def current_bit(new_value = nil)
|
51
|
+
@tape[@tape_pointer] = new_value unless new_value.nil?
|
52
|
+
|
53
|
+
@tape[@tape_pointer]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esolang
|
4
|
+
# The Refinements module provides refinements for String class to enable
|
5
|
+
# direct interpretation of esoteric programming languages.
|
6
|
+
#
|
7
|
+
# To use these refinements, you need to include them using the `using` keyword:
|
8
|
+
#
|
9
|
+
# ```ruby
|
10
|
+
# require 'esolang'
|
11
|
+
# ```
|
12
|
+
module Refinements
|
13
|
+
# Refines the String class to provide a convenient method for interpreting Boolfuck code.
|
14
|
+
refine String do
|
15
|
+
# Interprets Boolfuck code directly on a String.
|
16
|
+
#
|
17
|
+
# @param input [String] The input for the Boolfuck program (optional).
|
18
|
+
# @return [String] The result of the Boolfuck interpretation.
|
19
|
+
def boolfuck(input = '')
|
20
|
+
Esolang::Interpreters::Boolfuck.new(self, input).run
|
21
|
+
end
|
22
|
+
|
23
|
+
# Interprets Smallfuck code directly on a String.
|
24
|
+
#
|
25
|
+
# @param tape [String] The initial tape state for the Smallfuck program.
|
26
|
+
# @return [String] The result of the Smallfuck interpretation.
|
27
|
+
def smallfuck(tape)
|
28
|
+
Esolang::Interpreters::Smallfuck.new(self, tape).run
|
29
|
+
end
|
30
|
+
|
31
|
+
# Interprets Paintfuck code directly on a String.
|
32
|
+
#
|
33
|
+
# @param iterations [Integer] The number of iterations for the Paintfuck program.
|
34
|
+
# @param width [Integer] The width of the Paintfuck canvas.
|
35
|
+
# @param height [Integer] The height of the Paintfuck canvas.
|
36
|
+
# @return [String] The result of the Paintfuck interpretation.
|
37
|
+
def paintfuck(iterations, width, height)
|
38
|
+
Esolang::Interpreters::Paintfuck.new(self, iterations, width, height).run
|
39
|
+
end
|
40
|
+
|
41
|
+
# Interprets Brainfuck code directly on a String.
|
42
|
+
#
|
43
|
+
# @param input [String] The input for the Brainfuck program (optional).
|
44
|
+
# @return [String] The result of the Brainfuck interpretation.
|
45
|
+
def brainfuck(input = '')
|
46
|
+
Esolang::Interpreters::Brainfuck.new(self, input).run
|
47
|
+
end
|
48
|
+
|
49
|
+
# Interprets Ook! code directly on a String.
|
50
|
+
#
|
51
|
+
# @param input [String] The input for the Ook! program (optional).
|
52
|
+
# @return [String] The result of the Ook! interpretation.
|
53
|
+
def ook(input = '')
|
54
|
+
Esolang::Interpreters::Ook.new(self, input).run
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: esolang
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Kipp
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-22 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |-
|
14
|
+
A gem for working with esoteric programming languages.
|
15
|
+
Usage: require 'esolang'; using Esolang::Refinements
|
16
|
+
Adds string refinements, usage: e.g. 'code_string'.boolfuck('user_input'). Alternative usage: e.g. Esolang.boolfuck(code, input)
|
17
|
+
email:
|
18
|
+
- daniel.kipp@gmail.com
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- lib/esolang.rb
|
24
|
+
- lib/interpreters/base_interpreter.rb
|
25
|
+
- lib/interpreters/boolfuck_interpreter.rb
|
26
|
+
- lib/interpreters/brainfuck_interpreter.rb
|
27
|
+
- lib/interpreters/ook_interpreter.rb
|
28
|
+
- lib/interpreters/paintfuck_interpreter.rb
|
29
|
+
- lib/interpreters/smallfuck_interpreter.rb
|
30
|
+
- lib/refinements/refinements.rb
|
31
|
+
homepage:
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubygems_version: 3.3.7
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: Interpreter gem for different Esolangs
|
54
|
+
test_files: []
|