Skip to content

Commit

Permalink
Rebase on main
Browse files Browse the repository at this point in the history
  • Loading branch information
AlSchlo committed Feb 11, 2025
1 parent 3cbc5a8 commit 5066787
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 6 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

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

152 changes: 146 additions & 6 deletions optd-dsl/src/gen/operator.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use crate::ast::{Field, LogicalOp, Operator, OperatorKind, ScalarOp, Type};
use crate::{
analyzer::semantic::SemanticAnalyzer,

Check warning on line 2 in optd-dsl/src/gen/operator.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] optd-dsl/src/gen/operator.rs#L2

warning: unused imports: `analyzer::semantic::SemanticAnalyzer` and `parser::parse_file` --> optd-dsl/src/gen/operator.rs:2:5 | 2 | analyzer::semantic::SemanticAnalyzer, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 3 | ast::{Field, LogicalOp, Operator, OperatorKind, ScalarOp, Type}, 4 | parser::parse_file, | ^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
Raw output
optd-dsl/src/gen/operator.rs:2:5:w:warning: unused imports: `analyzer::semantic::SemanticAnalyzer` and `parser::parse_file`
 --> optd-dsl/src/gen/operator.rs:2:5
  |
2 |     analyzer::semantic::SemanticAnalyzer,
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 |     ast::{Field, LogicalOp, Operator, OperatorKind, ScalarOp, Type},
4 |     parser::parse_file,
  |     ^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default


__END__
ast::{Field, LogicalOp, Operator, OperatorKind, ScalarOp, Type},
parser::parse_file,
};
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use syn::parse_quote;
Expand Down Expand Up @@ -63,8 +67,99 @@ impl FieldInfo {
}
}

