blob: c4e46b5ea6a60d9dd4c8047136eab03b2b3fb7d7 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Generating C constants from bind programs
#![allow(dead_code)]
use crate::instruction::{Condition, Instruction};
fn c_macro_invocation(macro_name: &str, arguments: &Vec<String>) -> String {
let mut parts = vec![macro_name, "("];
let argument_string = arguments.join(", ");
parts.push(&argument_string);
parts.push(")");
parts.join("")
}
fn to_macro_parts(condition: &Condition) -> Vec<String> {
match condition {
Condition::Always => vec!["AL".to_string()],
Condition::Equal(b, v) => vec!["EQ".to_string(), b.to_string(), v.to_string()],
Condition::NotEqual(b, v) => vec!["NE".to_string(), b.to_string(), v.to_string()],
Condition::GreaterThan(b, v) => vec!["GT".to_string(), b.to_string(), v.to_string()],
Condition::LessThan(b, v) => vec!["LT".to_string(), b.to_string(), v.to_string()],
Condition::GreaterThanEqual(b, v) => vec!["GE".to_string(), b.to_string(), v.to_string()],
Condition::LessThanEqual(b, v) => vec!["LE".to_string(), b.to_string(), v.to_string()],
}
}
fn to_c_constant(instruction: &Instruction) -> String {
match instruction {
Instruction::Abort(condition) => {
c_macro_invocation("BI_ABORT_IF", &to_macro_parts(condition))
}
Instruction::Match(condition) => {
c_macro_invocation("BI_MATCH_IF", &to_macro_parts(condition))
}
Instruction::Goto(condition, a) => {
let mut parts = to_macro_parts(condition);
parts.push(a.to_string());
c_macro_invocation("BI_GOTO_IF", &parts)
}
Instruction::Label(a) => c_macro_invocation("BI_LABEL", &vec![a.to_string()]),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_abort_value() {
let instruction = Instruction::Abort(Condition::Always);
let c_constant = to_c_constant(&instruction);
assert_eq!(c_constant, "BI_ABORT_IF(AL)")
}
fn test_abort_if_value() {
let instruction = Instruction::Abort(Condition::Equal(2, 3));
let c_constant = to_c_constant(&instruction);
assert_eq!(c_constant, "BI_ABORT_IF(EQ, 2, 3)")
}
#[test]
fn test_match_value() {
let instruction = Instruction::Match(Condition::Always);
let c_constant = to_c_constant(&instruction);
assert_eq!(c_constant, "BI_MATCH_IF(AL)")
}
#[test]
fn test_match_if_value() {
let instruction = Instruction::Match(Condition::GreaterThanEqual(18, 19));
let c_constant = to_c_constant(&instruction);
assert_eq!(c_constant, "BI_MATCH_IF(GE, 18, 19)")
}
#[test]
fn test_goto_value() {
let instruction = Instruction::Goto(Condition::Always, 42);
let c_constant = to_c_constant(&instruction);
assert_eq!(c_constant, "BI_GOTO_IF(AL, 42)")
}
#[test]
fn test_goto_if_value() {
let instruction = Instruction::Goto(Condition::LessThan(5, 6), 55);
let c_constant = to_c_constant(&instruction);
assert_eq!(c_constant, "BI_GOTO_IF(LT, 5, 6, 55)")
}
#[test]
fn test_label_value() {
let instruction = Instruction::Label(23);
let c_constant = to_c_constant(&instruction);
assert_eq!(c_constant, "BI_LABEL(23)")
}
}