use std::path::PathBuf;
#[cfg(feature = "compiler-plugin")]
use serde::{Deserialize, Serialize};
use property::Property;
mod utils;
#[derive(Debug, Default, Property)]
pub(crate) struct Ast {
syntax_version: Option<SyntaxVersion>,
namespace: String,
imports: Vec<ImportStmt>,
decls: Vec<TopDecl>,
}
impl Default for SyntaxVersion {
fn default() -> Self {
Self { version: 1 }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Property)]
#[property(get(public))]
#[cfg_attr(
feature = "compiler-plugin",
derive(Deserialize, Serialize),
serde(deny_unknown_fields)
)]
pub struct SyntaxVersion {
version: usize,
}
#[derive(Debug, Clone, Property)]
pub(crate) struct ImportStmt {
name: String,
paths: Vec<String>,
path_supers: usize,
imported_base: PathBuf,
imported_depth: usize,
}
#[derive(Debug)]
pub(crate) enum TopDecl {
Option_(OptionDecl),
Union(UnionDecl),
Array(ArrayDecl),
Struct(StructDecl),
Vector(VectorDecl),
Table(TableDecl),
}
#[derive(Debug, Property)]
pub(crate) struct OptionDecl {
name: String,
item: ItemDecl,
imported_depth: usize,
}
#[derive(Debug, Property)]
pub(crate) struct UnionDecl {
name: String,
items: Vec<CustomUnionItemDecl>,
imported_depth: usize,
}
#[derive(Debug, Property)]
pub(crate) struct ArrayDecl {
name: String,
item: ItemDecl,
item_count: usize,
imported_depth: usize,
}
#[derive(Debug, Property)]
pub(crate) struct StructDecl {
name: String,
fields: Vec<FieldDecl>,
imported_depth: usize,
}
#[derive(Debug, Property)]
pub(crate) struct VectorDecl {
name: String,
item: ItemDecl,
imported_depth: usize,
}
#[derive(Debug, Property)]
pub(crate) struct TableDecl {
name: String,
fields: Vec<FieldDecl>,
imported_depth: usize,
}
#[derive(Debug, Property)]
pub(crate) struct ItemDecl {
typ: String,
}
#[derive(Debug, Property)]
pub(crate) struct CustomUnionItemDecl {
typ: String,
id: usize,
}
#[derive(Debug, Property)]
pub(crate) struct FieldDecl {
name: String,
typ: String,
}
impl Ast {
pub(crate) fn add_import(&mut self, stmt: ImportStmt) {
self.imports.push(stmt);
}
pub(crate) fn add_decl(&mut self, decl: impl Into<TopDecl>) {
self.decls.push(decl.into());
}
}
impl TopDecl {
pub(crate) fn name(&self) -> &str {
match self {
TopDecl::Option_(inner) => inner.name(),
TopDecl::Union(inner) => inner.name(),
TopDecl::Array(inner) => inner.name(),
TopDecl::Struct(inner) => inner.name(),
TopDecl::Vector(inner) => inner.name(),
TopDecl::Table(inner) => inner.name(),
}
}
}
macro_rules! impl_into_top_decl_for {
($item:ident, $decl:ident) => {
impl From<$decl> for TopDecl {
fn from(decl: $decl) -> Self {
TopDecl::$item(decl)
}
}
};
}
impl_into_top_decl_for!(Option_, OptionDecl);
impl_into_top_decl_for!(Union, UnionDecl);
impl_into_top_decl_for!(Array, ArrayDecl);
impl_into_top_decl_for!(Struct, StructDecl);
impl_into_top_decl_for!(Vector, VectorDecl);
impl_into_top_decl_for!(Table, TableDecl);