Make `extern` keyword redundant

c53210515bb30a51ea8f4b23803945305e1d72f9418e1b1bd80b529c222c733c
It's strictly not needed.
Alexis Sellier committed ago 1 parent e6e66a53
lib/std/lang/parser.rad +16 -3
1920 1920
        return try parseMethodDecl(p, attrs);
1921 1921
    }
1922 1922
    let name = try parseIdent(p, "expected function name");
1923 1923
    let sig = try parseFnTypeSig(p);
1924 1924
    let mut body: ?*ast::Node = nil;
1925 +
    let mut fnAttrs = attrs;
1925 1926
1926 -
    if let a = attrs; ast::attributesContains(&a, ast::Attribute::Extern) {
1927 -
        try expect(p, scanner::TokenKind::Semicolon, "expected `;` after extern function declaration");
1927 +
    if consume(p, scanner::TokenKind::Semicolon) {
1928 +
        if let a = attrs; ast::attributesContains(&a, ast::Attribute::Extern) {
1929 +
            // Keep existing attributes unchanged.
1930 +
        } else {
1931 +
            let mut list = ast::nodeSlice(p.arena, 4);
1932 +
            if let a = attrs {
1933 +
                for i in 0..a.list.len {
1934 +
                    list.append(a.list[i], p.allocator);
1935 +
                }
1936 +
            }
1937 +
            let attrNode = nodeAttribute(p, ast::Attribute::Extern);
1938 +
            list.append(attrNode, p.allocator);
1939 +
            fnAttrs = ast::Attributes { list };
1940 +
        }
1928 1941
    } else {
1929 1942
        body = try parseBlock(p);
1930 1943
    }
1931 1944
    return node(p, ast::NodeValue::FnDecl(
1932 -
        ast::FnDecl { name, sig, body, attrs }
1945 +
        ast::FnDecl { name, sig, body, attrs: fnAttrs }
1933 1946
    ));
1934 1947
}
1935 1948
1936 1949
/// Parse a pointer or slice type.
1937 1950
fn parsePointerType(p: *mut Parser) -> *ast::Node
lib/std/lang/parser/tests.rad +57 -0
1139 1139
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Pub));
1140 1140
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1141 1141
    try testing::expect(decl.body == nil);
1142 1142
}
1143 1143
1144 +
@test fn testParseFnDeclAttributesExplicitExternKeepsTwoAttrs() throws (testing::TestError) {
1145 +
    let node = try! parseStmtStr("pub extern fn explicit();");
1146 +
    let case ast::NodeValue::FnDecl(decl) = node.value
1147 +
        else throw testing::TestError::Failed;
1148 +
1149 +
    let attrs = decl.attrs
1150 +
        else throw testing::TestError::Failed;
1151 +
    try testing::expect(attrs.list.len == 2);
1152 +
}
1153 +
1154 +
/// Test parsing a top-level function declaration with inferred extern.
1155 +
@test fn testParseFnDeclInferredExtern() throws (testing::TestError) {
1156 +
    let node = try! parseStmtStr("fn run();");
1157 +
    let case ast::NodeValue::FnDecl(decl) = node.value
1158 +
        else throw testing::TestError::Failed;
1159 +
1160 +
    try expectIdent(decl.name, "run");
1161 +
1162 +
    let attrs = decl.attrs
1163 +
        else throw testing::TestError::Failed;
1164 +
1165 +
    try testing::expect(attrs.list.len == 1);
1166 +
1167 +
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1168 +
        else throw testing::TestError::Failed;
1169 +
    try testing::expect(attr0 == ast::Attribute::Extern);
1170 +
1171 +
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1172 +
    try testing::expect(decl.body == nil);
1173 +
}
1174 +
1175 +
/// Test parsing a top-level exported function declaration with inferred extern.
1176 +
@test fn testParseFnDeclExportInferredExtern() throws (testing::TestError) {
1177 +
    let node = try! parseStmtStr("export fn run();");
1178 +
    let case ast::NodeValue::FnDecl(decl) = node.value
1179 +
        else throw testing::TestError::Failed;
1180 +
1181 +
    try expectIdent(decl.name, "run");
1182 +
1183 +
    let attrs = decl.attrs
1184 +
        else throw testing::TestError::Failed;
1185 +
1186 +
    try testing::expect(attrs.list.len == 2);
1187 +
1188 +
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1189 +
        else throw testing::TestError::Failed;
1190 +
    try testing::expect(attr0 == ast::Attribute::Pub);
1191 +
1192 +
    let case ast::NodeValue::Attribute(attr1) = attrs.list[1].value
1193 +
        else throw testing::TestError::Failed;
1194 +
    try testing::expect(attr1 == ast::Attribute::Extern);
1195 +
1196 +
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Pub));
1197 +
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1198 +
    try testing::expect(decl.body == nil);
1199 +
}
1200 +
1144 1201
/// Test parsing a scoped identifier type.
1145 1202
@test fn testParseTypeScopedIdent() throws (testing::TestError) {
1146 1203
    let node = try! parseTypeStr("module::Type");
1147 1204
    let case ast::NodeValue::TypeSig(ts) = node.value
1148 1205
        else throw testing::TestError::Failed;
test/tests/extern.inferred.rad added +5 -0
1 +
fn externalFoo() -> i32;
2 +
3 +
@default fn main() -> i32 {
4 +
    return 0;
5 +
}