mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 18:52:58 +03:00
Some cleanup
This commit is contained in:
parent
678f8b02a1
commit
af08c4f2e5
@ -117,7 +117,9 @@ impl ParserContext<'_> {
|
|||||||
fn parse_return_statement(&mut self) -> Result<ReturnStatement> {
|
fn parse_return_statement(&mut self) -> Result<ReturnStatement> {
|
||||||
let start = self.expect(&Token::Return)?;
|
let start = self.expect(&Token::Return)?;
|
||||||
let expression = match self.token.token {
|
let expression = match self.token.token {
|
||||||
|
// If the next token is a semicolon, implicitly return a unit expression, `()`.
|
||||||
Token::Semicolon => Expression::Unit(UnitExpression { span: self.token.span }),
|
Token::Semicolon => Expression::Unit(UnitExpression { span: self.token.span }),
|
||||||
|
// Otherwise, attempt to parse an expression.
|
||||||
_ => self.parse_expression()?,
|
_ => self.parse_expression()?,
|
||||||
};
|
};
|
||||||
self.expect(&Token::Semicolon)?;
|
self.expect(&Token::Semicolon)?;
|
||||||
|
@ -318,6 +318,6 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_unit(&mut self, _input: &'a UnitExpression) -> (String, String) {
|
fn visit_unit(&mut self, _input: &'a UnitExpression) -> (String, String) {
|
||||||
unreachable!("`UnitExpression`s should not exist in the AST at this phase of compilation.")
|
unreachable!("`UnitExpression`s should not be visited during code generation.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,4 +712,12 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_unit(&mut self, input: &'a UnitExpression, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||||
|
// Unit expression are only allowed inside a return statement.
|
||||||
|
if !self.is_return {
|
||||||
|
self.emit_err(TypeCheckerError::unit_tuple(input.span()));
|
||||||
|
}
|
||||||
|
Some(Type::Unit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,10 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
|||||||
for Member { identifier, type_ } in input.members.iter() {
|
for Member { identifier, type_ } in input.members.iter() {
|
||||||
// Check that the member type is not a tuple.
|
// Check that the member type is not a tuple.
|
||||||
if matches!(type_, Type::Tuple(_)) {
|
if matches!(type_, Type::Tuple(_)) {
|
||||||
self.emit_err(if input.is_record {
|
self.emit_err(TypeCheckerError::composite_data_type_cannot_contain_tuple(
|
||||||
TypeCheckerError::record_cannot_contain_tuple(identifier.span)
|
if input.is_record { "record" } else { "struct" },
|
||||||
} else {
|
identifier.span,
|
||||||
TypeCheckerError::struct_cannot_contain_tuple(identifier.span)
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// Ensure that there are no record members.
|
// Ensure that there are no record members.
|
||||||
self.assert_member_is_not_record(identifier.span, input.identifier.name, type_);
|
self.assert_member_is_not_record(identifier.span, input.identifier.name, type_);
|
||||||
|
@ -378,6 +378,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
|||||||
false => f.output_type.clone(),
|
false => f.output_type.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set the `has_return` flag.
|
||||||
self.has_return = true;
|
self.has_return = true;
|
||||||
|
|
||||||
// Check that the return expression is not a nested tuple.
|
// Check that the return expression is not a nested tuple.
|
||||||
@ -389,6 +390,11 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the `is_return` flag.
|
||||||
|
self.is_return = true;
|
||||||
|
// Type check the associated expression.
|
||||||
self.visit_expression(&input.expression, return_type);
|
self.visit_expression(&input.expression, return_type);
|
||||||
|
// Unset the `is_return` flag.
|
||||||
|
self.is_return = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@ pub struct TypeChecker<'a> {
|
|||||||
pub(crate) is_finalize: bool,
|
pub(crate) is_finalize: bool,
|
||||||
/// Whether or not we are currently traversing an imported program.
|
/// Whether or not we are currently traversing an imported program.
|
||||||
pub(crate) is_imported: bool,
|
pub(crate) is_imported: bool,
|
||||||
|
/// Whether or not we are currently traversing a return statement.
|
||||||
|
pub(crate) is_return: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const BOOLEAN_TYPE: Type = Type::Boolean;
|
const BOOLEAN_TYPE: Type = Type::Boolean;
|
||||||
@ -98,6 +100,7 @@ impl<'a> TypeChecker<'a> {
|
|||||||
has_finalize: false,
|
has_finalize: false,
|
||||||
is_finalize: false,
|
is_finalize: false,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
|
is_return: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,8 +412,7 @@ fn analyze_source_file(src: &str, source_file_start_pos: BytePos) -> (Vec<BytePo
|
|||||||
let src_bytes = src.as_bytes();
|
let src_bytes = src.as_bytes();
|
||||||
|
|
||||||
while i < src.len() {
|
while i < src.len() {
|
||||||
let i_usize = i;
|
let byte = src_bytes[i];
|
||||||
let byte = src_bytes[i_usize];
|
|
||||||
|
|
||||||
// How much to advance to get to the next UTF-8 char in the string.
|
// How much to advance to get to the next UTF-8 char in the string.
|
||||||
let mut char_len = 1;
|
let mut char_len = 1;
|
||||||
|
@ -479,16 +479,9 @@ create_messages!(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@formatted
|
@formatted
|
||||||
struct_cannot_contain_tuple {
|
composite_data_type_cannot_contain_tuple {
|
||||||
args: (),
|
args: (data_type: impl Display),
|
||||||
msg: format!("A struct cannot contain a tuple."),
|
msg: format!("A {data_type} cannot contain a tuple."),
|
||||||
help: None,
|
|
||||||
}
|
|
||||||
|
|
||||||
@formatted
|
|
||||||
record_cannot_contain_tuple {
|
|
||||||
args: (),
|
|
||||||
msg: format!("A record cannot contain a tuple."),
|
|
||||||
help: None,
|
help: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user