Applied cargo fmt, location tracking, error handling

Reviewed-on: #1
pull/2/head
itycodes 3 weeks ago
commit c2dabb8157

@ -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));
}
}

@ -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
}
}

@ -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);
}
}

@ -1,10 +1,10 @@
use std::fmt::Write;
pub mod parser;
pub mod compiler;
pub mod parser;
fn main() {
let mut ops: Vec<(Option<String>, Vec<String>)> = Vec::new();
// OpMemoryModel Logical GLSL450
// OpEntryPoint Fragment %main "main"
// OpExecutionMode %main OriginUpperLeft
@ -18,23 +18,88 @@ fn main() {
//%5 = OpLabel
// OpReturn
// OpFunctionEnd
ops.push((None, vec!["OpCapability".to_string(), "Shader".to_string()]));
ops.push((Some("%1".to_string()), vec!["OpExtInstImport".to_string(), "\"GLSL.std.450\"".to_string()]));
ops.push((None, vec!["OpMemoryModel".to_string(), "Logical".to_string(), "GLSL450".to_string()]));
ops.push((None, vec!["OpEntryPoint".to_string(), "Fragment".to_string(), "%main".to_string(), "\"main\"".to_string()]));
ops.push((None, vec!["OpExecutionMode".to_string(), "%main".to_string(), "OriginUpperLeft".to_string()]));
ops.push((None, vec!["OpSource".to_string(), "GLSL".to_string(), "450".to_string()]));
ops.push((None, vec!["OpSourceExtension".to_string(), "\"GL_GOOGLE_cpp_style_line_directive\"".to_string()]));
ops.push((None, vec!["OpSourceExtension".to_string(), "\"GL_GOOGLE_include_directive\"".to_string()]));
ops.push((None, vec!["OpName".to_string(), "%main".to_string(), "\"main\"".to_string()]));
ops.push((
Some("%1".to_string()),
vec![
"OpExtInstImport".to_string(),
"\"GLSL.std.450\"".to_string(),
],
));
ops.push((
None,
vec![
"OpMemoryModel".to_string(),
"Logical".to_string(),
"GLSL450".to_string(),
],
));
ops.push((
None,
vec![
"OpEntryPoint".to_string(),
"Fragment".to_string(),
"%main".to_string(),
"\"main\"".to_string(),
],
));
ops.push((
None,
vec![
"OpExecutionMode".to_string(),
"%main".to_string(),
"OriginUpperLeft".to_string(),
],
));
ops.push((
None,
vec![
"OpSource".to_string(),
"GLSL".to_string(),
"450".to_string(),
],
));
ops.push((
None,
vec![
"OpSourceExtension".to_string(),
"\"GL_GOOGLE_cpp_style_line_directive\"".to_string(),
],
));
ops.push((
None,
vec![
"OpSourceExtension".to_string(),
"\"GL_GOOGLE_include_directive\"".to_string(),
],
));
ops.push((
None,
vec![
"OpName".to_string(),
"%main".to_string(),
"\"main\"".to_string(),
],
));
ops.push((Some("%void".to_string()), vec!["OpTypeVoid".to_string()]));
ops.push((Some("%3".to_string()), vec!["OpTypeFunction".to_string(), "%void".to_string()]));
ops.push((Some("%main".to_string()), vec!["OpFunction".to_string(), "%void".to_string(), "None".to_string(), "%3".to_string()]));
ops.push((
Some("%3".to_string()),
vec!["OpTypeFunction".to_string(), "%void".to_string()],
));
ops.push((
Some("%main".to_string()),
vec![
"OpFunction".to_string(),
"%void".to_string(),
"None".to_string(),
"%3".to_string(),
],
));
ops.push((Some("%5".to_string()), vec!["OpLabel".to_string()]));
ops.push((None, vec!["OpReturn".to_string()]));
ops.push((None, vec!["OpFunctionEnd".to_string()]));
let mut out: String = String::new();
for op in ops {

@ -2,9 +2,102 @@
mod tests;
use std::iter::Peekable;
use std::ops::{Deref, RangeInclusive};
use std::vec::IntoIter;
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug)]
pub enum Location {
Char {
line: usize,
col: usize,
},
String {
lines: RangeInclusive<usize>,
cols: RangeInclusive<usize>,
},
}
#[derive(Debug)]
pub enum ParseError {
UnexpectedParenClose(Location),
UnexpectedEof,
}
impl Location {
/// Since [`Localised`] doesn't test for location match, allow for creating simple dummy
/// locations for testing
#[cfg(test)]
pub fn dummy() -> Location {
Self::Char { line: 0, col: 0 }
}
pub fn range(start: &Location, end: &Location) -> Location {
Location::String {
lines: start.line_start()..=end.line_end(),
cols: start.col_start()..=end.col_end(),
}
}
pub fn line_start(&self) -> usize {
match self {
Location::Char { line, .. } => *line,
Location::String { lines, .. } => *lines.start(),
}
}
pub fn col_start(&self) -> usize {
match self {
Location::Char { col, .. } => *col,
Location::String { cols, .. } => *cols.start(),
}
}
pub fn line_end(&self) -> usize {
match self {
Location::Char { line, .. } => *line,
Location::String { lines, .. } => *lines.end(),
}
}
pub fn col_end(&self) -> usize {
match self {
Location::Char { col, .. } => *col,
Location::String { cols, .. } => *cols.end(),
}
}
}
#[derive(Debug, Clone)]
pub struct Localised<T: Clone> {
pub location: Location,
pub item: T,
}
impl<T: Clone> Localised<T> {
#[cfg(test)]
pub fn dummy_location(item: T) -> Self {
Self {
location: Location::dummy(),
item,
}
}
}
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)
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Token {
LeftParen,
RightParen,
@ -13,56 +106,126 @@ pub enum Token {
#[derive(Debug, PartialEq, Clone)]
pub enum Ast {
Symbol(String),
List(Vec<Ast>),
Symbol(Localised<String>),
List(Localised<Vec<Ast>>),
Root(Vec<Ast>),
}
pub fn tokenize(input: &str) -> Vec<Token> {
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();
while let Some(c) = chars.next() {
// let mut chars = input.chars().peekable();
let mut chars = (1..)
.zip(input.split('\n'))
.flat_map(|(l_num, l)| {
(1..).zip(l.chars()).map(move |(c_num, c)| Localised {
location: Location::Char {
line: l_num,
col: c_num,
},
item: c,
})
})
.peekable();
while let Some(Localised { location, item: c }) = chars.next() {
match c {
'(' => tokens.push(Token::LeftParen),
')' => tokens.push(Token::RightParen),
'(' => tokens.push(Localised {
location,
item: Token::LeftParen,
}),
')' => tokens.push(Localised {
location,
item: Token::RightParen,
}),
_ if c.is_whitespace() => (),
_ => {
let start = location.clone();
let mut end = location;
let mut symbol = c.to_string();
while let Some(&c) = chars.peek() {
if c.is_whitespace() || c == '(' || c == ')' {
while let Some(Localised { item: c, .. }) = chars.peek() {
if c.is_whitespace() || *c == '(' || *c == ')' {
break;
}
symbol.push(c);
chars.next();
symbol.push(*c);
let Localised { location, .. } = chars.next().unwrap();
end = location;
}
tokens.push(Token::Symbol(symbol));
tokens.push(Localised {
location: Location::range(&start, &end),
item: Token::Symbol(symbol),
});
}
}
}
tokens
}
fn parse_expr(tokens: &mut Peekable<IntoIter<Token>>) -> Ast {
fn parse_expr(tokens: &mut Peekable<IntoIter<Localised<Token>>>) -> Result<Ast, ParseError> {
match tokens.next() {
Some(Token::LeftParen) => {
Some(Localised {
location: start,
item: Token::LeftParen,
}) => {
let mut list = Vec::new();
while tokens.peek() != Some(&Token::RightParen) {
list.push(parse_expr(tokens));
while !matches!(
tokens.peek(),
Some(Localised {
item: Token::RightParen,
..
})
) {
list.push(parse_expr(tokens)?);
}
tokens.next();
Ast::List(list)
let Some(Localised {
location: end,
item: Token::RightParen,
}) = tokens.next()
else {
unreachable!()
};
Ok(Ast::List(Localised {
location: Location::range(&start, &end),
item: list,
}))
}
Some(Token::RightParen) => panic!("unexpected )"),
Some(Token::Symbol(s)) => Ast::Symbol(s),
None => panic!("unexpected EOF"),
Some(Localised {
location,
item: Token::RightParen,
}) => Err(ParseError::UnexpectedParenClose(location)),
Some(Localised {
location,
item: Token::Symbol(s),
}) => Ok(Ast::Symbol(Localised { location, item: s })),
None => Err(ParseError::UnexpectedEof),
}
}
pub fn parse(tokens: Vec<Token>) -> Ast {
pub fn parse(tokens: Vec<Localised<Token>>) -> Result<Ast, ParseError> {
let mut tokens = tokens.into_iter().peekable();
let mut ast: Vec<Ast> = Vec::new();
while tokens.peek().is_some() {
ast.push(parse_expr(&mut tokens));
ast.push(parse_expr(&mut tokens)?);
}
Ast::Root(ast)
}
Ok(Ast::Root(ast))
}
pub fn parse_string(src: &str) -> Result<Ast, ParseError> {
let tokens = tokenize(src);
parse(tokens)
}

@ -1,22 +1,38 @@
use crate::parser::{tokenize, parse, Token, Ast};
use crate::parser::{Ast, Localised, Token, parse, tokenize};
#[test]
fn test_tokenize() {
let input = "(+ (* 1:u8 2) 2)";
let expected = vec![
Token::LeftParen,
Token::Symbol("+".to_string()),
Token::LeftParen,
Token::Symbol("*".to_string()),
Token::Symbol("1:u8".to_string()),
Token::Symbol("2".to_string()),
Token::RightParen,
Token::Symbol("2".to_string()),
Token::RightParen,
Localised::dummy_location(Token::LeftParen),
Localised::dummy_location(Token::Symbol("+".to_string())),
Localised::dummy_location(Token::LeftParen),
Localised::dummy_location(Token::Symbol("*".to_string())),
Localised::dummy_location(Token::Symbol("1:u8".to_string())),
Localised::dummy_location(Token::Symbol("2".to_string())),
Localised::dummy_location(Token::RightParen),
Localised::dummy_location(Token::Symbol("2".to_string())),
Localised::dummy_location(Token::RightParen),
];
assert_eq!(tokenize(input), expected);
}
#[test]
#[should_panic]
fn test_unexpected_pclose() {
let input = "())";
let tokens = tokenize(input);
let _ast = parse(tokens).unwrap();
}
#[test]
#[should_panic]
fn test_unexpected_eof() {
let input = "(1 2 3 4";
let tokens = tokenize(input);
let _ast = parse(tokens).unwrap();
}
#[test]
fn test_parse() {
let src = "
@ -34,92 +50,93 @@ fn test_parse() {
1.0
1.0)))
";
let ast = parse(tokenize(src));
println!("{:?}", ast);
let ast = parse(tokenize(src)).unwrap();
let test_ast: Ast = Ast::Root(vec![
Ast::List(vec![
Ast::Symbol("module".to_string()),
Ast::Symbol("Shader".to_string()),
Ast::Symbol("Logical".to_string()),
Ast::Symbol("GLSL450".to_string()),
]),
Ast::List(vec![
Ast::Symbol("import".to_string()),
Ast::Symbol(":std".to_string()),
Ast::Symbol("GLSL.std.450".to_string()),
]),
Ast::List(vec![
Ast::Symbol("bind".to_string()),
Ast::List(vec![
Ast::Symbol("frag-coord:*v4f32i".to_string()),
]),
Ast::List(vec![
Ast::Symbol("BuiltIn".to_string()),
Ast::Symbol("FragCoord".to_string()),
]),
]),
Ast::List(vec![
Ast::Symbol("bind".to_string()),
Ast::List(vec![
Ast::Symbol("out-color:*v4f32o".to_string()),
]),
Ast::List(vec![
Ast::Symbol("Location".to_string()),
Ast::Symbol("0".to_string()),
]),
]),
Ast::List(vec![
Ast::Symbol("dec".to_string()),
Ast::Symbol("frag-coord:*v4f32i".to_string()),
Ast::Symbol("Input".to_string()),
]),
Ast::List(vec![
Ast::Symbol("dec".to_string()),
Ast::Symbol("out-color:*v4f32o".to_string()),
Ast::Symbol("Output".to_string()),
]),
Ast::List(vec![
Ast::Symbol("entry".to_string()),
Ast::Symbol("main".to_string()),
Ast::Symbol("Fragment".to_string()),
Ast::Symbol("OriginUpperLeft".to_string()),
Ast::List(vec![
Ast::Symbol(":frag-coord".to_string()),
Ast::Symbol(":out-color".to_string()),
]),
]),
Ast::List(vec![
Ast::Symbol("fun".to_string()),
Ast::List(vec![
Ast::Symbol("main".to_string()),
]),
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::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("module".to_string())),
Ast::Symbol(Localised::dummy_location("Shader".to_string())),
Ast::Symbol(Localised::dummy_location("Logical".to_string())),
Ast::Symbol(Localised::dummy_location("GLSL450".to_string())),
])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("import".to_string())),
Ast::Symbol(Localised::dummy_location(":std".to_string())),
Ast::Symbol(Localised::dummy_location("GLSL.std.450".to_string())),
])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("bind".to_string())),
Ast::List(Localised::dummy_location(vec![Ast::Symbol(
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("FragCoord".to_string())),
])),
])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("bind".to_string())),
Ast::List(Localised::dummy_location(vec![Ast::Symbol(
Localised::dummy_location("out-color:*v4f32o".to_string()),
)])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("Location".to_string())),
Ast::Symbol(Localised::dummy_location("0".to_string())),
])),
])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("dec".to_string())),
Ast::Symbol(Localised::dummy_location("frag-coord:*v4f32i".to_string())),
Ast::Symbol(Localised::dummy_location("Input".to_string())),
])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("dec".to_string())),
Ast::Symbol(Localised::dummy_location("out-color:*v4f32o".to_string())),
Ast::Symbol(Localised::dummy_location("Output".to_string())),
])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("entry".to_string())),
Ast::Symbol(Localised::dummy_location("main".to_string())),
Ast::Symbol(Localised::dummy_location("Fragment".to_string())),
Ast::Symbol(Localised::dummy_location("OriginUpperLeft".to_string())),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location(":frag-coord".to_string())),
Ast::Symbol(Localised::dummy_location(":out-color".to_string())),
])),
])),
Ast::List(Localised::dummy_location(vec![
Ast::Symbol(Localised::dummy_location("fun".to_string())),
Ast::List(Localised::dummy_location(vec![Ast::Symbol(
Localised::dummy_location("main".to_string()),
)])),
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())),
])),
])),
])),
]);
println!("ast = {:#?}", ast);
println!("test_ast = {:#?}", test_ast);
assert_eq!(ast, test_ast);
}
}

Loading…
Cancel
Save