From fc6686a2a129f54bb88c382a30fedd58259decc8 Mon Sep 17 00:00:00 2001 From: DOOM1EM8Cover Date: Fri, 1 Sep 2023 04:14:35 +0100 Subject: [PATCH] Started codegen work for a few languages, more interpretation changes, and overall work --- core/Cargo.toml | 2 +- core/src/autodoc/schema.rs | 4 +- core/src/codegen/lua/lib.lua | 3 + core/src/codegen/luau/luau.rs | 52 +++ core/src/codegen/luau/mod.rs | 21 ++ core/src/codegen/mod.rs | 25 +- core/src/codegen/python/_3_11_0.rs | 151 ++++++++ core/src/codegen/python/mod.rs | 19 + core/src/codegen/rust.rs | 102 ------ core/src/codegen/rust/_1_7_0.rs | 169 +++++++++ core/src/codegen/rust/mod.rs | 19 + core/src/lib.rs | 4 +- core/src/project/build/mod.rs | 43 ++- core/src/project/idl/parser_new.rs | 6 +- core/src/project/ir/compiler/interpret.rs | 23 +- core/src/project/ir/compiler/report.rs | 7 +- core/src/project/ir/context.rs | 25 +- core/src/project/ir/diff/mod.rs | 4 +- core/src/project/ir/frozen/loader.rs | 2 +- core/src/project/ir/frozen/mod.rs | 2 +- core/src/project/ir/interpreter/freezing.rs | 19 +- core/src/project/ir/interpreter/interpret.rs | 6 +- core/src/project/ir/interpreter/mod.rs | 1 - core/src/project/ir/interpreter/report.rs | 10 +- core/src/report.rs | 34 +- core/src/schema/idl/ast/unit.rs | 5 +- core/src/schema/idl/idl.pest | 9 +- core/src/schema/idl/parser.rs | 10 +- core/src/schema/idl/parser_new.rs | 27 +- .../ir/compiler/interpreted/interpreter.rs | 296 --------------- .../{primitive.rs => kind_search.rs} | 156 ++++++-- .../src/schema/ir/compiler/interpreted/mod.rs | 3 +- .../ir/compiler/interpreted/sanitizer.rs | 2 +- .../ir/compiler/interpreter/meta_stage.rs | 79 ++-- .../ir/compiler/interpreter/object_stage.rs | 337 +++++++++++++++++- .../ir/compiler/interpreter/semi_frozen.rs | 26 +- core/src/schema/ir/compiler/mod.rs | 4 +- core/src/schema/ir/compiler/report.rs | 62 ++-- core/src/schema/ir/context.rs | 35 +- core/src/schema/ir/diff/mod.rs | 6 +- core/src/schema/ir/frozen/unit.rs | 17 +- core/tests/autodoc/mod.rs | 2 +- core/tests/idl/unit.rs | 6 +- core/tests/package/test/config.idp | 2 + .../generated/0.0.1/rust/1.70.0/health.rs | 0 .../test/generated/python/3.11.0/health.py | 14 + .../test/generated/python/3.11.0/ping.py | 16 + .../test/generated/rust/1.70.0/health.rs | 8 + .../test/generated/rust/1.70.0/ping.rs | 10 + core/tests/package/test/health.ids | 6 +- core/tests/package/test/ping.ids | 10 +- 51 files changed, 1250 insertions(+), 651 deletions(-) create mode 100644 core/src/codegen/lua/lib.lua create mode 100644 core/src/codegen/luau/luau.rs create mode 100644 core/src/codegen/luau/mod.rs create mode 100644 core/src/codegen/python/_3_11_0.rs create mode 100644 core/src/codegen/python/mod.rs delete mode 100644 core/src/codegen/rust.rs create mode 100644 core/src/codegen/rust/_1_7_0.rs create mode 100644 core/src/codegen/rust/mod.rs delete mode 100644 core/src/schema/ir/compiler/interpreted/interpreter.rs rename core/src/schema/ir/compiler/interpreted/{primitive.rs => kind_search.rs} (55%) delete mode 100644 core/tests/package/test/generated/0.0.1/rust/1.70.0/health.rs create mode 100644 core/tests/package/test/generated/python/3.11.0/health.py create mode 100644 core/tests/package/test/generated/python/3.11.0/ping.py create mode 100644 core/tests/package/test/generated/rust/1.70.0/health.rs create mode 100644 core/tests/package/test/generated/rust/1.70.0/ping.rs diff --git a/core/Cargo.toml b/core/Cargo.toml index fdc22bf..4380e67 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -19,7 +19,7 @@ semver = "1.0.18" blake3 = "1.4.1" lz4_flex = "0.11.1" lex = "0.6.0" -snafu = "0.7.5" +snafu = { version = "0.7.5", features = ["guide"] } strum_macros = "0.25.1" strum = { version = "0.25.0", features = ["derive"] } downcast-rs = "1.2.0" diff --git a/core/src/autodoc/schema.rs b/core/src/autodoc/schema.rs index 21f2455..ba87015 100644 --- a/core/src/autodoc/schema.rs +++ b/core/src/autodoc/schema.rs @@ -3,7 +3,7 @@ // Crate Uses use crate::schema::ir::diff::Differ; use crate::schema::ir::frozen::unit::FrozenUnit; -use crate::schema::ir::compiler::interpreted::primitive::KindValue; +use crate::schema::ir::compiler::interpreted::kind_search::KindValue; // External Uses @@ -61,7 +61,7 @@ impl Differ for Document { if left_value_display != right_value_display { self.minor_changes.push( format!( - "Constant '{}' default value changed from '{}' to '{}'", name, + "Constant '{}' default value changed from '{:?}' to '{:?}'", name, left_value_display, right_value_display ) ) diff --git a/core/src/codegen/lua/lib.lua b/core/src/codegen/lua/lib.lua new file mode 100644 index 0000000..30fc2b4 --- /dev/null +++ b/core/src/codegen/lua/lib.lua @@ -0,0 +1,3 @@ + +-- https://andrejs-cainikovs.blogspot.com/2009/05/lua-constants.html +-- http://lua-users.org/wiki/ReadOnlyTables diff --git a/core/src/codegen/luau/luau.rs b/core/src/codegen/luau/luau.rs new file mode 100644 index 0000000..361fb3d --- /dev/null +++ b/core/src/codegen/luau/luau.rs @@ -0,0 +1,52 @@ +// Standard Uses + +// Crate Uses +use crate::schema::ir::frozen::unit::FrozenUnit; + +// External Uses + + +pub(crate) fn frozen_to_code(units: &Vec) -> String { + let mut code = String::new(); + + let mut code = "// Generated code with Comline compiler and code generator\n\n" + .to_owned(); + + for unit in units { code += &*unit_to_code(&unit); } + + code +} + +fn unit_to_code(frozen_unit: &FrozenUnit) -> String { + let mut code = String::new(); + + use FrozenUnit::*; + match frozen_unit { + Namespace(_) => {} + Import(_) => {} + Constant { docstring, name, kind_value } => { + let (kind_name, kind_value) = kind_value.name_and_value(); + code += &*format!("const {name}: {}", kind_name); + + if let Some(value) = kind_value { + code += &*format!(" = {value}"); + } + + code += ";\n"; + } + Property { .. } => {} + Parameter { .. } => {} + ExpressionBlock { .. } => {} + Enum { .. } => {} + EnumVariant(_) => {} + Settings { .. } => {} + Struct { .. } => {} + Protocol { .. } => {} + Function { .. } => {} + Error { .. } => {} + Validator { .. } => {} + _ => panic!("Reached forbidden or unimplemented node") + } + + code +} diff --git a/core/src/codegen/luau/mod.rs b/core/src/codegen/luau/mod.rs new file mode 100644 index 0000000..b1121fc --- /dev/null +++ b/core/src/codegen/luau/mod.rs @@ -0,0 +1,21 @@ +// https://luau-lang.org/ + +// Relative Modules +pub mod luau; + +// Standard Uses +use std::collections::HashMap; + +// Crate Uses +use crate::codegen::VersionGenerators; + +// External Uses +use once_cell::sync::Lazy; + + +pub(crate) static GENERATORS: VersionGenerators = Lazy::new(|| { + HashMap::from([ + ("Luau", luau::frozen_to_code as _) + ]) +}); + diff --git a/core/src/codegen/mod.rs b/core/src/codegen/mod.rs index 5dde353..c762851 100644 --- a/core/src/codegen/mod.rs +++ b/core/src/codegen/mod.rs @@ -1,5 +1,7 @@ // Relative Modules -pub mod rust; +pub(crate) mod rust; +pub(crate) mod luau; +pub(crate) mod python; // Standard Uses use std::collections::HashMap; @@ -11,18 +13,25 @@ use crate::schema::ir::frozen::unit::FrozenUnit; use once_cell::sync::Lazy; +pub type VersionGenerators = Lazy>; pub type GeneratorFn = fn(&Vec) -> String; +pub type Generator = (GeneratorFn, &'static str); -static GENERATORS: Lazy> = Lazy::new(|| { +static LANG_GENERATORS: Lazy> = Lazy::new(|| { HashMap::from([ - ("rust", rust::frozen_unit_to_code as _), + ("rust", (&rust::GENERATORS, "rs")), + + ("luau", (&luau::GENERATORS, "luau")), + ("python", (&python::GENERATORS, "py")) ]) }); -pub fn find_generator(name: &str) -> Option<&GeneratorFn> { - if !GENERATORS.contains_key(name) { - return None - } +pub fn find_generator(name: &str, version: &str) -> Option<(&'static GeneratorFn, &'static str)> { + if let Some((lang_generator, extension)) = LANG_GENERATORS.get(name) { + if let Some(version_generator) = lang_generator.get(version) { + return Some((version_generator, extension)) + } + }; - GENERATORS.get(name) + None } diff --git a/core/src/codegen/python/_3_11_0.rs b/core/src/codegen/python/_3_11_0.rs new file mode 100644 index 0000000..8273255 --- /dev/null +++ b/core/src/codegen/python/_3_11_0.rs @@ -0,0 +1,151 @@ +// Standard Uses + +// Crate Uses +use crate::schema::ir::frozen::unit::{FrozenArgument, FrozenUnit}; +use crate::schema::ir::compiler::interpreted::kind_search::KindValue; + +// External Uses +use eyre::anyhow; + + +#[allow(unused)] +pub fn frozen_to_code(units: &Vec) -> String { + let mut code = "\ + # Generated code with Comline compiler and code generator\n\n" + .to_owned(); + + code += "\ + import typing\n\ + import ctypes\n\ + \n\n\ + "; + + for unit in units { code += &*unit_to_code(&unit); } + + code +} + +#[allow(unused)] +fn unit_to_code(frozen_unit: &FrozenUnit) -> String { + let mut code = String::new(); + + use FrozenUnit::*; + match frozen_unit { + Namespace(_) => {} + Import(_) => {} + Constant { docstring, name, kind_value } => { + let (kind_name, default_value) = kind_value.name_and_value(); + + let Ok(kind_py) = from_frozen_kind_to_python_kind(kind_value) else { + panic!("No appropriate kind was found for '{kind_name}'") + }; + + // Name and kind + code += &*format!("{name}: typing.Final[{kind_py}]"); + + // Value + if let Some(value) = default_value { + code += &*format!(" = {value}"); + } + + code += "\n\n"; + } + Property { .. } => {} + Parameter { .. } => {} + ExpressionBlock { .. } => {} + Enum { .. } => {} + EnumVariant(_) => {} + Settings { .. } => {} + Struct { .. } => {} + Protocol { + docstring, parameters, + name, functions + } => { + // Async + // TODO: Can we signify assyncness in python protocols, or if its that important, ABCs? + // Associated methods already can be marked "async" + + // Class Start + code += &*format!("class {name}(typing.Protocol):\n"); + + // Functions + for function in functions { + code += &*unit_to_code(function); + } + + // Class End + code += "\n"; + } + Function { + docstring, name, synchronous, + arguments, returns, + throws + } => { + // Async definition + if !synchronous { code += "async "; } + + // Function Start + code += &*format!("\tdef {name}("); + + // Arguments + code += "self"; + + let mut idx = 0; + while idx != arguments.len() { + let FrozenArgument { name, kind } + = arguments.get(idx).unwrap(); + + let (kind_name, kind_value) = kind.name_and_value(); + code += &*format!("{}: {:?}", name, kind_name); + + if idx != arguments.len() { code += ", " } + + idx += 1; + } + + // Arguments End + code += "):\n\t\t...\n\n"; + + // Returns + // code += format!("-> {}", return) + + // Function End + } + Error { .. } => {} + Validator { .. } => {} + _ => panic!("Reached forbidden or unimplemented node") + } + + code +} + +fn from_frozen_kind_to_python_kind(kind_value: &KindValue) -> eyre::Result { + let kind = match kind_value { + KindValue::Primitive(primitive) => { + let name = primitive.name(); + from_frozen_primitive_to_ctypes(name) + .ok_or_else(|| anyhow!("No primitive equivalent found for {name}"))? + } + KindValue::EnumVariant(_, _) => { + todo!() + } + KindValue::Union(_) => { + todo!() + } + KindValue::Namespaced(_, _) => { + todo!() + } + }; + + Ok(kind) +} + +fn from_frozen_primitive_to_ctypes(primitive: &str) -> Option { + let kind = match primitive { + "u8" => "c_uint8", + "u16" => "c_uint16", + _ => { return None } + }; + + Some(format!("ctypes.{kind}")) +} diff --git a/core/src/codegen/python/mod.rs b/core/src/codegen/python/mod.rs new file mode 100644 index 0000000..2dfa150 --- /dev/null +++ b/core/src/codegen/python/mod.rs @@ -0,0 +1,19 @@ +// Relative Modules +pub(crate) mod _3_11_0; + +// Standard Uses +use std::collections::HashMap; + +// Crate Uses +use crate::codegen::VersionGenerators; + +// External Uses +use once_cell::sync::Lazy; + + +pub(crate) static GENERATORS: VersionGenerators = Lazy::new(|| { + HashMap::from([ + ("3.11.0", _3_11_0::frozen_to_code as _) + ]) +}); + diff --git a/core/src/codegen/rust.rs b/core/src/codegen/rust.rs deleted file mode 100644 index 5c3b038..0000000 --- a/core/src/codegen/rust.rs +++ /dev/null @@ -1,102 +0,0 @@ -// Standard Uses - -// Crate Uses -use crate::schema::ir::frozen::unit::FrozenUnit; - -// External Uses - - -#[allow(unused)] -pub fn frozen_unit_to_code(units: &Vec) -> String { - - "".to_owned() -} - -/* -fn unit_to_code(frozen_unit: FrozenUnit) -> String { - let mut code = String::new(); - - use FrozenUnit::*; - match frozen_unit { - Tag(_) => {} - Namespace(_) => {} - Import(_) => {} - Constant { .. } => {} - Property { .. } => {} - Parameter { .. } => {} - ExpressionBlock { .. } => {} - Enum { .. } => {} - EnumVariant(_) => {} - Settings { .. } => {} - Struct { .. } => {} - Protocol { .. } => {} - Function { .. } => {} - Error { .. } => {} - Validator { .. } => {} - _ => panic!("Reached forbidden or unimplemented node") - } - - code -} - -fn protocol_to_code(unit: FrozenUnit) -> String { - let FrozenUnit::Protocol { - docstring, parameters, name, functions - } = unit else { panic!() }; - - let mut code = String::new(); - - // Trait Start - // TODO: Maybe only include async_trait if at least one of the functions need it - code.push_str("#[async_trait]"); - code.push_str(&*format!("pub trait {} {{", name)); - - // Functions - for function in functions { - let FrozenUnit::Function { - docstring, name, synchronous, direction, - arguments, returns, throws - } = function else { panic!() }; - - let mut fn_code = String::new(); - - // Async definition (with async_trait) - if !synchronous { - fn_code.push_str("async "); - } - - // Fn - fn_code.push_str(&*format!("fn {} (", name)); - - // Arguments - let mut idx = 0; - while idx != arguments.len() { - let FrozenUnit::Parameter { - name, default_value - } = arguments.get(idx).unwrap(); - - if argument.id.is_none() { - fn_code.push_str(&*format!("arg{}: {:?}", idx, argument.type_)); - if idx != arguments.len() { fn_code.push_str(", ") } - } else { - fn_code.push_str( - &*format!("{}: {:?}", argument.id.clone().unwrap(), argument.type_) - ); - if idx != arguments.len() { fn_code.push_str(", ") } - } - - idx += 1; - } - - // Returns - - code.push_str(&*fn_code) - } - - // Trait End - code.push_str("}}"); - - code.to_owned() -} -*/ - diff --git a/core/src/codegen/rust/_1_7_0.rs b/core/src/codegen/rust/_1_7_0.rs new file mode 100644 index 0000000..f6b3828 --- /dev/null +++ b/core/src/codegen/rust/_1_7_0.rs @@ -0,0 +1,169 @@ +// Standard Uses + +// Crate Uses +use crate::schema::ir::frozen::unit::{FrozenArgument, FrozenUnit}; + +// External Uses + + +#[allow(unused)] +pub fn frozen_to_code(units: &Vec) -> String { + let mut code = "// Generated code with Comline compiler and code generator\n\n" + .to_owned(); + + for unit in units { code += &*unit_to_code(&unit); } + + code +} + +#[allow(unused)] +fn unit_to_code(frozen_unit: &FrozenUnit) -> String { + let mut code = String::new(); + + use FrozenUnit::*; + match frozen_unit { + Namespace(_) => {} + Import(_) => {} + Constant { docstring, name, kind_value } => { + let (kind_name, kind_value) = kind_value.name_and_value(); + code += &*format!("pub const {name}: {}", kind_name); + + if let Some(value) = kind_value { + code += &*format!(" = {value}"); + } + + code += ";\n\n"; + } + Property { .. } => {} + Parameter { .. } => {} + ExpressionBlock { .. } => {} + Enum { .. } => {} + EnumVariant(_) => {} + Settings { .. } => {} + Struct { .. } => {} + Protocol { + docstring, parameters, + name, functions + } => { + // Async + // TODO: Only include async_trait if at least one of the functions needs it + // code += "#[async_trait]\n"; + + // Trait Start + code += &*format!("pub trait {} {{\n", name); + + // Functions + for function in functions { + code += &*unit_to_code(function); + } + + // Trait End + code += "\n}\n\n"; + } + Function { + docstring, name, synchronous, + arguments, returns, + throws + } => { + code += "\t"; + + // Async definition (with async_trait) + if !synchronous { code += "async "; } + + // Function Start + code += &*format!("fn {} (", name); + code += "&self"; + + // Arguments + let mut idx = 0; + while idx != arguments.len() { + let FrozenArgument { name, kind } + = arguments.get(idx).unwrap(); + + let (kind_name, kind_value) = kind.name_and_value(); + code += &*format!("{}: {:?}", name, kind_name); + + if idx != arguments.len() { code += ", " } + + idx += 1; + } + + // Arguments End + code += ")"; + + // Returns + // code += format!("-> {}", return) + + // Function End + code += ";\n"; + } + Error { .. } => {} + Validator { .. } => {} + _ => panic!("Reached forbidden or unimplemented node") + } + + code +} + +/* +fn protocol_to_code(unit: FrozenUnit) -> String { + let FrozenUnit::Protocol { + docstring, parameters, name, functions + } = unit else { panic!() }; + + let mut code = String::new(); + + // Trait Start + // TODO: Maybe only include async_trait if at least one of the functions need it + code.push_str("#[async_trait]"); + code.push_str(&*format!("pub trait {} {{", name)); + + // Functions + for function in functions { + let FrozenUnit::Function { + docstring, name, synchronous, direction, + arguments, returns, throws + } = function else { panic!() }; + + let mut fn_code = String::new(); + + // Async definition (with async_trait) + if !synchronous { + fn_code.push_str("async "); + } + + // Fn + fn_code.push_str(&*format!("fn {} (", name)); + + // Arguments + let mut idx = 0; + while idx != arguments.len() { + let FrozenUnit::Parameter { + name, default_value + } = arguments.get(idx).unwrap(); + + if argument.id.is_none() { + fn_code.push_str(&*format!("arg{}: {:?}", idx, argument.type_)); + if idx != arguments.len() { fn_code.push_str(", ") } + } else { + fn_code.push_str( + &*format!("{}: {:?}", argument.id.clone().unwrap(), argument.type_) + ); + if idx != arguments.len() { fn_code.push_str(", ") } + } + + idx += 1; + } + + // Returns + + code.push_str(&*fn_code) + } + + // Trait End + code.push_str("}}"); + + code.to_owned() +} +*/ + diff --git a/core/src/codegen/rust/mod.rs b/core/src/codegen/rust/mod.rs new file mode 100644 index 0000000..e47d42f --- /dev/null +++ b/core/src/codegen/rust/mod.rs @@ -0,0 +1,19 @@ +// Relative Modules +pub(crate) mod _1_7_0; + +// Standard Uses +use std::collections::HashMap; + +// Crate Uses +use crate::codegen::VersionGenerators; + +// External Uses +use once_cell::sync::Lazy; + + +pub(crate) static GENERATORS: VersionGenerators = Lazy::new(|| { + HashMap::from([ + ("1.70.0", _1_7_0::frozen_to_code as _) + ]) +}); + diff --git a/core/src/lib.rs b/core/src/lib.rs index ae5dc48..ba15eb8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,8 +1,8 @@ +#![deny(rust_2018_idioms)] + // Extern -extern crate pest; #[macro_use] extern crate pest_derive; -extern crate serde; #[macro_use] extern crate serde_derive; extern crate rmp_serde as rmps; diff --git a/core/src/project/build/mod.rs b/core/src/project/build/mod.rs index 3271e95..7f9e832 100644 --- a/core/src/project/build/mod.rs +++ b/core/src/project/build/mod.rs @@ -1,10 +1,10 @@ -use std::cell::RefCell; // Standard Uses use std::path::Path; use std::collections::HashMap; use std::fs::File; use std::io::Write; use std::rc::Rc; +use std::cell::RefCell; // Crate Uses use crate::codegen; @@ -54,7 +54,9 @@ pub fn build(path: &Path) -> Result<()> { let unit = idl::parser_new::from_path(concrete_path)?; - let context = ir::context::SchemaContext::with_project_and_main(unit); + let context = ir::context::SchemaContext::with_project_and_main( + unit, concrete_path.file_stem().unwrap().to_str().unwrap().to_owned() + ); compiled_project.add_schema_context( Rc::new(RefCell::new(context)) @@ -63,13 +65,14 @@ pub fn build(path: &Path) -> Result<()> { compiler::interpret::interpret_context(&mut compiled_project)?; - generate_code_for_targets(&mut compiled_project, &frozen)?; + generate_code_for_targets(&mut compiled_project, &frozen, path)?; Ok(()) } pub fn generate_code_for_targets<'a>( - compiled_project: &mut ProjectContext<'a>, frozen_units: &'a Vec + compiled_project: &'a mut ProjectContext<'a>, frozen_units: &'a Vec, + base_path: &Path ) -> Result<()> { for item in frozen_units.iter() { match item { @@ -85,18 +88,20 @@ pub fn generate_code_for_targets<'a>( }; let path = resolve_path_query(&details.generation_path, args).unwrap(); - let path = Path::new(&path); + let path = base_path.join(path); - let generator = codegen::find_generator(name); - - if generator.is_none() { + let Some((gen_fn, extension)) = + codegen::find_generator(name, version) else + { panic!( - "No generator found for language named {} with version {}", + "No generator found for language named '{}' with version '{}'", name, version ) - } + }; - generate_code_for_context(&compiled_project, generator, &path)?; + generate_code_for_context( + &compiled_project, gen_fn, extension, &path + )?; }, _ => {} } @@ -125,19 +130,23 @@ pub fn resolve_path_query(query: &Option, args: Args) -> Result, +pub fn generate_code_for_context<'a>( + context: &ProjectContext<'a>, + generator: &GeneratorFn, extension: &str, target_path: &Path ) -> Result<()> { + std::fs::create_dir_all(target_path)?; + for schema_context in context.schema_contexts.iter() { let schema_ctx = schema_context.borrow(); let frozen_schema = schema_ctx.frozen_schema.as_ref().unwrap(); + let file_path = target_path.join( + format!("{}.{}", &schema_ctx.name, extension) + ); - let mut code = "Generated code with Comline compiler".to_owned(); + let code = &*generator(frozen_schema); - code += &*generator.unwrap()(frozen_schema); - - std::fs::write(target_path, code).unwrap(); + std::fs::write(file_path, code).unwrap(); } Ok(()) diff --git a/core/src/project/idl/parser_new.rs b/core/src/project/idl/parser_new.rs index 1d4fc4b..cd47193 100644 --- a/core/src/project/idl/parser_new.rs +++ b/core/src/project/idl/parser_new.rs @@ -49,7 +49,7 @@ pub fn parse_source(source: String, name: String) -> Result { Ok((codemap, units)) } -pub fn parse_inner(pair: Pair, file: &Arc) -> Result { +pub fn parse_inner(pair: Pair<'_, Rule>, file: &Arc) -> Result { match pair.as_rule() { Rule::congregation => { let span = pair.as_span(); @@ -96,7 +96,7 @@ pub fn parse_inner(pair: Pair, file: &Arc) -> Result #[allow(unused)] -fn parse_assignment(pair: Pair, file: &Arc) -> Result { +fn parse_assignment(pair: Pair<'_, Rule>, file: &Arc) -> Result { let unit = match pair.as_rule() { Rule::number => { Ok(AssignmentUnit::Number(pair.as_str().parse().unwrap())) @@ -156,7 +156,7 @@ fn parse_assignment(pair: Pair, file: &Arc) -> Result, file: &Arc) -> Result { +fn parse_list_item(pair: Pair<'_, Rule>, file: &Arc) -> Result { let span = pair.as_span(); let item_span = file.insert_span(span.start(), span.end()); diff --git a/core/src/project/ir/compiler/interpret.rs b/core/src/project/ir/compiler/interpret.rs index 5beb223..70c058c 100644 --- a/core/src/project/ir/compiler/interpret.rs +++ b/core/src/project/ir/compiler/interpret.rs @@ -1,32 +1,29 @@ // Standard Uses +use std::rc::Rc; // Crate Uses use crate::project::ir::context::ProjectContext; -use crate::schema::ir::compiler::interpreter::meta_stage; +use crate::schema::ir::compiler::interpreter::{meta_stage, object_stage}; // External Uses use eyre::{anyhow, Result}; -pub fn interpret_context<'a>( - // project_context: &'a RefCell>, - project_context: &'a ProjectContext<'a>, -) -> Result<()> { - let len = project_context.schema_contexts.len(); - - for i in 0..len { +pub fn interpret_context(project_context: &ProjectContext<'_>) -> Result<()> { + for schema_context in project_context.schema_contexts.iter() { meta_stage::compile_schema_metadata( - &project_context.schema_contexts[i], + Rc::clone(&schema_context), project_context ).map_err(|e| anyhow!("{}", e))?; } - /* for schema_context in project_context.schema_contexts.iter() { - interpreter::interpret_context(schema_context, project_context) - .map_err(|e| anyhow!("{}", e))?; + object_stage::compile_schema( + Rc::clone(&schema_context), + project_context + ).map_err(|e| anyhow!("{}", e))?; } - */ Ok(()) } + diff --git a/core/src/project/ir/compiler/report.rs b/core/src/project/ir/compiler/report.rs index fb92696..dda4d32 100644 --- a/core/src/project/ir/compiler/report.rs +++ b/core/src/project/ir/compiler/report.rs @@ -11,16 +11,13 @@ use snafu::Snafu; #[derive(Debug, Snafu)] #[snafu(visibility(pub(crate)))] pub enum CompileError { - // #[strum(props(Id="2"))] #[snafu(display("Found namespace '{target}' when its already declared in '{origin}'"))] - Namespace { origin: String, target: String }, + Namespace { origin: String, target: String } = 0, - // #[strum(props(Id="2"))] #[snafu(display("Spec version was not assigned'"))] // SpecVersionNotTold { source: Box } SpecVersionNotTold { source: io::Error }, - // #[strum(props(Id="2"))] #[snafu(display("Schema paths list is empty, at least one schema is required'"))] // SpecVersionNotTold { source: Box } SchemaPathsEmpty, @@ -36,4 +33,4 @@ impl From for Error { } */ -pub type CompileResult = std::result::Result; +pub type CompileResult = Result; diff --git a/core/src/project/ir/context.rs b/core/src/project/ir/context.rs index 8642408..c5ded69 100644 --- a/core/src/project/ir/context.rs +++ b/core/src/project/ir/context.rs @@ -50,7 +50,7 @@ impl<'a> ProjectContext<'a> { ) } - pub(crate) fn add_relative_project_context(mut self, context: Rc) { + pub(crate) fn add_relative_project_context(mut self, context: Rc>) { todo!() } @@ -63,7 +63,7 @@ impl<'a> ProjectContext<'a> { } pub(crate) fn find_schema_by_import(&self, import: &str) - -> Option<&'a Rc>> + -> Option<&Rc>>> { for schema_context in self.schema_contexts.iter() { let units = &schema_context.borrow().schema.1; @@ -79,6 +79,23 @@ impl<'a> ProjectContext<'a> { None } + /* + pub(crate) fn find_schema_by_import(&self, import: &str) + -> Option<&Rc>>> + { + for schema_context in self.schema_contexts.iter() { + let schema_ctx = schema_context.borrow(); + let state = schema_ctx.compile_state.borrow(); + + if let Some(state) = &state.namespace { + return Some(schema_context) + } + } + + None + } + */ + /* pub(crate) fn find_whole_unit_by_import(&self, import: &str) -> Option<&WholeUnit> { if self.include_stdlib { @@ -97,7 +114,9 @@ impl<'a> ProjectContext<'a> { } */ - pub(crate) fn find_relative_project_context(&self, import: &str) -> Option<&ProjectContext> { + pub(crate) fn find_relative_project_context(&self, import: &str) + -> Option<&ProjectContext<'a>> + { todo!() } diff --git a/core/src/project/ir/diff/mod.rs b/core/src/project/ir/diff/mod.rs index c999cc7..d793e4a 100644 --- a/core/src/project/ir/diff/mod.rs +++ b/core/src/project/ir/diff/mod.rs @@ -24,8 +24,8 @@ pub trait Differ: Downcast + Debug { // fn on_assignment_changed(&self, old: AssignmentUnit, new: AssignmentUnit); #[allow(unused)] - fn differ( - &self, previous: &Vec, next: &FrozenWhole, + fn differ<'a>( + &self, previous: &Vec, next: &FrozenWhole<'a>, document_gen: bool, auto_version: bool ) { // differ(previous, next, document_gen, auto_version) diff --git a/core/src/project/ir/frozen/loader.rs b/core/src/project/ir/frozen/loader.rs index f948388..835b657 100644 --- a/core/src/project/ir/frozen/loader.rs +++ b/core/src/project/ir/frozen/loader.rs @@ -9,7 +9,7 @@ use eyre::Result; #[allow(unused)] -pub fn from_frozen_origin(path: &Path) -> Option { +pub fn from_frozen_origin(path: &Path) -> Option> { // let context = from_frozen_objects(&project_path); todo!() diff --git a/core/src/project/ir/frozen/mod.rs b/core/src/project/ir/frozen/mod.rs index 9286f7b..0a6d49e 100644 --- a/core/src/project/ir/frozen/mod.rs +++ b/core/src/project/ir/frozen/mod.rs @@ -47,7 +47,7 @@ pub struct PublishTarget { } pub fn schema_paths(units: &Vec) - -> FilterMap, fn(&FrozenUnit) -> Option<&str>> + -> FilterMap, fn(&FrozenUnit) -> Option<&str>> { units.iter().filter_map(|unit| { match unit { diff --git a/core/src/project/ir/interpreter/freezing.rs b/core/src/project/ir/interpreter/freezing.rs index 70569f2..5fca56d 100644 --- a/core/src/project/ir/interpreter/freezing.rs +++ b/core/src/project/ir/interpreter/freezing.rs @@ -2,18 +2,17 @@ // Crate Uses use crate::project::idl::ast::{AssignmentUnit, ASTUnit, DictKeyValue, ListItem}; -use crate::project::ir::compiler::report::CompileError; use crate::project::ir::context::ProjectContext; use crate::project::ir::frozen::{FrozenUnit, FrozenWhole, LanguageDetails, PublishTarget}; -use crate::report::ReportDetails; use crate::utils::codemap::Span; // External Uses #[allow(unused)] -pub fn interpret_node_into_frozen(context: &ProjectContext, node: &ASTUnit) - -> Result, ReportDetails> +pub fn interpret_node_into_frozen<'a>( + context: &ProjectContext<'a>, node: &ASTUnit +) -> Result, Box> { // use crate::project::idl::ast::ASTUnit::*; match node { @@ -27,9 +26,9 @@ pub fn interpret_node_into_frozen(context: &ProjectContext, node: &ASTUnit) } } -pub fn interpret_assignment( - context: &ProjectContext, name: &(Span, String), node: &(Span, AssignmentUnit) -) -> Result, ReportDetails> { +pub fn interpret_assignment<'a>( + context: &ProjectContext<'a>, name: &(Span, String), node: &(Span, AssignmentUnit) +) -> Result, Box> { let result = match &*name.1 { "specification_version" => { let AssignmentUnit::Number(version) = &node.1 else { @@ -84,7 +83,7 @@ pub fn interpret_assignment( } fn interpret_assignment_code_generation(items: &Vec) - -> Result, ReportDetails> + -> Result, Box> { let mut languages = vec![]; @@ -144,7 +143,7 @@ fn interpret_assignment_code_generation(items: &Vec) } fn interpret_assigment_publish_targets(items: &Vec) - -> Result, ReportDetails> + -> Result, Box> { let mut targets = vec![]; @@ -204,7 +203,7 @@ fn interpret_assigment_publish_targets(items: &Vec) #[allow(unused)] pub fn into_frozen_whole<'a>( context: &'a ProjectContext<'a>, interpreted: Vec -) -> Result> +) -> Result, Box> { todo!() // Ok((Rc::from(context), interpreted)) diff --git a/core/src/project/ir/interpreter/interpret.rs b/core/src/project/ir/interpreter/interpret.rs index 24c9d43..6438605 100644 --- a/core/src/project/ir/interpreter/interpret.rs +++ b/core/src/project/ir/interpreter/interpret.rs @@ -3,16 +3,14 @@ // Crate Uses use crate::project::ir::context::ProjectContext; use crate::project::ir::frozen::FrozenUnit; -use crate::project::ir::compiler::report::CompileError; use crate::project::ir::interpreter::freezing; -use crate::report::ReportDetails; // External Uses #[allow(unused)] -pub fn interpret_context<'a>(mut context: &ProjectContext) - -> Result, ReportDetails> +pub fn interpret_context<'a>(mut context: &ProjectContext<'a>) + -> Result, Box> { let mut interpreted = vec![]; diff --git a/core/src/project/ir/interpreter/mod.rs b/core/src/project/ir/interpreter/mod.rs index fd58763..0ede437 100644 --- a/core/src/project/ir/interpreter/mod.rs +++ b/core/src/project/ir/interpreter/mod.rs @@ -36,7 +36,6 @@ impl<'a> Compile for Interpreter<'a> { let frozen = interpret::interpret_context(&context) .map_err(|e| anyhow!("{:?}", e))?; - // Ok((RefCell::new(context), frozen)) Ok((context, frozen)) } diff --git a/core/src/project/ir/interpreter/report.rs b/core/src/project/ir/interpreter/report.rs index 1e5238a..21a8a73 100644 --- a/core/src/project/ir/interpreter/report.rs +++ b/core/src/project/ir/interpreter/report.rs @@ -1,20 +1,15 @@ // Standard Uses // Crate Uses -use crate::schema::ir::compiler::report::CompileWarning; -use crate::project::idl::ast::AssignmentUnit; -use crate::project::ir::compiler::report::CompileResult; -use crate::project::ir::frozen::Dependency; -use crate::report::ReportDetails; // External Uses - +/* #[allow(unused)] pub fn report_errors( spec_version: Option, schema_paths: Option>, dependencies: Option>, assignments: Vec -) -> CompileResult<()> { +) -> Result<(), dyn snafu::Error> { // let mut errors = vec![]; // let spec_version = spec_version.context(report::SpecVersionNotToldSnafu); @@ -48,3 +43,4 @@ pub fn report_warnings( warnings } +*/ diff --git a/core/src/report.rs b/core/src/report.rs index 21e7f58..4539dd0 100644 --- a/core/src/report.rs +++ b/core/src/report.rs @@ -1,32 +1,35 @@ // Standard Uses -use std::marker::PhantomData; +use std::cell::Ref; +use std::ops::Range; -// Local Uses +// Crate Uses use crate::schema::ir::context::SchemaContext; -use crate::schema::ir::compiler::report::CompileError; use crate::utils::codemap::Span; // External Uses -use ariadne::Color; #[derive(Debug)] -pub struct ReportDetails { - // pub id: u16, - // pub message: String, - pub(crate) phantom: PhantomData, // pub kind: T, - pub span: Option +pub struct ReportDetails { + pub line: Range, + pub pos: Range } -#[allow(unused)] -impl ReportDetails { - fn code(&self) -> u8 { - 0 +impl ReportDetails { + pub(crate) fn fetch( + schema_context: &Ref<'_, SchemaContext<'_>>, span: &Span + ) -> Option { + let pos = schema_context.schema.0.files().first() + .unwrap().range_of(*span).unwrap(); + + Some(Self { line: Default::default(), pos }) } } + +/* #[allow(unused)] -pub fn report_errors(context: SchemaContext, errors: Vec>) { +pub fn report_errors<'a>(context: SchemaContext<'_>, errors: Vec>) { let out = Color::Fixed(81); /* @@ -47,8 +50,9 @@ pub fn report_errors(context: SchemaContext, errors: Vec>) { +pub fn report_warnings(context: SchemaContext<'_>, warnings: Vec>) { todo!() } +*/ diff --git a/core/src/schema/idl/ast/unit.rs b/core/src/schema/idl/ast/unit.rs index 4cb10f5..7774b68 100644 --- a/core/src/schema/idl/ast/unit.rs +++ b/core/src/schema/idl/ast/unit.rs @@ -79,7 +79,9 @@ pub enum ASTUnit { throws: Vec<(Span, String)> }, Argument { - name: Option<(Span, String)>, // TODO: Having optional names might not be a good thing + // TODO: Having optional names might not be a good thing, think about it + // name: Option<(Span, String)>, + name: (Span, String), kind: (Span, String) }, Error { @@ -107,6 +109,7 @@ pub enum ASTUnit { } +#[allow(unused)] pub(crate) fn namespace(units: &Vec) -> &String { let mut namespace: Option<&String> = None; diff --git a/core/src/schema/idl/idl.pest b/core/src/schema/idl/idl.pest index 065c801..4dee683 100644 --- a/core/src/schema/idl/idl.pest +++ b/core/src/schema/idl/idl.pest @@ -134,7 +134,7 @@ protocol = { ~ "{" ~ WS? ~ function* ~ WS? ~ "}" } function = { - WS? ~ property* + WS? ~ docstring? ~ property* ~ (index ~ WS? ~ "#" ~ WS?)? ~ (asynchronous ~ WS?)? ~ (direction ~ WS?)? @@ -143,6 +143,7 @@ function = { ~ (WS? ~ "->" ~ WS? ~ returns+)? // ~ (WS? ~ ":" ~ WS? ~ parameter+)? ~ (WS? ~ "!" ~ WS? ~ throws)? + ~ ";" } direction = { "client" | "server" } @@ -153,15 +154,15 @@ argument = { ~ WS? } returns = { ","? ~ WS? ~ (kind) ~ WS? } -parameter = { - WS? ~ id ~ WS? ~ "=" ~ WS? ~ value ~ WS? -} throws = { function_call } // Common Rules +parameter = { + WS? ~ id ~ WS? ~ "=" ~ WS? ~ value ~ WS? +} property = { WS? ~ "@" ~ WS? ~ property_domain diff --git a/core/src/schema/idl/parser.rs b/core/src/schema/idl/parser.rs index 9a22b8f..f6d6434 100644 --- a/core/src/schema/idl/parser.rs +++ b/core/src/schema/idl/parser.rs @@ -175,7 +175,7 @@ pub fn parse_inner(pairs: Pair) -> Result { } */ -pub fn to_docstring(pair: Pair, file: &Arc) -> SpannedUnit { +pub fn to_docstring(pair: Pair<'_, Rule>, file: &Arc) -> SpannedUnit { let pair = pair.into_inner().next().unwrap(); match pair.as_rule() { @@ -238,7 +238,7 @@ pub fn to_parameters(mut pairs: Pairs) -> Vec { } */ -pub fn to_value_other(pair: Pair) -> Option { +pub fn to_value_other(pair: Pair<'_, Rule>) -> Option { let inner = pair.into_inner().next().unwrap(); match inner.as_rule() { @@ -252,7 +252,7 @@ pub fn to_value_other(pair: Pair) -> Option { } #[allow(unused)] -pub fn to_field(pair: Pair, file: &Arc) -> ASTUnit { +pub fn to_field(pair: Pair<'_, Rule>, file: &Arc) -> ASTUnit { let pairs = pair.into_inner(); let mut docstring = vec![]; @@ -298,7 +298,7 @@ pub fn to_property(pair: Pair, file: &Arc) -> ASTUnit { */ #[allow(unused)] -fn to_function(pair: Pair) -> ASTUnit { +fn to_function(pair: Pair<'_, Rule>) -> ASTUnit { let inner = pair.into_inner(); let mut synchronous = true; @@ -370,7 +370,7 @@ fn to_argument(pairs: Pairs) -> Argument { } */ -pub fn to_expression_block(pair: Pair) -> ASTUnit { +pub fn to_expression_block(pair: Pair<'_, Rule>) -> ASTUnit { let inner = pair.into_inner().next().unwrap(); // let mut expression = vec![]; diff --git a/core/src/schema/idl/parser_new.rs b/core/src/schema/idl/parser_new.rs index c4bbc0e..98be77e 100644 --- a/core/src/schema/idl/parser_new.rs +++ b/core/src/schema/idl/parser_new.rs @@ -1,10 +1,11 @@ // Standard Uses use std::path::Path; +use std::rc::Rc; use std::sync::Arc; // Local Uses use crate::utils::codemap::{CodeMap, FileMap}; -use crate::schema::idl::ast::unit::{ASTUnit, SourcedWhole, SpannedUnit}; +use crate::schema::idl::ast::unit::{ASTUnit, SourcedWholeRc, SpannedUnit}; // External Uses use eyre::{bail, Result}; @@ -18,7 +19,7 @@ pub struct SchemaParser; #[allow(unused)] -pub fn from_path(path: &Path) -> Result { +pub fn from_path(path: &Path) -> Result { if !path.exists() { bail!("Path doesn't exist: {:?}", path) } let source = std::fs::read_to_string(path).unwrap(); @@ -30,7 +31,7 @@ pub fn from_path(path: &Path) -> Result { sourced_whole } -pub fn parse_source(source: String, name: String) -> Result { +pub fn parse_source(source: String, name: String) -> Result { let mut codemap = CodeMap::new(); let file = codemap.insert_file(name, source.clone()); @@ -39,7 +40,7 @@ pub fn parse_source(source: String, name: String) -> Result { for pair in pairs { if let Ok(unit) = parse_inner(pair, &file) { - units.push(unit) + units.push(Rc::new(unit)) } } @@ -47,7 +48,7 @@ pub fn parse_source(source: String, name: String) -> Result { } #[allow(unused)] -pub fn parse_inner(pair: Pair, file: &Arc) -> Result { +pub fn parse_inner(pair: Pair<'_, Rule>, file: &Arc) -> Result { match pair.as_rule() { Rule::namespace => { let span = pair.as_span(); @@ -261,7 +262,7 @@ pub fn parse_inner(pair: Pair, file: &Arc) -> Result } -pub fn to_docstring(pair: Pair, file: &Arc) -> Result { +pub fn to_docstring(pair: Pair<'_, Rule>, file: &Arc) -> Result { let pair = pair.into_inner().next().unwrap(); match pair.as_rule() { @@ -299,7 +300,7 @@ pub fn to_docstring(pair: Pair, file: &Arc) -> Result, file: &Arc) -> Result { +pub fn to_parameter(pair: Pair<'_, Rule>, file: &Arc) -> Result { let pair_span = pair.as_span(); let unit_span = file.insert_span(pair_span.start(), pair_span.end()); let mut inner = pair.into_inner(); @@ -323,7 +324,7 @@ pub fn to_parameter(pair: Pair, file: &Arc) -> Result, file: &Arc) -> Result { +pub fn to_field(pair: Pair<'_, Rule>, file: &Arc) -> Result { let pair_span = pair.as_span(); let unit_span = file.insert_span(pair_span.start(), pair_span.end()); let mut inner = pair.into_inner(); @@ -354,7 +355,7 @@ pub fn to_field(pair: Pair, file: &Arc) -> Result { })) } -pub fn to_property(pair: Pair, file: &Arc) -> Result { +pub fn to_property(pair: Pair<'_, Rule>, file: &Arc) -> Result { let pair_span = pair.as_span(); let unit_span = file.insert_span(pair_span.start(), pair_span.end()); let inner = pair.into_inner().next().unwrap(); @@ -380,7 +381,7 @@ pub fn to_property(pair: Pair, file: &Arc) -> Result #[allow(unused)] -fn to_enum_variant(pair: Pair, file: &Arc) -> Result { +fn to_enum_variant(pair: Pair<'_, Rule>, file: &Arc) -> Result { let pair_span = pair.as_span(); let unit_span = file.insert_span(pair_span.start(), pair_span.end()); let inner = pair.into_inner(); @@ -405,7 +406,7 @@ fn to_enum_variant(pair: Pair, file: &Arc) -> Result } #[allow(unused)] -fn to_function(pair: Pair, file: &Arc) -> Result { +fn to_function(pair: Pair<'_, Rule>, file: &Arc) -> Result { let pair_span = pair.as_span(); let unit_span = file.insert_span(pair_span.start(), pair_span.end()); let inner = pair.into_inner(); @@ -436,10 +437,10 @@ fn to_function(pair: Pair, file: &Arc) -> Result { let kind_span = kind_pair.as_span(); arguments.push((unit_span, ASTUnit::Argument { - name: Some(( + name: ( file.insert_span(name_span.start(), name_span.end()), name_pair.as_str().to_owned() - )), + ), kind: ( file.insert_span(kind_span.start(), kind_span.end()), kind_pair.as_str().to_owned() diff --git a/core/src/schema/ir/compiler/interpreted/interpreter.rs b/core/src/schema/ir/compiler/interpreted/interpreter.rs deleted file mode 100644 index cb6156b..0000000 --- a/core/src/schema/ir/compiler/interpreted/interpreter.rs +++ /dev/null @@ -1,296 +0,0 @@ -// Standard Uses -use std::cell::RefMut; - -// Local Uses -use crate::schema::idl::ast::unit::{ASTUnit, SpannedUnit}; -use crate::schema::ir::context::SchemaContext; -use crate::schema::ir::compiler::interpreted::primitive::KindValue; -use crate::schema::ir::compiler::report::CompileError; -use crate::schema::ir::frozen::unit::FrozenUnit; -use crate::project::ir::context::ProjectContext; -use crate::report::ReportDetails; - -// External Uses - - - -#[allow(unused)] -pub fn interpret_context<'a>( - schema_context: &'a mut SchemaContext<'a>, - project_context: &'a RefMut> -) -> Result<(), ReportDetails> { - let mut interpreted: Vec = vec![]; - - for i in 0..schema_context.schema.1.len() { - let spanned_unit = &schema_context.schema.1[i]; - - use crate::schema::idl::ast::unit::ASTUnit::*; - match &spanned_unit.1 { - Namespace(s, n) => { - let name = n.clone(); - let Some(ctx) - = project_context.find_schema_by_import(&n) else - { - return Err(ReportDetails { - // kind: "Namespace".to_string(), - /* - message: format!( - "Namespace {} used in another schema: {} and {},\n \ - only one schema per namespace is allowed", - n, context.main.0.filename(), unit_namespace.unwrap().0.filename() - ), - start: 0, end: 0, - */ - phantom: Default::default(), - span: None, - }) - }; - - if let Some(name) = &schema_context.compile_state.borrow_mut().namespace { - panic!("Namespace {} was already previously set", name) - } else { - schema_context.compile_state.borrow_mut().namespace = Some(name) - } - } - Docstring {..} => { - todo!() - } - Import(s, i) => { - /* - let Some(ctx) - = project_context.find_schema_by_import(i) else { - panic!("No import") - }; - */ - } - // Docstring { .. } => {} - Constant { - docstring, name, - kind, default_value - } => { - /* - let kind_value = primitive::to_kind_value( - schema_context, kind, default_value - ); - */ - } - Property { .. } => {} - Parameter { .. } => {} - ExpressionBlock { .. } => {} - Enum { .. } => {} - EnumVariant { .. } => {} - Settings { .. } => {} - Struct { .. } => {} - Protocol { .. } => {} - Function { .. } => {} - Argument { .. } => {} - Error { .. } => {} - Validator { .. } => {} - Field { .. } => {} - } - } - - // Ok(context.unwrap().compile_state.to_frozen()) - Ok(()) - - /* - for (unit, span) in &context.config.1 { - use crate::schema::idl::ast::unit::ASTUnit::*; - match unit { - ASTUnit::Namespace(n) => { - let unit_namespace = context.find_whole_unit_by_import(n); - - /* - if unit_namespace.is_some() { - return Err(ReportDetails { - kind: "Namespace".to_string(), - message: format!( - "Namespace {} used in another schema: {} and {},\n \ - only one schema per namespace is allowed", - n, context.main.0.filename(), unit_namespace.unwrap().0.filename() - ), - start: 0, end: 0, - }) - } - */ - - interpreted.push(FrozenUnit::Namespace(n.clone())); - }, - Import(_) => { - let import = interpret_node(&context, unit)?; - interpreted.push(import); - } - Constant { .. } => { - let constant = interpret_node(&context, unit)?; - interpreted.push(constant); - } - Enum { .. } => { - let r#enum = interpret_node(&context, unit)?; - interpreted.push(r#enum); - } - /* - Unit::Settings { .. } => {} - Unit::Struct { .. } => {} - Unit::Protocol { .. } => {} - Unit::Error { .. } => {} - */ - - Validator { .. } => { - let validator = interpret_node(&context, unit)?; - interpreted.push(validator); - } - /* - //r => panic!("Left to impl: {:?}", r) - */ - _ => {} - } - } - */ -} - -#[allow(unused)] -pub fn interpret_node<'a>( - schema_context: &'a SchemaContext<'a>, - project_context: &'a ProjectContext<'a>, - node: &ASTUnit -) - -> Result> -{ - use crate::schema::idl::ast::unit::ASTUnit::*; - match node { - Namespace(_, n) => { - let mut found: Option<&SchemaContext> = None; - - /* - for relative_ctx in schema_ctx.borrow().schema_contexts.iter() { - if unit::namespace(&relative_ctx.schema.1) == n { - /* - if found.is_some() { - return Err(ReportDetails { - kind: "namespace".to_string(), - message: format!( - "Found namespace {} when its already declared in {}", - &n, &relative_ctx.main.0.filename() - ), - start: 0, end: 0, - }) - } - */ - - found = Some(relative_ctx) - } - } - */ - } - Import(_, i) => { - let relative_unit = project_context.find_schema_by_import(&i); - - /* - if relative_unit.is_none() { - let relative_unit = relative_unit.unwrap(); - - return Err(ReportDetails { - kind: "import".to_string(), - message: format!("Could not find namespace of {}", relative_unit.0.filename()), - start: 0, end: 0, - }) - } - */ - - return Ok(FrozenUnit::Import(i.clone())) - }, - Constant { - name: (_, name), kind: (_, kind), - default_value, .. - } => { - /* - let kind_value = primitive::to_kind_value(kind, default_value); - - return Ok(FrozenUnit::Constant { - docstring: None, - name: name.clone(), kind_value - }) - */ - } - Enum { name, variants, .. } => { - let mut frozen_variants: Vec = vec![]; - - for variant in variants { - pub(crate) fn to_variant(variant: &ASTUnit) -> KindValue { - match variant { - EnumVariant { name, kind } => { - if kind.is_none() { - return KindValue::EnumVariant( - name.1.clone(),None - ) - } - - return KindValue::EnumVariant( - name.1.clone(), None - ) - }, - _ => panic!("Should not be here") - } - } - - frozen_variants.push(FrozenUnit::EnumVariant( - to_variant(&variant.1) - )); - } - - return Ok(FrozenUnit::Enum { - docstring: None, - name: name.1.clone(), - variants: frozen_variants - }) - } - /* - EnumVariant { .. } => {} - Settings { .. } => {} - Struct { .. } => {} - Protocol { .. } => {} - Function { .. } => {} - Error { .. } => {} - */ - #[allow(unused)] - Validator { - docstring, properties, - name, expression_block - } => { - let properties = to_properties(properties); - let expr_block = Box::new(FrozenUnit::ExpressionBlock { function_calls: vec![] }); - - - return Ok(FrozenUnit::Validator { - docstring: Some("".to_owned()), // TODO: Docstrings should likely be a vector of units - properties: vec![], - name: name.1.clone(), - expression_block: expr_block - }) - } - /* - Field { .. } => {} - Parameter { .. } => {} - Property { .. } => {} - ExpressionBlock { .. } => {} - */ - missing => unimplemented!("Missing implementation for node '{:?}'", missing) - } - - panic!() -} - -#[allow(unused)] -fn to_properties(nodes: &Vec) -> Vec { - let properties = vec![]; - - for node in nodes { - - } - - properties -} - -pub fn into_frozen_unit() -> FrozenUnit { - todo!() -} diff --git a/core/src/schema/ir/compiler/interpreted/primitive.rs b/core/src/schema/ir/compiler/interpreted/kind_search.rs similarity index 55% rename from core/src/schema/ir/compiler/interpreted/primitive.rs rename to core/src/schema/ir/compiler/interpreted/kind_search.rs index 291d2ba..9d1eb26 100644 --- a/core/src/schema/ir/compiler/interpreted/primitive.rs +++ b/core/src/schema/ir/compiler/interpreted/kind_search.rs @@ -1,21 +1,28 @@ // Standard Uses +use std::cell::Ref; // Local Uses - -use std::cell::RefCell; -use std::rc::Rc; -// External Uses -use strum_macros::EnumProperty; use crate::schema::ir::context::SchemaContext; +use crate::schema::ir::compiler::report::CompileError; +use crate::schema::ir::compiler::report; +use crate::project::ir::context::ProjectContext; +use crate::report::ReportDetails; use crate::utils::codemap::Span; +// External Uses +use strum_macros::EnumProperty; +use snafu::ResultExt; -#[derive(Debug, Eq, PartialEq, Deserialize, Serialize)] -#[derive(EnumProperty)] + +#[derive(Debug, Eq, PartialEq)] +#[derive(Deserialize, Serialize, EnumProperty)] #[repr(u8)] pub enum Primitive { + #[strum(props(Name="bool", Description="boolean, 1 byte"))] + Boolean(Option) = 0, + #[strum(props(Name="u8", Description="unsigned 1 byte, 8 bits"))] - U8(Option) = 0, + U8(Option), #[strum(props(Name="u16", Description="unsigned 2 bytes, 16 bits"))] U16(Option), @@ -53,6 +60,9 @@ pub enum Primitive { impl Primitive { pub fn value_str(&self) -> Option { match self { + Primitive::Boolean(b) => { + if let Some(b) = b { Some(b.to_string()) } else { None } + } Primitive::U8(u) => { if let Some(u) = u { Some(u.to_string()) } else { None } } @@ -92,6 +102,11 @@ impl Primitive { } } + pub fn name(&self) -> &str { + use strum::EnumProperty; + self.get_str("Name").unwrap() + } + pub fn name_description(&self) -> String { use strum::EnumProperty; format!("{}({})", self.get_str("Name").unwrap(), self.get_str("Description").unwrap()) @@ -113,14 +128,14 @@ pub enum KindValue { Primitive(Primitive), EnumVariant(String, Option>), Union(Vec), - Namespaced(String) + Namespaced(String, Option>) } impl KindValue { - pub fn name_and_value(&self) -> (String, String) { + pub fn name_and_value(&self) -> (String, Option) { match self { KindValue::Primitive(primitive) => { - return (primitive.name_description(), primitive.value_str().unwrap()) + return (primitive.name().to_owned(), Some(primitive.value_str().unwrap())) } KindValue::EnumVariant(name, value) => { let value = value.as_ref().unwrap(); @@ -131,37 +146,121 @@ impl KindValue { todo!() } #[allow(unused)] - KindValue::Namespaced(namespace) => { + KindValue::Namespaced(namespace, ..) => { todo!() } } } } - -pub(crate) fn to_kind_value( - schema_context: &Rc>, +pub fn resolve_kind_value( + schema_context: &Ref<'_, SchemaContext<'_>>, project_context: &'_ ProjectContext<'_>, kind: &(Span, String), value: &Option<(Span, String)> -) -> KindValue { +) -> Result> { if value.is_none() { - return to_kind_only(kind) + if let Some(kind) = to_kind_only(schema_context, project_context, kind) { + return Ok(kind) + } } - KindValue::Primitive( - to_primitive(schema_context, kind, value.clone().unwrap().1).unwrap() - ) -} + if let Some(kind_value) = to_kind_value( + schema_context, kind, &value.as_ref().unwrap() + ) { + return Ok(kind_value) + }; -fn to_kind_only(kind: &(Span, String)) -> KindValue { - match kind { - &_ => panic!("Cant") - } + Err(CompileError::TypeNotFound { name: kind.1.clone() }) + .context(report::CompileSnafu { + details: ReportDetails::fetch(schema_context, &kind.0).unwrap() + })? } #[allow(unused)] -fn to_primitive( - schema_context: &Rc>, - kind: &(Span, String), value: String +pub(crate) fn to_kind_value( + schema_context: &Ref<'_, SchemaContext<'_>>, + kind: &(Span, String), value: &(Span, String) +) -> Option { + if let Some(primitive) = to_primitive_kind_value(kind, &value.1) { + return Some(KindValue::Primitive(primitive)) + } + + None +} + +#[allow(unused)] +pub(crate) fn to_kind_only( + schema_context: &Ref<'_, SchemaContext<'_>>, project_context: &'_ ProjectContext<'_>, + kind: &(Span, String) +) -> Option { + if let Some(primitive) = to_primitive_kind_only(kind) { + return Some(KindValue::Primitive(primitive)) + } + + if let Some(namespaced) = to_namespaced_kind_only(schema_context, kind) { + return Some(namespaced) + } + + if let Some(union) = to_union_kind_only(schema_context, kind) { + return Some(union) + } + + None +} + + +fn to_namespaced_kind_only( + schema_context: &Ref<'_, SchemaContext<'_>>, kind: &(Span, String) +) -> Option { + let state = schema_context.compile_state.borrow(); + + for (_, structure) in state.structures.iter() { + if structure.name.1 == kind.1 { + return Some(KindValue::Namespaced( + structure.name.1.clone(), None + )) + } + } + + for (_, constant) in state.consts.iter() { + if constant.name.1 == kind.1 { + return Some(KindValue::Namespaced( + constant.name.1.clone(), None + )) + } + } + + None +} + +fn to_union_kind_only( + schema_context: &Ref<'_, SchemaContext<'_>>, kind: &(Span, String) +) -> Option { + todo!() +} + +fn to_primitive_kind_only(kind: &(Span, String)) -> Option { + use self::Primitive::*; + match &*kind.1 { + "u8" => Some(U8(None)), + "u16" => Some(U16(None)), + "u32" => Some(U32(None)), + "u64" => Some(U64(None)), + "u128" => Some(U128(None)), + + "s8" => Some(S8(None)), + "s16" => Some(S16(None)), + "s32" => Some(S32(None)), + "s64" => Some(S64(None)), + "s128" => Some(S128(None)), + + "str" => Some(String(None)), + "bool" => Some(Boolean(None)), + _ => { None } + } +} + +fn to_primitive_kind_value<'a>( + kind: &(Span, String), value: &str ) -> Option { use self::Primitive::*; let kv = match &*kind.1 { @@ -178,6 +277,7 @@ fn to_primitive( "s128" => S128(Some(value.parse().unwrap())), "str" => String(Some(value.to_owned())), + "bool" => Boolean(Some(value.parse().unwrap())), _ => { panic!("Got unknown type '{:#}'", kind.1) } }; diff --git a/core/src/schema/ir/compiler/interpreted/mod.rs b/core/src/schema/ir/compiler/interpreted/mod.rs index cf71720..cad30ad 100644 --- a/core/src/schema/ir/compiler/interpreted/mod.rs +++ b/core/src/schema/ir/compiler/interpreted/mod.rs @@ -1,6 +1,5 @@ // Relative Modules pub mod sanitizer; pub mod serialization; -pub mod primitive; -pub mod interpreter; +pub mod kind_search; diff --git a/core/src/schema/ir/compiler/interpreted/sanitizer.rs b/core/src/schema/ir/compiler/interpreted/sanitizer.rs index d5901b7..5f5b010 100644 --- a/core/src/schema/ir/compiler/interpreted/sanitizer.rs +++ b/core/src/schema/ir/compiler/interpreted/sanitizer.rs @@ -7,6 +7,6 @@ use crate::schema::ir::context::SchemaContext; #[allow(unused)] -fn sanitize_context_units(context: &SchemaContext) { +fn sanitize_context_units(context: &SchemaContext<'_>) { todo!() } diff --git a/core/src/schema/ir/compiler/interpreter/meta_stage.rs b/core/src/schema/ir/compiler/interpreter/meta_stage.rs index 0371c02..4dec725 100644 --- a/core/src/schema/ir/compiler/interpreter/meta_stage.rs +++ b/core/src/schema/ir/compiler/interpreter/meta_stage.rs @@ -1,20 +1,23 @@ // Standard Uses use std::cell::RefCell; use std::rc::Rc; -use crate::project::ir::context::ProjectContext; +use snafu::ResultExt; // Crate Uses use crate::report::ReportDetails; -use crate::schema::ir::compiler::report::CompileError; use crate::schema::ir::context::SchemaContext; +use crate::project::ir::context::ProjectContext; +use crate::schema::ir::compiler::interpreter::semi_frozen; +use crate::schema::ir::compiler::report; +use crate::schema::ir::compiler::report::CompileError; // External Uses pub fn compile_schema_metadata<'a>( - schema_context: &Rc>, - project_context: &'a ProjectContext<'a> -) -> Result<(), ReportDetails> { + schema_context: Rc>>, + project_context: &ProjectContext<'a> +) -> Result<(), Box> { let schema_ctx = schema_context.borrow(); for i in 0..schema_ctx.schema.1.len() { @@ -22,24 +25,14 @@ pub fn compile_schema_metadata<'a>( use crate::schema::idl::ast::unit::ASTUnit::*; match &spanned_unit.1 { - Namespace(_, n) => { - + Namespace(span, n) => { let name = n.clone(); - let Some(_) = project_context.find_schema_by_import(&n) else - { - return Err(ReportDetails { - // kind: "Namespace".to_string(), - /* - message: format!( - "Namespace {} used in another schema: {} and {},\n \ - only one schema per namespace is allowed", - n, context.main.0.filename(), unit_namespace.unwrap().0.filename() - ), - start: 0, end: 0, - */ - phantom: Default::default(), - span: None, - }) + let Some(_) = project_context.find_schema_by_import(&n) else { + Err(CompileError::NamespaceCollision { + origin: "aa".to_string(), target: "aaa".to_string() + }).context(report::CompileSnafu { + details: ReportDetails::fetch(&schema_ctx, span).unwrap() + })? }; let mut compile_state = schema_ctx.compile_state.borrow_mut(); @@ -52,23 +45,33 @@ pub fn compile_schema_metadata<'a>( Docstring {..} => { todo!() } - Import(_, _) => { - /* - let Some(ctx) - = project_context.find_schema_by_import(i) else { - panic!("No import") - }; - */ + Import(span, import) => { + let spanned = Rc::clone(&spanned_unit); + + schema_ctx.compile_state.borrow_mut().imports.entry(spanned).or_insert( + semi_frozen::Import { + namespace: (*span, import.clone()), + // alias: alias.clone + } + ); } // Docstring { .. } => {} #[allow(unused)] Constant { name, ..} => { - /* + let spanned_unit = Rc::clone(&spanned_unit); + schema_ctx.compile_state.borrow_mut().consts - .entry(&spanned_unit).or_insert( - SemiFrozenUnit::Constant { name: name.clone() } + .entry(spanned_unit).or_insert( + semi_frozen::Constant { name: name.clone() } + ); + } + Struct { name, .. } => { + let spanned_unit = Rc::clone(&spanned_unit); + + schema_ctx.compile_state.borrow_mut().structures + .entry(spanned_unit).or_insert( + semi_frozen::Structure { name: name.clone() } ); - */ } Property { .. } => {} Parameter { .. } => {} @@ -76,8 +79,14 @@ pub fn compile_schema_metadata<'a>( Enum { .. } => {} EnumVariant { .. } => {} Settings { .. } => {} - Struct { .. } => {} - Protocol { .. } => {} + Protocol { name, .. } => { + let spanned_unit = Rc::clone(&spanned_unit); + + schema_ctx.compile_state.borrow_mut().protocols + .entry(spanned_unit).or_insert( + semi_frozen::Protocol { name: name.clone() } + ); + } Function { .. } => {} Argument { .. } => {} Error { .. } => {} diff --git a/core/src/schema/ir/compiler/interpreter/object_stage.rs b/core/src/schema/ir/compiler/interpreter/object_stage.rs index 80ee862..37674d4 100644 --- a/core/src/schema/ir/compiler/interpreter/object_stage.rs +++ b/core/src/schema/ir/compiler/interpreter/object_stage.rs @@ -1,18 +1,343 @@ // Standard Uses use std::rc::Rc; -use std::cell::RefCell; +use std::cell::{Ref, RefCell}; // Crate Uses -use crate::report::ReportDetails; -use crate::schema::ir::compiler::report::CompileError; use crate::schema::ir::context::SchemaContext; +use crate::schema::idl::ast::unit::{ASTUnit, SpannedUnit}; +use crate::schema::ir::compiler::interpreted::kind_search; +use crate::schema::ir::compiler::interpreted::kind_search::{KindValue}; +use crate::schema::ir::frozen::unit::{FrozenArgument, FrozenUnit}; +use crate::project::ir::context::ProjectContext; // External Uses #[allow(unused)] -pub fn compile_schema_metadata(schema_context: &Rc> -) -> Result<(), ReportDetails> +pub fn compile_schema<'a>( + schema_context: Rc>>, + project_context: &ProjectContext<'a> +) -> Result<(), Box> { + let schema_ctx = schema_context.borrow(); + let mut interpreted: Vec = vec![]; + + for spanned_unit in &schema_ctx.schema.1 { + use crate::schema::idl::ast::unit::ASTUnit::*; + match &spanned_unit.1 { + Namespace(..) => {} + Docstring {..} => { + todo!() + } + Import(s, i) => { + let Some(import_ctx) + = project_context.find_schema_by_import(i) else { + panic!("No schema found by import '{}'", i) + }; + } + // Docstring { .. } => {} + Constant { + docstring, name, + kind, default_value + } => { + let state = schema_ctx.compile_state.borrow(); + + let kind_value = kind_search::resolve_kind_value( + &schema_ctx, project_context, kind, default_value + )?; + + interpreted.push(FrozenUnit::Constant { + docstring: None, + name: name.1.clone(), + kind_value, + }); + } + Property { .. } => {} + Parameter { .. } => {} + ExpressionBlock { .. } => {} + Enum { .. } => {} + EnumVariant { .. } => {} + Settings { .. } => {} + Struct { .. } => {} + Protocol { + docstring, parameters, + name, functions + } => { + let state = schema_ctx.compile_state.borrow(); + + let mut params = vec![]; + let mut funcs = vec![]; + for function in functions { + funcs.push(to_function_frozen( + &schema_ctx, &project_context, function + )?); + } + + interpreted.push(FrozenUnit::Protocol { + docstring: "".to_string(), + parameters: params, + name: name.1.clone(), + functions: funcs, + }); + } + Function { name, .. } => { + } + Argument { .. } => {} + Error { .. } => {} + Validator { .. } => {} + Field { .. } => {} + } + } + + drop(schema_ctx); + let mut schema_ctx = RefCell::borrow_mut(&schema_context); + schema_ctx.frozen_schema = Some(interpreted); + + Ok(()) + + /* + for (unit, span) in &context.config.1 { + use crate::schema::idl::ast::unit::ASTUnit::*; + match unit { + ASTUnit::Namespace(n) => { + let unit_namespace = context.find_whole_unit_by_import(n); + + /* + if unit_namespace.is_some() { + return Err(ReportDetails { + kind: "Namespace".to_string(), + message: format!( + "Namespace {} used in another schema: {} and {},\n \ + only one schema per namespace is allowed", + n, context.main.0.filename(), unit_namespace.unwrap().0.filename() + ), + start: 0, end: 0, + }) + } + */ + + interpreted.push(FrozenUnit::Namespace(n.clone())); + }, + Import(_) => { + let import = interpret_node(&context, unit)?; + interpreted.push(import); + } + Constant { .. } => { + let constant = interpret_node(&context, unit)?; + interpreted.push(constant); + } + Enum { .. } => { + let r#enum = interpret_node(&context, unit)?; + interpreted.push(r#enum); + } + /* + Unit::Settings { .. } => {} + Unit::Struct { .. } => {} + Unit::Protocol { .. } => {} + Unit::Error { .. } => {} + */ + + Validator { .. } => { + let validator = interpret_node(&context, unit)?; + interpreted.push(validator); + } + /* + //r => panic!("Left to impl: {:?}", r) + */ + _ => {} + } + } + */ +} + +fn to_function_frozen( + schema_ctx: &Ref<'_, SchemaContext<'_>>, project_context: &'_ ProjectContext<'_>, + spanned_unit: &SpannedUnit +) -> Result> { + #[allow(unused)] + let ASTUnit::Function { + docstring, parameters, name, + asynchronous, + arguments, returns, throws + } = &spanned_unit.1 else { panic!() }; + let sync = || { if let Some(_) = asynchronous { false } else { true } }; + + let mut args = vec![]; + let mut rets = vec![]; + + for (_, unit) in arguments { + let ASTUnit::Argument { name, kind } = unit else { panic!() }; + + let Some(kind) = kind_search::to_kind_only( + &schema_ctx, project_context, kind + ) else { panic!() }; + + args.push(FrozenArgument { + name: name.1.clone(), + kind + }); + } + + for ret in returns { + let Some(kind) = kind_search::to_kind_only( + &schema_ctx, project_context, ret + ) else { panic!() }; + + rets.push(kind); + } + + Ok(FrozenUnit::Function { + docstring: "".to_string(), + name: name.1.clone(), + synchronous: sync(), + // direction: Box::new(()), + arguments: args, + returns: rets, + throws: vec![], + }) +} + +#[allow(unused)] +pub fn interpret_node<'a>( + schema_context: &'a SchemaContext<'a>, + project_context: &'a ProjectContext<'a>, + node: &ASTUnit +) -> Result> { + use crate::schema::idl::ast::unit::ASTUnit::*; + match node { + Namespace(_, n) => { + let mut found: Option<&SchemaContext<'a>> = None; + + /* + for relative_ctx in schema_ctx.borrow().schema_contexts.iter() { + if unit::namespace(&relative_ctx.schema.1) == n { + /* + if found.is_some() { + return Err(ReportDetails { + kind: "namespace".to_string(), + message: format!( + "Found namespace {} when its already declared in {}", + &n, &relative_ctx.main.0.filename() + ), + start: 0, end: 0, + }) + } + */ + + found = Some(relative_ctx) + } + } + */ + } + Import(_, i) => { + let relative_unit = project_context.find_schema_by_import(&i); + + /* + if relative_unit.is_none() { + let relative_unit = relative_unit.unwrap(); + + return Err(ReportDetails { + kind: "import".to_string(), + message: format!("Could not find namespace of {}", relative_unit.0.filename()), + start: 0, end: 0, + }) + } + */ + + return Ok(FrozenUnit::Import(i.clone())) + }, + Constant { + name: (_, name), kind: (_, kind), + default_value, .. + } => { + /* + let kind_value = primitive::to_kind_value(kind, default_value); + + return Ok(FrozenUnit::Constant { + docstring: None, + name: name.clone(), kind_value + }) + */ + } + Enum { name, variants, .. } => { + let mut frozen_variants: Vec = vec![]; + + for variant in variants { + pub(crate) fn to_variant(variant: &ASTUnit) -> KindValue { + match variant { + EnumVariant { name, kind } => { + if kind.is_none() { + return KindValue::EnumVariant( + name.1.clone(),None + ) + } + + return KindValue::EnumVariant( + name.1.clone(), None + ) + }, + _ => panic!("Should not be here") + } + } + + frozen_variants.push(FrozenUnit::EnumVariant( + to_variant(&variant.1) + )); + } + + return Ok(FrozenUnit::Enum { + docstring: None, + name: name.1.clone(), + variants: frozen_variants + }) + } + /* + EnumVariant { .. } => {} + Settings { .. } => {} + Struct { .. } => {} + Protocol { .. } => {} + Function { .. } => {} + Error { .. } => {} + */ + #[allow(unused)] + Validator { + docstring, properties, + name, expression_block + } => { + let properties = to_properties(properties); + let expr_block = Box::new(FrozenUnit::ExpressionBlock { function_calls: vec![] }); + + + return Ok(FrozenUnit::Validator { + docstring: Some("".to_owned()), // TODO: Docstrings should likely be a vector of units + properties: vec![], + name: name.1.clone(), + expression_block: expr_block + }) + } + /* + Field { .. } => {} + Parameter { .. } => {} + Property { .. } => {} + ExpressionBlock { .. } => {} + */ + missing => unimplemented!("Missing implementation for node '{:?}'", missing) + } + + panic!() +} + +#[allow(unused)] +fn to_properties(nodes: &Vec) -> Vec { + let properties = vec![]; + + for node in nodes { + + } + + properties +} + +pub fn into_frozen_unit() -> FrozenUnit { todo!() -} \ No newline at end of file +} diff --git a/core/src/schema/ir/compiler/interpreter/semi_frozen.rs b/core/src/schema/ir/compiler/interpreter/semi_frozen.rs index f632a74..876ab9f 100644 --- a/core/src/schema/ir/compiler/interpreter/semi_frozen.rs +++ b/core/src/schema/ir/compiler/interpreter/semi_frozen.rs @@ -6,10 +6,28 @@ use crate::utils::codemap::Span; // External Uses + #[derive(Clone)] -pub enum SemiFrozenUnit { - Constant { - name: (Span, String) - }, +pub struct Import { + pub(crate) namespace: (Span, String), + // TODO: Alias of imports for schemas, objects, etc, is needed for namespace conflicts + // pub(crate) alias: (Span, String) +} + +// TODO: All of these structures might be able to be replace with a single one, since +// a lot of them might just need to have a name and span to the objects +#[derive(Clone)] +pub struct Structure { + pub(crate) name: (Span, String) +} + +#[derive(Clone)] +pub struct Constant { + pub(crate) name: (Span, String) +} + +#[derive(Clone)] +pub struct Protocol { + pub(crate) name: (Span, String) } diff --git a/core/src/schema/ir/compiler/mod.rs b/core/src/schema/ir/compiler/mod.rs index c658b1b..29db461 100644 --- a/core/src/schema/ir/compiler/mod.rs +++ b/core/src/schema/ir/compiler/mod.rs @@ -7,7 +7,7 @@ pub mod report; // Local Uses use crate::schema::idl::parser_new; -use crate::schema::idl::ast::unit::{ASTUnit, SourcedWhole}; +use crate::schema::idl::ast::unit::{ASTUnit, SourcedWholeRc}; // External Uses @@ -29,5 +29,5 @@ pub trait Compile { } - fn from_sourced_whole(sourced: SourcedWhole) -> Self::Output; + fn from_sourced_whole(sourced: SourcedWholeRc) -> Self::Output; } diff --git a/core/src/schema/ir/compiler/report.rs b/core/src/schema/ir/compiler/report.rs index b506ae6..011f62a 100644 --- a/core/src/schema/ir/compiler/report.rs +++ b/core/src/schema/ir/compiler/report.rs @@ -1,47 +1,63 @@ // Standard Uses -use std::fmt::{Display, Formatter}; // Crate Uses use crate::report::ReportDetails; // External Uses use snafu::Snafu; -use strum::EnumProperty; -use strum_macros::FromRepr; -// TODO: repr(u16) is here so we could turn a enum variant instance into its corresponding number -// however i didn't find how to do it without having to match pattern every each one of -// the variants and return the number by casting the variant, so strum props were used. -// If in the future we know of a better solution, it should be applied #[repr(u16)] -#[derive(EnumProperty)] #[derive(Debug, Snafu)] pub enum CompileError { - #[strum(props(Id="1"))] - #[snafu(display("Found namespace '{target}' when its already declared in '{origin}'"))] - Namespace { source: std::io::Error, origin: String, target: String } = 1, + #[snafu(display( + "Found namespace '{target}' when its already declared in '{origin}'" + ))] + NamespaceCollision { origin: String, target: String } = 0, + + #[snafu(display("No type found by name '{name}'"))] + TypeNotFound { name: String }, } impl CompileError { - pub fn code(&self) -> u16 { - self.get_str("Id").expect("Variant does not have a 'Id' property").parse().unwrap() - } -} - -impl Display for ReportDetails { - #[allow(unused)] - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "TODO: Display needs implementation here") + pub(crate) fn code(&self) -> u16 { + unsafe { *<*const _>::from(self).cast::() } } } -// TODO: Same case as the enum `CompileError` about the repr -#[derive(EnumProperty, FromRepr)] +#[repr(u16)] #[derive(Debug, Snafu)] pub enum CompileWarning { - #[strum(props(Id="1"))] #[snafu(display("No dependencies were assigned, this will automatically add Comline's langlib'"))] DependenciesNotFilled } + +impl CompileWarning { + pub(crate) fn code(&self) -> u16 { + unsafe { *<*const _>::from(self).cast::() } + } +} + + +#[derive(Debug, Snafu)] +#[snafu(visibility(pub(crate)))] +pub enum Report { + #[snafu(display( + "Error[E0{}]: {source}\nAt line {}:{} (position {}:{})", + source.code(), details.line.start, details.line.end, details.pos.start, details.pos.end + ))] + CompileErrorError { + source: CompileError, + details: ReportDetails, + }, + + #[snafu(display( + "Warning[W0{}]: {source}\nAt line {}:{} (position {}:{})", + source.code(), details.line.start, details.line.end, details.pos.start, details.pos.end + ))] + CompileWarningError { + source: CompileWarning, + details: ReportDetails, + }, +} diff --git a/core/src/schema/ir/context.rs b/core/src/schema/ir/context.rs index 5de0a12..375bd09 100644 --- a/core/src/schema/ir/context.rs +++ b/core/src/schema/ir/context.rs @@ -1,22 +1,28 @@ use std::cell::RefCell; use std::collections::HashMap; +use std::marker::PhantomData; +use std::rc::Rc; // Local Uses -use crate::schema::idl::ast::unit::{SourcedWhole, SpannedUnit}; -use crate::schema::ir::compiler::interpreter::semi_frozen::SemiFrozenUnit; +use crate::schema::idl::ast::unit::{SourcedWholeRc, SpannedUnit}; +use crate::schema::ir::compiler::interpreter::semi_frozen; use crate::schema::ir::frozen::unit::FrozenUnit; // External Uses #[derive(Clone, Default)] -pub struct CompileState<'a> { +pub struct CompileState<'e> { pub namespace: Option, - pub consts: HashMap<&'a SpannedUnit, SemiFrozenUnit> + pub imports: HashMap, semi_frozen::Import>, + pub consts: HashMap, semi_frozen::Constant>, + pub structures: HashMap, semi_frozen::Structure>, + pub protocols: HashMap, semi_frozen::Protocol>, + pub phantom: PhantomData<&'e ()>, } #[allow(unused)] -impl<'a> CompileState<'_> { +impl<'e> CompileState<'_> { pub(crate) fn to_frozen(&self) -> Vec { let mut interpreted = vec![]; @@ -27,7 +33,8 @@ impl<'a> CompileState<'_> { } pub struct SchemaContext<'a> { - pub schema: SourcedWhole, + pub name: String, + pub schema: SourcedWholeRc, pub frozen_schema: Option>, // pub project_context: Option<&'a RefCell>>, // pub project_context: Option<&'a mut ProjectContext<'a>>, @@ -37,8 +44,9 @@ pub struct SchemaContext<'a> { #[allow(unused)] impl<'a> SchemaContext<'a> { - pub fn with_main(schema: SourcedWhole) -> Self{ + pub fn with_main(schema: SourcedWholeRc, name: String) -> Self{ Self { + name, schema, frozen_schema: None, // project_context: None, @@ -47,10 +55,12 @@ impl<'a> SchemaContext<'a> { } pub fn with_project_and_main( - schema: SourcedWhole, + schema: SourcedWholeRc, // project: &'a RefCell> + name: String ) -> Self { Self { + name, schema, frozen_schema: None, // project_context: Some(project), @@ -58,15 +68,6 @@ impl<'a> SchemaContext<'a> { } } - pub fn with_main_no_std(schema: SourcedWhole) -> Self{ - Self { - schema, - frozen_schema: None, - // project_context: None, - compile_state: Default::default(), - } - } - pub(crate) fn sanitize_units(self) { todo!() } diff --git a/core/src/schema/ir/diff/mod.rs b/core/src/schema/ir/diff/mod.rs index 9b6c21e..6351fb7 100644 --- a/core/src/schema/ir/diff/mod.rs +++ b/core/src/schema/ir/diff/mod.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; // Crate Uses use crate::schema::ir::frozen::unit::{FrozenUnit, FrozenWhole}; -use crate::schema::ir::compiler::interpreted::primitive::KindValue; +use crate::schema::ir::compiler::interpreted::kind_search::KindValue; // External Uses use downcast_rs::{Downcast, impl_downcast}; @@ -18,8 +18,8 @@ pub trait Differ: Downcast + Debug { &mut self, name: &str, left_kind_value: &KindValue, right_kind_value: &KindValue ); - fn differ( - &self, previous: &Vec, next: &FrozenWhole, + fn differ<'a>( + &self, previous: &Vec, next: &FrozenWhole<'a>, document_gen: bool, auto_version: bool ) { todo!() diff --git a/core/src/schema/ir/frozen/unit.rs b/core/src/schema/ir/frozen/unit.rs index 6eadfd5..289be13 100644 --- a/core/src/schema/ir/frozen/unit.rs +++ b/core/src/schema/ir/frozen/unit.rs @@ -2,13 +2,15 @@ // Crate Uses use crate::schema::ir::context::SchemaContext; -use crate::schema::ir::compiler::interpreted::primitive::KindValue; +use crate::schema::ir::compiler::interpreted::kind_search::KindValue; // External Uses pub type FrozenWhole<'a> = (SchemaContext<'a>, Vec); + +// TODO: A lot of string instances could be &'a str, boxes could also get ditched, etc #[derive(Deserialize, Serialize)] #[derive(Debug, Eq, PartialEq)] pub enum FrozenUnit { @@ -60,9 +62,9 @@ pub enum FrozenUnit { docstring: String, name: String, synchronous: bool, - direction: Box, - arguments: Vec, - returns: Vec, + // direction: Box, + arguments: Vec, + returns: Vec, throws: Vec }, Error { @@ -86,3 +88,10 @@ pub enum FrozenUnit { kind_value: KindValue, } } + +#[derive(Deserialize, Serialize)] +#[derive(Debug, Eq, PartialEq)] +pub struct FrozenArgument { + pub name: String, + pub kind: KindValue +} diff --git a/core/tests/autodoc/mod.rs b/core/tests/autodoc/mod.rs index 8d8c539..fb1f0bc 100644 --- a/core/tests/autodoc/mod.rs +++ b/core/tests/autodoc/mod.rs @@ -6,7 +6,7 @@ use comline::schema::ir::frozen::unit::FrozenUnit; // External Uses use once_cell::sync::Lazy; use comline::autodoc; -use comline::schema::ir::compiler::interpreted::primitive::{KindValue, Primitive}; +use comline::schema::ir::compiler::interpreted::kind_search::{KindValue, Primitive}; static PREVIOUS_FROZEN_UNITS: Lazy> = Lazy::new(|| diff --git a/core/tests/idl/unit.rs b/core/tests/idl/unit.rs index 13faa90..d8d9860 100644 --- a/core/tests/idl/unit.rs +++ b/core/tests/idl/unit.rs @@ -5,8 +5,8 @@ use std::path::Path; // External Uses use comline::schema::{idl, ir}; -use comline::schema::idl::constants::SCHEMA_EXTENSION; use comline::schema::idl::ast::unit::ASTUnit; +use comline::schema::idl::constants::SCHEMA_EXTENSION; use comline::utils::codemap::Span; @@ -193,7 +193,9 @@ fn compile_unit() { let path = Path::new(path); let unit = idl::parser_new::from_path(path).unwrap(); - let context = ir::context::SchemaContext::with_main(unit); + let context = ir::context::SchemaContext::with_main( + unit, path.file_stem().unwrap().to_str().unwrap().to_owned() + ); /* let frozen_unit = interpreter::interpret_context(context).unwrap(); diff --git a/core/tests/package/test/config.idp b/core/tests/package/test/config.idp index b274980..5bbc3f2 100644 --- a/core/tests/package/test/config.idp +++ b/core/tests/package/test/config.idp @@ -3,10 +3,12 @@ specification_version = 1 schema_paths = [ "ping.ids" + "health.ids" ] code_generation = { languages = { + python#3.11.0 = { package_versions=[all] } rust#1.70.0 = { package_versions=[all] } } } diff --git a/core/tests/package/test/generated/0.0.1/rust/1.70.0/health.rs b/core/tests/package/test/generated/0.0.1/rust/1.70.0/health.rs deleted file mode 100644 index e69de29..0000000 diff --git a/core/tests/package/test/generated/python/3.11.0/health.py b/core/tests/package/test/generated/python/3.11.0/health.py new file mode 100644 index 0000000..fac84c5 --- /dev/null +++ b/core/tests/package/test/generated/python/3.11.0/health.py @@ -0,0 +1,14 @@ +# Generated code with Comline compiler and code generator + +import typing +import ctypes + + +class HealthCheck(typing.Protocol): + def alive(self): + ... + + def capabilities(self): + ... + + diff --git a/core/tests/package/test/generated/python/3.11.0/ping.py b/core/tests/package/test/generated/python/3.11.0/ping.py new file mode 100644 index 0000000..71cef35 --- /dev/null +++ b/core/tests/package/test/generated/python/3.11.0/ping.py @@ -0,0 +1,16 @@ +# Generated code with Comline compiler and code generator + +import typing +import ctypes + + +LOW_PING_RATE: typing.Final[ctypes.c_uint16] = 20 + +class Ping(typing.Protocol): + def ping(self): + ... + + def ping_limit(self): + ... + + diff --git a/core/tests/package/test/generated/rust/1.70.0/health.rs b/core/tests/package/test/generated/rust/1.70.0/health.rs new file mode 100644 index 0000000..34b0800 --- /dev/null +++ b/core/tests/package/test/generated/rust/1.70.0/health.rs @@ -0,0 +1,8 @@ +// Generated code with Comline compiler and code generator + +pub trait HealthCheck { + fn alive (&self); + fn capabilities (&self); + +} + diff --git a/core/tests/package/test/generated/rust/1.70.0/ping.rs b/core/tests/package/test/generated/rust/1.70.0/ping.rs new file mode 100644 index 0000000..a7cc74c --- /dev/null +++ b/core/tests/package/test/generated/rust/1.70.0/ping.rs @@ -0,0 +1,10 @@ +// Generated code with Comline compiler and code generator + +pub const LOW_PING_RATE: u16 = 20; + +pub trait Ping { + fn ping (&self); + fn ping_limit (&self); + +} + diff --git a/core/tests/package/test/health.ids b/core/tests/package/test/health.ids index dac0fbb..31d365e 100644 --- a/core/tests/package/test/health.ids +++ b/core/tests/package/test/health.ids @@ -2,13 +2,13 @@ namespace test::idl::health struct Capabilities { - names: str[] + names: str } /// Health check an address @provider=Any protocol HealthCheck { - function alive() -> bool - function capabilities() -> Capabilities + function alive() -> bool; + function capabilities() -> Capabilities; } diff --git a/core/tests/package/test/ping.ids b/core/tests/package/test/ping.ids index 87362ec..9fb3de6 100644 --- a/core/tests/package/test/ping.ids +++ b/core/tests/package/test/ping.ids @@ -1,15 +1,17 @@ // Ping Schema -namespace tests::idl::ping +namespace test::idl::ping -const LOW_PING_RATE:u16 = 20; +import test::idl::health + +const LOW_PING_RATE: u16 = 20 /// Ping another address @provider=Any protocol Ping { - function ping() -> bool + function ping() -> bool; @timeout_ms=1000 - function ping_limit() -> bool + function ping_limit() -> bool; }