A bit of work on the parser, schema syntax, compilation/interpretation, and so on
This commit is contained in:
parent
9eebd7675c
commit
304e521971
|
@ -8,6 +8,14 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.71"
|
||||||
once_cell = "1.17.1"
|
once_cell = "1.17.1"
|
||||||
|
panik-handler = "0.1.0"
|
||||||
pest = "2.6.0"
|
pest = "2.6.0"
|
||||||
pest_derive = "2.6.0"
|
pest_derive = "2.6.0"
|
||||||
rmp = "0.8.11"
|
rmp = "0.8.11"
|
||||||
|
rmp-serde = "1.1.1"
|
||||||
|
serde = "1.0.164"
|
||||||
|
serde_derive = "1.0.164"
|
||||||
|
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
pretty_assertions = "1.3.0"
|
||||||
|
|
|
@ -2,15 +2,6 @@ namespace examples.thing.simple
|
||||||
|
|
||||||
const AGREEMENT_KEY: string = "agreement_key"
|
const AGREEMENT_KEY: string = "agreement_key"
|
||||||
|
|
||||||
|
|
||||||
@min_chars=0 max_chars=1024
|
|
||||||
validator StringBounds {
|
|
||||||
assert_error(
|
|
||||||
value.length > params.max_chars or value.length < params.min_chars,
|
|
||||||
"String {value.name} must be more than {params.min_chars} and less than {params.max_chars}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@min_chars=16 max_chars=60
|
@min_chars=16 max_chars=60
|
||||||
validator PasswordCheck {
|
validator PasswordCheck {
|
||||||
assert_valid(
|
assert_valid(
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
// Standard Uses
|
// Standard Uses
|
||||||
|
|
||||||
// Local Uses
|
// Local Uses
|
||||||
use crate::ir::unit::{Protocol, Unit};
|
//use crate::ir::unit::{Protocol, Unit};
|
||||||
|
|
||||||
// External Uses
|
// External Uses
|
||||||
|
|
||||||
|
/*
|
||||||
fn unit_to_code(unit: Unit) -> String {
|
fn unit_to_code(unit: Unit) -> String {
|
||||||
let mut code = String::new();
|
let mut code = String::new();
|
||||||
|
|
||||||
|
@ -73,3 +74,4 @@ fn protocol_to_code(protocol: Protocol) -> String {
|
||||||
|
|
||||||
code.to_owned()
|
code.to_owned()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// IDL grammar
|
// IDL grammar
|
||||||
schema = _{
|
schema = _{
|
||||||
namespace
|
COMMENT* ~ MULTILINE_COMMENT*
|
||||||
|
~ WS?
|
||||||
|
~ namespace
|
||||||
~ (
|
~ (
|
||||||
COMMENT | import
|
COMMENT | import
|
||||||
| settings | constant
|
| settings | constant
|
||||||
|
@ -25,13 +27,12 @@ constant = {
|
||||||
}
|
}
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
WS ~ parameter*
|
WS? ~ "settings" ~ WS? ~ id? ~ WS?
|
||||||
~ "settings" ~ WS? ~ id? ~ WS?
|
|
||||||
~ "{" ~ WS? ~ parameter* ~ WS? ~ "}"
|
~ "{" ~ WS? ~ parameter* ~ WS? ~ "}"
|
||||||
}
|
}
|
||||||
|
|
||||||
enumeration = {
|
enumeration = {
|
||||||
WS ~ parameter*
|
WS? ~ property*
|
||||||
~ "enum" ~ WS ~ id ~ WS?
|
~ "enum" ~ WS ~ id ~ WS?
|
||||||
~ "{" ~ WS? ~ enum_variant+ ~ WS? ~ "}"
|
~ "{" ~ WS? ~ enum_variant+ ~ WS? ~ "}"
|
||||||
~ WS?
|
~ WS?
|
||||||
|
@ -41,7 +42,7 @@ enum_variant = {
|
||||||
}
|
}
|
||||||
|
|
||||||
validator = {
|
validator = {
|
||||||
WS ~ parameter*
|
WS? ~ property*
|
||||||
~ "validator" ~ WS ~ id ~ WS?
|
~ "validator" ~ WS ~ id ~ WS?
|
||||||
~ "{" ~ WS? ~ function_call* ~ WS? ~ "}"
|
~ "{" ~ WS? ~ function_call* ~ WS? ~ "}"
|
||||||
~ WS?
|
~ WS?
|
||||||
|
@ -77,14 +78,15 @@ boolean_operator = {
|
||||||
}
|
}
|
||||||
|
|
||||||
structure = {
|
structure = {
|
||||||
WS? ~ parameter*
|
WS? ~ docstring? ~ property*
|
||||||
~ "struct" ~ WS ~ id ~ WS?
|
~ "struct" ~ WS ~ id ~ WS?
|
||||||
~ "{" ~ WS? ~ (constant | field)+ ~ WS? ~ "}"
|
~ "{" ~ WS? ~ (constant | field)+ ~ WS? ~ "}"
|
||||||
~ WS?
|
~ WS?
|
||||||
}
|
}
|
||||||
field = {
|
field = {
|
||||||
WS? ~ property*
|
WS? ~ property*
|
||||||
~ (index ~ "#")? ~ (WS? ~ requirement)?
|
// ~ (index ~ "#")?
|
||||||
|
~ (WS? ~ requirement)?
|
||||||
~ WS? ~ id ~ WS? ~ ":" ~ WS? ~ kind
|
~ WS? ~ id ~ WS? ~ ":" ~ WS? ~ kind
|
||||||
~ (WS? ~ "=" ~ WS? ~ value)? ~ WS?
|
~ (WS? ~ "=" ~ WS? ~ value)? ~ WS?
|
||||||
}
|
}
|
||||||
|
@ -92,7 +94,7 @@ index = @{ digit }
|
||||||
requirement = { "optional" }
|
requirement = { "optional" }
|
||||||
|
|
||||||
error = {
|
error = {
|
||||||
WS? ~ property*
|
WS? ~ docstring? ~ property*
|
||||||
~ "error" ~ WS ~ id ~ WS?
|
~ "error" ~ WS ~ id ~ WS?
|
||||||
~ "{" ~ WS?
|
~ "{" ~ WS?
|
||||||
~ (parameter | field)+
|
~ (parameter | field)+
|
||||||
|
@ -100,19 +102,19 @@ error = {
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol = {
|
protocol = {
|
||||||
WS? ~ property* ~ WS?
|
WS? ~ docstring? ~ property*
|
||||||
~ "protocol" ~ WS ~ id ~ WS?
|
~ "protocol" ~ WS ~ id ~ WS?
|
||||||
~ "{" ~ WS? ~ function* ~ WS? ~ "}"
|
~ "{" ~ WS? ~ function* ~ WS? ~ "}"
|
||||||
}
|
}
|
||||||
function = {
|
function = {
|
||||||
WS? ~ property* ~ WS?
|
WS? ~ property*
|
||||||
~ (index ~ WS? ~ "#" ~ WS?)?
|
~ (index ~ WS? ~ "#" ~ WS?)?
|
||||||
~ (asynchronous ~ WS?)?
|
~ (asynchronous ~ WS?)?
|
||||||
~ (direction ~ WS?)?
|
~ (direction ~ WS?)?
|
||||||
~ "function" ~ WS ~ id ~ WS?
|
~ "function" ~ WS ~ id ~ WS?
|
||||||
~ "(" ~ WS? ~ argument* ~ WS? ~ ")"
|
~ "(" ~ WS? ~ argument* ~ WS? ~ ")"
|
||||||
~ (WS? ~ "->" ~ WS? ~ returns+)?
|
~ (WS? ~ "->" ~ WS? ~ returns+)?
|
||||||
~ (WS? ~ ":" ~ WS? ~ parameter+)?
|
// ~ (WS? ~ ":" ~ WS? ~ parameter+)?
|
||||||
~ (WS? ~ "!" ~ WS? ~ throw+)?
|
~ (WS? ~ "!" ~ WS? ~ throw+)?
|
||||||
}
|
}
|
||||||
direction = { "client" | "server" }
|
direction = { "client" | "server" }
|
||||||
|
@ -167,8 +169,12 @@ instantiation = {
|
||||||
~ "(" ~ domain ~ ")"
|
~ "(" ~ domain ~ ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
docstring = {
|
||||||
|
"///" ~ (!NEWLINE ~ ANY)* ~ NEWLINE
|
||||||
|
}
|
||||||
|
|
||||||
value = {
|
value = {
|
||||||
"true" | "false"
|
"true" | "false" | digit
|
||||||
| string | string_interpolated
|
| string | string_interpolated
|
||||||
| instantiation
|
| instantiation
|
||||||
| domain | domain_namespaced
|
| domain | domain_namespaced
|
||||||
|
@ -197,5 +203,12 @@ alpha = { 'a'..'z' | 'A'..'Z' }
|
||||||
digit = { '0'..'9' }
|
digit = { '0'..'9' }
|
||||||
|
|
||||||
WS = _{ (" " | "\t" | "\n")+ }
|
WS = _{ (" " | "\t" | "\n")+ }
|
||||||
COMMENT = _{ "//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE }
|
COMMENT = _{
|
||||||
// MULTILINE_COMMENT = _{ "/*" ~ (MULTILINE_COMMENT | !"*/" ~ ANY)* ~ "*/" }
|
!"///" ~
|
||||||
|
"//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE
|
||||||
|
}
|
||||||
|
MULTILINE_COMMENT = _{
|
||||||
|
"/*"
|
||||||
|
~ (MULTILINE_COMMENT | !"*/" ~ ANY)*
|
||||||
|
~ "*/"
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
// Standard Uses
|
// Standard Uses
|
||||||
|
|
||||||
// Local Uses
|
// Local Uses
|
||||||
use crate::ir::new_unit::Unit;
|
use crate::ir::new_unit::{Unit, UnitIndex, VUnit, WholeUnit};
|
||||||
|
use crate::ir::primitive;
|
||||||
|
use crate::ir::primitive::TypeValue;
|
||||||
|
|
||||||
// External Uses
|
// External Uses
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pest::iterators::Pair;
|
use pest::{iterators::Pair, Parser};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
@ -13,24 +15,205 @@ use pest::iterators::Pair;
|
||||||
pub struct IDLParser;
|
pub struct IDLParser;
|
||||||
|
|
||||||
|
|
||||||
/*
|
pub fn from_path(path: &str) -> Result<WholeUnit> {
|
||||||
pub fn parse_into_unit(content: &str) -> Result<Vec<Unit>> {
|
let raw = std::fs::read_to_string(path).unwrap();
|
||||||
|
let vunit = parse_into_unit(raw.clone().as_str()).unwrap();
|
||||||
|
let index = UnitIndex::Index { path: path.to_string(), source: raw };
|
||||||
|
|
||||||
|
Ok((index, vunit))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_into_unit(content: &str) -> Result<VUnit> {
|
||||||
let pairs = IDLParser::parse(Rule::schema, content)?;
|
let pairs = IDLParser::parse(Rule::schema, content)?;
|
||||||
let mut units = vec![];
|
let mut unit = vec![];
|
||||||
|
|
||||||
for pair in pairs { units.push(parse_inner(pair).unwrap()) }
|
for pair in pairs { unit.push(parse_inner(pair).unwrap()) }
|
||||||
|
|
||||||
Ok(units)
|
Ok(unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn parse_inner(pairs: Pair<Rule>) -> Result<Unit> {
|
pub fn parse_inner(pairs: Pair<Rule>) -> Result<Unit> {
|
||||||
match pairs.as_rule() {
|
match pairs.as_rule() {
|
||||||
Rule::schema {
|
/*
|
||||||
|
Rule::schema => {
|
||||||
|
todo!()
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
|
Rule::namespace => {
|
||||||
|
Ok(Unit::Namespace(pairs.into_inner().as_str().to_owned()))
|
||||||
|
},
|
||||||
|
Rule::import => {
|
||||||
|
Ok(Unit::Import(pairs.into_inner().as_str().to_owned()))
|
||||||
}
|
}
|
||||||
|
Rule::constant => {
|
||||||
|
let pairs = pairs.into_inner();
|
||||||
|
|
||||||
|
let mut docstring: Option<String> = None;
|
||||||
|
let mut id: Option<String> = None;
|
||||||
|
let mut kind: Option<TypeValue> = None;
|
||||||
|
let mut default_value: Option<String> = None;
|
||||||
|
|
||||||
|
for pair in pairs {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::docstring => docstring = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::id => id = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::kind => kind = Some(primitive::to_type(pair.as_str())),
|
||||||
|
Rule::value => default_value = to_value_other(pair),
|
||||||
|
(r) => panic!("Rule not implemented on 'constant': {:?}", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Unit::Constant {
|
||||||
|
docstring,
|
||||||
|
name: id.ok_or("Id is not present").unwrap(),
|
||||||
|
kind: kind.ok_or("Type is not present").unwrap(),
|
||||||
|
default_value,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Rule::settings => {
|
||||||
|
let mut pairs = pairs.into_inner();
|
||||||
|
|
||||||
|
let mut docstring: Option<String> = None;
|
||||||
|
let mut name: Option<String> = None;
|
||||||
|
let mut parameters: Vec<Unit> = vec![];
|
||||||
|
|
||||||
|
for pair in pairs {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::docstring => docstring = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::id => name = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::parameter => parameters.push(to_parameter(pair)),
|
||||||
|
(r) => panic!("Rule not implemented on 'settings': {:?}", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Unit::Settings {
|
||||||
|
docstring,
|
||||||
|
name: name.unwrap(),
|
||||||
|
parameters,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Rule::enumeration => {
|
||||||
|
let mut pairs = pairs.into_inner();
|
||||||
|
|
||||||
|
let mut docstring: Option<String> = None;
|
||||||
|
let mut name: Option<String> = None;
|
||||||
|
let mut variants: Vec<Unit> = vec![];
|
||||||
|
|
||||||
|
for pair in pairs {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::docstring => docstring = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::id => name = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::enum_variant => {
|
||||||
|
let mut inner = pair.into_inner();
|
||||||
|
let name = inner.next().unwrap().as_str().to_string();
|
||||||
|
let kind = inner.next().map(|s| s.as_str().to_string());
|
||||||
|
|
||||||
|
variants.push(Unit::EnumVariant {
|
||||||
|
name, kind,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(r) => panic!("Rule not implemented on 'enumeration': {:?}", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Unit::Enum {
|
||||||
|
docstring, name: name.unwrap(),
|
||||||
|
variants,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Rule::structure => {
|
||||||
|
let mut pairs = pairs.into_inner();
|
||||||
|
|
||||||
|
let mut docstring: Option<String> = None;
|
||||||
|
let mut parameters: Vec<Unit> = vec![];
|
||||||
|
let mut name: Option<String> = None;
|
||||||
|
let mut fields: Vec<Unit> = vec![];
|
||||||
|
|
||||||
|
for pair in pairs {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::docstring => docstring = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::id => name = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::parameter => parameters.push(to_parameter(pair)),
|
||||||
|
Rule::field => fields.push(to_field(pair)),
|
||||||
|
(r) => panic!("Rule not implemented on 'structure': {:?}", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Unit::Struct {
|
||||||
|
docstring, parameters,
|
||||||
|
name: name.unwrap(), fields: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
(r) => panic!("Rule not implemented: {:?}", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn to_parameters(mut pairs: Pairs<Rule>) -> Vec<Unit> {
|
||||||
|
let mut params = vec![];
|
||||||
|
|
||||||
|
let t = pairs.as_str();
|
||||||
|
while let Some(pair) = pairs.next() {
|
||||||
|
let temp = pair.as_str();
|
||||||
|
|
||||||
|
params.push(to_parameter(pair.into_inner()));
|
||||||
|
}
|
||||||
|
|
||||||
|
params
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
pub fn to_parameter(mut pair: Pair<Rule>) -> Unit {
|
||||||
|
let mut pairs = pair.into_inner();
|
||||||
|
|
||||||
|
Unit::Parameter {
|
||||||
|
name: pairs.next().unwrap().as_str().to_string(),
|
||||||
|
default_value: pairs.next().unwrap().as_str().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn to_value_other(pair: Pair<Rule>) -> Option<String> {
|
||||||
|
let inner = pair.into_inner().next().unwrap();
|
||||||
|
|
||||||
|
match inner.as_rule() {
|
||||||
|
Rule::string => Some(inner.as_str().to_string()),
|
||||||
|
Rule::string_interpolated => Some(inner.as_str().to_string()),
|
||||||
|
Rule::digit => Some(inner.as_str().to_string()),
|
||||||
|
r => panic!("Rule not implemented in 'value': {:?}", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// "".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_field(pair: Pair<Rule>) -> Unit {
|
||||||
|
let mut pairs = pair.into_inner();
|
||||||
|
|
||||||
|
let mut docstring: Option<String> = None;
|
||||||
|
let mut parameters: Vec<Unit> = vec![];
|
||||||
|
let mut optional: bool = false;
|
||||||
|
let mut name: Option<String> = None;
|
||||||
|
let mut kind: Option<String> = None;
|
||||||
|
let mut default_value: Option<String> = None;
|
||||||
|
|
||||||
|
for pair in pairs {
|
||||||
|
match pair.as_rule() {
|
||||||
|
Rule::docstring => docstring = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::parameter => parameters.push(to_parameter(pair)),
|
||||||
|
Rule::requirement => optional = true,
|
||||||
|
Rule::id => name = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::kind => kind = Some(pair.as_str().to_owned()),
|
||||||
|
Rule::value => default_value = Some(pair.as_str().to_owned()),
|
||||||
|
r => panic!("Rule not implemented in 'field': {:?}", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit::Field {
|
||||||
|
docstring, parameters,
|
||||||
|
optional,
|
||||||
|
name: name.unwrap(), kind: kind.unwrap(), default_value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Local Uses
|
// Local Uses
|
||||||
use crate::ir::primitive;
|
use crate::ir::primitive;
|
||||||
use crate::ir::primitive::TypeValue;
|
use crate::ir::primitive::TypeValue;
|
||||||
|
|
||||||
use crate::ir::unit::{
|
use crate::ir::unit::{
|
||||||
Argument, Const, Direction, Enum, EnumVariant,
|
Argument, Const, Direction, Enum, EnumVariant,
|
||||||
Error, Field, Function, Parameter,
|
Error, Field, Function, Parameter,
|
||||||
|
@ -19,7 +20,7 @@ use pest::Parser;
|
||||||
#[grammar = "idl/idl.pest"]
|
#[grammar = "idl/idl.pest"]
|
||||||
pub struct IDLParser;
|
pub struct IDLParser;
|
||||||
|
|
||||||
|
/*
|
||||||
pub fn parse_into_unit(raw: &str) -> Result<Unit> {
|
pub fn parse_into_unit(raw: &str) -> Result<Unit> {
|
||||||
let parse = IDLParser::parse(Rule::schema, raw)?;
|
let parse = IDLParser::parse(Rule::schema, raw)?;
|
||||||
|
|
||||||
|
@ -173,9 +174,9 @@ fn parse_inner(record: Pair<Rule>) -> Result<Unit> {
|
||||||
|
|
||||||
inner
|
inner
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn to_parameters(mut pairs: Pairs<Rule>) -> Vec<Parameter> {
|
||||||
fn to_parameters(mut pairs: Pairs<Rule>) -> Vec<Parameter> {
|
|
||||||
let mut params = vec![];
|
let mut params = vec![];
|
||||||
|
|
||||||
while let Some(pair) = pairs.next() {
|
while let Some(pair) = pairs.next() {
|
||||||
|
@ -185,7 +186,7 @@ fn to_parameters(mut pairs: Pairs<Rule>) -> Vec<Parameter> {
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_parameter(mut pairs: Pairs<Rule>) -> Parameter {
|
pub fn to_parameter(mut pairs: Pairs<Rule>) -> Parameter {
|
||||||
Parameter {
|
Parameter {
|
||||||
id: pairs.next().unwrap().as_str().to_owned(),
|
id: pairs.next().unwrap().as_str().to_owned(),
|
||||||
value: pairs.next().unwrap().as_str().as_bytes().to_vec()
|
value: pairs.next().unwrap().as_str().as_bytes().to_vec()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Relative Modules
|
// Relative Modules
|
||||||
mod sanitizer;
|
mod sanitizer;
|
||||||
mod context;
|
pub mod context;
|
||||||
mod serialization;
|
mod serialization;
|
||||||
pub mod unit;
|
pub mod unit;
|
||||||
pub mod new_unit;
|
pub mod new_unit;
|
||||||
|
|
|
@ -1,7 +1,43 @@
|
||||||
// Standard Uses
|
// Standard Uses
|
||||||
|
|
||||||
// Local Uses
|
// Local Uses
|
||||||
|
use crate::ir::context::Context;
|
||||||
|
use crate::ir::new_unit::{Unit, VUnit};
|
||||||
|
|
||||||
// External Uses
|
// External Uses
|
||||||
|
use anyhow::{Result, bail};
|
||||||
|
|
||||||
|
|
||||||
|
pub fn interpret_unit(context: Context) -> Result<VUnit> {
|
||||||
|
let interpreted = vec![];
|
||||||
|
|
||||||
|
for unit in &context.main.1 {
|
||||||
|
match unit {
|
||||||
|
// Unit::Tag(_) => {}
|
||||||
|
Unit::Namespace(n) => {}
|
||||||
|
Unit::Import(i) => {
|
||||||
|
let relative_unit = context.find_unit(i)?;
|
||||||
|
|
||||||
|
bail!(format!("Could not find in namespace {}", i))
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Unit::Constant { .. } => {}
|
||||||
|
Unit::Enum { .. } => {}
|
||||||
|
Unit::EnumVariant { .. } => {}
|
||||||
|
Unit::Property { .. } => {}
|
||||||
|
Unit::Parameter { .. } => {}
|
||||||
|
Unit::Settings { .. } => {}
|
||||||
|
Unit::Struct { .. } => {}
|
||||||
|
Unit::Protocol { .. } => {}
|
||||||
|
Unit::Function { .. } => {}
|
||||||
|
Unit::Error { .. } => {}
|
||||||
|
Unit::Validator { .. } => {}
|
||||||
|
Unit::Field { .. } => {}
|
||||||
|
*/
|
||||||
|
r => panic!("Left to impl: {:?}", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(interpreted)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,34 @@
|
||||||
// Local Uses
|
// Local Uses
|
||||||
use crate::ir::unit::Unit;
|
use crate::ir::unit::Unit;
|
||||||
use crate::ir::serialization::Origin;
|
use crate::ir::serialization::Origin;
|
||||||
|
use crate::ir::new_unit::{UnitIndex, VUnit, WholeUnit};
|
||||||
|
|
||||||
// External Uses
|
// External Uses
|
||||||
|
use anyhow::{Result, bail};
|
||||||
|
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub units: Vec<(Origin, Unit)>
|
pub main: WholeUnit,
|
||||||
|
pub relative_units: Vec<WholeUnit>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
impl Context {
|
impl Context {
|
||||||
fn add_unit(self, origin: Origin, unit: Unit) {
|
pub fn with_main(main: WholeUnit) -> Self{
|
||||||
|
Context { main, relative_units: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_relative_unit(mut self, whole_unit: WholeUnit) {
|
||||||
|
self.relative_units.push(whole_unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn sanitize_units(self) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sanitize_units(self) {
|
pub(crate) fn find_unit(&self, import: &str) -> Result<&WholeUnit> {
|
||||||
|
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
// Standard Uses
|
// Standard Uses
|
||||||
|
|
||||||
// Local Uses
|
// Local Uses
|
||||||
use crate::ir::primitive::{Primitive, TypeValue};
|
use crate::ir::primitive::TypeValue;
|
||||||
|
|
||||||
// External Uses
|
// External Uses
|
||||||
|
|
||||||
|
|
||||||
pub type OrderIndex = u16;
|
pub type OrderIndex = u16;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
pub enum Direction { Client, Server, Both }
|
pub enum Direction { Client, Server, Both }
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
pub enum Unit {
|
pub enum Unit {
|
||||||
|
/*
|
||||||
Schema {
|
Schema {
|
||||||
tag: String,
|
tag: String,
|
||||||
namespace: String,
|
namespace: String,
|
||||||
|
@ -26,34 +27,53 @@ pub enum Unit {
|
||||||
errors: Vec<Unit>,
|
errors: Vec<Unit>,
|
||||||
protocols: Vec<Unit>
|
protocols: Vec<Unit>
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
|
Tag(String),
|
||||||
|
Namespace(String),
|
||||||
|
Import(String),
|
||||||
Constant {
|
Constant {
|
||||||
|
docstring: Option<String>,
|
||||||
name: String,
|
name: String,
|
||||||
kind: String,
|
kind: TypeValue, // String
|
||||||
default_value: String,
|
default_value: Option<String>,
|
||||||
},
|
},
|
||||||
Enum {
|
Enum {
|
||||||
|
docstring: Option<String>,
|
||||||
name: String,
|
name: String,
|
||||||
|
variants: Vec<Unit>
|
||||||
|
},
|
||||||
|
EnumVariant {
|
||||||
|
name: String,
|
||||||
|
kind: Option<String>
|
||||||
},
|
},
|
||||||
Property {
|
Property {
|
||||||
name: String,
|
name: String,
|
||||||
values: Vec<String>
|
values: Vec<String>
|
||||||
},
|
},
|
||||||
|
Parameter {
|
||||||
|
name: String,
|
||||||
|
default_value: String
|
||||||
|
},
|
||||||
Settings {
|
Settings {
|
||||||
|
docstring: Option<String>,
|
||||||
name: String,
|
name: String,
|
||||||
parameters: Vec<Unit>,
|
parameters: Vec<Unit>,
|
||||||
},
|
},
|
||||||
Struct {
|
Struct {
|
||||||
name: String,
|
docstring: Option<String>,
|
||||||
parameters: Vec<Unit>,
|
parameters: Vec<Unit>,
|
||||||
functions: Vec<Unit>
|
name: String,
|
||||||
|
fields: Vec<Unit>,
|
||||||
},
|
},
|
||||||
Protocol {
|
Protocol {
|
||||||
name: String,
|
docstring: String,
|
||||||
parameters: Vec<Unit>,
|
parameters: Vec<Unit>,
|
||||||
|
name: String,
|
||||||
functions: Vec<Unit>
|
functions: Vec<Unit>
|
||||||
},
|
},
|
||||||
Function {
|
Function {
|
||||||
index: OrderIndex,
|
docstring: String,
|
||||||
|
// index: OrderIndex,
|
||||||
name: String,
|
name: String,
|
||||||
synchronous: bool,
|
synchronous: bool,
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
|
@ -62,17 +82,40 @@ pub enum Unit {
|
||||||
throws: Vec<Unit>
|
throws: Vec<Unit>
|
||||||
},
|
},
|
||||||
Error {
|
Error {
|
||||||
name: String,
|
docstring: String,
|
||||||
parameters: Vec<Unit>,
|
parameters: Vec<Unit>,
|
||||||
|
name: String,
|
||||||
fields: Vec<Unit>
|
fields: Vec<Unit>
|
||||||
},
|
},
|
||||||
|
Validator {
|
||||||
|
docstring: String,
|
||||||
|
parameters: Vec<Unit>,
|
||||||
|
name: String,
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
Field {
|
Field {
|
||||||
index: OrderIndex,
|
docstring: Option<String>,
|
||||||
|
parameters: Vec<Unit>,
|
||||||
|
// index: OrderIndex,
|
||||||
|
optional: bool,
|
||||||
|
name: String,
|
||||||
|
kind: String,
|
||||||
|
default_value: Option<String>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum UnitIndex {
|
pub enum UnitIndex {
|
||||||
Source(String),
|
Index {
|
||||||
|
path: String,
|
||||||
|
source: String,
|
||||||
|
// nodes: Vec<Unit>
|
||||||
|
},
|
||||||
|
Node {
|
||||||
|
index: u32,
|
||||||
|
start_position: u32, length: u32
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type VUnit = Vec<Unit>;
|
||||||
|
pub type WholeUnit = (UnitIndex, VUnit);
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
// External Uses
|
// External Uses
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Primitive {
|
pub enum Primitive {
|
||||||
|
@ -27,7 +26,7 @@ pub enum Primitive {
|
||||||
Namespaced(String)
|
Namespaced(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum TypeValue {
|
pub enum TypeValue {
|
||||||
U8 = 0, U16, U32, U64, U128,
|
U8 = 0, U16, U32, U64, U128,
|
||||||
|
@ -93,4 +92,3 @@ fn to_value(type_: &TypeValue, value: &str) -> Vec<u8> {
|
||||||
TypeValue::Namespaced => Vec::from([value.parse::<u8>().unwrap()]),
|
TypeValue::Namespaced => Vec::from([value.parse::<u8>().unwrap()]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,5 @@ use crate::ir::context::Context;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn sanitize_context_units(context: &Context) {
|
fn sanitize_context_units(context: &Context) {
|
||||||
for (_, unit) in &context.units {
|
todo!()
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,13 @@
|
||||||
extern crate pest;
|
extern crate pest;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate pest_derive;
|
extern crate pest_derive;
|
||||||
|
extern crate serde;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
extern crate rmp_serde as rmps;
|
||||||
|
|
||||||
// Relative Modules
|
// Relative Modules
|
||||||
pub mod ir;
|
pub mod ir;
|
||||||
pub mod codegen;
|
pub mod codegen;
|
||||||
pub mod idl;
|
pub mod idl;
|
||||||
|
pub mod stdlib;
|
||||||
|
|
14
src/stdlib/lang_items.rs
Normal file
14
src/stdlib/lang_items.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Standard Uses
|
||||||
|
|
||||||
|
// Local Uses
|
||||||
|
use crate::ir::new_unit::Unit;
|
||||||
|
use crate::idl::parser::from_path;
|
||||||
|
|
||||||
|
// External Uses
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub const LANGUAGE_ITEMS: [Vec<Unit>] = *[
|
||||||
|
from_path("src/stdlib/validators/string_bounds.ids").unwrap()
|
||||||
|
];
|
||||||
|
*/
|
10
src/stdlib/mod.rs
Normal file
10
src/stdlib/mod.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Relative Modules
|
||||||
|
pub mod lang_items;
|
||||||
|
pub mod validators;
|
||||||
|
|
||||||
|
|
||||||
|
// Standard Uses
|
||||||
|
|
||||||
|
// Local Uses
|
||||||
|
|
||||||
|
// External Uses
|
0
src/stdlib/validators/mod.rs
Normal file
0
src/stdlib/validators/mod.rs
Normal file
12
src/stdlib/validators/string_bounds.ids
Normal file
12
src/stdlib/validators/string_bounds.ids
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace std::validators::StringBounds
|
||||||
|
|
||||||
|
/// Checks if a string length is between a minimum and a maximum
|
||||||
|
/// @min_chars: Minimum length of the string
|
||||||
|
/// @max_chars: Maximum length of the string
|
||||||
|
@min_chars=0 max_chars=1024
|
||||||
|
validator StringBounds {
|
||||||
|
assert_equal(
|
||||||
|
value.length > params.max_chars or value.length < params.min_chars,
|
||||||
|
"String {value.name} must be more than {params.min_chars} and less than {params.max_chars}"
|
||||||
|
)
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
mod pest;
|
mod unit;
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
// Standard Uses
|
|
||||||
|
|
||||||
// Local Uses
|
|
||||||
|
|
||||||
// External Uses
|
|
||||||
use comline::idl;
|
|
||||||
use comline::idl::constants::SCHEMA_EXTENSION;
|
|
||||||
use comline::ir::unit::Unit;
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn from_raw_to_unit() {
|
|
||||||
let raw = std::fs::read_to_string(
|
|
||||||
format!("tests/idl/simple.{}", SCHEMA_EXTENSION)
|
|
||||||
).unwrap();
|
|
||||||
let unit = idl::pest::parse_into_unit(raw.as_str()).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
unit, Unit::Items(vec![
|
|
||||||
Unit::Namespace("".to_string()),
|
|
||||||
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,27 +1,39 @@
|
||||||
|
// Simple Schema
|
||||||
namespace tests.idl.simple
|
namespace tests.idl.simple
|
||||||
|
|
||||||
const POWER: u8 = 10
|
import std::validators::StringBounds
|
||||||
const DEFAULT_NAME: str = f"flower {POWER}"
|
|
||||||
|
const POWER: u8 = 1
|
||||||
|
const DEFAULT_NAME: str = f"flower power: {POWER}"
|
||||||
|
|
||||||
settings Test {
|
settings Test {
|
||||||
|
forbid_indexing=True
|
||||||
forbid_optional_indexing=True
|
forbid_optional_indexing=True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EncryptionMode {
|
||||||
|
None
|
||||||
|
Encrypt
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A message that can be sent through the mail protocol
|
||||||
struct Message {
|
struct Message {
|
||||||
1# name: str = DEFAULT_NAME
|
1# name: str = DEFAULT_NAME
|
||||||
|
2# encryption_mode: EncryptionMode = default
|
||||||
|
|
||||||
@validators=[StringBounds(min_chars=3 max_chars=12)]
|
@validators=[StringBounds(min_chars=3 max_chars=12)]
|
||||||
2# optional recipient: str = "bee"
|
2# optional recipient: str = "bee"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Throw when sending a message to a missing recipient
|
||||||
error RecipientNotFoundError {
|
error RecipientNotFoundError {
|
||||||
message = f"Recipient with name {self.recipient} not found"
|
message = "Recipient with name {self.recipient} not found"
|
||||||
|
|
||||||
@validators=[StringBounds(min_chars=8 max_chars=16)]
|
@validators=[StringBounds(min_chars=8 max_chars=16)]
|
||||||
1# recipient: str
|
1# recipient: str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mail API for receiving and sending emails
|
||||||
@provider=Any
|
@provider=Any
|
||||||
protocol Mail {
|
protocol Mail {
|
||||||
|
|
||||||
|
|
72
tests/idl/unit.rs
Normal file
72
tests/idl/unit.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Standard Uses
|
||||||
|
|
||||||
|
// Local Uses
|
||||||
|
|
||||||
|
// External Uses
|
||||||
|
use comline::{idl, ir};
|
||||||
|
use comline::idl::constants::SCHEMA_EXTENSION;
|
||||||
|
use comline::ir::new_unit::Unit;
|
||||||
|
use panik_handler;
|
||||||
|
use pretty_assertions::{assert_eq, assert_ne};
|
||||||
|
use comline::ir::compiler;
|
||||||
|
use comline::ir::primitive::TypeValue;
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_raw_to_unit() {
|
||||||
|
panik_handler::install();
|
||||||
|
|
||||||
|
let raw = std::fs::read_to_string(
|
||||||
|
format!("tests/idl/simple.{}", SCHEMA_EXTENSION)
|
||||||
|
).unwrap();
|
||||||
|
let unit = idl::parser::parse_into_unit(raw.as_str()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
unit, vec![
|
||||||
|
Unit::Namespace("tests.idl.simple".to_string()),
|
||||||
|
Unit::Import("std::validators::StringBounds".to_string()),
|
||||||
|
Unit::Constant {
|
||||||
|
docstring: None, name: "POWER".to_string(),
|
||||||
|
kind: TypeValue::U8, default_value: Some("1".to_string()),
|
||||||
|
},
|
||||||
|
Unit::Constant {
|
||||||
|
docstring: None, name: "DEFAULT_NAME".to_string(),
|
||||||
|
kind: TypeValue::String, default_value: Some("f\"flower power: {POWER}\"".to_string()),
|
||||||
|
},
|
||||||
|
Unit::Settings {
|
||||||
|
docstring: None, name: "Test".to_string(),
|
||||||
|
parameters: vec![
|
||||||
|
Unit::Parameter {
|
||||||
|
name: "forbid_indexing".to_string(),
|
||||||
|
default_value: "True".to_string(),
|
||||||
|
},
|
||||||
|
Unit::Parameter {
|
||||||
|
name: "forbid_optional_indexing".to_string(),
|
||||||
|
default_value: "True".to_string(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Unit::Enum {
|
||||||
|
docstring: None, name: "EncryptionMode".to_string(),
|
||||||
|
variants: vec![
|
||||||
|
Unit::EnumVariant { name: "None".to_string(), kind: None },
|
||||||
|
Unit::EnumVariant { name: "Encrypt".to_string(), kind: None }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compile_unit() {
|
||||||
|
let unit = idl::parser::from_path(
|
||||||
|
format!("tests/idl/simple.{}", SCHEMA_EXTENSION).as_str()
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
let context = ir::context::Context::with_main(unit);
|
||||||
|
|
||||||
|
let interpreted = compiler::interpret_unit(context);
|
||||||
|
|
||||||
|
println!("{:?}", interpreted);
|
||||||
|
}
|
Loading…
Reference in a new issue