compiler/
lib/
examples/
std/
arch/
rv64/
asm/
scanner/
tests.rad
6.1 KiB
emit.rad
8.2 KiB
parser.rad
30.3 KiB
scanner.rad
9.2 KiB
tests.rad
7.3 KiB
asm.rad
23.3 KiB
decode.rad
14.3 KiB
emit.rad
31.6 KiB
encode.rad
21.6 KiB
isel.rad
51.6 KiB
printer.rad
12.8 KiB
tests.rad
17.2 KiB
rv64.rad
14.4 KiB
char/
collections/
lang/
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.3 KiB
intrinsics.rad
467 B
io.rad
1.7 KiB
lang.rad
276 B
mem.rad
2.3 KiB
sys.rad
179 B
testing.rad
2.4 KiB
tests.rad
15.7 KiB
vec.rad
3.2 KiB
std.rad
281 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
336 B
.gitsigners
112 B
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
4.1 KiB
README
2.5 KiB
STYLE
2.6 KiB
std.lib
1.2 KiB
std.lib.test
347 B
lib/std/arch/rv64/asm/scanner/tests.rad
raw
| 1 | use std::mem; |
| 2 | use std::testing; |
| 3 | use std::lang::strings; |
| 4 | |
| 5 | /// String pool used by assembler scanner tests. |
| 6 | unsafe static TEST_STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 }; |
| 7 | |
| 8 | /// Create a scanner for test input. |
| 9 | fn testScanner(source: *[u8]) -> super::Scanner { |
| 10 | unsafe { |
| 11 | return super::scanner(super::SourceKind::String, source, &mut TEST_STRING_POOL); |
| 12 | } |
| 13 | } |
| 14 | |
| 15 | /// Scanner recognizes assembler-specific sigils and scoped names. |
| 16 | @test unsafe fn testScanRegisterDirectiveAndLabelTokens() throws (testing::TestError) { |
| 17 | let mut s = testScanner( |
| 18 | ".text %sp @entry name::tail 42" |
| 19 | ); |
| 20 | let directive = super::next(&mut s); |
| 21 | try testing::expect(directive.kind == super::TokenKind::Directive); |
| 22 | try testing::expect(mem::eq(directive.source, ".text")); |
| 23 | |
| 24 | let reg = super::next(&mut s); |
| 25 | try testing::expect(reg.kind == super::TokenKind::Register); |
| 26 | try testing::expect(mem::eq(reg.source, "%sp")); |
| 27 | |
| 28 | let label = super::next(&mut s); |
| 29 | try testing::expect(label.kind == super::TokenKind::Label); |
| 30 | try testing::expect(mem::eq(label.source, "@entry")); |
| 31 | |
| 32 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident); |
| 33 | try testing::expect(super::next(&mut s).kind == super::TokenKind::ColonColon); |
| 34 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident); |
| 35 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Number); |
| 36 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof); |
| 37 | } |
| 38 | |
| 39 | /// Keyword-shaped text remains plain assembler identifiers. |
| 40 | @test unsafe fn testScanKeywordShapedAsmNamesRemainAsmTokens() throws (testing::TestError) { |
| 41 | let mut s = testScanner( |
| 42 | "and or not align addi .text @label" |
| 43 | ); |
| 44 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident); |
| 45 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident); |
| 46 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident); |
| 47 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident); |
| 48 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident); |
| 49 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Directive); |
| 50 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Label); |
| 51 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof); |
| 52 | } |
| 53 | |
| 54 | /// Quoted labels can spell symbol names that are not identifier-shaped. |
| 55 | @test unsafe fn testScanQuotedLabelToken() throws (testing::TestError) { |
| 56 | let mut s = testScanner( |
| 57 | "@\"foo.bar.baz\"" |
| 58 | ); |
| 59 | let label = super::next(&mut s); |
| 60 | try testing::expect(label.kind == super::TokenKind::QuotedLabel); |
| 61 | try testing::expect(mem::eq(label.source, "@\"foo.bar.baz\"")); |
| 62 | try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof); |
| 63 | } |
| 64 | |
| 65 | /// Sigil-prefixed tokens require the name to start immediately after the sigil. |
| 66 | @test unsafe fn testScanSigilsRequireAdjacency() throws (testing::TestError) { |
| 67 | let mut regScan = testScanner("% a0"); |
| 68 | try testing::expect(super::next(&mut regScan).kind == super::TokenKind::Invalid); |
| 69 | |
| 70 | let mut labelScan = testScanner("@ entry"); |
| 71 | try testing::expect(super::next(&mut labelScan).kind == super::TokenKind::Invalid); |
| 72 | |
| 73 | let mut directiveScan = testScanner(". text"); |
| 74 | try testing::expect(super::next(&mut directiveScan).kind == super::TokenKind::Invalid); |
| 75 | } |
| 76 | |
| 77 | /// Scanner reaches EOF after trailing whitespace and comments. |
| 78 | @test unsafe fn testScanProgramEndingWithNewline() throws (testing::TestError) { |
| 79 | let mut s = testScanner( |
| 80 | ".text;\n@start\naddi %a0 %zero 42;\nsd %a0 8(%sp);\n// comment\nbeq %a0 %zero @done;\n@done\nret;\n" |
| 81 | ); |
| 82 | loop { |
| 83 | let tok = super::next(&mut s); |
| 84 | if tok.kind == super::TokenKind::Eof { |
| 85 | try testing::expect(tok.source.len == 0); |
| 86 | return; |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | /// Signed numbers scan only the numeric formats supported by the assembler scanner. |
| 92 | @test unsafe fn testScanSignedHexAndUnsupportedNumericForms() throws (testing::TestError) { |
| 93 | let mut s = testScanner( |
| 94 | "+0x2a -0b10 45.5" |
| 95 | ); |
| 96 | let mut tok = super::next(&mut s); |
| 97 | try testing::expect(tok.kind == super::TokenKind::Number); |
| 98 | try testing::expect(mem::eq(tok.source, "+0x2a")); |
| 99 | |
| 100 | set tok = super::next(&mut s); |
| 101 | try testing::expect(tok.kind == super::TokenKind::Number); |
| 102 | try testing::expect(mem::eq(tok.source, "-0")); |
| 103 | |
| 104 | set tok = super::next(&mut s); |
| 105 | try testing::expect(tok.kind == super::TokenKind::Ident); |
| 106 | try testing::expect(mem::eq(tok.source, "b10")); |
| 107 | |
| 108 | set tok = super::next(&mut s); |
| 109 | try testing::expect(tok.kind == super::TokenKind::Number); |
| 110 | try testing::expect(mem::eq(tok.source, "45")); |
| 111 | |
| 112 | set tok = super::next(&mut s); |
| 113 | try testing::expect(tok.kind == super::TokenKind::Invalid); |
| 114 | try testing::expect(mem::eq(tok.source, "expected directive name after `.`")); |
| 115 | |
| 116 | set tok = super::next(&mut s); |
| 117 | try testing::expect(tok.kind == super::TokenKind::Number); |
| 118 | try testing::expect(mem::eq(tok.source, "5")); |
| 119 | } |
| 120 | |
| 121 | /// Unterminated string and character literals report invalid tokens. |
| 122 | @test unsafe fn testScanUnterminatedDelimitedLiterals() throws (testing::TestError) { |
| 123 | let mut stringScan = testScanner("\"unterminated"); |
| 124 | let stringTok = super::next(&mut stringScan); |
| 125 | try testing::expect(stringTok.kind == super::TokenKind::Invalid); |
| 126 | try testing::expect(mem::eq(stringTok.source, "unterminated string")); |
| 127 | |
| 128 | let mut escapedStringScan = testScanner("\"unterminated\\"); |
| 129 | let escapedStringTok = super::next(&mut escapedStringScan); |
| 130 | try testing::expect(escapedStringTok.kind == super::TokenKind::Invalid); |
| 131 | try testing::expect(mem::eq(escapedStringTok.source, "unterminated string")); |
| 132 | |
| 133 | let mut charScan = testScanner("'x"); |
| 134 | let charTok = super::next(&mut charScan); |
| 135 | try testing::expect(charTok.kind == super::TokenKind::Invalid); |
| 136 | try testing::expect(mem::eq(charTok.source, "unterminated character")); |
| 137 | |
| 138 | let mut escapedCharScan = testScanner("'\\"); |
| 139 | let escapedCharTok = super::next(&mut escapedCharScan); |
| 140 | try testing::expect(escapedCharTok.kind == super::TokenKind::Invalid); |
| 141 | try testing::expect(mem::eq(escapedCharTok.source, "unterminated character")); |
| 142 | } |