verilization_compiler/lang/
mod.rs

1//! Defines generator related code for languages.
2
3pub mod generator;
4
5use crate::model;
6use std::ffi::OsString;
7use std::io;
8use std::path::Path;
9use num_bigint::BigUint;
10use std::marker::PhantomData;
11
12/// Error that could occur during generation.
13#[derive(Debug)]
14pub enum GeneratorError {
15	IOError(io::Error),
16	UnknownLanguage(String),
17	InvalidOptions(String),
18	UnmappedPackage(model::PackageName),
19	CouldNotFind(model::QualifiedName),
20	CouldNotFindVersion(model::QualifiedName, BigUint),
21	CouldNotResolveTypeParameter(String),
22	TypeCannotBeSequence(model::QualifiedName),
23	TypeDoesNotHaveCase(model::QualifiedName, Option<BigUint>, String),
24	IncorrectCaseArity(model::QualifiedName, String),
25	RecordLiteralNotForStruct,
26	ExternTypeDoesNotHaveRecordLiteral(model::QualifiedName),
27	CouldNotFindRecordField(model::QualifiedName, Option<BigUint>, String),
28	CouldNotGenerateType,
29	InvalidTypeForConstant,
30	InvalidTypeForCodec,
31}
32
33impl From<io::Error> for GeneratorError {
34	fn from(err: io::Error) -> Self {
35		GeneratorError::IOError(err)
36	}
37}
38
39/// Outputs files produced by the generator.
40/// 
41/// Allows for capturing the output without writing directly to the file system.
42pub trait OutputHandler<'state> {
43	type FileHandle : io::Write;
44	fn create_file<P: AsRef<Path>>(&'state mut self, path: P) -> Result<Self::FileHandle, GeneratorError>;
45}
46
47/// Defines a language supported by Verilization.
48pub trait Language {
49
50	/// An intermediate step for the language options.
51	type OptionsBuilder;
52
53	/// Finalized options.
54	type Options;
55
56	/// Gets the name of the language.
57	fn name() -> &'static str;
58
59	/// Gets an option builder with no options set.
60	fn empty_options() -> Self::OptionsBuilder;
61
62	/// Sets an option.
63	fn add_option(builder: &mut Self::OptionsBuilder, name: &str, value: OsString) -> Result<(), GeneratorError>;
64
65	/// Ensures that any required options have been set and finalizes the options.
66	fn finalize_options(builder: Self::OptionsBuilder) -> Result<Self::Options, GeneratorError>;
67	
68	/// Generates serialization code for the language.
69	fn generate<Output: for<'output> OutputHandler<'output>>(model: &model::Verilization, options: Self::Options, output: &mut Output) -> Result<(), GeneratorError>;
70
71}
72
73pub trait LanguageHandler {
74	type Result;
75	fn run<Lang: Language>(&mut self) -> Self::Result;
76}
77
78pub trait LanguageRegistry : Sized {
79	fn has_language(&self, lang_name: &str) -> bool;
80	fn handle_language<Handler: LanguageHandler>(&self, lang_name: &str, handler: &mut Handler) -> Option<Handler::Result>;
81	fn each_language<Handler: LanguageHandler>(&self, handler: &mut Handler) -> Vec<Handler::Result>;
82
83	fn add_language<Lang: Language>(self) -> LanguageRegistryCons<Lang, Self> {
84		LanguageRegistryCons {
85			prev: self,
86			dummy_lang: PhantomData {},
87		}
88	}
89}
90
91pub struct EmptyLanguageRegistry {}
92pub struct LanguageRegistryCons<Lang: Language, Prev: LanguageRegistry> {
93	prev: Prev,
94	dummy_lang: PhantomData<Lang>,
95}
96
97pub fn language_registry_new() -> EmptyLanguageRegistry {
98	EmptyLanguageRegistry {}
99}
100
101impl LanguageRegistry for EmptyLanguageRegistry {
102	fn has_language(&self, _lang_name: &str) -> bool {
103		false
104	}
105
106	fn handle_language<Handler: LanguageHandler>(&self, _lang_name: &str, _handler: &mut Handler) -> Option<Handler::Result> {
107		None
108	}
109
110	fn each_language<Handler: LanguageHandler>(&self, _handler: &mut Handler) -> Vec<Handler::Result> {
111		Vec::new()
112	}
113}
114
115impl <Lang: Language, Prev: LanguageRegistry> LanguageRegistry for LanguageRegistryCons<Lang, Prev> {
116	fn has_language(&self, lang_name: &str) -> bool  {
117		lang_name == Lang::name() || self.prev.has_language(lang_name)
118	}
119
120	fn handle_language<Handler: LanguageHandler>(&self, lang_name: &str, handler: &mut Handler) -> Option<Handler::Result> {
121		if lang_name == Lang::name() {
122			Some(handler.run::<Lang>())
123		}
124		else {
125			self.prev.handle_language(lang_name, handler)
126		}
127	}
128
129	fn each_language<Handler: LanguageHandler>(&self, handler: &mut Handler) -> Vec<Handler::Result> {
130		let mut results = self.prev.each_language(handler);
131		results.push(handler.run::<Lang>());
132		results
133	}
134}
135