hack_assembler 0.1.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/.gitignore +9 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/Pong.asm +28374 -0
- data/PongL.asm +27490 -0
- data/README.md +32 -0
- data/Rakefile +10 -0
- data/bin/hack_assembler +17 -0
- data/hack2asm.gemspec +24 -0
- data/lib/hack_assembler/a_instruction.rb +14 -0
- data/lib/hack_assembler/assembler.rb +21 -0
- data/lib/hack_assembler/c_instruction.rb +17 -0
- data/lib/hack_assembler/computation_translator.rb +41 -0
- data/lib/hack_assembler/destination_translator.rb +22 -0
- data/lib/hack_assembler/jump_translator.rb +22 -0
- data/lib/hack_assembler/parser_error.rb +4 -0
- data/lib/hack_assembler/version.rb +3 -0
- data/lib/hack_assembler.rb +21 -0
- data/out.hack +27483 -0
- data/test/a_instruction_test.rb +21 -0
- data/test/assembler_test.rb +27 -0
- data/test/c_instruction_test.rb +44 -0
- data/test/computation_translator_test.rb +115 -0
- data/test/destination_translator_test.rb +39 -0
- data/test/hack2asm_test.rb +7 -0
- data/test/jump_translator_test.rb +39 -0
- data/test/test_helper.rb +6 -0
- metadata +123 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AInstructionTest < Minitest::Test
|
4
|
+
def test_that_it_converts_zero
|
5
|
+
bytecode = AInstruction.translate('@0')
|
6
|
+
assert_equal '0000000000000000', bytecode
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_that_it_converts_a_positive_value
|
10
|
+
bytecode = AInstruction.translate('@4')
|
11
|
+
assert_equal '0000000000000100', bytecode
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_that_it_raises_parser_error_on_symbol
|
15
|
+
assert_raises(ParserError) { AInstruction.translate('@ERR') }
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_that_it_raises_parser_error_on_missing_value
|
19
|
+
assert_raises(ParserError) { AInstruction.translate('@') }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AssemblerTest < Minitest::Test
|
4
|
+
def test_translates_a_and_c_instructions
|
5
|
+
source_code = "@4\n" << "0;JMP\n"
|
6
|
+
bytecode = Assembler.translate(source_code)
|
7
|
+
assert_equal "0000000000000100\n" << "1110101010000111\n", bytecode
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_ignores_comments
|
11
|
+
source_code = "// A comment\n" << "@4\n" << "// Another comment\n"
|
12
|
+
bytecode = Assembler.translate(source_code)
|
13
|
+
assert_equal "0000000000000100\n", bytecode
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_ignores_empty_lines
|
17
|
+
source_code = "\n@4\n\n"
|
18
|
+
bytecode = Assembler.translate(source_code)
|
19
|
+
assert_equal "0000000000000100\n", bytecode
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_ignores_indentation_and_trailing_spaces
|
23
|
+
source_code = " @4 \n"
|
24
|
+
bytecode = Assembler.translate(source_code)
|
25
|
+
assert_equal "0000000000000100\n", bytecode
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CInstructionTest < Minitest::Test
|
4
|
+
def test_translation_of_unconditional_jump
|
5
|
+
bytecode = CInstruction.translate('0;JMP')
|
6
|
+
assert_equal '1110101010000111', bytecode
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_translation_of_assignment
|
10
|
+
bytecode = CInstruction.translate('A=M+1')
|
11
|
+
assert_equal '1111110111100000', bytecode
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_that_bad_instruction_raises_error
|
15
|
+
assert_raises(ParserError) { CInstruction.translate(';JMP') }
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_that_computation_translator_writes_on_output
|
19
|
+
bytecode = nil
|
20
|
+
ComputationTranslator.stub(:translate, '0000000') do
|
21
|
+
bytecode = CInstruction.translate('0;JMP')
|
22
|
+
end
|
23
|
+
|
24
|
+
assert_equal '1110000000000111', bytecode
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_that_destination_translator_writes_on_output
|
28
|
+
bytecode = nil
|
29
|
+
DestinationTranslator.stub(:translate, '111') do
|
30
|
+
bytecode = CInstruction.translate('0;JMP')
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_equal '1110101010111111', bytecode
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_that_jump_translator_writes_on_output
|
37
|
+
bytecode = nil
|
38
|
+
JumpTranslator.stub(:translate, '000') do
|
39
|
+
bytecode = CInstruction.translate('0;JMP')
|
40
|
+
end
|
41
|
+
|
42
|
+
assert_equal '1110101010000000', bytecode
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ComputationTranslatorTest < Minitest::Test
|
4
|
+
def test_that_it_raises_error_on_unknown_code
|
5
|
+
assert_raises(ParserError) { ComputationTranslator.translate('X') }
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_that_it_converts_single_register_code_for_a
|
9
|
+
assert_equal '0110000', ComputationTranslator.translate('A')
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_that_it_converts_single_register_code_for_m
|
13
|
+
assert_equal '1110000', ComputationTranslator.translate('M')
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_that_it_converts_one_constant
|
17
|
+
assert_equal '0111111', ComputationTranslator.translate('1')
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_that_it_converts_minus_one_constant
|
21
|
+
assert_equal '0111010', ComputationTranslator.translate('-1')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_that_it_converts_d_register
|
25
|
+
assert_equal '0001100', ComputationTranslator.translate('D')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_that_it_converts_not_d_register
|
29
|
+
assert_equal '0001101', ComputationTranslator.translate('!D')
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_that_it_converts_not_a_register
|
33
|
+
assert_equal '0110001', ComputationTranslator.translate('!A')
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_that_it_converts_not_m_register
|
37
|
+
assert_equal '1110001', ComputationTranslator.translate('!M')
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_that_it_converts_minus_d_register
|
41
|
+
assert_equal '0001111', ComputationTranslator.translate('-D')
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_that_it_converts_minus_a_register
|
45
|
+
assert_equal '0110011', ComputationTranslator.translate('-A')
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_that_it_converts_minus_m_register
|
49
|
+
assert_equal '1110011', ComputationTranslator.translate('-M')
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_that_it_converts_d_register_plus_one
|
53
|
+
assert_equal '0011111', ComputationTranslator.translate('D+1')
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_that_it_converts_a_register_plus_one
|
57
|
+
assert_equal '0110111', ComputationTranslator.translate('A+1')
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_that_it_converts_m_register_plus_one
|
61
|
+
assert_equal '1110111', ComputationTranslator.translate('M+1')
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_that_it_converts_d_register_minus_one
|
65
|
+
assert_equal '0001110', ComputationTranslator.translate('D-1')
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_that_it_converts_a_register_minus_one
|
69
|
+
assert_equal '0110010', ComputationTranslator.translate('A-1')
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_that_it_converts_m_register_minus_one
|
73
|
+
assert_equal '1110010', ComputationTranslator.translate('M-1')
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_that_it_converts_d_register_plus_a_register
|
77
|
+
assert_equal '0000010', ComputationTranslator.translate('D+A')
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_that_it_converts_d_register_plus_m_register
|
81
|
+
assert_equal '1000010', ComputationTranslator.translate('D+M')
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_that_it_converts_d_register_minus_a_register
|
85
|
+
assert_equal '0010011', ComputationTranslator.translate('D-A')
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_that_it_converts_d_register_minus_m_register
|
89
|
+
assert_equal '1010011', ComputationTranslator.translate('D-M')
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_that_it_converts_a_register_minus_d_register
|
93
|
+
assert_equal '0000111', ComputationTranslator.translate('A-D')
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_that_it_converts_m_register_minus_d_register
|
97
|
+
assert_equal '1000111', ComputationTranslator.translate('M-D')
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_that_it_converts_d_register_and_a_register
|
101
|
+
assert_equal '0000000', ComputationTranslator.translate('D&A')
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_that_it_converts_d_register_and_m_register
|
105
|
+
assert_equal '1000000', ComputationTranslator.translate('D&M')
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_that_it_converts_d_register_or_a_register
|
109
|
+
assert_equal '0010101', ComputationTranslator.translate('D|A')
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_that_it_converts_d_register_or_m_register
|
113
|
+
assert_equal '1010101', ComputationTranslator.translate('D|M')
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DestinationTranslatorTest < Minitest::Test
|
4
|
+
def test_that_it_raises_error_on_unknown_code
|
5
|
+
assert_raises(ParserError) { DestinationTranslator.translate('ADZ') }
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_that_it_translates_null_destination_code
|
9
|
+
assert_equal '000', DestinationTranslator.translate(nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_that_it_translates_m_destination_code
|
13
|
+
assert_equal '001', DestinationTranslator.translate('M')
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_that_it_translates_d_destination_code
|
17
|
+
assert_equal '010', DestinationTranslator.translate('D')
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_that_it_translates_md_destination_code
|
21
|
+
assert_equal '011', DestinationTranslator.translate('MD')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_that_it_translates_a_destination_code
|
25
|
+
assert_equal '100', DestinationTranslator.translate('A')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_that_it_translates_am_destination_code
|
29
|
+
assert_equal '101', DestinationTranslator.translate('AM')
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_that_it_translates_ad_destination_code
|
33
|
+
assert_equal '110', DestinationTranslator.translate('AD')
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_that_it_translates_amd_destination_code
|
37
|
+
assert_equal '111', DestinationTranslator.translate('AMD')
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class JumpTranslatorTest < Minitest::Test
|
4
|
+
def test_that_it_raises_error_on_unknown_code
|
5
|
+
assert_raises(ParserError) { JumpTranslator.translate('ERR') }
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_that_it_translates_null_code
|
9
|
+
assert_equal '000', JumpTranslator.translate(nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_that_it_translates_unconditional_jump_code
|
13
|
+
assert_equal '111', JumpTranslator.translate('JMP')
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_that_it_translates_greater_than_zero_jump_code
|
17
|
+
assert_equal '001', JumpTranslator.translate('JGT')
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_that_it_translates_equals_zero_jump_code
|
21
|
+
assert_equal '010', JumpTranslator.translate('JEQ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_that_it_translates_greater_or_equals_zero_jump_code
|
25
|
+
assert_equal '011', JumpTranslator.translate('JGE')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_that_it_translates_less_than_zero_jump_code
|
29
|
+
assert_equal '100', JumpTranslator.translate('JLT')
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_that_it_translates_not_equals_zero_jump_code
|
33
|
+
assert_equal '101', JumpTranslator.translate('JNE')
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_that_it_translates_less_or_equals_zero_jump_code
|
37
|
+
assert_equal '110', JumpTranslator.translate('JLE')
|
38
|
+
end
|
39
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hack_assembler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Federico Rebora
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-24 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.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
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: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Assembler that takes .hack code and converts it to Hack machine ASM
|
56
|
+
email:
|
57
|
+
- ufinii@gmail.com
|
58
|
+
executables:
|
59
|
+
- hack_assembler
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".travis.yml"
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE.txt
|
67
|
+
- Pong.asm
|
68
|
+
- PongL.asm
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/hack_assembler
|
72
|
+
- hack2asm.gemspec
|
73
|
+
- lib/hack_assembler.rb
|
74
|
+
- lib/hack_assembler/a_instruction.rb
|
75
|
+
- lib/hack_assembler/assembler.rb
|
76
|
+
- lib/hack_assembler/c_instruction.rb
|
77
|
+
- lib/hack_assembler/computation_translator.rb
|
78
|
+
- lib/hack_assembler/destination_translator.rb
|
79
|
+
- lib/hack_assembler/jump_translator.rb
|
80
|
+
- lib/hack_assembler/parser_error.rb
|
81
|
+
- lib/hack_assembler/version.rb
|
82
|
+
- out.hack
|
83
|
+
- test/a_instruction_test.rb
|
84
|
+
- test/assembler_test.rb
|
85
|
+
- test/c_instruction_test.rb
|
86
|
+
- test/computation_translator_test.rb
|
87
|
+
- test/destination_translator_test.rb
|
88
|
+
- test/hack2asm_test.rb
|
89
|
+
- test/jump_translator_test.rb
|
90
|
+
- test/test_helper.rb
|
91
|
+
homepage: ''
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.4.5
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Converts .hack files to .asm
|
115
|
+
test_files:
|
116
|
+
- test/a_instruction_test.rb
|
117
|
+
- test/assembler_test.rb
|
118
|
+
- test/c_instruction_test.rb
|
119
|
+
- test/computation_translator_test.rb
|
120
|
+
- test/destination_translator_test.rb
|
121
|
+
- test/hack2asm_test.rb
|
122
|
+
- test/jump_translator_test.rb
|
123
|
+
- test/test_helper.rb
|