Skip to content

Commit

Permalink
refactor: intermediate resolved ref in transpiler
Browse files Browse the repository at this point in the history
  • Loading branch information
gabotechs committed Nov 11, 2022
1 parent 837a3e2 commit 5a40df6
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 137 deletions.
4 changes: 2 additions & 2 deletions graphqxl_parser/src/ast_value_basic_type.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::fmt::{Display, Formatter};
use crate::parser::Rule;
use crate::utils::unknown_rule_error;
use crate::{Identifier, OwnedSpan};
use pest::iterators::Pair;
use std::fmt::{Display, Formatter};

#[derive(Debug, Clone, PartialEq)]
pub enum ValueBasicType {
Expand All @@ -16,7 +16,7 @@ pub enum ValueBasicType {
impl Display for ValueBasicType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", {
match self {
match self {
ValueBasicType::Int => "Int",
ValueBasicType::Float => "Float",
ValueBasicType::Boolean => "Boolean",
Expand Down
3 changes: 2 additions & 1 deletion graphqxl_transpiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ use std::error::Error;

use crate::transpiler::GraphqxlTranspiler;

mod resolve_expandable_ref;
mod resolve_modified_ref;
mod transpile_block_def;
mod transpile_description;
mod transpile_generic_block_def;
mod transpile_spec;
mod transpiler;
mod modified_ref;

pub fn transpile_spec(spec: &Spec) -> Result<Spec, Box<dyn Error>> {
GraphqxlTranspiler::from(spec).transpile()
Expand Down
4 changes: 0 additions & 4 deletions graphqxl_transpiler/src/modified_ref/mod.rs

This file was deleted.

85 changes: 0 additions & 85 deletions graphqxl_transpiler/src/modified_ref/transpile_modified_ref.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
use crate::modified_ref::transpile_modified_ref::{
ModifiedRefStackContext, _transpile_modified_ref,
};
use crate::resolve_modified_ref::{resolve_modified_ref_with_context, ModifiedRefStackContext, ResolvedRef};
use crate::transpile_description::transpile_description;
use graphqxl_parser::{BlockDef, BlockEntry, ExpandableRef, ValueBasicType};
use std::collections::HashMap;
use std::error::Error;

const VARIABLES_PREFIX: &str = "variables";

pub(crate) fn transpile_expandable_ref(
pub(crate) fn resolve_expandable_ref(
expandable_ref: &ExpandableRef,
store: &HashMap<String, BlockDef>,
stack_context: ModifiedRefStackContext,
) -> Result<BlockDef, Box<dyn Error>> {
) -> Result<ResolvedRef, Box<dyn Error>> {
let referenced_block_def = match store.get(&expandable_ref.identifier.id) {
Some(block_def) => block_def,
None => {
Expand Down Expand Up @@ -52,9 +50,8 @@ pub(crate) fn transpile_expandable_ref(
generic_call_args.get(i).unwrap(),
);
}

let mut concrete_block_def = generic_referenced_block_def.clone();
concrete_block_def.generic = None;

let mut resolved_ref = ResolvedRef::init(&generic_referenced_block_def);

let mut description_replacements = HashMap::new();
for (key, value) in generic_map.iter() {
Expand All @@ -64,11 +61,11 @@ pub(crate) fn transpile_expandable_ref(
);
}

transpile_description(&mut concrete_block_def, &description_replacements, true)?;
transpile_description(&mut resolved_ref, &description_replacements, true)?;

let mut new_entries = vec![];
let mut new_fields = vec![];

for entry in concrete_block_def.entries.iter() {
for entry in generic_referenced_block_def.entries.iter() {
let new_entry = entry.clone();
// if it is a field...
match new_entry {
Expand All @@ -86,16 +83,19 @@ pub(crate) fn transpile_expandable_ref(
}
}
}
new_entries.push(BlockEntry::Field(block_field))
new_fields.push(block_field)
}
BlockEntry::SpreadRef(modified_ref) => {
// NOTE: Careful here, recursive brain exploding ahead
let block_def =
_transpile_modified_ref(&modified_ref, store, stack_context.plus_1())?;
new_entries.extend_from_slice(&block_def.entries);
let resolved_ref = resolve_modified_ref_with_context(
&modified_ref,
store,
stack_context.plus_1(),
)?;
new_fields.extend_from_slice(&resolved_ref.fields);
}
}
}
concrete_block_def.entries = new_entries;
Ok(concrete_block_def)
resolved_ref.fields = new_fields;
Ok(resolved_ref)
}
102 changes: 102 additions & 0 deletions graphqxl_transpiler/src/resolve_modified_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use crate::resolve_expandable_ref::resolve_expandable_ref;
use graphqxl_parser::{
BlockDef, BlockField, Directive, Implements, ModifiedRef, OwnedSpan, ValueType,
};
use std::collections::HashMap;
use std::error::Error;
use std::ops::Deref;

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct ResolvedRef {
pub span: OwnedSpan,
pub implements: Option<Implements>,
pub description: String,
pub fields: Vec<BlockField>,
pub directives: Vec<Directive>,
}

impl ResolvedRef {
pub(crate) fn init(value: &BlockDef) -> Self {
Self {
span: value.span.clone(),
implements: value.implements.clone(),
description: value.description.clone(),
fields: vec![],
directives: value.directives.clone()
}
}
}

fn nullable(resolved_ref: &ResolvedRef) -> ResolvedRef {
let mut optional_block_def = resolved_ref.clone();
for field in optional_block_def.fields.iter_mut() {
if let Some(value_type) = &mut field.value_type {
if let ValueType::NonNullable(inner) = value_type {
*value_type = inner.deref().deref().deref().clone()
}
}
}
optional_block_def
}

fn non_nullable(resolved_ref: &ResolvedRef) -> ResolvedRef {
let mut required_block_def = resolved_ref.clone();
for field in required_block_def.fields.iter_mut() {
if let Some(value_type) = &mut field.value_type {
if let ValueType::NonNullable(_) = value_type {
// do nothing here
} else {
*value_type = ValueType::NonNullable(Box::new(value_type.clone()))
}
}
}
required_block_def
}

#[derive(Default, Clone)]
pub(crate) struct ModifiedRefStackContext {
stack_count: usize,
}

impl ModifiedRefStackContext {
pub(crate) fn plus_1(&self) -> Self {
let mut clone = self.clone();
clone.stack_count += 1;
clone
}
}

pub(crate) fn resolve_modified_ref_with_context(
modified_ref: &ModifiedRef,
store: &HashMap<String, BlockDef>,
stack_context: ModifiedRefStackContext,
) -> Result<ResolvedRef, Box<dyn Error>> {
// todo: where does this come from
if stack_context.stack_count > 100 {
return Err(modified_ref
.span()
.make_error("maximum nested spread operator surpassed"));
}
match modified_ref {
ModifiedRef::Required(modified_ref, _) => Ok(non_nullable(
&resolve_modified_ref_with_context(modified_ref, store, stack_context.plus_1())?,
)),
ModifiedRef::Optional(modified_ref, _) => Ok(nullable(&resolve_modified_ref_with_context(
modified_ref,
store,
stack_context.plus_1(),
)?)),
ModifiedRef::ExpandableRef(expandable_ref) => Ok(resolve_expandable_ref(
expandable_ref,
store,
stack_context.plus_1(),
)?),
}
}

pub(crate) fn resolve_modified_ref(
modified_ref: &ModifiedRef,
store: &HashMap<String, BlockDef>,
) -> Result<ResolvedRef, Box<dyn Error>> {
resolve_modified_ref_with_context(modified_ref, store, ModifiedRefStackContext::default())
}
29 changes: 14 additions & 15 deletions graphqxl_transpiler/src/transpile_block_def.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::modified_ref::transpile_modified_ref;
use crate::resolve_modified_ref::resolve_modified_ref;
use crate::transpile_description::transpile_description;
use graphqxl_parser::{BlockDef, BlockEntry, Identifier};
use std::collections::{HashMap, HashSet};
Expand Down Expand Up @@ -45,11 +45,14 @@ fn transpile_block_def(
let mut entries_to_evaluate = vec![];

for entry in block_def.entries.iter() {
if let BlockEntry::SpreadRef(modified_ref) = entry {
let referenced_type = transpile_modified_ref(modified_ref, store)?;
entries_to_evaluate.extend(referenced_type.entries);
} else {
entries_to_evaluate.push(entry.clone());
match entry {
BlockEntry::SpreadRef(modified_ref) => {
let referenced_type = resolve_modified_ref(modified_ref, store)?;
entries_to_evaluate.extend(referenced_type.fields);
}
BlockEntry::Field(field) => {
entries_to_evaluate.push(field.clone());
}
}
}

Expand All @@ -67,19 +70,15 @@ fn transpile_block_def(
false,
)?;

for entry in entries_to_evaluate {
let mut field = if let BlockEntry::Field(field) = entry {
field
} else {
// We now that at this point all the BlockEntries should be Fields
unreachable!()
};
for field in entries_to_evaluate.iter_mut() {
if seen.contains(&field.name.id) {
return Err(field.span.make_error("repeated field"));
}
seen.insert(field.name.id.clone());
transpile_description(&mut field, &template_string_replacements, false)?;
transpiled_block_def.entries.push(BlockEntry::Field(field));
transpile_description(field, &template_string_replacements, false)?;
transpiled_block_def
.entries
.push(BlockEntry::Field(field.clone()));
}
Ok(transpiled_block_def)
}
Expand Down
17 changes: 17 additions & 0 deletions graphqxl_transpiler/src/transpile_description.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ use graphqxl_parser::{BlockDef, BlockField, OwnedSpan};
use regex::{escape, Regex};
use std::collections::HashMap;
use std::error::Error;
use crate::resolve_modified_ref::ResolvedRef;

pub(crate) trait TemplateDescription {
fn get_description(&self) -> &str;
fn mutate_description(&mut self, new_description: &str);
fn owned_span(&self) -> &OwnedSpan;
}

// TODO: this could be done with a macro
impl TemplateDescription for BlockField {
fn get_description(&self) -> &str {
&self.description
Expand Down Expand Up @@ -37,6 +39,21 @@ impl TemplateDescription for BlockDef {
}
}


impl TemplateDescription for ResolvedRef {
fn get_description(&self) -> &str {
&self.description
}

fn mutate_description(&mut self, new_description: &str) {
self.description = new_description.to_string();
}

fn owned_span(&self) -> &OwnedSpan {
&self.span
}
}

pub(crate) fn transpile_description<T: TemplateDescription>(
with_template_description: &mut T,
replace: &HashMap<String, String>,
Expand Down
Loading

0 comments on commit 5a40df6

Please sign in to comment.