diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-04-18 20:47:47 +1200 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-04-18 20:47:59 +1200 |
commit | 75018f1ec69162a0695e603030f5e1a5cc105af0 (patch) | |
tree | 0ea32433b9f548644b5789cbce910f99956617f0 /src/stages/intermediate.rs | |
parent | e0595e64cc1fa3c9b01a73ed9c67487e40dc54f9 (diff) | |
download | torque-asm-75018f1ec69162a0695e603030f5e1a5cc105af0.zip |
Allow a macro to invoke itself safely
A macro can now invoke itself if the invocation is inside a conditional
block that will eventually return false. The assembler stack can still
overflow if the macro recurses too deeply, or if a macro calls itself
without a conditional block.
Diffstat (limited to 'src/stages/intermediate.rs')
-rw-r--r-- | src/stages/intermediate.rs | 28 |
1 files changed, 13 insertions, 15 deletions
diff --git a/src/stages/intermediate.rs b/src/stages/intermediate.rs index ca17aa0..c28426c 100644 --- a/src/stages/intermediate.rs +++ b/src/stages/intermediate.rs @@ -203,28 +203,26 @@ impl<'a> Environment<'a> { } } BlockToken::ConditionalBlock(cond) => { - let predicate = self.parse_integer_token(&cond.predicate, &cond.predicate.source); - let mut body = self.parse_block_token(&cond.body, &cond.body.source); - if let Some(predicate) = predicate { - let mut found_error = false; + if let Some(predicate) = self.parse_integer_token(&cond.predicate, &cond.predicate.source) { if let Some(source) = integer_contains_label_reference(&predicate) { let error = IntermediateError::LabelReferenceInConditionPredicate; let new_source = cond.predicate.source.clone().wrap(source); self.errors.push(Tracked::from(error, new_source)); - found_error = true; - }; - if let Some(source) = block_contains_label_definition(&cond.body, &cond.body.source) { - let error = IntermediateError::LabelDefinitionInConditionBody; - let new_source = cond.body.source.clone().wrap(source); - self.errors.push(Tracked::from(error, new_source)); - found_error = true; - } - if !found_error { + } else { match evaluate_integer(&predicate, &cond.predicate.source) { - Ok(value) => if value != 0 { intermediate.append(&mut body) }, + Ok(value) => if value != 0 { + let mut body = self.parse_block_token(&cond.body, &cond.body.source); + if let Some(source) = block_contains_label_definition(&cond.body, &cond.body.source) { + let error = IntermediateError::LabelDefinitionInConditionBody; + let new_source = cond.body.source.clone().wrap(source); + self.errors.push(Tracked::from(error, new_source)); + } else { + intermediate.append(&mut body); + } + }, Err(error) => self.errors.push(error), } - } + }; } } BlockToken::WordTemplate(word_template) => { |