program typecheck_bench

// Benchmark: lex โ†’ parse โ†’ typecheck a small Trident program.
// Reads source bytes from public input, lexes, parses, typechecks,
// asserts token/node/error counts match expected values.
use vm.io.io

use vm.io.mem

use vm.core.convert

use std.compiler.lexer

use std.compiler.parser

use std.compiler.typecheck

fn main() {
    // Read layout parameters from public input
    let src_base: Field = io.read()
    let src_len: Field = io.read()
    let tok_base: Field = io.read()
    let lex_err_base: Field = io.read()
    let lex_state_base: Field = io.read()
    let ast_base: Field = io.read()
    let parse_err_base: Field = io.read()
    let parse_state_base: Field = io.read()
    let parse_stack_base: Field = io.read()
    let tc_state_base: Field = io.read()
    let expected_tok_count: Field = io.read()
    let expected_err_count: Field = io.read()

    // Load source bytes from public input into RAM
    let src_len_u32: U32 = convert.as_u32(src_len)
    for i in 0..src_len_u32 bounded 2048 {
        let idx: Field = convert.as_field(i)
        let byte: Field = io.read()
        mem.write(src_base + idx, byte)
    }

    // Stage 1: Lex
    lexer.lex(src_base, src_len, tok_base, lex_err_base, lex_state_base)
    let tok_count: Field = mem.read(lex_state_base + 1)
    let lex_err_count: Field = mem.read(lex_state_base + 2)
    assert(tok_count == expected_tok_count)
    assert(lex_err_count == 0)

    // Stage 2: Parse
    parser.parse(tok_base, tok_count, ast_base, parse_err_base, parse_state_base, parse_stack_base)
    let node_count: Field = mem.read(parse_state_base + 2)
    let parse_err_count: Field = mem.read(parse_state_base + 3)
    assert(parse_err_count == 0)

    // Stage 3: Typecheck
    // Initialize typecheck state
    mem.write(tc_state_base, ast_base)
    mem.write(tc_state_base + 1, node_count)
    // Type pool
    mem.write(tc_state_base + 2, tc_state_base + 32)
    mem.write(tc_state_base + 3, 0)
    // Function table
    mem.write(tc_state_base + 4, tc_state_base + 2032)
    mem.write(tc_state_base + 5, 0)
    // Variable scope
    mem.write(tc_state_base + 6, tc_state_base + 4032)
    mem.write(tc_state_base + 7, 0)
    // Struct table
    mem.write(tc_state_base + 8, tc_state_base + 6032)
    mem.write(tc_state_base + 9, 0)
    // Struct fields
    mem.write(tc_state_base + 10, tc_state_base + 7032)
    mem.write(tc_state_base + 11, 0)
    // Constant table
    mem.write(tc_state_base + 12, tc_state_base + 8032)
    mem.write(tc_state_base + 13, 0)
    // Event table
    mem.write(tc_state_base + 14, tc_state_base + 8532)
    mem.write(tc_state_base + 15, 0)
    // Event fields
    mem.write(tc_state_base + 16, tc_state_base + 9032)
    mem.write(tc_state_base + 17, 0)
    // Error output
    mem.write(tc_state_base + 18, tc_state_base + 9532)
    mem.write(tc_state_base + 19, 0)
    // Work stack
    mem.write(tc_state_base + 20, tc_state_base + 10032)
    mem.write(tc_state_base + 21, 0)
    // Scope depth
    mem.write(tc_state_base + 22, 0)
    // Digest width, hash rate, field limbs, xfield width
    mem.write(tc_state_base + 23, 5)
    mem.write(tc_state_base + 24, 10)
    mem.write(tc_state_base + 25, 2)
    mem.write(tc_state_base + 26, 3)
    // In pure fn
    mem.write(tc_state_base + 27, 0)
    // Result stack
    mem.write(tc_state_base + 28, tc_state_base + 14032)
    mem.write(tc_state_base + 29, 0)

    typecheck.check(tc_state_base)
    let tc_err_count: Field = typecheck.error_count(tc_state_base)
    assert(tc_err_count == expected_err_count)

    // Output counts as proof of work
    io.write(tok_count)
    io.write(node_count)
    io.write(tc_err_count)
}

Dimensions

trident/std/compiler/typecheck.tri

Local Graph