Skip to content

Commit

Permalink
feat: _local
Browse files Browse the repository at this point in the history
  • Loading branch information
aljazerzen committed Mar 25, 2024
1 parent 0ef30d2 commit e87869c
Show file tree
Hide file tree
Showing 42 changed files with 904 additions and 670 deletions.
6 changes: 5 additions & 1 deletion prqlc/prqlc-ast/src/expr/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,11 @@ impl<'de> Deserialize<'de> for Ident {
}

pub fn display_ident(f: &mut std::fmt::Formatter, ident: &Ident) -> Result<(), std::fmt::Error> {
for part in &ident.path {
let mut path = &ident.path[..];
if path.first().map_or(false, |f| f == "_local") {
path = &path[1..];
}
for part in path {
display_ident_part(f, part)?;
f.write_char('.')?;
}
Expand Down
3 changes: 3 additions & 0 deletions prqlc/prqlc/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ impl Command {
let mut root_module_def = prql_to_pl_tree(sources)?;

drop_module_def(&mut root_module_def.stmts, "std");
drop_module_def(&mut root_module_def.stmts, "_local");

pl_to_prql(&root_module_def)?.into_bytes()
}
Expand All @@ -302,6 +303,7 @@ impl Command {
let mut restricted = prqlc::semantic::ast_expand::restrict_module_def(expanded);

drop_module_def(&mut restricted.stmts, "std");
drop_module_def(&mut restricted.stmts, "_local");

pl_to_prql(&restricted)?.into_bytes()
}
Expand All @@ -323,6 +325,7 @@ impl Command {
// resolved PL, restricted back into AST
let mut root_module = semantic::ast_expand::restrict_module(root_module.module);
drop_module_def(&mut root_module.stmts, "std");
drop_module_def(&mut root_module.stmts, "_local");
out.extend(pl_to_prql(&root_module)?.into_bytes());

out
Expand Down
7 changes: 6 additions & 1 deletion prqlc/prqlc/src/codegen/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,12 @@ impl WriteSource for Ident {
opt.consume_width(width as u16)?;

let mut r = String::new();
for part in &self.path {

let mut path = &self.path[..];
if path.first().map_or(false, |f| f == "_local") {
path = &path[1..];
}
for part in path {
r += &write_ident_part(part);
r += ".";
}
Expand Down
3 changes: 2 additions & 1 deletion prqlc/prqlc/src/ir/pl/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,9 @@ pub fn fold_func_param<T: ?Sized + PlFold>(
.into_iter()
.map(|param| {
Ok(FuncParam {
name: param.name,
ty: fold_type_opt(fold, param.ty)?,
default_value: fold_optional_box(fold, param.default_value)?,
..param
})
})
.try_collect()
Expand Down
1 change: 1 addition & 0 deletions prqlc/prqlc/src/semantic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub const NS_PARAM: &str = "_param";
pub const NS_DEFAULT_DB: &str = "db";
pub const NS_QUERY_DEF: &str = "prql";
pub const NS_MAIN: &str = "main";
pub const NS_LOCAL: &str = "_local";

// refers to the containing module (direct parent)
pub const NS_SELF: &str = "_self";
Expand Down
93 changes: 83 additions & 10 deletions prqlc/prqlc/src/semantic/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use crate::ir::pl::{Expr, Ident, Lineage, LineageColumn};
use crate::Error;

use super::{
NS_DEFAULT_DB, NS_GENERIC, NS_INFER, NS_INFER_MODULE, NS_MAIN, NS_PARAM, NS_QUERY_DEF, NS_SELF,
NS_STD, NS_THAT, NS_THIS,
NS_DEFAULT_DB, NS_GENERIC, NS_INFER, NS_INFER_MODULE, NS_LOCAL, NS_MAIN, NS_PARAM,
NS_QUERY_DEF, NS_SELF, NS_STD, NS_THAT, NS_THIS,
};
use crate::ir::decl::{Decl, DeclKind, Module, RootModule, TableDecl, TableExpr};

Expand All @@ -31,15 +31,75 @@ impl Module {
Decl::from(DeclKind::Module(Module::new_database())),
),
(NS_STD.to_string(), Decl::from(DeclKind::default())),
(
NS_LOCAL.to_string(),
Decl::from(DeclKind::Module(Module {
names: HashMap::from_iter(
[
"array",
"scalar",
"tuple",
"range",
"relation",
"transform",
// transforms
"from",
"select",
"filter",
"derive",
"aggregate",
"sort",
"take",
"join",
"group",
"window",
"append",
"intersect",
"remove",
"loop",
// agg
"min",
"max",
"sum",
"average",
"stddev",
"all",
"any",
"concat_array",
"count",
"count_distinct",
"lag",
"lead",
"first",
"last",
"rank",
"rank_dense",
"row_number",
// utils
"in",
"as",
]
.into_iter()
.map(|s| {
(
s.to_string(),
Decl::from(DeclKind::Import(Ident::from_path(vec!["std", s]))),
)
}),
),
shadowed: None,
redirects: vec![
Ident::from_name(NS_THIS),
Ident::from_name(NS_THAT),
Ident::from_name(NS_PARAM),
Ident::from_name(NS_GENERIC),
],
infer_decl: None,
})),
),
]),
shadowed: None,
redirects: vec![
Ident::from_name(NS_THIS),
Ident::from_name(NS_THAT),
Ident::from_name(NS_PARAM),
Ident::from_name(NS_STD),
Ident::from_name(NS_GENERIC),
],
redirects: vec![],
infer_decl: None,
}
}
Expand Down Expand Up @@ -236,7 +296,10 @@ impl Module {
LineageColumn::All { input_id, .. } => {
lineage.find_input(*input_id).map(|i| &i.name)
}
LineageColumn::Single { name, .. } => name.as_ref().and_then(|n| n.path.first()),
LineageColumn::Single { name, .. } => name
.as_ref()
.and_then(|n| n.path.first())
.filter(|x| x.as_str() != NS_THIS),
};

// get or create input namespace
Expand Down Expand Up @@ -455,6 +518,16 @@ fn decl_has_annotation(decl: &Decl, annotation_name: &Ident) -> bool {
type HintAndSpan = (Option<String>, Option<Span>);

impl RootModule {
pub fn local(&self) -> &Module {
let decl = self.module.names.get(NS_LOCAL).unwrap();
decl.kind.as_module().unwrap()
}

pub fn local_mut(&mut self) -> &mut Module {
let decl = self.module.names.get_mut(NS_LOCAL).unwrap();
decl.kind.as_module_mut().unwrap()
}

/// Finds that main pipeline given a path to either main itself or its parent module.
/// Returns main expr and fq ident of the decl.
pub fn find_main_rel(&self, path: &[String]) -> Result<(&TableExpr, Ident), HintAndSpan> {
Expand Down
19 changes: 16 additions & 3 deletions prqlc/prqlc/src/semantic/resolve_decls/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use itertools::Itertools;

use crate::ir::decl;
use crate::ir::pl::{self, ImportDef, PlFold};
use crate::semantic::{NS_DEFAULT_DB, NS_LOCAL, NS_STD, NS_THIS};
use crate::{ast, utils, Error};
use crate::{Result, WithErrorInfo};

Expand Down Expand Up @@ -181,6 +182,7 @@ impl pl::PlFold for NameResolver<'_> {
let (ident, indirections) = self.resolve_ident(ident).with_span(ty.span)?;

if !indirections.is_empty() {
log::debug!("resolved type ident to : {ident} + {indirections:?}");
return Err(
Error::new_simple("types are not allowed indirections").with_span(ty.span)
);
Expand All @@ -204,8 +206,16 @@ impl NameResolver<'_> {
let mod_path = match first.as_str() {
"project" => Some(vec![]),
"module" => Some(self.decl_module_path.to_vec()),
"std" => Some(vec!["std".to_string()]),
"db" => Some(vec!["db".to_string()]),
"super" => {
let mut path = self.decl_module_path.to_vec();
path.pop();
Some(path)
}

NS_STD => Some(vec![NS_STD.to_string()]),
NS_DEFAULT_DB => Some(vec![NS_DEFAULT_DB.to_string()]),
NS_THIS => Some(vec![NS_LOCAL.to_string(), NS_THIS.to_string()]),
"prql" => Some(vec![NS_STD.to_string(), "prql".to_string()]),
_ => None,
};
let mod_decl = mod_path
Expand Down Expand Up @@ -236,7 +246,10 @@ impl NameResolver<'_> {
let mut steps = ident.into_iter();
let first = steps.next().unwrap();
let indirections = steps.collect_vec();
(ast::Ident::from_name(first), indirections)
(
ast::Ident::from_path(vec![NS_LOCAL.to_string(), first]),
indirections,
)
};
Ok((ident, indirections))
}
Expand Down
12 changes: 6 additions & 6 deletions prqlc/prqlc/src/semantic/resolver/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::ast::{Ty, TyKind, TyTupleField};
use crate::ir::decl::{DeclKind, Module};
use crate::ir::pl::*;
use crate::semantic::resolver::{flatten, types, Resolver};
use crate::semantic::{NS_INFER, NS_SELF, NS_THAT, NS_THIS};
use crate::semantic::{NS_INFER, NS_LOCAL, NS_SELF, NS_THAT, NS_THIS};
use crate::utils::IdGenerator;
use crate::{Error, Reason, Span, WithErrorInfo};

Expand All @@ -17,8 +17,8 @@ impl PlFold for Resolver<'_> {
fn fold_type(&mut self, ty: Ty) -> Result<Ty> {
Ok(match ty.kind {
TyKind::Ident(ident) => {
self.root_mod.module.shadow(NS_THIS);
self.root_mod.module.shadow(NS_THAT);
self.root_mod.local_mut().shadow(NS_THIS);
self.root_mod.local_mut().shadow(NS_THAT);

let fq_ident = self.resolve_ident(&ident)?;

Expand All @@ -41,8 +41,8 @@ impl PlFold for Resolver<'_> {
let mut ty = decl_ty.clone();
ty.name = ty.name.or(Some(fq_ident.name));

self.root_mod.module.unshadow(NS_THIS);
self.root_mod.module.unshadow(NS_THAT);
self.root_mod.local_mut().unshadow(NS_THIS);
self.root_mod.local_mut().unshadow(NS_THAT);

ty
}
Expand Down Expand Up @@ -266,7 +266,7 @@ impl Resolver<'_> {
let except = self.coerce_into_tuple(expr)?;

self.fold_expr(Expr::new(ExprKind::All {
within: Box::new(Expr::new(Ident::from_name(NS_THIS))),
within: Box::new(Expr::new(Ident::from_path(vec![NS_LOCAL, NS_THIS]))),
except: Box::new(except),
}))
}
Expand Down
31 changes: 17 additions & 14 deletions prqlc/prqlc/src/semantic/resolver/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::ast::{Ty, TyFunc, TyKind};
use crate::ir::decl::{Decl, DeclKind, Module};
use crate::ir::pl::*;
use crate::semantic::resolver::types;
use crate::semantic::{NS_GENERIC, NS_PARAM, NS_THAT, NS_THIS};
use crate::semantic::{NS_GENERIC, NS_LOCAL, NS_PARAM, NS_THAT, NS_THIS};
use crate::{Error, Span, WithErrorInfo};

use super::Resolver;
Expand Down Expand Up @@ -51,7 +51,7 @@ impl Resolver<'_> {

// push the env
let closure_env = Module::from_exprs(closure.env);
self.root_mod.module.stack_push(NS_PARAM, closure_env);
self.root_mod.local_mut().stack_push(NS_PARAM, closure_env);
let closure = Box::new(Func {
env: HashMap::new(),
..*closure
Expand Down Expand Up @@ -103,7 +103,7 @@ impl Resolver<'_> {
};

// pop the env
self.root_mod.module.stack_pop(NS_PARAM).unwrap();
self.root_mod.local_mut().stack_pop(NS_PARAM).unwrap();

Ok(Expr { span, ..res })
}
Expand All @@ -114,14 +114,14 @@ impl Resolver<'_> {

let (func_env, body, return_ty) = env_of_closure(*closure);

self.root_mod.module.stack_push(NS_PARAM, func_env);
self.root_mod.local_mut().stack_push(NS_PARAM, func_env);

// fold again, to resolve inner variables & functions
let body = self.fold_expr(body)?;

// remove param decls
log::debug!("stack_pop: {:?}", body.id);
let func_env = self.root_mod.module.stack_pop(NS_PARAM).unwrap();
let func_env = self.root_mod.local_mut().stack_pop(NS_PARAM).unwrap();

Ok(if let ExprKind::Func(mut inner_closure) = body.kind {
// body couldn't been resolved - construct a closure to be evaluated later
Expand Down Expand Up @@ -176,7 +176,7 @@ impl Resolver<'_> {
// insert _generic.name declaration
let ident = Ident::from_path(vec![NS_GENERIC, generic_param.name.as_str()]);
let decl = Decl::from(DeclKind::Ty(Ty::new(TyKind::GenericArg(generic_id))));
self.root_mod.module.insert(ident, decl).unwrap();
self.root_mod.local_mut().insert(ident, decl).unwrap();
}

func.params = func
Expand All @@ -191,7 +191,7 @@ impl Resolver<'_> {
.try_collect()?;
func.return_ty = fold_type_opt(self, func.return_ty)?;

self.root_mod.module.names.remove(NS_GENERIC);
self.root_mod.local_mut().names.remove(NS_GENERIC);
Ok(func)
}

Expand Down Expand Up @@ -255,8 +255,8 @@ impl Resolver<'_> {

// resolve relational args
if has_relations {
self.root_mod.module.shadow(NS_THIS);
self.root_mod.module.shadow(NS_THAT);
self.root_mod.local_mut().shadow(NS_THIS);
self.root_mod.local_mut().shadow(NS_THAT);

for (pos, (index, (param, mut arg))) in relations.into_iter().with_position() {
let is_last = matches!(pos, Position::Last | Position::Only);
Expand All @@ -276,9 +276,9 @@ impl Resolver<'_> {
if partial_application_position.is_none() {
let frame = arg.lineage.as_ref().unwrap();
if is_last {
self.root_mod.module.insert_frame(frame, NS_THIS);
self.root_mod.local_mut().insert_frame(frame, NS_THIS);
} else {
self.root_mod.module.insert_frame(frame, NS_THAT);
self.root_mod.local_mut().insert_frame(frame, NS_THAT);
}
}

Expand All @@ -300,7 +300,9 @@ impl Resolver<'_> {
// add aliased columns into scope
if let Some(alias) = field.alias.clone() {
let id = field.id.unwrap();
self.root_mod.module.insert_frame_col(NS_THIS, alias, id);
self.root_mod
.local_mut()
.insert_frame_col(NS_THIS, alias, id);
}
fields_new.push(field);
}
Expand All @@ -323,8 +325,8 @@ impl Resolver<'_> {
}

if has_relations {
self.root_mod.module.unshadow(NS_THIS);
self.root_mod.module.unshadow(NS_THAT);
self.root_mod.local_mut().unshadow(NS_THIS);
self.root_mod.local_mut().unshadow(NS_THAT);
}

Ok(if let Some(position) = partial_application_position {
Expand Down Expand Up @@ -425,6 +427,7 @@ fn extract_partial_application(mut func: Box<Func>, position: usize) -> Box<Func

let param_name = format!("_partial_{}", arg.id.unwrap());
let substitute_arg = Expr::new(Ident::from_path(vec![
NS_LOCAL.to_string(),
NS_PARAM.to_string(),
param_name.clone(),
]));
Expand Down
Loading

0 comments on commit e87869c

Please sign in to comment.