1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

process external functions in semantics

This commit is contained in:
schaeff 2019-05-13 20:59:54 +02:00
parent 5f83bc86e7
commit c6219be41d
2 changed files with 116 additions and 31 deletions

View file

@ -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>>;

View file

@ -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>,