wip
This commit is contained in:
parent
c84c0c5ca7
commit
266320f7d9
7 changed files with 473 additions and 226 deletions
16
t.code
Normal file
16
t.code
Normal file
|
@ -0,0 +1,16 @@
|
|||
struct Foo {
|
||||
a: field,
|
||||
b: field[2],
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
a: Foo,
|
||||
b: field[2]
|
||||
}
|
||||
|
||||
def f(Foo a) -> (Foo):
|
||||
return a
|
||||
|
||||
def main(Bar a) -> (Foo):
|
||||
return f(a.a)
|
||||
|
|
@ -7,15 +7,25 @@ use zokrates_pest_ast as pest;
|
|||
impl<'ast, T: Field> From<pest::File<'ast>> for absy::Module<'ast, T> {
|
||||
fn from(prog: pest::File<'ast>) -> absy::Module<T> {
|
||||
absy::Module {
|
||||
types: prog
|
||||
// types: prog
|
||||
// .structs
|
||||
// .into_iter()
|
||||
// .map(|t| absy::TypeDeclarationNode::from(t))
|
||||
// .collect(),
|
||||
// functions: prog
|
||||
// .functions
|
||||
// .into_iter()
|
||||
// .map(|f| absy::FunctionDeclarationNode::from(f))
|
||||
// .collect(),
|
||||
symbols: prog
|
||||
.structs
|
||||
.into_iter()
|
||||
.map(|t| absy::TypeDeclarationNode::from(t))
|
||||
.collect(),
|
||||
functions: prog
|
||||
.functions
|
||||
.into_iter()
|
||||
.map(|f| absy::FunctionDeclarationNode::from(f))
|
||||
.map(|t| absy::SymbolDeclarationNode::from(t))
|
||||
.chain(
|
||||
prog.functions
|
||||
.into_iter()
|
||||
.map(|f| absy::SymbolDeclarationNode::from(f)),
|
||||
)
|
||||
.collect(),
|
||||
imports: prog
|
||||
.imports
|
||||
|
@ -35,8 +45,8 @@ impl<'ast> From<pest::ImportDirective<'ast>> for absy::ImportNode<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<pest::StructDefinition<'ast>> for absy::TypeDeclarationNode<'ast> {
|
||||
fn from(definition: pest::StructDefinition<'ast>) -> absy::TypeDeclarationNode {
|
||||
impl<'ast, T: Field> From<pest::StructDefinition<'ast>> for absy::SymbolDeclarationNode<'ast, T> {
|
||||
fn from(definition: pest::StructDefinition<'ast>) -> absy::SymbolDeclarationNode<'ast, T> {
|
||||
use absy::NodeValue;
|
||||
|
||||
let span = definition.span;
|
||||
|
@ -52,9 +62,9 @@ impl<'ast> From<pest::StructDefinition<'ast>> for absy::TypeDeclarationNode<'ast
|
|||
}
|
||||
.span(span.clone()); // TODO check
|
||||
|
||||
absy::TypeDeclaration {
|
||||
absy::SymbolDeclaration {
|
||||
id,
|
||||
symbol: absy::TypeSymbol::Here(ty),
|
||||
symbol: absy::Symbol::HereType(ty),
|
||||
}
|
||||
.span(span)
|
||||
}
|
||||
|
@ -74,8 +84,8 @@ impl<'ast> From<pest::StructField<'ast>> for absy::StructFieldNode<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ast, T: Field> From<pest::Function<'ast>> for absy::FunctionDeclarationNode<'ast, T> {
|
||||
fn from(function: pest::Function<'ast>) -> absy::FunctionDeclarationNode<T> {
|
||||
impl<'ast, T: Field> From<pest::Function<'ast>> for absy::SymbolDeclarationNode<'ast, T> {
|
||||
fn from(function: pest::Function<'ast>) -> absy::SymbolDeclarationNode<T> {
|
||||
use absy::NodeValue;
|
||||
|
||||
let span = function.span;
|
||||
|
@ -115,9 +125,9 @@ impl<'ast, T: Field> From<pest::Function<'ast>> for absy::FunctionDeclarationNod
|
|||
}
|
||||
.span(span.clone()); // TODO check
|
||||
|
||||
absy::FunctionDeclaration {
|
||||
absy::SymbolDeclaration {
|
||||
id,
|
||||
symbol: absy::FunctionSymbol::Here(function),
|
||||
symbol: absy::Symbol::HereFunction(function),
|
||||
}
|
||||
.span(span)
|
||||
}
|
||||
|
|
|
@ -31,11 +31,8 @@ pub type ModuleId = String;
|
|||
/// A collection of `Module`s
|
||||
pub type Modules<'ast, T> = HashMap<ModuleId, Module<'ast, T>>;
|
||||
|
||||
/// A collection of `FunctionDeclaration`. Duplicates are allowed here as they are fine syntatically.
|
||||
pub type FunctionDeclarations<'ast, T> = Vec<FunctionDeclarationNode<'ast, T>>;
|
||||
|
||||
/// A collection of `StructDeclaration`. Duplicates are allowed here as they are fine syntatically.
|
||||
pub type TypeDeclarations<'ast> = Vec<TypeDeclarationNode<'ast>>;
|
||||
/// A collection of `SymbolDeclaration`. Duplicates are allowed here as they are fine syntatically.
|
||||
pub type Declarations<'ast, T> = Vec<SymbolDeclarationNode<'ast, T>>;
|
||||
|
||||
/// A `Program` is a collection of `Module`s and an id of the main `Module`
|
||||
pub struct Program<'ast, T: Field> {
|
||||
|
@ -45,34 +42,26 @@ pub struct Program<'ast, T: Field> {
|
|||
|
||||
/// A declaration of a `FunctionSymbol`, be it from an import or a function definition
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct FunctionDeclaration<'ast, T: Field> {
|
||||
pub struct SymbolDeclaration<'ast, T: Field> {
|
||||
pub id: Identifier<'ast>,
|
||||
pub symbol: FunctionSymbol<'ast, T>,
|
||||
pub symbol: Symbol<'ast, T>,
|
||||
}
|
||||
|
||||
/// A declaration of a `TypeSymbol`, be it from an import or a function definition
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct TypeDeclaration<'ast> {
|
||||
pub id: Identifier<'ast>,
|
||||
pub symbol: TypeSymbol<'ast>,
|
||||
pub enum Symbol<'ast, T: Field> {
|
||||
HereType(StructTypeNode<'ast>),
|
||||
HereFunction(FunctionNode<'ast, T>),
|
||||
There(SymbolImportNode<'ast>),
|
||||
Flat(FlatEmbed),
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for TypeDeclaration<'ast> {
|
||||
impl<'ast, T: Field> fmt::Display for SymbolDeclaration<'ast, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.symbol {
|
||||
TypeSymbol::Here(ref s) => write!(f, "struct {} {}", self.id, s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type TypeDeclarationNode<'ast> = Node<TypeDeclaration<'ast>>;
|
||||
|
||||
impl<'ast, T: Field> fmt::Display for FunctionDeclaration<'ast, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.symbol {
|
||||
FunctionSymbol::Here(ref fun) => write!(f, "def {}{}", self.id, fun),
|
||||
FunctionSymbol::There(ref import) => write!(f, "import {} as {}", import, self.id),
|
||||
FunctionSymbol::Flat(ref flat_fun) => write!(
|
||||
Symbol::HereType(ref t) => write!(f, "struct {} {}", self.id, t),
|
||||
Symbol::HereFunction(ref fun) => write!(f, "def {}{}", self.id, fun),
|
||||
Symbol::There(ref import) => write!(f, "import {} as {}", import, self.id),
|
||||
Symbol::Flat(ref flat_fun) => write!(
|
||||
f,
|
||||
"def {}{}:\n\t// hidden",
|
||||
self.id,
|
||||
|
@ -82,31 +71,30 @@ impl<'ast, T: Field> fmt::Display for FunctionDeclaration<'ast, T> {
|
|||
}
|
||||
}
|
||||
|
||||
type FunctionDeclarationNode<'ast, T> = Node<FunctionDeclaration<'ast, T>>;
|
||||
type SymbolDeclarationNode<'ast, T> = Node<SymbolDeclaration<'ast, T>>;
|
||||
|
||||
/// A module as a collection of `FunctionDeclaration`s
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Module<'ast, T: Field> {
|
||||
/// Structs of the module
|
||||
pub types: TypeDeclarations<'ast>,
|
||||
/// Functions of the module
|
||||
pub functions: FunctionDeclarations<'ast, T>,
|
||||
/// Symbols of the module
|
||||
pub symbols: Declarations<'ast, T>,
|
||||
pub imports: Vec<ImportNode<'ast>>, // we still use `imports` as they are not directly converted into `FunctionDeclaration`s after the importer is done, `imports` is empty
|
||||
}
|
||||
|
||||
/// A function, be it defined in this module, imported from another module or a flat embed
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum FunctionSymbol<'ast, T: Field> {
|
||||
Here(FunctionNode<'ast, T>),
|
||||
There(FunctionImportNode<'ast>),
|
||||
Flat(FlatEmbed),
|
||||
}
|
||||
// /// A function, be it defined in this module, imported from another module or a flat embed
|
||||
// #[derive(Debug, Clone, PartialEq)]
|
||||
// pub enum FunctionSymbol<'ast, T: Field> {
|
||||
// Here(FunctionNode<'ast, T>),
|
||||
// There(FunctionImportNode<'ast>),
|
||||
// Flat(FlatEmbed),
|
||||
// }
|
||||
|
||||
/// A user defined type, a struct defined in this module for now // TODO allow importing types
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TypeSymbol<'ast> {
|
||||
Here(StructTypeNode<'ast>),
|
||||
}
|
||||
// /// A user defined type, a struct defined in this module for now // TODO allow importing types
|
||||
// #[derive(Debug, Clone, PartialEq)]
|
||||
// pub enum TypeSymbol<'ast> {
|
||||
// Here(StructTypeNode<'ast>),
|
||||
// There(TypeImportNode<'ast>),
|
||||
// }
|
||||
|
||||
/// A struct type definition
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -145,32 +133,32 @@ impl<'ast> fmt::Display for StructField<'ast> {
|
|||
|
||||
type StructFieldNode<'ast> = Node<StructField<'ast>>;
|
||||
|
||||
/// A function import
|
||||
/// An import
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct FunctionImport<'ast> {
|
||||
/// the id of the function in the target module. Note: there may be many candidates as imports statements do not specify the signature
|
||||
pub function_id: Identifier<'ast>,
|
||||
pub struct SymbolImport<'ast> {
|
||||
/// the id of the symbol in the target module. Note: there may be many candidates as imports statements do not specify the signature. In that case they must all be functions however.
|
||||
pub symbol_id: Identifier<'ast>,
|
||||
/// the id of the module to import from
|
||||
pub module_id: ModuleId,
|
||||
}
|
||||
|
||||
type FunctionImportNode<'ast> = Node<FunctionImport<'ast>>;
|
||||
type SymbolImportNode<'ast> = Node<SymbolImport<'ast>>;
|
||||
|
||||
impl<'ast> FunctionImport<'ast> {
|
||||
impl<'ast> SymbolImport<'ast> {
|
||||
pub fn with_id_in_module<S: Into<Identifier<'ast>>, U: Into<ModuleId>>(
|
||||
function_id: S,
|
||||
symbol_id: S,
|
||||
module_id: U,
|
||||
) -> Self {
|
||||
FunctionImport {
|
||||
function_id: function_id.into(),
|
||||
SymbolImport {
|
||||
symbol_id: symbol_id.into(),
|
||||
module_id: module_id.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for FunctionImport<'ast> {
|
||||
impl<'ast> fmt::Display for SymbolImport<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} from {}", self.function_id, self.module_id)
|
||||
write!(f, "{} from {}", self.symbol_id, self.module_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +172,7 @@ impl<'ast, T: Field> fmt::Display for Module<'ast, T> {
|
|||
.collect::<Vec<_>>(),
|
||||
);
|
||||
res.extend(
|
||||
self.functions
|
||||
self.symbols
|
||||
.iter()
|
||||
.map(|x| format!("{}", x))
|
||||
.collect::<Vec<_>>(),
|
||||
|
@ -197,13 +185,13 @@ impl<'ast, T: Field> fmt::Debug for Module<'ast, T> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"module(\n\timports:\n\t\t{}\n\tfunctions:\n\t\t{}\n)",
|
||||
"module(\n\timports:\n\t\t{}\n\tsymbols:\n\t\t{}\n)",
|
||||
self.imports
|
||||
.iter()
|
||||
.map(|x| format!("{:?}", x))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n\t\t"),
|
||||
self.functions
|
||||
self.symbols
|
||||
.iter()
|
||||
.map(|x| format!("{:?}", x))
|
||||
.collect::<Vec<_>>()
|
||||
|
|
|
@ -74,13 +74,12 @@ impl<'ast, T: Field> NodeValue for Expression<'ast, T> {}
|
|||
impl<'ast, T: Field> NodeValue for ExpressionList<'ast, T> {}
|
||||
impl<'ast, T: Field> NodeValue for Assignee<'ast, T> {}
|
||||
impl<'ast, T: Field> NodeValue for Statement<'ast, T> {}
|
||||
impl<'ast, T: Field> NodeValue for FunctionDeclaration<'ast, T> {}
|
||||
impl<'ast> NodeValue for TypeDeclaration<'ast> {}
|
||||
impl<'ast, T: Field> NodeValue for SymbolDeclaration<'ast, T> {}
|
||||
impl<'ast> NodeValue for StructType<'ast> {}
|
||||
impl<'ast> NodeValue for StructField<'ast> {}
|
||||
impl<'ast, T: Field> NodeValue for Function<'ast, T> {}
|
||||
impl<'ast, T: Field> NodeValue for Module<'ast, T> {}
|
||||
impl<'ast> NodeValue for FunctionImport<'ast> {}
|
||||
impl<'ast> NodeValue for SymbolImport<'ast> {}
|
||||
impl<'ast> NodeValue for Variable<'ast> {}
|
||||
impl<'ast> NodeValue for Parameter<'ast> {}
|
||||
impl<'ast> NodeValue for Import<'ast> {}
|
||||
|
|
|
@ -124,7 +124,7 @@ impl Importer {
|
|||
modules: &mut HashMap<ModuleId, Module<'ast, T>>,
|
||||
arena: &'ast Arena<String>,
|
||||
) -> Result<Module<'ast, T>, CompileErrors> {
|
||||
let mut functions: Vec<_> = vec![];
|
||||
let mut symbols: Vec<_> = vec![];
|
||||
|
||||
for import in destination.imports {
|
||||
let pos = import.pos();
|
||||
|
@ -136,10 +136,10 @@ impl Importer {
|
|||
"EMBED/sha256round" => {
|
||||
let alias = alias.unwrap_or("sha256round");
|
||||
|
||||
functions.push(
|
||||
FunctionDeclaration {
|
||||
symbols.push(
|
||||
SymbolDeclaration {
|
||||
id: &alias,
|
||||
symbol: FunctionSymbol::Flat(FlatEmbed::Sha256Round),
|
||||
symbol: Symbol::Flat(FlatEmbed::Sha256Round),
|
||||
}
|
||||
.start_end(pos.0, pos.1),
|
||||
);
|
||||
|
@ -147,10 +147,10 @@ impl Importer {
|
|||
"EMBED/unpack" => {
|
||||
let alias = alias.unwrap_or("unpack");
|
||||
|
||||
functions.push(
|
||||
FunctionDeclaration {
|
||||
symbols.push(
|
||||
SymbolDeclaration {
|
||||
id: &alias,
|
||||
symbol: FunctionSymbol::Flat(FlatEmbed::Unpack),
|
||||
symbol: Symbol::Flat(FlatEmbed::Unpack),
|
||||
}
|
||||
.start_end(pos.0, pos.1),
|
||||
);
|
||||
|
@ -185,11 +185,11 @@ impl Importer {
|
|||
|
||||
modules.insert(import.source.to_string(), compiled);
|
||||
|
||||
functions.push(
|
||||
FunctionDeclaration {
|
||||
symbols.push(
|
||||
SymbolDeclaration {
|
||||
id: &alias,
|
||||
symbol: FunctionSymbol::There(
|
||||
FunctionImport::with_id_in_module(
|
||||
symbol: Symbol::There(
|
||||
SymbolImport::with_id_in_module(
|
||||
"main",
|
||||
import.source.clone(),
|
||||
)
|
||||
|
@ -218,11 +218,11 @@ impl Importer {
|
|||
}
|
||||
}
|
||||
|
||||
functions.extend(destination.functions);
|
||||
symbols.extend(destination.symbols);
|
||||
|
||||
Ok(Module {
|
||||
imports: vec![],
|
||||
functions: functions,
|
||||
symbols,
|
||||
..destination
|
||||
})
|
||||
}
|
||||
|
|
|
@ -159,17 +159,17 @@ impl<'ast> Checker<'ast> {
|
|||
|
||||
let mut errors = vec![];
|
||||
|
||||
match Checker::check_single_main(modules.get(&program.main).unwrap()) {
|
||||
Ok(_) => {}
|
||||
Err(e) => errors.push(e),
|
||||
};
|
||||
|
||||
// recursively type-check modules starting with `main`
|
||||
match self.check_module(&program.main, &mut modules, &mut typed_modules) {
|
||||
Ok(()) => {}
|
||||
Err(e) => errors.extend(e),
|
||||
};
|
||||
|
||||
match Checker::check_single_main(typed_modules.get(&program.main).unwrap()) {
|
||||
Ok(_) => {}
|
||||
Err(e) => errors.push(e),
|
||||
};
|
||||
|
||||
if errors.len() > 0 {
|
||||
return Err(errors);
|
||||
}
|
||||
|
@ -180,19 +180,61 @@ impl<'ast> Checker<'ast> {
|
|||
})
|
||||
}
|
||||
|
||||
fn check_type_symbol<T: Field>(
|
||||
&mut self,
|
||||
s: TypeSymbol<'ast>,
|
||||
module_id: &ModuleId,
|
||||
modules: &mut Modules<'ast, T>,
|
||||
typed_modules: &mut TypedModules<'ast, T>,
|
||||
) -> Result<Type, Vec<Error>> {
|
||||
match s {
|
||||
TypeSymbol::Here(t) => {
|
||||
self.check_struct_type_declaration(t, module_id, modules, typed_modules)
|
||||
}
|
||||
}
|
||||
}
|
||||
// fn check_type_symbol<T: Field>(
|
||||
// &mut self,
|
||||
// s: StructTypeNode<'ast>,
|
||||
// module_id: &ModuleId,
|
||||
// modules: &mut Modules<'ast, T>,
|
||||
// typed_modules: &mut TypedModules<'ast, T>,
|
||||
// ) -> Result<Type, Vec<Error>> {
|
||||
|
||||
// let mut errors = vec![];
|
||||
|
||||
// match s {
|
||||
// TypeSymbol::Here(t) => {
|
||||
// self.check_struct_type_declaration(t, module_id, modules, typed_modules)
|
||||
// }
|
||||
// TypeSymbol::There(import_node) => {
|
||||
// let pos = import_node.pos();
|
||||
// let import = import_node.value;
|
||||
|
||||
// let res =
|
||||
// match Checker::new().check_module(&import.module_id, modules, typed_modules) {
|
||||
// Ok(()) => {
|
||||
// match self
|
||||
// .types
|
||||
// .get(&import.module_id)
|
||||
// .unwrap()
|
||||
// .get(import.type_id)
|
||||
// {
|
||||
// Some(ty) => Some(ty),
|
||||
// None => {
|
||||
// errors.push(Error {
|
||||
// pos: Some(pos),
|
||||
// message: format!(
|
||||
// "Type {} not found in module {}",
|
||||
// import.type_id, import.module_id
|
||||
// ),
|
||||
// });
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Err(e) => {
|
||||
// errors.extend(e);
|
||||
// None
|
||||
// }
|
||||
// };
|
||||
|
||||
// // return if any errors occured
|
||||
// if errors.len() > 0 {
|
||||
// return Err(errors);
|
||||
// }
|
||||
|
||||
// Ok(res.unwrap().clone())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn check_struct_type_declaration<T: Field>(
|
||||
&mut self,
|
||||
|
@ -235,81 +277,268 @@ impl<'ast> Checker<'ast> {
|
|||
Some(module) => {
|
||||
assert_eq!(module.imports.len(), 0);
|
||||
|
||||
for declaration in module.types {
|
||||
let ids = HashSet::new();
|
||||
|
||||
for declaration in module.symbols {
|
||||
let pos = declaration.pos();
|
||||
let declaration = declaration.value;
|
||||
|
||||
let ty = self
|
||||
.check_type_symbol(declaration.symbol, module_id, modules, typed_modules)
|
||||
.unwrap();
|
||||
self.types
|
||||
.entry(module_id.clone())
|
||||
.or_default()
|
||||
.insert(declaration.id.to_string(), ty);
|
||||
}
|
||||
match declaration.symbol {
|
||||
Symbol::HereType(t) => {
|
||||
match ids.insert(declaration.id) {
|
||||
true => errors.push(Error {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Another symbol with id {} is already defined",
|
||||
declaration.id,
|
||||
),
|
||||
}),
|
||||
false => {}
|
||||
};
|
||||
|
||||
for declaration in module.functions {
|
||||
self.enter_scope();
|
||||
let ty = self
|
||||
.check_struct_type_declaration(t, module_id, modules, typed_modules)
|
||||
.unwrap();
|
||||
|
||||
let pos = declaration.pos();
|
||||
let declaration = declaration.value;
|
||||
self.types
|
||||
.entry(module_id.clone())
|
||||
.or_default()
|
||||
.insert(declaration.id.to_string(), ty);
|
||||
}
|
||||
Symbol::HereFunction(f) => {
|
||||
self.enter_scope();
|
||||
|
||||
match self.check_function_symbol(
|
||||
declaration.symbol,
|
||||
module_id,
|
||||
modules,
|
||||
typed_modules,
|
||||
) {
|
||||
Ok(checked_function_symbols) => {
|
||||
for funct in checked_function_symbols {
|
||||
let query = FunctionQuery::new(
|
||||
declaration.id.clone(),
|
||||
&funct.signature(&typed_modules).inputs,
|
||||
&funct
|
||||
.signature(&typed_modules)
|
||||
.outputs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|o| Some(o))
|
||||
.collect(),
|
||||
);
|
||||
match self.check_function(f, module_id) {
|
||||
Ok(funct) => {
|
||||
let query = FunctionQuery::new(
|
||||
declaration.id.clone(),
|
||||
&funct.signature(&typed_modules).inputs,
|
||||
&funct
|
||||
.signature(&typed_modules)
|
||||
.outputs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|o| Some(o))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let candidates = self.find_candidates(&query);
|
||||
let candidates = self.find_candidates(&query);
|
||||
|
||||
match candidates.len() {
|
||||
1 => {
|
||||
errors.push(Error {
|
||||
match candidates.len() {
|
||||
1 => {
|
||||
errors.push(Error {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Duplicate definition for function {} with signature {}",
|
||||
declaration.id,
|
||||
funct.signature(&typed_modules)
|
||||
),
|
||||
});
|
||||
}
|
||||
0 => {}
|
||||
_ => panic!(
|
||||
"duplicate function declaration should have been caught"
|
||||
),
|
||||
}
|
||||
|
||||
ids.insert(declaration.id);
|
||||
|
||||
self.functions.insert(
|
||||
FunctionKey::with_id(declaration.id.clone())
|
||||
.signature(funct.signature(&typed_modules).clone()),
|
||||
);
|
||||
checked_functions.insert(
|
||||
FunctionKey::with_id(declaration.id.clone())
|
||||
.signature(funct.signature(&typed_modules).clone()),
|
||||
funct,
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
errors.extend(e);
|
||||
}
|
||||
}
|
||||
|
||||
self.exit_scope();
|
||||
}
|
||||
Symbol::There(import) => {
|
||||
let pos = import.pos();
|
||||
let import = import.value;
|
||||
|
||||
match Checker::new().check_module(
|
||||
&import.module_id,
|
||||
modules,
|
||||
typed_modules,
|
||||
) {
|
||||
Ok(()) => {
|
||||
// find candidates in the checked module
|
||||
let function_candidates: Vec<_> = typed_modules
|
||||
.get(&import.module_id)
|
||||
.unwrap()
|
||||
.functions
|
||||
.iter()
|
||||
.filter(|(k, _)| k.id == import.symbol_id)
|
||||
.map(|(_, v)| FunctionKey {
|
||||
id: import.symbol_id.clone(),
|
||||
signature: v.signature(&typed_modules).clone(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// find candidates in the types
|
||||
let type_candidate = self
|
||||
.types
|
||||
.get(&import.module_id)
|
||||
.map(|m| m.get(import.symbol_id));
|
||||
|
||||
match (function_candidates.len(), type_candidate) {
|
||||
(0, Some(t)) => errors.push(Error {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Duplicate definition for function {} with signature {}",
|
||||
declaration.id,
|
||||
funct.signature(&typed_modules)
|
||||
"Duplicate symbol {} in module {}",
|
||||
import.symbol_id, import.module_id
|
||||
),
|
||||
});
|
||||
}),
|
||||
(0, None) => unreachable!(),
|
||||
_ => {
|
||||
ids.insert(declaration.id);
|
||||
for candidate in function_candidates {
|
||||
self.functions
|
||||
.insert(candidate.clone().id(declaration.id));
|
||||
checked_functions.insert(
|
||||
candidate.clone().id(declaration.id),
|
||||
TypedFunctionSymbol::There(
|
||||
candidate,
|
||||
import.module_id.clone(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
0 => {}
|
||||
_ => panic!(
|
||||
"duplicate function declaration should have been caught"
|
||||
),
|
||||
}
|
||||
self.functions.insert(
|
||||
FunctionKey::with_id(declaration.id.clone())
|
||||
.signature(funct.signature(&typed_modules).clone()),
|
||||
);
|
||||
checked_functions.insert(
|
||||
FunctionKey::with_id(declaration.id.clone())
|
||||
.signature(funct.signature(&typed_modules).clone()),
|
||||
funct,
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
errors.extend(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(e) => {
|
||||
errors.extend(e);
|
||||
Symbol::Flat(funct) => {
|
||||
let query = FunctionQuery::new(
|
||||
declaration.id.clone(),
|
||||
&funct.signature::<T>().inputs,
|
||||
&funct
|
||||
.signature::<T>()
|
||||
.outputs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|o| Some(o))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let candidates = self.find_candidates(&query);
|
||||
|
||||
match candidates.len() {
|
||||
1 => {
|
||||
errors.push(Error {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Duplicate definition for function {} with signature {}",
|
||||
declaration.id,
|
||||
funct.signature::<T>()
|
||||
),
|
||||
});
|
||||
}
|
||||
0 => {}
|
||||
_ => {
|
||||
panic!("duplicate function declaration should have been caught")
|
||||
}
|
||||
}
|
||||
ids.insert(declaration.id);
|
||||
self.functions.insert(
|
||||
FunctionKey::with_id(declaration.id.clone())
|
||||
.signature(funct.signature::<T>().clone()),
|
||||
);
|
||||
checked_functions.insert(
|
||||
FunctionKey::with_id(declaration.id.clone())
|
||||
.signature(funct.signature::<T>().clone()),
|
||||
TypedFunctionSymbol::Flat(funct),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.exit_scope();
|
||||
}
|
||||
|
||||
// for declaration in module.types {
|
||||
// let pos = declaration.pos();
|
||||
// let declaration = declaration.value;
|
||||
|
||||
// let ty = self
|
||||
// .check_type_symbol(declaration.symbol, module_id, modules, typed_modules)
|
||||
// .unwrap();
|
||||
// self.types
|
||||
// .entry(module_id.clone())
|
||||
// .or_default()
|
||||
// .insert(declaration.id.to_string(), ty);
|
||||
// }
|
||||
|
||||
// for declaration in module.functions {
|
||||
// self.enter_scope();
|
||||
|
||||
// let pos = declaration.pos();
|
||||
// let declaration = declaration.value;
|
||||
|
||||
// match self.check_function_symbol(
|
||||
// declaration.symbol,
|
||||
// module_id,
|
||||
// modules,
|
||||
// typed_modules,
|
||||
// ) {
|
||||
// Ok(checked_function_symbols) => {
|
||||
// for funct in checked_function_symbols {
|
||||
// let query = FunctionQuery::new(
|
||||
// declaration.id.clone(),
|
||||
// &funct.signature(&typed_modules).inputs,
|
||||
// &funct
|
||||
// .signature(&typed_modules)
|
||||
// .outputs
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .map(|o| Some(o))
|
||||
// .collect(),
|
||||
// );
|
||||
|
||||
// let candidates = self.find_candidates(&query);
|
||||
|
||||
// match candidates.len() {
|
||||
// 1 => {
|
||||
// errors.push(Error {
|
||||
// pos: Some(pos),
|
||||
// message: format!(
|
||||
// "Duplicate definition for function {} with signature {}",
|
||||
// declaration.id,
|
||||
// funct.signature(&typed_modules)
|
||||
// ),
|
||||
// });
|
||||
// }
|
||||
// 0 => {}
|
||||
// _ => panic!(
|
||||
// "duplicate function declaration should have been caught"
|
||||
// ),
|
||||
// }
|
||||
// self.functions.insert(
|
||||
// FunctionKey::with_id(declaration.id.clone())
|
||||
// .signature(funct.signature(&typed_modules).clone()),
|
||||
// );
|
||||
// checked_functions.insert(
|
||||
// FunctionKey::with_id(declaration.id.clone())
|
||||
// .signature(funct.signature(&typed_modules).clone()),
|
||||
// funct,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// Err(e) => {
|
||||
// errors.extend(e);
|
||||
// }
|
||||
// }
|
||||
|
||||
// self.exit_scope();
|
||||
// }
|
||||
Some(TypedModule {
|
||||
functions: checked_functions,
|
||||
})
|
||||
|
@ -336,11 +565,11 @@ impl<'ast> Checker<'ast> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn check_single_main<T: Field>(module: &Module<T>) -> Result<(), Error> {
|
||||
fn check_single_main<T: Field>(module: &TypedModule<T>) -> Result<(), Error> {
|
||||
match module
|
||||
.functions
|
||||
.iter()
|
||||
.filter(|node| node.value.id == "main")
|
||||
.filter(|(key, _)| key.id == "main")
|
||||
.count()
|
||||
{
|
||||
1 => Ok(()),
|
||||
|
@ -369,7 +598,7 @@ impl<'ast> Checker<'ast> {
|
|||
&mut self,
|
||||
funct_node: FunctionNode<'ast, T>,
|
||||
module_id: &ModuleId,
|
||||
) -> Result<TypedFunction<'ast, T>, Vec<Error>> {
|
||||
) -> Result<TypedFunctionSymbol<'ast, T>, Vec<Error>> {
|
||||
let mut errors = vec![];
|
||||
let funct = funct_node.value;
|
||||
|
||||
|
@ -401,7 +630,7 @@ impl<'ast> Checker<'ast> {
|
|||
return Err(errors);
|
||||
}
|
||||
|
||||
Ok(TypedFunction {
|
||||
Ok(TypedFunctionSymbol::Here(TypedFunction {
|
||||
arguments: funct
|
||||
.arguments
|
||||
.into_iter()
|
||||
|
@ -409,7 +638,7 @@ impl<'ast> Checker<'ast> {
|
|||
.collect(),
|
||||
statements: statements_checked,
|
||||
signature,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn check_parameter(&self, p: ParameterNode<'ast>, module_id: &ModuleId) -> Parameter<'ast> {
|
||||
|
@ -452,69 +681,69 @@ impl<'ast> Checker<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_function_symbol<T: Field>(
|
||||
&mut self,
|
||||
funct_symbol: FunctionSymbol<'ast, T>,
|
||||
module_id: &ModuleId,
|
||||
modules: &mut Modules<'ast, T>,
|
||||
typed_modules: &mut TypedModules<'ast, T>,
|
||||
) -> Result<Vec<TypedFunctionSymbol<'ast, T>>, Vec<Error>> {
|
||||
let mut symbols = vec![];
|
||||
let mut errors = vec![];
|
||||
// fn check_function_symbol<T: Field>(
|
||||
// &mut self,
|
||||
// funct_symbol: FunctionSymbol<'ast, T>,
|
||||
// module_id: &ModuleId,
|
||||
// modules: &mut Modules<'ast, T>,
|
||||
// typed_modules: &mut TypedModules<'ast, T>,
|
||||
// ) -> Result<Vec<TypedFunctionSymbol<'ast, T>>, Vec<Error>> {
|
||||
// let mut symbols = vec![];
|
||||
// let mut errors = vec![];
|
||||
|
||||
match funct_symbol {
|
||||
FunctionSymbol::Here(funct_node) => self
|
||||
.check_function(funct_node, module_id)
|
||||
.map(|f| vec![TypedFunctionSymbol::Here(f)]),
|
||||
FunctionSymbol::There(import_node) => {
|
||||
let pos = import_node.pos();
|
||||
let import = import_node.value;
|
||||
// match funct_symbol {
|
||||
// FunctionSymbol::Here(funct_node) => self
|
||||
// .check_function(funct_node, module_id)
|
||||
// .map(|f| vec![TypedFunctionSymbol::Here(f)]),
|
||||
// FunctionSymbol::There(import_node) => {
|
||||
// let pos = import_node.pos();
|
||||
// let import = import_node.value;
|
||||
|
||||
match Checker::new().check_module(&import.module_id, modules, typed_modules) {
|
||||
Ok(()) => {
|
||||
// find candidates in the checked module
|
||||
let candidates: Vec<_> = typed_modules
|
||||
.get(&import.module_id)
|
||||
.unwrap()
|
||||
.functions
|
||||
.iter()
|
||||
.filter(|(k, _)| k.id == import.function_id)
|
||||
.map(|(_, v)| FunctionKey {
|
||||
id: import.function_id.clone(),
|
||||
signature: v.signature(&typed_modules).clone(),
|
||||
})
|
||||
.collect();
|
||||
// match Checker::new().check_module(&import.module_id, modules, typed_modules) {
|
||||
// Ok(()) => {
|
||||
// // find candidates in the checked module
|
||||
// let candidates: Vec<_> = typed_modules
|
||||
// .get(&import.module_id)
|
||||
// .unwrap()
|
||||
// .functions
|
||||
// .iter()
|
||||
// .filter(|(k, _)| k.id == import.function_id)
|
||||
// .map(|(_, v)| FunctionKey {
|
||||
// id: import.function_id.clone(),
|
||||
// signature: v.signature(&typed_modules).clone(),
|
||||
// })
|
||||
// .collect();
|
||||
|
||||
match candidates.len() {
|
||||
0 => errors.push(Error {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Function {} not found in module {}",
|
||||
import.function_id, import.module_id
|
||||
),
|
||||
}),
|
||||
_ => {
|
||||
symbols.extend(candidates.into_iter().map(|f| {
|
||||
TypedFunctionSymbol::There(f, import.module_id.clone())
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
errors.extend(e);
|
||||
}
|
||||
};
|
||||
// match candidates.len() {
|
||||
// 0 => errors.push(Error {
|
||||
// pos: Some(pos),
|
||||
// message: format!(
|
||||
// "Function {} not found in module {}",
|
||||
// import.function_id, import.module_id
|
||||
// ),
|
||||
// }),
|
||||
// _ => {
|
||||
// symbols.extend(candidates.into_iter().map(|f| {
|
||||
// TypedFunctionSymbol::There(f, import.module_id.clone())
|
||||
// }))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Err(e) => {
|
||||
// errors.extend(e);
|
||||
// }
|
||||
// };
|
||||
|
||||
// return if any errors occured
|
||||
if errors.len() > 0 {
|
||||
return Err(errors);
|
||||
}
|
||||
// // return if any errors occured
|
||||
// if errors.len() > 0 {
|
||||
// return Err(errors);
|
||||
// }
|
||||
|
||||
Ok(symbols)
|
||||
}
|
||||
FunctionSymbol::Flat(flat_fun) => Ok(vec![TypedFunctionSymbol::Flat(flat_fun)]),
|
||||
}
|
||||
}
|
||||
// Ok(symbols)
|
||||
// }
|
||||
// FunctionSymbol::Flat(flat_fun) => Ok(vec![TypedFunctionSymbol::Flat(flat_fun)]),
|
||||
// }
|
||||
// }
|
||||
|
||||
fn check_variable(
|
||||
&self,
|
||||
|
|
|
@ -145,6 +145,11 @@ impl<'ast> FunctionKey<'ast> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn id<S: Into<Identifier<'ast>>>(mut self, id: S) -> Self {
|
||||
self.id = id.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_slug(&self) -> String {
|
||||
format!("{}_{}", self.id, self.signature.to_slug())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue