Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 13 additions & 122 deletions libs/@local/graph/api/src/rest/entity_query_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
//!
//! When changing any of these types, make sure that the OpenAPI generator types do not degenerate
//! into any of these cases.
#![expect(
dead_code,
reason = "https://linear.app/hash/issue/BE-537/hashql-remove-old-backend-wire-up-hashql-in-the-api"
)]
Comment thread
indietyp marked this conversation as resolved.
use alloc::borrow::Cow;
use core::{cmp, ops::Range};

Expand Down Expand Up @@ -41,23 +45,17 @@ use hash_graph_store::{
};
use hashql_ast::error::AstDiagnosticCategory;
use hashql_core::{
collections::fast_hash_map_with_capacity,
heap::Heap,
module::ModuleRegistry,
span::{SpanId, SpanTable},
r#type::environment::Environment,
};
use hashql_diagnostics::{
DiagnosticIssues, Failure, Severity, Status, StatusExt as _, Success,
DiagnosticIssues, Failure, Severity,
category::{DiagnosticCategory, canonical_category_id},
diagnostic::render::{Format, RenderOptions},
source::{DiagnosticSpan, Source, SourceId, Sources},
};
use hashql_eval::{
error::EvalDiagnosticCategory,
graph::{error::GraphCompilerDiagnosticCategory, read::FilterSlice},
source::{DiagnosticSpan, Source, Sources},
};
use hashql_hir::{error::HirDiagnosticCategory, visit::Visitor as _};
use hashql_eval::error::EvalDiagnosticCategory;
use hashql_hir::error::HirDiagnosticCategory;
use hashql_syntax_jexpr::{error::JExprDiagnosticCategory, span::Span};
use http::StatusCode;
use serde::Deserialize;
Expand Down Expand Up @@ -329,92 +327,6 @@ pub enum EntityQuery<'q> {
}

impl<'q> EntityQuery<'q> {
fn compile_query<'heap>(
heap: &'heap Heap,
spans: &mut SpanTable<Span>,
query: &RawJsonValue,
) -> Status<Filter<'heap, Entity>, HashQLDiagnosticCategory, SpanId> {
// Parse the query
let mut parser = hashql_syntax_jexpr::Parser::new(heap, spans);
let mut ast = parser
.parse_expr(query.get().as_bytes())
.map_err(|diagnostic| {
Failure::new(diagnostic.map_category(HashQLDiagnosticCategory::JExpr))
})?;

let mut env = Environment::new(heap);
let modules = ModuleRegistry::new(&env);

// Lower the AST
let Success {
value: types,
advisories,
} = hashql_ast::lowering::lower(heap.intern_symbol("main"), &mut ast, &env, &modules)
.map_category(|category| {
HashQLDiagnosticCategory::Ast(AstDiagnosticCategory::Lowering(category))
})?;

let interner = hashql_hir::intern::Interner::new(heap);
let mut context = hashql_hir::context::HirContext::new(&interner, &modules);

// Reify the HIR from the AST
let Success {
value: hir,
advisories,
} = hashql_hir::node::NodeData::from_ast(ast, &mut context, &types)
.map_category(|category| {
HashQLDiagnosticCategory::Hir(HirDiagnosticCategory::Reification(category))
})
.with_diagnostics(advisories)?;

// Lower the HIR
let Success {
value: hir,
advisories,
} = hashql_hir::lower::lower(hir, &types, &mut env, &mut context)
.map_category(|category| {
HashQLDiagnosticCategory::Hir(HirDiagnosticCategory::Lowering(category))
})
.with_diagnostics(advisories)?;

// Evaluate the HIR
// TODO: https://linear.app/hash/issue/BE-41/hashql-expose-input-in-graph-api
let inputs = fast_hash_map_with_capacity(0);
let mut compiler = hashql_eval::graph::read::GraphReadCompiler::new(heap, &inputs);

compiler.visit_node(hir);

let Success {
value: result,
advisories,
} = compiler
.finish()
.map_category(|category| {
HashQLDiagnosticCategory::Eval(EvalDiagnosticCategory::Graph(
GraphCompilerDiagnosticCategory::Read(category),
))
})
.with_diagnostics(advisories)?;

let output = result.output.get(&hir.id).expect("TODO");

// Compile the Filter into one
let filters = match output {
FilterSlice::Entity { range } => result.filters.entity(range.clone()),
};

let filter = match filters {
[] => Filter::All(Vec::new()),
[filter] => filter.clone(),
_ => Filter::All(filters.to_vec()),
};

Ok(Success {
value: filter,
advisories,
})
}

