use crate::{
resolve::{resolve_low_module, ModuleAndImports},
ImportAsset, ModuleDeclarationError,
};
use arora_registry::{ModuleFrozen, ReadableRegistry};
use arora_types::record::{
module::frozen::ExportKind,
ty::{FrozenTy, PrimitiveKind},
Resolver,
};
use arora_types::{
module::low::{
Executor, ExportFunction, ExportSymbol, Header, ImportFunction, ImportSymbol, Parameter,
TypeRef,
},
ty::{
BOOLEAN_ID, F32_ID, F64_ID, I16_ID, I32_ID, I64_ID, I8_ID, STRING_ID, U16_ID, U32_ID,
U64_ID, U8_ID, UNIT_ID,
},
SemanticVersion,
};
use arora_vfs::{Directory, Entry, File};
use semver::Version;
use std::fs::read_to_string;
use std::path::Path;
use uuid::Uuid;
pub fn generate_header_file(
id: &Uuid,
module: &ModuleFrozen,
imports: &[ImportAsset],
executor: &String,
) -> Result<Directory, ModuleDeclarationError> {
let header = Header {
id: id.to_owned(),
name: module.name.to_owned(),
author: String::new(),
description: None,
license: String::new(),
version: SemanticVersion {
major: 0u32,
minor: 0u32,
patch: 0u32,
},
executor: Executor {
name: executor.to_owned(),
min_version: None,
max_version: None,
},
exports: module
.exports
.iter()
.map(|(export_id, export)| {
let ExportKind::Function(function) = &export.kind;
ExportSymbol::Function(ExportFunction {
id: export_id.to_owned(),
name: export.name.to_owned(),
parameters: function
.parameter_ordering
.iter()
.map(|parameter_id| {
let parameter = function.parameters.get(parameter_id).unwrap();
Parameter {
name: parameter.name.to_owned(),
ty: low_type_ref_from_unfrozen_ty(¶meter.ty),
mutable: parameter.mutable,
id: parameter_id.to_owned(),
default_value: None,
}
})
.collect(),
ret: low_type_ref_from_unfrozen_ty(&function.return_ty),
})
})
.collect(),
imports: imports
.iter()
.map(|import| {
let ExportKind::Function(import_function) = &import.import.kind;
ImportSymbol::Function(ImportFunction {
id: import.id.to_owned(),
name: import.import.name.to_owned(),
module: import.module_id.to_owned(),
parameters: import_function
.parameter_ordering
.iter()
.map(|parameter_id| {
let parameter = import_function.parameters.get(parameter_id).unwrap();
Parameter {
name: parameter.name.to_owned(),
ty: low_type_ref_from_unfrozen_ty(¶meter.ty),
mutable: parameter.mutable,
id: parameter_id.to_owned(),
default_value: None,
}
})
.collect(),
ret: low_type_ref_from_unfrozen_ty(&import_function.return_ty),
})
})
.collect(),
executable_mime: "".to_string(),
};
let mut result = Directory::new();
let header_file = File::new(serde_yaml::to_string(&header).unwrap().as_bytes());
result
.insert("module.yaml", Entry::File(header_file))
.map_err(ModuleDeclarationError::VfsError)?;
Ok(result)
}
pub async fn module_frozen_from_header_file<P: AsRef<Path>, R: ReadableRegistry + Resolver>(
header_path: P,
registry: &mut R,
) -> Result<(Uuid, Version, ModuleAndImports), ModuleDeclarationError> {
let header: Header = serde_yaml::from_str(
&read_to_string(header_path.as_ref()).map_err(ModuleDeclarationError::IoError)?,
)
.map_err(|e| {
ModuleDeclarationError::Generic(format!(
"header file {} contains invalid yaml: {}",
header_path.as_ref().display(),
e
))
})?;
Ok((
header.id.to_owned(),
header.version.to_owned().into(),
resolve_low_module(header, registry).await?,
))
}
fn low_type_ref_from_unfrozen_ty(unfrozen: &FrozenTy) -> TypeRef {
match unfrozen {
FrozenTy::Primitive(primitive) => match primitive.kind {
PrimitiveKind::Unit => TypeRef::Scalar {
id: UNIT_ID.to_owned(),
},
PrimitiveKind::Boolean => TypeRef::Scalar {
id: BOOLEAN_ID.to_owned(),
},
PrimitiveKind::U8 => TypeRef::Scalar {
id: U8_ID.to_owned(),
},
PrimitiveKind::U16 => TypeRef::Scalar {
id: U16_ID.to_owned(),
},
PrimitiveKind::U32 => TypeRef::Scalar {
id: U32_ID.to_owned(),
},
PrimitiveKind::U64 => TypeRef::Scalar {
id: U64_ID.to_owned(),
},
PrimitiveKind::I8 => TypeRef::Scalar {
id: I8_ID.to_owned(),
},
PrimitiveKind::I16 => TypeRef::Scalar {
id: I16_ID.to_owned(),
},
PrimitiveKind::I32 => TypeRef::Scalar {
id: I32_ID.to_owned(),
},
PrimitiveKind::I64 => TypeRef::Scalar {
id: I64_ID.to_owned(),
},
PrimitiveKind::F32 => TypeRef::Scalar {
id: F32_ID.to_owned(),
},
PrimitiveKind::F64 => TypeRef::Scalar {
id: F64_ID.to_owned(),
},
PrimitiveKind::String => TypeRef::Scalar {
id: STRING_ID.to_owned(),
},
PrimitiveKind::ArrayBoolean => TypeRef::Array {
id: BOOLEAN_ID.to_owned(),
},
PrimitiveKind::ArrayU8 => TypeRef::Array {
id: U8_ID.to_owned(),
},
PrimitiveKind::ArrayU16 => TypeRef::Array {
id: U16_ID.to_owned(),
},
PrimitiveKind::ArrayU32 => TypeRef::Array {
id: U32_ID.to_owned(),
},
PrimitiveKind::ArrayU64 => TypeRef::Array {
id: U64_ID.to_owned(),
},
PrimitiveKind::ArrayI8 => TypeRef::Array {
id: I8_ID.to_owned(),
},
PrimitiveKind::ArrayI16 => TypeRef::Array {
id: I16_ID.to_owned(),
},
PrimitiveKind::ArrayI32 => TypeRef::Array {
id: I32_ID.to_owned(),
},
PrimitiveKind::ArrayI64 => TypeRef::Array {
id: I64_ID.to_owned(),
},
PrimitiveKind::ArrayF32 => TypeRef::Array {
id: F32_ID.to_owned(),
},
PrimitiveKind::ArrayF64 => TypeRef::Array {
id: F64_ID.to_owned(),
},
PrimitiveKind::ArrayString => TypeRef::Array {
id: STRING_ID.to_owned(),
},
},
FrozenTy::FrozenScalar(scalar) => TypeRef::Scalar {
id: scalar.reference.id.to_owned(),
},
FrozenTy::FrozenArray(array) => TypeRef::Array {
id: array.reference.id.to_owned(),
},
}
}