Skip to content

Commit 5049e3f

Browse files
Fix WAT parsing around heap type and skip concrete heap type parsing
We need to change the core `ValueType` modeling to support the concrete heap type, which can reference another type by index, but it would be a non-trivial change. So, for now, we skip parsing the concrete heap type and only support the abstract heap type for now.
1 parent 9966354 commit 5049e3f

File tree

2 files changed

+40
-54
lines changed

2 files changed

+40
-54
lines changed

Sources/WAT/Parser/WatParser.swift

Lines changed: 38 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ struct WatParser {
238238
var inlineElement: ElementDecl?
239239
let isMemory64 = try expectAddressSpaceType()
240240

241-
if let refType = try maybeRefType() {
241+
if let refType = try takeRefType() {
242242
guard try parser.takeParenBlockStart("elem") else {
243243
throw WatParserError("expected elem", location: parser.lexer.location())
244244
}
@@ -373,7 +373,7 @@ struct WatParser {
373373
// | funcidx* (iff the tableuse is omitted)
374374
let indices: ElementDecl.Indices
375375
let type: ReferenceType
376-
if let refType = try maybeRefType() {
376+
if let refType = try takeRefType() {
377377
indices = .elementExprList(parser.lexer)
378378
type = refType
379379
} else if try parser.takeKeyword("func") || table == nil {
@@ -606,70 +606,56 @@ struct WatParser {
606606
}
607607

608608
mutating func valueType() throws -> ValueType {
609-
if try parser.peek(.leftParen) != nil {
610-
return try _referenceValueType()
609+
if try parser.takeKeyword("i32") {
610+
return .i32
611+
} else if try parser.takeKeyword("i64") {
612+
return .i64
613+
} else if try parser.takeKeyword("f32") {
614+
return .f32
615+
} else if try parser.takeKeyword("f64") {
616+
return .f64
617+
} else if let refType = try takeRefType() {
618+
return .ref(refType)
611619
} else {
612-
return try _valueType()
613-
}
614-
}
615-
616-
// must consume right paren
617-
mutating func _referenceValueType() throws -> ValueType {
618-
var isNullable = false
619-
_ = try parser.takeParenBlockStart("ref")
620-
if try parser.peekKeyword() == "null" {
621-
_ = try parser.takeKeyword("null")
622-
isNullable = true
623-
}
624-
625-
if try parser.takeId() != nil {
626-
_ = try parser.take(.rightParen)
627-
return .ref(refType(keyword: "func", isNullable: isNullable)!)
628-
}
629-
630-
let keyword = try parser.expectKeyword()
631-
_ = try parser.take(.rightParen)
632-
if let refType = refType(keyword: keyword, isNullable: isNullable) { return .ref(refType) }
633-
throw WatParserError("unexpected value type \(keyword)", location: parser.lexer.location())
634-
}
635-
636-
mutating func _valueType() throws -> ValueType {
637-
let keyword = try parser.expectKeyword()
638-
switch keyword {
639-
case "i32": return .i32
640-
case "i64": return .i64
641-
case "f32": return .f32
642-
case "f64": return .f64
643-
default:
644-
if let refType = refType(keyword: keyword, isNullable: true) { return .ref(refType) }
645-
throw WatParserError("unexpected value type \(keyword)", location: parser.lexer.location())
646-
}
647-
}
648-
649-
mutating func refType(keyword: String, isNullable: Bool) -> ReferenceType? {
650-
switch keyword {
651-
case "funcref": return .funcRef
652-
case "externref": return .externRef
653-
case "func": return ReferenceType(isNullable: isNullable, heapType: .funcRef)
654-
case "extern": return ReferenceType(isNullable: isNullable, heapType: .funcRef)
655-
default: return nil
620+
throw WatParserError("expected value type", location: parser.lexer.location())
656621
}
657622
}
658623

659624
mutating func refType() throws -> ReferenceType {
660-
let keyword = try parser.expectKeyword()
661-
guard let refType = refType(keyword: keyword, isNullable: true) else {
662-
throw WatParserError("unexpected ref type \(keyword)", location: parser.lexer.location())
625+
guard let refType = try takeRefType() else {
626+
throw WatParserError("expected reference type", location: parser.lexer.location())
663627
}
664628
return refType
665629
}
666630

667-
mutating func maybeRefType() throws -> ReferenceType? {
631+
/// Parse a reference type tokens if the head tokens seems like so.
632+
mutating func takeRefType() throws -> ReferenceType? {
633+
// Check abbreviations first
634+
// https://webassembly.github.io/function-references/core/text/types.html#abbreviations
668635
if try parser.takeKeyword("funcref") {
669636
return .funcRef
670637
} else if try parser.takeKeyword("externref") {
671638
return .externRef
639+
} else if try parser.takeParenBlockStart("ref") {
640+
let isNullable = try parser.takeKeyword("null")
641+
let heapType = try heapType()
642+
try parser.expect(.rightParen)
643+
return ReferenceType(isNullable: isNullable, heapType: heapType)
672644
}
673645
return nil
674646
}
647+
648+
/// > Note:
649+
/// <https://webassembly.github.io/function-references/core/text/types.html#heap-types>
650+
mutating func heapType() throws -> HeapType {
651+
if try parser.takeKeyword("func") {
652+
return .abstract(.funcRef)
653+
} else if try parser.takeKeyword("extern") {
654+
return .abstract(.externRef)
655+
} else if try parser.takeIndexOrId() != nil {
656+
// TODO: Implement (ref $t)
657+
throw WatParserError("concrete heap type is not supported yet", location: parser.lexer.location())
658+
}
659+
throw WatParserError("expected heap type", location: parser.lexer.location())
660+
}
675661
}

Tests/WasmKitTests/SpectestTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ final class SpectestTests: XCTestCase {
7373
configuration: defaultConfig
7474
)
7575

76-
XCTAssertEqual(result.passed, 1400)
77-
XCTAssertEqual(result.failed, 134)
76+
XCTAssertEqual(result.passed, 1228)
77+
XCTAssertEqual(result.failed, 49)
7878
XCTAssertEqual(
7979
result.sortedFailedCases(),
8080
[

0 commit comments

Comments
 (0)