Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add syntax_version identifier to molecule #64

Merged
merged 3 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ci:
@set -eu; \
export RUSTFLAGS='-D warnings'; \
make fmt clippy; \
make ci-examples ci-crates; \
make cargo-test ci-examples ci-crates; \
echo "Success!"

RUST_DEV_PROJS = examples/ci-tests tests
Expand Down Expand Up @@ -40,6 +40,15 @@ clippy:
cd - > /dev/null; \
done

cargo-test:
@set -eu; \
for dir in ${RUST_PROJS}; do \
cd "$${dir}"; \
cargo test; \
cd - > /dev/null; \
done


ci-msrv:
@set -eu; \
for dir in ${RUST_PROD_PROJS}; do \
Expand Down
2 changes: 2 additions & 0 deletions tools/codegen/src/ast/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub(crate) mod raw;
pub(crate) mod verified;

pub use raw::SyntaxVersion;

pub use verified::{
Array, Ast, DefaultContent, DynVec, FieldDecl, FixVec, HasName, ImportStmt, ItemDecl, Option_,
Primitive, Struct, Table, TopDecl, Union, UnionItemDecl,
Expand Down
21 changes: 21 additions & 0 deletions tools/codegen/src/ast/raw/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
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, 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,
Expand Down
92 changes: 91 additions & 1 deletion tools/codegen/src/ast/raw/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use std::{ffi, fs, io::Read as _, path::Path, str::FromStr};
use pest::{error::Error as PestError, iterators::Pairs, Parser as _};
use same_file::is_same_file;

use crate::ast::raw::CustomUnionItemDecl;
use crate::{
ast::raw as ast,
ast::raw::CustomUnionItemDecl,
ast::raw::SyntaxVersion,
parser,
utils::{self, PairsUtils as _},
};
Expand Down Expand Up @@ -231,6 +232,22 @@ impl parser::Parser {
panic!("grammar should have only one EOI");
}
match pair.as_rule() {
parser::Rule::syntax_version_stmt => {
let mut pair = pair.into_inner();
let syntax_version = SyntaxVersion {
version: pair.next_usize(),
};
pair.next_should_be_none();
if ast.syntax_version.is_some() {
// compare ast.syntax_version and syntax_version
// panic if there is a conflict syntax_version
if ast.syntax_version != Some(syntax_version) {
panic!("all schema files' syntax version should be same");
}
} else {
ast.syntax_version = Some(syntax_version);
}
}
parser::Rule::import_stmt => {
let mut pair = pair.into_inner();
let node = pair.next_import(path, imported_depth);
Expand Down Expand Up @@ -312,6 +329,79 @@ impl parser::Parser {
if !eoi {
panic!("grammar should have only one EOI");
}

if ast.syntax_version.is_none() {
ast.syntax_version = Some(SyntaxVersion::default());
}
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::{parser, utils, SyntaxVersion};
use std::io::Write;

#[test]
fn test_default_syntax_version_should_be_1_0() {
use utils::ParserUtils;
// get path of file
let mut schema_file = tempfile::NamedTempFile::new().unwrap();
let _ = schema_file.write(b"array uint32 [byte; 4];").unwrap();
schema_file.flush().unwrap();

let file = schema_file.into_temp_path();

let ast = parser::Parser::preprocess(&file).unwrap();
assert_eq!(ast.syntax_version, Some(SyntaxVersion { version: 1 }));
}

#[test]
fn test_parse_syntax_version() {
use utils::ParserUtils;
// get path of file
let mut schema_file = tempfile::NamedTempFile::new().unwrap();
let test_version = SyntaxVersion { version: 7 };
schema_file
.write_fmt(format_args!("syntax = {};", test_version.version))
.unwrap();
let _ = schema_file.write(b"array uint32 [byte; 4];").unwrap();
schema_file.flush().unwrap();

let file = schema_file.into_temp_path();

let ast = parser::Parser::preprocess(&file).unwrap();
assert_eq!(ast.syntax_version, Some(test_version));
}

#[test]
#[should_panic]
// if A `syntax = 1` schema file imports a `syntax = 2` schema file, it should panic
fn test_different_syntax_version_should_panic() {
use utils::ParserUtils;

let mut child_schema_file = tempfile::NamedTempFile::new().unwrap();
child_schema_file
.write_fmt(format_args!("syntax = 2;"))
.unwrap();
let _ = child_schema_file.write(b"array uint64 [byte; 8];").unwrap();
child_schema_file.flush().unwrap();

let child_file = child_schema_file.into_temp_path();
let child_file_path = child_file.to_str().unwrap();

let mut root_schema_file = tempfile::NamedTempFile::new().unwrap();
root_schema_file
.write_fmt(format_args!("syntax = 1;",))
.unwrap();
root_schema_file
.write_fmt(format_args!("import {:?}", child_file_path))
.unwrap();
let _ = root_schema_file.write(b"array uint32 [byte; 4];").unwrap();
root_schema_file.flush().unwrap();

let file = root_schema_file.into_temp_path();

parser::Parser::preprocess(&file).unwrap();
}
}
4 changes: 4 additions & 0 deletions tools/codegen/src/ast/verified/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ impl super::Ast {
let result = decls_result.get(decl.name()).unwrap();
decls.push(Rc::clone(result));
}

let syntax_version = raw.syntax_version().unwrap().to_owned();

Self {
syntax_version,
namespace,
imports,
decls,
Expand Down
3 changes: 3 additions & 0 deletions tools/codegen/src/ast/verified/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ mod recover;
pub use default_content::DefaultContent;
pub use has_name::HasName;

use crate::ast::SyntaxVersion;

type Deps<'a> = HashMap<&'a str, Rc<super::TopDecl>>;

#[derive(Debug, Property)]
#[property(get(public))]
pub struct Ast {
syntax_version: SyntaxVersion,
namespace: String,
imports: Vec<ImportStmt>,
decls: Vec<Rc<TopDecl>>,
Expand Down
3 changes: 3 additions & 0 deletions tools/codegen/src/ast/verified/recover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ impl super::Ast {
let result = decls_result.get(decl.name()).unwrap();
decls.push(Rc::clone(result));
}

let syntax_version = ir.syntax_version().to_owned();
Self {
syntax_version,
namespace,
imports,
decls,
Expand Down
4 changes: 4 additions & 0 deletions tools/codegen/src/grammar.pest
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,12 @@ path_super = @{ "../" }
path = { path_super* ~ (identifier ~ "/")* ~ identifier }
import_stmt = { "import" ~ (brk)+ ~ path ~ (brk)* ~ stmt_end }

syntax_version = @{ digit+ }
syntax_version_stmt = { "syntax" ~ (brk)* ~ "=" ~ (brk)* ~ syntax_version ~ (brk)* ~ stmt_end}

grammar = {
SOI ~ (brk)* ~
(syntax_version_stmt)? ~ (brk)* ~
(import_stmt ~ (brk)*)* ~
decl_stmt ~
((brk)* ~ decl_stmt)* ~ (brk)* ~
Expand Down
1 change: 1 addition & 0 deletions tools/codegen/src/ir/from_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ impl ToIntermediate for ast::Ast {
type Ir = super::Ir;
fn to_ir(&self) -> Self::Ir {
Self::Ir {
syntax_version: self.syntax_version().to_owned(),
namespace: self.namespace().to_owned(),
imports: self.imports().iter().map(ToIntermediate::to_ir).collect(),
decls: self.decls().iter().map(|decl| decl.to_ir()).collect(),
Expand Down
4 changes: 4 additions & 0 deletions tools/codegen/src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ use property::Property;
pub use format::Format;
pub(crate) use from_ast::ToIntermediate;

use crate::ast::SyntaxVersion;

/// Intermediate file.
#[derive(Debug, Property, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct Ir {
#[serde(default)]
syntax_version: SyntaxVersion,
namespace: String,
imports: Vec<ImportStmt>,
#[serde(rename = "declarations")]
Expand Down