diff --git a/src/compiler/backend/tests.rs b/src/compiler/backend/tests.rs index 0f21e2f..4252995 100644 --- a/src/compiler/backend/tests.rs +++ b/src/compiler/backend/tests.rs @@ -1,8 +1,8 @@ #[test] fn test_emit() { + use crate::compiler::backend::*; use crate::compiler::*; use crate::parser::*; - use crate::compiler::backend::*; let src = " (module Shader Logical GLSL450) (import :std GLSL.std.450) @@ -18,8 +18,8 @@ fn test_emit() { 1.0 1.0))) "; - let mut ast = parse(tokenize(src)); - let module = meta_compile(&mut ast); + let ast = parse(tokenize(src)); + let module = meta_compile(&mut ast.unwrap()); let res = spirv_meta(module); println!("{}", res); } @@ -28,12 +28,24 @@ fn test_emit() { 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(&"*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)); -} \ No newline at end of file +} diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 140a57a..8635d0c 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -1,4 +1,4 @@ -use crate::parser::Ast; +use crate::parser::{Ast, Localised, Location}; pub mod backend; @@ -10,13 +10,13 @@ mod tests; #[derive(Debug, PartialEq, Default, Clone)] pub enum Capability { #[default] - Shader + Shader, } #[derive(Debug, PartialEq, Default, Clone)] pub enum ExecutionMode { #[default] - OriginUpperLeft + OriginUpperLeft, } #[derive(Debug, PartialEq, Default, Clone)] @@ -40,7 +40,7 @@ pub enum AddressingModel { Logical, Physical32, Physical64, - PhysicalStorageBuffer64 + PhysicalStorageBuffer64, } #[derive(Debug, PartialEq, Default, Clone)] pub enum MemoryModel { @@ -48,7 +48,7 @@ pub enum MemoryModel { GLSL450, OpenCL, VulkanKHR, - Simple + Simple, } #[derive(Debug, PartialEq, Default, Clone)] @@ -147,9 +147,9 @@ pub fn meta_compile(ast: &mut Ast) -> Module { memory_model: MemoryModel::GLSL450, }; module.capabilities.push(Capability::Shader); - assert_eq!(exec, Ast::Symbol("Logical".to_string())); - assert_eq!(memory, Ast::Symbol("GLSL450".to_string())); - assert_eq!(cap, Ast::Symbol("Shader".to_string())); + assert_eq!(exec.symbol(), Some("Logical".to_string())); + assert_eq!(memory.symbol(), Some("GLSL450".to_string())); + assert_eq!(cap.symbol(), Some("Shader".to_string())); } "import" => { let name = match &list[1] { @@ -170,28 +170,38 @@ pub fn meta_compile(ast: &mut Ast) -> Module { Ast::List(l) => l, _ => panic!("Expected list! {:?}", list[1]), }; - let name_and_type: String = name_and_type.iter().map(|x| { - match x { + let name_and_type: String = name_and_type + .iter() + .map(|x| match x { Ast::Symbol(s) => s.to_string(), _ => panic!("Expected symbol! {:?}", x), - } - }).collect(); + }) + .collect(); // name_and_type is of the name:type format, like foo:f32 - let name: String = name_and_type.split(":").collect::<Vec<&str>>()[0].to_string(); - let typ: String = name_and_type.split(":").collect::<Vec<&str>>()[1].to_string(); + let name: String = + name_and_type.split(":").collect::<Vec<&str>>()[0] + .to_string(); + let typ: String = + name_and_type.split(":").collect::<Vec<&str>>()[1] + .to_string(); let bind = match &list[2] { Ast::List(l) => l, _ => panic!("Expected list! {:?}", list[2]), }; - let bind: Vec<String> = bind.iter().map(|x| { - match x { + let bind: Vec<String> = bind + .iter() + .map(|x| match x { Ast::Symbol(s) => s.to_string(), _ => panic!("Expected symbol! {:?}", x), - } - }).collect(); + }) + .collect(); let bind_name = match bind[0].as_str() { - "BuiltIn" => Decoration::BuiltIn(BuiltinDecoration::FragCoord), - "Location" => Decoration::Location(bind[1].parse::<u32>().unwrap()), + "BuiltIn" => { + Decoration::BuiltIn(BuiltinDecoration::FragCoord) + } + "Location" => Decoration::Location( + bind[1].parse::<u32>().unwrap(), + ), _ => panic!("Unknown bind! {:?}", bind), }; let mut exists = false; @@ -214,8 +224,12 @@ pub fn meta_compile(ast: &mut Ast) -> Module { Ast::Symbol(s) => s, _ => panic!("Expected symbol! {:?}", list[1]), }; - let name: String = name_and_type.split(":").collect::<Vec<&str>>()[0].to_string(); - let typ: String = name_and_type.split(":").collect::<Vec<&str>>()[1].to_string(); + let name: String = + name_and_type.split(":").collect::<Vec<&str>>()[0] + .to_string(); + let typ: String = + name_and_type.split(":").collect::<Vec<&str>>()[1] + .to_string(); let storage_class = match &list[2] { Ast::Symbol(s) => s, _ => panic!("Expected symbol! {:?}", list[2]), @@ -240,9 +254,12 @@ pub fn meta_compile(ast: &mut Ast) -> Module { }); } if exists { - module.globals.iter_mut() + module + .globals + .iter_mut() .find(|x| x.name.as_str() == name.as_str()) - .unwrap().storage_class = storage_class.clone(); + .unwrap() + .storage_class = storage_class.clone(); } } "entry" => { @@ -262,22 +279,21 @@ pub fn meta_compile(ast: &mut Ast) -> Module { Ast::List(l) => l, _ => panic!("Expected list! {:?}", list[4]), }; - let interface: Vec<String> = interface.iter().map(|x| { - match x { - Ast::Symbol(s) => { - s.to_string().replace(":", "") - }, + let interface: Vec<String> = interface + .iter() + .map(|x| match x { + Ast::Symbol(s) => s.to_string().replace(":", ""), _ => panic!("Expected symbol! {:?}", x), - } - }).collect(); + }) + .collect(); module.entry_points.push(EntryPoint { execution_model: ExecutionModel::Fragment, execution_mode: ExecutionMode::OriginUpperLeft, name: name.to_string(), interface: interface, }); - assert_eq!(exec_model, "Fragment"); - assert_eq!(exec_mode, "OriginUpperLeft"); + assert_eq!(**exec_model, "Fragment"); + assert_eq!(**exec_mode, "OriginUpperLeft"); } "fun" => { let name = match &list[1] { @@ -289,12 +305,23 @@ pub fn meta_compile(ast: &mut Ast) -> Module { _ => panic!("Expected symbol! {:?}", name), }; let body = list[2..].to_vec(); + let location = if let (Some(s), Some(e)) = ( + body.first().map(|a| a.location()).flatten(), + body.last().map(|a| a.location()).flatten(), + ) { + Location::range(s, e) + } else { + Location::Char { line: 0, col: 0 } + }; let fun = Function { name: name.to_string(), return_type: "void".to_string(), arguments: vec![], body: Some(vec![]), - ast: Some(Ast::List(body)), + ast: Some(Ast::List(Localised { + location, + item: body, + })), }; module.functions.push(fun); } @@ -308,7 +335,8 @@ pub fn meta_compile(ast: &mut Ast) -> Module { } } } - _ => panic!("Non-root ast") + _ => panic!("Non-root ast"), } module -} \ No newline at end of file +} + diff --git a/src/compiler/tests.rs b/src/compiler/tests.rs index 33398bd..a7c7e13 100644 --- a/src/compiler/tests.rs +++ b/src/compiler/tests.rs @@ -1,4 +1,4 @@ -use crate::parser::{tokenize, parse}; +use crate::parser::{parse, tokenize}; #[test] fn test_compile() { @@ -18,9 +18,9 @@ fn test_compile() { 1.0 1.0))) "; - let mut ast = parse(tokenize(src)); + let ast = parse(tokenize(src)); println!("{:#?}", ast); - let module = meta_compile(&mut ast); + let module = meta_compile(&mut ast.unwrap()); println!("{:#?}", module); let test_module = Module { capabilities: vec![Capability::Shader], @@ -49,25 +49,36 @@ fn test_compile() { return_type: "void".to_string(), arguments: vec![], body: Some(vec![]), - ast: Some(Ast::List(vec![ - Ast::List(vec![ - Ast::Symbol("store-ptr".to_string()), - Ast::List(vec![Ast::Symbol("out-color".to_string())]), - Ast::List(vec![ - Ast::Symbol("v4f32i".to_string()), - Ast::List(vec![ - Ast::Symbol("/".to_string()), - Ast::List(vec![ - Ast::Symbol(".xy".to_string()), - Ast::List(vec![Ast::Symbol("load-ptr".to_string()), Ast::Symbol("frag-coord".to_string())]), - ]), - Ast::List(vec![Ast::Symbol("v2f32".to_string()), Ast::Symbol("1920.0".to_string()), Ast::Symbol("1080.0".to_string())]), - ]), - Ast::Symbol("1.0".to_string()), - Ast::Symbol("1.0".to_string()), - ]), + 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, @@ -78,5 +89,8 @@ fn test_compile() { value: "GLSL.std.450".to_string(), }], }; + dbg!(&module); + dbg!(&test_module); assert_eq!(module, test_module); -} \ No newline at end of file +} + diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 427f1f6..f7b9a58 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -2,11 +2,11 @@ mod tests; use std::iter::Peekable; -use std::ops::RangeInclusive; +use std::ops::{Deref, RangeInclusive}; use std::vec::IntoIter; #[derive(Clone, Debug)] -enum Location { +pub enum Location { Char { line: usize, col: usize, @@ -68,9 +68,9 @@ impl Location { } #[derive(Debug, Clone)] -struct Localised<T: Clone> { - location: Location, - item: T, +pub struct Localised<T: Clone> { + pub location: Location, + pub item: T, } impl<T: Clone> Localised<T> { @@ -83,6 +83,14 @@ impl<T: Clone> Localised<T> { } } +impl<T: Clone> Deref for Localised<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.item + } +} + impl<T: PartialEq + Clone> PartialEq for Localised<T> { fn eq(&self, other: &Self) -> bool { self.item.eq(&other.item) @@ -103,6 +111,23 @@ pub enum Ast { Root(Vec<Ast>), } +impl Ast { + pub fn symbol(self) -> Option<String> { + match self { + Ast::Symbol(Localised { item, .. }) => Some(item), + _ => None, + } + } + + pub fn location(&self) -> Option<&Location> { + match self { + Ast::Symbol(Localised { location, .. }) => Some(location), + Ast::List(Localised { location, .. }) => Some(location), + Ast::Root(_) => None, + } + } +} + pub fn tokenize(input: &str) -> Vec<Localised<Token>> { let mut tokens = Vec::new(); // let mut chars = input.chars().peekable(); diff --git a/src/parser/tests.rs b/src/parser/tests.rs index 88f38cf..07bde87 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -51,7 +51,6 @@ fn test_parse() { 1.0))) "; let ast = parse(tokenize(src)).unwrap(); - println!("{:?}", ast); let test_ast: Ast = Ast::Root(vec![ Ast::List(Localised::dummy_location(vec![ Ast::Symbol(Localised::dummy_location("module".to_string())), @@ -70,7 +69,7 @@ fn test_parse() { Localised::dummy_location("frag-coord:*v4f32i".to_string()), )])), Ast::List(Localised::dummy_location(vec![ - Ast::Symbol(Localised::dummy_location("Builtin".to_string())), + Ast::Symbol(Localised::dummy_location("BuiltIn".to_string())), Ast::Symbol(Localised::dummy_location("FragCoord".to_string())), ])), ])), @@ -115,7 +114,7 @@ fn test_parse() { Localised::dummy_location("out-color".to_string()), )])), Ast::List(Localised::dummy_location(vec![ - Ast::Symbol(Localised::dummy_location("v4f23i".to_string())), + 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![ @@ -137,5 +136,7 @@ fn test_parse() { ])), ])), ]); + println!("ast = {:#?}", ast); + println!("test_ast = {:#?}", test_ast); assert_eq!(ast, test_ast); }