Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wiggle/generate/src/codegen_settings.rs
3054 views
1
use crate::config::{AsyncConf, ErrorConf, ErrorConfField, TracingConf};
2
use proc_macro2::{Ident, TokenStream};
3
use quote::quote;
4
use std::collections::HashMap;
5
use std::rc::Rc;
6
use wasmtime_environ::error::{Error, format_err};
7
use witx::{Document, Id, InterfaceFunc, Module, NamedType, TypeRef};
8
9
pub use crate::config::Asyncness;
10
11
pub struct CodegenSettings {
12
pub errors: ErrorTransform,
13
pub async_: AsyncConf,
14
pub wasmtime: bool,
15
/// Disabling this feature makes it possible to remove all of the tracing
16
/// code emitted in the Wiggle-generated code; this can be helpful while
17
/// inspecting the code (e.g., with `cargo expand`).
18
pub tracing: TracingConf,
19
/// Determine whether the context structure will use `&mut self` (true) or
20
/// simply `&self`.
21
pub mutable: bool,
22
}
23
impl CodegenSettings {
24
pub fn new(
25
error_conf: &ErrorConf,
26
async_: &AsyncConf,
27
doc: &Document,
28
wasmtime: bool,
29
tracing: &TracingConf,
30
mutable: bool,
31
) -> Result<Self, Error> {
32
let errors = ErrorTransform::new(error_conf, doc)?;
33
Ok(Self {
34
errors,
35
async_: async_.clone(),
36
wasmtime,
37
tracing: tracing.clone(),
38
mutable,
39
})
40
}
41
pub fn get_async(&self, module: &Module, func: &InterfaceFunc) -> Asyncness {
42
self.async_.get(module.name.as_str(), func.name.as_str())
43
}
44
}
45
46
pub struct ErrorTransform {
47
m: Vec<ErrorType>,
48
}
49
50
impl ErrorTransform {
51
pub fn empty() -> Self {
52
Self { m: Vec::new() }
53
}
54
pub fn new(conf: &ErrorConf, doc: &Document) -> Result<Self, Error> {
55
let mut richtype_identifiers = HashMap::new();
56
let m = conf.iter().map(|(ident, field)|
57
match field {
58
ErrorConfField::Trappable(field) => if let Some(abi_type) = doc.typename(&Id::new(ident.to_string())) {
59
Ok(ErrorType::Generated(TrappableErrorType { abi_type, rich_type: field.rich_error.clone() }))
60
} else {
61
Err(format_err!("No witx typename \"{}\" found", ident.to_string()))
62
},
63
ErrorConfField::User(field) => if let Some(abi_type) = doc.typename(&Id::new(ident.to_string())) {
64
if let Some(ident) = field.rich_error.get_ident() {
65
if let Some(prior_def) = richtype_identifiers.insert(ident.clone(), field.err_loc)
66
{
67
return Err(format_err!(
68
"duplicate rich type identifier of {ident:?} not allowed. prior definition at {prior_def:?}",
69
));
70
}
71
Ok(ErrorType::User(UserErrorType {
72
abi_type,
73
rich_type: field.rich_error.clone(),
74
method_fragment: ident.to_string()
75
}))
76
} else {
77
return Err(format_err!(
78
"rich error type must be identifier for now - TODO add ability to provide a corresponding identifier: {:?}",
79
field.err_loc
80
))
81
}
82
}
83
else { Err(format_err!("No witx typename \"{}\" found", ident.to_string())) }
84
}
85
).collect::<Result<Vec<_>, Error>>()?;
86
Ok(Self { m })
87
}
88
89
pub fn iter(&self) -> impl Iterator<Item = &ErrorType> {
90
self.m.iter()
91
}
92
93
pub fn for_abi_error(&self, tref: &TypeRef) -> Option<&ErrorType> {
94
match tref {
95
TypeRef::Name(nt) => self.for_name(nt),
96
TypeRef::Value { .. } => None,
97
}
98
}
99
100
pub fn for_name(&self, nt: &NamedType) -> Option<&ErrorType> {
101
self.m.iter().find(|e| e.abi_type().name == nt.name)
102
}
103
}
104
105
pub enum ErrorType {
106
User(UserErrorType),
107
Generated(TrappableErrorType),
108
}
109
impl ErrorType {
110
pub fn abi_type(&self) -> &NamedType {
111
match self {
112
Self::User(u) => &u.abi_type,
113
Self::Generated(r) => &r.abi_type,
114
}
115
}
116
}
117
118
pub struct TrappableErrorType {
119
abi_type: Rc<NamedType>,
120
rich_type: Ident,
121
}
122
123
impl TrappableErrorType {
124
pub fn abi_type(&self) -> TypeRef {
125
TypeRef::Name(self.abi_type.clone())
126
}
127
pub fn typename(&self) -> TokenStream {
128
let richtype = &self.rich_type;
129
quote!(#richtype)
130
}
131
}
132
133
pub struct UserErrorType {
134
abi_type: Rc<NamedType>,
135
rich_type: syn::Path,
136
method_fragment: String,
137
}
138
139
impl UserErrorType {
140
pub fn abi_type(&self) -> TypeRef {
141
TypeRef::Name(self.abi_type.clone())
142
}
143
pub fn typename(&self) -> TokenStream {
144
let t = &self.rich_type;
145
quote!(#t)
146
}
147
pub fn method_fragment(&self) -> &str {
148
&self.method_fragment
149
}
150
}
151
152