Skip to content

Commit

Permalink
Merge branch 'main' into fixed-decimals
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcelGarus committed Feb 23, 2023
2 parents 809462d + 8ad8d8b commit 5a2983a
Show file tree
Hide file tree
Showing 43 changed files with 326 additions and 717 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion compiler/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ fn raw_build(

let lir = db.lir(module.clone(), tracing.clone()).unwrap();
if debug {
module.dump_associated_debug_file("lir", &format!("{lir}"));
module.dump_associated_debug_file("lir", &format!("{}\n", lir.to_rich_ir()));
}

Some(lir)
Expand Down
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 @@ -451,7 +454,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_for_needs, &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
Loading

1 comment on commit 5a2983a

@jwbot
Copy link
Collaborator

@jwbot jwbot commented on 5a2983a Feb 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiler

Benchmark suite Current: 5a2983a Previous: 8ad8d8b Ratio
Time: Compiler/hello_world 32779832 ns/iter (± 949700) 32101724 ns/iter (± 955340) 1.02
Time: Compiler/fibonacci 957834131 ns/iter (± 9438115) 962495231 ns/iter (± 9307315) 1.00
Time: VM Runtime/hello_world 24183865 ns/iter (± 526906) 25174112 ns/iter (± 479396) 0.96
Time: VM Runtime/fibonacci/15 218324604 ns/iter (± 1578068) 250683122 ns/iter (± 2093043) 0.87

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.