use crate::empty_expr;
use crate::prelude::*;
use crate::zero_expr_float;
#[derive(Clone, Debug)]
pub enum ASTValue {
None,
Boolean(Option<String>, bool),
Int(Option<String>, i32),
Int2(Option<String>, Box<Expr>, Box<Expr>),
Int3(Option<String>, Box<Expr>, Box<Expr>, Box<Expr>),
Int4(Option<String>, Box<Expr>, Box<Expr>, Box<Expr>, Box<Expr>),
Float(Option<String>, f32),
Float2(Option<String>, Box<Expr>, Box<Expr>),
Float3(Option<String>, Box<Expr>, Box<Expr>, Box<Expr>),
Float4(Option<String>, Box<Expr>, Box<Expr>, Box<Expr>, Box<Expr>),
Mat2(Option<String>, Vec<Box<Expr>>),
Mat3(Option<String>, Vec<Box<Expr>>),
Mat4(Option<String>, Vec<Box<Expr>>),
String(Option<String>, String),
Struct(String, Option<String>, Vec<Box<Expr>>),
Function(String, Vec<ASTValue>, Box<ASTValue>),
}
impl ASTValue {
pub fn write_definition(&self, instr: &str, name: &str, precision: &str) -> Vec<String> {
match self {
ASTValue::Int(_, _) => vec![format!("({} {} f{})", instr, name, precision)],
ASTValue::Int2(_, _, _) => vec![
format!("({} ${}_x i{})", instr, name, precision),
format!("({} ${}_y i{})", instr, name, precision),
],
ASTValue::Int3(_, _, _, _) => vec![
format!("({} ${}_x i{})", instr, name, precision),
format!("({} ${}_y i{})", instr, name, precision),
format!("({} ${}_z i{})", instr, name, precision),
],
ASTValue::Int4(_, _, _, _, _) => vec![
format!("({} ${}_x i{})", instr, name, precision),
format!("({} ${}_y i{})", instr, name, precision),
format!("({} ${}_z i{})", instr, name, precision),
format!("({} ${}_w i{})", instr, name, precision),
],
ASTValue::Float(_, _) => vec![format!("({} {} f{})", instr, name, precision)],
ASTValue::Float2(_, _, _) => vec![
format!("({} ${}_x f{})", instr, name, precision),
format!("({} ${}_y f{})", instr, name, precision),
],
ASTValue::Float3(_, _, _, _) => vec![
format!("({} ${}_x f{})", instr, name, precision),
format!("({} ${}_y f{})", instr, name, precision),
format!("({} ${}_z f{})", instr, name, precision),
],
ASTValue::Float4(_, _, _, _, _) => vec![
format!("({} ${}_x f{})", instr, name, precision),
format!("({} ${}_y f{})", instr, name, precision),
format!("({} ${}_z f{})", instr, name, precision),
format!("({} ${}_w f{})", instr, name, precision),
],
ASTValue::Mat2(_, _) => vec![
format!("({} ${}_x f{})", instr, name, precision),
format!("({} ${}_y f{})", instr, name, precision),
format!("({} ${}_z f{})", instr, name, precision),
format!("({} ${}_w f{})", instr, name, precision),
],
ASTValue::Mat3(_, _) => vec![
format!("({} ${}_1 f{})", instr, name, precision),
format!("({} ${}_2 f{})", instr, name, precision),
format!("({} ${}_3 f{})", instr, name, precision),
format!("({} ${}_4 f{})", instr, name, precision),
format!("({} ${}_5 f{})", instr, name, precision),
format!("({} ${}_6 f{})", instr, name, precision),
format!("({} ${}_7 f{})", instr, name, precision),
format!("({} ${}_8 f{})", instr, name, precision),
format!("({} ${}_9 f{})", instr, name, precision),
],
ASTValue::Struct(_, _, _) => vec![format!("({} ${} i32)", instr, name)],
_ => vec![],
}
}
pub fn write_access(&self, instr: &str, name: &str) -> Vec<String> {
match self {
ASTValue::Float(_, _) | ASTValue::Int(_, _) => vec![format!("({} {})", instr, name)],
ASTValue::Float2(_, _, _) | ASTValue::Int2(_, _, _) => vec![
format!("({} ${}_x)", instr, name),
format!("({} ${}_y)", instr, name),
],
ASTValue::Float3(_, _, _, _) | ASTValue::Int3(_, _, _, _) => vec![
format!("({} ${}_x)", instr, name),
format!("({} ${}_y)", instr, name),
format!("({} ${}_z)", instr, name),
],
ASTValue::Float4(_, _, _, _, _) | ASTValue::Int4(_, _, _, _, _) => vec![
format!("({} ${}_x)", instr, name),
format!("({} ${}_y)", instr, name),
format!("({} ${}_z)", instr, name),
format!("({} ${}_w)", instr, name),
],
ASTValue::Mat2(_, _) => vec![
format!("({} ${}_x)", instr, name),
format!("({} ${}_y)", instr, name),
format!("({} ${}_z)", instr, name),
format!("({} ${}_w)", instr, name),
],
ASTValue::Mat3(_, _) => vec![
format!("({} ${}_1)", instr, name),
format!("({} ${}_2)", instr, name),
format!("({} ${}_3)", instr, name),
format!("({} ${}_4)", instr, name),
format!("({} ${}_5)", instr, name),
format!("({} ${}_6)", instr, name),
format!("({} ${}_7)", instr, name),
format!("({} ${}_8)", instr, name),
format!("({} ${}_9)", instr, name),
],
ASTValue::Struct(_, _, _) => vec![format!("({} ${})", instr, name)],
_ => vec![],
}
}
pub fn to_float(&self) -> Option<f32> {
match self {
ASTValue::Float(_, f) => Some(*f),
_ => None,
}
}
pub fn to_int(&self) -> Option<i32> {
match self {
ASTValue::Int(_, i) => Some(*i),
_ => None,
}
}
pub fn is_float_based(&self) -> bool {
matches!(
self,
ASTValue::Float(_, _)
| ASTValue::Float2(_, _, _)
| ASTValue::Float3(_, _, _, _)
| ASTValue::Float4(_, _, _, _, _)
)
}
pub fn is_truthy(&self) -> bool {
match self {
ASTValue::Boolean(_, b) => *b,
ASTValue::Int(_, i) => *i != 0,
ASTValue::Int2(_, _, _) => true,
ASTValue::Int3(_, _, _, _) => true,
ASTValue::Int4(_, _, _, _, _) => true,
ASTValue::Float(_, i) => *i != 0.0,
ASTValue::Float2(_, _, _) => true,
ASTValue::Float3(_, _, _, _) => true,
ASTValue::Float4(_, _, _, _, _) => true,
ASTValue::String(_, s) => !s.is_empty(),
ASTValue::Function(_, _, _) => true,
_ => false,
}
}
pub fn components(&self) -> usize {
match self {
ASTValue::Int(_, _) => 1,
ASTValue::Int2(_, _, _) => 2,
ASTValue::Int3(_, _, _, _) => 3,
ASTValue::Int4(_, _, _, _, _) => 4,
ASTValue::Float(_, _) => 1,
ASTValue::Float2(_, _, _) => 2,
ASTValue::Float3(_, _, _, _) => 3,
ASTValue::Float4(_, _, _, _, _) => 4,
ASTValue::Mat2(_, _) => 4,
ASTValue::Mat3(_, _) => 9,
ASTValue::Mat4(_, _) => 16,
_ => 0,
}
}
pub fn to_type(&self) -> String {
match self {
ASTValue::None => "void".to_string(),
ASTValue::Boolean(_, _) => "bool".to_string(),
ASTValue::Int(_, _) => "int".to_string(),
ASTValue::Int2(_, _, _) => "ivec2".to_string(),
ASTValue::Int3(_, _, _, _) => "ivec3".to_string(),
ASTValue::Int4(_, _, _, _, _) => "ivec4".to_string(),
ASTValue::Float(_, _) => "float".to_string(),
ASTValue::Float2(_, _, _) => "vec2".to_string(),
ASTValue::Float3(_, _, _, _) => "vec3".to_string(),
ASTValue::Float4(_, _, _, _, _) => "vec4".to_string(),
ASTValue::String(_, _) => "string".to_string(),
ASTValue::Function(_, _, _) => "fn".to_string(),
ASTValue::Mat2(_, _) => "mat2".to_string(),
ASTValue::Mat3(_, _) => "mat3".to_string(),
ASTValue::Mat4(_, _) => "mat4".to_string(),
ASTValue::Struct(_, _, _) => "struct".to_string(),
}
}
pub fn to_wat_type(&self, pr: &str) -> Option<String> {
match self {
ASTValue::Boolean(_, _) => Some(format!("(i{}", pr)),
ASTValue::Int(_, _) => Some(format!("i{}", pr)),
ASTValue::Int2(_, _, _) => Some(format!("i{} i{}", pr, pr)),
ASTValue::Int3(_, _, _, _) => Some(format!("i{} i{} i{}", pr, pr, pr)),
ASTValue::Int4(_, _, _, _, _) => Some(format!("i{} i{} i{} i{}", pr, pr, pr, pr)),
ASTValue::Float(_, _) => Some(format!("f{}", pr)),
ASTValue::Float2(_, _, _) => Some(format!("f{} f{}", pr, pr)),
ASTValue::Float3(_, _, _, _) => Some(format!("f{} f{} f{}", pr, pr, pr)),
ASTValue::Float4(_, _, _, _, _) => Some(format!("f{} f{} f{} f{}", pr, pr, pr, pr)),
ASTValue::Mat2(_, _) => Some(format!("f{} f{} f{} f{}", pr, pr, pr, pr)),
ASTValue::Mat3(_, _) => Some(format!(
"f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr}",
pr = pr
)),
ASTValue::Mat4(_, _) => Some(format!(
"f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr} f{pr}",
pr = pr
)),
ASTValue::Struct(_, _, _) => Some("i32".to_string()),
_ => None,
}
}
pub fn to_wat_component_type(&self, pr: &str) -> String {
if self.is_float_based() {
format!("f{}", pr)
} else {
format!("i{}", pr)
}
}
pub fn from_token_type(name: Option<String>, token_type: &TokenType) -> ASTValue {
match token_type {
TokenType::Void => ASTValue::None,
TokenType::True => ASTValue::Boolean(name, true),
TokenType::False => ASTValue::Boolean(name, false),
TokenType::Int => ASTValue::Int(name, 0),
TokenType::Int2 => ASTValue::Int2(name, empty_expr!(), empty_expr!()),
TokenType::Int3 => ASTValue::Int3(name, empty_expr!(), empty_expr!(), empty_expr!()),
TokenType::Int4 => ASTValue::Int4(
name,
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
),
TokenType::Float => ASTValue::Float(name, 0.0),
TokenType::Float2 => ASTValue::Float2(name, empty_expr!(), empty_expr!()),
TokenType::Float3 => {
ASTValue::Float3(name, empty_expr!(), empty_expr!(), empty_expr!())
}
TokenType::Float4 => ASTValue::Float4(
name,
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
),
TokenType::Mat2 => ASTValue::Mat2(
name,
vec![empty_expr!(), empty_expr!(), empty_expr!(), empty_expr!()],
),
TokenType::Mat3 => ASTValue::Mat3(
name,
vec![
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
],
),
TokenType::Mat4 => ASTValue::Mat4(
name,
vec![
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
empty_expr!(),
],
),
TokenType::String => ASTValue::String(name, "".to_string()),
_ => ASTValue::None,
}
}
pub fn name(&self) -> Option<String> {
match self {
ASTValue::Boolean(name, _) => name.clone(),
ASTValue::Int(name, _) => name.clone(),
ASTValue::Int2(name, _, _) => name.clone(),
ASTValue::Int3(name, _, _, _) => name.clone(),
ASTValue::Int4(name, _, _, _, _) => name.clone(),
ASTValue::Float(name, _) => name.clone(),
ASTValue::Float2(name, _, _) => name.clone(),
ASTValue::Float3(name, _, _, _) => name.clone(),
ASTValue::Float4(name, _, _, _, _) => name.clone(),
ASTValue::String(name, _) => name.clone(),
ASTValue::Function(name, _, _) => Some(name.clone()),
ASTValue::Mat2(name, _) => name.clone(),
ASTValue::Mat3(name, _) => name.clone(),
ASTValue::Mat4(name, _) => name.clone(),
ASTValue::Struct(_, instance_name, _) => instance_name.clone(),
ASTValue::None => None,
}
}
pub fn as_empty_expression(&self) -> Expr {
match self {
ASTValue::Int(_, _) => Expr::Value(
ASTValue::Int(Some("1".to_string()), 0),
vec![],
vec![],
Location::default(),
),
ASTValue::Float(_, _) => Expr::Value(
ASTValue::Float(Some("1".to_string()), 0.0),
vec![],
vec![],
Location::default(),
),
ASTValue::Float2(_, _, _) => Expr::Value(
ASTValue::Float2(
Some("2".to_string()),
zero_expr_float!(),
zero_expr_float!(),
),
vec![],
vec![],
Location::default(),
),
ASTValue::Float3(_, _, _, _) => Expr::Value(
ASTValue::Float3(
Some("3".to_string()),
zero_expr_float!(),
zero_expr_float!(),
zero_expr_float!(),
),
vec![],
vec![],
Location::default(),
),
_ => Expr::Value(self.clone(), vec![], vec![], Location::default()),
}
}
}