Implement parsing for *traits* feature

7c675193733c63905e6b426393a971e02397bf82be956f5aa664e047c51d66d6
Alexis Sellier committed ago 1 parent 66464ff6
lib/std/lang/ast.rad +47 -0
277 277
        /// Whether this record has labeled fields.
278 278
        labeled: bool,
279 279
    },
280 280
    /// Anonymous function type.
281 281
    Fn(FnSig),
282 +
    /// Trait object type, eg. `*opaque Allocator`.
283 +
    TraitObject {
284 +
        /// Trait name identifier.
285 +
        traitName: *Node,
286 +
        /// Whether the pointer is mutable.
287 +
        mutable: bool,
288 +
    },
282 289
}
283 290
284 291
/// Function signature.
285 292
pub record FnSig {
286 293
    /// Parameter type nodes in declaration order.
801 808
        /// Alignment value.
802 809
        value: *Node,
803 810
    },
804 811
    /// Catch clause within a try expression.
805 812
    CatchClause(CatchClause),
813 +
    /// Trait declaration.
814 +
    TraitDecl {
815 +
        /// Trait name identifier.
816 +
        name: *Node,
817 +
        /// Method signature nodes ([`TraitMethodSig`]).
818 +
        methods: NodeList,
819 +
        /// Optional attributes.
820 +
        attrs: ?Attributes,
821 +
    },
822 +
    /// Method signature inside a trait declaration.
823 +
    TraitMethodSig {
824 +
        /// Method name identifier.
825 +
        name: *Node,
826 +
        /// Receiver type node (eg. `*mut Allocator`).
827 +
        receiver: *Node,
828 +
        /// Function signature.
829 +
        sig: FnSig,
830 +
    },
831 +
    /// Instance block.
832 +
    InstanceDecl {
833 +
        /// Trait name identifier.
834 +
        traitName: *Node,
835 +
        /// Target type identifier.
836 +
        targetType: *Node,
837 +
        /// Method definition nodes ([`InstanceMethodDecl`]).
838 +
        methods: NodeList,
839 +
    },
840 +
    /// Method definition inside an instance block.
841 +
    InstanceMethodDecl {
842 +
        /// Method name identifier.
843 +
        name: *Node,
844 +
        /// Receiver binding name ([`Ident`] node).
845 +
        receiverName: *Node,
846 +
        /// Receiver type node (eg. `*mut Arena`).
847 +
        receiverType: *Node,
848 +
        /// Function signature.
849 +
        sig: FnSig,
850 +
        /// Method body.
851 +
        body: *Node,
852 +
    },
806 853
}
807 854
808 855
/// Full AST node with shared metadata and variant-specific payload.
809 856
pub record Node {
810 857
    /// Unique identifier for this node.
lib/std/lang/ast/printer.rad +21 -0
93 93
            if let rt = sig.returnType {
94 94
                ret = toExpr(a, rt);
95 95
            }
96 96
            return sexpr::list(a, "fn", &[sexpr::list(a, "params", nodeListToExprs(a, &sig.params)), ret]);
97 97
        }
98 +
        case super::TypeSig::TraitObject { traitName, mutable } =>
99 +
            return sexpr::list(a, "obj", &[sexpr::sym("mut"), toExpr(a, traitName)]) if mutable
100 +
                else sexpr::list(a, "obj", &[toExpr(a, traitName)]),
98 101
    }
99 102
}
100 103
101 104
/// Convert a node list to a slice of expressions.
102 105
fn nodeListToExprs(a: *mut alloc::Arena, nodes: *super::NodeList) -> *[sexpr::Expr] {
433 436
        }
434 437
        case super::NodeValue::UnionDeclVariant(v) => {
435 438
            return variantToExpr(a, v.name, v.type);
436 439
        }
437 440
        case super::NodeValue::ExprStmt(e) => return toExpr(a, e),
441 +
        case super::NodeValue::TraitDecl { name, methods, .. } => {
442 +
            let children = nodeListToExprs(a, &methods);
443 +
            return sexpr::block(a, "trait", &[toExpr(a, name)], children);
444 +
        }
