Broken; Rust's Display trait is weird. Help.

pull/3/head
itycodes 3 weeks ago
parent 6036a5fe90
commit 3d5369cc36

@ -2,9 +2,114 @@
mod tests;
use crate::compiler::Module;
use std::{fmt::Write, ops::Add};
use std::fmt::Write;
use std::fmt;
pub fn fix_name(name: &String) -> String {
use super::StorageClass;
#[derive(Debug, PartialEq, Clone)]
pub enum Type {
Pointer(Box<Type>, StorageClass),
Vector(Box<Type>, u32),
Float(u32),
Int(u32),
Unsigned(u32),
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Type::Pointer(typ, storage_class) => {
match storage_class {
StorageClass::Input => write!(f, "*{}i", typ),
StorageClass::Output => write!(f, "*{}o", typ),
StorageClass::Undefined => panic!("Bound a non-declared variable"),
}
},
Type::Vector(typ, size) => write!(f, "v{}{}", size, typ),
Type::Float(size) => write!(f, "f{}", size),
Type::Int(size) => write!(f, "s{}", size),
Type::Unsigned(size) => write!(f, "u{}", size),
}
}
}
pub fn parse_type(typ: String) -> Type {
// pointers have the format *<t>i or *<t>o, for the storage class
// floats have the format f<size>, so f32, f64...
// ints have the format s<size>, so s32, s64...
// unsigned ints have the format u<size>, so u32, u64...
// So, *v4f32i is a pointer to a vector of 4 floats, with the storage class Input.
// *v4f32o is a pointer to a vector of 4 floats, with the storage class Output.
let c = typ.chars().next().unwrap();
match c {
'*' => {
let mut chars = typ.chars();
chars.next();
let typ = chars.collect::<String>();
let storage_class = match typ.chars().last().unwrap() {
'i' => StorageClass::Input,
'o' => StorageClass::Output,
_ => panic!("Invalid storage class"),
};
let typ = typ.chars().take(typ.len() - 1).collect::<String>();
Type::Pointer(Box::new(parse_type(typ)), storage_class)
},
'v' => {
let mut chars = typ.chars();
chars.next();
let size = chars.next().unwrap().to_digit(10).unwrap();
let typ = chars.collect::<String>();
Type::Vector(Box::new(parse_type(typ)), size)
},
'f' => {
let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
Type::Float(size)
},
's' => {
let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
Type::Int(size)
},
'u' => {
let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
Type::Unsigned(size)
},
_ => panic!("Invalid type"),
}
}
fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) {
match typ {
Type::Unsigned(size) => {
ops.push((format!("%u{}", size).to_string(), format!("OpTypeInt {}", size)));
},
Type::Int(size) => {
ops.push((format!("%s{}", size).to_string(), format!("OpTypeInt {}", size)));
},
Type::Float(size) => {
ops.push((format!("%f{}", size).to_string(), format!("OpTypeFloat {}", size)));
},
Type::Vector(typ, size) => {
emit_type(*typ.clone(), ops);
let typ_id = format!("%{}", *typ.clone());
ops.push((format!("%v{}{}", typ_id, size).to_string(), format!("OpTypeVector {} {}", typ_id, size)))
},
Type::Pointer(typ, storage_class) => {
emit_type(*typ.clone(), ops);
let typ_id = format!("%{}", *typ.clone());
let storage_class = match storage_class {
StorageClass::Input => "Input",
StorageClass::Output => "Output",
StorageClass::Undefined => panic!("Bound a non-declared variable"),
};
ops.push((format!("%{}{}", typ_id, storage_class).to_string(), format!("OpTypePointer {} {}", storage_class, typ_id)))
},
}
}
fn fix_name(name: &String) -> String {
format!("%{}", name.clone().replace("-", "_"))
}
@ -51,13 +156,18 @@ pub fn spirv_meta(module: Module) -> String {
for global in module.globals {
let name = fix_name(&global.name);
let typ = global.typ;
let _typ = global.typ;
let storage_class = match global.storage_class {
crate::compiler::StorageClass::Input => "Input",
crate::compiler::StorageClass::Output => "Output",
crate::compiler::StorageClass::Undefined => panic!("Bound a non-declared variable"),
};
let typ_id = "%undefined_type";
let typ_id = format!("%{}", _typ);
let mut type_ops = Vec::new();
emit_type(parse_type(_typ), &mut type_ops);
for op in type_ops {
ops.push((Some(op.0), vec![op.1]));
}
ops.push((Some(name.clone()), vec!["OpVariable".to_string(), typ_id.to_string(), storage_class.to_string()]));
for dec in global.decorations {
// Decorations have the format Location 0, or Builtin FragCoord

@ -22,4 +22,18 @@ fn test_emit() {
let module = meta_compile(&mut ast);
let res = spirv_meta(module);
println!("{}", res);
}
#[test]
fn test_type_parse() {
use crate::compiler::backend::*;
use Type::*;
assert_eq!(parse_type("*v4f32i".to_string()),
Pointer(Box::new(Vector(Box::new(Float(32)), 4)), StorageClass::Input));
assert_eq!(parse_type("*v4f32o".to_string()),
Pointer(Box::new(Vector(Box::new(Float(32)), 4)), StorageClass::Output));
assert_eq!(parse_type("v2f32".to_string()),
Vector(Box::new(Float(32)), 2));
assert_eq!(parse_type("f32".to_string()), Float(32));
assert_eq!(parse_type("s32".to_string()), Int(32));
}

@ -2,6 +2,8 @@ use crate::parser::Ast;
pub mod backend;
use std::fmt;
#[cfg(test)]
mod tests;
@ -75,6 +77,16 @@ pub enum StorageClass {
Output,
}
impl fmt::Display for StorageClass {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
StorageClass::Undefined => write!(f, "Undefined"),
StorageClass::Input => write!(f, "Input"),
StorageClass::Output => write!(f, "Output"),
}
}
}
#[derive(Debug, PartialEq, Default, Clone)]
pub struct GlobalVariable {
pub name: String,

@ -28,7 +28,7 @@ fn test_compile() {
execution_model: ExecutionModel::Fragment,
execution_mode: ExecutionMode::OriginUpperLeft,
name: "main".to_string(),
interface: vec![":frag-coord".to_string(), ":out-color".to_string()],
interface: vec!["frag-coord".to_string(), "out-color".to_string()],
}],
globals: vec![
GlobalVariable {

Loading…
Cancel
Save