Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions src/compiler/destructuring_planner/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,19 @@ pub fn create_loop_index_binding_plan<T: VariableBindingContext>(
pub fn create_parameter_binding_plan<T: VariableBindingContext>(
param_expr: &ExprRef,
context: &T,
scoping: ScopingMode,
) -> Result<BindingPlan> {
let mut newly_bound = BTreeSet::new();
let destructuring_plan = create_destructuring_plan_with_tracking(
param_expr,
context,
ScopingMode::AllowShadowing,
&mut newly_bound,
)
.ok_or_else(|| BindingPlannerError::FailedToCreateDestructuringPlan {
plan_type: "parameter".to_string(),
span: param_expr.span().clone(),
})?;

validate_pattern_bindings(param_expr, &newly_bound, context)?;
let destructuring_plan =
create_destructuring_plan_with_tracking(param_expr, context, scoping, &mut newly_bound)
.ok_or_else(|| BindingPlannerError::FailedToCreateDestructuringPlan {
plan_type: "parameter".to_string(),
span: param_expr.span().clone(),
})?;

if scoping == ScopingMode::AllowShadowing {
validate_pattern_bindings(param_expr, &newly_bound, context)?;
}

Ok(BindingPlan::Parameter {
param_expr: param_expr.clone(),
Expand Down
8 changes: 6 additions & 2 deletions src/compiler/hoist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,9 @@ impl LoopHoister {
for param in args {
// Create binding plan for function parameter
match super::destructuring_planner::create_parameter_binding_plan(
param, &context,
param,
&context,
ScopingMode::AllowShadowing,
) {
Ok(binding_plan) => {
let expr_idx = param.as_ref().eidx();
Expand Down Expand Up @@ -708,7 +710,9 @@ impl LoopHoister {
// If the last parameter expression contains unbound vars, create a binding plan
if let Some(last_param) = params.last() {
match super::destructuring_planner::create_parameter_binding_plan(
last_param, context,
last_param,
context,
ScopingMode::RespectParent,
) {
Ok(binding_plan) => {
let expr_idx = last_param.as_ref().eidx();
Expand Down
14 changes: 9 additions & 5 deletions src/languages/rego/compiler/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ impl<'a> Compiler<'a> {
if !self.is_builtin(builtin_name) {
return Err(CompilerError::NotBuiltinFunction {
name: builtin_name.to_string(),
});
}
.into());
}

// Check if we already have an index for this builtin
Expand All @@ -44,7 +45,8 @@ impl<'a> Compiler<'a> {
} else {
return Err(CompilerError::UnknownBuiltinFunction {
name: builtin_name.to_string(),
});
}
.into());
};

// Create builtin info and add it to the program
Expand Down Expand Up @@ -199,10 +201,12 @@ impl<'a> Compiler<'a> {
expr: &ExprRef,
context: &str,
) -> Result<BindingPlan> {
self.get_binding_plan_for_expr(expr)
.ok_or_else(|| CompilerError::MissingBindingPlan {
self.get_binding_plan_for_expr(expr).ok_or_else(|| {
CompilerError::MissingBindingPlan {
context: context.to_string(),
})
}
.at(expr.span())
})
}

pub(super) fn resolve_variable(&mut self, var_name: &str, span: &Span) -> Result<Register> {
Expand Down
43 changes: 31 additions & 12 deletions src/languages/rego/compiler/destructuring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<'a> Compiler<'a> {
rhs_expr, lhs_plan, ..
} => {
let rhs_reg = self.compile_rego_expr_with_span(rhs_expr, rhs_expr.span(), false)?;
self.apply_destructuring_plan(
let _ = self.apply_destructuring_plan(
lhs_plan,
rhs_reg,
span,
Expand All @@ -54,21 +54,31 @@ impl<'a> Compiler<'a> {
rhs_expr, lhs_plan, ..
} => {
let rhs_reg = self.compile_rego_expr_with_span(rhs_expr, rhs_expr.span(), false)?;
self.apply_destructuring_plan(lhs_plan, rhs_reg, span, PlanContext::Assignment)?;
let _ = self.apply_destructuring_plan(
lhs_plan,
rhs_reg,
span,
PlanContext::Assignment,
)?;
Ok(self.load_bool_literal(true, span))
}
AssignmentPlan::EqualsBindRight {
lhs_expr, rhs_plan, ..
} => {
let lhs_reg = self.compile_rego_expr_with_span(lhs_expr, lhs_expr.span(), false)?;
self.apply_destructuring_plan(rhs_plan, lhs_reg, span, PlanContext::Assignment)?;
let _ = self.apply_destructuring_plan(
rhs_plan,
lhs_reg,
span,
PlanContext::Assignment,
)?;
Ok(self.load_bool_literal(true, span))
}
AssignmentPlan::EqualsBothSides { element_pairs, .. } => {
for (value_expr, value_plan) in element_pairs {
let value_reg =
self.compile_rego_expr_with_span(value_expr, value_expr.span(), false)?;
self.apply_destructuring_plan(
let _ = self.apply_destructuring_plan(
value_plan,
value_reg,
span,
Expand Down Expand Up @@ -124,7 +134,7 @@ impl<'a> Compiler<'a> {
plan: &BindingPlan,
value_register: Register,
span: &Span,
) -> Result<()> {
) -> Result<Option<Register>> {
match plan {
BindingPlan::Assignment { .. } => {
bail!("assignment binding plans should be handled via compile_assignment_plan")
Expand Down Expand Up @@ -160,9 +170,11 @@ impl<'a> Compiler<'a> {
span: &Span,
) -> Result<()> {
if let (Some(plan), Some(register)) = (key_plan, key_register) {
self.apply_destructuring_plan(plan, register, span, PlanContext::SomeIn)?;
let _ = self.apply_destructuring_plan(plan, register, span, PlanContext::SomeIn)?;
}
self.apply_destructuring_plan(value_plan, value_register, span, PlanContext::SomeIn)
let _ =
self.apply_destructuring_plan(value_plan, value_register, span, PlanContext::SomeIn)?;
Ok(())
}

fn apply_destructuring_plan(
Expand All @@ -171,7 +183,7 @@ impl<'a> Compiler<'a> {
value_register: Register,
span: &Span,
context: PlanContext,
) -> Result<()> {
) -> Result<Option<Register>> {
match plan {
DestructuringPlan::Var(name_span) => {
self.bind_variable(name_span, value_register, span, context)?;
Expand All @@ -189,6 +201,9 @@ impl<'a> Compiler<'a> {
},
span,
);
if self.soft_assert_mode {
return Ok(Some(cmp_reg));
}
self.emit_instruction(Instruction::AssertCondition { condition: cmp_reg }, span);
}
DestructuringPlan::EqualityValue(expected_value) => {
Expand All @@ -202,6 +217,9 @@ impl<'a> Compiler<'a> {
},
span,
);
if self.soft_assert_mode {
return Ok(Some(cmp_reg));
}
self.emit_instruction(Instruction::AssertCondition { condition: cmp_reg }, span);
}
DestructuringPlan::Array { element_plans } => {
Expand All @@ -225,7 +243,8 @@ impl<'a> Compiler<'a> {
span,
);
}
self.apply_destructuring_plan(element_plan, element_reg, span, context)?;
let _ =
self.apply_destructuring_plan(element_plan, element_reg, span, context)?;
}
}
DestructuringPlan::Object {
Expand All @@ -249,7 +268,7 @@ impl<'a> Compiler<'a> {
},
span,
);
self.apply_destructuring_plan(field_plan, field_reg, span, context)?;
let _ = self.apply_destructuring_plan(field_plan, field_reg, span, context)?;
}

for (key_expr, field_plan) in dynamic_fields {
Expand All @@ -270,11 +289,11 @@ impl<'a> Compiler<'a> {
},
span,
);
self.apply_destructuring_plan(field_plan, field_reg, span, context)?;
let _ = self.apply_destructuring_plan(field_plan, field_reg, span, context)?;
}
}
}
Ok(())
Ok(None)
}

fn bind_variable(
Expand Down
53 changes: 52 additions & 1 deletion src/languages/rego/compiler/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
use alloc::format;
use alloc::string::String;

use crate::lexer::Span;
use core::fmt;

#[derive(thiserror::Error, Debug)]
pub enum CompilerError {
#[error("Not a builtin function: {name}")]
Expand Down Expand Up @@ -68,4 +71,52 @@ impl From<anyhow::Error> for CompilerError {
}
}

pub type Result<T> = ::core::result::Result<T, CompilerError>;
#[derive(Debug)]
pub struct SpannedCompilerError {
pub error: CompilerError,
pub span: Option<Span>,
}

impl SpannedCompilerError {
pub fn new(error: CompilerError) -> Self {
Self { error, span: None }
}

pub fn with_span(mut self, span: &Span) -> Self {
if self.span.is_none() {
self.span = Some(span.clone());
}
self
}
}

impl fmt::Display for SpannedCompilerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(span) = &self.span {
let msg = format!("{}", self.error);
write!(f, "{}", span.message("error", &msg))
} else {
write!(f, "{}", self.error)
}
}
}

impl From<CompilerError> for SpannedCompilerError {
fn from(error: CompilerError) -> Self {
Self::new(error)
}
}

impl core::error::Error for SpannedCompilerError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
Some(&self.error)
}
}

impl CompilerError {
pub fn at(self, span: &Span) -> SpannedCompilerError {
SpannedCompilerError::from(self).with_span(span)
}
}

pub type Result<T> = ::core::result::Result<T, SpannedCompilerError>;
5 changes: 3 additions & 2 deletions src/languages/rego/compiler/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ impl<'a> Compiler<'a> {
let result: Result<Register> = match binding_plan {
BindingPlan::Assignment { plan } => self
.compile_assignment_plan_using_hoisted_destructuring(&plan, span)
.map_err(CompilerError::from),
.map_err(|e| CompilerError::from(e).at(span)),
other => Err(CompilerError::UnexpectedBindingPlan {
context: "assignment expression".to_string(),
found: format!("{other:?}"),
}),
}
.at(span)),
};

return result;
Expand Down
2 changes: 1 addition & 1 deletion src/languages/rego/compiler/expressions/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl<'a> Compiler<'a> {
);
Ok(dest)
}
_ => Err(CompilerError::InvalidUnaryMinus),
_ => Err(CompilerError::InvalidUnaryMinus.at(span)),
}
}

Expand Down
Loading
Loading