Skip to content

Commit 3a9a3a4

Browse files
authoredApr 15, 2022
wip: very very basic compiler implementation (librasn#92)
* wip: very very basic implementation * small style fix
1 parent 550a335 commit 3a9a3a4

File tree

8 files changed

+445
-91
lines changed

8 files changed

+445
-91
lines changed
 

‎compiler/src/codegen.rs

+232-72
Large diffs are not rendered by default.

‎compiler/src/codegen/constant.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ impl Constant {
2424
pub fn generate(self, backend: &mut Rust) -> Fallible<String> {
2525
use heck::ShoutySnakeCase;
2626

27+
let (ty, _) = backend.generate_type(&self.ty, None)?;
28+
2729
Ok(format!(
2830
"{vis}const {name}: {ty} = {value};",
2931
vis = self.visibility,
3032
name = self.name.to_shouty_snake_case(),
31-
ty = backend.generate_type(&self.ty)?,
33+
ty = ty,
3234
value = backend.generate_value(&self.value)?,
3335
))
3436
}

‎compiler/src/codegen/constant_enum.rs

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use failure::Fallible;
2+
use heck::CamelCase;
3+
use itertools::Itertools;
4+
use std::collections::HashSet;
5+
use std::hash::{Hash, Hasher};
6+
7+
use super::imports::Visibility;
8+
9+
#[derive(Clone, Debug, Eq)]
10+
pub struct Triple {
11+
pub key: String,
12+
pub value_type: String,
13+
pub value: String,
14+
}
15+
16+
impl Triple {
17+
pub fn new(key: String, value_type: String, value: String) -> Self {
18+
Self {
19+
key,
20+
value_type,
21+
value,
22+
}
23+
}
24+
}
25+
26+
impl PartialEq for Triple {
27+
fn eq(&self, other: &Self) -> bool {
28+
self.key == other.key
29+
}
30+
}
31+
32+
impl Hash for Triple {
33+
fn hash<H: Hasher>(&self, state: &mut H) {
34+
state.write(self.key.as_bytes());
35+
}
36+
}
37+
38+
#[derive(Clone, Debug, Eq)]
39+
pub struct ConstantEnum {
40+
visibility: Visibility,
41+
name: String,
42+
variants: HashSet<Triple>,
43+
}
44+
45+
impl PartialEq for ConstantEnum {
46+
fn eq(&self, other: &Self) -> bool {
47+
self.name == other.name
48+
}
49+
}
50+
51+
impl Hash for ConstantEnum {
52+
fn hash<H: Hasher>(&self, state: &mut H) {
53+
state.write(self.name.as_bytes());
54+
}
55+
}
56+
57+
impl ConstantEnum {
58+
pub fn new(visibility: Visibility, name: String, variants: HashSet<Triple>) -> Self {
59+
Self {
60+
visibility,
61+
name,
62+
variants,
63+
}
64+
}
65+
66+
pub fn generate(self) -> String {
67+
format!(
68+
r#"
69+
#[non_exhaustive]
70+
{vis}struct {name};
71+
impl {name} {{
72+
{variants}
73+
}}"#,
74+
vis = self.visibility,
75+
name = self.name.to_camel_case(),
76+
variants = self
77+
.variants
78+
.iter()
79+
.map(|triple| format!(
80+
"\t{}{}: {} = {};",
81+
self.visibility,
82+
triple.key.to_camel_case(),
83+
triple.value_type.to_camel_case(),
84+
triple.value
85+
))
86+
.join("\n"),
87+
)
88+
}
89+
}

‎compiler/src/codegen/imports.rs

+6
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,9 @@ impl fmt::Display for Visibility {
4343
visibility.fmt(f)
4444
}
4545
}
46+
47+
impl Default for Visibility {
48+
fn default() -> Self {
49+
Visibility::Private
50+
}
51+
}

‎compiler/src/codegen/structs.rs

+107-14
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,41 @@
1+
use crate::codegen::imports::Visibility;
2+
use crate::parser::{Prefix, TagKind};
13
use std::fmt;
24

35
pub struct Struct {
6+
visibility: Visibility,
47
name: String,
58
fields: Vec<Field>,
69
attributes: Vec<Attribute>,
710
}
811

912
impl Struct {
10-
pub fn new<I: Into<String>>(name: I) -> Self {
13+
pub fn new<I: Into<String>>(visibility: Visibility, name: I) -> Self {
1114
Self {
15+
visibility,
1216
name: name.into(),
1317
fields: Vec::new(),
1418
attributes: vec![Attribute::Derive(vec![
15-
Derive::Serialize,
16-
Derive::Deserialize,
19+
Derive::AsnType,
20+
Derive::Encode,
21+
Derive::Decode,
22+
Derive::PartialEq,
23+
Derive::PartialOrd,
24+
Derive::Eq,
25+
Derive::Ord,
26+
Derive::Debug,
1727
])],
1828
}
1929
}
2030

2131
pub fn add_field(&mut self, field: Field) {
2232
self.fields.push(field);
2333
}
34+
35+
pub fn add_rasn_attributes(mut self, attributes: Vec<Rasn>) -> Self {
36+
self.attributes.push(Attribute::Rasn(attributes));
37+
self
38+
}
2439
}
2540

2641
impl fmt::Display for Struct {
@@ -30,7 +45,7 @@ impl fmt::Display for Struct {
3045
writeln!(f)?;
3146
}
3247

33-
writeln!(f, "struct {} {{", self.name)?;
48+
writeln!(f, "{}struct {} {{", self.visibility, self.name)?;
3449

3550
if !self.fields.is_empty() {
3651
itertools::join(self.fields.iter().map(ToString::to_string), "\n").fmt(f)?;
@@ -42,6 +57,7 @@ impl fmt::Display for Struct {
4257
}
4358

4459
pub struct Field {
60+
visibility: Visibility,
4561
attributes: Vec<Attribute>,
4662
name: String,
4763
optional: bool,
@@ -52,7 +68,13 @@ pub struct Field {
5268
impl fmt::Display for Field {
5369
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5470
if !self.attributes.is_empty() {
55-
itertools::join(self.attributes.iter().map(ToString::to_string), "\n").fmt(f)?;
71+
itertools::join(
72+
self.attributes
73+
.iter()
74+
.map(|x| format!("\t{}", x.to_string())),
75+
"\n",
76+
)
77+
.fmt(f)?;
5678
writeln!(f)?;
5779
}
5880

@@ -62,16 +84,18 @@ impl fmt::Display for Field {
6284
self.ty.clone()
6385
};
6486

65-
write!(f, "{}: {},", self.name, ty)
87+
write!(f, "\t{}{}: {},", self.visibility, self.name, ty)
6688
}
6789
}
6890

6991
#[derive(Default)]
7092
pub struct FieldBuilder {
93+
visibility: Visibility,
7194
name: String,
7295
ty: String,
7396
optional: bool,
7497
default_value: Option<String>,
98+
attributes: Vec<Attribute>,
7599
}
76100

77101
impl FieldBuilder {
@@ -80,12 +104,18 @@ impl FieldBuilder {
80104
let ty = ty.into();
81105

82106
Self {
107+
visibility: Visibility::Private,
83108
name,
84109
ty,
85110
..Self::default()
86111
}
87112
}
88113

114+
pub fn visibility(mut self, visibility: Visibility) -> Self {
115+
self.visibility = visibility;
116+
self
117+
}
118+
89119
pub fn optional(mut self, optional: bool) -> Self {
90120
self.optional = optional;
91121
self
@@ -96,15 +126,20 @@ impl FieldBuilder {
96126
self
97127
}
98128

99-
pub fn build(self) -> Field {
100-
let mut attributes = Vec::new();
129+
pub fn add_rasn_attribute(mut self, attributes: Vec<Rasn>) -> Self {
130+
self.attributes.push(Attribute::Rasn(attributes));
131+
self
132+
}
101133

134+
pub fn build(mut self) -> Field {
102135
if let Some(default_value) = self.default_value {
103-
attributes.push(Attribute::Serde(Serde::Default(default_value)));
136+
self.attributes
137+
.push(Attribute::Serde(Serde::Default(default_value)));
104138
}
105139

106140
Field {
107-
attributes,
141+
visibility: self.visibility,
142+
attributes: self.attributes,
108143
name: self.name,
109144
optional: self.optional,
110145
ty: self.ty,
@@ -115,6 +150,7 @@ impl FieldBuilder {
115150
pub enum Attribute {
116151
Serde(Serde),
117152
Derive(Vec<Derive>),
153+
Rasn(Vec<Rasn>),
118154
}
119155

120156
impl fmt::Display for Attribute {
@@ -127,6 +163,10 @@ impl fmt::Display for Attribute {
127163
"#[derive({})]",
128164
itertools::join(defaults.iter().map(ToString::to_string), ", ")
129165
),
166+
Attribute::Rasn(defaults) => format!(
167+
"#[rasn({})]",
168+
itertools::join(defaults.iter().map(ToString::to_string), ", ")
169+
),
130170
};
131171

132172
attribute.fmt(f)
@@ -138,17 +178,70 @@ pub enum Serde {
138178
}
139179

140180
pub enum Derive {
141-
Serialize,
142-
Deserialize,
181+
AsnType,
182+
Encode,
183+
Decode,
184+
PartialEq,
185+
PartialOrd,
186+
Eq,
187+
Ord,
188+
Debug,
143189
}
144190

145191
impl fmt::Display for Derive {
146192
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147193
let derive = match self {
148-
Derive::Serialize => "Serialize",
149-
Derive::Deserialize => "Deserialize",
194+
Derive::AsnType => "AsnType",
195+
Derive::Encode => "Encode",
196+
Derive::Decode => "Decode",
197+
Derive::PartialEq => "PartialEq",
198+
Derive::PartialOrd => "PartialOrd",
199+
Derive::Eq => "Eq",
200+
Derive::Ord => "Ord",
201+
Derive::Debug => "Debug",
150202
};
151203

152204
derive.fmt(f)
153205
}
154206
}
207+
208+
pub enum Rasn {
209+
Type(&'static str),
210+
Prefix(Prefix),
211+
}
212+
213+
impl fmt::Display for Rasn {
214+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215+
let rasn = match self {
216+
Rasn::Type(type_name) => type_name.to_string(),
217+
Rasn::Prefix(prefix) => match prefix.kind {
218+
TagKind::Explicit => format!(
219+
"tag(explicit({class}{number}))",
220+
class = prefix
221+
.class
222+
.map(|x| x.to_string().to_lowercase() + ", ")
223+
.unwrap_or(String::from("")),
224+
number = prefix.number
225+
),
226+
TagKind::Implicit => format!(
227+
"tag(implicit({class}{number}))",
228+
class = prefix
229+
.class
230+
.map(|x| x.to_string().to_lowercase() + ", ")
231+
.unwrap_or(String::from("")),
232+
number = prefix.number
233+
),
234+
_ => format!(
235+
"tag({class}{number})",
236+
class = prefix
237+
.class
238+
.map(|x| x.to_string().to_lowercase() + ", ")
239+
.unwrap_or(String::from("")),
240+
number = prefix.number
241+
),
242+
},
243+
};
244+
245+
rasn.fmt(f)
246+
}
247+
}

‎compiler/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ impl NotationCompiler {
4141

4242
let mut output = Vec::new();
4343

44-
CodeGenerator::<Vec<u8>, Rust>::new(fixed_tree, &mut output)
45-
.generate()?;
44+
CodeGenerator::<Vec<u8>, Rust>::new(fixed_tree, &mut output).generate()?;
4645

4746
Ok(String::from_utf8(output).unwrap())
4847
}

‎compiler/src/parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ impl<'a> Parser<'a> {
994994
component_list.extension = Some(Extension {
995995
exception,
996996
additions,
997-
marker
997+
marker,
998998
});
999999
}
10001000

‎compiler/src/parser/types/prefix.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ pub struct Prefix {
99
}
1010

1111
impl Prefix {
12-
pub fn new(encoding: Option<String>, kind: TagKind, class: Option<Class>, number: Number) -> Self {
12+
pub fn new(
13+
encoding: Option<String>,
14+
kind: TagKind,
15+
class: Option<Class>,
16+
number: Number,
17+
) -> Self {
1318
Self {
1419
encoding,
1520
class,

0 commit comments

Comments
 (0)
Please sign in to comment.