From c49b2f6b024a9cd51f5591f927c6dc47b0381b85 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Sat, 12 Aug 2023 16:06:02 +0200 Subject: [PATCH 01/11] Treat responsibilities like other parameters --- compiler/cli/src/run.rs | 15 ++-- compiler/frontend/src/builtin_functions.rs | 3 +- compiler/frontend/src/hir_to_mir.rs | 86 ++++++++----------- compiler/frontend/src/lir/expression.rs | 15 +--- compiler/frontend/src/mir/body.rs | 20 ++--- compiler/frontend/src/mir/expression.rs | 38 +------- .../common_subtree_elimination.rs | 35 +------- .../src/mir_optimize/constant_folding.rs | 16 ++-- .../frontend/src/mir_optimize/inlining.rs | 3 - compiler/frontend/src/mir_optimize/mod.rs | 11 +-- compiler/frontend/src/mir_optimize/pure.rs | 10 +-- compiler/frontend/src/mir_optimize/utils.rs | 18 +--- .../frontend/src/mir_optimize/validate.rs | 2 - compiler/frontend/src/mir_to_lir.rs | 42 ++------- compiler/fuzzer/src/runner.rs | 5 +- .../src/debug_adapter/session.rs | 9 +- .../src/debug_adapter/tracer.rs | 9 +- .../features_candy/analyzer/static_panics.rs | 12 ++- compiler/vm/src/builtin_functions.rs | 55 ++++-------- compiler/vm/src/heap/object.rs | 4 + compiler/vm/src/instructions.rs | 50 ++++++----- compiler/vm/src/lir.rs | 3 - compiler/vm/src/mir_to_lir.rs | 15 +--- compiler/vm/src/tracer/mod.rs | 2 - compiler/vm/src/tracer/stack_trace.rs | 37 +++----- compiler/vm/src/tracer/tuple.rs | 4 +- compiler/vm/src/vm.rs | 17 +--- 27 files changed, 165 insertions(+), 371 deletions(-) diff --git a/compiler/cli/src/run.rs b/compiler/cli/src/run.rs index c1b81ff70..deb31d955 100644 --- a/compiler/cli/src/run.rs +++ b/compiler/cli/src/run.rs @@ -85,8 +85,8 @@ pub(crate) fn run(options: Options) -> ProgramResult { debug!("Running main function."); // TODO: Add more environment stuff. - let stdout = Handle::new(&mut heap, 1); - let stdin = Handle::new(&mut heap, 0); + let stdout = Handle::new(&mut heap, 2); + let stdin = Handle::new(&mut heap, 1); let environment = Struct::create_with_symbol_keys( &mut heap, true, @@ -98,8 +98,7 @@ pub(crate) fn run(options: Options) -> ProgramResult { lir.clone(), heap, main, - &[environment], - platform, + &[environment, platform.into()], StackTracer::default(), ); @@ -107,7 +106,9 @@ pub(crate) fn run(options: Options) -> ProgramResult { match vm.run_forever() { StateAfterRunForever::CallingHandle(mut call) => { if call.handle == stdout { - let message = call.arguments[0]; + let [message, _responsible] = call.arguments[..] else { + unreachable!() + }; match message.into() { Data::Text(text) => println!("{}", text.get()), @@ -115,6 +116,10 @@ pub(crate) fn run(options: Options) -> ProgramResult { } vm = call.complete(Tag::create_nothing()); } else if call.handle == stdin { + let [_responsible] = call.arguments[..] else { + unreachable!() + }; + print!(">> "); io::stdout().flush().unwrap(); let input = { diff --git a/compiler/frontend/src/builtin_functions.rs b/compiler/frontend/src/builtin_functions.rs index 462dfd438..939a04cc5 100644 --- a/compiler/frontend/src/builtin_functions.rs +++ b/compiler/frontend/src/builtin_functions.rs @@ -111,7 +111,8 @@ impl BuiltinFunction { #[must_use] pub const fn num_parameters(&self) -> usize { - match self { + // Responsibility parameter. + 1 + match self { Self::Equals => 2, Self::FunctionRun => 1, Self::GetArgumentCount => 1, diff --git a/compiler/frontend/src/hir_to_mir.rs b/compiler/frontend/src/hir_to_mir.rs index c219c1522..5a5c997cd 100644 --- a/compiler/frontend/src/hir_to_mir.rs +++ b/compiler/frontend/src/hir_to_mir.rs @@ -94,7 +94,7 @@ fn generate_needs_function(body: &mut BodyBuilder) -> Id { let true_tag = body.push_bool(true); let false_tag = body.push_bool(false); let is_condition_true = - body.push_call(builtin_equals, vec![condition, true_tag], needs_code); + body.push_call(builtin_equals, vec![condition, true_tag, needs_code]); let is_condition_bool = body.push_if_else( &needs_id.child("isConditionTrue"), is_condition_true, @@ -102,7 +102,7 @@ fn generate_needs_function(body: &mut BodyBuilder) -> Id { body.push_reference(true_tag); }, |body| { - body.push_call(builtin_equals, vec![condition, false_tag], needs_code); + body.push_call(builtin_equals, vec![condition, false_tag, needs_code]); }, needs_code, ); @@ -122,12 +122,11 @@ fn generate_needs_function(body: &mut BodyBuilder) -> Id { // Make sure the reason is a text. let builtin_type_of = body.push_builtin(BuiltinFunction::TypeOf); - let type_of_reason = body.push_call(builtin_type_of, vec![reason], responsible_for_call); + let type_of_reason = body.push_call(builtin_type_of, vec![reason, responsible_for_call]); let text_tag = body.push_tag("Text".to_string(), None); let is_reason_text = body.push_call( builtin_equals, - vec![type_of_reason, text_tag], - responsible_for_call, + vec![type_of_reason, text_tag, responsible_for_call], ); body.push_if_else( &needs_id.child("isReasonText"), @@ -270,8 +269,7 @@ impl<'a> LoweringContext<'a> { let one = body.push_int(1.into()); let reason = body.push_call( list_get_function, - vec![pattern_result, one], - responsible, + vec![pattern_result, one, responsible], ); body.push_panic(reason, responsible); @@ -290,7 +288,7 @@ impl<'a> LoweringContext<'a> { 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) + body.push_call(list_get, vec![result, index, responsible]) } } hir::Expression::Match { expression, cases } => { @@ -346,22 +344,21 @@ impl<'a> LoweringContext<'a> { function, arguments, } => { - let responsible = body.push_hir_id(hir_id.clone()); + let call_site = body.push_hir_id(hir_id.clone()); let arguments = arguments .iter() .map(|argument| self.mapping[argument]) + .chain([call_site]) .collect_vec(); if self.tracing.calls.is_enabled() { - let hir_call = body.push_hir_id(hir_id.clone()); body.push(Expression::TraceCallStarts { - hir_call, + hir_call: call_site, function: self.mapping[function], arguments: arguments.clone(), - responsible, }); } - let call = body.push_call(self.mapping[function], arguments, responsible); + let call = body.push_call(self.mapping[function], arguments); if self.tracing.calls.is_enabled() { body.push(Expression::TraceCallEnds { return_value: call }); body.push_reference(call) @@ -389,8 +386,8 @@ impl<'a> LoweringContext<'a> { self.mapping[condition], self.mapping[reason], responsible_for_needs, + responsible, ], - responsible, ) } hir::Expression::Error { errors, .. } => { @@ -474,8 +471,7 @@ impl<'a> LoweringContext<'a> { let one = body.push_int(1.into()); let reason = body.push_call( list_get_function, - vec![pattern_result, one], - responsible_for_match, + vec![pattern_result, one, responsible_for_match], ); no_match_reasons.push(reason); @@ -492,8 +488,12 @@ impl<'a> LoweringContext<'a> { }); body.push_call( builtin_if_else, - vec![is_match, then_function, else_function], - responsible_for_match, + vec![ + is_match, + then_function, + else_function, + responsible_for_match, + ], ) } } @@ -544,18 +544,17 @@ impl PatternLoweringContext { body.push_builtin(BuiltinFunction::TagWithoutValue); let actual_symbol = body.push_call( builtin_tag_without_value, - vec![expression], - self.responsible, + vec![expression, self.responsible], ); let expected_symbol = body.push_tag(symbol.clone(), None); self.compile_equals(body, expected_symbol, actual_symbol, |body| { let builtin_tag_has_value = body.push_builtin(BuiltinFunction::TagHasValue); - let actual_has_value = body.push_call(builtin_tag_has_value, vec![expression], self.responsible); + let actual_has_value = body.push_call(builtin_tag_has_value, vec![expression, self.responsible]); let expected_has_value = body.push_bool(value.is_some()); self.compile_equals(body, expected_has_value, actual_has_value, |body| { if let Some(value) = value { let builtin_tag_get_value = body.push_builtin(BuiltinFunction::TagGetValue); - let actual_value = body.push_call(builtin_tag_get_value, vec![expression], self.responsible); + let actual_value = body.push_call(builtin_tag_get_value, vec![expression, self.responsible]); self.compile(body, actual_value, value); } else { self.push_match(body, vec![]); @@ -567,9 +566,9 @@ impl PatternLoweringContext { ] } else { let builtin_tag_get_value = body.push_builtin(BuiltinFunction::TagGetValue); - let actual_value = body.push_call(builtin_tag_get_value, vec![expression], self.responsible); + let actual_value = body.push_call(builtin_tag_get_value, vec![expression, self.responsible]); let builtin_to_debug_text = body.push_builtin(BuiltinFunction::ToDebugText); - let actual_value_text = body.push_call(builtin_to_debug_text, vec![actual_value], self.responsible); + let actual_value_text = body.push_call(builtin_to_debug_text, vec![actual_value, self.responsible]); vec![ body.push_text("Expected tag to not have a value, but it has one: `".to_string()), actual_value_text, @@ -598,7 +597,7 @@ impl PatternLoweringContext { let expected = body.push_int(list.len().into()); let builtin_list_length = body.push_builtin(BuiltinFunction::ListLength); let actual_length = - body.push_call(builtin_list_length, vec![expression], self.responsible); + body.push_call(builtin_list_length, vec![expression, self.responsible]); self.compile_equals( body, expected, @@ -614,8 +613,7 @@ impl PatternLoweringContext { let index = body.push_int(index.into()); let item = body.push_call( builtin_list_get, - vec![expression, index], - self.responsible, + vec![expression, index, self.responsible], ); let result = self.compile(body, item, item_pattern); (result, item_pattern.captured_identifier_count()) @@ -651,8 +649,7 @@ impl PatternLoweringContext { let key = self.compile_pattern_to_key_expression(body, key_pattern); let has_key = body.push_call( builtin_struct_has_key, - vec![expression, key], - self.responsible, + vec![expression, key, self.responsible,], ); let result = body.push_if_else( @@ -661,8 +658,7 @@ impl PatternLoweringContext { |body| { let value = body.push_call( builtin_struct_get, - vec![expression, key], - self.responsible, + vec![expression, key, self.responsible], ); self.compile(body, value, value_pattern); }, @@ -672,14 +668,12 @@ impl PatternLoweringContext { let key_as_text = body.push_call( to_debug_text, - vec![key], - self.responsible, + vec![key, self.responsible], ); let struct_as_text = body.push_call( to_debug_text, - vec![expression], - self.responsible, + vec![expression, self.responsible], ); let reason_parts = vec![ @@ -736,7 +730,7 @@ impl PatternLoweringContext { let Some(index) = index else { return body.push_reference(nothing); }; let index = body.push_int((1 + index).into()); - body.push_call(list_get_function, vec![result, index], self.responsible) + body.push_call(list_get_function, vec![result, index, self.responsible]) }) .collect(); self.push_match(body, captured_identifiers); @@ -792,7 +786,7 @@ impl PatternLoweringContext { { let expected_type = body.push_tag(expected_type, None); let builtin_type_of = body.push_builtin(BuiltinFunction::TypeOf); - let type_ = body.push_call(builtin_type_of, vec![expression], self.responsible); + let type_ = body.push_call(builtin_type_of, vec![expression, self.responsible]); self.compile_equals( body, expected_type, @@ -823,7 +817,7 @@ impl PatternLoweringContext { E: FnOnce(&mut BodyBuilder, Id, Id) -> Vec, { let builtin_equals = body.push_builtin(BuiltinFunction::Equals); - let equals = body.push_call(builtin_equals, vec![expected, actual], self.responsible); + let equals = body.push_call(builtin_equals, vec![expected, actual, self.responsible]); body.push_if_else( &self.hir_id.child("equals"), @@ -832,8 +826,8 @@ impl PatternLoweringContext { |body| { let to_debug_text = body.push_builtin(BuiltinFunction::ToDebugText); let expected_as_text = - body.push_call(to_debug_text, vec![expected], self.responsible); - let actual_as_text = body.push_call(to_debug_text, vec![actual], self.responsible); + body.push_call(to_debug_text, vec![expected, self.responsible]); + let actual_as_text = body.push_call(to_debug_text, vec![actual, self.responsible]); let reason_parts = reason_factory(body, expected_as_text, actual_as_text); let reason = self.push_text_concatenate(body, reason_parts); self.push_no_match(body, reason); @@ -897,8 +891,7 @@ impl PatternLoweringContext { let index = body.push_int((index + 1).into()); let captured_identifier = body.push_call( list_get_function, - vec![return_value, index], - self.responsible, + vec![return_value, index, self.responsible], ); captured_identifiers.push(captured_identifier); } @@ -920,8 +913,7 @@ impl PatternLoweringContext { .reduce(|left, right| { body.push_call( builtin_text_concatenate, - vec![left, right], - self.responsible, + vec![left, right, self.responsible], ) }) .unwrap() @@ -952,16 +944,14 @@ impl BodyBuilder { let zero = self.push_int(0.into()); let match_or_no_match_tag = self.push_call( list_get_function, - vec![match_or_no_match, zero], - responsible, + vec![match_or_no_match, zero, responsible], ); let equals_function = self.push_builtin(BuiltinFunction::Equals); let match_tag = self.push_match_tag(); self.push_call( equals_function, - vec![match_or_no_match_tag, match_tag], - responsible, + vec![match_or_no_match_tag, match_tag, responsible], ) } diff --git a/compiler/frontend/src/lir/expression.rs b/compiler/frontend/src/lir/expression.rs index 45526ce89..c8d90c13a 100644 --- a/compiler/frontend/src/lir/expression.rs +++ b/compiler/frontend/src/lir/expression.rs @@ -42,7 +42,6 @@ pub enum Expression { Call { function: Id, arguments: Vec, - responsible: Id, }, Panic { @@ -54,7 +53,6 @@ pub enum Expression { hir_call: Id, function: Id, arguments: Vec, - responsible: Id, }, TraceCallEnds { @@ -128,7 +126,6 @@ impl ToRichIr for Expression { Self::Call { function, arguments, - responsible, } => { builder.push("call ", None, EnumSet::empty()); function.build_rich_ir(builder); @@ -138,9 +135,6 @@ impl ToRichIr for Expression { } else { builder.push_children(arguments, " "); } - builder.push(" (", None, EnumSet::empty()); - responsible.build_rich_ir(builder); - builder.push(" is responsible)", None, EnumSet::empty()); } Self::Panic { reason, @@ -148,23 +142,20 @@ impl ToRichIr for Expression { } => { builder.push("panicking because ", None, EnumSet::empty()); reason.build_rich_ir(builder); - builder.push(" (", None, EnumSet::empty()); + builder.push(", ", None, EnumSet::empty()); responsible.build_rich_ir(builder); - builder.push(" is at fault)", None, EnumSet::empty()); + builder.push(" is at fault", None, EnumSet::empty()); } Self::TraceCallStarts { hir_call, function, arguments, - responsible, } => { builder.push("trace: start of call of ", None, EnumSet::empty()); function.build_rich_ir(builder); builder.push(" with ", None, EnumSet::empty()); builder.push_children(arguments, " "); - builder.push(" (", None, EnumSet::empty()); - responsible.build_rich_ir(builder); - builder.push(" is responsible, code is at ", None, EnumSet::empty()); + builder.push(" (code is at ", None, EnumSet::empty()); hir_call.build_rich_ir(builder); builder.push(")", None, EnumSet::empty()); } diff --git a/compiler/frontend/src/mir/body.rs b/compiler/frontend/src/mir/body.rs index 6d162f289..33d89d2e1 100644 --- a/compiler/frontend/src/mir/body.rs +++ b/compiler/frontend/src/mir/body.rs @@ -240,21 +240,16 @@ impl Body { visitor: &mut dyn FnMut(Id, &mut Expression, &VisibleExpressions, bool), ) { if let Expression::Function { - parameters, - responsible_parameter, - body, - .. + parameters, body, .. } = expression { for parameter in &*parameters { visible.insert(*parameter, Expression::Parameter); } - visible.insert(*responsible_parameter, Expression::Parameter); body.visit_with_visible_rec(visible, visitor); for parameter in &*parameters { visible.remove(*parameter); } - visible.remove(*responsible_parameter); } visitor(id, expression, visible, is_returned); @@ -306,8 +301,11 @@ impl FunctionBodyBuilder { let (id_generator, body) = self.body_builder.finish(); let function = Expression::Function { original_hirs: vec![self.hir_id].into_iter().collect(), - parameters: self.parameters, - responsible_parameter: self.responsible_parameter, + parameters: self + .parameters + .into_iter() + .chain([self.responsible_parameter]) + .collect(), body, }; (id_generator, function) @@ -381,11 +379,10 @@ impl BodyBuilder { self.push(function) } - pub fn push_call(&mut self, function: Id, arguments: Vec, responsible: Id) -> Id { + pub fn push_call(&mut self, function: Id, arguments: Vec) -> Id { self.push(Expression::Call { function, arguments, - responsible, }) } pub fn push_if_else( @@ -405,8 +402,7 @@ impl BodyBuilder { let else_function = self.push_function(hir_id.child("else"), |body, _| else_builder(body)); self.push_call( builtin_if_else, - vec![condition, then_function, else_function], - responsible, + vec![condition, then_function, else_function, responsible], ) } diff --git a/compiler/frontend/src/mir/expression.rs b/compiler/frontend/src/mir/expression.rs index b4a4888b3..68f403b5f 100644 --- a/compiler/frontend/src/mir/expression.rs +++ b/compiler/frontend/src/mir/expression.rs @@ -53,7 +53,6 @@ pub enum Expression { Function { original_hirs: FxHashSet, parameters: Vec, - responsible_parameter: Id, body: Body, }, @@ -65,7 +64,6 @@ pub enum Expression { Call { function: Id, arguments: Vec, - responsible: Id, }, UseModule { @@ -86,7 +84,6 @@ pub enum Expression { hir_call: Id, function: Id, arguments: Vec, - responsible: Id, }, TraceCallEnds { @@ -228,7 +225,6 @@ impl Hash for Expression { Self::Function { original_hirs, parameters, - responsible_parameter, body, } => { { @@ -241,18 +237,15 @@ impl Hash for Expression { hash.hash(state); } parameters.hash(state); - responsible_parameter.hash(state); body.hash(state); } Self::Parameter => {} Self::Call { function, arguments, - responsible, } => { function.hash(state); arguments.hash(state); - responsible.hash(state); } Self::UseModule { current_module, @@ -274,12 +267,10 @@ impl Hash for Expression { hir_call, function, arguments, - responsible, } => { hir_call.hash(state); function.hash(state); arguments.hash(state); - responsible.hash(state); } Self::TraceCallEnds { return_value } => return_value.hash(state), Self::TraceExpressionEvaluated { @@ -353,7 +344,6 @@ impl ToRichIr for Expression { // assignment. original_hirs: _, parameters, - responsible_parameter, body, } => { builder.push("{ ", None, EnumSet::empty()); @@ -369,22 +359,9 @@ impl ToRichIr for Expression { }, " ", ); - builder.push( - if parameters.is_empty() { - "(responsible " - } else { - " (+ responsible " - }, - None, - EnumSet::empty(), - ); - let range = builder.push( - responsible_parameter.to_string(), - TokenType::Parameter, - EnumSet::empty(), - ); - builder.push_definition(*responsible_parameter, range); - builder.push(") ->", None, EnumSet::empty()); + if !parameters.is_empty() { + builder.push(" ->", None, EnumSet::empty()); + } builder.push_foldable(|builder| { builder.indent(); builder.push_newline(); @@ -400,7 +377,6 @@ impl ToRichIr for Expression { Self::Call { function, arguments, - responsible, } => { builder.push("call ", None, EnumSet::empty()); function.build_rich_ir(builder); @@ -410,9 +386,6 @@ impl ToRichIr for Expression { } else { builder.push_children(arguments, " "); } - builder.push(" (", None, EnumSet::empty()); - responsible.build_rich_ir(builder); - builder.push(" is responsible)", None, EnumSet::empty()); } Self::UseModule { current_module, @@ -441,15 +414,12 @@ impl ToRichIr for Expression { hir_call, function, arguments, - responsible, } => { builder.push("trace: start of call of ", None, EnumSet::empty()); function.build_rich_ir(builder); builder.push(" with ", None, EnumSet::empty()); builder.push_children(arguments, " "); - builder.push(" (", None, EnumSet::empty()); - responsible.build_rich_ir(builder); - builder.push(" is responsible, code is at ", None, EnumSet::empty()); + builder.push(" (code is at ", None, EnumSet::empty()); hir_call.build_rich_ir(builder); builder.push(")", None, EnumSet::empty()); } diff --git a/compiler/frontend/src/mir_optimize/common_subtree_elimination.rs b/compiler/frontend/src/mir_optimize/common_subtree_elimination.rs index bfb92c183..0431f8eab 100644 --- a/compiler/frontend/src/mir_optimize/common_subtree_elimination.rs +++ b/compiler/frontend/src/mir_optimize/common_subtree_elimination.rs @@ -172,11 +172,10 @@ impl NormalizationState { self.register_defined_id(*id); } } - fn register_function_ids(&mut self, parameters: &[Id], responsible_parameter: Id) { + fn register_function_ids(&mut self, parameters: &[Id]) { for parameter in parameters { self.register_defined_id(*parameter); } - self.register_defined_id(responsible_parameter); } fn register_defined_id(&mut self, id: Id) { let replacement = self.id_generator.generate(); @@ -390,29 +389,21 @@ impl NormalizedComparison for Expression { Self::Function { original_hirs: _, parameters: self_parameters, - responsible_parameter: self_responsible_parameter, body: self_body, }, Self::Function { original_hirs: _, parameters: other_parameters, - responsible_parameter: other_responsible_parameter, body: other_body, }, ) => { - self_normalization - .register_function_ids(self_parameters, *self_responsible_parameter); - other_normalization - .register_function_ids(other_parameters, *other_responsible_parameter); + self_normalization.register_function_ids(self_parameters); + other_normalization.register_function_ids(other_parameters); self_parameters.equals_normalized( self_normalization, other_parameters, other_normalization, - ) && self_responsible_parameter.equals_normalized( - self_normalization, - other_responsible_parameter, - other_normalization, ) && self_body.equals_normalized( self_normalization, other_body, @@ -424,12 +415,10 @@ impl NormalizedComparison for Expression { Self::Call { function: self_function, arguments: self_arguments, - responsible: self_responsible, }, Self::Call { function: other_function, arguments: other_arguments, - responsible: other_responsible, }, ) => { self_function.equals_normalized( @@ -440,10 +429,6 @@ impl NormalizedComparison for Expression { self_normalization, other_arguments, other_normalization, - ) && self_responsible.equals_normalized( - self_normalization, - other_responsible, - other_normalization, ) } ( @@ -494,13 +479,11 @@ impl NormalizedComparison for Expression { hir_call: self_hir_call, function: self_function, arguments: self_arguments, - responsible: self_responsible, }, Self::TraceCallStarts { hir_call: other_hir_call, function: other_function, arguments: other_arguments, - responsible: other_responsible, }, ) => { self_hir_call.equals_normalized( @@ -515,10 +498,6 @@ impl NormalizedComparison for Expression { self_normalization, other_arguments, other_normalization, - ) && self_responsible.equals_normalized( - self_normalization, - other_responsible, - other_normalization, ) } ( @@ -594,24 +573,20 @@ impl NormalizedComparison for Expression { Self::Function { original_hirs: _, parameters, - responsible_parameter, body, } => { - normalization.register_function_ids(parameters, *responsible_parameter); + normalization.register_function_ids(parameters); parameters.hash_normalized(normalization, state); - responsible_parameter.hash_normalized(normalization, state); body.hash_normalized(normalization, state); } Self::Parameter => {} Self::Call { function, arguments, - responsible, } => { function.hash_normalized(normalization, state); arguments.hash_normalized(normalization, state); - responsible.hash_normalized(normalization, state); } Self::UseModule { current_module, @@ -633,12 +608,10 @@ impl NormalizedComparison for Expression { hir_call, function, arguments, - responsible, } => { hir_call.hash_normalized(normalization, state); function.hash_normalized(normalization, state); arguments.hash_normalized(normalization, state); - responsible.hash_normalized(normalization, state); } Self::TraceCallEnds { return_value } => { return_value.hash_normalized(normalization, state); diff --git a/compiler/frontend/src/mir_optimize/constant_folding.rs b/compiler/frontend/src/mir_optimize/constant_folding.rs index 2adbdf520..97306c758 100644 --- a/compiler/frontend/src/mir_optimize/constant_folding.rs +++ b/compiler/frontend/src/mir_optimize/constant_folding.rs @@ -54,7 +54,6 @@ pub fn fold_constants(context: &mut Context, expression: &mut CurrentExpression) let Expression::Call { function, arguments, - responsible, } = &**expression else { return; @@ -69,14 +68,12 @@ pub fn fold_constants(context: &mut Context, expression: &mut CurrentExpression) let Expression::Builtin(builtin) = function else { return; }; - let arguments = arguments.clone(); - let responsible = *responsible; + let Some(result) = run_builtin( &mut *expression, *builtin, &arguments, - responsible, context.visible, context.id_generator, context.pureness, @@ -94,7 +91,6 @@ fn run_builtin( expression: &mut CurrentExpression, builtin: BuiltinFunction, arguments: &[Id], - responsible: Id, visible: &VisibleExpressions, id_generator: &mut IdGenerator, pureness: &PurenessInsights, @@ -104,6 +100,7 @@ fn run_builtin( builtin.num_parameters(), "wrong number of arguments for calling builtin function {builtin:?}", ); + let (&responsible, arguments) = arguments.split_last().unwrap(); let result = match builtin { BuiltinFunction::Equals => { @@ -116,8 +113,7 @@ fn run_builtin( }; Expression::Call { function: *function, - arguments: vec![], - responsible, + arguments: vec![responsible], } } BuiltinFunction::GetArgumentCount => { @@ -127,7 +123,8 @@ fn run_builtin( let Expression::Function { parameters, .. } = visible.get(*function) else { return None; }; - parameters.len().into() + // The responsibility parameter doesn't count. + (parameters.len() - 1).into() } BuiltinFunction::IfElse => { let [condition, then, else_] = arguments else { @@ -136,8 +133,7 @@ fn run_builtin( let condition = visible.get(*condition).try_into().ok()?; Expression::Call { function: if condition { *then } else { *else_ }, - arguments: vec![], - responsible, + arguments: vec![responsible], } } BuiltinFunction::IntAdd => { diff --git a/compiler/frontend/src/mir_optimize/inlining.rs b/compiler/frontend/src/mir_optimize/inlining.rs index 00440a045..212cfcb97 100644 --- a/compiler/frontend/src/mir_optimize/inlining.rs +++ b/compiler/frontend/src/mir_optimize/inlining.rs @@ -77,7 +77,6 @@ impl Context<'_> { let Expression::Call { function, arguments, - responsible: responsible_argument, } = &**expression else { // Expression is not a call. @@ -91,7 +90,6 @@ impl Context<'_> { let Expression::Function { original_hirs: _, parameters, - responsible_parameter, body, } = self.visible.get(*function) else { @@ -107,7 +105,6 @@ impl Context<'_> { .iter() .zip(arguments.iter()) .map(|(parameter, argument)| (*parameter, *argument)) - .chain([(*responsible_parameter, *responsible_argument)]) .chain( body.defined_ids() .into_iter() diff --git a/compiler/frontend/src/mir_optimize/mod.rs b/compiler/frontend/src/mir_optimize/mod.rs index 314867870..768d57cd9 100644 --- a/compiler/frontend/src/mir_optimize/mod.rs +++ b/compiler/frontend/src/mir_optimize/mod.rs @@ -166,26 +166,19 @@ impl Context<'_> { fn optimize_expression(&mut self, expression: &mut CurrentExpression) { 'outer: loop { if let Expression::Function { - parameters, - responsible_parameter, - body, - .. + parameters, body, .. } = &mut **expression { for parameter in &*parameters { self.visible.insert(*parameter, Expression::Parameter); } - self.visible - .insert(*responsible_parameter, Expression::Parameter); - self.pureness - .enter_function(parameters, *responsible_parameter); + self.pureness.enter_function(parameters); self.optimize_body(body); for parameter in &*parameters { self.visible.remove(*parameter); } - self.visible.remove(*responsible_parameter); } loop { diff --git a/compiler/frontend/src/mir_optimize/pure.rs b/compiler/frontend/src/mir_optimize/pure.rs index f2d5b8116..75db26b59 100644 --- a/compiler/frontend/src/mir_optimize/pure.rs +++ b/compiler/frontend/src/mir_optimize/pure.rs @@ -60,20 +60,12 @@ impl PurenessInsights { // TODO: Don't optimize lifted constants again. // Then, we can also add asserts here about not visiting them twice. } - pub(super) fn enter_function(&mut self, parameters: &[Id], responsible_parameter: Id) { + pub(super) fn enter_function(&mut self, parameters: &[Id]) { self.definition_pureness .extend(parameters.iter().map(|id| (*id, true))); - let _existing = self.definition_pureness.insert(responsible_parameter, true); - // TODO: Handle lifted constants properly. - // assert!(existing.is_none()); self.definition_constness .extend(parameters.iter().map(|id| (*id, false))); - let _existing = self - .definition_constness - .insert(responsible_parameter, false); - // TODO: Handle lifted constants properly. - // assert!(existing.is_none()); } pub(super) fn on_normalize_ids(&mut self, mapping: &FxHashMap) { fn update(values: &mut FxHashMap, mapping: &FxHashMap) { diff --git a/compiler/frontend/src/mir_optimize/utils.rs b/compiler/frontend/src/mir_optimize/utils.rs index d408af400..189608bbe 100644 --- a/compiler/frontend/src/mir_optimize/utils.rs +++ b/compiler/frontend/src/mir_optimize/utils.rs @@ -15,14 +15,10 @@ impl Expression { } fn collect_defined_ids(&self, defined: &mut Vec) { if let Self::Function { - parameters, - responsible_parameter, - body, - .. + parameters, body, .. } = self { defined.extend(parameters); - defined.push(*responsible_parameter); body.collect_defined_ids(defined); } } @@ -79,11 +75,9 @@ impl Expression { Self::Call { function, arguments, - responsible, } => { referenced.insert(*function); referenced.extend(arguments); - referenced.insert(*responsible); } Self::UseModule { current_module: _, @@ -104,12 +98,10 @@ impl Expression { hir_call, function, arguments, - responsible, } => { referenced.insert(*hir_call); referenced.insert(*function); referenced.extend(arguments); - referenced.insert(*responsible); } Self::TraceCallEnds { return_value } => { referenced.insert(*return_value); @@ -223,26 +215,22 @@ impl Expression { Self::Function { original_hirs: _, parameters, - responsible_parameter, body, } => { for parameter in parameters { replacer(parameter); } - replacer(responsible_parameter); body.replace_id_references(replacer); } Self::Parameter => {} Self::Call { function, arguments, - responsible, } => { replacer(function); for argument in arguments { replacer(argument); } - replacer(responsible); } Self::UseModule { current_module: _, @@ -263,14 +251,12 @@ impl Expression { hir_call, function, arguments, - responsible, } => { replacer(hir_call); replacer(function); for argument in arguments { replacer(argument); } - replacer(responsible); } Self::TraceCallEnds { return_value } => { replacer(return_value); @@ -308,13 +294,11 @@ impl Expression { Self::Function { original_hirs: _, parameters, - responsible_parameter, body, } => { for parameter in parameters { replacer(parameter); } - replacer(responsible_parameter); body.replace_ids(replacer); } // All other expressions don't define IDs and instead only contain diff --git a/compiler/frontend/src/mir_optimize/validate.rs b/compiler/frontend/src/mir_optimize/validate.rs index e768c38ef..d541dfc44 100644 --- a/compiler/frontend/src/mir_optimize/validate.rs +++ b/compiler/frontend/src/mir_optimize/validate.rs @@ -27,13 +27,11 @@ impl Body { if let Expression::Function { original_hirs: _, parameters, - responsible_parameter, body, } = expression { let mut inner_visible = visible.clone(); inner_visible.extend(parameters.iter().copied()); - inner_visible.insert(*responsible_parameter); body.validate(defined_ids, inner_visible); } diff --git a/compiler/frontend/src/mir_to_lir.rs b/compiler/frontend/src/mir_to_lir.rs index ef7620b6c..dfe0b79c3 100644 --- a/compiler/frontend/src/mir_to_lir.rs +++ b/compiler/frontend/src/mir_to_lir.rs @@ -28,7 +28,6 @@ fn lir(db: &dyn MirToLir, module: Module, tracing: TracingConfig) -> LirResult { FxHashSet::from_iter([hir::Id::new(module, vec![])]), &[], &[], - mir::Id::from_usize(0), &mir.body, ); let lir = Lir::new(context.constants, context.bodies); @@ -52,17 +51,9 @@ impl LoweringContext { original_hirs: FxHashSet, captured: &[mir::Id], parameters: &[mir::Id], - responsible_parameter: mir::Id, body: &mir::Body, ) -> lir::BodyId { - let body = CurrentBody::compile_function( - self, - original_hirs, - captured, - parameters, - responsible_parameter, - body, - ); + let body = CurrentBody::compile_function(self, original_hirs, captured, parameters, body); self.bodies.push(body) } } @@ -82,35 +73,26 @@ impl CurrentBody { original_hirs: FxHashSet, captured: &[mir::Id], parameters: &[mir::Id], - responsible_parameter: mir::Id, body: &mir::Body, ) -> lir::Body { - let mut lir_body = Self::new(captured, parameters, responsible_parameter); + let mut lir_body = Self::new(captured, parameters); for (id, expression) in body.iter() { lir_body.compile_expression(context, id, expression); } lir_body.finish(&context.constant_mapping, original_hirs) } - fn new(captured: &[mir::Id], parameters: &[mir::Id], responsible_parameter: mir::Id) -> Self { + fn new(captured: &[mir::Id], parameters: &[mir::Id]) -> Self { let captured_count = captured.len(); let parameter_count = parameters.len(); let id_mapping: FxHashMap<_, _> = captured .iter() .chain(parameters.iter()) .copied() - .chain([responsible_parameter]) .enumerate() .map(|(index, id)| (id, lir::Id::from_usize(index))) .collect(); - // The responsible parameter is a HIR ID, which is always constant. - // Hence, it never has to be dropped. - let ids_to_drop = id_mapping - .iter() - .filter(|(&k, _)| k != responsible_parameter) - .map(|(_, v)| v) - .copied() - .collect(); + let ids_to_drop = id_mapping.iter().map(|(_, v)| v).copied().collect(); Self { id_mapping, captured_count, @@ -215,7 +197,6 @@ impl CurrentBody { mir::Expression::Function { original_hirs, parameters, - responsible_parameter, body, } => { let captured = expression @@ -225,13 +206,8 @@ impl CurrentBody { .sorted() .collect_vec(); - let body_id = context.compile_function( - original_hirs.clone(), - &captured, - parameters, - *responsible_parameter, - body, - ); + let body_id = + context.compile_function(original_hirs.clone(), &captured, parameters, body); if captured.is_empty() { self.push_constant(context, id, body_id); } else { @@ -245,17 +221,14 @@ impl CurrentBody { mir::Expression::Call { function, arguments, - responsible, } => { let function = self.id_for(context, *function); let arguments = self.ids_for(context, arguments); - let responsible = self.id_for(context, *responsible); self.push( id, lir::Expression::Call { function, arguments, - responsible, }, ); } @@ -287,19 +260,16 @@ impl CurrentBody { hir_call, function, arguments, - responsible, } => { let hir_call = self.id_for(context, *hir_call); let function = self.id_for(context, *function); let arguments = self.ids_for(context, arguments); - let responsible = self.id_for(context, *responsible); self.push( id, lir::Expression::TraceCallStarts { hir_call, function, arguments, - responsible, }, ); } diff --git a/compiler/fuzzer/src/runner.rs b/compiler/fuzzer/src/runner.rs index a4a3d87cd..45bc2b9eb 100644 --- a/compiler/fuzzer/src/runner.rs +++ b/compiler/fuzzer/src/runner.rs @@ -75,17 +75,16 @@ impl + Clone> Runner { .clone_to_heap_with_mapping(&mut heap, &mut mapping) .try_into() .unwrap(); - let arguments = input + let mut arguments = input .arguments .clone_to_heap_with_mapping(&mut heap, &mut mapping); - let responsible = HirId::create(&mut heap, true, Id::fuzzer()); + arguments.push(HirId::create(&mut heap, true, Id::fuzzer()).into()); let vm = Vm::for_function( lir.clone(), heap, function, &arguments, - responsible, StackTracer::default(), ); diff --git a/compiler/language_server/src/debug_adapter/session.rs b/compiler/language_server/src/debug_adapter/session.rs index 4899d3cb5..2a6db87b7 100644 --- a/compiler/language_server/src/debug_adapter/session.rs +++ b/compiler/language_server/src/debug_adapter/session.rs @@ -214,8 +214,13 @@ impl DebugSession { let environment = Struct::create(&mut heap, true, &FxHashMap::default()).into(); let platform = HirId::create(&mut heap, true, Id::platform()); let tracer = DebugTracer::default(); - let vm = - Vm::for_function(Rc::new(lir), heap, main, &[environment], platform, tracer); + let vm = Vm::for_function( + Rc::new(lir), + heap, + main, + &[environment, platform.into()], + tracer, + ); // TODO: remove when we support pause and continue let vm = match vm.run_n_without_handles(10000) { diff --git a/compiler/language_server/src/debug_adapter/tracer.rs b/compiler/language_server/src/debug_adapter/tracer.rs index 52ed38f29..20fce39db 100644 --- a/compiler/language_server/src/debug_adapter/tracer.rs +++ b/compiler/language_server/src/debug_adapter/tracer.rs @@ -42,17 +42,10 @@ impl Tracer for DebugTracer { fn call_started( &mut self, heap: &mut Heap, - call_site: HirId, callee: InlineObject, arguments: Vec, - responsible: HirId, ) { - let call = Call { - call_site, - callee, - arguments, - responsible, - }; + let call = Call { callee, arguments }; call.dup(heap); self.call_stack.push(StackFrame::new(call)); } diff --git a/compiler/language_server/src/features_candy/analyzer/static_panics.rs b/compiler/language_server/src/features_candy/analyzer/static_panics.rs index 429499e83..8444ce114 100644 --- a/compiler/language_server/src/features_candy/analyzer/static_panics.rs +++ b/compiler/language_server/src/features_candy/analyzer/static_panics.rs @@ -50,24 +50,22 @@ impl StaticPanicsOfExpression for Expression { let referenced = self.referenced_ids(); match self { Expression::Function { - parameters, - responsible_parameter, - body, - .. + parameters, body, .. } => { - let is_fuzzable = referenced.contains(responsible_parameter); + parameters + .last() + .map(|responsible| referenced.contains(responsible)) + .unwrap_or(true); for parameter in parameters.iter() { visible.insert(*parameter, Expression::Parameter); } - visible.insert(*responsible_parameter, Expression::Parameter); body.collect_static_panics(visible, panics, is_fuzzable); for parameter in parameters { visible.remove(*parameter); } - visible.remove(*responsible_parameter); } Expression::Panic { reason, diff --git a/compiler/vm/src/builtin_functions.rs b/compiler/vm/src/builtin_functions.rs index 68643e82e..cf42a6610 100644 --- a/compiler/vm/src/builtin_functions.rs +++ b/compiler/vm/src/builtin_functions.rs @@ -4,7 +4,7 @@ use crate::{ SymbolId, SymbolTable, Tag, Text, ToDebugText, }, instructions::InstructionResult, - vm::{CallHandle, MachineState, Panic}, + vm::{MachineState, Panic}, }; use candy_frontend::{ builtin_functions::BuiltinFunction, @@ -15,19 +15,25 @@ use itertools::Itertools; use num_bigint::BigInt; use paste::paste; use std::str::FromStr; -use tracing::{info, span, Level}; +use tracing::info; impl MachineState { pub(super) fn run_builtin_function( &mut self, builtin_function: BuiltinFunction, args: &[InlineObject], - responsible: HirId, symbol_table: &SymbolTable, ) -> InstructionResult { - let result = span!(Level::TRACE, "Running builtin").in_scope(|| match &builtin_function { + let responsible: HirId = (*args.last().unwrap()).try_into().unwrap(); + let args = &args[..args.len() - 1]; + + let result = match &builtin_function { BuiltinFunction::Equals => self.heap.equals(args), - BuiltinFunction::FunctionRun => self.heap.function_run(args, responsible), + BuiltinFunction::FunctionRun => { + let [callee] = args else { unreachable!() }; + self.call(*callee, &[responsible.into()], symbol_table); + return InstructionResult::Done; + } BuiltinFunction::GetArgumentCount => self.heap.get_argument_count(args), BuiltinFunction::IfElse => self.heap.if_else(args, responsible), BuiltinFunction::IntAdd => self.heap.int_add(args), @@ -70,7 +76,7 @@ impl MachineState { BuiltinFunction::TextTrimStart => self.heap.text_trim_start(args), BuiltinFunction::ToDebugText => self.heap.to_debug_text(args, symbol_table), BuiltinFunction::TypeOf => self.heap.type_of(args), - }); + }; match result { Ok(Return(value)) => { @@ -80,8 +86,7 @@ impl MachineState { Ok(DivergeControlFlow { function, responsible, - }) => self.call_function(function, &[], responsible), - Ok(CallHandle(call)) => InstructionResult::CallHandle(call), + }) => self.call_function(function, &[responsible.into()]), Err(reason) => InstructionResult::Panic(Panic { reason, responsible: responsible.get().to_owned(), @@ -97,7 +102,6 @@ enum SuccessfulBehavior { function: Function, responsible: HirId, }, - CallHandle(CallHandle), } impl From for BuiltinResult { @@ -162,36 +166,6 @@ impl Heap { }) } - fn function_run(&mut self, args: &[InlineObject], responsible: HirId) -> BuiltinResult { - unpack!(self, args, |function: Any| { - match **function { - Data::Builtin(_) => { - // TODO: Replace with `unreachable!()` once we have guards - // for argument counts on the Candy side – there are no - // builtins without arguments. - return Err("`✨.functionRun` called with builtin".to_string()); - } - Data::Function(function) => DivergeControlFlow { - function, - responsible, - }, - Data::Handle(handle) => { - if handle.argument_count() != 0 { - return Err( - "`✨.functionRun` expects a function or handle without arguments" - .to_string(), - ); - } - CallHandle(CallHandle { - handle, - arguments: vec![], - responsible, - }) - } - _ => return Err("`✨.functionRun` expects a function or handle".to_string()), - } - }) - } fn get_argument_count(&mut self, args: &[InlineObject]) -> BuiltinResult { unpack_and_later_drop!(self, args, |function: Any| { let count = match **function { @@ -200,7 +174,8 @@ impl Heap { Data::Handle(handle) => handle.argument_count(), _ => return Err("`✨.getArgumentCount` expects a function or handle".to_string()), }; - Return(Int::create(self, true, count).into()) + let count_without_responsibility = count - 1; + Return(Int::create(self, true, count_without_responsibility).into()) }) } diff --git a/compiler/vm/src/heap/object.rs b/compiler/vm/src/heap/object.rs index 65f00f6f4..efa88d8b0 100644 --- a/compiler/vm/src/heap/object.rs +++ b/compiler/vm/src/heap/object.rs @@ -586,6 +586,10 @@ pub struct Handle(InlineHandle); impl Handle { pub fn new(heap: &mut Heap, argument_count: usize) -> Self { + assert!( + argument_count >= 1, + "Each handle needs to accept at least a responsibility parameter." + ); let id = heap.handle_id_generator.generate(); Self::create(heap, id, argument_count) } diff --git a/compiler/vm/src/instructions.rs b/compiler/vm/src/instructions.rs index 94b98d8f7..4f945f682 100644 --- a/compiler/vm/src/instructions.rs +++ b/compiler/vm/src/instructions.rs @@ -118,7 +118,6 @@ impl MachineState { InstructionResult::Done } Instruction::Call { num_args } => { - let responsible = self.pop_from_data_stack().try_into().unwrap(); let mut arguments = (0..*num_args) .map(|_| self.pop_from_data_stack()) .collect_vec(); @@ -126,13 +125,12 @@ impl MachineState { arguments.reverse(); let callee = self.pop_from_data_stack(); - self.call(callee, &arguments, responsible, symbol_table) + self.call(callee, &arguments, symbol_table) } Instruction::TailCall { num_locals_to_pop, num_args, } => { - let responsible = self.pop_from_data_stack().try_into().unwrap(); let mut arguments = (0..*num_args) .map(|_| self.pop_from_data_stack()) .collect_vec(); @@ -146,7 +144,7 @@ impl MachineState { // Tail calling a function is basically just a normal call, but // pretending we are our caller. self.next_instruction = self.call_stack.pop(); - self.call(callee, &arguments, responsible, symbol_table) + self.call(callee, &arguments, symbol_table) } Instruction::Return => { self.next_instruction = self.call_stack.pop(); @@ -171,16 +169,14 @@ impl MachineState { }) } Instruction::TraceCallStarts { num_args } => { - let responsible = self.pop_from_data_stack().try_into().unwrap(); let mut args = vec![]; for _ in 0..*num_args { args.push(self.pop_from_data_stack()); } let callee = self.pop_from_data_stack(); - let call_site = self.pop_from_data_stack().try_into().unwrap(); args.reverse(); - tracer.call_started(&mut self.heap, call_site, callee, args, responsible); + tracer.call_started(&mut self.heap, callee, args); InstructionResult::Done } Instruction::TraceCallEnds => { @@ -212,16 +208,16 @@ impl MachineState { &mut self, callee: InlineObject, arguments: &[InlineObject], - responsible: HirId, symbol_table: &SymbolTable, ) -> InstructionResult { match callee.into() { - Data::Function(function) => self.call_function(function, arguments, responsible), + Data::Function(function) => self.call_function(function, arguments), Data::Builtin(builtin) => { callee.drop(&mut self.heap); - self.run_builtin_function(builtin.get(), arguments, responsible, symbol_table) + self.run_builtin_function(builtin.get(), arguments, symbol_table) } Data::Handle(handle) => { + let responsible: HirId = (*arguments.last().unwrap()).try_into().unwrap(); if arguments.len() != handle.argument_count() { return InstructionResult::Panic(Panic { reason: format!( @@ -233,16 +229,16 @@ impl MachineState { }); } InstructionResult::CallHandle(CallHandle { - handle, - arguments: arguments.to_vec(), - responsible, - }) - }, + handle, + arguments: arguments.to_vec(), + }) + } Data::Tag(tag) => { + let responsible: HirId = (*arguments.last().unwrap()).try_into().unwrap(); if tag.has_value() { return InstructionResult::Panic(Panic { reason: "A tag's value cannot be overwritten by calling it. Use `tag.withValue` instead.".to_string(), - responsible: responsible.get().to_owned(), + responsible: responsible.get().clone(), }); } @@ -257,27 +253,30 @@ impl MachineState { "A tag can only hold exactly one value, but you called it with {} arguments.", arguments.len(), ), - responsible: responsible.get().to_owned(), + responsible: responsible.get().clone(), }) } } - _ => InstructionResult::Panic(Panic { - reason: format!( - "You can only call functions, builtins, tags, and handles, but you tried to call {}.", - DisplayWithSymbolTable::to_string(&callee, symbol_table), - ), - responsible: responsible.get().to_owned(), - }), + _ => { + let responsible: HirId = (*arguments.last().unwrap()).try_into().unwrap(); + InstructionResult::Panic(Panic { + reason: format!( + "You can only call functions, builtins, tags, and handles, but you tried to call {}.", + DisplayWithSymbolTable::to_string(&callee, symbol_table), + ), + responsible: responsible.get().clone(), + }) + } } } pub fn call_function( &mut self, function: Function, arguments: &[InlineObject], - responsible: HirId, ) -> InstructionResult { let expected_num_args = function.argument_count(); if arguments.len() != expected_num_args { + let responsible: HirId = (*arguments.last().unwrap()).try_into().unwrap(); return InstructionResult::Panic(Panic { reason: format!( "A function expected {expected_num_args} parameters, but you called it with {} arguments.", @@ -296,7 +295,6 @@ impl MachineState { } self.data_stack.extend_from_slice(captured); self.data_stack.extend_from_slice(arguments); - self.push_to_data_stack(responsible); self.next_instruction = Some(function.body()); InstructionResult::Done } diff --git a/compiler/vm/src/lir.rs b/compiler/vm/src/lir.rs index ffa182a7a..73dc6ef32 100644 --- a/compiler/vm/src/lir.rs +++ b/compiler/vm/src/lir.rs @@ -155,7 +155,6 @@ impl Instruction { stack.push(top); } Instruction::Call { num_args } => { - stack.pop(); // responsible stack.pop_multiple(*num_args); stack.pop(); // function/builtin stack.push(result); // return value @@ -164,7 +163,6 @@ impl Instruction { num_locals_to_pop, num_args, } => { - stack.pop(); // responsible stack.pop_multiple(*num_args); stack.pop(); // function/builtin stack.pop_multiple(*num_locals_to_pop); @@ -181,7 +179,6 @@ impl Instruction { } Instruction::TraceCallStarts { num_args } => { stack.pop(); // HIR ID - stack.pop(); // responsible stack.pop_multiple(*num_args); stack.pop(); // callee } diff --git a/compiler/vm/src/mir_to_lir.rs b/compiler/vm/src/mir_to_lir.rs index 816a2fb2f..a1bfdbd93 100644 --- a/compiler/vm/src/mir_to_lir.rs +++ b/compiler/vm/src/mir_to_lir.rs @@ -71,7 +71,6 @@ where FxHashSet::from_iter([hir::Id::new(module, vec![])]), &FxHashSet::default(), &[], - Id::from_usize(0), &mir.body, ); module_function.set_body(start); @@ -85,7 +84,6 @@ fn compile_function( original_hirs: FxHashSet, captured: &FxHashSet, parameters: &[Id], - responsible_parameter: Id, body: &Body, ) -> InstructionPointer { let mut context = LoweringContext { @@ -100,14 +98,13 @@ fn compile_function( for parameter in parameters { context.stack.push(*parameter); } - context.stack.push(responsible_parameter); for (id, expression) in body.iter() { context.compile_expression(id, expression); } // Expressions may not push things onto the stack, but to the constant heap // instead. - if *context.stack.last().unwrap() != body.return_value() { + if context.stack.last() != Some(&body.return_value()) { context.emit_reference_to(body.return_value()); } @@ -240,7 +237,6 @@ impl<'c> LoweringContext<'c> { Expression::Function { original_hirs, parameters, - responsible_parameter, body, } => { let captured = expression @@ -255,19 +251,18 @@ impl<'c> LoweringContext<'c> { original_hirs.clone(), &captured, parameters, - *responsible_parameter, body, ); if captured.is_empty() { - let list = Function::create( + let function = Function::create( &mut self.lir.constant_heap, false, &[], parameters.len(), instructions, ); - self.constants.insert(id, list.into()); + self.constants.insert(id, function.into()); } else { for captured in &captured { self.emit_reference_to(*captured); @@ -291,13 +286,11 @@ impl<'c> LoweringContext<'c> { Expression::Call { function, arguments, - responsible, } => { self.emit_reference_to(*function); for argument in arguments { self.emit_reference_to(*argument); } - self.emit_reference_to(*responsible); self.emit( id, Instruction::Call { @@ -327,14 +320,12 @@ impl<'c> LoweringContext<'c> { hir_call, function, arguments, - responsible, } => { self.emit_reference_to(*hir_call); self.emit_reference_to(*function); for argument in arguments { self.emit_reference_to(*argument); } - self.emit_reference_to(*responsible); self.emit( id, Instruction::TraceCallStarts { diff --git a/compiler/vm/src/tracer/mod.rs b/compiler/vm/src/tracer/mod.rs index 2ad22ba94..5f7844b80 100644 --- a/compiler/vm/src/tracer/mod.rs +++ b/compiler/vm/src/tracer/mod.rs @@ -20,10 +20,8 @@ pub trait Tracer { fn call_started( &mut self, _heap: &mut Heap, - _call_site: HirId, _callee: InlineObject, _arguments: Vec, - _responsible: HirId, ) { } fn call_ended(&mut self, _heap: &mut Heap, _return_value: InlineObject) {} diff --git a/compiler/vm/src/tracer/stack_trace.rs b/compiler/vm/src/tracer/stack_trace.rs index 4707aeec8..a1aa3b819 100644 --- a/compiler/vm/src/tracer/stack_trace.rs +++ b/compiler/vm/src/tracer/stack_trace.rs @@ -14,27 +14,21 @@ pub struct StackTracer { #[derive(Clone, Debug)] pub struct Call { - pub call_site: HirId, pub callee: InlineObject, pub arguments: Vec, - pub responsible: HirId, } impl Call { pub fn dup(&self, heap: &mut Heap) { - self.call_site.dup(); self.callee.dup(heap); for argument in &self.arguments { argument.dup(heap); } - self.responsible.dup(); } pub fn drop(&self, heap: &mut Heap) { - self.call_site.drop(heap); self.callee.drop(heap); for argument in &self.arguments { argument.drop(heap); } - self.responsible.drop(heap); } } @@ -42,17 +36,10 @@ impl Tracer for StackTracer { fn call_started( &mut self, heap: &mut Heap, - call_site: HirId, callee: InlineObject, arguments: Vec, - responsible: HirId, ) { - let call = Call { - call_site, - callee, - arguments, - responsible, - }; + let call = Call { callee, arguments }; call.dup(heap); self.call_stack.push(call); } @@ -69,23 +56,27 @@ impl StackTracer { let mut caller_locations_and_calls = vec![]; for Call { - call_site, - callee, - arguments, - .. + callee, arguments, .. } in self.call_stack.iter().rev() { - let hir_id = call_site.get(); - let module = hir_id.module.clone(); + let call_site: HirId = match arguments.last().copied() { + Some(responsible) => responsible.try_into().unwrap(), + None => { + continue; // Call of a module. + } + }; + let call_site = call_site.get().clone(); + + let module = call_site.module.clone(); let cst_id = if module.package.is_tooling() { None } else { - db.hir_to_cst_id(hir_id) + db.hir_to_cst_id(&call_site) }; let cst = cst_id.map(|id| db.find_cst(module.clone(), id)); let span = cst.map(|cst| db.range_to_positions(module.clone(), cst.data.span)); let caller_location_string = format!( - "{hir_id} {}", + "{call_site} {}", span.map(|it| format!( "{}:{} – {}:{}", it.start.line, it.start.character, it.end.line, it.end.character, @@ -96,7 +87,7 @@ impl StackTracer { "{} {}", cst_id .and_then(|id| { - let cst = db.find_cst(hir_id.module.clone(), id); + let cst = db.find_cst(call_site.module.clone(), id); match cst.kind { CstKind::Call { receiver, .. } => extract_receiver_name(&receiver), _ => None, diff --git a/compiler/vm/src/tracer/tuple.rs b/compiler/vm/src/tracer/tuple.rs index 3bc447cfa..90b727b31 100644 --- a/compiler/vm/src/tracer/tuple.rs +++ b/compiler/vm/src/tracer/tuple.rs @@ -16,12 +16,10 @@ impl Tracer for Tuple { fn call_started( &mut self, heap: &mut Heap, - call_site: HirId, callee: InlineObject, arguments: Vec, - responsible: HirId, ) { - for_tuples!( #(Tuple.call_started(heap, call_site, callee, arguments.clone(), responsible);)* ); + for_tuples!( #(Tuple.call_started(heap, callee, arguments.clone());)* ); } fn call_ended(&mut self, heap: &mut Heap, return_value: InlineObject) { for_tuples!( #(Tuple.call_ended(heap, return_value);)* ); diff --git a/compiler/vm/src/vm.rs b/compiler/vm/src/vm.rs index d9cef0e86..d70622ea1 100644 --- a/compiler/vm/src/vm.rs +++ b/compiler/vm/src/vm.rs @@ -1,5 +1,5 @@ use crate::{ - heap::{Function, Handle, Heap, HirId, InlineObject}, + heap::{Function, Handle, Heap, InlineObject}, instruction_pointer::InstructionPointer, instructions::InstructionResult, lir::Lir, @@ -35,7 +35,6 @@ pub(super) struct MachineState { pub struct CallHandle { pub handle: Handle, pub arguments: Vec, - pub responsible: HirId, } #[derive(Clone, Debug)] @@ -54,16 +53,9 @@ where mut heap: Heap, function: Function, arguments: &[InlineObject], - responsible: HirId, mut tracer: T, ) -> Self { - tracer.call_started( - &mut heap, - responsible, - function.into(), - arguments.to_vec(), - responsible, - ); + tracer.call_started(&mut heap, function.into(), arguments.to_vec()); let mut state = MachineState { next_instruction: None, @@ -71,7 +63,7 @@ where call_stack: vec![], heap, }; - state.call_function(function, arguments, responsible); + state.call_function(function, arguments); let inner = Box::new(VmInner { lir, state, tracer }); Self { inner } @@ -79,7 +71,6 @@ where pub fn for_module(lir: L, tracer: T) -> Self { let actual_lir = lir.borrow(); let function = actual_lir.module_function; - let responsible = actual_lir.responsible_module; assert_eq!( function.captured_len(), 0, @@ -90,7 +81,7 @@ where 0, "Function is not a module function because it has arguments.", ); - Self::for_function(lir, Heap::default(), function, &[], responsible, tracer) + Self::for_function(lir, Heap::default(), function, &[], tracer) } pub fn lir(&self) -> &L { From c9c4182ad2c9235264bf59994cbf99b9358fadeb Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Sat, 12 Aug 2023 16:06:26 +0200 Subject: [PATCH 02/11] Do not emit PopMultipleBelowTop(0) instruction --- compiler/vm/src/mir_to_lir.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/vm/src/mir_to_lir.rs b/compiler/vm/src/mir_to_lir.rs index a1bfdbd93..a5ca3d03c 100644 --- a/compiler/vm/src/mir_to_lir.rs +++ b/compiler/vm/src/mir_to_lir.rs @@ -365,6 +365,9 @@ impl<'c> LoweringContext<'c> { } } fn emit(&mut self, id: Id, instruction: Instruction) { + if matches!(instruction, Instruction::PopMultipleBelowTop(0)) { + return; + } instruction.apply_to_stack(&mut self.stack, id); self.instructions.push(instruction); } From d73ed0e051ff8965d2867081f4ebe73288b928fb Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Sat, 12 Aug 2023 16:19:58 +0200 Subject: [PATCH 03/11] Make clippy happy --- compiler/frontend/src/mir_to_lir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/frontend/src/mir_to_lir.rs b/compiler/frontend/src/mir_to_lir.rs index dfe0b79c3..378842842 100644 --- a/compiler/frontend/src/mir_to_lir.rs +++ b/compiler/frontend/src/mir_to_lir.rs @@ -92,7 +92,7 @@ impl CurrentBody { .enumerate() .map(|(index, id)| (id, lir::Id::from_usize(index))) .collect(); - let ids_to_drop = id_mapping.iter().map(|(_, v)| v).copied().collect(); + let ids_to_drop = id_mapping.values().copied().collect(); Self { id_mapping, captured_count, From 78fa5da992a7875c6b6a44d90a078d2ae38769e8 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Sat, 12 Aug 2023 17:14:52 +0200 Subject: [PATCH 04/11] Fix stuff --- compiler/backend_inkwell/src/lib.rs | 4 ---- compiler/cli/src/run.rs | 1 - compiler/frontend/src/mir_optimize/constant_folding.rs | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/backend_inkwell/src/lib.rs b/compiler/backend_inkwell/src/lib.rs index 67a3a4153..0fc5ba97d 100644 --- a/compiler/backend_inkwell/src/lib.rs +++ b/compiler/backend_inkwell/src/lib.rs @@ -521,9 +521,7 @@ impl<'ctx> CodeGen<'ctx> { original_hirs, parameters, body, - responsible_parameter, } => { - self.unrepresented_ids.insert(*responsible_parameter); let name = original_hirs .iter() .sorted() @@ -616,9 +614,7 @@ impl<'ctx> CodeGen<'ctx> { candy_frontend::mir::Expression::Call { function, arguments, - responsible, } => { - self.unrepresented_ids.insert(*responsible); let mut args: Vec<_> = arguments .iter() .map(|arg| self.get_value_with_id(function_ctx, arg).unwrap().into()) diff --git a/compiler/cli/src/run.rs b/compiler/cli/src/run.rs index deb31d955..61f324453 100644 --- a/compiler/cli/src/run.rs +++ b/compiler/cli/src/run.rs @@ -120,7 +120,6 @@ pub(crate) fn run(options: Options) -> ProgramResult { unreachable!() }; - print!(">> "); io::stdout().flush().unwrap(); let input = { let stdin = io::stdin(); diff --git a/compiler/frontend/src/mir_optimize/constant_folding.rs b/compiler/frontend/src/mir_optimize/constant_folding.rs index 97306c758..1d4be20c3 100644 --- a/compiler/frontend/src/mir_optimize/constant_folding.rs +++ b/compiler/frontend/src/mir_optimize/constant_folding.rs @@ -60,7 +60,7 @@ pub fn fold_constants(context: &mut Context, expression: &mut CurrentExpression) }; let function = context.visible.get(*function); - if let Expression::Tag { symbol, value: None } = function && arguments.len() == 1 { + if let Expression::Tag { symbol, value: None } = function && arguments.len() == 2 { **expression = Expression::Tag { symbol: symbol.clone(), value: Some(arguments[0]) }; return; } From 33703b3344273a8fa11a27c86d9616922a5078b1 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Sat, 12 Aug 2023 17:21:34 +0200 Subject: [PATCH 05/11] Fix more stuff --- compiler/vm/fuzz/fuzz_targets/vm.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/vm/fuzz/fuzz_targets/vm.rs b/compiler/vm/fuzz/fuzz_targets/vm.rs index cc8e23a1b..187f3f766 100644 --- a/compiler/vm/fuzz/fuzz_targets/vm.rs +++ b/compiler/vm/fuzz/fuzz_targets/vm.rs @@ -87,8 +87,7 @@ fuzz_target!(|data: &[u8]| { &lir, heap, main, - &[environment.into()], - responsible, + &[environment.into(), responsible.into()], DummyTracer, ) .run_forever_without_handles(); From 20ea4bc3d41981d1a785b2a3d688d3f6f37fcfaf Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Sat, 12 Aug 2023 17:49:11 +0200 Subject: [PATCH 06/11] Fix benchmarks --- compiler/vm/benches/utils.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/vm/benches/utils.rs b/compiler/vm/benches/utils.rs index 0bdf65ce4..52419b452 100644 --- a/compiler/vm/benches/utils.rs +++ b/compiler/vm/benches/utils.rs @@ -112,9 +112,14 @@ pub fn run(lir: impl Borrow) -> (Heap, InlineObject) { // Run the `main` function. let environment = Struct::create(&mut heap, true, &FxHashMap::default()); let responsible = HirId::create(&mut heap, true, hir::Id::user()); - let VmFinished { heap, result, .. } = - Vm::for_function(lir, heap, main, &[environment.into()], responsible, tracer) - .run_forever_without_handles(); + let VmFinished { heap, result, .. } = Vm::for_function( + lir, + heap, + main, + &[environment.into(), responsible.into()], + tracer, + ) + .run_forever_without_handles(); match result { Ok(return_value) => (heap, return_value), Err(panic) => { From 5662465b8a5d459a5023f389de5d8aa0ac5cccd9 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 17 Aug 2023 13:35:34 +0200 Subject: [PATCH 07/11] Optimize needs True again --- compiler/frontend/src/mir_optimize/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/frontend/src/mir_optimize/mod.rs b/compiler/frontend/src/mir_optimize/mod.rs index 768d57cd9..5efb5c6d8 100644 --- a/compiler/frontend/src/mir_optimize/mod.rs +++ b/compiler/frontend/src/mir_optimize/mod.rs @@ -212,7 +212,7 @@ impl Context<'_> { if let Expression::Call { function, arguments, .. } = &**expression && let Expression::Function { original_hirs, .. } = self.visible.get(*function) && original_hirs.contains(&hir::Id::needs()) - && arguments.len() == 3 + && arguments.len() == 4 && let Expression::Tag { symbol, value: None } = self.visible.get(arguments[0]) && symbol == "True" { **expression = Expression::nothing(); From 061a726481e5100b0f2fa87fb93914cdcd8782c0 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 17 Aug 2023 14:22:43 +0200 Subject: [PATCH 08/11] Don't have a responsible parameter in the LIR --- compiler/frontend/src/lir/body.rs | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/compiler/frontend/src/lir/body.rs b/compiler/frontend/src/lir/body.rs index 7edf71d0c..24a41200c 100644 --- a/compiler/frontend/src/lir/body.rs +++ b/compiler/frontend/src/lir/body.rs @@ -73,24 +73,7 @@ impl ToRichIr for Bodies { builder.push_definition(parameter_id, range); } - let responsible_parameter_id = body.responsible_parameter_id(); - builder.push( - if body.parameter_count == 0 { - " (responsible " - } else { - " (+ responsible " - }, - None, - EnumSet::empty(), - ); - let range = builder.push( - responsible_parameter_id.to_string(), - TokenType::Parameter, - EnumSet::empty(), - ); - builder.push_definition(responsible_parameter_id, range); - - builder.push(") =", None, EnumSet::empty()); + builder.push(" =", None, EnumSet::empty()); builder.indent(); builder.push_newline(); @@ -106,7 +89,6 @@ impl ToRichIr for Bodies { /// /// - captured variables /// - parameters -/// - responsible parameter /// - locals #[derive(Clone, Debug, Eq, PartialEq)] pub struct Body { @@ -152,16 +134,12 @@ impl Body { (self.captured_count..self.captured_count + self.parameter_count).map(Id::from_usize) } - fn responsible_parameter_id(&self) -> Id { - Id::from_usize(self.captured_count + self.parameter_count) - } - #[must_use] pub fn expressions(&self) -> &[Expression] { &self.expressions } pub fn ids_and_expressions(&self) -> impl Iterator { - let offset = self.captured_count + self.parameter_count + 1; + let offset = self.captured_count + self.parameter_count; self.expressions .iter() .enumerate() From f1461ce42fdd2d521f9c3732bb81a3f07c704a15 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 17 Aug 2023 14:37:38 +0200 Subject: [PATCH 09/11] Don't drop reponsible parameters because they are const --- compiler/frontend/src/mir_to_lir.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/frontend/src/mir_to_lir.rs b/compiler/frontend/src/mir_to_lir.rs index 378842842..28e31593d 100644 --- a/compiler/frontend/src/mir_to_lir.rs +++ b/compiler/frontend/src/mir_to_lir.rs @@ -92,7 +92,14 @@ impl CurrentBody { .enumerate() .map(|(index, id)| (id, lir::Id::from_usize(index))) .collect(); - let ids_to_drop = id_mapping.values().copied().collect(); + + // Don't drop responsible parameters because they are guaranteed to be + // constant and thereby not reference-counted. + let mut ids_to_drop: FxHashSet = id_mapping.values().copied().collect(); + if let Some(responsible_id) = parameters.last() { + ids_to_drop.remove(&id_mapping[responsible_id]); + } + Self { id_mapping, captured_count, From 80e95606826f88f0f0bfd7fd3333eac7c8aef960 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 17 Aug 2023 14:54:15 +0200 Subject: [PATCH 10/11] Make it so builtins accept responsible parameters --- .../candy_runtime/candy_builtin.c | 34 +++++++++---------- .../candy_runtime/candy_builtin.h | 30 ++++++++-------- .../candy_runtime/candy_runtime.c | 9 +++-- compiler/backend_inkwell/src/lib.rs | 9 +++-- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/compiler/backend_inkwell/candy_runtime/candy_builtin.c b/compiler/backend_inkwell/candy_runtime/candy_builtin.c index 2a3b92154..a4c8ee5aa 100644 --- a/compiler/backend_inkwell/candy_runtime/candy_builtin.c +++ b/compiler/backend_inkwell/candy_runtime/candy_builtin.c @@ -3,7 +3,7 @@ #include #include "candy_runtime.h" -const candy_value_t *candy_builtin_equals(candy_value_t *left, candy_value_t *right) +const candy_value_t *candy_builtin_equals(candy_value_t *left, candy_value_t *right, candy_value_t *responsible) { if (left ->type != right->type) @@ -22,7 +22,7 @@ const candy_value_t *candy_builtin_equals(candy_value_t *left, candy_value_t *ri } } -const candy_value_t *candy_builtin_if_else(candy_value_t *condition, candy_value_t *then, candy_value_t *otherwise) +const candy_value_t *candy_builtin_if_else(candy_value_t *condition, candy_value_t *then, candy_value_t *otherwise, candy_value_t *responsible) { candy_value_t *body = candy_tag_to_bool(condition) ? then : otherwise; candy_function function = (body->value).function.function; @@ -30,17 +30,17 @@ const candy_value_t *candy_builtin_if_else(candy_value_t *condition, candy_value return function(environment); } -candy_value_t *candy_builtin_int_add(candy_value_t *left, candy_value_t *right) +candy_value_t *candy_builtin_int_add(candy_value_t *left, candy_value_t *right, candy_value_t *responsible) { return make_candy_int(left->value.integer + right->value.integer); } -candy_value_t *candy_builtin_int_subtract(candy_value_t *left, candy_value_t *right) +candy_value_t *candy_builtin_int_subtract(candy_value_t *left, candy_value_t *right, candy_value_t *responsible) { return make_candy_int(left->value.integer - right->value.integer); } -candy_value_t *candy_builtin_int_bit_length(candy_value_t *value) +candy_value_t *candy_builtin_int_bit_length(candy_value_t *value, candy_value_t *responsible) { int64_t int_value = value->value.integer; int is_negative = int_value < 0; @@ -57,22 +57,22 @@ candy_value_t *candy_builtin_int_bit_length(candy_value_t *value) return make_candy_int(shifts + is_negative); } -candy_value_t *candy_builtin_int_bitwise_and(candy_value_t *left, candy_value_t *right) +candy_value_t *candy_builtin_int_bitwise_and(candy_value_t *left, candy_value_t *right, candy_value_t *responsible) { return make_candy_int(left->value.integer & right->value.integer); } -candy_value_t *candy_builtin_int_bitwise_or(candy_value_t *left, candy_value_t *right) +candy_value_t *candy_builtin_int_bitwise_or(candy_value_t *left, candy_value_t *right, candy_value_t *responsible) { return make_candy_int(left->value.integer | right->value.integer); } -candy_value_t *candy_builtin_int_bitwise_xor(candy_value_t *left, candy_value_t *right) +candy_value_t *candy_builtin_int_bitwise_xor(candy_value_t *left, candy_value_t *right, candy_value_t *responsible) { return make_candy_int(left->value.integer ^ right->value.integer); } -const candy_value_t *candy_builtin_int_compare_to(candy_value_t *left, candy_value_t *right) +const candy_value_t *candy_builtin_int_compare_to(candy_value_t *left, candy_value_t *right, candy_value_t *responsible) { int64_t left_value = left->value.integer; int64_t right_value = right->value.integer; @@ -90,7 +90,7 @@ const candy_value_t *candy_builtin_int_compare_to(candy_value_t *left, candy_val } } -candy_value_t *candy_builtin_list_length(const candy_value_t *list) +candy_value_t *candy_builtin_list_length(const candy_value_t *list, candy_value_t *responsible) { size_t index = 0; while (list->value.list[index] != NULL) @@ -100,34 +100,34 @@ candy_value_t *candy_builtin_list_length(const candy_value_t *list) return make_candy_int(index); } -const candy_value_t *candy_builtin_print(candy_value_t *value) +const candy_value_t *candy_builtin_print(candy_value_t *value, candy_value_t *responsible) { print_candy_value(value); printf("\n"); return &__internal_nothing; } -candy_value_t *candy_builtin_struct_get(candy_value_t *structure, candy_value_t *key) +candy_value_t *candy_builtin_struct_get(candy_value_t *structure, candy_value_t *key, candy_value_t *responsible) { size_t index = 0; - while (!candy_tag_to_bool(candy_builtin_equals(structure->value.structure.keys[index], key))) + while (!candy_tag_to_bool(candy_builtin_equals(structure->value.structure.keys[index], key, responsible))) { index++; } return structure->value.structure.values[index]; } -candy_value_t *candy_builtin_struct_get_keys(candy_value_t *structure) +candy_value_t *candy_builtin_struct_get_keys(candy_value_t *structure, candy_value_t *responsible) { return make_candy_list(structure->value.structure.keys); } -const candy_value_t *candy_builtin_struct_has_key(candy_value_t *structure, candy_value_t *key) +const candy_value_t *candy_builtin_struct_has_key(candy_value_t *structure, candy_value_t *key, candy_value_t *responsible) { size_t index = 0; while (structure->value.structure.keys[index] != NULL) { - if (candy_tag_to_bool(candy_builtin_equals(structure->value.structure.keys[index], key))) + if (candy_tag_to_bool(candy_builtin_equals(structure->value.structure.keys[index], key, responsible))) { return &__internal_true; } @@ -135,7 +135,7 @@ const candy_value_t *candy_builtin_struct_has_key(candy_value_t *structure, cand return &__internal_false; } -const candy_value_t *candy_builtin_type_of(candy_value_t *value) +const candy_value_t *candy_builtin_type_of(candy_value_t *value, candy_value_t *responsible) { switch (value->type) { diff --git a/compiler/backend_inkwell/candy_runtime/candy_builtin.h b/compiler/backend_inkwell/candy_runtime/candy_builtin.h index 0b6d1a3e0..f5731162f 100644 --- a/compiler/backend_inkwell/candy_runtime/candy_builtin.h +++ b/compiler/backend_inkwell/candy_runtime/candy_builtin.h @@ -1,17 +1,17 @@ #include "candy_runtime.h" -const candy_value_t *candy_builtin_equals(candy_value_t *left, candy_value_t *right); -const candy_value_t *candy_builtin_if_else(candy_value_t *condition, candy_value_t *then, candy_value_t *otherwise); -candy_value_t *candy_builtin_int_add(candy_value_t *left, candy_value_t *right); -candy_value_t *candy_builtin_int_subtract(candy_value_t *left, candy_value_t *right); -candy_value_t *candy_builtin_int_bit_length(candy_value_t *value); -candy_value_t *candy_builtin_int_bitwise_and(candy_value_t *left, candy_value_t *right); -candy_value_t *candy_builtin_int_bitwise_or(candy_value_t *left, candy_value_t *right); -candy_value_t *candy_builtin_int_bitwise_xor(candy_value_t *left, candy_value_t *right); -const candy_value_t *candy_builtin_int_compare_to(candy_value_t *left, candy_value_t *right); -candy_value_t *candy_builtin_list_length(const candy_value_t *list); -const candy_value_t *candy_builtin_print(candy_value_t *value); -candy_value_t *candy_builtin_struct_get(candy_value_t *structure, candy_value_t *key); -candy_value_t *candy_builtin_struct_get_keys(candy_value_t *structure); -const candy_value_t *candy_builtin_struct_has_key(candy_value_t *structure, candy_value_t *key); -const candy_value_t *candy_builtin_type_of(candy_value_t *value); +const candy_value_t *candy_builtin_equals(candy_value_t *left, candy_value_t *right, candy_value_t *responsible); +const candy_value_t *candy_builtin_if_else(candy_value_t *condition, candy_value_t *then, candy_value_t *otherwise, candy_value_t *responsible); +candy_value_t *candy_builtin_int_add(candy_value_t *left, candy_value_t *right, candy_value_t *responsible); +candy_value_t *candy_builtin_int_subtract(candy_value_t *left, candy_value_t *right, candy_value_t *responsible); +candy_value_t *candy_builtin_int_bit_length(candy_value_t *value, candy_value_t *responsible); +candy_value_t *candy_builtin_int_bitwise_and(candy_value_t *left, candy_value_t *right, candy_value_t *responsible); +candy_value_t *candy_builtin_int_bitwise_or(candy_value_t *left, candy_value_t *right, candy_value_t *responsible); +candy_value_t *candy_builtin_int_bitwise_xor(candy_value_t *left, candy_value_t *right, candy_value_t *responsible); +const candy_value_t *candy_builtin_int_compare_to(candy_value_t *left, candy_value_t *right, candy_value_t *responsible); +candy_value_t *candy_builtin_list_length(const candy_value_t *list, candy_value_t *responsible); +const candy_value_t *candy_builtin_print(candy_value_t *value, candy_value_t *responsible); +candy_value_t *candy_builtin_struct_get(candy_value_t *structure, candy_value_t *key, candy_value_t *responsible); +candy_value_t *candy_builtin_struct_get_keys(candy_value_t *structure, candy_value_t *responsible); +const candy_value_t *candy_builtin_struct_has_key(candy_value_t *structure, candy_value_t *key, candy_value_t *responsible); +const candy_value_t *candy_builtin_type_of(candy_value_t *value, candy_value_t *responsible); diff --git a/compiler/backend_inkwell/candy_runtime/candy_runtime.c b/compiler/backend_inkwell/candy_runtime/candy_runtime.c index 28f42158c..ba5643e99 100644 --- a/compiler/backend_inkwell/candy_runtime/candy_runtime.c +++ b/compiler/backend_inkwell/candy_runtime/candy_runtime.c @@ -59,7 +59,9 @@ void print_candy_value(const candy_value_t *value) break; case CANDY_TYPE_LIST: printf("("); - candy_value_t *length = candy_builtin_list_length(value); + // TODO: The responsible parameter is not by builtin_list_length + // anyways, so we just pass anything. + candy_value_t *length = candy_builtin_list_length(value, value); size_t list_length = length->value.integer; free_candy_value(length); size_t index = 0; @@ -183,11 +185,14 @@ void *get_candy_function_environment(candy_value_t *function) return function->value.function.environment; } -void candy_panic(const candy_value_t *reason) +void candy_panic(const candy_value_t *reason, const candy_value_t* responsible) { printf("The program panicked for the following reason: \n"); print_candy_value(reason); printf("\n"); + printf("The code at "); + print_candy_value(responsible); + printf(" is responsible."); exit(-1); } diff --git a/compiler/backend_inkwell/src/lib.rs b/compiler/backend_inkwell/src/lib.rs index 0fc5ba97d..14a1ba879 100644 --- a/compiler/backend_inkwell/src/lib.rs +++ b/compiler/backend_inkwell/src/lib.rs @@ -696,12 +696,17 @@ impl<'ctx> CodeGen<'ctx> { } } candy_frontend::mir::Expression::UseModule { .. } => unreachable!(), - candy_frontend::mir::Expression::Panic { reason, .. } => { + candy_frontend::mir::Expression::Panic { + reason, + responsible, + } => { let panic_fn = self.module.get_function("candy_panic").unwrap(); let reason = self.get_value_with_id(function_ctx, reason).unwrap(); + let responsible = self.get_value_with_id(function_ctx, responsible).unwrap(); - self.builder.build_call(panic_fn, &[reason.into()], ""); + self.builder + .build_call(panic_fn, &[reason.into(), responsible.into()], ""); self.builder.build_unreachable(); } From 992eda2dcdfd6b003c38c5f1bd9ebe7a71a810d5 Mon Sep 17 00:00:00 2001 From: Marcel Garus Date: Thu, 19 Oct 2023 17:13:42 +0200 Subject: [PATCH 11/11] Adjust some code after the merge --- compiler/frontend/src/lir/expression.rs | 4 ---- compiler/frontend/src/lir_optimize.rs | 6 +----- compiler/fuzzer/src/runner.rs | 4 +++- compiler/language_server/src/debug_adapter/tracer.rs | 7 ++++++- compiler/vm/src/environment.rs | 6 +++--- compiler/vm/src/tracer/mod.rs | 1 + compiler/vm/src/tracer/tuple.rs | 3 ++- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/frontend/src/lir/expression.rs b/compiler/frontend/src/lir/expression.rs index c5a9cb4f2..01ec9c186 100644 --- a/compiler/frontend/src/lir/expression.rs +++ b/compiler/frontend/src/lir/expression.rs @@ -111,13 +111,11 @@ impl Expression { Self::Call { function, arguments, - responsible, } => { *function = replacer(*function); for argument in arguments { *argument = replacer(*argument); } - *responsible = replacer(*responsible); } Self::Panic { reason, @@ -130,14 +128,12 @@ impl Expression { hir_call, function, arguments, - responsible, } => { *hir_call = replacer(*hir_call); *function = replacer(*function); for argument in arguments { *argument = replacer(*argument); } - *responsible = replacer(*responsible); } Self::TraceCallEnds { return_value } => { *return_value = replacer(*return_value); diff --git a/compiler/frontend/src/lir_optimize.rs b/compiler/frontend/src/lir_optimize.rs index b213e8e1a..132522b95 100644 --- a/compiler/frontend/src/lir_optimize.rs +++ b/compiler/frontend/src/lir_optimize.rs @@ -38,11 +38,7 @@ impl Body { let mut id_mapping = FxHashMap::default(); let mut reference_count_adjustments = self.get_combined_reference_count_adjustments(); - for id in self - .captured_ids() - .chain(self.parameter_ids()) - .chain([self.responsible_parameter_id()]) - { + for id in self.captured_ids().chain(self.parameter_ids()) { new_body.maybe_dup(&mut reference_count_adjustments, id, &id_mapping); } diff --git a/compiler/fuzzer/src/runner.rs b/compiler/fuzzer/src/runner.rs index 22ec38c8d..68716d09b 100644 --- a/compiler/fuzzer/src/runner.rs +++ b/compiler/fuzzer/src/runner.rs @@ -78,11 +78,13 @@ impl + Clone> Runner { let mut arguments = input .arguments .clone_to_heap_with_mapping(&mut heap, &mut mapping); - arguments.push(HirId::create(&mut heap, true, Id::fuzzer()).into()); + let fuzzer_responsibility = HirId::create(&mut heap, true, Id::fuzzer()); + arguments.push(fuzzer_responsibility.into()); let vm = Vm::for_function( byte_code.clone(), &mut heap, + fuzzer_responsibility, function, &arguments, StackTracer::default(), diff --git a/compiler/language_server/src/debug_adapter/tracer.rs b/compiler/language_server/src/debug_adapter/tracer.rs index 53cfa18d0..aa0e39d4d 100644 --- a/compiler/language_server/src/debug_adapter/tracer.rs +++ b/compiler/language_server/src/debug_adapter/tracer.rs @@ -42,10 +42,15 @@ impl Tracer for DebugTracer { fn call_started( &mut self, heap: &mut Heap, + call_site: HirId, callee: InlineObject, arguments: Vec, ) { - let call = Call { callee, arguments }; + let call = Call { + call_site, + callee, + arguments, + }; call.dup(heap); self.call_stack.push(StackFrame::new(call)); } diff --git a/compiler/vm/src/environment.rs b/compiler/vm/src/environment.rs index d3556459e..330a787bf 100644 --- a/compiler/vm/src/environment.rs +++ b/compiler/vm/src/environment.rs @@ -59,9 +59,9 @@ impl DefaultEnvironment { .map(|it| Text::create(heap, true, it).into()) .collect_vec(); let arguments = List::create(heap, true, arguments.as_slice()); - let get_random_bytes_handle = Handle::new(heap, 1); - let stdin_handle = Handle::new(heap, 0); - let stdout_handle = Handle::new(heap, 1); + let get_random_bytes_handle = Handle::new(heap, 2); + let stdin_handle = Handle::new(heap, 1); + let stdout_handle = Handle::new(heap, 2); let environment_object = Struct::create_with_symbol_keys( heap, true, diff --git a/compiler/vm/src/tracer/mod.rs b/compiler/vm/src/tracer/mod.rs index 5f7844b80..64188ee5e 100644 --- a/compiler/vm/src/tracer/mod.rs +++ b/compiler/vm/src/tracer/mod.rs @@ -20,6 +20,7 @@ pub trait Tracer { fn call_started( &mut self, _heap: &mut Heap, + _call_site: HirId, _callee: InlineObject, _arguments: Vec, ) { diff --git a/compiler/vm/src/tracer/tuple.rs b/compiler/vm/src/tracer/tuple.rs index 90b727b31..c6e5abe8c 100644 --- a/compiler/vm/src/tracer/tuple.rs +++ b/compiler/vm/src/tracer/tuple.rs @@ -16,10 +16,11 @@ impl Tracer for Tuple { fn call_started( &mut self, heap: &mut Heap, + call_site: HirId, callee: InlineObject, arguments: Vec, ) { - for_tuples!( #(Tuple.call_started(heap, callee, arguments.clone());)* ); + for_tuples!( #(Tuple.call_started(heap, call_site, callee, arguments.clone());)* ); } fn call_ended(&mut self, heap: &mut Heap, return_value: InlineObject) { for_tuples!( #(Tuple.call_ended(heap, return_value);)* );