mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-18 23:02:35 +03:00
had to handle negation of signed integers
This commit is contained in:
parent
2c252f7878
commit
67fd130c0c
@ -39,7 +39,7 @@ fn return_incorrect_type(t1: Option<Type>, t2: Option<Type>, expected: Option<Ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TypeChecker<'a> {
|
impl<'a> TypeChecker<'a> {
|
||||||
pub(crate) fn compare_expr_type(&self, expr: &Expression, expected: Option<Type>, span: &Span) -> Option<Type> {
|
pub(crate) fn compare_expr_type(&mut self, expr: &Expression, expected: Option<Type>, span: &Span) -> Option<Type> {
|
||||||
match expr {
|
match expr {
|
||||||
Expression::Identifier(ident) => {
|
Expression::Identifier(ident) => {
|
||||||
if let Some(var) = self.symbol_table.lookup_variable(&ident.name) {
|
if let Some(var) = self.symbol_table.lookup_variable(&ident.name) {
|
||||||
@ -55,11 +55,95 @@ impl<'a> TypeChecker<'a> {
|
|||||||
ValueExpression::Boolean(_, _) => Some(self.assert_type(Type::Boolean, expected, value.span())),
|
ValueExpression::Boolean(_, _) => Some(self.assert_type(Type::Boolean, expected, value.span())),
|
||||||
ValueExpression::Char(_) => Some(self.assert_type(Type::Char, expected, value.span())),
|
ValueExpression::Char(_) => Some(self.assert_type(Type::Char, expected, value.span())),
|
||||||
ValueExpression::Field(_, _) => Some(self.assert_type(Type::Field, expected, value.span())),
|
ValueExpression::Field(_, _) => Some(self.assert_type(Type::Field, expected, value.span())),
|
||||||
ValueExpression::Integer(type_, _, _) => {
|
ValueExpression::Integer(type_, str_content, _) => {
|
||||||
|
match type_ {
|
||||||
|
IntegerType::I8 => {
|
||||||
|
let int = if self.negate {
|
||||||
|
self.negate = false;
|
||||||
|
format!("-{str_content}")
|
||||||
|
} else {
|
||||||
|
str_content.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if int.parse::<i8>().is_err() {
|
||||||
|
self.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(int, "i8", value.span()).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IntegerType::I16 => {
|
||||||
|
let int = if self.negate {
|
||||||
|
self.negate = false;
|
||||||
|
format!("-{str_content}")
|
||||||
|
} else {
|
||||||
|
str_content.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if int.parse::<i16>().is_err() {
|
||||||
|
self.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(int, "i16", value.span()).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IntegerType::I32 => {
|
||||||
|
let int = if self.negate {
|
||||||
|
self.negate = false;
|
||||||
|
format!("-{str_content}")
|
||||||
|
} else {
|
||||||
|
str_content.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if int.parse::<i32>().is_err() {
|
||||||
|
self.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(int, "i32", value.span()).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IntegerType::I64 => {
|
||||||
|
let int = if self.negate {
|
||||||
|
self.negate = false;
|
||||||
|
format!("-{str_content}")
|
||||||
|
} else {
|
||||||
|
str_content.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if int.parse::<i64>().is_err() {
|
||||||
|
self.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(int, "i64", value.span()).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IntegerType::I128 => {
|
||||||
|
let int = if self.negate {
|
||||||
|
self.negate = false;
|
||||||
|
format!("-{str_content}")
|
||||||
|
} else {
|
||||||
|
str_content.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if int.parse::<i128>().is_err() {
|
||||||
|
self.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(int, "i128", value.span()).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntegerType::U8 if str_content.parse::<u8>().is_err() => self
|
||||||
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(str_content, "u8", value.span()).into()),
|
||||||
|
IntegerType::U16 if str_content.parse::<u16>().is_err() => self
|
||||||
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(str_content, "u16", value.span()).into()),
|
||||||
|
IntegerType::U32 if str_content.parse::<u32>().is_err() => self
|
||||||
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(str_content, "u32", value.span()).into()),
|
||||||
|
IntegerType::U64 if str_content.parse::<u64>().is_err() => self
|
||||||
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(str_content, "u64", value.span()).into()),
|
||||||
|
IntegerType::U128 if str_content.parse::<u128>().is_err() => self
|
||||||
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::invalid_int_value(str_content, "u128", value.span()).into()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
Some(self.assert_type(Type::IntegerType(*type_), expected, value.span()))
|
Some(self.assert_type(Type::IntegerType(*type_), expected, value.span()))
|
||||||
}
|
}
|
||||||
ValueExpression::Group(_) => Some(self.assert_type(Type::Group, expected, value.span())),
|
ValueExpression::Group(_) => Some(self.assert_type(Type::Group, expected, value.span())),
|
||||||
ValueExpression::String(_, _) => None,
|
ValueExpression::String(_, _) => unreachable!("String types are not reachable"),
|
||||||
},
|
},
|
||||||
Expression::Binary(binary) => match binary.op {
|
Expression::Binary(binary) => match binary.op {
|
||||||
BinaryOperation::And | BinaryOperation::Or => {
|
BinaryOperation::And | BinaryOperation::Or => {
|
||||||
@ -163,19 +247,25 @@ impl<'a> TypeChecker<'a> {
|
|||||||
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
|
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
|
||||||
}
|
}
|
||||||
UnaryOperation::Negate => {
|
UnaryOperation::Negate => {
|
||||||
/* match expected {
|
// -128i8
|
||||||
|
// -(-128i16 + 3i16) = 125i16
|
||||||
|
match expected.as_ref() {
|
||||||
|
Some(
|
||||||
Type::IntegerType(
|
Type::IntegerType(
|
||||||
IntegerType::I8
|
IntegerType::I8
|
||||||
| IntegerType::I16
|
| IntegerType::I16
|
||||||
| IntegerType::I32
|
| IntegerType::I32
|
||||||
| IntegerType::I64
|
| IntegerType::I64
|
||||||
| IntegerType::I128,
|
| IntegerType::I128,
|
||||||
) => {},
|
)
|
||||||
Type::Field | Type::Group => {}
|
| Type::Field
|
||||||
_ => self.handler.emit_err(
|
| Type::Group,
|
||||||
TypeCheckerError::type_is_not_negatable(expected.clone(), unary.inner.span()).into(),
|
) => self.negate = !self.negate,
|
||||||
),
|
Some(t) => self
|
||||||
} */
|
.handler
|
||||||
|
.emit_err(TypeCheckerError::type_is_not_negatable(t, unary.inner.span()).into()),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
|
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -25,9 +25,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
|||||||
// statements should always have some parent block
|
// statements should always have some parent block
|
||||||
let parent = self.parent.unwrap();
|
let parent = self.parent.unwrap();
|
||||||
|
|
||||||
if let Some(func) = self.symbol_table.lookup_fn(&parent) {
|
// Would never be None.
|
||||||
self.compare_expr_type(&input.expression, Some(func.output.clone()), input.expression.span());
|
let func_output_type = self.symbol_table.lookup_fn(&parent).map(|f| f.output.clone());
|
||||||
}
|
self.compare_expr_type(&input.expression, func_output_type, input.expression.span());
|
||||||
|
|
||||||
VisitResult::VisitChildren
|
VisitResult::VisitChildren
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
|||||||
|
|
||||||
fn visit_assign(&mut self, input: &'a AssignStatement) -> VisitResult {
|
fn visit_assign(&mut self, input: &'a AssignStatement) -> VisitResult {
|
||||||
let var_name = &input.assignee.identifier.name;
|
let var_name = &input.assignee.identifier.name;
|
||||||
if let Some(var) = self.symbol_table.lookup_variable(var_name) {
|
let var_type = if let Some(var) = self.symbol_table.lookup_variable(var_name) {
|
||||||
match &var.declaration {
|
match &var.declaration {
|
||||||
Declaration::Const => self
|
Declaration::Const => self
|
||||||
.handler
|
.handler
|
||||||
@ -70,11 +70,17 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.compare_expr_type(&input.value, Some(var.type_.clone()), input.value.span());
|
Some(var.type_.clone())
|
||||||
} else {
|
} else {
|
||||||
self.handler.emit_err(
|
self.handler.emit_err(
|
||||||
TypeCheckerError::unknown_sym("variable", &input.assignee.identifier.name, &input.assignee.span).into(),
|
TypeCheckerError::unknown_sym("variable", &input.assignee.identifier.name, &input.assignee.span).into(),
|
||||||
)
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if var_type.is_some() {
|
||||||
|
self.compare_expr_type(&input.value, var_type, input.value.span());
|
||||||
}
|
}
|
||||||
|
|
||||||
VisitResult::VisitChildren
|
VisitResult::VisitChildren
|
||||||
|
@ -24,6 +24,7 @@ pub struct TypeChecker<'a> {
|
|||||||
pub(crate) symbol_table: &'a mut SymbolTable<'a>,
|
pub(crate) symbol_table: &'a mut SymbolTable<'a>,
|
||||||
pub(crate) handler: &'a Handler,
|
pub(crate) handler: &'a Handler,
|
||||||
pub(crate) parent: Option<Symbol>,
|
pub(crate) parent: Option<Symbol>,
|
||||||
|
pub(crate) negate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ARITHMATIC_TYPES: &[Type] = &[
|
const ARITHMATIC_TYPES: &[Type] = &[
|
||||||
@ -74,6 +75,7 @@ impl<'a> TypeChecker<'a> {
|
|||||||
symbol_table,
|
symbol_table,
|
||||||
handler,
|
handler,
|
||||||
parent: None,
|
parent: None,
|
||||||
|
negate: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,12 @@ create_messages!(
|
|||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For when a type is does not exist.
|
/// For when an integer is not in a valid range.
|
||||||
@formatted
|
@formatted
|
||||||
unknown_type {
|
invalid_int_value {
|
||||||
args: (),
|
args: (value: impl Display, type_: impl Display),
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"The type",
|
"The value {value} is not a valid `{type_}`",
|
||||||
),
|
),
|
||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user