add checks for ident types being allowed built in types

This commit is contained in:
gluax 2022-05-30 11:29:00 -07:00
parent 2db204b81e
commit 1da03e728b
9 changed files with 61 additions and 42 deletions

1
Cargo.lock generated
View File

@ -1344,6 +1344,7 @@ dependencies = [
name = "leo-stdlib"
version = "1.5.3"
dependencies = [
"indexmap",
"leo-ast",
"leo-errors",
"leo-span",

View File

@ -26,6 +26,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
self.parent = Some(input.name());
input.input.iter().for_each(|i| {
let input_var = i.get_variable();
self.validate_ident_type(&Some(input_var.type_));
if let Err(err) = self.symbol_table.insert_variable(
input_var.identifier.name,

View File

@ -29,10 +29,10 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
// statements should always have some parent block
let parent = self.visitor.parent.unwrap();
self.visit_expression(
&input.expression,
&self.visitor.symbol_table.lookup_fn(&parent).map(|f| f.output),
);
let return_type = &self.visitor.symbol_table.lookup_fn(&parent).map(|f| f.output);
self.visitor.validate_ident_type(return_type);
self.visit_expression(&input.expression, return_type);
}
fn visit_definition(&mut self, input: &'a DefinitionStatement) {
@ -43,6 +43,8 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
};
input.variable_names.iter().for_each(|v| {
self.visitor.validate_ident_type(&Some(input.type_));
if let Err(err) = self.visitor.symbol_table.insert_variable(
v.identifier.name,
VariableSymbol {
@ -83,6 +85,7 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
};
if var_type.is_some() {
self.visitor.validate_ident_type(&var_type);
self.visit_expression(&input.value, &var_type);
}
}
@ -103,8 +106,10 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
self.visitor.handler.emit_err(err);
}
self.visit_expression(&input.start, &Some(input.type_));
self.visit_expression(&input.stop, &Some(input.type_));
let iter_type = &Some(input.type_);
self.visitor.validate_ident_type(iter_type);
self.visit_expression(&input.start, iter_type);
self.visit_expression(&input.stop, iter_type);
}
fn visit_console(&mut self, input: &'a ConsoleStatement) {

View File

@ -14,9 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{IntegerType, Type};
use indexmap::IndexSet;
use leo_ast::{IntegerType, Node, Type};
use leo_errors::{emitter::Handler, TypeCheckerError};
use leo_span::{Span, Symbol};
use leo_stdlib::*;
use crate::SymbolTable;
@ -25,6 +27,8 @@ pub struct TypeChecker<'a> {
pub(crate) handler: &'a Handler,
pub(crate) parent: Option<Symbol>,
pub(crate) negate: bool,
pub(crate) account_types: IndexSet<Symbol>,
pub(crate) algorithms_types: IndexSet<Symbol>,
}
const INT_TYPES: [Type; 10] = [
@ -74,6 +78,18 @@ impl<'a> TypeChecker<'a> {
handler,
parent: None,
negate: false,
account_types: Account::types(),
algorithms_types: Algorithms::types(),
}
}
/// Validates that an ident type is a valid one.
pub(crate) fn validate_ident_type(&self, type_: &Option<Type>) {
if let Some(Type::Identifier(ident)) = type_ {
if !(self.account_types.contains(&ident.name) || self.algorithms_types.contains(&ident.name)) {
self.handler
.emit_err(TypeCheckerError::invalid_built_in_type(&ident.name, ident.span()).into());
}
}
}

View File

@ -28,7 +28,9 @@ version = "1.5.3"
path = "../../leo/errors"
version = "1.5.3"
[dependencies.leo-span]
path = "../../leo/span"
version = "1.5.3"
[dependencies]
indexmap = "1.7.0"

View File

@ -16,34 +16,20 @@
use crate::Types;
use leo_ast::{Identifier, Type};
use leo_span::{Span, Symbol};
use indexmap::IndexSet;
use leo_span::Symbol;
pub struct Account;
impl Types for Account {
fn types() -> Vec<Type> {
vec![
Type::Identifier(Identifier {
name: Symbol::intern("ComputeKey"),
span: Span::dummy(),
}),
Type::Identifier(Identifier {
name: Symbol::intern("PrivateKey"),
span: Span::dummy(),
}),
Type::Identifier(Identifier {
name: Symbol::intern("Record"),
span: Span::dummy(),
}),
Type::Identifier(Identifier {
name: Symbol::intern("Signature"),
span: Span::dummy(),
}),
Type::Identifier(Identifier {
name: Symbol::intern("ViewKey"),
span: Span::dummy(),
}),
]
fn types() -> IndexSet<Symbol> {
IndexSet::from([
Symbol::intern("ComputeKey"),
Symbol::intern("PrivateKey"),
Symbol::intern("Record"),
Symbol::intern("Signature"),
Symbol::intern("ViewKey"),
])
}
}

View File

@ -16,16 +16,13 @@
use crate::Types;
use leo_ast::{Identifier, Type};
use leo_span::{Span, Symbol};
use indexmap::IndexSet;
use leo_span::Symbol;
pub struct Algorithms;
impl Types for Algorithms {
fn types() -> Vec<Type> {
vec![Type::Identifier(Identifier {
name: Symbol::intern("Poseidon"),
span: Span::dummy(),
})]
fn types() -> IndexSet<Symbol> {
IndexSet::from([Symbol::intern("Poseidon")])
}
}

View File

@ -16,7 +16,8 @@
#![doc = include_str!("../README.md")]
use leo_ast::Type;
use indexmap::IndexSet;
use leo_span::Symbol;
mod account;
pub use account::*;
@ -25,5 +26,5 @@ mod algorithms;
pub use algorithms::*;
pub trait Types {
fn types() -> Vec<Type>;
fn types() -> IndexSet<Symbol>;
}

View File

@ -132,4 +132,14 @@ create_messages!(
),
help: None,
}
/// For when an invalid built in type is used.
@formatted
invalid_built_in_type {
args: (type_: impl Display),
msg: format!(
"The type {type_} is not a valid built in type.",
),
help: None,
}
);