process external functions in semantics
This commit is contained in:
parent
5f83bc86e7
commit
c6219be41d
2 changed files with 116 additions and 31 deletions
|
@ -22,7 +22,6 @@ use zokrates_field::field::Field;
|
|||
use std::rc::Rc;
|
||||
|
||||
type Identifier = String;
|
||||
type Alias = String;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Module<T: Field> {
|
||||
|
@ -35,16 +34,7 @@ pub struct Module<T: Field> {
|
|||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum FunctionSymbol<T: Field> {
|
||||
Here(FunctionNode<T>),
|
||||
There(Option<Alias>, Identifier, Rc<Module<T>>),
|
||||
}
|
||||
|
||||
impl<T: Field> FunctionSymbol<T> {
|
||||
pub fn signature(&self) -> Signature {
|
||||
match self {
|
||||
FunctionSymbol::Here(func_node) => func_node.value.signature.clone(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
There(Identifier, Rc<Module<T>>),
|
||||
}
|
||||
|
||||
pub type FunctionSymbolNode<T> = Node<FunctionSymbol<T>>;
|
||||
|
|
|
@ -152,26 +152,20 @@ impl Checker {
|
|||
for (id, func) in module.functions {
|
||||
self.enter_scope();
|
||||
|
||||
let dec = FunctionDeclaration {
|
||||
id,
|
||||
signature: func.value.signature(),
|
||||
};
|
||||
|
||||
match func.value {
|
||||
FunctionSymbol::Here(func_node) => {
|
||||
match self.check_function(func_node) {
|
||||
Ok(checked_function) => {
|
||||
checked_functions.push(checked_function);
|
||||
}
|
||||
Err(e) => {
|
||||
errors.extend(e);
|
||||
}
|
||||
};
|
||||
match self.check_function_symbol(func) {
|
||||
Ok(checked_function) => {
|
||||
self.functions
|
||||
.extend(checked_function.iter().map(|f| FunctionDeclaration {
|
||||
signature: f.signature.clone(),
|
||||
id: id.clone(),
|
||||
}));
|
||||
checked_functions.extend(checked_function.into_iter());
|
||||
}
|
||||
Err(e) => {
|
||||
errors.extend(e);
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
|
||||
self.functions.insert(dec);
|
||||
self.exit_scope();
|
||||
}
|
||||
|
||||
|
@ -286,6 +280,36 @@ impl Checker {
|
|||
})
|
||||
}
|
||||
|
||||
fn check_function_symbol<T: Field>(
|
||||
&mut self,
|
||||
funct_symbol_node: FunctionSymbolNode<T>,
|
||||
) -> Result<Vec<TypedFunction<T>>, Vec<Error>> {
|
||||
let pos = funct_symbol_node.pos();
|
||||
let funct_symbol = funct_symbol_node.value;
|
||||
|
||||
match funct_symbol {
|
||||
FunctionSymbol::Here(funct_node) => self.check_function(funct_node).map(|f| vec![f]),
|
||||
FunctionSymbol::There(id, module) => {
|
||||
// this is where we check that there are functions at the other end of the import
|
||||
let candidates: Result<Vec<_>, Vec<_>> = module
|
||||
.functions
|
||||
.iter()
|
||||
.filter(|(i, _)| *i == id)
|
||||
.map(|(_, f)| self.check_function_symbol(f.clone()))
|
||||
.collect(); // TODO not clone
|
||||
let candidates: Vec<_> = candidates?.into_iter().flat_map(|x| x).collect();
|
||||
|
||||
match candidates.len() {
|
||||
0 => Err(vec![Error {
|
||||
pos: Some(pos),
|
||||
message: format!("Function {} not found in module {}", id, "TODO"),
|
||||
}]),
|
||||
_ => Ok(candidates),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_statement<T: Field>(
|
||||
&mut self,
|
||||
stat: &StatementNode<T>,
|
||||
|
@ -962,9 +986,80 @@ impl Checker {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// use super::*;
|
||||
// use absy::parameter::Parameter;
|
||||
// use zokrates_field::field::FieldPrime;
|
||||
use super::*;
|
||||
//use absy::parameter::Parameter;
|
||||
use std::rc::Rc;
|
||||
use zokrates_field::field::FieldPrime;
|
||||
|
||||
mod symbols {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn imported_symbol() {
|
||||
// foo.code
|
||||
// def main() -> (field):
|
||||
// return 1
|
||||
|
||||
// bar.code
|
||||
// from "./foo.code" import main
|
||||
|
||||
// after semantic check, bar should have one function which returns one (imported from foo.rs)
|
||||
|
||||
let foo: Module<FieldPrime> = Module {
|
||||
functions: vec![(
|
||||
String::from("main"),
|
||||
FunctionSymbol::Here(
|
||||
Function {
|
||||
id: String::from("main"),
|
||||
statements: vec![Statement::Return(
|
||||
ExpressionList {
|
||||
expressions: vec![
|
||||
Expression::Number(FieldPrime::from(1)).at(0, 0, 0)
|
||||
],
|
||||
}
|
||||
.at(0, 0, 0),
|
||||
)
|
||||
.at(0, 0, 0)],
|
||||
signature: Signature::new().outputs(vec![Type::FieldElement]),
|
||||
arguments: vec![],
|
||||
}
|
||||
.at(0, 0, 0),
|
||||
)
|
||||
.at(0, 0, 0),
|
||||
)],
|
||||
imported_functions: vec![],
|
||||
imports: vec![],
|
||||
};
|
||||
|
||||
let bar: Module<FieldPrime> = Module {
|
||||
functions: vec![(
|
||||
String::from("main"),
|
||||
FunctionSymbol::There(String::from("main"), Rc::new(foo)).at(0, 0, 0),
|
||||
)],
|
||||
imported_functions: vec![],
|
||||
imports: vec![],
|
||||
};
|
||||
|
||||
let mut checker = Checker::new();
|
||||
|
||||
let checked_bar = checker.check_module(bar);
|
||||
assert_eq!(
|
||||
checked_bar,
|
||||
Ok(TypedProg {
|
||||
functions: vec![TypedFunction {
|
||||
id: String::from("main"),
|
||||
signature: Signature::new().outputs(vec![Type::FieldElement]),
|
||||
arguments: vec![],
|
||||
statements: vec![TypedStatement::Return(vec![
|
||||
FieldElementExpression::Number(FieldPrime::from(1)).into()
|
||||
])]
|
||||
}],
|
||||
imported_functions: vec![],
|
||||
imports: vec![]
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn new_with_args(
|
||||
// scope: HashSet<ScopedVariable>,
|
||||
|
|
Loading…
Reference in a new issue