From 5d06ba11c981430aca68f2ea31771fca7f18529b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Sabat=C3=A9=20Sol=C3=A0?= Date: Wed, 22 Jan 2025 22:22:46 +0100 Subject: [PATCH] Implement echo control statements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miquel Sabaté Solà --- lib/xixanta/src/assembler.rs | 31 ++++++++++++++++++++++++++++++- lib/xixanta/src/node.rs | 13 +++++++++++++ lib/xixanta/src/opcodes.rs | 6 +++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs index 4ee769b..66fe418 100644 --- a/lib/xixanta/src/assembler.rs +++ b/lib/xixanta/src/assembler.rs @@ -1,5 +1,5 @@ use crate::mapping::{get_mapping_configuration, Mapping}; -use crate::node::{ControlType, NodeType, OperationType, PNode, PString}; +use crate::node::{ControlType, EchoKind, NodeType, OperationType, PNode, PString}; use crate::object::{Bundle, Context, Object, ObjectType}; use crate::opcodes::{AddressingMode, INSTRUCTIONS}; use crate::parser::Parser; @@ -569,6 +569,7 @@ impl<'a> Assembler<'a> { // On control statements which modify the context, there are // some further evaluating to do. match control_type { + ControlType::Echo(t) => self.evaluate_echo(node, t)?, ControlType::StartRepeat => { self.evaluate_repeat_statement(node)?; } @@ -708,6 +709,33 @@ impl<'a> Assembler<'a> { } } + // Consume an .info/.warning/.error call. + fn evaluate_echo(&mut self, node: &PNode, t: &EchoKind) -> Result<(), Vec> { + let arg = node.args.as_ref().unwrap().first().unwrap(); + let val = &arg.value.value[1..arg.value.value.len() - 1]; + + match t { + EchoKind::Info => println!("info: {}", val), + EchoKind::Warning => self.warnings.push(Error { + global: false, + line: node.value.line, + source: self.source_for(node), + message: val.to_string(), + }), + EchoKind::Error => { + return Err(Error { + global: false, + line: node.value.line, + source: self.source_for(node), + message: val.to_string(), + } + .into()); + } + } + + Ok(()) + } + // Consume a node which contains a macro call by pushing its bundles now. fn bundle_call(&mut self, node: &PNode) -> Result<(), Vec> { // Get the macro we are trying to reproduce. @@ -1372,6 +1400,7 @@ impl<'a> Assembler<'a> { } NodeType::Control(ControlType::EndIf) => Ok(()), NodeType::Control(ControlType::IncludeSource) => Ok(()), + NodeType::Control(ControlType::Echo(_)) => Ok(()), _ => Err(Error { line: node.value.line, message: format!( diff --git a/lib/xixanta/src/node.rs b/lib/xixanta/src/node.rs index 243b478..8273967 100644 --- a/lib/xixanta/src/node.rs +++ b/lib/xixanta/src/node.rs @@ -121,6 +121,13 @@ impl PString { } } +#[derive(Debug, Clone, PartialEq)] +pub enum EchoKind { + Info, + Warning, + Error, +} + /// The type of control function being used. Use this enum in order to detect /// which control function was detected instead of the node value. #[derive(Debug, Clone, PartialEq)] @@ -150,6 +157,7 @@ pub enum ControlType { Else, EndIf, Defined, + Echo(EchoKind), } impl fmt::Display for ControlType { @@ -180,6 +188,11 @@ impl fmt::Display for ControlType { ControlType::Else => write!(f, ".else"), ControlType::EndIf => write!(f, ".endif"), ControlType::Defined => write!(f, ".defined"), + ControlType::Echo(t) => match t { + EchoKind::Info => write!(f, ".info"), + EchoKind::Warning => write!(f, ".warning"), + EchoKind::Error => write!(f, ".error"), + }, } } } diff --git a/lib/xixanta/src/opcodes.rs b/lib/xixanta/src/opcodes.rs index 865b5cd..752f8ea 100644 --- a/lib/xixanta/src/opcodes.rs +++ b/lib/xixanta/src/opcodes.rs @@ -1,4 +1,4 @@ -use crate::node::ControlType; +use crate::node::{ControlType, EchoKind}; use std::collections::HashMap; use std::fmt; @@ -765,6 +765,10 @@ lazy_static! { functions.insert(String::from(".endif"), Control { control_type: ControlType::EndIf, has_identifier: None, required_args: Some((0, 0)), touches_context: false, only_string: false }); functions.insert(String::from(".def"), Control { control_type: ControlType::Defined, has_identifier: None, required_args: Some((1, 1)), touches_context: false, only_string: false }); functions.insert(String::from(".defined"), Control { control_type: ControlType::Defined, has_identifier: None, required_args: Some((1, 1)), touches_context: false, only_string: false }); + functions.insert(String::from(".info"), Control { control_type: ControlType::Echo(EchoKind::Info), has_identifier: None, required_args: Some((1, 1)), touches_context: false, only_string: true }); + functions.insert(String::from(".out"), Control { control_type: ControlType::Echo(EchoKind::Info), has_identifier: None, required_args: Some((1, 1)), touches_context: false, only_string: true }); + functions.insert(String::from(".warning"), Control { control_type: ControlType::Echo(EchoKind::Warning), has_identifier: None, required_args: Some((1, 1)), touches_context: false, only_string: true }); + functions.insert(String::from(".error"), Control { control_type: ControlType::Echo(EchoKind::Error), has_identifier: None, required_args: Some((1, 1)), touches_context: false, only_string: true }); functions };