Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jvanstraten committed Sep 8, 2022
1 parent f316b2d commit ef9ee25
Show file tree
Hide file tree
Showing 14 changed files with 366 additions and 133 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ serde_yaml = "0.9"
# both the schema and the input, so we need to depend on that as well, even
# though we don't actually do any JSON serialization and deserialization.
jsonschema = { version = "=0.15.0", default-features = false }
serde_json = "1"
serde_json = { version = "1", features = ["preserve_order"] }

# Used for checking identifier syntax (could be removed if regexes don't end up
# being useful elsewhere too).
Expand Down
3 changes: 3 additions & 0 deletions rs/src/output/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ pub enum Classification {
#[strum(props(HiddenDescription = "invalid compound vs. simple function name usage"))]
LinkCompoundVsSimpleFunctionName = 3010,

#[strum(props(Description = "discouraged name"))]
LinkDiscouragedName = 3011,

// Type-related diagnostics (group 4).
#[strum(props(HiddenDescription = "type-related diagnostics"))]
Type = 4000,
Expand Down
30 changes: 16 additions & 14 deletions rs/src/output/extension/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,22 @@ impl<T> ResolutionResult<T> {
self.expect(parse_context, if_not_applicable, |_, _| true, true, false)
}

/// Emits an error if one or more definitions were found for this name
/// resolution, to be used just before defining a new item.
pub fn expect_not_yet_defined(&self, parse_context: &mut context::Context) {
if !self.visible.is_empty() {
traversal::push_diagnostic(
parse_context,
diagnostic::Level::Error,
cause!(
LinkDuplicateDefinition,
"{} is already defined",
self.unresolved_reference
),
);
}
}

/// Silently returns the first matching item, if any. If there are none,
/// this just returns an unresolved reference. Use
/// filter_items().expect_one() to formulate error messages if there are
Expand Down Expand Up @@ -567,18 +583,4 @@ impl<T> ResolutionResult<T> {
.next()
.flatten()
}

/// Return an error if one or more definitions were found for this name
/// resolution, to be used just before defining a new item.
pub fn expect_not_yet_defined(&self) -> diagnostic::Result<()> {
if self.visible.is_empty() {
Ok(())
} else {
Err(cause!(
LinkDuplicateDefinition,
"{} is already defined",
self.unresolved_reference
))
}
}
}
12 changes: 8 additions & 4 deletions rs/src/output/extension/simple/type_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,27 @@ use crate::output::type_system::meta::pattern::Pattern;
/// A definition of a user-defined type class.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct Definition {
/// The underlying structure of the type.
pub structure: Vec<(String, data::class::Simple)>,
/// Name of the type class.
pub name: String,

/// The parameters expected by the data type.
pub parameter_slots: Vec<ParameterSlot>,

/// Whether or not the last parameter slot is variadic.
pub parameters_variadic: bool,

/// Optional underlying structure of the type.
/// TODO: change to Option<Vec<(String, meta::Program)>> and propagate changes
pub structure: Vec<(String, data::class::Simple)>,
}

/// A parameter slot for a user-defined data type.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParameterSlot {
/// YAML-provided name of the parameter.
/// Name of the parameter.
pub name: String,

/// YAML-provided human-readable description of the parameter.
/// Human-readable description of the parameter.
pub description: String,

/// Pattern for type- and bounds-checking parameters bound to this slot.
Expand Down
66 changes: 0 additions & 66 deletions rs/src/parse/extensions/simple/builder.rs

This file was deleted.

41 changes: 41 additions & 0 deletions rs/src/parse/extensions/simple/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: Apache-2.0

//! Module providing private helper functions that are not specific to any
//! particular simple extension construct.

use crate::output::diagnostic::Result;
use crate::parse::context;