fn generate_code(operators: &[Operator]) -> proc_macro2::TokenStream {
let mut generated_code = proc_macro2::TokenStream::new();
fn generate_logical_enum(operators: &[LogicalOp]) -> TokenStream {

Check warning on line 70 in optd-dsl/src/gen/operator.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] optd-dsl/src/gen/operator.rs#L70

warning: function `generate_logical_enum` is never used --> optd-dsl/src/gen/operator.rs:70:4 | 70 | fn generate_logical_enum(operators: &[LogicalOp]) -> TokenStream { | ^^^^^^^^^^^^^^^^^^^^^
Raw output
optd-dsl/src/gen/operator.rs:70:4:w:warning: function `generate_logical_enum` is never used
  --> optd-dsl/src/gen/operator.rs:70:4
   |
70 | fn generate_logical_enum(operators: &[LogicalOp]) -> TokenStream {
   |    ^^^^^^^^^^^^^^^^^^^^^


__END__
let variants: Vec<_> = operators
.iter()
.map(|op| {
let name = format_ident!("{}", &op.name);
quote! {
#name(#name<Value, Relation, Scalar>)
}
})
.collect();

let variant_names: Vec<_> = operators
.iter()
.map(|op| format_ident!("{}", &op.name))
.collect();

quote! {
#[derive(Debug, Clone, PartialEq, Deserialize)]
pub enum LogicalOperator<Value, Relation, Scalar> {
#(#variants,)*
}

#[derive(Debug, Clone, PartialEq, sqlx::Type)]
pub enum LogicalOperatorKind {
#(#variant_names,)*
}

impl<Relation, Scalar> LogicalOperator<OptdValue, Relation, Scalar>
where
Relation: Clone,
Scalar: Clone,
{
pub fn operator_kind(&self) -> LogicalOperatorKind {
match self {
#(LogicalOperator::#variant_names => LogicalOperatorKind::#variant_names,)*
}
}
}
}
}

fn generate_scalar_enum(operators: &[ScalarOp]) -> TokenStream {

Check warning on line 111 in optd-dsl/src/gen/operator.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] optd-dsl/src/gen/operator.rs#L111

warning: function `generate_scalar_enum` is never used --> optd-dsl/src/gen/operator.rs:111:4 | 111 | fn generate_scalar_enum(operators: &[ScalarOp]) -> TokenStream { | ^^^^^^^^^^^^^^^^^^^^
Raw output
optd-dsl/src/gen/operator.rs:111:4:w:warning: function `generate_scalar_enum` is never used
   --> optd-dsl/src/gen/operator.rs:111:4
    |
111 | fn generate_scalar_enum(operators: &[ScalarOp]) -> TokenStream {
    |    ^^^^^^^^^^^^^^^^^^^^


__END__
let variants: Vec<_> = operators
.iter()
.map(|op| {
let name = format_ident!("{}", &op.name);
quote! {
#name(#name<Value, Scalar>)
}
})
.collect();

let variant_names: Vec<_> = operators
.iter()
.map(|op| format_ident!("{}", &op.name))
.collect();

quote! {
#[derive(Debug, Clone, PartialEq, Deserialize)]
pub enum ScalarOperator<Value, Scalar> {
#(#variants,)*
}

#[derive(Debug, Clone, PartialEq, sqlx::Type)]
pub enum ScalarOperatorKind {
#(#variant_names,)*
}

impl<Scalar> ScalarOperator<OptdValue, Scalar>
where
Scalar: Clone,
{
pub fn operator_kind(&self) -> ScalarOperatorKind {
match self {
#(ScalarOperator::#variant_names => ScalarOperatorKind::#variant_names,)*
}
}
}
}
}

fn generate_code(operators: &[Operator]) -> TokenStream {

Check warning on line 151 in optd-dsl/src/gen/operator.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] optd-dsl/src/gen/operator.rs#L151

warning: function `generate_code` is never used --> optd-dsl/src/gen/operator.rs:151:4 | 151 | fn generate_code(operators: &[Operator]) -> TokenStream { | ^^^^^^^^^^^^^
Raw output
optd-dsl/src/gen/operator.rs:151:4:w:warning: function `generate_code` is never used
   --> optd-dsl/src/gen/operator.rs:151:4
    |
151 | fn generate_code(operators: &[Operator]) -> TokenStream {
    |    ^^^^^^^^^^^^^


__END__
let mut logical_ops = Vec::new();
let mut scalar_ops = Vec::new();

for operator in operators.into_iter().cloned() {

Check warning on line 155 in optd-dsl/src/gen/operator.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] optd-dsl/src/gen/operator.rs#L155

warning: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` --> optd-dsl/src/gen/operator.rs:155:31 | 155 | for operator in operators.into_iter().cloned() { | ^^^^^^^^^ help: call directly: `iter` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref = note: `#[warn(clippy::into_iter_on_ref)]` on by default
Raw output
optd-dsl/src/gen/operator.rs:155:31:w:warning: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice`
   --> optd-dsl/src/gen/operator.rs:155:31
    |
155 |     for operator in operators.into_iter().cloned() {
    |                               ^^^^^^^^^ help: call directly: `iter`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
    = note: `#[warn(clippy::into_iter_on_ref)]` on by default


__END__
match operator {
Operator::Logical(op) => logical_ops.push(op),
Operator::Scalar(op) => scalar_ops.push(op),
}
}

let mut generated_code = TokenStream::new();

// Generate enums first
let logical_enum = generate_logical_enum(&logical_ops);
Expand Down Expand Up @@ -118,8 +213,39 @@ fn generate_logical_operator(operator: &LogicalOp) -> TokenStream {
}
}

fn generate_scalar_operator(_operator: &ScalarOp) -> proc_macro2::TokenStream {
unimplemented!()
fn generate_scalar_operator(operator: &ScalarOp) -> TokenStream {

Check warning on line 216 in optd-dsl/src/gen/operator.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] optd-dsl/src/gen/operator.rs#L216

warning: function `generate_scalar_operator` is never used --> optd-dsl/src/gen/operator.rs:216:4 | 216 | fn generate_scalar_operator(operator: &ScalarOp) -> TokenStream { | ^^^^^^^^^^^^^^^^^^^^^^^^
Raw output
optd-dsl/src/gen/operator.rs:216:4:w:warning: function `generate_scalar_operator` is never used
   --> optd-dsl/src/gen/operator.rs:216:4
    |
216 | fn generate_scalar_operator(operator: &ScalarOp) -> TokenStream {
    |    ^^^^^^^^^^^^^^^^^^^^^^^^


__END__
let name = format_ident!("{}", &operator.name);
let fields: Vec<FieldInfo> = operator.fields.iter().map(FieldInfo::new).collect();
let struct_fields: Vec<_> = fields.iter().map(|f| f.struct_field()).collect();
let ctor_params: Vec<_> = fields.iter().map(|f| f.ctor_param()).collect();
let ctor_inits: Vec<_> = fields.iter().map(|f| f.ctor_init()).collect();
let field_names: Vec<_> = fields.iter().map(|f| &f.name).collect();
let fn_name = format_ident!("{}", operator.name.to_lowercase());

quote! {
use super::ScalarOperator;
use crate::values::OptdValue;
use serde::Deserialize;

#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct #name<Value, Scalar> {
#(#struct_fields,)*
}

impl<Scalar> #name<OptdValue, Scalar> {
pub fn new(#(#ctor_params,)*) -> Self {
Self {
#(#ctor_inits,)*
}
}
}

pub fn #fn_name<Scalar>(
#(#ctor_params,)*
) -> ScalarOperator<OptdValue, Scalar> {
ScalarOperator::#name(#name::new(#(#field_names,)*))
}
}
}

#[test]
Expand Down Expand Up @@ -148,10 +274,24 @@ fn test_generate_logical_operator() {
#generated
};
let formatted = prettyplease::unparse(&syntax_tree);
println!("Generated code:\n{}", formatted);

// Basic validation
let code = formatted.to_string();
assert!(code.contains("pub child: Relation"));
assert!(code.contains("pub predicate: Scalar"));
}

#[test]
fn test_working_file() {
let input = include_str!("../programs/working.optd");
let out = parse_file(input).unwrap();
let mut analyzer = SemanticAnalyzer::new();
analyzer.validate_file(&out).unwrap();

let generated_code = generate_code(&out.operators);
let syntax_tree: syn::File = parse_quote! {
#generated_code
};
let formatted = prettyplease::unparse(&syntax_tree);
println!("Generated code:\n{}", formatted);
}

0 comments on commit 5066787

Please sign in to comment.