lib/std/lang/module/printer.rad 2.6 KiB raw
1
//! Module graph pretty printer using S-expression syntax.
2
3
use std::fmt;
4
use std::mem;
5
use std::io;
6
use std::lang::sexpr;
7
use std::lang::alloc;
8
9
/// Format a u32 and allocate the result in the arena.
10
fn formatId(a: *mut alloc::Arena, id: u32) -> *[u8] {
11
    let mut digits: [u8; 10] = undefined;
12
    let text = fmt::formatU32(id, &mut digits[..]);
13
    let ptr = try alloc::allocSlice(a, 1, 1, text.len) catch { return "?"; };
14
    let slice = ptr as *mut [u8];
15
    try mem::copy(slice, text) catch { return "?"; };
16
    return slice;
17
}
18
19
/// Convert a module state into an S-expression symbol.
20
fn stateToExpr(state: super::ModuleState) -> sexpr::Expr {
21
    match state {
22
        case super::ModuleState::Vacant => return sexpr::sym("vacant"),
23
        case super::ModuleState::Registered => return sexpr::sym("registered"),
24
        case super::ModuleState::Parsing => return sexpr::sym("parsing"),
25
        case super::ModuleState::Parsed => return sexpr::sym("parsed"),
26
        case super::ModuleState::Analyzing => return sexpr::sym("analyzing"),
27
        case super::ModuleState::Ready => return sexpr::sym("ready"),
28
    }
29
}
30
31
/// Recursively convert a module entry and its descendants to an S-expression.
32
fn subtreeToExpr(
33
    a: *mut alloc::Arena,
34
    graph: *super::ModuleGraph,
35
    entry: *super::ModuleEntry
36
) -> sexpr::Expr {
37
    let idText = formatId(a, entry.id as u32);
38
    let path = super::moduleQualifiedPath(entry);
39
    let mut pathBuf: *[sexpr::Expr] = &[];
40
    if path.len > 0 {
41
        let buf = try! sexpr::allocExprs(a, path.len);
42
        for seg, i in path { buf[i] = sexpr::sym(seg); }
43
        pathBuf = buf;
44
    }
45
46
    let mut childBuf: *[sexpr::Expr] = &[];
47
    if entry.childrenLen > 0 {
48
        let buf = try! sexpr::allocExprs(a, entry.childrenLen);
49
        for i in 0..entry.childrenLen {
50
            if let child = super::get(graph, entry.children[i]) {
51
                buf[i] = subtreeToExpr(a, graph, child);
52
            }
53
        }
54
        childBuf = buf;
55
    }
56
57
    return sexpr::block(a, "module", &[
58
        sexpr::sym(entry.name),
59
        sexpr::list(a, "id", &[sexpr::sym(idText)]),
60
        sexpr::list(a, "state", &[stateToExpr(entry.state)]),
61
        sexpr::Expr::Str(entry.filePath),
62
        sexpr::Expr::List { head: "::", tail: pathBuf, multiline: false }
63
    ], childBuf);
64
}
65
66
/// Print the entire module graph in S-expression format.
67
pub fn printGraph(graph: *super::ModuleGraph, arena: *mut alloc::Arena) {
68
    // Print all root modules.
69
    for i in 0..graph.entriesLen {
70
        let entry = &graph.entries[i];
71
        if entry.parent == nil {
72
            sexpr::print(subtreeToExpr(arena, graph, entry), 0);
73
            io::print("\n");
74
        }
75
    }
76
}