445 +
        case super::NodeValue::TraitMethodSig { name, receiver, sig } => {
446 +
            let params = sexpr::list(a, "params", nodeListToExprs(a, &sig.params));
447 +
            let ret = toExprOrNull(a, sig.returnType);
448 +
            return sexpr::list(a, "methodSig", &[toExpr(a, receiver), toExpr(a, name), params, ret]);
449 +
        }
450 +
        case super::NodeValue::InstanceDecl { traitName, targetType, methods } => {
451 +
            let children = nodeListToExprs(a, &methods);
452 +
            return sexpr::block(a, "instance", &[toExpr(a, traitName), toExpr(a, targetType)], children);
453 +
        }
454 +
        case super::NodeValue::InstanceMethodDecl { name, receiverName, receiverType, sig, body } => {
455 +
            let params = sexpr::list(a, "params", nodeListToExprs(a, &sig.params));
456 +
            let ret = toExprOrNull(a, sig.returnType);
457 +
            return sexpr::block(a, "method", &[toExpr(a, receiverType), toExpr(a, receiverName), toExpr(a, name), params, ret], &[toExpr(a, body)]);
458 +
        }
438 459
        else => return sexpr::sym("?"),
439 460
    }
440 461
}
441 462
442 463
/// Dump the tree rooted at `root`, using the provided arena for allocation.
lib/std/lang/parser.rad +140 -18
13 13
pub const U32_MAX: u32 = 0xFFFFFFFF;
14 14
/// Maximum representable `u64` value.
15 15
pub const U64_MAX: u64 = 0xFFFFFFFFFFFFFFFF;
16 16
/// Maximum number of fields in a record.
17 17
pub const MAX_RECORD_FIELDS: u32 = 32;
18 +
/// Maximum number of trait methods.
19 +
pub const MAX_TRAIT_METHODS: u32 = 8;
18 20
19 21
/// Maximum number of parser errors before aborting.
20 22
const MAX_ERRORS: u32 = 8;
21 23
22 24
/// Parser error type.
672 674
        case ast::NodeValue::Match(_) => return false,
673 675
        case ast::NodeValue::Block(_) => return false,
674 676
        case ast::NodeValue::FnDecl(_) => return false,
675 677
        case ast::NodeValue::RecordDecl(_) => return false,
676 678
        case ast::NodeValue::UnionDecl(_) => return false,
679 +
        case ast::NodeValue::TraitDecl { .. } => return false,
680 +
        case ast::NodeValue::InstanceDecl { .. } => return false,
677 681
        else => return true,
678 682
    }
679 683
}
680 684
681 685
/// Parse a primary leaf expression without postfix operators.
955 959
            p.current.kind == scanner::TokenKind::Union or
956 960
            p.current.kind == scanner::TokenKind::Record or
957 961
            p.current.kind == scanner::TokenKind::Mod or
958 962
            p.current.kind == scanner::TokenKind::Static or
959 963
            p.current.kind == scanner::TokenKind::Const or
960 -
            p.current.kind == scanner::TokenKind::Use;
964 +
            p.current.kind == scanner::TokenKind::Use or
965 +
            p.current.kind == scanner::TokenKind::Trait;
961 966
962 967
        if not allowed {
963 968
            throw failParsing(p, "attributes are not allowed in this context");
964 969
        }
965 970
    }
1032 1037
            return try parseUse(p, attrs);
1033 1038
        }
1034 1039
        case scanner::TokenKind::Mod => {
1035 1040
            return try parseMod(p, attrs);
1036 1041
        }
1042 +
        case scanner::TokenKind::Trait => {
1043 +
            return try parseTraitDecl(p, attrs);
1044 +
        }
1045 +
        case scanner::TokenKind::Instance => {
1046 +
            return try parseInstanceDecl(p);
1047 +
        }
1037 1048
        else => {
1038 1049
            return try parseExprStmt(p);
1039 1050
        }
1040 1051
    }
1041 1052
}
1933 1944
1934 1945
        return node(p, ast::NodeValue::TypeSig(
1935 1946
            ast::TypeSig::Slice { itemType, mutable }
1936 1947
        ));
1937 1948
    }
1949 +
    // Check for `*opaque Trait` or `*mut opaque Trait`.
