aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock40
-rw-r--r--Cargo.toml4
-rw-r--r--crates/nasm/Cargo.toml4
-rw-r--r--lib/xixanta/src/assembler.rs94
-rw-r--r--lib/xixanta/src/context.rs13
-rw-r--r--lib/xixanta/src/node.rs30
-rw-r--r--lib/xixanta/src/opcodes.rs30
-rw-r--r--lib/xixanta/src/parser.rs70
8 files changed, 182 insertions, 103 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 72365c6..e86a0da 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "anstream"
-version = "0.6.15"
+version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -19,33 +19,33 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.8"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
[[package]]
name = "anstyle-parse"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.4"
+version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys",
@@ -53,9 +53,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.89"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
+checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
[[package]]
name = "clap"
@@ -99,9 +99,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "colorchoice"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "heck"
@@ -146,9 +146,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.87"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
@@ -170,9 +170,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
-version = "2.0.79"
+version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
+checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [
"proc-macro2",
"quote",
@@ -193,9 +193,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "windows-sys"
-version = "0.52.0"
+version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
diff --git a/Cargo.toml b/Cargo.toml
index 1ea211b..552c48f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,3 +10,7 @@ authors = ["Miquel Sabaté Solà"]
[workspace.dependencies]
xixanta = { path = "./lib/xixanta", version = "0.1.0" }
+
+[profile.release]
+codegen-units = 1
+lto = true
diff --git a/crates/nasm/Cargo.toml b/crates/nasm/Cargo.toml
index b89b48c..110e5ad 100644
--- a/crates/nasm/Cargo.toml
+++ b/crates/nasm/Cargo.toml
@@ -5,6 +5,6 @@ edition = "2021"
authors = ["Miquel Sabaté Solà <mikisabate@gmail.com>"]
[dependencies]
-anyhow = "1.0.82"
-clap = { version = "4.5.4", features = ["derive"] }
+anyhow = "^1"
+clap = { version = "^4", features = ["derive"] }
xixanta.workspace = true
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index e614b42..0f164d7 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -1,7 +1,7 @@
use crate::context::Context;
use crate::errors::{Error, EvalError};
use crate::mapping::Segment;
-use crate::node::{NodeType, PNode, PString};
+use crate::node::{ControlType, NodeType, PNode, PString};
use crate::opcodes::{AddressingMode, INSTRUCTIONS};
use crate::parser::Parser;
use std::cmp::Ordering;
@@ -145,7 +145,7 @@ impl Assembler {
let mut current_macro = None;
for (idx, node) in nodes.iter().enumerate() {
- match node.node_type {
+ match &node.node_type {
NodeType::Label => {
if let Err(err) =
self.context
@@ -174,43 +174,46 @@ impl Assembler {
Err(e) => errors.push(Error::Eval(e)),
}
}
- NodeType::Control => {
+ NodeType::Control(control_type) => {
// TODO: prevent nesting of control statements depending on
// a definition (e.g. .macro's cannot be nested inside of
// another control statement, but .if yes).
- let id = node.value.value.as_str();
-
- if id == ".macro" {
- // TODO: macros are only on the global scope.
- //
- // TODO: boy this is ugly. In fact, this stupid shit if
- // current_macro might not be relevant anymore.
- current_macro = Some(&node.left.as_ref().unwrap().value);
- // TODO: watch out for weird shit on the name of arguments.
- self.macros
- .entry(node.left.as_ref().unwrap().value.value.clone())
- .or_insert(Macro {
- nodes: Range {
- start: idx + 1,
- end: idx + 1,
- },
- args: node
- .args
- .clone()
- .unwrap_or_default()
- .into_iter()
- .map(|a| a.value)
- .collect::<Vec<_>>(),
- });
- } else if id == ".endmacro" {
- // TODO: if m.nodes.start < idx - 1 => empty macro
- if let Some(name) = current_macro {
+ match control_type {
+ ControlType::StartMacro => {
+ // TODO: macros are only on the global scope.
+ //
+ // TODO: boy this is ugly. In fact, this stupid shit if
+ // current_macro might not be relevant anymore.
+ current_macro = Some(&node.left.as_ref().unwrap().value);
+ // TODO: watch out for weird shit on the name of arguments.
self.macros
- .entry(name.value.clone())
- .and_modify(|m| m.nodes.end = idx - 1);
+ .entry(node.left.as_ref().unwrap().value.value.clone())
+ .or_insert(Macro {
+ nodes: Range {
+ start: idx + 1,
+ end: idx + 1,
+ },
+ args: node
+ .args
+ .clone()
+ .unwrap_or_default()
+ .into_iter()
+ .map(|a| a.value)
+ .collect::<Vec<_>>(),
+ });
+ }
+ ControlType::EndMacro => {
+ // TODO: if m.nodes.start < idx - 1 => empty macro
+
+ if let Some(name) = current_macro {
+ self.macros
+ .entry(name.value.clone())
+ .and_modify(|m| m.nodes.end = idx - 1);
+ }
+ current_macro = None;
}
- current_macro = None;
+ _ => {}
}
if let Err(err) = self.context.change_context(node) {
// TODO: forbid if inside_macro
@@ -271,7 +274,7 @@ impl Assembler {
}
}
}
- NodeType::Control => {
+ NodeType::Control(_) => {
if let Err(e) = self.evaluate_control_statement(node) {
errors.push(Error::Eval(e));
}
@@ -422,7 +425,7 @@ impl Assembler {
match node.node_type {
NodeType::Instruction => Ok(self.evaluate_instruction(node)?),
NodeType::Literal => Ok(self.evaluate_literal(node)?),
- NodeType::Control => Ok(self.evaluate_control_expression(node)?),
+ NodeType::Control(_) => Ok(self.evaluate_control_expression(node)?),
NodeType::Value => match self.literal_mode {
Some(LiteralMode::Hexadecimal) => Ok(self.evaluate_hexadecimal(node)?),
Some(LiteralMode::Binary) => Ok(self.evaluate_binary(node)?),
@@ -722,31 +725,30 @@ impl Assembler {
// Otherwise, check the function that could act as a statement that
// produces bundles.
- let function = node.value.value.as_str();
- match function {
- ".byte" | ".db" => self.push_evaluated_arguments(node, 1),
- ".addr" | ".word" | ".dw" => self.push_evaluated_arguments(node, 2),
+ match node.node_type {
+ NodeType::Control(ControlType::Byte) => self.push_evaluated_arguments(node, 1),
+ NodeType::Control(ControlType::Addr) | NodeType::Control(ControlType::Word) => {
+ self.push_evaluated_arguments(node, 2)
+ }
_ => Err(EvalError {
line: node.value.line,
message: format!(
"cannot handle control statement '{}' in this context",
- function
+ node.value.value
),
}),
}
}
fn evaluate_control_expression(&mut self, node: &PNode) -> Result<Bundle, EvalError> {
- let function = node.value.value.to_lowercase();
-
- match function.as_str() {
- ".hibyte" => self.evaluate_byte(node, true),
- ".lobyte" => self.evaluate_byte(node, false),
+ match node.node_type {
+ NodeType::Control(ControlType::Hibyte) => self.evaluate_byte(node, true),
+ NodeType::Control(ControlType::Lobyte) => self.evaluate_byte(node, false),
_ => Err(EvalError {
line: node.value.line,
message: format!(
"cannot handle control statement '{}' as an expression in this context",
- function
+ node.value.value
),
}),
}
diff --git a/lib/xixanta/src/context.rs b/lib/xixanta/src/context.rs
index bccac12..6933085 100644
--- a/lib/xixanta/src/context.rs
+++ b/lib/xixanta/src/context.rs
@@ -1,6 +1,6 @@
use crate::assembler::Bundle;
use crate::errors::{ContextError, ContextErrorReason};
-use crate::node::{PNode, PString};
+use crate::node::{ControlType, NodeType, PNode, PString};
use crate::opcodes::CONTROL_FUNCTIONS;
use std::collections::HashMap;
@@ -111,16 +111,19 @@ impl Context {
}
// And push/pop the context depending on the control being used.
- match node.value.value.as_str() {
- ".macro" => {
+ match node.node_type {
+ NodeType::Control(ControlType::StartMacro) => {
self.context_push(&node.left.clone().unwrap());
Ok((true, false))
}
- ".proc" | ".scope" => {
+ NodeType::Control(ControlType::StartProc)
+ | NodeType::Control(ControlType::StartScope) => {
self.context_push(&node.left.clone().unwrap());
Ok((true, true))
}
- ".endmacro" | ".endproc" | ".endscope" => {
+ NodeType::Control(ControlType::EndMacro)
+ | NodeType::Control(ControlType::EndProc)
+ | NodeType::Control(ControlType::EndScope) => {
self.context_pop(&node.value)?;
Ok((true, true))
}
diff --git a/lib/xixanta/src/node.rs b/lib/xixanta/src/node.rs
index a28d625..c787394 100644
--- a/lib/xixanta/src/node.rs
+++ b/lib/xixanta/src/node.rs
@@ -82,6 +82,24 @@ impl PString {
}
}
+/// 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)]
+pub enum ControlType {
+ Hibyte,
+ Lobyte,
+ StartMacro,
+ EndMacro,
+ StartProc,
+ EndProc,
+ StartScope,
+ EndScope,
+ Segment,
+ Byte,
+ Word,
+ Addr,
+}
+
/// The PNode type.
#[derive(Debug, Clone, PartialEq)]
pub enum NodeType {
@@ -106,10 +124,12 @@ pub enum NodeType {
Assignment,
/// A control statement (e.g. ".proc foo"). The `value` string contains the
- /// name of the function, the `left` an optional identifier (e.g. the "foo"
- /// on ".proc foo"), and the `args` contain any possible arguments that have
- /// been passed to this control statement.
- Control,
+ /// name of the function as it was provided (use the `ControlType` value of
+ /// the enum to detect which function was exactly provided), the `left` an
+ /// optional identifier (e.g. the "foo" on ".proc foo"), and the `args`
+ /// contain any possible arguments that have been passed to this control
+ /// statement.
+ Control(ControlType),
/// A literal expression, that is, something that starts with '#', '%' or
/// '$'. The `left` node contains the inner expression.
@@ -130,7 +150,7 @@ impl fmt::Display for NodeType {
NodeType::Instruction => write!(f, "instruction"),
NodeType::Indirection => write!(f, "indirection"),
NodeType::Assignment => write!(f, "assignment"),
- NodeType::Control => write!(f, "control function"),
+ NodeType::Control(_) => write!(f, "control function"),
NodeType::Literal => write!(f, "literal"),
NodeType::Label => write!(f, "label"),
NodeType::Call => write!(f, "call"),
diff --git a/lib/xixanta/src/opcodes.rs b/lib/xixanta/src/opcodes.rs
index 0e7f379..4e336ba 100644
--- a/lib/xixanta/src/opcodes.rs
+++ b/lib/xixanta/src/opcodes.rs
@@ -1,3 +1,4 @@
+use crate::node::ControlType;
use std::collections::HashMap;
use std::fmt;
@@ -55,6 +56,7 @@ pub struct ShortEntry {
#[derive(Debug)]
pub struct Control {
+ pub control_type: ControlType,
pub has_identifier: bool,
pub required_args: Option<usize>,
pub touches_context: bool,
@@ -714,20 +716,20 @@ lazy_static! {
pub static ref CONTROL_FUNCTIONS: HashMap<String, Control> = {
let mut functions = HashMap::new();
- functions.insert(String::from(".hibyte"), Control { has_identifier: false, required_args: Some(1), touches_context: false });
- functions.insert(String::from(".lobyte"), Control { has_identifier: false, required_args: Some(1), touches_context: false });
- functions.insert(String::from(".macro"), Control { has_identifier: true, required_args: None, touches_context: true });
- functions.insert(String::from(".proc"), Control { has_identifier: true, required_args: Some(0), touches_context: true });
- functions.insert(String::from(".scope"), Control { has_identifier: true, required_args: Some(0), touches_context: true });
- functions.insert(String::from(".endscope"), Control { has_identifier: false, required_args: Some(0), touches_context: true });
- functions.insert(String::from(".endproc"), Control { has_identifier: false, required_args: Some(0), touches_context: true });
- functions.insert(String::from(".endmacro"), Control { has_identifier: false, required_args: Some(0), touches_context: true });
- functions.insert(String::from(".segment"), Control { has_identifier: false, required_args: Some(1), touches_context: true });
- functions.insert(String::from(".byte"), Control { has_identifier: false, required_args: None, touches_context: false });
- functions.insert(String::from(".db"), Control { has_identifier: false, required_args: None, touches_context: false });
- functions.insert(String::from(".word"), Control { has_identifier: false, required_args: None, touches_context: false });
- functions.insert(String::from(".dw"), Control { has_identifier: false, required_args: None, touches_context: false });
- functions.insert(String::from(".addr"), Control { has_identifier: false, required_args: None, touches_context: false });
+ functions.insert(String::from(".hibyte"), Control { control_type: ControlType::Hibyte, has_identifier: false, required_args: Some(1), touches_context: false });
+ functions.insert(String::from(".lobyte"), Control { control_type: ControlType::Lobyte, has_identifier: false, required_args: Some(1), touches_context: false });
+ functions.insert(String::from(".macro"), Control { control_type: ControlType::StartMacro, has_identifier: true, required_args: None, touches_context: true });
+ functions.insert(String::from(".proc"), Control { control_type: ControlType::StartProc, has_identifier: true, required_args: Some(0), touches_context: true });
+ functions.insert(String::from(".scope"), Control { control_type: ControlType::StartScope, has_identifier: true, required_args: Some(0), touches_context: true });
+ functions.insert(String::from(".endscope"), Control { control_type: ControlType::EndScope, has_identifier: false, required_args: Some(0), touches_context: true });
+ functions.insert(String::from(".endproc"), Control { control_type: ControlType::EndProc, has_identifier: false, required_args: Some(0), touches_context: true });
+ functions.insert(String::from(".endmacro"), Control { control_type: ControlType::EndMacro, has_identifier: false, required_args: Some(0), touches_context: true });
+ functions.insert(String::from(".segment"), Control { control_type: ControlType::Segment, has_identifier: false, required_args: Some(1), touches_context: true });
+ functions.insert(String::from(".byte"), Control { control_type: ControlType::Byte, has_identifier: false, required_args: None, touches_context: false });
+ functions.insert(String::from(".db"), Control { control_type: ControlType::Byte, has_identifier: false, required_args: None, touches_context: false });
+ functions.insert(String::from(".word"), Control { control_type: ControlType::Word, has_identifier: false, required_args: None, touches_context: false });
+ functions.insert(String::from(".dw"), Control { control_type: ControlType::Word, has_identifier: false, required_args: None, touches_context: false });
+ functions.insert(String::from(".addr"), Control { control_type: ControlType::Addr, has_identifier: false, required_args: None, touches_context: false });
functions
};
diff --git a/lib/xixanta/src/parser.rs b/lib/xixanta/src/parser.rs
index 2c20369..9e7b7d5 100644
--- a/lib/xixanta/src/parser.rs
+++ b/lib/xixanta/src/parser.rs
@@ -703,11 +703,13 @@ impl Parser {
fn parse_control(&mut self, id: PString, line: &str) -> Result<PNode, ParseError> {
let mut left = None;
let required;
+ let node_type;
// Ensure that this is a function that we know of. In the past this was
// not done and it brought too many problems that made the more
// "abstract" way of handling this just too complicated.
if let Some(control) = CONTROL_FUNCTIONS.get(&id.value.to_lowercase()) {
+ node_type = control.control_type.clone();
required = control.required_args;
// If this control function has an identifier (e.g. `.macro
@@ -740,7 +742,7 @@ impl Parser {
}
Ok(PNode {
- node_type: NodeType::Control,
+ node_type: NodeType::Control(node_type),
value: id,
left,
right: None,
@@ -815,6 +817,7 @@ impl Parser {
#[cfg(test)]
mod tests {
use super::*;
+ use crate::node::ControlType;
fn assert_one_valid(parser: &mut Parser, line: &str) {
assert!(parser.parse(line.as_bytes()).is_ok());
@@ -1356,7 +1359,12 @@ mod tests {
assert!(parser.parse(line.as_bytes()).is_ok());
let node = parser.nodes.last().unwrap();
- assert_node(node, NodeType::Control, line, ".endmacro");
+ assert_node(
+ node,
+ NodeType::Control(ControlType::EndMacro),
+ line,
+ ".endmacro",
+ );
assert!(node.left.is_none());
assert!(node.right.is_none());
assert!(node.args.is_none());
@@ -1378,7 +1386,12 @@ mod tests {
assert!(parser.parse(line.as_bytes()).is_ok());
let node = parser.nodes.last().unwrap();
- assert_node(node, NodeType::Control, line, ".hibyte");
+ assert_node(
+ node,
+ NodeType::Control(ControlType::Hibyte),
+ line,
+ ".hibyte",
+ );
assert!(node.left.is_none());
assert!(node.right.is_none());
@@ -1403,7 +1416,7 @@ mod tests {
assert!(parser.parse(line.as_bytes()).is_ok());
let node = parser.nodes.last().unwrap();
- assert_node(node, NodeType::Control, line, ".byte");
+ assert_node(node, NodeType::Control(ControlType::Byte), line, ".byte");
assert!(node.left.is_none());
assert!(node.right.is_none());
@@ -1428,7 +1441,12 @@ mod tests {
assert!(parser.parse(line.as_bytes()).is_ok());
let node = parser.nodes.last().unwrap();
- assert_node(node, NodeType::Control, line, ".scope");
+ assert_node(
+ node,
+ NodeType::Control(ControlType::StartScope),
+ line,
+ ".scope",
+ );
assert!(node.right.is_none());
assert!(node.args.is_none());
@@ -1452,7 +1470,12 @@ mod tests {
assert!(parser.parse(line.as_bytes()).is_ok());
let node = parser.nodes.last().unwrap();
- assert_node(node, NodeType::Control, line, ".macro");
+ assert_node(
+ node,
+ NodeType::Control(ControlType::StartMacro),
+ line,
+ ".macro",
+ );
assert!(node.right.is_none());
let left = node.left.clone().unwrap();
@@ -1479,7 +1502,12 @@ mod tests {
assert!(parser.parse(line.as_bytes()).is_ok());
let node = parser.nodes.last().unwrap();
- assert_node(node, NodeType::Control, line, ".macro");
+ assert_node(
+ node,
+ NodeType::Control(ControlType::StartMacro),
+ line,
+ ".macro",
+ );
assert!(node.right.is_none());
let left = node.left.clone().unwrap();
@@ -1522,7 +1550,12 @@ mod tests {
assert!(left.args.is_none());
let control = left.left.clone().unwrap();
- assert_node(&control, NodeType::Control, line, ".hibyte");
+ assert_node(
+ &control,
+ NodeType::Control(ControlType::Hibyte),
+ line,
+ ".hibyte",
+ );
assert!(control.left.is_none());
assert!(control.right.is_none());
@@ -1558,7 +1591,12 @@ mod tests {
assert!(left.args.is_none());
let control = left.left.clone().unwrap();
- assert_node(&control, NodeType::Control, line, ".hibyte");
+ assert_node(
+ &control,
+ NodeType::Control(ControlType::Hibyte),
+ line,
+ ".hibyte",
+ );
assert!(control.left.is_none());
assert!(control.right.is_none());
@@ -1597,7 +1635,12 @@ mod tests {
assert!(left.args.is_none());
let control = left.left.clone().unwrap();
- assert_node(&control, NodeType::Control, line, ".hibyte");
+ assert_node(
+ &control,
+ NodeType::Control(ControlType::Hibyte),
+ line,
+ ".hibyte",
+ );
assert!(control.left.is_none());
assert!(control.right.is_none());
@@ -1633,7 +1676,12 @@ mod tests {
assert!(left.args.is_none());
let control = left.left.clone().unwrap();
- assert_node(&control, NodeType::Control, line, ".hibyte");
+ assert_node(
+ &control,
+ NodeType::Control(ControlType::Hibyte),
+ line,
+ ".hibyte",
+ );
assert!(control.left.is_none());
assert!(control.right.is_none());