use num_bigint::{BigInt, Sign};
use pest::iterators::{Pair, Pairs};
use pest::Parser;
use pest::Span;
use pest_derive::Parser;
use serde::de::DeserializeOwned;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::rc::Rc;
mod tree;
use tree::Tree;
mod recipe;
pub use recipe::Recipe;
#[derive(Parser)]
#[grammar = "grammar.pest"]
struct MyParser;
type WriteResult = Result<(), std::io::Error>;
enum CompilationError {
DataNotStruct(u32),
EnumTypeIsNotInt(u32),
EnumValueOutOfBounds(u32),
EnumUndefinedName {
node_enum: u32,
node_name: u32,
},
EnumUndefinedData {
data_nid: u32,
},
ExpectedDatFloat(u32),
ExpectedDatInt(u32),
ExpectedDatStruct(u32),
ExpectedDatIdentifier(u32),
GenericArgCountMismatch {
nid: u32,
expected: usize,
current: usize,
},
IOError(std::io::Error),
RedefinedValue(u32),
TupleSizeMismatch {
node_tuple: u32,
node_data: u32,
},
UndefinedValue(u32),
UnresolvedType {
path: String,
node: u32,
},
ValueOutOfBounds(u32),
}
#[derive(Debug)]
pub struct SourceLocation {
source: Rc<String>,
start: usize,
end: usize,
}
impl SourceLocation {
fn new_from_span(source: Rc<String>, span: Span<'_>) -> Self {
SourceLocation {
source: source,
start: span.start(),
end: span.end(),
}
}
}
#[derive(Debug, Clone)]
pub enum RecTypeId {
Path(String),
Id(u32),
}
impl RecTypeId {
fn unwrap_id(&self) -> u32 {
match self {
Self::Id(value) => *value,
_ => panic!("unresolved type"),
}
}
}
#[derive(Debug, Clone)]
pub enum NodeContent {
RecInt {
bit_size: u32,
signed: bool,
},
RecFloat {
size: u32,
},
RecList,
RecMap,
RecEnum {
key_type: RecTypeId,
},
RecEnumItem {
value: BigInt,
},
RecStruct,
RecStructMember,
RecTupleMember {
tid: RecTypeId,
},
RecTypeInst {
tid: RecTypeId,
},
RecGeneric {
index: u32,
},
DatMap,
DatTuple,
DatList,
DatMapAssignment,
DatTupleMember,
RecTuple,
DatInt {
repr: String,
},
DatFloat {
repr: String,
},
DatEnum,
}
impl NodeContent {
fn may_be_generic(&self) -> bool {
match self {
NodeContent::RecStruct | NodeContent::RecList | NodeContent::RecMap => true,
_ => false,
}
}
}
#[derive(Debug)]
pub struct Node {
pub name: Option<String>,
pub source: Option<SourceLocation>,
pub content: NodeContent,
}
impl Node {
pub fn new_builtin(name: &str, content: NodeContent) -> Node {
Node {
name: Some(name.to_string()),
source: None,
content: content,
}
}
pub fn new_anonymous(content: NodeContent) -> Node {
Node {
name: None,
source: None,
content: content,
}
}
fn name_or_anonymous(&self) -> String {
match &self.name {
Some(name) => name.clone(),
None => "?".to_string(),
}
}
}
pub type NodeTree = Tree<Node>;
impl NodeTree {
fn create_generic_type(
&mut self,
parent: Option<u32>,
name: &str,
content: NodeContent,
n: u32,
) -> u32 {
let nid = self.create_with_parent(
parent,
Node {
name: Some(name.to_string()),
source: None,
content: content,
},
);
for i in 0..n {
self.create_with_parent(
Some(nid),
Node {
name: None,
source: None,
content: NodeContent::RecGeneric { index: i },
},
);
}
nid
}
pub fn create_root_struct(&mut self) -> u32 {
self.create(Node::new_anonymous(NodeContent::RecStruct))
}
pub fn create_struct(&mut self, parent: Option<u32>, name: &str) -> u32 {
self.create_with_parent(
parent,
Node {
name: Some(name.to_string()),
source: None,
content: NodeContent::RecStruct,
},
)
}
pub fn create_struct_member(&mut self, parent: u32, name: &str, nid_type: u32) -> u32 {
let nid = self.create_with_parent(
Some(parent),
Node {
name: Some(name.to_string()),
source: None,
content: NodeContent::RecStructMember,
},
);
self.child(nid, nid_type);
nid
}
pub fn create_enum(&mut self, parent: Option<u32>, name: &str, nid_key_type: u32) -> u32 {
self.create_with_parent(
parent,
Node {
name: Some(name.to_string()),
source: None,
content: NodeContent::RecEnum {
key_type: RecTypeId::Id(nid_key_type),
},
},
)
}
pub fn create_enum_member(&mut self, parent: u32, name: &str, value: BigInt) -> u32 {
self.create_with_parent(
Some(parent),
Node {
name: Some(name.to_string()),
source: None,
content: NodeContent::RecEnumItem { value: value },
},
)
}
pub fn create_tuple(&mut self, parent: Option<u32>) -> u32 {
self.create_with_parent(parent, Node::new_anonymous(NodeContent::RecTuple))
}
pub fn create_tuple_member(&mut self, parent: u32, ty: u32) -> u32 {
self.create_with_parent(
Some(parent),
Node::new_anonymous(NodeContent::RecTupleMember {
tid: RecTypeId::Id(ty),
}),
)
}
pub fn parse_recipe_string(&mut self, rec: &str) -> Result<u32, LoadError> {
let rec = rec.trim_start().trim_end();
let mut pairs = MyParser::parse(Rule::rec_type_anonymous, rec).unwrap();
let pair = pairs.next().unwrap();
let span = pair.as_span();
assert!(pairs.next().is_none());
if span.end() != rec.len() {
return Err(LoadError::RecipeParseError);
}
Ok(self.parse_rec_type(Rc::new(rec.to_string()), pair))
}
pub fn parse_struct_recipe_string(&mut self, rec: &str) -> Result<u32, LoadError> {
let rec = rec.trim_start().trim_end();
let mut pairs = MyParser::parse(Rule::file_rec, rec).unwrap();
let pair = pairs.next().unwrap();
let span = pair.as_span();
assert!(pairs.next().is_none());
if span.end() != rec.len() {
return Err(LoadError::RecipeParseError);
}
let nid = self.create(Node {
name: None,
source: None,
content: NodeContent::RecStruct,
});
self.parse_rec_struct_declarations(Rc::new(rec.to_string()), pair.into_inner(), nid);
Ok(nid)
}
pub fn parse_dat_value_string(&mut self, dat: &str) -> Result<u32, LoadError> {
let dat = dat.trim_start().trim_end();
let mut pairs = MyParser::parse(Rule::dat_value, dat).unwrap();
let pair = pairs.next().unwrap();
let span = pair.as_span();
assert!(pairs.next().is_none());
if span.end() != dat.len() {
Err(LoadError::DataParseError)
} else {
Ok(self.parse_dat_value(Rc::new(dat.to_string()), pair))
}
}
pub fn parse_dat_map_string(&mut self, dat: &str) -> Result<u32, LoadError> {
let dat = dat.trim_start().trim_end();
let mut pairs = MyParser::parse(Rule::file_dat, dat).unwrap();
let pair = pairs.next().unwrap();
let span = pair.as_span();
assert!(pairs.next().is_none());
if span.end() != dat.len() {
Err(LoadError::DataParseError)
} else {
Ok(self.parse_dat_map(Rc::new(dat.to_string()), pair))
}
}
fn parse_rec_type(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
match pair.as_rule() {
Rule::rec_type_inst => self.parse_rec_type_inst(source, pair),
Rule::rec_struct => self.parse_rec_struct(source, pair),
Rule::rec_struct_anonymous => self.parse_rec_struct(source, pair),
Rule::rec_enum => self.parse_rec_enum(source, pair),
Rule::rec_enum_anonymous => self.parse_rec_enum(source, pair),
Rule::rec_tuple => self.parse_rec_tuple(source, pair),
_ => {
panic!();
}
}
}
fn parse_rec_type_inst(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let span = pair.as_span();
let mut inner = pair.into_inner();
let nid = self.create(Node {
name: None,
source: Some(SourceLocation::new_from_span(source.clone(), span)),
content: NodeContent::RecTypeInst {
tid: RecTypeId::Path(inner.next().unwrap().as_str().to_string()),
},
});
if let Some(pair) = inner.next() {
for pair in pair.into_inner() {
let generic_argument_nid = self.parse_rec_type_inst(source.clone(), pair);
self.child(nid, generic_argument_nid);
}
}
assert_eq!(inner.next(), None);
nid
}
fn parse_rec_struct(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let span = pair.as_span().clone();
let mut inner = pair.into_inner();
let mut pair = inner.next().unwrap();
let mut name = None;
if pair.as_rule() == Rule::identifier {
name = Some(pair.as_str().to_string());
pair = inner.next().unwrap();
};
let id = self.create(Node {
name: name,
source: Some(SourceLocation::new_from_span(source.clone(), span)),
content: NodeContent::RecStruct,
});
if pair.as_rule() == Rule::rec_generic_decl {
self.parse_rec_generic_decl(source.clone(), id, pair);
pair = inner.next().unwrap();
}
self.parse_rec_struct_declarations(source, pair.into_inner(), id);
assert!(inner.next().is_none());
id
}
fn parse_rec_generic_decl(&mut self, source: Rc<String>, struct_nid: u32, pair: Pair<Rule>) {
let mut arg_index = 0;
for pair in pair.into_inner() {
self.create_with_parent(
Some(struct_nid),
Node {
name: Some(pair.as_str().to_string()),
source: Some(SourceLocation::new_from_span(
source.clone(),
pair.as_span(),
)),
content: NodeContent::RecGeneric { index: arg_index },
},
);
arg_index = arg_index.checked_add(1).unwrap();
}
}
fn parse_rec_tuple(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let tuple_nid = self.create(Node {
name: None,
source: Some(SourceLocation::new_from_span(
source.clone(),
pair.as_span(),
)),
content: NodeContent::RecTuple,
});
for pair in pair.into_inner() {
self.create_with_parent(
Some(tuple_nid),
Node {
name: None,
source: Some(SourceLocation::new_from_span(
source.clone(),
pair.as_span(),
)),
content: NodeContent::RecTupleMember {
tid: RecTypeId::Path(pair.as_str().to_string()),
},
},
);
}
tuple_nid
}
fn parse_rec_struct_declarations(
&mut self,
source: Rc<String>,
inner: Pairs<Rule>,
parent: u32,
) {
for b in inner {
let child = self.parse_rec_struct_declaration(source.clone(), b);
self.child(parent, child);
}
}
fn parse_rec_struct_declaration(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let span = pair.as_span();
match pair.as_rule() {
Rule::member => {
let mut inner = pair.into_inner();
let struct_nid = self.create(Node {
name: Some(inner.next().unwrap().as_str().to_string()),
source: Some(SourceLocation::new_from_span(source.clone(), span)),
content: NodeContent::RecStructMember,
});
let type_pair = inner.next().unwrap();
let type_nid = self.parse_rec_type(source, type_pair);
self.child(struct_nid, type_nid);
struct_nid
}
Rule::rec_struct => self.parse_rec_struct(source, pair),
Rule::rec_enum => self.parse_rec_enum(source, pair),
_ => {
panic!()
}
}
}
fn parse_rec_enum(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let span = pair.as_span();
let mut inner = pair.into_inner();
let mut pair = inner.next().unwrap();
let name = if pair.as_rule() == Rule::identifier {
let res = Some(pair.as_str().to_string());
pair = inner.next().unwrap();
res
} else {
None
};
let enum_nid = self.create(Node {
name: name,
source: Some(SourceLocation::new_from_span(source.clone(), span)),
content: NodeContent::RecEnum {
key_type: RecTypeId::Path("i32".to_string()),
},
});
for pair in pair.into_inner() {
let span = pair.as_span();
let mut inner = pair.into_inner();
let name = inner.next().unwrap().as_str().to_string();
let enum_item_nid = self.create_with_parent(
Some(enum_nid),
Node {
name: Some(name),
source: Some(SourceLocation::new_from_span(source.clone(), span.clone())),
content: NodeContent::RecEnumItem {
value: BigInt::from(0),
},
},
);
if let Some(pair) = inner.next() {
match pair.as_rule() {
Rule::rec_enum_tuple => {
let tuple_nid = self.parse_rec_tuple(source.clone(), pair);
self.child(enum_item_nid, tuple_nid);
}
Rule::rec_struct_declarations => {
let struct_nid = self.create_with_parent(
Some(enum_item_nid),
Node {
name: None,
source: Some(SourceLocation::new_from_span(source.clone(), span)),
content: NodeContent::RecStruct,
},
);
self.parse_rec_struct_declarations(
source.clone(),
pair.into_inner(),
struct_nid,
);
}
_ => {
panic!()
} }
};
assert!(inner.next().is_none());
}
assert!(inner.next().is_none());
enum_nid
}
fn parse_dat_map(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let span = pair.as_span();
let node = self.create(Node {
name: None,
source: Some(SourceLocation::new_from_span(source.clone(), span)),
content: NodeContent::DatMap,
});
for p in pair.into_inner() {
let child = self.parse_dat_map_assignment(source.clone(), p);
self.child(node, child);
}
node
}
fn parse_dat_map_assignment(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let span = pair.as_span();
let mut inner = pair.into_inner();
let nid_key = self.parse_dat_value(source.clone(), inner.next().unwrap());
let nid_value = self.parse_dat_value(source.clone(), inner.next().unwrap());
let nid = self.create(Node {
name: None,
source: Some(SourceLocation::new_from_span(source, span)),
content: NodeContent::DatMapAssignment,
});
assert_eq!(inner.next(), None);
self.child(nid, nid_key);
self.child(nid, nid_value);
nid
}
fn parse_dat_tuple_or_list(
&mut self,
source: Rc<String>,
pair: Pair<Rule>,
content: NodeContent,
) -> u32 {
if let NodeContent::DatTuple | NodeContent::DatList = content {
} else {
panic!();
}
let node = self.create(Node {
name: None,
source: Some(SourceLocation::new_from_span(
source.clone(),
pair.as_span(),
)),
content: content,
});
for p in pair.into_inner() {
let child = self.parse_dat_value(source.clone(), p);
self.child(node, child)
}
node
}
fn parse_dat_enum(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
let span = pair.as_span();
let mut inner = pair.into_inner();
let node = self.create(Node {
name: Some(inner.next().unwrap().as_str().to_string()),
source: Some(SourceLocation::new_from_span(source.clone(), span)),
content: NodeContent::DatEnum,
});
if let Some(pair) = inner.next() {
let child_nid = match pair.as_rule() {
Rule::dat_tuple => {
self.parse_dat_tuple_or_list(source.clone(), pair, NodeContent::DatTuple)
}
Rule::dat_map => self.parse_dat_map(source, pair),
_ => panic!(),
};
self.child(node, child_nid);
}
node
}
fn parse_dat_primitive_value(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
self.create(Node {
name: None,
source: Some(SourceLocation::new_from_span(source, pair.as_span())),
content: match pair.as_rule() {
Rule::int => NodeContent::DatInt {
repr: pair.as_str().to_string(),
},
Rule::float => NodeContent::DatFloat {
repr: pair.as_str().to_string(),
},
_ => panic!(),
},
})
}
fn parse_dat_value(&mut self, source: Rc<String>, pair: Pair<Rule>) -> u32 {
match pair.as_rule() {
Rule::int | Rule::float => self.parse_dat_primitive_value(source, pair),
Rule::dat_map => self.parse_dat_map(source, pair),
Rule::dat_enum => self.parse_dat_enum(source, pair),
Rule::dat_tuple => self.parse_dat_tuple_or_list(source, pair, NodeContent::DatTuple),
Rule::dat_list => self.parse_dat_tuple_or_list(source, pair, NodeContent::DatList),
_ => panic!(),
}
}
fn number_of_generic_types(&self, nid: u32) -> usize {
let node = self.get_item(nid);
match node.value.content {
NodeContent::RecStruct | NodeContent::RecList | NodeContent::RecMap => node
.children()
.iter()
.filter(|&&nid| {
if let NodeContent::RecGeneric { .. } = self.get(nid).content {
true
} else {
false
}
})
.count(),
_ => 0,
}
}
fn node_path(&self, id: u32) -> String {
let node = self.get_item(id);
match *node.parent() {
Some(parent_id) => {
match self.get_item(parent_id).parent {
Some(_) => {
self.node_path(parent_id)
+ &"::".to_string()
+ &node.value.name_or_anonymous()
}
None => node.value.name_or_anonymous(),
}
}
None => node.value.name_or_anonymous(),
}
}
fn populate_natives(&mut self, node: u32) {
let natives = [
(
"i8",
NodeContent::RecInt {
bit_size: 8,
signed: true,
},
),
(
"u8",
NodeContent::RecInt {
bit_size: 8,
signed: false,
},
),
(
"i16",
NodeContent::RecInt {
bit_size: 16,
signed: true,
},
),
(
"u16",
NodeContent::RecInt {
bit_size: 16,
signed: false,
},
),
(
"i32",
NodeContent::RecInt {
bit_size: 32,
signed: true,
},
),
(
"u32",
NodeContent::RecInt {
bit_size: 32,
signed: false,
},
),
(
"i64",
NodeContent::RecInt {
bit_size: 64,
signed: true,
},
),
(
"u64",
NodeContent::RecInt {
bit_size: 64,
signed: false,
},
),
("f32", NodeContent::RecFloat { size: 32 }),
("f64", NodeContent::RecFloat { size: 64 }),
];
for native in natives.iter() {
self.create_with_parent(
Some(node),
Node {
name: Some(native.0.to_string()),
source: None,
content: native.1.clone(),
},
);
}
let node_bool_enum = bool::recipe(self);
self.child(node, node_bool_enum);
self.create_generic_type(Some(node), "List", NodeContent::RecList, 1);
self.create_generic_type(Some(node), "Map", NodeContent::RecMap, 2);
}
}
fn int_bounds(bit_size: u32, signed: bool) -> (BigInt, BigInt) {
let max: BigInt = BigInt::from(2).pow(if signed { bit_size - 1 } else { bit_size }) - 1;
(
if signed {
-max.clone() - 1
} else {
BigInt::from(0)
},
max,
)
}
enum WriteIntCheckBoundsError {
IOError(std::io::Error),
OutOfBounds,
}
impl From<std::io::Error> for WriteIntCheckBoundsError {
fn from(e: std::io::Error) -> Self {
WriteIntCheckBoundsError::IOError(e)
}
}
fn write_int_check_bounds(
wr: &mut dyn std::io::Write,
bit_size: u32,
signed: bool,
value: &BigInt,
) -> Result<(), WriteIntCheckBoundsError> {
let (min, max) = int_bounds(bit_size, signed);
if (*value <= max) && (*value >= min) {
let bytes = if signed {
let mut bytes = value.to_signed_bytes_le();
let negative = value.sign() == Sign::Minus;
while bytes.len() < (bit_size / 8) as usize {
bytes.push(if negative { 0xff } else { 0 });
}
bytes
} else {
let mut bytes = value.to_bytes_le().1;
while bytes.len() < (bit_size / 8) as usize {
bytes.push(0);
}
bytes
};
wr.write(bytes.as_slice())?;
Ok(())
} else {
Err(WriteIntCheckBoundsError::OutOfBounds)
}
}
struct Compiler<'a> {
tree: NodeTree,
io: &'a mut dyn std::io::Write,
errors: Vec<CompilationError>,
generic_stack: Vec<Vec<u32>>,
}
impl Compiler<'_> {
pub fn new<'a>(io: &'a mut dyn std::io::Write) -> Compiler<'a> {
Compiler {
tree: NodeTree::new(),
io: io,
errors: Vec::new(),
generic_stack: Vec::new(),
}
}
fn error(&mut self, err: CompilationError) {
self.errors.push(err);
}
fn resolve_types(&mut self, nid: u32) {
let node = self.tree.get(nid);
match node.content.clone() {
NodeContent::RecInt { .. }
| NodeContent::RecFloat { .. }
| NodeContent::RecList
| NodeContent::RecMap => {}
NodeContent::RecStruct | NodeContent::RecTuple | NodeContent::RecStructMember => {
for child_id in self.tree.children(nid).clone() {
self.resolve_types(child_id);
}
}
NodeContent::RecTupleMember { tid } => {
let resolved_tid = self.resolve_type_id(tid.clone(), nid);
if let NodeContent::RecTupleMember { tid } = &mut self.tree.get_mut(nid).content {
*tid = resolved_tid;
} else {
panic!();
}
}
NodeContent::RecEnum { key_type: tid } => {
let resolved_tid = self.resolve_type_id(tid.clone(), nid);
if let NodeContent::RecEnum { key_type: tid } = &mut self.tree.get_mut(nid).content
{
*tid = resolved_tid.clone();
} else {
panic!();
}
if let RecTypeId::Id(rec_type_id) = resolved_tid {
let rec_type = self.tree.get(rec_type_id);
if let NodeContent::RecInt { bit_size, signed } = rec_type.content {
let mut next_value = BigInt::from(0);
for child_id in self.tree.children(nid).clone() {
let child = self.tree.get_mut(child_id);
if let NodeContent::RecEnumItem { value } = &mut child.content {
let (min, max) = int_bounds(bit_size, signed);
if (next_value >= min) && (next_value <= max) {
*value = next_value.clone();
next_value = next_value + 1;
} else {
self.error(CompilationError::EnumValueOutOfBounds(child_id));
}
if let Some(data_type_node) =
self.tree.get_item(child_id).unique_child_or_none()
{
self.resolve_types(data_type_node);
}
} else {
panic!();
}
}
} else {
self.error(CompilationError::EnumTypeIsNotInt(rec_type_id));
}
}
}
NodeContent::RecTypeInst { tid } => {
let resolved_tid = self.resolve_type_id(tid.clone(), nid);
if let NodeContent::RecTypeInst { tid } = &mut self.tree.get_mut(nid).content {
*tid = resolved_tid.clone();
} else {
panic!();
}
let children = self.tree.children(nid).clone();
for child_id in children.clone() {
self.resolve_types(child_id);
}
if let RecTypeId::Id(resolved_type_nid) = resolved_tid {
let expected_arg_count = self.tree.number_of_generic_types(resolved_type_nid);
let current_arg_count = children.len();
if current_arg_count != expected_arg_count {
self.error(CompilationError::GenericArgCountMismatch {
nid: nid,
expected: expected_arg_count,
current: current_arg_count,
});
}
}
}
NodeContent::RecEnumItem { .. }
| NodeContent::RecGeneric { .. }
| NodeContent::DatMap
| NodeContent::DatTuple
| NodeContent::DatList
| NodeContent::DatEnum
| NodeContent::DatMapAssignment
| NodeContent::DatTupleMember
| NodeContent::DatInt { .. }
| NodeContent::DatFloat { .. } => {}
}
}
fn resolve_type_id(&mut self, tid: RecTypeId, nid: u32) -> RecTypeId {
match &tid {
RecTypeId::Path(path) => {
if let Some(id) = self.resolve_typename(nid, &path) {
RecTypeId::Id(id)
} else {
self.error(CompilationError::UnresolvedType {
path: path.clone(),
node: nid,
});
tid.clone()
}
}
RecTypeId::Id(_) => tid.clone(),
}
}
fn resolve_typename(&self, scope: u32, typename: &String) -> Option<u32> {
let scope_node = self.tree.get_item(scope);
match scope_node.value.content {
NodeContent::RecStructMember { .. } | NodeContent::RecTupleMember { .. } => {
match scope_node.parent() {
Some(id) => self.resolve_typename(*id, typename),
None => None,
}
}
NodeContent::RecStruct => {
match self
.tree
.children(scope)
.iter()
.find(|&&a| self.tree.get(a).name == Some(typename.clone()))
.copied()
{
Some(node) => Some(node),
None => match scope_node.parent() {
Some(id) => self.resolve_typename(*id, typename),
None => None,
},
}
}
NodeContent::RecTuple
| NodeContent::RecTypeInst { .. }
| NodeContent::RecEnumItem { .. } => {
self.resolve_typename(scope_node.parent().unwrap(), typename)
}
NodeContent::RecEnum { .. } => match scope_node.parent() {
Some(id) => self.resolve_typename(*id, typename),
None => None,
},
NodeContent::RecInt { .. }
| NodeContent::RecFloat { .. }
| NodeContent::RecList
| NodeContent::RecMap
| NodeContent::RecGeneric { .. } => None,
NodeContent::DatMap
| NodeContent::DatMapAssignment
| NodeContent::DatTupleMember
| NodeContent::DatInt { .. }
| NodeContent::DatFloat { .. }
| NodeContent::DatEnum
| NodeContent::DatTuple
| NodeContent::DatList => {
panic!()
}
}
}
fn write(&mut self, rec_node: u32, dat_node: u32) -> WriteResult {
match self.tree.get(rec_node).content.clone() {
NodeContent::RecInt { bit_size, signed } => {
self.write_int(rec_node, dat_node, bit_size, signed);
}
NodeContent::RecFloat { size } => {
self.write_float(dat_node, size)?;
}
NodeContent::RecList => {
self.write_list(rec_node, dat_node)?;
}
NodeContent::RecMap => {
self.write_map(rec_node, dat_node)?;
}
NodeContent::RecStruct => {
self.write_struct(rec_node, dat_node)?;
}
NodeContent::RecTuple => {
self.write_tuple(rec_node, dat_node)?
}
NodeContent::RecStructMember => {
let type_nid = self.tree.get_item(rec_node).unique_child();
self.write_struct_member(rec_node, dat_node, type_nid)?;
}
NodeContent::RecEnum { key_type: tid } => {
self.write_enum(rec_node, dat_node, tid.unwrap_id())?;
}
NodeContent::RecTypeInst { tid } => {
let may_be_generic = self.tree.get(tid.unwrap_id()).content.may_be_generic();
if may_be_generic {
let generics = self.tree.children(rec_node).clone();
self.generic_stack.push(generics);
}
let write_result = self.write(tid.unwrap_id(), dat_node);
if may_be_generic {
self.generic_stack.pop();
}
write_result?;
}
NodeContent::RecGeneric { index } => {
let current_generics = self.generic_stack.last().unwrap().clone();
let type_nid = current_generics.get(index as usize).unwrap();
self.write(*type_nid, dat_node)?;
}
NodeContent::RecEnumItem { .. }
| NodeContent::RecTupleMember { .. }
| NodeContent::DatMap
| NodeContent::DatMapAssignment
| NodeContent::DatTupleMember
| NodeContent::DatInt { .. }
| NodeContent::DatFloat { .. }
| NodeContent::DatEnum
| NodeContent::DatTuple
| NodeContent::DatList => {
panic!();
}
}
Ok(())
}
fn write_int(&mut self, _rec_nid: u32, dat_nid: u32, bit_size: u32, signed: bool) {
if let NodeContent::DatInt { repr } = &self.tree.get(dat_nid).content {
let int = BigInt::parse_bytes(repr.as_bytes(), 10).unwrap();
match write_int_check_bounds(&mut self.io, bit_size, signed, &int) {
Ok(_) => {}
Err(_) => {
self.error(CompilationError::ValueOutOfBounds(dat_nid));
}
}
} else {
self.error(CompilationError::ExpectedDatInt(dat_nid));
}
}
fn write_float(&mut self, dat_nid: u32, bit_size: u32) -> WriteResult {
if let NodeContent::DatInt { repr } | NodeContent::DatFloat { repr } =
&self.tree.get(dat_nid).content
{
match bit_size {
32 => {
if let Ok(f) = repr.parse::<f32>() {
self.io.write(&f.to_le_bytes())?;
Ok(())
} else {
panic!();
}
}
64 => {
if let Ok(f) = repr.parse::<f64>() {
self.io.write(&f.to_le_bytes())?;
Ok(())
} else {
panic!();
}
}
_ => {
panic!();
}
}
} else {
self.error(CompilationError::ExpectedDatFloat(dat_nid));
Ok(())
}
}
fn write_list(&mut self, rec_nid: u32, dat_nid: u32) -> WriteResult {
let item_type_nid = self.tree.unique_child(rec_nid);
let items = self.tree.children(dat_nid).clone();
let bytes = items.len().to_le_bytes();
self.io.write(&bytes)?;
for &item_nid in items.iter() {
self.write(item_type_nid, item_nid)?
}
Ok(())
}
fn write_map(&mut self, rec_nid: u32, dat_nid: u32) -> WriteResult {
let generic_args = self.tree.children(rec_nid).clone();
assert_eq!(generic_args.len(), 2);
let items = self.tree.children(dat_nid).clone();
let bytes = items.len().to_le_bytes();
self.io.write(&bytes)?;
for &item_nid in items.iter() {
let item_children = self.tree.children(item_nid).clone();
assert_eq!(item_children.len(), 2);
for i in 0..2 {
self.write(generic_args[i], item_children[i])?
}
}
Ok(())
}
fn write_struct(&mut self, rec_node: u32, dat_node: u32) -> WriteResult {
let dat_node_item = self.tree.get_item(dat_node);
if let NodeContent::DatMap = dat_node_item.value.content {
let mut error = false;
for nid_child in dat_node_item.children().clone() {
let child = self.tree.get_item(nid_child);
if let NodeContent::DatMapAssignment = child.value.content {
let children = child.children();
assert_eq!(children.len(), 2);
let key = self.tree.get_item(children[0]);
if key.children().len() != 0 {
self.error(CompilationError::ExpectedDatIdentifier(nid_child));
error = true;
}
} else {
self.error(CompilationError::ExpectedDatIdentifier(nid_child));
error = true;
}
}
if error {
return Ok(());
}
for &child in self.tree.children(rec_node).clone().iter() {
match self.tree.get(child).content {
NodeContent::RecStructMember { .. } => self.write(child, dat_node)?,
NodeContent::RecEnum { .. }
| NodeContent::RecGeneric { .. }
| NodeContent::RecStruct { .. }
| NodeContent::RecTuple
| NodeContent::RecInt { .. }
| NodeContent::RecFloat { .. }
| NodeContent::RecList
| NodeContent::RecMap
| NodeContent::RecTypeInst { .. } => {}
NodeContent::RecEnumItem { .. }
| NodeContent::RecTupleMember { .. }
| NodeContent::DatMap
| NodeContent::DatMapAssignment
| NodeContent::DatTupleMember
| NodeContent::DatInt { .. }
| NodeContent::DatFloat { .. }
| NodeContent::DatEnum
| NodeContent::DatTuple
| NodeContent::DatList => {
panic!()
}
}
}
Ok(())
} else {
self.errors.push(CompilationError::DataNotStruct(dat_node));
Ok(())
}
}
fn write_struct_member(&mut self, rec_nid: u32, dat_nid: u32, rec_type_id: u32) -> WriteResult {
let dat_node_item = self.tree.get_item(dat_nid);
if let NodeContent::DatMap = dat_node_item.value.content {
let name = self.tree.get(rec_nid).name.clone();
let dat_node_children = dat_node_item.children.clone();
let candidates: Vec<u32> = dat_node_children
.iter()
.filter(|&&a| {
let children = self.tree.get_item(a).children();
assert_eq!(children.len(), 2);
self.tree.get(children[0]).name == name
})
.cloned()
.collect();
let mut iter = candidates.iter();
if let Some(member) = iter.next() {
let nid_dat = self.tree.get_item(*member).children[1];
self.write(rec_type_id, nid_dat)?;
while let Some(member) = iter.next() {
self.error(CompilationError::RedefinedValue(*member));
}
} else {
self.error(CompilationError::UndefinedValue(rec_nid));
}
} else {
self.error(CompilationError::ExpectedDatStruct(dat_nid));
}
Ok(())
}
fn write_tuple(&mut self, rec_node: u32, dat_node: u32) -> WriteResult {
let tuple_children = self.tree.children(rec_node).clone();
let data_children = self.tree.children(dat_node).clone();
if tuple_children.len() != data_children.len() {
self.error(CompilationError::TupleSizeMismatch {
node_tuple: rec_node,
node_data: dat_node,
});
Ok(())
} else {
for (t, d) in tuple_children.iter().zip(data_children.iter()) {
if let NodeContent::RecTupleMember { tid } = &self.tree.get(*t).content.clone() {
self.write(tid.unwrap_id(), *d)?;
} else {
panic!();
}
}
Ok(())
}
}
fn write_enum(&mut self, rec_nid: u32, dat_nid: u32, rec_type_id: u32) -> WriteResult {
let dat_node = self.tree.get(dat_nid);
if let NodeContent::DatEnum = dat_node.content {
match self.tree.children(rec_nid).iter().find(|&&a| {
self.tree.get(a).name.clone().unwrap() == dat_node.name.clone().unwrap()
}) {
Some(nid) => {
if let NodeContent::RecInt { bit_size, signed } =
self.tree.get(rec_type_id).content
{
if let NodeContent::RecEnumItem { value } = &self.tree.get(*nid).content {
match write_int_check_bounds(&mut self.io, bit_size, signed, &value) {
Ok(()) => {}
Err(WriteIntCheckBoundsError::OutOfBounds) => panic!(), Err(WriteIntCheckBoundsError::IOError(e)) => return Err(e),
}
if let Some(enum_item_data_type_nid) =
self.tree.get_item(*nid).unique_child_or_none()
{
if let Some(enum_assocoiated_data_nid) =
self.tree.get_item(dat_nid).unique_child_or_none()
{
self.write(enum_item_data_type_nid, enum_assocoiated_data_nid)?;
} else {
self.error(CompilationError::EnumUndefinedData {
data_nid: dat_nid,
});
}
}
Ok(())
} else {
panic!();
}
} else {
panic!();
}
}
None => {
self.error(CompilationError::EnumUndefinedName {
node_enum: rec_nid,
node_name: dat_nid,
});
Ok(())
}
}
} else {
panic!();
}
}
}
fn print_errors(tree: &NodeTree, errors: &Vec<CompilationError>) {
for error in errors {
match error {
CompilationError::DataNotStruct(node) => {
println!("Error: data {} must be a structure", tree.node_path(*node));
}
CompilationError::EnumTypeIsNotInt(node) => {
println!(
"Error: enumeration type {} is not an integer",
tree.node_path(*node)
);
}
CompilationError::EnumValueOutOfBounds(node) => {
println!(
"Error: enumeration value {} out of bounds",
tree.node_path(*node)
);
}
CompilationError::EnumUndefinedName {
node_enum,
node_name,
} => {
println!(
"Error: invalid name in {} for enumeration {}",
tree.node_path(*node_enum),
tree.node_path(*node_name)
);
}
CompilationError::EnumUndefinedData { data_nid } => {
println!(
"Error: enumeration data not defined for {}",
tree.node_path(*data_nid)
);
}
CompilationError::ExpectedDatFloat(node) => {
println!("Error: expected float for {}", tree.node_path(*node));
}
CompilationError::ExpectedDatInt(node) => {
println!("Error: expected integer for {}", tree.node_path(*node));
}
CompilationError::ExpectedDatStruct(node) => {
println!(
"Error: expected structure for {}={}",
*node,
tree.node_path(*node)
);
}
CompilationError::ExpectedDatIdentifier(nid) => {
println!(
"Error: expected identifier for structure assignement at {}",
tree.node_path(*nid)
);
}
CompilationError::GenericArgCountMismatch {
nid,
expected,
current,
} => {
println!(
"Error: invalid generic type argument count for {}, expected {}, got {}",
tree.node_path(*nid),
expected,
current
);
}
CompilationError::IOError(e) => {
println!("Error: {}", e);
}
CompilationError::RedefinedValue(node) => {
println!("Error: {} already defined", tree.node_path(*node));
}
CompilationError::TupleSizeMismatch {
node_tuple,
node_data,
} => {
println!(
"Error: incorrect number of elements in {} for tuple {}",
tree.node_path(*node_data),
tree.node_path(*node_tuple)
);
}
CompilationError::UndefinedValue(node) => {
println!("Error: {} is undefined", tree.node_path(*node));
}
CompilationError::UnresolvedType { path, node } => {
println!(
"Error: unresolved typename \"{}\" for {}",
path,
tree.node_path(*node)
);
}
CompilationError::ValueOutOfBounds(node) => {
println!("Error: value {} out of bounds", tree.node_path(*node));
}
}
}
}
#[derive(Debug)]
pub enum LoadError {
CompilationErrors,
InvalidRecExtension,
InvalidDatExtension,
RecFileAccess,
DatFileAccess,
IOError(std::io::Error),
RecipeParseError,
DataParseError,
}
impl From<std::io::Error> for LoadError {
fn from(e: std::io::Error) -> Self {
LoadError::IOError(e)
}
}
fn is_compilation_required(
rec_path: Option<&str>,
dat_path: &str,
bin_path: &str,
) -> Result<bool, LoadError> {
match std::fs::metadata(bin_path) {
Ok(bin_metadata) => match std::fs::metadata(dat_path) {
Ok(dat_metadata) => {
let bin_modified = bin_metadata.modified().unwrap();
if let Some(rec_path) = rec_path {
match std::fs::metadata(rec_path) {
Ok(rec_metadata) => Ok((bin_modified > dat_metadata.modified().unwrap())
|| (bin_modified > rec_metadata.modified().unwrap())),
Err(_) => Err(LoadError::RecFileAccess),
}
} else {
Ok(bin_modified > dat_metadata.modified().unwrap())
}
}
Err(_) => Err(LoadError::DatFileAccess),
},
Err(_) => Ok(true),
}
}
pub fn write_from_string_with_recipe<'a>(
out: &'a mut dyn std::io::Write,
rec: &str,
dat: &str,
) -> Result<(), LoadError> {
let mut compiler = Compiler::new(out);
let node_root = compiler.tree.create_root_struct();
compiler.tree.populate_natives(node_root);
let node_rec = compiler.tree.parse_recipe_string(rec).unwrap();
compiler.tree.child(node_root, node_rec);
compiler.resolve_types(node_rec);
if compiler.errors.len() > 0 {
return Err(LoadError::CompilationErrors);
}
let node_dat = match compiler.tree.get(node_rec).content {
NodeContent::RecStruct => compiler.tree.parse_dat_map_string(dat).unwrap(),
_ => compiler.tree.parse_dat_value_string(dat).unwrap(),
};
compiler.write(node_rec, node_dat)?;
Ok(())
}
pub fn load_from_file<T>(path: &str) -> Result<T, LoadError>
where
T: DeserializeOwned + Recipe,
{
let path = Path::new(path);
if path.extension() != Some(OsStr::new("dat")) {
return Err(LoadError::InvalidDatExtension);
}
let path_bin = path.with_extension("bin");
if is_compilation_required(None, path.to_str().unwrap(), path_bin.to_str().unwrap())? {
let mut dat = String::new();
File::open(path).unwrap().read_to_string(&mut dat).unwrap();
let mut file = File::create(path_bin.clone()).unwrap();
let mut compiler = Compiler::new(&mut file);
let nid_rec = T::recipe(&mut compiler.tree);
let nid_dat = compiler.tree.parse_dat_map_string(dat.as_str()).unwrap();
compiler.resolve_types(nid_rec);
compiler.write(nid_rec, nid_dat).unwrap();
}
let file = File::open(path_bin).unwrap();
return Ok(bincode::deserialize_from(file).unwrap());
}
pub fn load_from_string<T>(dat: &str) -> Result<T, LoadError>
where
T: Recipe + DeserializeOwned,
{
let mut bin = Vec::<u8>::new();
let mut compiler = Compiler::new(&mut bin);
let nid_rec = T::recipe(&mut compiler.tree);
let nid_dat = match compiler.tree.get(nid_rec).content {
NodeContent::RecStruct => compiler.tree.parse_dat_map_string(dat)?,
_ => compiler.tree.parse_dat_value_string(dat)?,
};
compiler.resolve_types(nid_rec);
compiler.write(nid_rec, nid_dat).unwrap();
Ok(bincode::deserialize_from(&bin[..]).unwrap())
}
pub fn load_from_file_with_recipe<T>(rec_path: &str, dat_path: &str) -> Result<T, LoadError>
where
T: DeserializeOwned,
{
let rec_path = Path::new(rec_path);
if rec_path.extension() != Some(OsStr::new("rec")) {
return Err(LoadError::InvalidRecExtension);
}
let dat_path = Path::new(dat_path);
if dat_path.extension() != Some(OsStr::new("dat")) {
return Err(LoadError::InvalidDatExtension);
}
let bin_path = dat_path.with_extension("bin");
match is_compilation_required(
Some(rec_path.to_str().unwrap()),
dat_path.to_str().unwrap(),
bin_path.to_str().unwrap(),
) {
Ok(true) => {
let mut rec = String::new();
File::open(rec_path)
.unwrap()
.read_to_string(&mut rec)
.unwrap();
let mut dat = String::new();
File::open(dat_path)
.unwrap()
.read_to_string(&mut dat)
.unwrap();
let mut file = File::create(bin_path.clone()).unwrap();
write_from_string_with_recipe(&mut file, &rec, &dat)?;
}
Ok(false) => {}
Err(e) => {
return Err(e);
}
}
let file = File::open(bin_path).unwrap();
Ok(bincode::deserialize_from(file).unwrap())
}