1950 +
    if consume(p, scanner::TokenKind::Opaque) {
1951 +
        if check(p, scanner::TokenKind::Ident) or check(p, scanner::TokenKind::Super) {
1952 +
            let traitName = try parseTypePath(p);
1953 +
            return node(p, ast::NodeValue::TypeSig(
1954 +
                ast::TypeSig::TraitObject { traitName, mutable }
1955 +
            ));
1956 +
        }
1957 +
        // Plain `*opaque`.
1958 +
        return node(p, ast::NodeValue::TypeSig(
1959 +
            ast::TypeSig::Pointer {
1960 +
                valueType: node(p, ast::NodeValue::TypeSig(ast::TypeSig::Opaque)),
1961 +
                mutable,
1962 +
            }
1963 +
        ));
1964 +
    }
1938 1965
    let valueType = try parseType(p);
1939 1966
1940 1967
    return node(p, ast::NodeValue::TypeSig(
1941 1968
        ast::TypeSig::Pointer { valueType, mutable }
1942 1969
    ));
1956 1983
    return node(p, ast::NodeValue::TypeSig(
1957 1984
        ast::TypeSig::Array { itemType, length }
1958 1985
    ));
1959 1986
}
1960 1987
1988 +
/// Parse a type path: an identifier optionally followed by `::` scope access.
1989 +
/// Returns an identifier node or a scope access chain.
1990 +
fn parseTypePath(p: *mut Parser) -> *ast::Node
1991 +
    throws (ParseError)
1992 +
{
1993 +
    let mut path: *ast::Node = undefined;
1994 +
    if p.current.kind == scanner::TokenKind::Super {
1995 +
        advance(p);
1996 +
        path = nodeSuper(p);
1997 +
    } else {
1998 +
        path = try parseIdent(p, "expected type identifier");
1999 +
    }
2000 +
    while consume(p, scanner::TokenKind::ColonColon) {
2001 +
        let part = try parseIdent(p, "expected identifier after `::`");
2002 +
        path = node(p, ast::NodeValue::ScopeAccess(
2003 +
            ast::Access { parent: path, child: part }
2004 +
        ));
2005 +
    }
2006 +
    return path;
2007 +
}
2008 +
1961 2009
/// Parse a type annotation.
1962 -
///
1963 -
/// Handles primitive types (u8, u16, u32, i8, i16, i32, bool, void),
1964 -
/// optional types (?T), pointer types (*T), array types ([T; N]),
1965 -
/// slice types (*[T]), record types, and function types.
1966 2010
pub fn parseType(p: *mut Parser) -> *ast::Node
1967 2011
    throws (ParseError)
