Merge pull request #770 from powdr-labs/allow_namespaced_to_be_function_called

Allow namespaced names to be function-called.
This commit is contained in:
Leo
2023-11-20 10:52:39 +00:00
committed by GitHub
7 changed files with 37 additions and 22 deletions

View File

@@ -108,7 +108,8 @@ where
match &mut statement {
PilStatement::Expression(_start, e) => match e {
Expression::FunctionCall(FunctionCall { id, arguments }) => {
if !self.macros.contains_key(id) {
assert!(id.namespace.is_none());
if !self.macros.contains_key(&id.name) {
panic!("Macro {id} not found - only macros allowed at this point, no fixed columns.");
}
let arguments = std::mem::take(arguments)
@@ -118,7 +119,7 @@ where
a
})
.collect();
if self.expand_macro(id, arguments).is_some() {
if self.expand_macro(&id.name, arguments).is_some() {
panic!("Invoked a macro in statement context with non-empty expression.");
}
}
@@ -185,10 +186,12 @@ where
*e = self.arguments[self.parameter_names[&poly.name]].clone()
}
} else if let Expression::FunctionCall(call) = e {
let name = call.id.as_str();
if !self.shadowing_locals.contains(name) && self.macros.contains_key(name) {
if call.id.namespace.is_none()
&& !self.shadowing_locals.contains(&call.id.name)
&& self.macros.contains_key(&call.id.name)
{
*e = self
.expand_macro(name, std::mem::take(&mut call.arguments))
.expand_macro(&call.id.name, std::mem::take(&mut call.arguments))
.expect("Invoked a macro in expression context with empty expression.")
}
}

View File

@@ -40,7 +40,7 @@ fn infer_machine<T: FieldElement>(mut machine: Machine<T>) -> Result<Machine<T>,
let def = machine
.instructions
.iter()
.find(|i| i.name == c.id)
.find(|i| i.name == c.id.to_string())
.unwrap();
let outputs = def.instruction.params.outputs.clone().unwrap_or_default();

View File

@@ -236,7 +236,8 @@ impl<T: FieldElement> ASMPILConverter<T> {
match *rhs {
Expression::FunctionCall(c) => {
self.handle_functional_instruction(lhs_with_reg, c.id, c.arguments)
assert!(c.id.namespace.is_none());
self.handle_functional_instruction(lhs_with_reg, c.id.name, c.arguments)
}
_ => self.handle_non_functional_assignment(start, lhs_with_reg, *rhs),
}

View File

@@ -231,7 +231,7 @@ pub struct IndexAccess<T, Ref = NamespacedPolynomialReference> {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct FunctionCall<T, Ref = NamespacedPolynomialReference> {
pub id: String,
pub id: Ref,
pub arguments: Vec<Expression<T, Ref>>,
}

View File

@@ -492,7 +492,7 @@ IndexAccess: IndexAccess<T> = {
}
FunctionCall: FunctionCall<T> = {
<id:Identifier> "(" <arguments:ExpressionList> ")" => FunctionCall {<>},
<id:NamespacedPolynomialReference> "(" <arguments:ExpressionList> ")" => FunctionCall {<>},
}
NamespacedPolynomialReference: NamespacedPolynomialReference = {

View File

@@ -84,7 +84,7 @@ impl<'a, T: FieldElement> Evaluator<'a, T> {
.map(|a| self.evaluate(a))
.collect::<Result<Vec<_>, _>>()?;
assert!(arg_values.len() == 1);
let values = &self.function_cache[id.as_str()];
let values = &self.function_cache[id.to_string().as_str()];
Ok(values[arg_values[0].to_degree() as usize % values.len()])
}
Expression::MatchExpression(scrutinee, arms) => {

View File

@@ -7,7 +7,7 @@ use analysis::MacroExpander;
use ast::parsed::visitor::ExpressionVisitable;
use ast::parsed::{
self, ArrayExpression, ArrayLiteral, FunctionDefinition, LambdaExpression, MatchArm,
MatchPattern, PilStatement, PolynomialName, SelectedExpressions,
MatchPattern, NamespacedPolynomialReference, PilStatement, PolynomialName, SelectedExpressions,
};
use number::{DegreeType, FieldElement};
@@ -558,16 +558,7 @@ impl<'a, T: FieldElement> ExpressionProcessor<'a, T> {
pub fn process_expression(&mut self, expr: parsed::Expression<T>) -> Expression<T> {
use parsed::Expression as PExpression;
match expr {
PExpression::Reference(poly) => {
if poly.namespace.is_none() && self.local_variables.contains_key(&poly.name) {
let id = self.local_variables[&poly.name];
Expression::Reference(Reference::LocalVar(id, poly.name.to_string()))
} else {
Expression::Reference(Reference::Poly(
self.process_namespaced_polynomial_reference(poly),
))
}
}
PExpression::Reference(poly) => Expression::Reference(self.process_reference(poly)),
PExpression::PublicReference(name) => Expression::PublicReference(name),
PExpression::Number(n) => Expression::Number(n),
PExpression::String(value) => Expression::String(value),
@@ -596,7 +587,7 @@ impl<'a, T: FieldElement> ExpressionProcessor<'a, T> {
})
}
PExpression::FunctionCall(c) => Expression::FunctionCall(parsed::FunctionCall {
id: self.analyzer.namespaced_ref_to_absolute(&None, &c.id),
id: self.process_reference(c.id),
arguments: self.process_expressions(c.arguments),
}),
PExpression::MatchExpression(scrutinee, arms) => Expression::MatchExpression(
@@ -617,6 +608,15 @@ impl<'a, T: FieldElement> ExpressionProcessor<'a, T> {
}
}
fn process_reference(&mut self, reference: NamespacedPolynomialReference) -> Reference {
if reference.namespace.is_none() && self.local_variables.contains_key(&reference.name) {
let id = self.local_variables[&reference.name];
Reference::LocalVar(id, reference.name.to_string())
} else {
Reference::Poly(self.process_namespaced_polynomial_reference(reference))
}
}
fn process_function(
&mut self,
params: &[String],
@@ -879,6 +879,17 @@ namespace N(65536);
let input = r#"namespace N(16);
col witness y[3];
(N.y[3] - 2) = 0;
"#;
let formatted = process_pil_file_contents::<GoldilocksField>(input).to_string();
assert_eq!(formatted, input);
}
#[test]
fn namespaced_call() {
let input = r#"namespace Assembly(2);
col fixed A = [0]*;
col fixed C(i) { (Assembly.A((i + 2)) + 3) };
col fixed D(i) { Assembly.C((i + 3)) };
"#;
let formatted = process_pil_file_contents::<GoldilocksField>(input).to_string();
assert_eq!(formatted, input);