/// Parser for names given to things.
pub fn parse_name(x: &str, y: &mut context::Context, construct: &str) -> Result<String> {
static IDENTIFIER_RE: once_cell::sync::Lazy<regex::Regex> =
once_cell::sync::Lazy::new(|| regex::Regex::new("[a-zA-Z_][a-zA-Z0-9_\\.]*").unwrap());

if x.is_empty() {
diagnostic!(
y,
Info,
LinkDiscouragedName,
"using the empty string as a {construct} name is not explicitly \
illegal, but probably not a good idea"
);
} else if !IDENTIFIER_RE.is_match(x) {
diagnostic!(
y,
Info,
LinkDiscouragedName,
"it is recommended for {construct} names to case-insensitively \
match [a-z_][a-z0-9_]* for maximum compatibility"
);
} else if x.contains('.') {
diagnostic!(
y,
Info,
LinkDiscouragedName,
"using periods within a {construct} name is not explicitly \
illegal, but probably not a good idea, as they are also used as \
namespace separators for dependencies"
);
}
Ok(x.to_owned())
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
use crate::input::yaml;
use crate::output::diagnostic::Result;
use crate::parse::context;
use crate::parse::extensions::simple::builder;
use crate::parse::extensions::simple::modules;

/// Parse a scalar function declaration.
pub fn parse_scalar_function(
_x: &yaml::Value,
_y: &mut context::Context,
_z: &mut builder::Builder,
_z: &mut modules::Builder,
) -> Result<()> {
// TODO
Ok(())
Expand All @@ -22,7 +22,7 @@ pub fn parse_scalar_function(
pub fn parse_aggregate_function(
_x: &yaml::Value,
_y: &mut context::Context,
_z: &mut builder::Builder,
_z: &mut modules::Builder,
) -> Result<()> {
// TODO
Ok(())
Expand Down
14 changes: 7 additions & 7 deletions rs/src/parse/extensions/simple/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0

//! Module providing parse/validation functions for advanced extensions, i.e.
//! Module providing parse/validation functions for simple extensions, i.e.
//! those based around YAML files.

use crate::input::proto::substrait;
Expand All @@ -10,12 +10,12 @@ use crate::output::extension::simple::module::Scope;
use crate::output::type_system::data;
use crate::parse::context;

mod builder;
mod common;
mod derivations;
mod function_decls;
mod type_decls;
mod type_variation_decls;
mod yaml;
mod functions;
mod modules;
mod type_classes;
mod type_variations;

/// Parse a user-defined name. Note that names are matched case-insensitively
/// because we return the name as lowercase.
Expand Down Expand Up @@ -51,7 +51,7 @@ fn parse_simple_extension_yaml_uri_mapping(
) -> Result<()> {
// Parse the fields.
let anchor = proto_primitive_field!(x, y, extension_uri_anchor, parse_anchor).1;
let yaml_data = proto_primitive_field!(x, y, uri, yaml::parse_uri)
let yaml_data = proto_primitive_field!(x, y, uri, modules::parse_uri)
.1
.unwrap();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,115 @@
// SPDX-License-Identifier: Apache-2.0

//! Module providing parse/validation functions for parsing YAML extension
//! files.
//! Module providing a builder structure to be used while parsing a simple
//! extension file.

use crate::input::yaml;
use crate::output::diagnostic::Result;
use crate::output::extension;
use crate::output::path;
use crate::parse::context;
use crate::parse::extensions::simple::builder;
use crate::parse::extensions::simple::function_decls;
use crate::parse::extensions::simple::type_decls;
use crate::parse::extensions::simple::type_variation_decls;
use crate::parse::extensions::simple::functions;
use crate::parse::extensions::simple::modules;
use crate::parse::extensions::simple::type_classes;
use crate::parse::extensions::simple::type_variations;
use crate::parse::traversal;
use crate::util;
use std::collections::HashMap;
use std::sync::Arc;

#[derive(Clone, Debug, Default)]
pub struct Builder {
/// Map with references to dependencies.
pub dependencies: HashMap<String, extension::simple::module::Reference>,

/// Namespace used for type classes defined in this extension and its
/// dependencies.
pub type_classes: extension::simple::type_class::NamespaceDefinition,

/// Namespace used for type variations defined in this extension and its
/// dependencies.
pub type_variations: extension::simple::type_variation::NamespaceDefinition,

/// Namespace used for functions defined in this extension and its
/// dependencies. Both simple and compound names are registered.
pub function_impls: extension::simple::function::NamespaceDefinition,
}

impl From<Builder> for extension::simple::module::Definition {
fn from(builder: Builder) -> Self {
extension::simple::module::Definition {
dependencies: builder.dependencies,
type_classes: Arc::new(builder.type_classes),
type_variations: Arc::new(builder.type_variations),
function_impls: Arc::new(builder.function_impls),
}
}
}

impl extension::simple::module::Scope for Builder {
/// Resolves a to-be-resolved reference to a type class.
fn resolve_type_class<T>(&self, name: T) -> extension::simple::type_class::ResolutionResult
where
T: Into<extension::simple::type_class::UnresolvedReference>,
{
self.type_classes.resolve_local(name.into())
}

/// Resolves a to-be-resolved reference to a type variation.
fn resolve_type_variation<T>(
&self,
name: T,
) -> extension::simple::type_variation::ResolutionResult
where
T: Into<extension::simple::type_variation::UnresolvedReference>,
{
self.type_variations.resolve_local(name.into())
}

/// Resolves a to-be-resolved reference to a function.
fn resolve_function<T>(&self, name: T) -> extension::simple::function::ResolutionResult
where
T: Into<extension::simple::function::UnresolvedReference>,
{
self.function_impls.resolve_local(name.into())
}
}

/// Toplevel parse function for a simple extension YAML file.
fn parse_root(
x: &yaml::Value,
y: &mut context::Context,
) -> Result<extension::simple::module::Definition> {
let mut builder = builder::Builder::default();
yaml_repeated_field!(x, y, "types", type_decls::parse_type, 0, &mut builder)?;
let mut builder = modules::Builder::default();
yaml_repeated_field!(
x,
y,
"types",
type_classes::parse_type_class,
0,
&mut builder
)?;
yaml_repeated_field!(
x,
y,
"type_variations",
type_variation_decls::parse_type_variation,
type_variations::parse_type_variation,
0,
&mut builder
)?;
yaml_repeated_field!(
x,
y,
"scalar_functions",
function_decls::parse_scalar_function,
functions::parse_scalar_function,
0,
&mut builder
)?;
yaml_repeated_field!(
x,
y,
"aggregate_functions",
function_decls::parse_aggregate_function,
functions::parse_aggregate_function,
0,
&mut builder
)?;
Expand Down
Loading

0 comments on commit ef9ee25

Please sign in to comment.