Module resolver

Module resolver 

Source
Expand description

§MON Semantic Analyzer (Resolver)

This module is responsible for the semantic analysis phase of the MON compilation pipeline. The Resolver traverses the Abstract Syntax Tree (AST) generated by the Parser and enriches it with semantic meaning.

§Architectural Overview

The resolver is a stateful visitor that walks the AST and performs several key actions:

  • Import Resolution: It finds, parses, and resolves import statements. It maintains a cache of already resolved documents to avoid redundant work and uses a resolving stack to detect circular dependencies between files. It also handles the mon: URI scheme for built-in schemas.

  • Symbol & Anchor Collection: It populates a global symbol table with type definitions (#struct, #enum) and a global map with all declared anchors (&my_anchor).

  • Alias and Spread Resolution: It replaces all aliases (*my_anchor) and spreads (...*my_anchor) with deep clones of their original values. This is where composition happens.

  • Validation: It performs type checking for any pair that has a validation specifier (:: MyType). It ensures that structs have the correct fields, enums have valid variants, and that all types match their definitions.

After the resolver has finished, the AST is considered fully resolved and validated.

§Use Cases

While you can use the resolver directly for fine-grained control, most users will interact with it via the top-level analyze function. Direct use is beneficial when:

  • You need to inspect the symbol table or anchors after resolution.
  • You want to provide a custom path for built-in schemas.
  • You are building a tool that needs to hook into a specific part of the analysis lifecycle.

§Example: Direct Resolver Usage

use mon_core::parser::Parser;
use mon_core::resolver::Resolver;
use mon_core::error::MonError;
use std::path::PathBuf;

let source = r#"
{
    MyStruct: #struct { name(String) },
    &my_data: { name: "Hello" },

    // This instance will be validated against MyStruct.
    instance :: MyStruct = *my_data
}
"#;
let file_path = PathBuf::from("my_file.mon");

// 1. The resolver needs a parsed document from the parser.
let mut parser = Parser::new_with_name(source, file_path.to_string_lossy().to_string())?;
let document = parser.parse_document()?;

// 2. Create and run the resolver.
let mut resolver = Resolver::new();
let resolved_document = resolver.resolve(document.clone(), source, file_path, None)?;

// 3. Inspect the results.
assert!(resolver.symbol_table.types.contains_key("MyStruct"));
assert!(resolver.anchors.contains_key("my_data"));

Structs§

Resolver
Traverses a MonDocument to resolve imports, aliases, and spreads, and to validate data against schemas.