Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some bugs and make core package richer #328

Merged
merged 17 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion compiler/frontend/src/ast_to_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl<'a> Context<'a> {

let (pattern, identifier_ids) = PatternContext::compile(pattern);
let body = self.push(
Some(ast.id.clone()),
None,
Expression::Destructure {
expression: body,
pattern,
Expand All @@ -267,6 +267,13 @@ impl<'a> Context<'a> {
(name, id)
})
.collect_vec();

self.push(
Some(ast.id.clone()),
Expression::Symbol("Nothing".to_string()),
None,
);

(names, body)
}
};
Expand Down
79 changes: 42 additions & 37 deletions compiler/frontend/src/cst_to_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,7 @@ impl LoweringContext {
closing_curly_braces,
} => {
if lowering_type != LoweringType::Expression {
errors.push(
self.create_error(
part,
AstError::PatternContainsInvalidExpression,
),
);
return self.create_ast_for_invalid_expression_in_pattern(cst);
};

if opening_curly_braces.len() != (opening_single_quote_count + 1)
Expand Down Expand Up @@ -612,24 +607,19 @@ impl LoweringContext {
}
CstKind::StructField { .. } => panic!("StructField should only appear in Struct."),
CstKind::StructAccess { struct_, dot, key } => {
let mut errors = vec![];

if lowering_type != LoweringType::Expression {
errors.push(self.create_error(cst, AstError::PatternContainsInvalidExpression));
return self.create_ast_for_invalid_expression_in_pattern(cst);
};

let ast = self.lower_struct_access(cst.id, struct_, dot, key);
self.wrap_in_errors(cst.id, ast, errors)
self.lower_struct_access(cst.id, struct_, dot, key)
}
CstKind::Match {
expression,
percent,
cases,
} => {
let mut errors = vec![];

if lowering_type != LoweringType::Expression {
errors.push(self.create_error(cst, AstError::PatternContainsInvalidExpression));
return self.create_ast_for_invalid_expression_in_pattern(expression);
};

let expression = self.lower_cst(expression, LoweringType::Expression);
Expand All @@ -642,24 +632,21 @@ impl LoweringContext {

let cases = self.lower_csts(cases);

let ast = self.create_ast(
self.create_ast(
cst.id,
AstKind::Match(Match {
expression: Box::new(expression),
cases,
}),
);
self.wrap_in_errors(cst.id, ast, errors)
)
}
CstKind::MatchCase {
pattern,
arrow: _,
body,
} => {
let mut errors = vec![];

if lowering_type != LoweringType::Expression {
errors.push(self.create_error(cst, AstError::PatternContainsInvalidExpression));
return self.create_ast_for_invalid_expression_in_pattern(pattern);
};

let pattern = self.lower_cst(pattern, LoweringType::Pattern);
Expand All @@ -668,14 +655,13 @@ impl LoweringContext {

let body = self.lower_csts(body);

let ast = self.create_ast(
self.create_ast(
cst.id,
AstKind::MatchCase(MatchCase {
pattern: Box::new(pattern),
body,
}),
);
self.wrap_in_errors(cst.id, ast, errors)
)
}
CstKind::OrPattern { left, right } => {
assert_eq!(lowering_type, LoweringType::Pattern);
Expand Down Expand Up @@ -746,8 +732,8 @@ impl LoweringContext {
let mut errors = vec![];

if lowering_type != LoweringType::Expression {
errors.push(self.create_error(cst, AstError::PatternContainsInvalidExpression));
};
return self.create_ast_for_invalid_expression_in_pattern(cst);
}

assert!(
matches!(opening_curly_brace.kind, CstKind::OpeningCurlyBrace),
Expand Down Expand Up @@ -885,24 +871,34 @@ impl LoweringContext {
dot
);

let key = match key.kind.clone() {
match key.kind.clone() {
CstKind::Identifier(identifier) => {
self.create_string(key.id.to_owned(), identifier.uppercase_first_letter())
let key =
self.create_string(key.id.to_owned(), identifier.uppercase_first_letter());
self.create_ast(
id,
AstKind::StructAccess(ast::StructAccess {
struct_: Box::new(struct_),
key,
}),
)
}
// TODO: handle CstKind::Error
CstKind::Error { error, .. } => self.create_ast(
id.to_owned(),
AstKind::Error {
child: None,
errors: vec![CompilerError {
module: self.module.clone(),
span: key.span.clone(),
payload: CompilerErrorPayload::Rcst(error),
}],
},
),
_ => panic!(
"Expected an identifier after the dot in a struct access, but found `{}`.",
key
),
};

self.create_ast(
id,
AstKind::StructAccess(ast::StructAccess {
struct_: Box::new(struct_),
key,
}),
)
}
}

fn lower_parameters(&mut self, csts: &[Cst]) -> (Vec<AstString>, Vec<CompilerError>) {
Expand Down Expand Up @@ -973,4 +969,13 @@ impl LoweringContext {
payload: CompilerErrorPayload::Ast(error),
}
}
fn create_ast_for_invalid_expression_in_pattern(&mut self, cst: &Cst) -> Ast {
self.create_ast(
cst.id,
AstKind::Error {
child: None,
errors: vec![self.create_error(cst, AstError::PatternContainsInvalidExpression)],
},
)
}
}
12 changes: 9 additions & 3 deletions compiler/frontend/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,10 @@ impl Pattern {
.iter()
.any(|(_, value_pattern)| value_pattern.contains_captured_identifiers()),
Pattern::Or(patterns) => patterns.first().unwrap().contains_captured_identifiers(),
Pattern::Error { .. } => false,
Pattern::Error { child, .. } => child
.as_ref()
.map(|child| child.contains_captured_identifiers())
.unwrap_or_default(),
}
}
pub fn captured_identifier_count(&self) -> usize {
Expand All @@ -351,11 +354,14 @@ impl Pattern {
// If the number or captured identifiers isn't the same in both
// sides, the pattern is invalid and the generated code will panic.
Pattern::Or(patterns) => patterns.first().unwrap().captured_identifier_count(),
Pattern::Error { .. } => {
Pattern::Error { child, .. } => {
// Since generated code panics in this case, it doesn't matter
// whether the child captured any identifiers since they can't
// be accessed anyway.
0
child
.as_ref()
.map(|child| child.captured_identifier_count())
.unwrap_or_default()
}
}
}
Expand Down
46 changes: 26 additions & 20 deletions compiler/frontend/src/hir_to_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,14 @@ struct LoweringContext<'a> {
mapping: &'a mut FxHashMap<hir::Id, Id>,
needs_function: Id,
tracing: &'a TracingConfig,
/// The result of the last pattern match and whether it was trivial
/// (i.e., `foo = …`).
last_pattern_result: Option<(Id, bool)>,
ongoing_destructuring: Option<OngoingDestructuring>,
}
#[derive(Clone)]
struct OngoingDestructuring {
result: Id,

/// Assignments such as `foo = …` are considered trivial.
is_trivial: bool,
}

impl<'a> LoweringContext<'a> {
Expand All @@ -183,7 +188,7 @@ impl<'a> LoweringContext<'a> {
mapping: &mut mapping,
needs_function,
tracing,
last_pattern_result: None,
ongoing_destructuring: None,
};
context.compile_expressions(body, module_hir_id, &hir.expressions);

Expand Down Expand Up @@ -236,7 +241,10 @@ impl<'a> LoweringContext<'a> {
if let hir::Pattern::NewIdentifier(_) = pattern {
// The trivial case: `foo = …`.
let result = body.push_reference(expression);
self.last_pattern_result = Some((result, true));
self.ongoing_destructuring = Some(OngoingDestructuring {
result,
is_trivial: true,
});
result
} else {
let pattern_result = PatternLoweringContext::compile_pattern(
Expand All @@ -246,6 +254,10 @@ impl<'a> LoweringContext<'a> {
expression,
pattern,
);
self.ongoing_destructuring = Some(OngoingDestructuring {
result: pattern_result,
is_trivial: false,
});

let nothing = body.push_nothing();
let is_match = body.push_is_match(pattern_result, responsible);
Expand All @@ -266,29 +278,20 @@ impl<'a> LoweringContext<'a> {
body.push_panic(reason, responsible);
},
responsible,
);

if !pattern.contains_captured_identifiers() {
body.push_reference(nothing)
} else {
// The generated expression will be followed by at least one
// identifier reference, so we don't have to generate a
// reference to the result in here.
self.last_pattern_result = Some((pattern_result, false));
pattern_result
}
)
}
}
hir::Expression::PatternIdentifierReference(identifier_id) => {
let (pattern_result, is_trivial) = self.last_pattern_result.unwrap();
let OngoingDestructuring { result, is_trivial } =
self.ongoing_destructuring.clone().unwrap();

if is_trivial {
body.push_reference(pattern_result)
body.push_reference(result)
} else {
let list_get = body.push_builtin(BuiltinFunction::ListGet);
let index = body.push_int((identifier_id.0 + 1).into());
let responsible = body.push_hir_id(hir_id.clone());
body.push_call(list_get, vec![pattern_result, index], responsible)
body.push_call(list_get, vec![result, index], responsible)
}
}
hir::Expression::Match { expression, cases } => {
Expand Down Expand Up @@ -436,7 +439,10 @@ impl<'a> LoweringContext<'a> {

let builtin_if_else = body.push_builtin(BuiltinFunction::IfElse);
let then_lambda = body.push_lambda(|body, _| {
self.last_pattern_result = Some((pattern_result, false));
self.ongoing_destructuring = Some(OngoingDestructuring {
result: pattern_result,
is_trivial: false,
});
self.compile_expressions(body, responsible, &case_body.expressions);
});
let else_lambda = body.push_lambda(|body, _| {
Expand Down
8 changes: 7 additions & 1 deletion compiler/frontend/src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ fn offset_to_position(
module: Module,
mut offset: Offset,
) -> Position {
let text = db.get_module_content_as_string(module.clone()).unwrap();
let Some(text) = db.get_module_content_as_string(module.clone()) else {
assert_eq!(*offset, 0);
return Position {
line: 0,
character: 0,
};
};
if *offset > text.len() {
*offset = text.len();
}
Expand Down
8 changes: 0 additions & 8 deletions old-packages/Core/src/Bool.candy

This file was deleted.

6 changes: 0 additions & 6 deletions old-packages/Core/src/Collections/List/Array.candy
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ use ...LinkedList
use ..

impl[Item] Array[Item] {
public static fun filled(length: Int /* UInt */, item: Item): Array[Item] {
# Creates a new `Array` of the given `length`, where every slot is filled with the same `item`.

This.generate(length, { item })
}

public static builtin fun generate(length: Int, generator: (Int) -> Item): Array[Item]
# Creates a new `Array` of the given `length` where the `generator` is invoked with indices to
# generate items to fill the slots.
Expand Down
16 changes: 0 additions & 16 deletions old-packages/Core/src/ControlFlow.candy

This file was deleted.

3 changes: 0 additions & 3 deletions old-packages/Core/src/Io/Print.candy

This file was deleted.

17 changes: 0 additions & 17 deletions old-packages/Core/src/Maybe.candy

This file was deleted.

Loading