1968 2012
{
1969 2013
    match p.current.kind {
1970 2014
        case scanner::TokenKind::Question => {
1980 2024
        }
1981 2025
        case scanner::TokenKind::LBracket => {
1982 2026
            return try parseArrayType(p);
1983 2027
        }
1984 2028
        case scanner::TokenKind::Super, scanner::TokenKind::Ident => {
1985 -
            let mut path: *ast::Node = undefined;
1986 -
            if p.current.kind == scanner::TokenKind::Super {
1987 -
                advance(p);
1988 -
                path = nodeSuper(p);
1989 -
            } else {
1990 -
                path = try parseIdent(p, "expected type identifier");
1991 -
            }
1992 -
            while consume(p, scanner::TokenKind::ColonColon) {
1993 -
                let part = try parseIdent(p, "expected identifier after `::`");
1994 -
                path = node(p, ast::NodeValue::ScopeAccess(
1995 -
                    ast::Access { parent: path, child: part }
1996 -
                ));
1997 -
            }
2029 +
            let path = try parseTypePath(p);
2030 +
1998 2031
            return node(p, ast::NodeValue::TypeSig(
1999 2032
                ast::TypeSig::Nominal(path)
2000 2033
            ));
2001 2034
        }
2002 2035
        case scanner::TokenKind::U8 => {
2270 2303
        case scanner::TokenKind::RBrace => return "expected `}`",
2271 2304
        else => return "expected delimiter",
2272 2305
    }
2273 2306
}
2274 2307
2308 +
/// Parse a trait declaration.
2309 +
/// Syntax: `trait Name { fn (*Trait) method(...) -> T; ... }`
2310 +
fn parseTraitDecl(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
2311 +
    throws (ParseError)
2312 +
{
2313 +
    try expect(p, scanner::TokenKind::Trait, "expected `trait`");
2314 +
    let name = try parseIdent(p, "expected trait name");
2315 +
    try expect(p, scanner::TokenKind::LBrace, "expected `{` after trait name");
2316 +
2317 +
    let mut methods = ast::nodeList(p.arena, MAX_TRAIT_METHODS);
2318 +
    while not check(p, scanner::TokenKind::RBrace) and
2319 +
          not check(p, scanner::TokenKind::Eof)
2320 +
    {
2321 +
        let method = try parseTraitMethodSig(p);
2322 +
        ast::nodeListPush(&mut methods, method);
2323 +
    }
2324 +
    try expect(p, scanner::TokenKind::RBrace, "expected `}` after trait methods");
2325 +
2326 +
    return node(p, ast::NodeValue::TraitDecl { name, methods, attrs });
2327 +
}
2328 +
2329 +
/// Parse a trait method signature.
2330 +
/// Syntax: `fn (*Trait) fnord(<params>) -> ReturnType;`
2331 +
fn parseTraitMethodSig(p: *mut Parser) -> *ast::Node
2332 +
    throws (ParseError)
2333 +
{
2334 +
    try expect(p, scanner::TokenKind::Fn, "expected `fn`");
2335 +
    try expect(p, scanner::TokenKind::LParen, "expected `(` before receiver");
2336 +
2337 +
    let receiver = try parseType(p);
2338 +
2339 +
    try expect(p, scanner::TokenKind::RParen, "expected `)` after receiver");
2340 +
2341 +
    let name = try parseIdent(p, "expected method name");
2342 +
    let sig = try parseFnTypeSig(p);
2343 +
    try expect(p, scanner::TokenKind::Semicolon, "expected `;` after method signature");
2344 +
2345 +
    return node(p, ast::NodeValue::TraitMethodSig { name, receiver, sig });
2346 +
}
2347 +
2348 +
/// Parse an instance block.
2349 +
/// Syntax: `instance Trait for Type { fn (t: *mut Type) fnord(..) {..} }`
2350 +
///
2351 +
/// Instance declarations do not accept attributes (e.g. `pub`).
2352 +
/// Visibility is determined by the trait declaration itself.
2353 +
fn parseInstanceDecl(p: *mut Parser) -> *ast::Node
2354 +
    throws (ParseError)
2355 +
{
2356 +
    try expect(p, scanner::TokenKind::Instance, "expected `instance`");
2357 +
    let traitName = try parseTypePath(p);
2358 +
    try expect(p, scanner::TokenKind::For, "expected `for` after trait name");
2359 +
    let targetType = try parseTypePath(p);
2360 +
    try expect(p, scanner::TokenKind::LBrace, "expected `{` after target type");
2361 +
2362 +
    let mut methods = ast::nodeList(p.arena, MAX_TRAIT_METHODS);
2363 +
    while not check(p, scanner::TokenKind::RBrace) and
2364 +
          not check(p, scanner::TokenKind::Eof)
2365 +
    {
2366 +
        let method = try parseInstanceMethodDecl(p);
2367 +
        ast::nodeListPush(&mut methods, method);
2368 +
    }
2369 +
    try expect(p, scanner::TokenKind::RBrace, "expected `}` after instance methods");
2370 +
2371 +
    return node(p, ast::NodeValue::InstanceDecl { traitName, targetType, methods });
2372 +
}
2373 +
2374 +
/// Parse an instance method declaration.
2375 +
/// Syntax: `fn (t: *mut Type) fnord(<params>) -> ReturnType { body }`
2376 +
fn parseInstanceMethodDecl(p: *mut Parser) -> *ast::Node
2377 +
    throws (ParseError)
2378 +
{
2379 +
    try expect(p, scanner::TokenKind::Fn, "expected `fn`");
2380 +
    try expect(p, scanner::TokenKind::LParen, "expected `(` before receiver");
2381 +
2382 +
    let receiverName = try parseIdent(p, "expected receiver name");
2383 +
    try expect(p, scanner::TokenKind::Colon, "expected `:` after receiver name");
2384 +
    let receiverType = try parseType(p);
2385 +
2386 +
    try expect(p, scanner::TokenKind::RParen, "expected `)` after receiver type");
2387 +
2388 +
    let name = try parseIdent(p, "expected method name");
2389 +
    let sig = try parseFnTypeSig(p);
2390 +
    let body = try parseBlock(p);
2391 +
2392 +
    return node(p, ast::NodeValue::InstanceMethodDecl {
2393 +
        name, receiverName, receiverType, sig, body,
2394 +
    });
2395 +
}
2396 +
2275 2397
/// Parse a comma-separated list enclosed by the given delimiters.
2276 2398
fn parseList(
2277 2399
    p: *mut Parser,
2278 2400
    open: scanner::TokenKind,
2279 2401
    close: scanner::TokenKind,
lib/std/lang/resolver.rad +4 -0
5398 5398
            } else {
5399 5399
                fnType.returnType = allocType(self, Type::Void);
5400 5400
            }
5401 5401
            return Type::Fn(allocFnType(self, fnType));
5402 5402
        }
5403 +
        case ast::TypeSig::TraitObject { .. } => {
5404 +
            // TODO.
5405 +
            throw emitError(self, node, ErrorKind::Internal);
5406 +
        }
5403 5407
    }
