use std::{
collections::{HashMap, HashSet},
rc::Rc,
};
use ferricel_types::{extensions::ExtensionDecl, functions::RuntimeFunction};
use walrus::{FunctionId, LocalId};
use crate::schema::ProtoSchema;
pub struct CompilerEnv {
pub(crate) functions: HashMap<RuntimeFunction, FunctionId>,
}
impl CompilerEnv {
pub fn get(&self, func: RuntimeFunction) -> FunctionId {
*self
.functions
.get(&func)
.unwrap_or_else(|| panic!("Function {} missing in runtime module", func.name()))
}
}
pub struct CompilerContext {
pub local_vars: HashMap<String, LocalId>,
pub schema: Option<ProtoSchema>,
pub container: Option<String>,
pub logger: slog::Logger,
pub extensions: Rc<ExtensionRegistry>,
}
impl CompilerContext {
pub fn new(
schema: Option<ProtoSchema>,
container: Option<String>,
logger: slog::Logger,
extensions: &[ExtensionDecl],
) -> Self {
Self {
local_vars: HashMap::new(),
schema,
container,
logger,
extensions: Rc::new(ExtensionRegistry::new(extensions)),
}
}
pub fn with_local(&self, name: String, local_id: LocalId) -> Self {
let mut local_vars = self.local_vars.clone();
local_vars.insert(name, local_id);
Self {
local_vars,
schema: self.schema.clone(),
container: self.container.clone(),
logger: self.logger.clone(),
extensions: self.extensions.clone(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ExtensionKey {
pub namespace: Option<String>,
pub function: String,
}
impl ExtensionKey {
pub fn new(namespace: Option<String>, function: String) -> Self {
Self {
namespace,
function,
}
}
}
pub struct ExtensionRegistry {
pub by_name: HashMap<ExtensionKey, ExtensionDecl>,
pub namespaces: HashSet<String>,
}
impl ExtensionRegistry {
pub fn new(extensions: &[ExtensionDecl]) -> Self {
let mut by_name = HashMap::new();
let mut namespaces = HashSet::new();
for decl in extensions {
if let Some(ref ns) = decl.namespace {
namespaces.insert(ns.clone());
}
by_name.insert(
ExtensionKey::new(decl.namespace.clone(), decl.function.clone()),
decl.clone(),
);
}
Self {
by_name,
namespaces,
}
}
pub fn is_empty(&self) -> bool {
self.by_name.is_empty()
}
}
pub enum CallShape<'a> {
Global,
Namespaced(&'a str),
Receiver(Option<&'a cel::common::ast::IdedExpr>),
}