use crate::{ compiler::{CompilerError, meta_compile}, parser::{Location, parse, tokenize}, }; #[test] fn test_compile() { use crate::compiler::*; let src = " (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) (dec out-color:*v4f32o Output) (entry main Fragment OriginUpperLeft (:frag-coord :out-color)) (fun (main) :void (store-ptr (out-color) (v4f32i (/ (.xy (load-ptr frag-coord)) (v2f32 1920.0 1080.0)) 1.0 1.0))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()).unwrap(); println!("{:#?}", module); let test_module = Module { capabilities: vec![Capability::Shader], entry_points: vec![EntryPoint { execution_model: ExecutionModel::Fragment, execution_mode: ExecutionMode::OriginUpperLeft, name: "main".to_string(), interface: vec!["frag-coord".to_string(), "out-color".to_string()], }], globals: vec![ GlobalVariable { name: "frag-coord".to_string(), typ: "*v4f32i".to_string(), storage_class: StorageClass::Input, decorations: vec![Decoration::BuiltIn(BuiltinDecoration::FragCoord)], }, GlobalVariable { name: "out-color".to_string(), typ: "*v4f32o".to_string(), storage_class: StorageClass::Output, decorations: vec![Decoration::Location(0)], }, ], functions: vec![Function { name: "main".to_string(), return_type: "void".to_string(), arguments: vec![], body: Some(vec![]), ast: Some(Ast::List(Localised::dummy_location(vec![Ast::List( Localised::dummy_location(vec![ Ast::Symbol(Localised::dummy_location("store-ptr".to_string())), Ast::List(Localised::dummy_location(vec![Ast::Symbol( Localised::dummy_location("out-color".to_string()), )])), Ast::List(Localised::dummy_location(vec![ Ast::Symbol(Localised::dummy_location("v4f32i".to_string())), Ast::List(Localised::dummy_location(vec![ Ast::Symbol(Localised::dummy_location("/".to_string())), Ast::List(Localised::dummy_location(vec![ Ast::Symbol(Localised::dummy_location(".xy".to_string())), Ast::List(Localised::dummy_location(vec![ Ast::Symbol(Localised::dummy_location("load-ptr".to_string())), Ast::Symbol(Localised::dummy_location( "frag-coord".to_string(), )), ])), ])), Ast::List(Localised::dummy_location(vec![ Ast::Symbol(Localised::dummy_location("v2f32".to_string())), Ast::Symbol(Localised::dummy_location("1920.0".to_string())), Ast::Symbol(Localised::dummy_location("1080.0".to_string())), ])), ])), Ast::Symbol(Localised::dummy_location("1.0".to_string())), Ast::Symbol(Localised::dummy_location("1.0".to_string())), ])), ]), )]))), }], memory_model: Memory { addressing_model: AddressingModel::Logical, memory_model: MemoryModel::GLSL450, }, imports: vec![Import { name: ":std".to_string(), value: "GLSL.std.450".to_string(), }], }; dbg!(&module); dbg!(&test_module); assert_eq!(module, test_module); } #[test] fn expected_symbol() { let src = " (module Shader Logical ) (import :std GLSL.std.450) (bind (frag-coord:*v4f32i) (BuiltIn FragCoord)) (bind (out-color:*v4f32o) (Location 0)) (dec frag-coord:*v4f32i Input) (dec out-color:*v4f32o Output) (entry main Fragment OriginUpperLeft (:frag-coord :out-color)) (fun (main) :void (store-ptr (out-color) (v4f32i (/ (.xy (load-ptr frag-coord)) (v2f32 1920.0 1080.0)) 1.0 1.0))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()); assert!(matches!( module, Err(CompilerError::ExpectedSymbol(Location::Char { line: 2, col: 24 })) )) } #[test] fn expected_list() { let src = " (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) (dec 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))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()); let Err(CompilerError::ExpectedList(Location::String { lines, cols })) = module else { panic!() }; assert_eq!(lines, 9..=9); assert_eq!(cols, 6..=9); } #[test] fn unknown_keyword() { let src = " (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) (dec out-color:*v4f32o Output) (entry main Fragment OriginUpperLeft (:frag-coord :out-color)) (fum (main) (store-ptr (out-color) (v4f32i (/ (.xy (load-ptr frag-coord)) (v2f32 1920.0 1080.0)) 1.0 1.0))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()); let Err(CompilerError::UnknownKeyword(kw, Location::String { lines, cols })) = module else { panic!() }; assert_eq!(kw, "fum".to_string()); assert_eq!(lines, 9..=9); assert_eq!(cols, 2..=4); } #[test] fn expected_one_of() { let src = " (module Shader Loical GLSL450) (import :std GLSL.std.450) (bind (frag-coord:*v4f32i) (BuiltIn FragCoord)) (bind (out-color:*v4f32o) (Location 0)) (dec frag-coord:*v4f32i Input) (dec 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))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()); let Err(CompilerError::ExpectedOneOf(l, kw, Location::String { lines, cols })) = module else { panic!() }; assert_eq!(l, vec!["Logical".to_string()]); assert_eq!(kw, "Loical".to_string()); assert_eq!(lines, 2..=2); assert_eq!(cols, 16..=21); } #[test] fn trailing_tokens() { let src = " (module Shader Logical GLSL450 GLSL451) (import :std GLSL.std.450) (bind (frag-coord:*v4f32i) (BuiltIn FragCoord)) (bind (out-color:*v4f32o) (Location 0)) (dec frag-coord:*v4f32i Input) (dec 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))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()); let Err(CompilerError::TrailingTokens(Location::String { lines, cols })) = module else { panic!() }; assert_eq!(lines, 2..=2); assert_eq!(cols, 32..=38); } #[test] fn unknown_bind() { let src = " (module Shader Logical GLSL450) (import :std GLSL.std.450) (bind (frag-coord:*v4f32i) (BuiltIm FragCoord)) (bind (out-color:*v4f32o) (Location 0)) (dec frag-coord:*v4f32i Input) (dec 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))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()); dbg!(&module); let Err(CompilerError::UnknownBind(b, Location::String { lines, cols })) = module else { panic!() }; assert_eq!(b, "BuiltIm"); assert_eq!(lines, 4..=4); assert_eq!(cols, 28..=46); } #[test] fn expected_type() { let src = " (module Shader Logical GLSL450) (import :std GLSL.std.450) (bind (frag-coord) (BuiltIn FragCoord)) (bind (out-color:*v4f32o) (Location 0)) (dec frag-coord:*v4f32i Input) (dec 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))) "; let ast = parse(tokenize(src)); println!("{:#?}", ast); let module = meta_compile(ast.unwrap()); dbg!(&module); let Err(CompilerError::ExpectedType(Location::Char { line: 4, col: 18 })) = module else { panic!() }; }