forked from itycodes/shaderc
				
			
							parent
							
								
									db7be30a7a
								
							
						
					
					
						commit
						6cf6beda27
					
				@ -0,0 +1,213 @@
 | 
				
			|||||||
 | 
					use std::fmt::{self, Display, Write};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    compiler::CompilerError,
 | 
				
			||||||
 | 
					    parser::{Location, ParseError},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn print_error<E: FormattedLocatedError>(err: E, src: Option<&str>) {
 | 
				
			||||||
 | 
					    let mut buf = String::new();
 | 
				
			||||||
 | 
					    match src {
 | 
				
			||||||
 | 
					        Some(src) => {
 | 
				
			||||||
 | 
					            err.fmt_with_src(&mut buf, &src).unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        None => err.fmt(&mut buf).unwrap(),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    print!("{buf}");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait FormattedLocatedError {
 | 
				
			||||||
 | 
					    fn fmt<W: fmt::Write>(&self, w: &mut W) -> fmt::Result;
 | 
				
			||||||
 | 
					    fn fmt_with_src<W: fmt::Write>(&self, w: &mut W, src: &str) -> fmt::Result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Display for Location {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Location::Char { line, col } => write!(f, "{line}:{col}"),
 | 
				
			||||||
 | 
					            Location::String { lines, cols } => write!(f, "{}:{}", lines.start(), cols.start()),
 | 
				
			||||||
 | 
					            Location::All => write!(f, "Entire file"),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl FormattedLocatedError for ParseError {
 | 
				
			||||||
 | 
					    fn fmt<W: fmt::Write>(&self, w: &mut W) -> fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            ParseError::UnexpectedParenClose(location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Unexpected closing paren at {location}")?
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ParseError::UnexpectedEof => writeln!(w, "Unexpected end of file")?,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fmt_with_src<W: fmt::Write>(&self, w: &mut W, src: &str) -> fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            ParseError::UnexpectedParenClose(location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Unexpected closing paren at {location}")?;
 | 
				
			||||||
 | 
					                here(location, src, Some("Unexpected ')'".to_string()), w)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ParseError::UnexpectedEof => writeln!(w, "Unexpected end of file")?,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl FormattedLocatedError for CompilerError {
 | 
				
			||||||
 | 
					    fn fmt<W: fmt::Write>(&self, w: &mut W) -> fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            CompilerError::ExpectedSymbol(location) => {
 | 
				
			||||||
 | 
					                writeln!(
 | 
				
			||||||
 | 
					                    w,
 | 
				
			||||||
 | 
					                    "Expected a symbol but got a list or nothing at {location}"
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::ExpectedList(location) => {
 | 
				
			||||||
 | 
					                writeln!(
 | 
				
			||||||
 | 
					                    w,
 | 
				
			||||||
 | 
					                    "Expected a list but got a symbol or nothing at {location}"
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::UnknownKeyword(k, location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected keyword {k} at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected one of: module, import, bind, dec, entry, fun")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::ExpectedOneOf(vec, k, location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected token {k} at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected one of: {}", vec.join(", "))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::TrailingTokens(location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected trailing tokens at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected end of list")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::UnknownBind(b, location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected keyword {b} at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected one of: BuiltIn, Location")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::ExpectedType(location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Expected name:type but got name at {location}")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fmt_with_src<W: fmt::Write>(&self, w: &mut W, src: &str) -> fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            CompilerError::ExpectedSymbol(location) => {
 | 
				
			||||||
 | 
					                writeln!(
 | 
				
			||||||
 | 
					                    w,
 | 
				
			||||||
 | 
					                    "Expected a symbol but got a list or nothing at {location}"
 | 
				
			||||||
 | 
					                )?;
 | 
				
			||||||
 | 
					                here(location, src, Some("Expected symbol".to_string()), w)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::ExpectedList(location) => {
 | 
				
			||||||
 | 
					                writeln!(
 | 
				
			||||||
 | 
					                    w,
 | 
				
			||||||
 | 
					                    "Expected a list but got a symbol or nothing at {location}"
 | 
				
			||||||
 | 
					                )?;
 | 
				
			||||||
 | 
					                here(location, src, Some("Expected List".to_string()), w)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::UnknownKeyword(k, location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected keyword {k} at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected one of: module, import, bind, dec, entry, fun")?;
 | 
				
			||||||
 | 
					                here(location, src, Some("Unexpected keyword".to_string()), w)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::ExpectedOneOf(vec, k, location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected token {k} at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected one of: {}", vec.join(", "))?;
 | 
				
			||||||
 | 
					                here(location, src, Some("Unexpected token".to_string()), w)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::TrailingTokens(location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected trailing tokens at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected end of list")?;
 | 
				
			||||||
 | 
					                here(location, src, Some("Unexpected token".to_string()), w)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::UnknownBind(b, location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Got unexpected keyword {b} at {location}")?;
 | 
				
			||||||
 | 
					                writeln!(w, "Expected one of: BuiltIn, Location")?;
 | 
				
			||||||
 | 
					                here(location, src, Some("Unexpected keyword".to_string()), w)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            CompilerError::ExpectedType(location) => {
 | 
				
			||||||
 | 
					                writeln!(w, "Expected name:type but got name at {location}")?;
 | 
				
			||||||
 | 
					                here(location, src, None, w)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn here<W: fmt::Write>(
 | 
				
			||||||
 | 
					    loc: &Location,
 | 
				
			||||||
 | 
					    src: &str,
 | 
				
			||||||
 | 
					    comment: Option<String>,
 | 
				
			||||||
 | 
					    w: &mut W,
 | 
				
			||||||
 | 
					) -> fmt::Result {
 | 
				
			||||||
 | 
					    writeln!(w, "Here:")?;
 | 
				
			||||||
 | 
					    writeln!(
 | 
				
			||||||
 | 
					        w,
 | 
				
			||||||
 | 
					        "{}",
 | 
				
			||||||
 | 
					        annotate_src(&loc, src, comment.unwrap_or_default())
 | 
				
			||||||
 | 
					    )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn annotate_src(loc: &Location, src: &str, comment: String) -> String {
 | 
				
			||||||
 | 
					    let src_lines = src.split('\n').collect::<Vec<_>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut buf = String::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match loc {
 | 
				
			||||||
 | 
					        Location::Char { line, col } => {
 | 
				
			||||||
 | 
					            writeln!(buf, "{}|{}", line_num(*line - 1), src_lines[*line - 2]).unwrap();
 | 
				
			||||||
 | 
					            writeln!(buf, "{}|{}", line_num(*line), src_lines[*line - 1]).unwrap();
 | 
				
			||||||
 | 
					            writeln!(buf, "{}|{}^ {}", "      ", " ".repeat(col - 1), comment).unwrap();
 | 
				
			||||||
 | 
					            writeln!(buf, "{}|{}", line_num(*line + 1), src_lines[*line]).unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Location::String { lines, cols } => {
 | 
				
			||||||
 | 
					            writeln!(
 | 
				
			||||||
 | 
					                buf,
 | 
				
			||||||
 | 
					                "{}|{}",
 | 
				
			||||||
 | 
					                line_num(*lines.start() - 1),
 | 
				
			||||||
 | 
					                src_lines[*lines.start() - 2]
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					            writeln!(
 | 
				
			||||||
 | 
					                buf,
 | 
				
			||||||
 | 
					                "{}",
 | 
				
			||||||
 | 
					                src_lines[(lines.start() - 1)..*lines.end()]
 | 
				
			||||||
 | 
					                    .iter()
 | 
				
			||||||
 | 
					                    .zip(lines.clone())
 | 
				
			||||||
 | 
					                    .map(|(l, n)| format!("{}|{}", line_num(n), l))
 | 
				
			||||||
 | 
					                    .collect::<Vec<_>>()
 | 
				
			||||||
 | 
					                    .join("\n")
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					            writeln!(
 | 
				
			||||||
 | 
					                buf,
 | 
				
			||||||
 | 
					                "{}|{}{} {}",
 | 
				
			||||||
 | 
					                "      ",
 | 
				
			||||||
 | 
					                " ".repeat(cols.start() - 1),
 | 
				
			||||||
 | 
					                "^".repeat(cols.end() - cols.start() + 1),
 | 
				
			||||||
 | 
					                comment
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					            writeln!(
 | 
				
			||||||
 | 
					                buf,
 | 
				
			||||||
 | 
					                "{}|{}",
 | 
				
			||||||
 | 
					                line_num(*lines.end() + 1),
 | 
				
			||||||
 | 
					                src_lines[*lines.end()]
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Location::All => todo!(),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    buf
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn line_num(num: usize) -> String {
 | 
				
			||||||
 | 
					    let num = format!("{num}");
 | 
				
			||||||
 | 
					    format!("{num}{}", " ".repeat(6 - num.len()))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,115 +1,219 @@
 | 
				
			|||||||
use std::fmt::Write;
 | 
					use compiler::{backend::spirv_meta, meta_compile};
 | 
				
			||||||
 | 
					use error::print_error;
 | 
				
			||||||
 | 
					use std::{env, fs, path::PathBuf};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use parser::parse_string;
 | 
				
			||||||
pub mod compiler;
 | 
					pub mod compiler;
 | 
				
			||||||
 | 
					mod error;
 | 
				
			||||||
pub mod parser;
 | 
					pub mod parser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Default)]
 | 
				
			||||||
 | 
					struct CompilerArgs {
 | 
				
			||||||
 | 
					    input: Option<PathBuf>,
 | 
				
			||||||
 | 
					    output: Option<PathBuf>,
 | 
				
			||||||
 | 
					    print_help: bool,
 | 
				
			||||||
 | 
					    print_version: bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SPIRV_VERSION: &'static str = "1.0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    let mut ops: Vec<(Option<String>, Vec<String>)> = Vec::new();
 | 
					    let args = parse_args();
 | 
				
			||||||
 | 
					    if args.print_version || args.print_help {
 | 
				
			||||||
    //    OpMemoryModel Logical GLSL450
 | 
					        if args.print_help {
 | 
				
			||||||
    //    OpEntryPoint Fragment %main "main"
 | 
					            print_help();
 | 
				
			||||||
    //    OpExecutionMode %main OriginUpperLeft
 | 
					        }
 | 
				
			||||||
    //    OpSource GLSL 450
 | 
					        if args.print_version {
 | 
				
			||||||
    //    OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
 | 
					            print_version();
 | 
				
			||||||
    //    OpSourceExtension "GL_GOOGLE_include_directive"
 | 
					        }
 | 
				
			||||||
    //    OpName %main "main"
 | 
					        return;
 | 
				
			||||||
    //%void = OpTypeVoid
 | 
					    }
 | 
				
			||||||
    //%3 = OpTypeFunction %void
 | 
					
 | 
				
			||||||
    //%main = OpFunction %void None %3
 | 
					    let Some(input) = args.input else {
 | 
				
			||||||
    //%5 = OpLabel
 | 
					        eprintln!("No input specified");
 | 
				
			||||||
    //    OpReturn
 | 
					        return;
 | 
				
			||||||
    //    OpFunctionEnd
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ops.push((None, vec!["OpCapability".to_string(), "Shader".to_string()]));
 | 
					    let output = args.output.unwrap_or(PathBuf::from("./out.spv"));
 | 
				
			||||||
    ops.push((
 | 
					
 | 
				
			||||||
        Some("%1".to_string()),
 | 
					    let src = match fs::read_to_string(input) {
 | 
				
			||||||
        vec![
 | 
					        Ok(i) => i,
 | 
				
			||||||
            "OpExtInstImport".to_string(),
 | 
					        Err(e) => {
 | 
				
			||||||
            "\"GLSL.std.450\"".to_string(),
 | 
					            eprintln!("{e}");
 | 
				
			||||||
        ],
 | 
					            return;
 | 
				
			||||||
    ));
 | 
					        }
 | 
				
			||||||
    ops.push((
 | 
					    };
 | 
				
			||||||
        None,
 | 
					
 | 
				
			||||||
        vec![
 | 
					    let ast = match parse_string(&src) {
 | 
				
			||||||
            "OpMemoryModel".to_string(),
 | 
					        Ok(i) => i,
 | 
				
			||||||
            "Logical".to_string(),
 | 
					        Err(e) => {
 | 
				
			||||||
            "GLSL450".to_string(),
 | 
					            print_error(e, Some(&src));
 | 
				
			||||||
        ],
 | 
					            return;
 | 
				
			||||||
    ));
 | 
					        }
 | 
				
			||||||
    ops.push((
 | 
					    };
 | 
				
			||||||
        None,
 | 
					
 | 
				
			||||||
        vec![
 | 
					    let module = match meta_compile(ast) {
 | 
				
			||||||
            "OpEntryPoint".to_string(),
 | 
					        Ok(m) => m,
 | 
				
			||||||
            "Fragment".to_string(),
 | 
					        Err(e) => {
 | 
				
			||||||
            "%main".to_string(),
 | 
					            print_error(e, Some(&src));
 | 
				
			||||||
            "\"main\"".to_string(),
 | 
					            return;
 | 
				
			||||||
        ],
 | 
					        }
 | 
				
			||||||
    ));
 | 
					    };
 | 
				
			||||||
    ops.push((
 | 
					
 | 
				
			||||||
        None,
 | 
					    let res = spirv_meta(module);
 | 
				
			||||||
        vec![
 | 
					
 | 
				
			||||||
            "OpExecutionMode".to_string(),
 | 
					    fs::write(output, res).unwrap();
 | 
				
			||||||
            "%main".to_string(),
 | 
					}
 | 
				
			||||||
            "OriginUpperLeft".to_string(),
 | 
					
 | 
				
			||||||
        ],
 | 
					fn parse_args() -> CompilerArgs {
 | 
				
			||||||
    ));
 | 
					    let mut args = env::args();
 | 
				
			||||||
    ops.push((
 | 
					
 | 
				
			||||||
        None,
 | 
					    let _prog = args.next().unwrap();
 | 
				
			||||||
        vec![
 | 
					
 | 
				
			||||||
            "OpSource".to_string(),
 | 
					    let mut parsed_args = CompilerArgs::default();
 | 
				
			||||||
            "GLSL".to_string(),
 | 
					
 | 
				
			||||||
            "450".to_string(),
 | 
					    while let Some(arg) = args.next() {
 | 
				
			||||||
        ],
 | 
					        if let Some(arg) = arg.strip_prefix("--") {
 | 
				
			||||||
    ));
 | 
					            match arg {
 | 
				
			||||||
    ops.push((
 | 
					                "help" => parsed_args.print_help = true,
 | 
				
			||||||
        None,
 | 
					                "version" => parsed_args.print_version = true,
 | 
				
			||||||
        vec![
 | 
					                "input" => {
 | 
				
			||||||
            "OpSourceExtension".to_string(),
 | 
					                    if parsed_args.input.is_none() {
 | 
				
			||||||
            "\"GL_GOOGLE_cpp_style_line_directive\"".to_string(),
 | 
					                        let Some(input) = args.next() else {
 | 
				
			||||||
        ],
 | 
					                            eprintln!("input needs a file");
 | 
				
			||||||
    ));
 | 
					                            eprintln!();
 | 
				
			||||||
    ops.push((
 | 
					                            parsed_args.print_help = true;
 | 
				
			||||||
        None,
 | 
					                            return parsed_args;
 | 
				
			||||||
        vec![
 | 
					                        };
 | 
				
			||||||
            "OpSourceExtension".to_string(),
 | 
					
 | 
				
			||||||
            "\"GL_GOOGLE_include_directive\"".to_string(),
 | 
					                        parsed_args.input = Some(PathBuf::from(input));
 | 
				
			||||||
        ],
 | 
					                    } else {
 | 
				
			||||||
    ));
 | 
					                        eprintln!("input can be passed only once");
 | 
				
			||||||
    ops.push((
 | 
					                        eprintln!();
 | 
				
			||||||
        None,
 | 
					                        parsed_args.print_help = true;
 | 
				
			||||||
        vec![
 | 
					                        return parsed_args;
 | 
				
			||||||
            "OpName".to_string(),
 | 
					                    }
 | 
				
			||||||
            "%main".to_string(),
 | 
					                }
 | 
				
			||||||
            "\"main\"".to_string(),
 | 
					                "output" => {
 | 
				
			||||||
        ],
 | 
					                    if parsed_args.output.is_none() {
 | 
				
			||||||
    ));
 | 
					                        let Some(output) = args.next() else {
 | 
				
			||||||
    ops.push((Some("%void".to_string()), vec!["OpTypeVoid".to_string()]));
 | 
					                            parsed_args.print_help = true;
 | 
				
			||||||
    ops.push((
 | 
					                            eprintln!("output needs a file");
 | 
				
			||||||
        Some("%3".to_string()),
 | 
					                            eprintln!();
 | 
				
			||||||
        vec!["OpTypeFunction".to_string(), "%void".to_string()],
 | 
					                            return parsed_args;
 | 
				
			||||||
    ));
 | 
					                        };
 | 
				
			||||||
    ops.push((
 | 
					
 | 
				
			||||||
        Some("%main".to_string()),
 | 
					                        parsed_args.output = Some(PathBuf::from(output));
 | 
				
			||||||
        vec![
 | 
					                    } else {
 | 
				
			||||||
            "OpFunction".to_string(),
 | 
					                        eprintln!("output can be passed only once");
 | 
				
			||||||
            "%void".to_string(),
 | 
					                        eprintln!();
 | 
				
			||||||
            "None".to_string(),
 | 
					                        parsed_args.print_help = true;
 | 
				
			||||||
            "%3".to_string(),
 | 
					                        return parsed_args;
 | 
				
			||||||
        ],
 | 
					                    }
 | 
				
			||||||
    ));
 | 
					                }
 | 
				
			||||||
    ops.push((Some("%5".to_string()), vec!["OpLabel".to_string()]));
 | 
					                a => {
 | 
				
			||||||
    ops.push((None, vec!["OpReturn".to_string()]));
 | 
					                    eprintln!("unknown arg --{a}");
 | 
				
			||||||
    ops.push((None, vec!["OpFunctionEnd".to_string()]));
 | 
					                    eprintln!();
 | 
				
			||||||
 | 
					                    parsed_args.print_help = true;
 | 
				
			||||||
    let mut out: String = String::new();
 | 
					                    return parsed_args;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
    for op in ops {
 | 
					            }
 | 
				
			||||||
        if op.0.is_some() {
 | 
					            continue;
 | 
				
			||||||
            write!(out, "{} = ", op.0.unwrap()).unwrap();
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
        for arg in op.1 {
 | 
					        if let Some(arg) = arg.strip_prefix("-") {
 | 
				
			||||||
            write!(out, "{} ", arg).unwrap();
 | 
					            let mut chars = arg.chars();
 | 
				
			||||||
        }
 | 
					            while let Some(arg) = chars.next() {
 | 
				
			||||||
        writeln!(out).unwrap();
 | 
					                match arg {
 | 
				
			||||||
    }
 | 
					                    'i' => {
 | 
				
			||||||
    println!("{}", out);
 | 
					                        if chars.next().is_some() {
 | 
				
			||||||
 | 
					                            parsed_args.print_help = true;
 | 
				
			||||||
 | 
					                            eprintln!("-i needs to be last in combined args");
 | 
				
			||||||
 | 
					                            return parsed_args;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if parsed_args.input.is_none() {
 | 
				
			||||||
 | 
					                            let Some(input) = args.next() else {
 | 
				
			||||||
 | 
					                                eprintln!("input needs a file");
 | 
				
			||||||
 | 
					                                eprintln!();
 | 
				
			||||||
 | 
					                                parsed_args.print_help = true;
 | 
				
			||||||
 | 
					                                return parsed_args;
 | 
				
			||||||
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            parsed_args.input = Some(PathBuf::from(input));
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            eprintln!("input can be passed only once");
 | 
				
			||||||
 | 
					                            eprintln!();
 | 
				
			||||||
 | 
					                            parsed_args.print_help = true;
 | 
				
			||||||
 | 
					                            return parsed_args;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    'o' => {
 | 
				
			||||||
 | 
					                        if chars.next().is_some() {
 | 
				
			||||||
 | 
					                            parsed_args.print_help = true;
 | 
				
			||||||
 | 
					                            eprintln!("-o needs to be last in combined args");
 | 
				
			||||||
 | 
					                            eprintln!();
 | 
				
			||||||
 | 
					                            return parsed_args;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if parsed_args.output.is_none() {
 | 
				
			||||||
 | 
					                            let Some(output) = args.next() else {
 | 
				
			||||||
 | 
					                                parsed_args.print_help = true;
 | 
				
			||||||
 | 
					                                eprintln!("output needs a file");
 | 
				
			||||||
 | 
					                                return parsed_args;
 | 
				
			||||||
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            parsed_args.output = Some(PathBuf::from(output));
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            eprintln!("output can be passed only once");
 | 
				
			||||||
 | 
					                            eprintln!();
 | 
				
			||||||
 | 
					                            parsed_args.print_help = true;
 | 
				
			||||||
 | 
					                            return parsed_args;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    'h' => parsed_args.print_help = true,
 | 
				
			||||||
 | 
					                    'v' => parsed_args.print_version = true,
 | 
				
			||||||
 | 
					                    a => {
 | 
				
			||||||
 | 
					                        eprintln!("unknown arg -{a}");
 | 
				
			||||||
 | 
					                        eprintln!();
 | 
				
			||||||
 | 
					                        parsed_args.print_help = true;
 | 
				
			||||||
 | 
					                        return parsed_args;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        eprintln!("unknown arg {arg}");
 | 
				
			||||||
 | 
					        eprintln!();
 | 
				
			||||||
 | 
					        parsed_args.print_help = true;
 | 
				
			||||||
 | 
					        return parsed_args;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parsed_args
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn print_help() {
 | 
				
			||||||
 | 
					    println!("-- ShaderC shader compiler --");
 | 
				
			||||||
 | 
					    println!();
 | 
				
			||||||
 | 
					    println!("Arguments:");
 | 
				
			||||||
 | 
					    println!("\t-i --input:");
 | 
				
			||||||
 | 
					    println!("\t\tThe shader to be parsed and compiled, manadory argument");
 | 
				
			||||||
 | 
					    println!();
 | 
				
			||||||
 | 
					    println!("\t-o --output:");
 | 
				
			||||||
 | 
					    println!("\t\tWhere to output the compiled spirv assembly to, default: out.spv");
 | 
				
			||||||
 | 
					    println!();
 | 
				
			||||||
 | 
					    println!("\t-h --help:");
 | 
				
			||||||
 | 
					    println!("\t\tPrint this and exit");
 | 
				
			||||||
 | 
					    println!("\t-v --version:");
 | 
				
			||||||
 | 
					    println!("\t\tPrint the compilers version");
 | 
				
			||||||
 | 
					    println!();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn print_version() {
 | 
				
			||||||
 | 
					    println!(
 | 
				
			||||||
 | 
					        "ShaderC version: {}; SPIR-V version: {}",
 | 
				
			||||||
 | 
					        env!("CARGO_PKG_VERSION"),
 | 
				
			||||||
 | 
					        SPIRV_VERSION
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					(module Shader Logical GLSL450)
 | 
				
			||||||
 | 
					(import :std GLSL.std.450)
 | 
				
			||||||
 | 
					(bind (frag-coord:*v4f32i) (BuiltIn FragCoord))
 | 
				
			||||||
 | 
					(bind (out-color:*v4f32o) (Location 0))
 | 
				
			||||||
 | 
					(dec frag-coord:*v4f32i Input)
 | 
				
			||||||
 | 
					(decr out-color:*v4f32o Output)
 | 
				
			||||||
 | 
					(entry main Fragment OriginUpperLeft (:frag-coord :out-color))
 | 
				
			||||||
 | 
					(fun (main)
 | 
				
			||||||
 | 
					  (store-ptr (out-color)
 | 
				
			||||||
 | 
					    (v4f32i (/ (.xy (load-ptr frag-coord))
 | 
				
			||||||
 | 
					               (v2f32 1920.0 1080.0)) 
 | 
				
			||||||
 | 
					            1.0 
 | 
				
			||||||
 | 
					            1.0)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					OpCapability Shader 
 | 
				
			||||||
 | 
					OpMemoryModel Logical GLSL450 
 | 
				
			||||||
 | 
					OpEntryPoint Fragment %main "main" %frag_coord %out_color 
 | 
				
			||||||
 | 
					OpExecutionMode %main OriginUpperLeft 
 | 
				
			||||||
 | 
					%f32 = OpTypeFloat 32 
 | 
				
			||||||
 | 
					%v4f32 = OpTypeVector %f32 4 
 | 
				
			||||||
 | 
					%pv4f32i = OpTypePointer Input %v4f32 
 | 
				
			||||||
 | 
					%frag_coord = OpVariable %pv4f32i Input 
 | 
				
			||||||
 | 
					OpDecorate %frag_coord BuiltIn FragCoord 
 | 
				
			||||||
 | 
					%pv4f32o = OpTypePointer Output %v4f32 
 | 
				
			||||||
 | 
					%out_color = OpVariable %pv4f32o Output 
 | 
				
			||||||
 | 
					OpDecorate %out_color Location 0 
 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue