diff --git a/src/compiler/backend/tests.rs b/src/compiler/backend/tests.rs index 87c258d..5f899af 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,9 @@ 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); -} \ No newline at end of file +} + diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 9a83957..f037a65 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; @@ -8,13 +8,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)] @@ -38,7 +38,7 @@ pub enum AddressingModel { Logical, Physical32, Physical64, - PhysicalStorageBuffer64 + PhysicalStorageBuffer64, } #[derive(Debug, PartialEq, Default, Clone)] pub enum MemoryModel { @@ -46,7 +46,7 @@ pub enum MemoryModel { GLSL450, OpenCL, VulkanKHR, - Simple + Simple, } #[derive(Debug, PartialEq, Default, Clone)] @@ -135,9 +135,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] { @@ -158,28 +158,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::>()[0].to_string(); - let typ: String = name_and_type.split(":").collect::>()[1].to_string(); + let name: String = + name_and_type.split(":").collect::>()[0] + .to_string(); + let typ: String = + name_and_type.split(":").collect::>()[1] + .to_string(); let bind = match &list[2] { Ast::List(l) => l, _ => panic!("Expected list! {:?}", list[2]), }; - let bind: Vec = bind.iter().map(|x| { - match x { + let bind: Vec = 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::().unwrap()), + "BuiltIn" => { + Decoration::BuiltIn(BuiltinDecoration::FragCoord) + } + "Location" => Decoration::Location( + bind[1].parse::().unwrap(), + ), _ => panic!("Unknown bind! {:?}", bind), }; let mut exists = false; @@ -202,8 +212,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::>()[0].to_string(); - let typ: String = name_and_type.split(":").collect::>()[1].to_string(); + let name: String = + name_and_type.split(":").collect::>()[0] + .to_string(); + let typ: String = + name_and_type.split(":").collect::>()[1] + .to_string(); let storage_class = match &list[2] { Ast::Symbol(s) => s, _ => panic!("Expected symbol! {:?}", list[2]), @@ -228,9 +242,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" => { @@ -250,22 +267,21 @@ pub fn meta_compile(ast: &mut Ast) -> Module { Ast::List(l) => l, _ => panic!("Expected list! {:?}", list[4]), }; - let interface: Vec = interface.iter().map(|x| { - match x { - Ast::Symbol(s) => { - s.to_string().replace(":", "") - }, + let interface: Vec = 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] { @@ -277,12 +293,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); } @@ -296,7 +323,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 08b18e9..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], @@ -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 { @@ -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 { - location: Location, - item: T, +pub struct Localised { + pub location: Location, + pub item: T, } impl Localised { @@ -83,6 +83,14 @@ impl Localised { } } +impl Deref for Localised { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.item + } +} + impl PartialEq for Localised { fn eq(&self, other: &Self) -> bool { self.item.eq(&other.item) @@ -103,6 +111,23 @@ pub enum Ast { Root(Vec), } +impl Ast { + pub fn symbol(self) -> Option { + 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> { 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); }