From 5515bc61b576acf9b2a25edba3987bfe2c09fa6e Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Mon, 6 Feb 2023 13:49:15 +0100 Subject: [PATCH 01/15] Fix offset_to_lsp for code modules containing invalid UTF8 --- compiler/src/language_server/utils.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/src/language_server/utils.rs b/compiler/src/language_server/utils.rs index b75d9e828..f097948cf 100644 --- a/compiler/src/language_server/utils.rs +++ b/compiler/src/language_server/utils.rs @@ -125,7 +125,12 @@ pub fn offset_from_lsp_raw(text: &str, line_start_offsets: &[usize], position: P } fn offset_to_lsp(db: &dyn LspPositionConversion, module: Module, mut offset: usize) -> (u32, u32) { - let text = db.get_module_content_as_string(module.clone()).unwrap(); + let Some(text) = db.get_module_content_as_string(module.clone()) else { + // If the parsing failed, the parser only emitted an RCST error node + // saying that the file contains invalid UTF-8. In that case, we can + // just display this error at the beginning of the file. + return (0, 0); + }; if offset > text.len() { offset = text.len(); } From 4a706f814eb2f2a2cb469182d27429e86eef8b1f Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Mon, 6 Feb 2023 13:50:17 +0100 Subject: [PATCH 02/15] Lower invalid AST patterns correctly --- compiler/src/compiler/cst_to_ast.rs | 45 +++++++++++++---------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/compiler/src/compiler/cst_to_ast.rs b/compiler/src/compiler/cst_to_ast.rs index bf9752b14..94172895c 100644 --- a/compiler/src/compiler/cst_to_ast.rs +++ b/compiler/src/compiler/cst_to_ast.rs @@ -202,12 +202,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) @@ -610,24 +605,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); @@ -640,24 +630,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); @@ -666,14 +653,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); @@ -744,8 +730,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), @@ -971,4 +957,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)], + }, + ) + } } From 039e338d5b45ef9edf1cde4ec6822e586c777be9 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 9 Feb 2023 17:07:56 +0100 Subject: [PATCH 03/15] Fix patterns containing identifiers and errors --- compiler/frontend/src/hir.rs | 12 ++++-- compiler/frontend/src/hir_to_mir.rs | 60 +++++++++++++++++++---------- 2 files changed, 49 insertions(+), 23 deletions(-) diff --git a/compiler/frontend/src/hir.rs b/compiler/frontend/src/hir.rs index 260bf09ab..60d13f0b8 100644 --- a/compiler/frontend/src/hir.rs +++ b/compiler/frontend/src/hir.rs @@ -310,7 +310,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 { @@ -327,11 +330,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() } } } diff --git a/compiler/frontend/src/hir_to_mir.rs b/compiler/frontend/src/hir_to_mir.rs index b87998566..1fc265c90 100644 --- a/compiler/frontend/src/hir_to_mir.rs +++ b/compiler/frontend/src/hir_to_mir.rs @@ -155,9 +155,15 @@ struct LoweringContext<'a> { mapping: &'a mut FxHashMap, 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, +} +#[derive(Clone)] +struct OngoingDestructuring { + result: Id, + captured_identifier_count: usize, + + /// Assignments such as `foo = …` are considered trivial. + is_trivial: bool, } impl<'a> LoweringContext<'a> { @@ -182,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); @@ -235,7 +241,11 @@ 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, + captured_identifier_count: 1, + is_trivial: true, + }); result } else { let pattern_result = PatternLoweringContext::compile_pattern( @@ -267,28 +277,34 @@ impl<'a> LoweringContext<'a> { 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 - } + let pattern_result = body.push_reference(pattern_result); + self.ongoing_destructuring = Some(OngoingDestructuring { + result: pattern_result, + captured_identifier_count: pattern.captured_identifier_count(), + is_trivial: false, + }); + pattern_result } } hir::Expression::PatternIdentifierReference(identifier_id) => { - let (pattern_result, is_trivial) = self.last_pattern_result.unwrap(); - - if is_trivial { - body.push_reference(pattern_result) + let OngoingDestructuring { + result, + captured_identifier_count, + is_trivial, + } = self.ongoing_destructuring.clone().unwrap(); + + let mut expression = if is_trivial { + 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) + }; + if identifier_id.0 == captured_identifier_count - 1 { + expression = body.push_nothing(); } + expression } hir::Expression::Match { expression, cases } => { assert!(!cases.is_empty()); @@ -435,7 +451,11 @@ 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, + captured_identifier_count: case_pattern.captured_identifier_count(), + is_trivial: false, + }); self.compile_expressions(body, responsible, &case_body.expressions); }); let else_lambda = body.push_lambda(|body, _| { From 4a25621341aaef0d2a56eae2defda60393181d56 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 9 Feb 2023 17:28:40 +0100 Subject: [PATCH 04/15] Fix offset_to_position for non-UTF-8 code modules --- compiler/frontend/src/position.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/frontend/src/position.rs b/compiler/frontend/src/position.rs index efed33d5a..fd43d9934 100644 --- a/compiler/frontend/src/position.rs +++ b/compiler/frontend/src/position.rs @@ -65,7 +65,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(); } From e96c7a376bb4aff4a544056188ec66a7a3c2e834 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 9 Feb 2023 17:29:03 +0100 Subject: [PATCH 05/15] Use text interpolation in todo --- packages/Core/todo.candy | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/Core/todo.candy b/packages/Core/todo.candy index 5036a7234..824c64c4b 100644 --- a/packages/Core/todo.candy +++ b/packages/Core/todo.candy @@ -4,5 +4,4 @@ todo message := # Always panics with a todo message. needs (text.is message) ## There is no way to call `todo` correctly. - ## TODO: Use text interpolation when available. - needs False (text.concatenate "TODO: " message) + needs False "TODO: {message}" From 6854b8252472dca3a423ff3c35a189af0ce3533e Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 9 Feb 2023 17:30:01 +0100 Subject: [PATCH 06/15] Adjust bullet point prefixes --- packages/Core/function.candy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/Core/function.candy b/packages/Core/function.candy index 157a5f582..2a0b37eb8 100644 --- a/packages/Core/function.candy +++ b/packages/Core/function.candy @@ -33,10 +33,10 @@ doNotRun body := # # These are some of the benefits over commenting code out: # - # * Refactorings, like renaming of functions, also affect the code. - # * Candy doesn't report linter warnings for fields and functions in the outer scope that are + # - Refactorings, like renaming of functions, also affect the code. + # - Candy doesn't report linter warnings for fields and functions in the outer scope that are # only used in the code. - # * Making the code invalid (for example, by deleting needed functions) results in compiler + # - Making the code invalid (for example, by deleting needed functions) results in compiler # errors. needs (is0 body) Nothing From 834622eeb043106d4169bd11f87bbb1711cc241b Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 9 Feb 2023 19:16:44 +0100 Subject: [PATCH 07/15] Fix lowering of patterns --- compiler/frontend/src/ast_to_hir.rs | 9 ++++++++- compiler/frontend/src/hir_to_mir.rs | 17 +++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/compiler/frontend/src/ast_to_hir.rs b/compiler/frontend/src/ast_to_hir.rs index 6bf572f30..f8e641590 100644 --- a/compiler/frontend/src/ast_to_hir.rs +++ b/compiler/frontend/src/ast_to_hir.rs @@ -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, @@ -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) } }; diff --git a/compiler/frontend/src/hir_to_mir.rs b/compiler/frontend/src/hir_to_mir.rs index 1fc265c90..338ff82fb 100644 --- a/compiler/frontend/src/hir_to_mir.rs +++ b/compiler/frontend/src/hir_to_mir.rs @@ -160,7 +160,6 @@ struct LoweringContext<'a> { #[derive(Clone)] struct OngoingDestructuring { result: Id, - captured_identifier_count: usize, /// Assignments such as `foo = …` are considered trivial. is_trivial: bool, @@ -243,7 +242,6 @@ impl<'a> LoweringContext<'a> { let result = body.push_reference(expression); self.ongoing_destructuring = Some(OngoingDestructuring { result, - captured_identifier_count: 1, is_trivial: true, }); result @@ -280,31 +278,23 @@ impl<'a> LoweringContext<'a> { let pattern_result = body.push_reference(pattern_result); self.ongoing_destructuring = Some(OngoingDestructuring { result: pattern_result, - captured_identifier_count: pattern.captured_identifier_count(), is_trivial: false, }); pattern_result } } hir::Expression::PatternIdentifierReference(identifier_id) => { - let OngoingDestructuring { - result, - captured_identifier_count, - is_trivial, - } = self.ongoing_destructuring.clone().unwrap(); + let OngoingDestructuring { result, is_trivial } = + self.ongoing_destructuring.clone().unwrap(); - let mut expression = if is_trivial { + if is_trivial { 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![result, index], responsible) - }; - if identifier_id.0 == captured_identifier_count - 1 { - expression = body.push_nothing(); } - expression } hir::Expression::Match { expression, cases } => { assert!(!cases.is_empty()); @@ -453,7 +443,6 @@ impl<'a> LoweringContext<'a> { let then_lambda = body.push_lambda(|body, _| { self.ongoing_destructuring = Some(OngoingDestructuring { result: pattern_result, - captured_identifier_count: case_pattern.captured_identifier_count(), is_trivial: false, }); self.compile_expressions(body, responsible, &case_body.expressions); From 420f6e9e7941637b69932d64235392d77025d854 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 9 Feb 2023 19:17:13 +0100 Subject: [PATCH 08/15] Add repeat function --- packages/Core/_.candy | 2 +- packages/Core/controlFlow.candy | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/Core/_.candy b/packages/Core/_.candy index 995e2df59..2eab18532 100644 --- a/packages/Core/_.candy +++ b/packages/Core/_.candy @@ -2,7 +2,7 @@ bool := use ".bool" channel := use ".channel" [check] := use ".check" [async, await, parallel] := use ".concurrency" -[if, ifElse, loop, recursive] := use ".controlFlow" +[if, ifElse, loop, recursive, repeat] := use ".controlFlow" [equals] := use ".equality" function := use ".function" int := use ".int" diff --git a/packages/Core/controlFlow.candy b/packages/Core/controlFlow.candy index fd001e063..c4f91f160 100644 --- a/packages/Core/controlFlow.candy +++ b/packages/Core/controlFlow.candy @@ -1,6 +1,7 @@ bool = use "..bool" [equals] = use "..equality" function = use "..function" +[typeOf] = use "..type" ifElse condition then else := needs (bool.is condition) @@ -24,6 +25,7 @@ recursive initialArg body := ## TODO: Support breaking with a value as soon as tags are supported. ## TODO: Support looping with a state. loop body := + # Executes the body infinitely often. needs (function.is0 body) recursive Nothing { recurse arg -> result = function.run body @@ -32,3 +34,14 @@ loop body := "The `body` has to return `Continue` or `Break`." if (result | equals Continue) { recurse Nothing } } + +repeat times body := + needs (typeOf times | equals Int) + needs (times | ✨.intCompareTo 0 | equals Less | bool.not) + needs (function.is0 body) + recursive times { recurse times -> + if (times | ✨.intCompareTo 0 | equals Greater) { + function.run body + recurse (✨.intSubtract times 1) + } + } From a4b8ba66f598b3be9fd5c975a442838a68c27d81 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 9 Feb 2023 19:56:33 +0100 Subject: [PATCH 09/15] Handle struct access with CstError as key --- compiler/frontend/src/cst_to_ast.rs | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/compiler/frontend/src/cst_to_ast.rs b/compiler/frontend/src/cst_to_ast.rs index ab7c18bdf..1c135eaf1 100644 --- a/compiler/frontend/src/cst_to_ast.rs +++ b/compiler/frontend/src/cst_to_ast.rs @@ -864,24 +864,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, Vec) { From df94304f71e64a506641d9c894e7c5568b5b87df Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Fri, 10 Feb 2023 11:10:18 +0100 Subject: [PATCH 10/15] Add mutable --- packages/Core/_.candy | 1 + packages/Core/mutable.candy | 43 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 packages/Core/mutable.candy diff --git a/packages/Core/_.candy b/packages/Core/_.candy index 2eab18532..db324059c 100644 --- a/packages/Core/_.candy +++ b/packages/Core/_.candy @@ -8,6 +8,7 @@ function := use ".function" int := use ".int" iterable := use ".iterable" list := use ".list" +mutable := use ".mutable" [panic] := use ".panic" result := use ".result" struct := use ".struct" diff --git a/packages/Core/mutable.candy b/packages/Core/mutable.candy new file mode 100644 index 000000000..549ad9f77 --- /dev/null +++ b/packages/Core/mutable.candy @@ -0,0 +1,43 @@ +# Sometimes, the most intuitive way to express an algorithm involves mutable +# state. In Candy, most values are immutable – only fibers and channels allow +# changing the state over time. + +## How does this work? The `inScope` function spawns a fiber that keeps track of +## the value. You can request it to get and set the current value. + +channel = use "..channel" +[async, await, parallel] = use "..concurrency" +[recursive] = use "..controlFlow" +function = use "..function" + +inScope initialValue body := + needs (function.is1 body) + parallel { nursery -> + requests = channel.create 1 + nursery | async { + body requests.sendPort + requests.sendPort | channel.send Quit + } + finalValue = nursery | async { + recursive initialValue { recurse value -> + requests.receivePort | channel.receive % + (Get, answerPort) -> + needs (channel.isSendPort answerPort) + answerPort | channel.send value + recurse value + (Set, newValue) -> recurse newValue + Quit -> value + } + } + await finalValue + } + +set mutable newValue := + needs (channel.isSendPort mutable) + mutable | channel.send (Set, newValue) + +get mutable := + needs (channel.isSendPort mutable) + answerChannel = channel.create 1 + mutable | channel.send (Get, answerChannel.sendPort) + channel.receive answerChannel.receivePort From 2f0410d729f70b403c774dd3803115f58b36b17d Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Fri, 10 Feb 2023 11:13:03 +0100 Subject: [PATCH 11/15] Remove unneeded code from the old packages --- old-packages/Core/src/Bool.candy | 8 --- .../Core/src/Collections/List/Array.candy | 6 -- old-packages/Core/src/ControlFlow.candy | 16 ----- old-packages/Core/src/Io/Print.candy | 3 - old-packages/Core/src/Maybe.candy | 17 ----- old-packages/Core/src/Primitives.candy | 68 ------------------- .../Core/src/Ranges/Progressions.candy | 5 -- old-packages/Core/src/Ranges/Ranges.candy | 24 ------- old-packages/Core/src/Result.candy | 10 --- old-packages/core/src/assert.candy | 8 --- old-packages/core/src/collections/array.candy | 53 --------------- old-packages/core/src/maybe.candy | 42 ------------ old-packages/core/src/numbers/int.candy | 17 +---- .../core/src/operators/arithmetic.candy | 41 ----------- .../core/src/operators/comparison.candy | 44 ------------ .../core/src/operators/equality.candy | 21 ------ old-packages/core/src/operators/logical.candy | 23 ------- old-packages/core/src/operators/module.candy | 26 ------- old-packages/core/src/primitives.candy | 56 --------------- old-packages/core/src/reflection.candy | 6 -- old-packages/core/src/result.candy | 27 -------- old-packages/core/src/run.candy | 31 --------- old-packages/core/src/string.candy | 6 -- old-packages/core/src/todo.candy | 12 ---- old-packages/core/src/tuples.candy | 9 --- 25 files changed, 1 insertion(+), 578 deletions(-) delete mode 100644 old-packages/Core/src/Bool.candy delete mode 100644 old-packages/Core/src/ControlFlow.candy delete mode 100644 old-packages/Core/src/Io/Print.candy delete mode 100644 old-packages/Core/src/Maybe.candy delete mode 100644 old-packages/Core/src/Result.candy delete mode 100644 old-packages/core/src/assert.candy delete mode 100644 old-packages/core/src/collections/array.candy delete mode 100644 old-packages/core/src/maybe.candy delete mode 100644 old-packages/core/src/operators/arithmetic.candy delete mode 100644 old-packages/core/src/operators/comparison.candy delete mode 100644 old-packages/core/src/operators/equality.candy delete mode 100644 old-packages/core/src/operators/logical.candy delete mode 100644 old-packages/core/src/operators/module.candy delete mode 100644 old-packages/core/src/primitives.candy delete mode 100644 old-packages/core/src/reflection.candy delete mode 100644 old-packages/core/src/result.candy delete mode 100644 old-packages/core/src/run.candy delete mode 100644 old-packages/core/src/todo.candy delete mode 100644 old-packages/core/src/tuples.candy diff --git a/old-packages/Core/src/Bool.candy b/old-packages/Core/src/Bool.candy deleted file mode 100644 index bfea2b665..000000000 --- a/old-packages/Core/src/Bool.candy +++ /dev/null @@ -1,8 +0,0 @@ -use ..Hash -use ..Int -use ..Maybe -use ..Operators - -impl Bool: Hash { - fun hash[H: Hasher](): H { H.primitive(this.match[Int](true = { 1 }, false = { 0 })) } -} diff --git a/old-packages/Core/src/Collections/List/Array.candy b/old-packages/Core/src/Collections/List/Array.candy index d158d38e7..e434cb603 100644 --- a/old-packages/Core/src/Collections/List/Array.candy +++ b/old-packages/Core/src/Collections/List/Array.candy @@ -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. diff --git a/old-packages/Core/src/ControlFlow.candy b/old-packages/Core/src/ControlFlow.candy deleted file mode 100644 index 05147b70a..000000000 --- a/old-packages/Core/src/ControlFlow.candy +++ /dev/null @@ -1,16 +0,0 @@ -use ..Bool -use ..Int -use ..Maybe -use ..Primitives - -public builtin fun loop(body: () -> Nothing): Never -# Executes the body infinitely often. -## TODO(later, marcelgarus): Implement this in pure Candy once we have tail-call elimination. - -impl Int { - public fun times(body: () -> Nothing) { - # Executes the `body` `this` many times. - - 0.until(this).do({ body() }) - } -} diff --git a/old-packages/Core/src/Io/Print.candy b/old-packages/Core/src/Io/Print.candy deleted file mode 100644 index 7bab47c1c..000000000 --- a/old-packages/Core/src/Io/Print.candy +++ /dev/null @@ -1,3 +0,0 @@ -use ...Primitives - -builtin fun print(object: Any): Nothing diff --git a/old-packages/Core/src/Maybe.candy b/old-packages/Core/src/Maybe.candy deleted file mode 100644 index bd3c12164..000000000 --- a/old-packages/Core/src/Maybe.candy +++ /dev/null @@ -1,17 +0,0 @@ -use ..Bool -use ..Operators -use ..Panic -use ..Primitives - -impl[T] Maybe[T] { - public fun do(body: (T) -> Nothing) { this.map[Nothing](body) } -} - -impl[T: Hash] Maybe[T]: Hash { - fun hash[H: Hasher](): H { - this.match[H]( - some = { H.combine(List[H].of(H.primitive(1), it.hash[H]())) }, - none = { H.primitive(0) } - ) - } -} diff --git a/old-packages/Core/src/Primitives.candy b/old-packages/Core/src/Primitives.candy index 14412bcba..1a77a1999 100644 --- a/old-packages/Core/src/Primitives.candy +++ b/old-packages/Core/src/Primitives.candy @@ -2,34 +2,7 @@ use ..Bool use ..Hash use ..Operators -# This module contains the bread of the type-system-sandwich: -# -# * A top type: `Any` -# * A unit type: `Nothing` -# * A bottom type: `Never` - public trait Any { - # Could be anything, from an `Int8` to a `String` to a raspberry cookie. 🍪 - # - # All types are assignable to `Any`: - # - # * `let hey: Any = 4` - # * `print("Hello!")` (`print` expects `Any`) - - builtin fun as[T](): Maybe[T] - # Returns a `Some(this)` if `this` is of type `T`, otherwise `None()`. - # - # Here are some examples: - # - # * `4.as[Int]() == Some(4)` - # * `"Hello".as[Int]() == None()` - - fun is[T](): Bool { - # Checks if `this` is of type `T`. - - as[T]().isSome() - } - fun toString(): String # Returns `toDisplayString` if this type implements `ToDisplayString`, or `toDebugString` # otherwise. @@ -45,44 +18,3 @@ public trait Any { public trait ToDisplayString { fun toDisplayString(): String } - -public builtin type Nothing -# The default type for expressions that don't have an explicit result. -# -# Has only one instance, `nothing`. Because there's only one instance, instances of this type carry -# no information. -# -# Here are a few examples of expressions that evaluate to `Nothing`: -# -# * assignments like `let a = 5` -# * function calls of functions without an explicit return value like `print("Hello, world!")` -# * the explicit nothing instance: `nothing` - -public fun nothing(): Nothing {} - -impl Nothing: Equals { - fun equals(other: This) { true() } -} -impl Nothing: Hash { - fun hash[H: Hasher](): H { H.primitive(0) } -} - -## Because the `Never` type contains itself, it's impossible to instantiate. -public type Never = Never -# Can never be created. It's still useful to specify that an expression will never return directly. -# -# More specifically, this happens in these cases: -# -# * An expression runs endlessly. -# * An expression aborts the current control flow. -# -# Here are a few examples for expressions that evaluate to `Never`: -# -# * `return 5` -# * `break` -# * `panic("blub")` -# * `loop {}` -# -# There are no instances of `Never`. That's why we can claim that all (zero) instances can be -# converted to all other types loslessly – you can assign `Never` to anything: -# `let a: Int = return 5` works, because the result of `return 5` is never created. diff --git a/old-packages/Core/src/Ranges/Progressions.candy b/old-packages/Core/src/Ranges/Progressions.candy index 69a7e738c..958f31700 100644 --- a/old-packages/Core/src/Ranges/Progressions.candy +++ b/old-packages/Core/src/Ranges/Progressions.candy @@ -39,11 +39,6 @@ impl BoundedIntProgression: Equals { this.start == other.start & this.end == other.end & this.step = other.step } } -impl BoundedIntProgression: Hash { - fun hash[H: Hasher](): H { - H.combine(List[H].of(this.start.hash[H](), this.end.hash[H](), this.step.hash[H]())) - } -} impl BoundedIntProgression: Iterate[Int] { fun iterate(): Maybe[(Int, Iterate[Int])] { (this.end > this.start).then[(Int, Iterate[Int])]({ diff --git a/old-packages/Core/src/Ranges/Ranges.candy b/old-packages/Core/src/Ranges/Ranges.candy index 47cce57c1..f22e55139 100644 --- a/old-packages/Core/src/Ranges/Ranges.candy +++ b/old-packages/Core/src/Ranges/Ranges.candy @@ -26,30 +26,6 @@ public trait Range[T: Compare]: Equals { public type RangeBound[T: Compare] = Included T | Excluded T | Unbounded -impl[T: Compare] RangeBound[T]: Equals { - fun equals(other: This): Bool { - this.match( - included = { value -> - other.match(included = { value == it }, excluded = { false() }, unbounded = { false() }) - }, - excluded = { value -> - other.match(included = { false() }, excluded = { value == it }, unbounded = { false() }) - }, - unbounded = { - other.match(included = { false() }, excluded = { false() }, unbounded = { true() }) - }, - ) - } -} -impl[T: Compare & Hash] RangeBound[T]: Hash { - fun hash[H: Hasher](): H { - this.match( - included = { H.combine(List[H].of(0.hash[H](), it.hash[H]())) }, - excluded = { H.combine(List[H].of(1.hash[H](), it.hash[H]())) }, - unbounded = { 2.hash[H]() }, - ) - } -} ## Inclusive start diff --git a/old-packages/Core/src/Result.candy b/old-packages/Core/src/Result.candy deleted file mode 100644 index d79e9fdcf..000000000 --- a/old-packages/Core/src/Result.candy +++ /dev/null @@ -1,10 +0,0 @@ -use ..Panic - -impl[Success: Hash, ErrorType: Hash] Result[Success, ErrorType]: Hash { - fun hash[H: Hasher](): H { - this.match[H]( - ok = { H.combine(List[H].of(H.primitive(0), it.hash[H]())) }, - error = { H.combine(List[H].of(H.primitive(1), it.hash[H]())) }, - ) - } -} diff --git a/old-packages/core/src/assert.candy b/old-packages/core/src/assert.candy deleted file mode 100644 index e024149d9..000000000 --- a/old-packages/core/src/assert.candy +++ /dev/null @@ -1,8 +0,0 @@ -use ..bool -use ..string - -public builtin fun assert(condition: Bool, message: String = "Assert failed.") -/// Throws an error if the `condition` is `false`. -/// -/// This function is useful for ensuring that your mental model of the state of your program matches -/// its actual state. diff --git a/old-packages/core/src/collections/array.candy b/old-packages/core/src/collections/array.candy deleted file mode 100644 index ca2b74a4c..000000000 --- a/old-packages/core/src/collections/array.candy +++ /dev/null @@ -1,53 +0,0 @@ -use ...numbers -use ..iterable -use ..list - -public builtin class Array { - /// A structure that holds a fixed number of `Item`s. - - public static fun filled(length: Int /* UInt */, item: Item): Array { - /// Creates a new `Array` of the given `length`, where every slot is filled with the same - /// `item`. - - generate(length, { item }) - } - - public static fun generate(length: Int, generator: (Int) => Item): Array - /// Creates a new `Array` of the given `length` where the `generator` is invoked with indizes to - /// generate items to fill the slots. - - public fun length(): Int - - public fun get(index: Int /* UInt */): Item - public fun set(index: Int /* UInt */, item: Item) - - public fun toList(): List { - let list = MutableList.empty() - mut let i = 0 - while i < length() { - list.append(get(i)) - i = i + 1 - } - list - } -} - -// TODO(never, marcelgarus): Make `Array` `Iterable`, this clashes with `Iterable.get`, which should return -// `Maybe`. -// impl Array: Iterable { -// fun iterator(): Iterator { -// ArrayIterator(this, 0) -// } -// } - -// class ArrayIterator { -// let array: Array -// mut let cursor: Int -// } -// impl ArrayIterator: Iterator { -// fun next(): Maybe { -// let item = array.get(0) -// cursor = cursor + 1 -// item -// } -// } diff --git a/old-packages/core/src/maybe.candy b/old-packages/core/src/maybe.candy deleted file mode 100644 index 1d0b8a340..000000000 --- a/old-packages/core/src/maybe.candy +++ /dev/null @@ -1,42 +0,0 @@ -use ..bool -use ..hash -use ..operators -use ..primitives - -public trait Maybe: Equals & Hash { - fun unwrap(): Value - fun orElse(alternative: () => Value): Value - fun map(mapper: (Value) => Out): Maybe { flatMap({ Some(mapper(it)) }) } - fun flatMap(mapper: (Value) => Maybe): Maybe - fun cast(): Maybe { map({ it as Out }) } - fun do(lambda: (Value) => Unit) { map({ lambda(it) }) } - - fun equals(other: This): Bool - fun hash(hasher: Hasher) -} - -public class Some { - let value: Value -} -impl Some: Equals & Hash & Maybe { - fun unwrap(): Value { value } - fun orElse(alternative: () => Value): Value { value } - fun flatMap(mapper: (Value) => Maybe): Maybe { mapper(value) } - - fun equals(other: This): Bool { - if (other is None) { return false } - (value as Equals) == (other.unwrap() as Equals) - } - fun hash(hasher: Hasher) { (value as Hash).hash(hasher) } -} - -// TODO(never, JonasWanke): remove type parameter when multi-impls are supported -public class None -impl None: Equals & Hash & Maybe { - fun unwrap(): Value { throw "Unwrapped `None`." } - fun orElse(alternative: () => Value): Value { alternative() } - fun flatMap(mapper: (Value) => Maybe): Maybe { None() } - - fun equals(other: This): Bool { (other is None) } - fun hash(hasher: Hasher) {} -} diff --git a/old-packages/core/src/numbers/int.candy b/old-packages/core/src/numbers/int.candy index e04fa07dd..082b45e93 100644 --- a/old-packages/core/src/numbers/int.candy +++ b/old-packages/core/src/numbers/int.candy @@ -5,23 +5,8 @@ use ...primitives use ...random use ...string -public builtin class Int { - static fun parse(value: String): Int -} -builtin impl Int: Equals & Comparable -builtin impl Int: Add & Subtract & Negate & Multiply & DivideTruncating & Modulo - impl Int: Hash { fun hash(hasher: Hasher) { hasher.write(this) } -} -impl Int { - fun times(action: (Int) => Unit) { - mut let index = 0 - while index < this { - action(index) - index = index + 1 - } - } -} +} \ No newline at end of file diff --git a/old-packages/core/src/operators/arithmetic.candy b/old-packages/core/src/operators/arithmetic.candy deleted file mode 100644 index 4627b34fc..000000000 --- a/old-packages/core/src/operators/arithmetic.candy +++ /dev/null @@ -1,41 +0,0 @@ -use ...numbers - -// trait BinaryPlus { -// fun plus(other: Other): Result -// } -trait Add { - fun add(other: This): This -} -// impl Add: BinaryPlus { -// fun plus(other: Other): Result { add(other) } -// } - -// trait BinaryMinus { -// fun minus(other: Other): Result -// } -trait Subtract { - fun subtract(other: This): This -} -// impl Subtract: BinaryMinus { -// fun minus(other: Other): Result { subtract(other) } -// } - -// trait PrefixMinus { -// fun prefixMinus(): Result -// } -trait Negate { - fun negate(): This -} -// impl ArithmeticNegate: PrefixMinus { -// fun prefixMinus(): Result { negate() } -// } - -trait Multiply { - fun multiply(other: This): This -} -trait DivideTruncating { - fun divideTruncating(other: This): Int -} -trait Modulo { - fun modulo(other: This): This -} diff --git a/old-packages/core/src/operators/comparison.candy b/old-packages/core/src/operators/comparison.candy deleted file mode 100644 index efad75c8f..000000000 --- a/old-packages/core/src/operators/comparison.candy +++ /dev/null @@ -1,44 +0,0 @@ -use ...bool -use ...numbers -use ..equality - -// trait BinaryLessThan { -// fun lessThan(other: Other): Result -// } -// trait BinaryLessThanOrEqual { -// fun lessThanOrEqual(other: Other): Result -// } - -// trait BinaryGreaterThan { -// fun greaterThan(other: Other): Result -// } -// trait BinaryGreaterThanOrEqual { -// fun greaterThanOrEqual(other: Other): Result -// } - -trait Comparable: Equals { - // : BinaryLessThan - // & BinaryLessThanOrEqual - // & BinaryGreaterThan - // & BinaryGreaterThanOrEqual { - fun compareTo(other: This): Less | Equal | Greater - - fun lessThan(other: This): Bool { compareTo(other) is Less } - fun lessThanOrEqual(other: This): Bool { compareTo(other) is Less | Equal } - fun greaterThan(other: This): Bool { compareTo(other) is Greater } - fun greaterThanOrEqual(other: This): Bool { compareTo(other) is Greater | Equal } - - class Less - class Equal - class Greater -} -// impl Comparable: BinaryLessThan { -// fun lessThan(other: Other): Result { add(other) } -// } - -public fun min(first: T, second: T): T { - if first <= second { first } else { second } -} -public fun max(first: T, second: T): T { - if first >= second { first } else { second } -} diff --git a/old-packages/core/src/operators/equality.candy b/old-packages/core/src/operators/equality.candy deleted file mode 100644 index d6902f7b1..000000000 --- a/old-packages/core/src/operators/equality.candy +++ /dev/null @@ -1,21 +0,0 @@ -use ...bool -use ...primitives - -// trait BinaryEquals { -// fun equalsOperator(other: Other): Result -// } -// trait BinaryNotEquals { -// fun notEqualsOperator(other: Other): Result -// } - -trait Equals /* : BinaryEquals & BinaryNotEquals */ { - fun equals(other: This): Bool - builtin fun equalsAny(other: Any): Bool - - fun notEquals(other: This): Bool { !equals(other) } - fun notEqualsAny(other: Any): Bool { !equalsAny(other) } -} -// impl Equals: BinaryEquals & BinaryNotEquals { -// fun equalsOperator(other: Other): Bool { /* this === other || */ equals(other) } -// fun notEqualsOperator(other: Other): Bool { equalsOperator(other).not() } -// } diff --git a/old-packages/core/src/operators/logical.candy b/old-packages/core/src/operators/logical.candy deleted file mode 100644 index fd369f777..000000000 --- a/old-packages/core/src/operators/logical.candy +++ /dev/null @@ -1,23 +0,0 @@ -use ...bool - -trait And { - fun and(other: This): Bool -} -trait Or { - fun or(other: This): Bool -} - -// trait PrefixExclamation { -// fun exclamation(): Result -// } - -trait Opposite /* : PrefixExclamation */ { - fun opposite(): This -} -// impl Opposite: PrefixExclamation { -// fun exclamation(): This { opposite() } -// } - -trait Implies { - fun implies(other: This): Bool -} diff --git a/old-packages/core/src/operators/module.candy b/old-packages/core/src/operators/module.candy deleted file mode 100644 index e271444bc..000000000 --- a/old-packages/core/src/operators/module.candy +++ /dev/null @@ -1,26 +0,0 @@ -public use .arithmetic -public use .comparison -public use .equality -public use .logical - -/* -trait PostfixIndexGet { - fun postfixIndexGet(index: Index): Result -} -trait GetOperator { - fun get(index: Index): Result -} -impl GetOperator: PostfixIndexGet { - fun postfixIndexGet(index: Index): Result { get(index) } -} - -trait PostfixIndexSet { - fun postfixIndexSet(index: Index, value: Value): Result -} -trait SetOperator { - fun set(index: Index, value: Value): Result -} -impl SetOperator: PostfixIndexSet { - fun postfixIndexSet(index: Index, value: Value): Result { set(index,value) } -} -*/ diff --git a/old-packages/core/src/primitives.candy b/old-packages/core/src/primitives.candy deleted file mode 100644 index 11192d61a..000000000 --- a/old-packages/core/src/primitives.candy +++ /dev/null @@ -1,56 +0,0 @@ -use ..bool -use ..hash -use ..operators -use ..string - -public builtin trait Any { - /// Could be anything, from an `Int8` to a `String` to a raspberry cookie. 🍪 - /// - /// All types are assignable to `Any`. - - builtin fun toString(): String -} - -// builtin impl Any: ToString - -// public builtin trait ToString { -// fun toString(): String -// } - -public builtin class Unit -/// The default type for expressions that don't have an explicit result. -/// -/// Has only one instance, `unit`. Because there's only one instance, instances of this type carry -/// no information. -/// -/// Here are a few examples of expressions that evaluate to `Unit`: -/// -/// * assignments like `let a = 5` -/// * function calls of functions without an explicit return value like `print("Hello, world!")` -/// * the explicit unit instance: `unit` - -public let unit: Unit = unitReturningFunction() -fun unitReturningFunction(): Unit {} - -impl Unit: Equals & Hash { - fun equals(other: This): Bool { true } - fun hash(hasher: Hasher) {} -} - -public builtin class Never -/// Can never be created. It's still useful to specify that an expression will never return -/// directly. More specifically, this is the case in the following cases: -/// -/// * An expression runs endlessly. -/// * An expression aborts the current control flow. -/// -/// Here are a few examples for expressions that evaluate to `Never`: -/// -/// * `return 5` -/// * `break` -/// * `throw "blub"` -/// * `loop {}` -/// -/// There are no instances of `Never`. That's why we can claim that all (zero) instances can be -/// converted to all other types loslessly – you can assign `Never` to anything: -/// `let a: Int = return 5` works, because the result of `return 5` is never created. diff --git a/old-packages/core/src/reflection.candy b/old-packages/core/src/reflection.candy deleted file mode 100644 index be3d4a3dc..000000000 --- a/old-packages/core/src/reflection.candy +++ /dev/null @@ -1,6 +0,0 @@ -// trait Declaration - -// builtin class ModuleDeclaration -// builtin impl ModuleDeclaration: Declaration - -class Type diff --git a/old-packages/core/src/result.candy b/old-packages/core/src/result.candy deleted file mode 100644 index b295d6e82..000000000 --- a/old-packages/core/src/result.candy +++ /dev/null @@ -1,27 +0,0 @@ -public trait Result { - /// The result of an operation that might fail. - /// - /// The following cases exist: - /// * In the success case, an `Ok` is returned, containing the returned value. - /// * In the error case, an `Error` is returned, containing an error describing what went wrong. - - fun unwrap(): Success -} - -public class Ok { - /// The result of an operation that succeeded. - - public let value: Success -} -impl Ok: Result { - fun unwrap(): Success { value } -} - -public class Error { - /// The result of an operation that failed. - - public let error: ErrorType -} -impl Error: Result { - fun unwrap(): Success { throw "Unwrapped `Error`: {error}." } -} diff --git a/old-packages/core/src/run.candy b/old-packages/core/src/run.candy deleted file mode 100644 index 40d13cff4..000000000 --- a/old-packages/core/src/run.candy +++ /dev/null @@ -1,31 +0,0 @@ -use ..primitives - -public fun run(code: () => T): T { - /// A function that runs the given lambda with no arguments. - /// - /// Calling this function is the same like calling the `code` by adding parenthesis at the end, - /// but it looks nicer: - /// - /// ``` - /// let a = run { - /// // Some code that can create local variables without cluttering the surrounding namespace. - /// } - /// ``` - - code() -} - -public fun doNotRun(code: () => Unit) { - /// A function that doesn't run the given lambda. - /// - /// This function is useful during development to mark `code` that's not ready to run yet. In - /// contrast to commenting out the `code`, the `code` is still part of the analyzed program. - /// - /// This has the following effects: - /// - /// * Refactorings, like renaming of classes, also affect the `code`. - /// * Candy stops reporting linter warnings for fields and functions in the outer scope that are - /// only used in the `code`. - /// * Making the `code` invalid (for example, by deleting needed classes, functions, or - /// properties) results in compiler errors. -} diff --git a/old-packages/core/src/string.candy b/old-packages/core/src/string.candy index 6d7e866c0..d16150b51 100644 --- a/old-packages/core/src/string.candy +++ b/old-packages/core/src/string.candy @@ -5,15 +5,9 @@ use ..numbers use ..operators public builtin class String { - builtin fun characters(): Iterable builtin fun substring(offset: Int, length: Int): String - builtin fun isEmpty(): Bool - builtin fun isNotEmpty(): Bool - builtin fun length(): Int - builtin fun split(pattern: String): List - builtin fun trimmed(): String } builtin impl String: Equals & Comparable impl String: Hash { diff --git a/old-packages/core/src/todo.candy b/old-packages/core/src/todo.candy deleted file mode 100644 index 979991731..000000000 --- a/old-packages/core/src/todo.candy +++ /dev/null @@ -1,12 +0,0 @@ -use ..primitives -use ..string - -public fun todo(message: String = "Not implemented"): Never { - /// Always throws a `TodoError`. - - throw TodoError(message) -} - -public class TodoError { - let message: String -} diff --git a/old-packages/core/src/tuples.candy b/old-packages/core/src/tuples.candy deleted file mode 100644 index fa0ae433e..000000000 --- a/old-packages/core/src/tuples.candy +++ /dev/null @@ -1,9 +0,0 @@ -/// Tuples are types that can hold multiple other types. -/// They're kind of like a class, but without a name and without giving the fields names. -/// -/// There is nothing to see here, because tuples are actually built into the compiler. -/// Just use parenthesis to create them on-the-fly: -/// -/// ``` -/// let a: (String, Int) = ("foo", 42)` -/// ```` From 8f46458e4e9bb4a198f5ef55e1974bc994588f91 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Fri, 10 Feb 2023 11:13:38 +0100 Subject: [PATCH 12/15] Add comment from old packages --- packages/Core/list.candy | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/Core/list.candy b/packages/Core/list.candy index 1c9843cdb..c27e8f100 100644 --- a/packages/Core/list.candy +++ b/packages/Core/list.candy @@ -7,6 +7,7 @@ result = use "..result" type = use "..type" filled length item := + # Creates a new list of the given length, where each slot is filled with the same item. needs (int.is length) needs (int.isNonNegative length) needs (int.fitsInRustU32 length) From ee5f5f6b8153fe9d22b7b9b212ea94722ed1181c Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Wed, 22 Feb 2023 17:03:43 +0100 Subject: [PATCH 13/15] Simplify code in mutable --- packages/Core/mutable.candy | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/Core/mutable.candy b/packages/Core/mutable.candy index 549ad9f77..c5eafffc4 100644 --- a/packages/Core/mutable.candy +++ b/packages/Core/mutable.candy @@ -18,18 +18,15 @@ inScope initialValue body := body requests.sendPort requests.sendPort | channel.send Quit } - finalValue = nursery | async { - recursive initialValue { recurse value -> - requests.receivePort | channel.receive % - (Get, answerPort) -> - needs (channel.isSendPort answerPort) - answerPort | channel.send value - recurse value - (Set, newValue) -> recurse newValue - Quit -> value - } + recursive initialValue { recurse value -> + requests.receivePort | channel.receive % + (Get, answerPort) -> + needs (channel.isSendPort answerPort) + answerPort | channel.send value + recurse value + (Set, newValue) -> recurse newValue + Quit -> value } - await finalValue } set mutable newValue := From b1db8daa7aba3d30147519310091c8da71b4c83f Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Wed, 22 Feb 2023 17:06:40 +0100 Subject: [PATCH 14/15] Simplify hir_to_mir --- compiler/frontend/src/hir_to_mir.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/frontend/src/hir_to_mir.rs b/compiler/frontend/src/hir_to_mir.rs index 338ff82fb..83c6e5408 100644 --- a/compiler/frontend/src/hir_to_mir.rs +++ b/compiler/frontend/src/hir_to_mir.rs @@ -275,12 +275,11 @@ impl<'a> LoweringContext<'a> { responsible, ); - let pattern_result = body.push_reference(pattern_result); self.ongoing_destructuring = Some(OngoingDestructuring { result: pattern_result, is_trivial: false, }); - pattern_result + body.push_nothing() } } hir::Expression::PatternIdentifierReference(identifier_id) => { From 304bd160eed22e07a079223faa866304499bae52 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 23 Feb 2023 15:24:26 +0100 Subject: [PATCH 15/15] Simplify code --- compiler/frontend/src/hir_to_mir.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/frontend/src/hir_to_mir.rs b/compiler/frontend/src/hir_to_mir.rs index 174a721a4..41e358f5a 100644 --- a/compiler/frontend/src/hir_to_mir.rs +++ b/compiler/frontend/src/hir_to_mir.rs @@ -254,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); @@ -274,13 +278,7 @@ impl<'a> LoweringContext<'a> { body.push_panic(reason, responsible); }, responsible, - ); - - self.ongoing_destructuring = Some(OngoingDestructuring { - result: pattern_result, - is_trivial: false, - }); - body.push_nothing() + ) } } hir::Expression::PatternIdentifierReference(identifier_id) => {