use std::sync::Arc;
use crate::{
capability::CapabilityName,
env::Cx,
error::Result,
id::{
ClassId, CodecId, FunctionId, LibId, MacroId, NumberDomainId, RuntimeId, ShapeId, Symbol,
},
value::Value,
};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Version(pub String);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct AbiVersion {
pub major: u16,
pub minor: u16,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LibTarget {
Native,
WasmComponent,
CodecSource(Symbol),
DataOnly,
HostRegistered,
}
impl LibTarget {
pub fn to_symbol(&self) -> Symbol {
match self {
LibTarget::Native => Symbol::new("native"),
LibTarget::WasmComponent => Symbol::new("wasm-component"),
LibTarget::CodecSource(codec) => codec.clone(),
LibTarget::DataOnly => Symbol::new("data-only"),
LibTarget::HostRegistered => Symbol::new("host-registered"),
}
}
pub fn from_symbol(symbol: &Symbol) -> Self {
if symbol.namespace.is_none() {
match symbol.name.as_ref() {
"native" => return LibTarget::Native,
"wasm-component" => return LibTarget::WasmComponent,
"data-only" => return LibTarget::DataOnly,
"host-registered" => return LibTarget::HostRegistered,
"lisp-source" => return LibTarget::CodecSource(Symbol::qualified("codec", "lisp")),
_ => {}
}
}
LibTarget::CodecSource(symbol.clone())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Dependency {
pub id: Symbol,
pub minimum_version: Option<Version>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Export {
Class {
symbol: Symbol,
class_id: Option<ClassId>,
},
Function {
symbol: Symbol,
function_id: Option<FunctionId>,
},
Macro {
symbol: Symbol,
macro_id: Option<MacroId>,
},
Shape {
symbol: Symbol,
shape_id: Option<ShapeId>,
},
Codec {
symbol: Symbol,
codec_id: Option<CodecId>,
},
NumberDomain {
symbol: Symbol,
number_domain_id: Option<NumberDomainId>,
},
Value {
symbol: Symbol,
},
Site {
symbol: Symbol,
runtime_id: Option<RuntimeId>,
},
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct ExportKind(Symbol);
impl ExportKind {
pub const CLASS: &'static str = "class";
pub const FUNCTION: &'static str = "function";
pub const MACRO: &'static str = "macro";
pub const SHAPE: &'static str = "shape";
pub const CODEC: &'static str = "codec";
pub const NUMBER_DOMAIN: &'static str = "number-domain";
pub const VALUE: &'static str = "value";
pub const SITE: &'static str = "site";
pub fn new(symbol: Symbol) -> Self {
Self(symbol)
}
pub fn named(name: &'static str) -> Self {
Self(Symbol::new(name))
}
pub fn symbol(&self) -> &Symbol {
&self.0
}
pub fn name(&self) -> Option<&str> {
match &self.0.namespace {
Some(_) => None,
None => Some(self.0.name.as_ref()),
}
}
pub fn duplicate_error_kind(&self) -> &'static str {
match self.name() {
Some(Self::CLASS) => Self::CLASS,
Some(Self::FUNCTION) => Self::FUNCTION,
Some(Self::MACRO) => Self::MACRO,
Some(Self::SHAPE) => Self::SHAPE,
Some(Self::CODEC) => Self::CODEC,
Some(Self::NUMBER_DOMAIN) => Self::NUMBER_DOMAIN,
Some(Self::VALUE) => Self::VALUE,
Some(Self::SITE) => Self::SITE,
_ => "export",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ExportState {
Resolved {
id: RuntimeId,
},
Declared,
Unsupported {
reason: String,
},
Invalid {
error: String,
},
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExportRecord {
pub kind: ExportKind,
pub symbol: Symbol,
pub state: ExportState,
}
impl Export {
pub fn symbol(&self) -> &Symbol {
match self {
Self::Class { symbol, .. }
| Self::Function { symbol, .. }
| Self::Macro { symbol, .. }
| Self::Shape { symbol, .. }
| Self::Codec { symbol, .. }
| Self::NumberDomain { symbol, .. }
| Self::Value { symbol }
| Self::Site { symbol, .. } => symbol,
}
}
pub fn kind(&self) -> &'static str {
match self {
Self::Class { .. } => "class",
Self::Function { .. } => "function",
Self::Macro { .. } => "macro",
Self::Shape { .. } => "shape",
Self::Codec { .. } => "codec",
Self::NumberDomain { .. } => "number-domain",
Self::Value { .. } => "value",
Self::Site { .. } => "site",
}
}
pub fn kind_symbol(&self) -> ExportKind {
ExportKind::named(self.kind())
}
pub fn declared_record(&self) -> ExportRecord {
ExportRecord {
kind: self.kind_symbol(),
symbol: self.symbol().clone(),
state: ExportState::Declared,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LibManifest {
pub id: Symbol,
pub version: Version,
pub abi: AbiVersion,
pub target: LibTarget,
pub requires: Vec<Dependency>,
pub capabilities: Vec<CapabilityName>,
pub exports: Vec<Export>,
}
impl LibManifest {
pub fn declared_export_records(&self) -> Vec<ExportRecord> {
self.exports.iter().map(Export::declared_record).collect()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LoadedLib {
pub id: LibId,
pub manifest: LibManifest,
pub exports: Vec<ExportRecord>,
pub trusted: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TestReport {
pub name: Symbol,
pub passed: bool,
pub detail: Option<String>,
pub mode: Symbol,
pub events: Vec<Value>,
pub effect: Option<Value>,
pub shape_report: Option<Value>,
pub skipped: bool,
}
impl TestReport {
pub fn from_result(name: Symbol, passed: bool, detail: Option<String>) -> Self {
Self {
name,
passed,
detail,
mode: Symbol::new("unknown"),
events: Vec::new(),
effect: None,
shape_report: None,
skipped: false,
}
}
pub fn skipped(name: Symbol, detail: Option<String>) -> Self {
Self {
name,
passed: false,
detail,
mode: Symbol::new("unknown"),
events: Vec::new(),
effect: None,
shape_report: None,
skipped: true,
}
}
}
pub trait Test: Send + Sync {
fn symbol(&self) -> Symbol;
fn lib(&self) -> Symbol;
fn describe(&self, cx: &mut Cx) -> Result<Value>;
fn run(&self, cx: &mut Cx) -> Result<TestReport>;
}
#[derive(Clone)]
pub struct RegisteredTest {
pub symbol: Symbol,
pub lib: Symbol,
pub test: Arc<dyn Test>,
pub subjects: Vec<Symbol>,
}