mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 15:15:47 +03:00
clippy
This commit is contained in:
parent
e78b292552
commit
ff4edada7e
@ -58,7 +58,7 @@ impl LocatorExpression {
|
||||
/// Check if the Locator name and program matches the other name and program.
|
||||
pub fn matches(&self, other: &Self) -> bool {
|
||||
self.name == other.name && self.program == other.program
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LocatorExpression {
|
||||
@ -134,7 +134,7 @@ impl<'de> Deserialize<'de> for LocatorExpression {
|
||||
Some(name) => Symbol::intern(name),
|
||||
None => return Err(E::custom("missing 'name' in serialized Identifier struct")),
|
||||
};
|
||||
|
||||
|
||||
let program = match key.get("program") {
|
||||
Some(program) => Symbol::intern(program),
|
||||
None => return Err(E::custom("missing 'program' in serialized Identifier struct")),
|
||||
|
@ -61,7 +61,7 @@ pub trait ExpressionConsumer {
|
||||
fn consume_identifier(&mut self, _input: Identifier) -> Self::Output;
|
||||
|
||||
fn consume_literal(&mut self, _input: Literal) -> Self::Output;
|
||||
|
||||
|
||||
fn consume_locator(&mut self, _input: LocatorExpression) -> Self::Output;
|
||||
|
||||
fn consume_ternary(&mut self, _input: TernaryExpression) -> Self::Output;
|
||||
|
@ -198,12 +198,9 @@ pub trait ExpressionReconstructor {
|
||||
fn reconstruct_literal(&mut self, input: Literal) -> (Expression, Self::AdditionalOutput) {
|
||||
(Expression::Literal(input), Default::default())
|
||||
}
|
||||
|
||||
|
||||
fn reconstruct_locator(&mut self, input: LocatorExpression) -> (Expression, Self::AdditionalOutput) {
|
||||
(
|
||||
Expression::Locator(input),
|
||||
Default::default(),
|
||||
)
|
||||
(Expression::Locator(input), Default::default())
|
||||
}
|
||||
|
||||
fn reconstruct_ternary(&mut self, input: TernaryExpression) -> (Expression, Self::AdditionalOutput) {
|
||||
|
@ -107,8 +107,8 @@ pub trait ExpressionVisitor<'a> {
|
||||
fn visit_literal(&mut self, _input: &'a Literal, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_locator(&mut self, input: &'a LocatorExpression, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
|
||||
fn visit_locator(&mut self, _input: &'a LocatorExpression, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
use crate::Type;
|
||||
|
||||
use leo_span::Symbol;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use leo_span::Symbol;
|
||||
|
||||
/// A mapping type of a key and value type.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
|
@ -494,7 +494,6 @@ impl ParserContext<'_> {
|
||||
} else if self.eat(&Token::Leo) {
|
||||
return Err(ParserError::only_aleo_external_calls(expr.span()).into());
|
||||
} else if self.eat(&Token::Aleo) {
|
||||
|
||||
expr = self.parse_external_resource(expr)?;
|
||||
} else {
|
||||
// Parse identifier name.
|
||||
|
@ -15,7 +15,31 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{CodeGenerator, Location};
|
||||
use leo_ast::{AccessExpression, ArrayAccess, ArrayExpression, AssociatedConstant, AssociatedFunction, BinaryExpression, BinaryOperation, CallExpression, CastExpression, ErrExpression, Expression, Identifier, Literal, LocatorExpression, MemberAccess, ProgramScope, StructExpression, TernaryExpression, TupleExpression, Type, UnaryExpression, UnaryOperation, UnitExpression};
|
||||
use leo_ast::{
|
||||
AccessExpression,
|
||||
ArrayAccess,
|
||||
ArrayExpression,
|
||||
AssociatedConstant,
|
||||
AssociatedFunction,
|
||||
BinaryExpression,
|
||||
BinaryOperation,
|
||||
CallExpression,
|
||||
CastExpression,
|
||||
ErrExpression,
|
||||
Expression,
|
||||
Identifier,
|
||||
Literal,
|
||||
LocatorExpression,
|
||||
MemberAccess,
|
||||
ProgramScope,
|
||||
StructExpression,
|
||||
TernaryExpression,
|
||||
TupleExpression,
|
||||
Type,
|
||||
UnaryExpression,
|
||||
UnaryOperation,
|
||||
UnitExpression,
|
||||
};
|
||||
use leo_span::sym;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
@ -515,7 +539,8 @@ impl<'a> CodeGenerator<'a> {
|
||||
// Initialize storage for the destination registers.
|
||||
let mut destinations = Vec::new();
|
||||
|
||||
let return_type = &self.symbol_table.lookup_fn_symbol(Location::new(Some(main_program), function_name)).unwrap().output_type;
|
||||
let return_type =
|
||||
&self.symbol_table.lookup_fn_symbol(Location::new(Some(main_program), function_name)).unwrap().output_type;
|
||||
match return_type {
|
||||
Type::Unit => {} // Do nothing
|
||||
Type::Tuple(tuple) => match tuple.length() {
|
||||
|
@ -37,8 +37,8 @@ impl Serialize for Location {
|
||||
S: Serializer,
|
||||
{
|
||||
let condensed_str = match self.program {
|
||||
Some(program) => format!("{}/{}", program, self.name),
|
||||
None => format!("{}", self.name),
|
||||
Some(program) => format!("{}/{}", program, self.name),
|
||||
None => format!("{}", self.name),
|
||||
};
|
||||
serializer.serialize_str(&condensed_str)
|
||||
}
|
||||
@ -51,12 +51,8 @@ impl<'de> Deserialize<'de> for Location {
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
let mut parts: Vec<&str> = s.split('/').collect();
|
||||
let program = if parts.len() == 1 {
|
||||
None
|
||||
} else {
|
||||
Some(Symbol::intern(parts.remove(0)))
|
||||
};
|
||||
let name = Symbol::intern(parts.get(0).unwrap());
|
||||
let program = if parts.len() == 1 { None } else { Some(Symbol::intern(parts.remove(0))) };
|
||||
let name = Symbol::intern(parts.first().unwrap());
|
||||
Ok(Location::new(program, name))
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use std::cell::RefCell;
|
||||
|
||||
use leo_ast::{normalize_json_value, remove_key_from_json, Composite, Function};
|
||||
use leo_errors::{AstError, Result};
|
||||
use leo_span::{Span, Symbol};
|
||||
use leo_span::Span;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -60,7 +60,7 @@ impl SymbolTable {
|
||||
/// Recursively checks if the symbol table contains an entry for the given symbol.
|
||||
/// Leo does not allow any variable shadowing or overlap between different symbols.
|
||||
pub fn check_shadowing(&self, location: &Location, span: Span) -> Result<()> {
|
||||
if let Some(_) = location.program {
|
||||
if location.program.is_some() {
|
||||
if self.functions.contains_key(location) {
|
||||
return Err(AstError::shadowed_function(location.name, span).into());
|
||||
} else if let Some(existing) = self.structs.get(location) {
|
||||
@ -68,16 +68,11 @@ impl SymbolTable {
|
||||
true => Err(AstError::shadowed_record(location.name, span).into()),
|
||||
false => Err(AstError::shadowed_struct(location.name, span).into()),
|
||||
};
|
||||
} else if self.variables.contains_key(location) {
|
||||
return Err(AstError::shadowed_variable(location.name, span).into());
|
||||
}
|
||||
else if self.variables.contains_key(location) {
|
||||
return Err(AstError::shadowed_variable(location.name, span).into())
|
||||
}
|
||||
}
|
||||
if let Some(parent) = self.parent.as_ref() {
|
||||
return parent.check_shadowing(location, span)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
if let Some(parent) = self.parent.as_ref() { parent.check_shadowing(location, span) } else { Ok(()) }
|
||||
}
|
||||
|
||||
/// Returns the current scope index.
|
||||
@ -244,30 +239,29 @@ mod tests {
|
||||
block: Default::default(),
|
||||
};
|
||||
symbol_table.insert_fn(func_loc, &insert).unwrap();
|
||||
symbol_table.insert_variable(
|
||||
Location::new(Some(Symbol::intern("credits")), Symbol::intern("accounts")),
|
||||
VariableSymbol {
|
||||
type_: Type::Address,
|
||||
span: Default::default(),
|
||||
declaration: VariableType::Const,
|
||||
}).unwrap();
|
||||
symbol_table.insert_struct(
|
||||
Location::new(Some(Symbol::intern("credits")), Symbol::intern("token")),
|
||||
&Composite {
|
||||
symbol_table
|
||||
.insert_variable(
|
||||
Location::new(Some(Symbol::intern("credits")), Symbol::intern("accounts")),
|
||||
VariableSymbol { type_: Type::Address, span: Default::default(), declaration: VariableType::Const },
|
||||
)
|
||||
.unwrap();
|
||||
symbol_table
|
||||
.insert_struct(Location::new(Some(Symbol::intern("credits")), Symbol::intern("token")), &Composite {
|
||||
is_record: false,
|
||||
span: Default::default(),
|
||||
id: 0,
|
||||
identifier: Identifier::new(Symbol::intern("token"), Default::default()),
|
||||
members: Vec::new(),
|
||||
external: None,
|
||||
}).unwrap();
|
||||
symbol_table.insert_variable(
|
||||
Location::new(None, Symbol::intern("foo")),
|
||||
VariableSymbol {
|
||||
})
|
||||
.unwrap();
|
||||
symbol_table
|
||||
.insert_variable(Location::new(None, Symbol::intern("foo")), VariableSymbol {
|
||||
type_: Type::Address,
|
||||
span: Default::default(),
|
||||
declaration: VariableType::Const,
|
||||
}).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
let json = symbol_table.to_json_string().unwrap();
|
||||
let deserialized = SymbolTable::from_json_string(&json).unwrap();
|
||||
assert_eq!(symbol_table, deserialized);
|
||||
|
@ -89,8 +89,10 @@ impl ExpressionReconstructor for Flattener<'_> {
|
||||
Type::Array(first_type) => self.ternary_array(first_type, &input.condition, &first, &second),
|
||||
Type::Composite(first_type) => {
|
||||
// Get the struct definitions.
|
||||
let first_type =
|
||||
self.symbol_table.lookup_struct(Location::new(first_type.program, first_type.id.name)).unwrap();
|
||||
let first_type = self
|
||||
.symbol_table
|
||||
.lookup_struct(Location::new(first_type.program, first_type.id.name))
|
||||
.unwrap();
|
||||
self.ternary_struct(first_type, &input.condition, &first, &second)
|
||||
}
|
||||
Type::Tuple(first_type) => self.ternary_tuple(first_type, &input.condition, &first, &second),
|
||||
|
@ -19,7 +19,7 @@ use leo_ast::{Expression::Literal, Type::Integer, *};
|
||||
use leo_errors::loop_unroller::LoopUnrollerError;
|
||||
use leo_span::{Span, Symbol};
|
||||
|
||||
use crate::{Location, unroller::Unroller, VariableSymbol, VariableType};
|
||||
use crate::{unroller::Unroller, Location, VariableSymbol, VariableType};
|
||||
|
||||
impl StatementReconstructor for Unroller<'_> {
|
||||
fn reconstruct_block(&mut self, input: Block) -> (Block, Self::AdditionalOutput) {
|
||||
@ -60,7 +60,7 @@ impl StatementReconstructor for Unroller<'_> {
|
||||
}
|
||||
|
||||
// Remove from symbol table
|
||||
self.symbol_table.borrow_mut().remove_variable_from_current_scope(Location::new(None,input.place.name));
|
||||
self.symbol_table.borrow_mut().remove_variable_from_current_scope(Location::new(None, input.place.name));
|
||||
|
||||
(
|
||||
Statement::Const(ConstDeclaration {
|
||||
@ -77,11 +77,13 @@ impl StatementReconstructor for Unroller<'_> {
|
||||
fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
|
||||
// Helper function to add variables to symbol table
|
||||
let insert_variable = |symbol: Symbol, type_: Type, span: Span| {
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol {
|
||||
type_,
|
||||
span,
|
||||
declaration: VariableType::Mut,
|
||||
}) {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol {
|
||||
type_,
|
||||
span,
|
||||
declaration: VariableType::Mut,
|
||||
})
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
};
|
||||
|
@ -16,7 +16,30 @@
|
||||
|
||||
use crate::{Location, StaticSingleAssigner};
|
||||
|
||||
use leo_ast::{AccessExpression, ArrayAccess, ArrayExpression, AssociatedFunction, BinaryExpression, CallExpression, CastExpression, Composite, Expression, ExpressionConsumer, Identifier, Literal, LocatorExpression, MemberAccess, Statement, StructExpression, StructVariableInitializer, TernaryExpression, TupleAccess, TupleExpression, UnaryExpression, UnitExpression};
|
||||
use leo_ast::{
|
||||
AccessExpression,
|
||||
ArrayAccess,
|
||||
ArrayExpression,
|
||||
AssociatedFunction,
|
||||
BinaryExpression,
|
||||
CallExpression,
|
||||
CastExpression,
|
||||
Composite,
|
||||
Expression,
|
||||
ExpressionConsumer,
|
||||
Identifier,
|
||||
Literal,
|
||||
LocatorExpression,
|
||||
MemberAccess,
|
||||
Statement,
|
||||
StructExpression,
|
||||
StructVariableInitializer,
|
||||
TernaryExpression,
|
||||
TupleAccess,
|
||||
TupleExpression,
|
||||
UnaryExpression,
|
||||
UnitExpression,
|
||||
};
|
||||
use leo_span::{sym, Symbol};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
@ -295,14 +318,13 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
|
||||
let (place, statement) = self.unique_simple_assign_statement(Expression::Literal(input));
|
||||
(Expression::Identifier(place), vec![statement])
|
||||
}
|
||||
|
||||
/// Consumes and returns the locator expression without making any modifciations
|
||||
|
||||
/// Consumes and returns the locator expression without making any modifciations
|
||||
fn consume_locator(&mut self, input: LocatorExpression) -> Self::Output {
|
||||
// Construct and accumulate a new assignment statement for the locator expression.
|
||||
let (place, statement) = self.unique_simple_assign_statement(Expression::Locator(input));
|
||||
(Expression::Identifier(place), vec![statement])
|
||||
}
|
||||
|
||||
|
||||
/// Consumes a ternary expression, accumulating any statements that are generated.
|
||||
fn consume_ternary(&mut self, input: TernaryExpression) -> Self::Output {
|
||||
|
@ -72,20 +72,22 @@ impl<'a> ProgramVisitor<'a> for SymbolTableCreator<'a> {
|
||||
|
||||
fn visit_mapping(&mut self, input: &'a Mapping) {
|
||||
// Check if mapping is external.
|
||||
let program = match self.is_stub {
|
||||
let program = match self.is_stub {
|
||||
true => self.program_name,
|
||||
false => None,
|
||||
};
|
||||
// Add the variable associated with the mapping to the symbol table.
|
||||
if let Err(err) = self.symbol_table.insert_variable(Location::new(program, input.identifier.name), VariableSymbol {
|
||||
type_: Type::Mapping(MappingType {
|
||||
key: Box::new(input.key_type.clone()),
|
||||
value: Box::new(input.value_type.clone()),
|
||||
program: self.program_name.unwrap(),
|
||||
}),
|
||||
span: input.span,
|
||||
declaration: VariableType::Mut,
|
||||
}) {
|
||||
if let Err(err) =
|
||||
self.symbol_table.insert_variable(Location::new(program, input.identifier.name), VariableSymbol {
|
||||
type_: Type::Mapping(MappingType {
|
||||
key: Box::new(input.key_type.clone()),
|
||||
value: Box::new(input.value_type.clone()),
|
||||
program: self.program_name.unwrap(),
|
||||
}),
|
||||
span: input.span,
|
||||
declaration: VariableType::Mut,
|
||||
})
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
Expression::Err(err) => self.visit_err(err, additional),
|
||||
Expression::Identifier(identifier) => self.visit_identifier(identifier, additional),
|
||||
Expression::Literal(literal) => self.visit_literal(literal, additional),
|
||||
Expression::Locator(locator) => panic!("aiya"), // TODO: self.visit_locator(locator, additional),
|
||||
Expression::Locator(locator) => self.visit_locator(locator, additional),
|
||||
Expression::Ternary(ternary) => self.visit_ternary(ternary, additional),
|
||||
Expression::Tuple(tuple) => self.visit_tuple(tuple, additional),
|
||||
Expression::Unary(unary) => self.visit_unary(unary, additional),
|
||||
@ -571,7 +571,8 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
Expression::Identifier(ident) => {
|
||||
// Note: The function symbol lookup is performed outside of the `if let Some(func) ...` block to avoid a RefCell lifetime bug in Rust.
|
||||
// Do not move it into the `if let Some(func) ...` block or it will keep `self.symbol_table_creation` alive for the entire block and will be very memory inefficient!
|
||||
let func = self.symbol_table.borrow().lookup_fn_symbol(Location::new(input.program, ident.name)).cloned();
|
||||
let func =
|
||||
self.symbol_table.borrow().lookup_fn_symbol(Location::new(input.program, ident.name)).cloned();
|
||||
if let Some(func) = func {
|
||||
// Check that the call is valid.
|
||||
// Note that this unwrap is safe since we always set the variant before traversing the body of the function.
|
||||
@ -650,7 +651,8 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
|
||||
fn visit_struct_init(&mut self, input: &'a StructExpression, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
let struct_ = self.symbol_table.borrow().lookup_struct(Location::new(self.program_name, input.name.name)).cloned();
|
||||
let struct_ =
|
||||
self.symbol_table.borrow().lookup_struct(Location::new(self.program_name, input.name.name)).cloned();
|
||||
if let Some(struct_) = struct_ {
|
||||
// Check struct type name.
|
||||
let ret = self.check_expected_struct(&struct_, additional, input.name.span());
|
||||
@ -767,6 +769,16 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_locator(&mut self, input: &'a LocatorExpression, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
// Check that the locator points to a valid resource in the ST.
|
||||
if let Some(var) = self.symbol_table.borrow().lookup_variable(Location::new(Some(input.program), input.name)) {
|
||||
Some(self.assert_and_return_type(var.type_.clone(), expected, input.span()))
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::unknown_sym("variable", input.name, input.span()));
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ternary(&mut self, input: &'a TernaryExpression, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_expression(&input.condition, &Some(Type::Boolean));
|
||||
|
||||
|
@ -69,8 +69,12 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
// Lookup function metadata in the symbol table.
|
||||
// Note that this unwrap is safe since function metadata is stored in a prior pass.
|
||||
let function_index =
|
||||
self.symbol_table.borrow().lookup_fn_symbol(Location::new(self.program_name, input.identifier.name)).unwrap().id;
|
||||
let function_index = self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_fn_symbol(Location::new(self.program_name, input.identifier.name))
|
||||
.unwrap()
|
||||
.id;
|
||||
|
||||
// Enter the function's scope.
|
||||
self.enter_scope(function_index);
|
||||
|
@ -68,7 +68,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
let var_type = if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(Location::new(None, var_name.name)) {
|
||||
let var_type = if let Some(var) =
|
||||
self.symbol_table.borrow_mut().lookup_variable(Location::new(None, var_name.name))
|
||||
{
|
||||
match &var.declaration {
|
||||
VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)),
|
||||
VariableType::Input(Mode::Constant) => {
|
||||
@ -192,11 +194,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
self.visit_expression(&input.value, &Some(input.type_.clone()));
|
||||
|
||||
// Add constants to symbol table so that any references to them in later statements will pass TC
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.place.name), VariableSymbol {
|
||||
type_: input.type_.clone(),
|
||||
span: input.place.span,
|
||||
declaration: VariableType::Const,
|
||||
}) {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.place.name), VariableSymbol {
|
||||
type_: input.type_.clone(),
|
||||
span: input.place.span,
|
||||
declaration: VariableType::Const,
|
||||
})
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
@ -240,11 +244,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// TODO: Dedup with unrolling pass.
|
||||
// Helper to insert the variables into the symbol table.
|
||||
let insert_variable = |symbol: Symbol, type_: Type, span: Span| {
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol {
|
||||
type_,
|
||||
span,
|
||||
declaration: VariableType::Mut,
|
||||
}) {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(Location::new(None, symbol), VariableSymbol {
|
||||
type_,
|
||||
span,
|
||||
declaration: VariableType::Mut,
|
||||
})
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
};
|
||||
@ -308,11 +314,13 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
let scope_index = self.create_child_scope();
|
||||
|
||||
// Add the loop variable to the scope of the loop body.
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.variable.name), VariableSymbol {
|
||||
type_: input.type_.clone(),
|
||||
span: input.span(),
|
||||
declaration: VariableType::Const,
|
||||
}) {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(Location::new(None, input.variable.name), VariableSymbol {
|
||||
type_: input.type_.clone(),
|
||||
span: input.span(),
|
||||
declaration: VariableType::Const,
|
||||
})
|
||||
{
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
|
||||
@ -381,14 +389,15 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// We can safely unwrap all self.parent instances because
|
||||
// statements should always have some parent block
|
||||
let parent = self.function.unwrap();
|
||||
let return_type = &self.symbol_table.borrow().lookup_fn_symbol(Location::new(self.program_name, parent)).map(|f| {
|
||||
match self.is_finalize {
|
||||
// TODO: Check this.
|
||||
// Note that this `unwrap()` is safe since we checked that the function has a finalize block.
|
||||
true => f.finalize.as_ref().unwrap().output_type.clone(),
|
||||
false => f.output_type.clone(),
|
||||
}
|
||||
});
|
||||
let return_type =
|
||||
&self.symbol_table.borrow().lookup_fn_symbol(Location::new(self.program_name, parent)).map(|f| {
|
||||
match self.is_finalize {
|
||||
// TODO: Check this.
|
||||
// Note that this `unwrap()` is safe since we checked that the function has a finalize block.
|
||||
true => f.finalize.as_ref().unwrap().output_type.clone(),
|
||||
false => f.output_type.clone(),
|
||||
}
|
||||
});
|
||||
|
||||
// Set the `has_return` flag.
|
||||
self.has_return = true;
|
||||
|
@ -976,10 +976,7 @@ impl<'a> TypeChecker<'a> {
|
||||
if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) {
|
||||
// Cannot modify external mappings.
|
||||
if mapping_type.program != self.program_name.unwrap() {
|
||||
self.handler.emit_err(TypeCheckerError::cannot_modify_external_mapping(
|
||||
"set",
|
||||
function_span,
|
||||
));
|
||||
self.handler.emit_err(TypeCheckerError::cannot_modify_external_mapping("set", function_span));
|
||||
}
|
||||
// Check that the second argument matches the key type of the mapping.
|
||||
self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1);
|
||||
@ -1003,10 +1000,8 @@ impl<'a> TypeChecker<'a> {
|
||||
if let Some(mapping_type) = self.assert_mapping_type(&arguments[0].0, arguments[0].1) {
|
||||
// Cannot modify external mappings.
|
||||
if mapping_type.program != self.program_name.unwrap() {
|
||||
self.handler.emit_err(TypeCheckerError::cannot_modify_external_mapping(
|
||||
"remove",
|
||||
function_span,
|
||||
));
|
||||
self.handler
|
||||
.emit_err(TypeCheckerError::cannot_modify_external_mapping("remove", function_span));
|
||||
}
|
||||
// Check that the second argument matches the key type of the mapping.
|
||||
self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1);
|
||||
@ -1078,7 +1073,10 @@ impl<'a> TypeChecker<'a> {
|
||||
pub(crate) fn check_duplicate_struct(&self, name: Symbol, program_1: Symbol, program_2: Symbol) -> bool {
|
||||
// Make sure that both structs have been defined already.
|
||||
let st = self.symbol_table.borrow();
|
||||
let (struct_1, struct_2) = match (st.lookup_struct(Location::new(Some(program_1), name)), st.lookup_struct(Location::new(Some(program_2), name))) {
|
||||
let (struct_1, struct_2) = match (
|
||||
st.lookup_struct(Location::new(Some(program_1), name)),
|
||||
st.lookup_struct(Location::new(Some(program_2), name)),
|
||||
) {
|
||||
(Some(struct_1), Some(struct_2)) => (struct_1, struct_2),
|
||||
_ => return false,
|
||||
};
|
||||
@ -1148,7 +1146,11 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
// Check that the named composite type has been defined.
|
||||
Type::Composite(struct_)
|
||||
if self.symbol_table.borrow().lookup_struct(Location::new(struct_.program, struct_.id.name)).is_none() =>
|
||||
if self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_struct(Location::new(struct_.program, struct_.id.name))
|
||||
.is_none() =>
|
||||
{
|
||||
is_valid = false;
|
||||
self.emit_err(TypeCheckerError::undefined_type(struct_.id.name, span));
|
||||
@ -1181,8 +1183,10 @@ impl<'a> TypeChecker<'a> {
|
||||
// Array elements cannot be records.
|
||||
Type::Composite(struct_type) => {
|
||||
// Look up the type.
|
||||
if let Some(struct_) =
|
||||
self.symbol_table.borrow().lookup_struct(Location::new(struct_type.program, struct_type.id.name))
|
||||
if let Some(struct_) = self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
.lookup_struct(Location::new(struct_type.program, struct_type.id.name))
|
||||
{
|
||||
// Check that the type is not a record.
|
||||
if struct_.is_record {
|
||||
@ -1241,7 +1245,9 @@ impl<'a> TypeChecker<'a> {
|
||||
|
||||
// If the function is not a transition function, then it cannot have a record as input
|
||||
if let Type::Composite(struct_) = input_var.type_() {
|
||||
if let Some(val) = self.symbol_table.borrow().lookup_struct(Location::new(struct_.program, struct_.id.name)) {
|
||||
if let Some(val) =
|
||||
self.symbol_table.borrow().lookup_struct(Location::new(struct_.program, struct_.id.name))
|
||||
{
|
||||
if val.is_record && !matches!(function.variant, Variant::Transition) {
|
||||
self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(input_var.span()));
|
||||
}
|
||||
@ -1250,13 +1256,14 @@ impl<'a> TypeChecker<'a> {
|
||||
|
||||
// Add non-stub inputs to the symbol table.
|
||||
if !self.is_stub {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(Location::new(None, input_var.identifier().name), VariableSymbol {
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
Location::new(None, input_var.identifier().name),
|
||||
VariableSymbol {
|
||||
type_: input_var.type_(),
|
||||
span: input_var.identifier().span(),
|
||||
declaration: VariableType::Input(input_var.mode()),
|
||||
})
|
||||
{
|
||||
},
|
||||
) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
@ -1349,13 +1356,14 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
// Add non-stub inputs to the symbol table.
|
||||
if !self.is_stub {
|
||||
if let Err(err) =
|
||||
self.symbol_table.borrow_mut().insert_variable(Location::new(None, input_var.identifier().name), VariableSymbol {
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
Location::new(None, input_var.identifier().name),
|
||||
VariableSymbol {
|
||||
type_: input_var.type_(),
|
||||
span: input_var.identifier().span(),
|
||||
declaration: VariableType::Input(input_var.mode()),
|
||||
})
|
||||
{
|
||||
},
|
||||
) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
}
|
||||
|
@ -768,7 +768,7 @@ create_messages!(
|
||||
msg: format!("The definition for `{struct_}` in program `{program_1}.aleo` does not match the definition in program `{program_2}.aleo`"),
|
||||
help: Some("Check that the struct definition in the current program matches the definition in the imported program.".to_string()),
|
||||
}
|
||||
|
||||
|
||||
@formatted
|
||||
cannot_modify_external_mapping {
|
||||
args: (operation: impl Display),
|
||||
|
Loading…
Reference in New Issue
Block a user