Class SemanticAnalyzer
The contract is Script → SemanticResult: the
engine analyses an AST, and text is not part of that contract. How a
Script is produced — the .relix grammar, a serialized query,
a programmatic builder — is a frontend concern, and every frontend enters
here.
Usage — AST-first (the primary entry point)
SemanticAnalyzer analyzer = new SemanticAnalyzer(loader); SemanticResult result = analyzer.analyze(script);The root is attributed to the synthetic path
AST_PATH
("<ast>"); pass a real one with analyze(Script, String) when
the caller knows where the AST came from.
Usage — loader-based
SemanticAnalyzer analyzer = new SemanticAnalyzer(loader);
SemanticResult result = analyzer.analyze("./weather.relix");
The root is fetched through the configured ScriptLoader, which is also
what resolves every import the script reaches — so how a path
becomes a Script stays a frontend decision. Reading .relix
text is one such frontend and lives outside the engine: see
Relix.parse in relix-embed, and FileSystemScriptLoader in
relix-console.
Built-in symbols
Pass aBuiltinProvider to register functions or relations that should
be available in every script without an explicit import:
SemanticAnalyzer analyzer = new SemanticAnalyzer(loader, myBuiltins);Use
BuiltinProvider.none() (the default) when no built-ins are needed.
Functions
The scalar functions a script may call come from the installed function libraries, discovered once per analyser and carried on to every later phase throughSemanticModel.functions(). A library function enters the symbol
table when a script first mentions it, so an analysed script's symbols are the
functions it calls rather than the whole library. Supply a
FunctionCatalog explicitly to control
what is callable.
Analysis phases
- Obtain the root script (supplied directly as a
Script, or loaded from a path via theScriptLoader). - Load all transitively imported files via the
ScriptLoader; detect and report import cycles. - Register built-in symbols via the
BuiltinProvider. - Collect all declarations (sources, assignments, defs) as typed symbols in the symbol table, processing files in topological import order.
- Resolve import statements — pull exported symbols from imported files into the importing file's scope.
- Infer schemas for relational-algebra expression bodies using a
SchemaInferenceVisitor; annotate the per-node schema map. - Assemble and validate the schema graph from
relatestatements andreferences:blocks, merging any supplemental session-learned edges (seewithSupplementalRelationships(com.darkcollective.relix.symbol.graph.SchemaGraph)). - Validate all names, arities, schema compatibility, and source-config completeness; accumulate all errors.
Instances are stateless after construction and may be reused across
multiple analyze calls.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringSynthetic path the root script is attributed to when it was supplied as an already-builtScriptwith no path of its own — seeanalyze(Script).static final StringSynthetic file path used inSemanticError.filePath()when the root script came from a stream — piped stdin, or any other unnamed source — rather than a named file. -
Constructor Summary
ConstructorsConstructorDescriptionSemanticAnalyzer(ScriptLoader loader) Creates an analyser with no built-in symbols and no catalog.SemanticAnalyzer(ScriptLoader loader, CatalogProvider catalog) Creates an analyser with no built-in symbols and the given catalog provider.SemanticAnalyzer(ScriptLoader loader, CatalogProvider catalog, GeneratorCatalog generators) Creates an analyser with no built-in symbols, the given catalog provider, and the given generator catalog.SemanticAnalyzer(ScriptLoader loader, BuiltinProvider builtins) Creates an analyser with a custom built-in provider and no catalog (connection tables must declare their schema).SemanticAnalyzer(ScriptLoader loader, BuiltinProvider builtins, CatalogProvider catalog) Creates an analyser with a custom built-in provider and catalog provider, and no generator catalog.SemanticAnalyzer(ScriptLoader loader, BuiltinProvider builtins, CatalogProvider catalog, GeneratorCatalog generators) Creates an analyser with a custom built-in provider, catalog provider, and generator catalog.SemanticAnalyzer(ScriptLoader loader, BuiltinProvider builtins, CatalogProvider catalog, GeneratorCatalog generators, FunctionCatalog functions) Creates an analyser that resolves function calls againstfunctionsrather than against the installed libraries. -
Method Summary
Modifier and TypeMethodDescriptionAnalyses an already-builtScript— the engine's primary entry point.Analyses an already-builtScriptthat came fromrootPath.Analyses the script atrootPathand returns a result containing the semantic model (if analysis produced one) and all diagnostics collected.withComponents(ComponentInventory components) Returns an analyser whoserelix.versionadditionally reports the components the host can see.withSessionEvents(List<QueryEvent> events) withSupplementalRelationships(SchemaGraph supplemental) Returns an analyser that merges the given supplemental relationships into the schema graph on every analysis.
-
Field Details
-
STDIN_PATH
Synthetic file path used inSemanticError.filePath()when the root script came from a stream — piped stdin, or any other unnamed source — rather than a named file.Like
AST_PATHit is not a file name, and is never passed to the file system. A caller analysing text it read from standard input uses it as the root path.- See Also:
-
AST_PATH
Synthetic path the root script is attributed to when it was supplied as an already-builtScriptwith no path of its own — seeanalyze(Script).Like
STDIN_PATHit is not a file name, and is never passed to the file system.- See Also:
-
-
Constructor Details
-
SemanticAnalyzer
Creates an analyser with a custom built-in provider and catalog provider, and no generator catalog.- Parameters:
loader- the script loader used to resolve imports; must not be nullbuiltins- the hook for registering built-in symbols; must not be nullcatalog- supplies schemas for connection-backed tables; must not be null
-
SemanticAnalyzer
public SemanticAnalyzer(ScriptLoader loader, BuiltinProvider builtins, CatalogProvider catalog, GeneratorCatalog generators) Creates an analyser with a custom built-in provider, catalog provider, and generator catalog.- Parameters:
loader- the script loader used to resolve imports; must not be nullbuiltins- the hook for registering built-in symbols; must not be nullcatalog- supplies schemas for connection-backed tables; must not be nullgenerators- supplies schemas for generator sources; must not be null
-
SemanticAnalyzer
public SemanticAnalyzer(ScriptLoader loader, BuiltinProvider builtins, CatalogProvider catalog, GeneratorCatalog generators, FunctionCatalog functions) Creates an analyser that resolves function calls againstfunctionsrather than against the installed libraries.Every other constructor discovers the installed libraries — one catalogue, built once and passed on through the
SemanticModel— which is what an embedder wants unless it is deliberately controlling which functions a script may call. PassingFunctionCatalog.empty()makes every function call unknown.- Parameters:
loader- the script loader used to resolve imports; must not be nullbuiltins- the hook for registering built-in symbols; must not be nullcatalog- supplies schemas for connection-backed tables; must not be nullgenerators- supplies schemas for generator sources; must not be nullfunctions- the functions scripts may call; must not be null
-
SemanticAnalyzer
Creates an analyser with a custom built-in provider and no catalog (connection tables must declare their schema).- Parameters:
loader- the script loader used to resolve imports; must not be nullbuiltins- the hook for registering built-in symbols; must not be null
-
SemanticAnalyzer
Creates an analyser with no built-in symbols and the given catalog provider.- Parameters:
loader- the script loader used to resolve imports; must not be nullcatalog- supplies schemas for connection-backed tables; must not be null
-
SemanticAnalyzer
Creates an analyser with no built-in symbols, the given catalog provider, and the given generator catalog.- Parameters:
loader- the script loader used to resolve imports; must not be nullcatalog- supplies schemas for connection-backed tables; must not be nullgenerators- supplies schemas for generator sources; must not be null
-
SemanticAnalyzer
Creates an analyser with no built-in symbols and no catalog.- Parameters:
loader- the script loader used to resolve imports; must not be null
-
-
Method Details
-
withSupplementalRelationships
Returns an analyser that merges the given supplemental relationships into the schema graph on every analysis.This is the seam for edges acquired outside the source text — conversational acquisition ("how do orders relate to customers?") and relationships captured from the joins a user actually wrote. A session host (the REPL) keeps its learned edges and re-supplies them on each accumulate-and-reanalyze pass. Supplemental edges are re-validated against the current symbol table each time; a stale edge (its relation or column no longer exists) is dropped with a warning, never a hard error — unlike a declared edge in the file, it is not a claim the current source makes.
- Parameters:
supplemental- the session-learned edges; must not be null- Returns:
- a new analyser instance; this one is unchanged
-
withComponents
Returns an analyser whoserelix.versionadditionally reports the components the host can see.The engine reports itself and the function libraries it holds; connectors, solvers and JDBC drivers live above it — a driver behind a
java.sqldependency no engine module may have — so whoever assembled the process supplies them here.- Parameters:
components- the host's inventory; must not be null- Returns:
- a new analyser instance; this one is unchanged
-
withSessionEvents
-
analyze
Analyses an already-builtScript— the engine's primary entry point.The script is analysed as the root of the import graph; any
importstatements it contains are still resolved through the configuredScriptLoader. The root carries no path of its own, so its relative import paths are normalised as-is ("./lib.relix"→"lib.relix") and it is attributed toAST_PATHin the diagnostics the analyser raises about the root file. Diagnostics about the tree's contents carry whateverSourceLocationthe AST itself holds. Useanalyze(Script, String)to supply a real path.- Parameters:
script- the root script; must not be null- Returns:
- the analysis result; never null
- Throws:
NullPointerException- ifscriptis null
-
analyze
Analyses an already-builtScriptthat came fromrootPath.Identical to
analyze(Script)except thatrootPathis the root node's key in the import graph — so it is the base the root's relativeimportpaths resolve against, and the file path the analyser names the root by. A frontend that read the script from a file (or from stdin, usingSTDIN_PATH) should use this overload.- Parameters:
script- the root script; must not be nullrootPath- the path to attribute the script to; must not be null- Returns:
- the analysis result; never null
- Throws:
NullPointerException- if either argument is null
-
analyze
Analyses the script atrootPathand returns a result containing the semantic model (if analysis produced one) and all diagnostics collected.- Parameters:
rootPath- the path of the root.relixfile, interpreted by the configuredScriptLoader- Returns:
- the analysis result; never null
- Throws:
NullPointerException- ifrootPathis null
-