strict_types/typelib/
compile.rs1use std::collections::BTreeMap;
25
26use encoding::LibName;
27use strict_encoding::TypeName;
28
29use crate::typelib::{Dependency, ExternTypes, InlineRef, InlineRef1, InlineRef2, LibRef};
30use crate::{SemId, Translate, TranspileError, TranspileRef, Ty};
31
32pub type TypeIndex = BTreeMap<TypeName, SemId>;
33
34#[deprecated(since = "1.3.0", note = "use CompileError")]
35pub type TranslateError = CompileError;
36
37#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)]
38#[display(doc_comments)]
39pub enum CompileError {
40 DuplicateName(TypeName),
42
43 UnknownType {
45 unknown: TypeName,
46 within: Ty<TranspileRef>,
47 },
48
49 Continue,
51
52 DuplicatedDependency(Dependency),
54
55 NestedInline(TypeName, String, String),
57
58 UnknownLib(LibName),
60
61 TooManyDependencies,
63
64 TooManyTypes,
66
67 LibTooLarge(LibName),
69
70 DependencyMissesType(LibName, SemId, TypeName),
72}
73
74impl From<TranspileError> for CompileError {
75 fn from(err: TranspileError) -> Self {
76 match err {
77 TranspileError::UnknownType { unknown, within } => {
78 Self::UnknownType { unknown, within }
79 }
80 TranspileError::UnknownLib(lib) => Self::UnknownLib(lib),
81 TranspileError::TooManyDependencies => Self::TooManyDependencies,
82 TranspileError::TooManyTypes => Self::TooManyTypes,
83 TranspileError::LibTooLarge(lib) => Self::LibTooLarge(lib),
84 TranspileError::DependencyMissesType(lib, sem_id, type_name) => {
85 Self::DependencyMissesType(lib, sem_id, type_name)
86 }
87 }
88 }
89}
90
91pub struct NestedContext {
92 pub top_name: TypeName,
93 pub index: TypeIndex,
94 pub extern_types: ExternTypes,
95 pub stack: Vec<String>,
96}
97
98impl Translate<LibRef> for TranspileRef {
99 type Context = ();
100 type Builder = NestedContext;
101 type Error = CompileError;
102
103 fn translate(
104 self,
105 builder: &mut Self::Builder,
106 ctx: &Self::Context,
107 ) -> Result<LibRef, Self::Error> {
108 match self {
109 TranspileRef::Embedded(ty) => {
110 builder.stack.push(ty.cls().to_string());
111 let res = ty.translate(builder, ctx).map(LibRef::Inline);
112 builder.stack.pop();
113 res
114 }
115 TranspileRef::Named(name) => {
116 let id = builder.index.get(&name).ok_or(CompileError::Continue)?;
117 Ok(LibRef::Named(*id))
118 }
119 TranspileRef::Extern(ext) => Ok(LibRef::Extern(ext.into())),
120 }
121 }
122}
123
124impl Translate<InlineRef> for TranspileRef {
125 type Context = ();
126 type Builder = NestedContext;
127 type Error = CompileError;
128
129 fn translate(
130 self,
131 builder: &mut Self::Builder,
132 ctx: &Self::Context,
133 ) -> Result<InlineRef, Self::Error> {
134 match self {
135 TranspileRef::Embedded(ty) => {
136 builder.stack.push(ty.cls().to_string());
137 let res = ty.translate(builder, ctx).map(InlineRef::Inline);
138 builder.stack.pop();
139 res
140 }
141 TranspileRef::Named(name) => {
142 let id = builder.index.get(&name).ok_or(CompileError::Continue)?;
143 Ok(InlineRef::Named(*id))
144 }
145 TranspileRef::Extern(ext) => Ok(InlineRef::Extern(ext.into())),
146 }
147 }
148}
149
150impl Translate<InlineRef1> for TranspileRef {
151 type Context = ();
152 type Builder = NestedContext;
153 type Error = CompileError;
154
155 fn translate(
156 self,
157 builder: &mut Self::Builder,
158 ctx: &Self::Context,
159 ) -> Result<InlineRef1, Self::Error> {
160 match self {
161 TranspileRef::Embedded(ty) => {
162 builder.stack.push(ty.cls().to_string());
163 let res = ty.translate(builder, ctx).map(InlineRef1::Inline);
164 builder.stack.pop();
165 res
166 }
167 TranspileRef::Named(name) => {
168 let id = builder.index.get(&name).ok_or(CompileError::Continue)?;
169 Ok(InlineRef1::Named(*id))
170 }
171 TranspileRef::Extern(ext) => Ok(InlineRef1::Extern(ext.into())),
172 }
173 }
174}
175
176impl Translate<InlineRef2> for TranspileRef {
177 type Context = ();
178 type Builder = NestedContext;
179 type Error = CompileError;
180
181 fn translate(
182 self,
183 builder: &mut Self::Builder,
184 _ctx: &Self::Context,
185 ) -> Result<InlineRef2, Self::Error> {
186 match self {
187 TranspileRef::Embedded(_ty) => {
188 let mut path = builder.stack.clone();
189 let name = path.pop().unwrap_or_else(|| s!("<unnamed>"));
190 Err(CompileError::NestedInline(builder.top_name.clone(), path.join("."), name))
191 }
192 TranspileRef::Named(name) => {
193 let id = builder.index.get(&name).ok_or(CompileError::Continue)?;
194 Ok(InlineRef2::Named(*id))
195 }
196 TranspileRef::Extern(ext) => Ok(InlineRef2::Extern(ext.into())),
197 }
198 }
199}