Skip to content

Commit

Permalink
attempt to add primitive types
Browse files Browse the repository at this point in the history
  • Loading branch information
eval-exec committed Jan 11, 2023
1 parent 5f94aa8 commit e4b0d25
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 16 deletions.
2 changes: 1 addition & 1 deletion bindings/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ cfg_if::cfg_if! {

pub mod error;
pub mod prelude;
mod primitive;
pub mod primitive;

// Little Endian
pub type Number = u32;
Expand Down
12 changes: 12 additions & 0 deletions std/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "molecule-std"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
molecule = { path = "../../bindings/rust" }

[build-dependencies]
codegen = { package ="molecule-codegen", path = "../../tools/codegen" }
20 changes: 20 additions & 0 deletions std/rust/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use codegen::{Compiler, Language};

fn compile_schema(schema: &str) {
let mut compiler = Compiler::new();
compiler
.input_schema_file(schema)
.generate_code(Language::Rust)
.output_dir_set_default()
.expand_primitive_types()
.run()
.unwrap();
println!("cargo:rerun-if-changed={}", schema);
}

fn main() {
println!("cargo:rerun-if-changed=primitive_types.mol");
compile_schema("primitive_types.mol");
let out_dir = ::std::env::var("OUT_DIR").unwrap();
println!("{}", out_dir);
}
1 change: 1 addition & 0 deletions std/rust/primitive_types.mol
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
array uint64 [byte; 8];
56 changes: 56 additions & 0 deletions std/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
pub mod prelude;
pub mod primitive_types;

extern crate alloc;

pub use alloc::{borrow::ToOwned, vec, vec::Vec};
use core::{clone::Clone, default::Default, fmt};
use molecule::prelude::*;
pub use molecule::{
bytes,
bytes::Bytes,
error,
error::VerificationResult,
hex_string, io,
primitive::{Byte, ByteReader},
verification_error,
};

use primitive_types::*;

pub trait Unpack<T> {
/// Unpack binary data into rust types.
fn unpack(&self) -> T;
}

/// A syntactic sugar to convert a rust type into binary data.
pub trait Pack<T: Entity> {
/// Packs a rust type into binary data.
fn pack(&self) -> T;
}

impl Pack<Uint64> for u64 {
fn pack(&self) -> Uint64 {
Uint64::new_unchecked(Bytes::from(self.to_le_bytes().to_vec()))
}
}

impl<'r> Unpack<u64> for Uint64Reader<'r> {
fn unpack(&self) -> u64 {
let mut b = [0u8; 8];
b.copy_from_slice(self.as_slice());
u64::from_le_bytes(b)
}
}

macro_rules! impl_conversion_for_entity_unpack {
($original:ty, $entity:ident) => {
impl Unpack<$original> for $entity {
fn unpack(&self) -> $original {
self.as_reader().unpack()
}
}
};
}

impl_conversion_for_entity_unpack!(u64, Uint64);
14 changes: 14 additions & 0 deletions std/rust/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
include!(concat!(env!("OUT_DIR"), "/primitive_types.rs"));

extern crate alloc;
pub use alloc::{borrow::ToOwned, vec, vec::Vec};
pub use molecule::{
bytes,
bytes::Bytes,
error,
error::VerificationResult,
hex_string, io, prelude,
prelude::*,
primitive::{Byte, ByteReader},
verification_error,
};
1 change: 1 addition & 0 deletions std/rust/src/primitive_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include!(concat!(env!("OUT_DIR"), "/primitive_types.rs"));
25 changes: 21 additions & 4 deletions tools/codegen/src/ast/verified/complete.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::ast::verified::{PRIMITIVE_BYTE, PRIMITIVE_EXT_TYPES};
use std::{
collections::{HashMap, HashSet},
rc::Rc,
Expand Down Expand Up @@ -162,23 +163,39 @@ impl CompleteRawDecl for raw::TableDecl {
}

impl super::Ast {
pub(crate) fn complete(raw: raw::Ast) -> Self {
pub(crate) fn complete(raw: raw::Ast, expand_primitive_ext_types: bool) -> Self {
let mut decls_idx = HashMap::new();
let mut decls_keys = HashSet::new();
for decl in raw.decls() {
let name = decl.name();
if super::TopDecl::new_primitive(name.to_lowercase().as_str()).is_some() {
if expand_primitive_ext_types {
if super::TopDecl::new_primitive_without_ext(name.to_lowercase().as_str()).is_some()
{
panic!("the name `{}` is reserved", name);
}
} else if super::TopDecl::new_primitive(name.to_lowercase().as_str()).is_some() {
panic!("the name `{}` is reserved", name);
}
if decls_idx.insert(name, decl).is_some() || !decls_keys.insert(name) {
panic!("the name `{}` is used more than once", name);
};
}
let mut decls_result = HashMap::new();

decls_result.insert(
"byte",
Rc::new(super::TopDecl::new_primitive("byte").unwrap()),
PRIMITIVE_BYTE,
Rc::new(super::TopDecl::new_primitive(PRIMITIVE_BYTE).unwrap()),
);

if !expand_primitive_ext_types {
PRIMITIVE_EXT_TYPES.iter().for_each(|&primitive_type| {
decls_result.insert(
primitive_type,
Rc::new(super::TopDecl::new_primitive(primitive_type).unwrap()),
);
});
}

loop {
if decls_keys.is_empty() {
break;
Expand Down
22 changes: 21 additions & 1 deletion tools/codegen/src/ast/verified/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ mod recover;
pub use default_content::DefaultContent;
pub use has_name::HasName;

const PRIMITIVE_BYTE: &str = "byte";

const PRIMITIVE_UINT64: &str = "uint64";
const PRIMITIVE_EXT_TYPES: &[&str] = &[PRIMITIVE_UINT64];

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

#[derive(Debug, Property)]
Expand Down Expand Up @@ -135,7 +140,22 @@ impl Ast {
impl TopDecl {
fn new_primitive(name: &str) -> Option<Self> {
match name {
"byte" => Some(Primitive {
PRIMITIVE_BYTE => Some(Primitive {
name: name.to_owned(),
size: 1,
}),
PRIMITIVE_UINT64 => Some(Primitive {
name: name.to_owned(),
size: 8,
}),
_ => None,
}
.map(Self::Primitive)
}

fn new_primitive_without_ext(name: &str) -> Option<Self> {
match name {
PRIMITIVE_BYTE => Some(Primitive {
name: name.to_owned(),
size: 1,
}),
Expand Down
24 changes: 20 additions & 4 deletions tools/codegen/src/ast/verified/recover.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::ast::verified::{PRIMITIVE_BYTE, PRIMITIVE_EXT_TYPES};
use std::{
collections::{HashMap, HashSet},
rc::Rc,
Expand Down Expand Up @@ -169,23 +170,38 @@ impl RecoverFromIr for ir::Table {
}

impl super::Ast {
pub(crate) fn recover(ir: ir::Ir) -> Self {
pub(crate) fn recover(ir: ir::Ir, expand_primitive_ext_types: bool) -> Self {
let mut decls_idx = HashMap::new();
let mut decls_keys = HashSet::new();
for decl in ir.decls() {
let name = decl.name();
if super::TopDecl::new_primitive(name.to_lowercase().as_str()).is_some() {
if expand_primitive_ext_types {
if super::TopDecl::new_primitive_without_ext(name.to_lowercase().as_str()).is_some()
{
panic!("the name `{}` is reserved", name);
}
} else if super::TopDecl::new_primitive(name.to_lowercase().as_str()).is_some() {
panic!("the name `{}` is reserved", name);
}
if decls_idx.insert(name, decl).is_some() || !decls_keys.insert(name) {
panic!("the name `{}` is used more than once", name);
};
}
let mut decls_result = HashMap::new();

decls_result.insert(
"byte",
Rc::new(super::TopDecl::new_primitive("byte").unwrap()),
PRIMITIVE_BYTE,
Rc::new(super::TopDecl::new_primitive(PRIMITIVE_BYTE).unwrap()),
);
if !expand_primitive_ext_types {
PRIMITIVE_EXT_TYPES.iter().for_each(|&primitive_type| {
decls_result.insert(
primitive_type,
Rc::new(super::TopDecl::new_primitive(primitive_type).unwrap()),
);
});
}

loop {
if decls_keys.is_empty() {
break;
Expand Down
14 changes: 12 additions & 2 deletions tools/codegen/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Compiler {
target: Option<generator::Target>,
input: Option<Input>,
output: Option<Output>,
expand_primitive_types: bool,
}

pub(crate) enum Input {
Expand Down Expand Up @@ -39,6 +40,7 @@ impl Compiler {
target: None,
input: None,
output: Some(Output::Stdout),
expand_primitive_types: false,
}
}

Expand All @@ -65,6 +67,11 @@ impl Compiler {
self
}

pub fn expand_primitive_types(&mut self) -> &mut Self {
self.expand_primitive_types = true;
self
}

pub fn output_dir_set_default(&mut self) -> &mut Self {
let out_dir = path::PathBuf::from(&env::var("OUT_DIR").unwrap_or_else(|_| ".".to_string()));
self.output_dir(out_dir)
Expand All @@ -90,6 +97,7 @@ impl Compiler {
ref output,
#[cfg(feature = "compiler-plugin")]
ref mut output,
expand_primitive_types: _,
} = self;
let target = target.ok_or("target is not set: generate code or intermediate data")?;
let input = input
Expand All @@ -113,10 +121,12 @@ impl Compiler {
.file_name()
.and_then(ffi::OsStr::to_str)
.to_owned();
parser::Parser::parse(file_path)
parser::Parser::parse(file_path, self.expand_primitive_types)
}
#[cfg(feature = "compiler-plugin")]
Input::Intermediate(format, ref data) => format.recover(data)?,
Input::Intermediate(format, ref data) => {
format.recover(data, self.expand_primitive_types)?
}
};
let generator = generator::Generator::new(ast);

Expand Down
5 changes: 3 additions & 2 deletions tools/codegen/src/ir/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ impl Format {
writer.write_all(&data)
}

pub fn recover(self, bytes: &[u8]) -> Result<ast::Ast, String> {
self.deserialize(bytes).map(ast::Ast::recover)
pub fn recover(self, bytes: &[u8], expand_primitive_types: bool) -> Result<ast::Ast, String> {
self.deserialize(bytes)
.map(|ir| ast::Ast::recover(v, expand_primitive_types))
}
}
4 changes: 2 additions & 2 deletions tools/codegen/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ pub(crate) use inner::{Parser as InnerParser, Rule};
pub struct Parser;

impl Parser {
pub fn parse<P: AsRef<Path>>(path: &P) -> ast::Ast {
pub fn parse<P: AsRef<Path>>(path: &P, expand_primitive_types: bool) -> ast::Ast {
let ast_raw = Self::preprocess(path).unwrap();
ast::Ast::complete(ast_raw)
ast::Ast::complete(ast_raw, expand_primitive_types)
}
}

0 comments on commit e4b0d25

Please sign in to comment.