5404 5408
}
5405 5409
5406 5410
/// Check if a type can be used for inferrence.
5407 5411
fn isTypeInferrable(type: Type) -> bool {
lib/std/lang/scanner.rad +8 -1
100 100
    Mod, Use, Super,
101 101
102 102
    // Type or function attributes.
103 103
    Pub, Extern, Static,
104 104
105 +
    // Trait-related tokens.
106 +
    Trait, Instance,
107 +
105 108
    // Type-related tokens.
106 109
    I8, I16, I32, I64, U8, U16, U32, U64,
107 110
    Void, Opaque, Fn, Bool, Union, Record, As
108 111
}
109 112
196 199
        case TokenKind::Use => return "Use",
197 200
        case TokenKind::Super => return "Super",
198 201
        case TokenKind::Pub => return "Pub",
199 202
        case TokenKind::Extern => return "Extern",
200 203
        case TokenKind::Static => return "Static",
204 +
        case TokenKind::Trait => return "Trait",
205 +
        case TokenKind::Instance => return "Instance",
201 206
        case TokenKind::I8 => return "I8",
202 207
        case TokenKind::I16 => return "I16",
203 208
        case TokenKind::I32 => return "I32",
204 209
        case TokenKind::I64 => return "I64",
205 210
        case TokenKind::U8 => return "U8",
223 228
    /// Corresponding token.
224 229
    tok: TokenKind,
225 230
}
226 231
227 232
/// Sorted keyword table for binary search.
228 -
const KEYWORDS: [Keyword; 50] = [
233 +
const KEYWORDS: [Keyword; 52] = [
229 234
    { name: "align", tok: TokenKind::Align },
230 235
    { name: "and", tok: TokenKind::And },
231 236
    { name: "as", tok: TokenKind::As },
232 237
    { name: "assert", tok: TokenKind::Assert },
233 238
    { name: "bool", tok: TokenKind::Bool },
245 250
    { name: "i32", tok: TokenKind::I32 },
246 251
    { name: "i64", tok: TokenKind::I64 },
247 252
    { name: "i8", tok: TokenKind::I8 },
248 253
    { name: "if", tok: TokenKind::If },
249 254
    { name: "in", tok: TokenKind::In },
255 +
    { name: "instance", tok: TokenKind::Instance },
250 256
    { name: "let", tok: TokenKind::Let },
251 257
    { name: "log", tok: TokenKind::Log },
252 258
    { name: "loop", tok: TokenKind::Loop },
253 259
    { name: "match", tok: TokenKind::Match },
254 260
    { name: "mod", tok: TokenKind::Mod },
263 269
    { name: "return", tok: TokenKind::Return },
264 270
    { name: "static", tok: TokenKind::Static },
265 271
    { name: "super", tok: TokenKind::Super },
266 272
    { name: "throw", tok: TokenKind::Throw },
267 273
    { name: "throws", tok: TokenKind::Throws },
274 +
    { name: "trait", tok: TokenKind::Trait },
268 275
    { name: "true", tok: TokenKind::True },
269 276
    { name: "try", tok: TokenKind::Try },
270 277
    { name: "u16", tok: TokenKind::U16 },
271 278
    { name: "u32", tok: TokenKind::U32 },
272 279
    { name: "u64", tok: TokenKind::U64 },