/// Compiles a query into an executable entity filter.
///
/// Transforms the query representation into a [`Filter`] that can be executed
Expand All @@ -427,35 +339,14 @@ impl<'q> EntityQuery<'q> {
/// Returns an error if the HashQL query cannot be compiled.
pub(crate) fn compile(
self,
heap: &'q Heap,
options: CompilationOptions,
_: &'q Heap,
_: CompilationOptions,
) -> Result<Filter<'q, Entity>, BoxedResponse> {
match self {
EntityQuery::Filter { filter } => Ok(filter),
EntityQuery::Query { query } => {
let mut spans = SpanTable::new(SourceId::new_unchecked(0x00));

let Success {
value: filter,
advisories,
} = Self::compile_query(heap, &mut spans, query).map_err(|failure| {
failure_to_response(failure, query.get(), &spans, options)
})?;
if !advisories.is_empty() {
// This isn't perfect, what we'd want instead is to return it alongside the
// response, the problem with that approach is just how: we'd need to adjust the
// return type, and respect interactive. Returning warnings before so that user
// can fix them before trying again seems to be the best approach for now.
return Err(issues_to_response(
advisories.generalize(),
Severity::Warning,
query.get(),
&spans,
options,
));
}

Ok(filter)
EntityQuery::Query { query: _ } => {
let response = (StatusCode::NOT_IMPLEMENTED, "https://linear.app/hash/issue/BE-537/hashql-remove-old-backend-wire-up-hashql-in-the-api").into_response();
Err(response.into())
Comment thread
indietyp marked this conversation as resolved.
}
Comment thread
indietyp marked this conversation as resolved.
}
}
Expand Down
5 changes: 3 additions & 2 deletions libs/@local/hashql/compiletest/src/suite/eval_postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use hashql_core::{
r#type::{TypeFormatter, TypeFormatterOptions, environment::Environment},
};
use hashql_diagnostics::DiagnosticIssues;
use hashql_eval::{context::EvalContext, postgres::PostgresCompiler};
use hashql_eval::{context::CodeGenerationContext, postgres::PostgresCompiler};
use hashql_mir::{
body::{Body, basic_block::BasicBlockId, terminator::TerminatorKind},
context::MirContext,
Expand Down Expand Up @@ -117,7 +117,8 @@ impl Suite for EvalPostgres {
let mir_buf = format_mir_with_placement(heap, &environment, &bodies, &analysis);
secondary_outputs.insert("mir", mir_buf);

let mut context = EvalContext::new_in(
let interner = interner.into();
let mut context = CodeGenerationContext::new_in(
&environment,
&interner,
&bodies,
Expand Down
10 changes: 5 additions & 5 deletions libs/@local/hashql/core/src/graph/linked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,13 @@ impl<E> HasId for Edge<E> {

impl<E> Edge<E> {
/// Returns the source node of this edge.
#[inline]
pub const fn source(&self) -> NodeId {
self.source
}

/// Returns the target node of this edge.
#[inline]
pub const fn target(&self) -> NodeId {
self.target
}
Expand Down Expand Up @@ -542,11 +544,9 @@ impl<N, E> Default for LinkedGraph<N, E> {
}
}

impl<N: core::fmt::Debug, E: core::fmt::Debug, A: Allocator> core::fmt::Debug
for LinkedGraph<N, E, A>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LinkedGraph")
impl<N: fmt::Debug, E: fmt::Debug, A: Allocator> fmt::Debug for LinkedGraph<N, E, A> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("LinkedGraph")
.field("nodes", &self.nodes)
.field("edges", &self.edges)
.finish()
Expand Down
46 changes: 41 additions & 5 deletions libs/@local/hashql/eval/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::{alloc::Allocator, ops::Index};
use core::{alloc::Allocator, fmt, ops::Index};

use hashql_core::{
heap::BumpAllocator, id::bit_vec::DenseBitSet, r#type::environment::Environment,
Expand All @@ -11,7 +11,6 @@ use hashql_mir::{
local::Local,
},
def::{DefId, DefIdSlice, DefIdVec},
intern::Interner,
pass::{
analysis::dataflow::{
TraversalLivenessAnalysis,
Expand All @@ -21,7 +20,7 @@ use hashql_mir::{
},
};

use crate::error::EvalDiagnosticIssues;
use crate::{error::EvalDiagnosticIssues, intern::Interner};

struct BasicBlockLiveOut<A: Allocator>(
Box<BasicBlockSlice<(DenseBitSet<Local>, TraversalPathBitSet)>, A>,
Expand Down Expand Up @@ -49,7 +48,7 @@ impl<A: Allocator> Index<(DefId, BasicBlockId)> for LiveOut<A> {
}
}

pub struct EvalContext<'ctx, 'heap, A: Allocator> {
pub struct CodeGenerationContext<'ctx, 'heap, A: Allocator> {
pub env: &'ctx Environment<'heap>,
pub interner: &'ctx Interner<'heap>,

Expand All @@ -58,10 +57,11 @@ pub struct EvalContext<'ctx, 'heap, A: Allocator> {

pub live_out: LiveOut<A>,
pub diagnostics: EvalDiagnosticIssues,

pub alloc: A,
}

impl<'ctx, 'heap, A: Allocator> EvalContext<'ctx, 'heap, A> {
impl<'ctx, 'heap, A: Allocator> CodeGenerationContext<'ctx, 'heap, A> {
pub fn new_in<S: BumpAllocator>(
env: &'ctx Environment<'heap>,
interner: &'ctx Interner<'heap>,
Expand Down Expand Up @@ -121,3 +121,39 @@ impl<'ctx, 'heap, A: Allocator> EvalContext<'ctx, 'heap, A> {
}
}
}

#[derive(Copy, Clone)]
pub struct CodeExecutionContext<'ctx, 'heap, A: Allocator> {
pub env: &'ctx Environment<'heap>,
pub interner: &'ctx Interner<'heap>,

pub bodies: &'ctx DefIdSlice<Body<'heap>>,
pub execution: &'ctx DefIdSlice<Option<ExecutionAnalysisResidual<A>>>,

pub alloc: A,
}

impl<A: Allocator> fmt::Debug for CodeExecutionContext<'_, '_, A> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("CodeExecutionContext")
.field("env", &self.env)
.field("interner", &self.interner)
.field("bodies", &self.bodies)
.field("execution", &self.execution)
.finish_non_exhaustive()
}
}

impl<'ctx, 'heap, A: Allocator> From<CodeGenerationContext<'ctx, 'heap, A>>
for CodeExecutionContext<'ctx, 'heap, A>
{
fn from(context: CodeGenerationContext<'ctx, 'heap, A>) -> Self {
Self {
env: context.env,
interner: context.interner,
bodies: context.bodies,
execution: context.execution,
alloc: context.alloc,
}
}
}
12 changes: 5 additions & 7 deletions libs/@local/hashql/eval/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ use alloc::borrow::Cow;
use hashql_core::span::SpanId;
use hashql_diagnostics::{Diagnostic, DiagnosticIssues, Severity, category::DiagnosticCategory};

#[cfg(feature = "graph")]
use crate::graph::error::GraphCompilerDiagnosticCategory;
use crate::postgres::error::PostgresDiagnosticCategory;
use crate::{
orchestrator::OrchestratorDiagnosticCategory, postgres::error::PostgresDiagnosticCategory,
};

pub type EvalDiagnostic<K = Severity> = Diagnostic<EvalDiagnosticCategory, SpanId, K>;
pub type EvalDiagnosticIssues<K = Severity> = DiagnosticIssues<EvalDiagnosticCategory, SpanId, K>;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum EvalDiagnosticCategory {
#[cfg(feature = "graph")]
Graph(GraphCompilerDiagnosticCategory),
Postgres(PostgresDiagnosticCategory),
Orchestrator(OrchestratorDiagnosticCategory),
}

impl DiagnosticCategory for EvalDiagnosticCategory {
Expand All @@ -28,9 +27,8 @@ impl DiagnosticCategory for EvalDiagnosticCategory {

fn subcategory(&self) -> Option<&dyn DiagnosticCategory> {
match self {
#[cfg(feature = "graph")]
Self::Graph(graph) => Some(graph),
Self::Postgres(postgres) => Some(postgres),
Self::Orchestrator(orchestrator) => Some(orchestrator),
}
}
}
28 changes: 28 additions & 0 deletions libs/@local/hashql/eval/src/intern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use hashql_core::{intern::InternSet, symbol::Symbol};

/// Interner for the evaluation stage.
///
/// Must be created from the MIR interner via [`From`] to preserve
/// [`Interned`](hashql_core::intern::Interned) pointer identity across
/// the MIR/eval boundary.
#[derive(Debug)]
pub struct Interner<'heap> {
pub symbols: InternSet<'heap, [Symbol<'heap>]>,
}

#[cfg(test)]
impl<'heap> Interner<'heap> {
pub(crate) fn testing(heap: &'heap hashql_core::heap::Heap) -> Self {
Self {
symbols: InternSet::new(heap),
}
}
}

impl<'heap> From<hashql_mir::intern::Interner<'heap>> for Interner<'heap> {
fn from(interner: hashql_mir::intern::Interner<'heap>) -> Self {
Self {
symbols: interner.symbols,
}
}
}
1 change: 1 addition & 0 deletions libs/@local/hashql/eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub mod context;
pub mod error;
#[cfg(feature = "graph")]
pub mod graph;
pub mod intern;
pub mod orchestrator;
pub mod postgres;

Expand Down
4 changes: 2 additions & 2 deletions libs/@local/hashql/eval/src/orchestrator/codec/decode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ mod tests;
/// [`Unknown`]: hashql_core::type::kind::TypeKind::Unknown
pub struct Decoder<'env, 'heap, A> {
env: &'env Environment<'heap>,
interner: &'env hashql_mir::intern::Interner<'heap>,
interner: &'env crate::intern::Interner<'heap>,

alloc: A,
}

impl<'env, 'heap, A: Allocator> Decoder<'env, 'heap, A> {
pub const fn new(
env: &'env Environment<'heap>,
interner: &'env hashql_mir::intern::Interner<'heap>,
interner: &'env crate::intern::Interner<'heap>,
alloc: A,
) -> Self {
Self {
Expand Down
Loading
Loading