1use std::collections::HashMap;
4
5use crate::arena::{Arena, Handle};
6use crate::expr::Expression;
7use crate::global::Binding;
8use crate::stmt::Block;
9use crate::types::Type;
10
11#[derive(Clone, Debug)]
13pub struct FunctionArgument {
14 pub name: Option<String>,
16 pub ty: Handle<Type>,
18 pub binding: Option<Binding>,
20}
21
22#[derive(Clone, Debug)]
24pub struct FunctionResult {
25 pub ty: Handle<Type>,
27 pub binding: Option<Binding>,
29}
30
31#[derive(Clone, Debug)]
33pub struct LocalVariable {
34 pub name: Option<String>,
36 pub ty: Handle<Type>,
38 pub init: Option<Handle<Expression>>,
40}
41
42#[derive(Clone, Debug)]
44pub struct Function {
45 pub name: Option<String>,
47 pub arguments: Vec<FunctionArgument>,
49 pub result: Option<FunctionResult>,
51 pub local_variables: Arena<LocalVariable>,
53 pub expressions: Arena<Expression>,
55 pub named_expressions: HashMap<Handle<Expression>, String>,
57 pub body: Block,
59}
60
61impl Function {
62 pub fn new(name: impl Into<String>) -> Self {
64 Self {
65 name: Some(name.into()),
66 arguments: Vec::new(),
67 result: None,
68 local_variables: Arena::new(),
69 expressions: Arena::new(),
70 named_expressions: HashMap::new(),
71 body: Vec::new(),
72 }
73 }
74}
75
76#[derive(Clone, Debug)]
78pub struct EntryPoint {
79 pub name: String,
81 pub workgroup_size: [u32; 3],
83 pub function: Function,
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use crate::expr::Literal;
91 use crate::types::{Scalar, TypeInner};
92
93 #[test]
94 fn function_new() {
95 let f = Function::new("test");
96 assert_eq!(f.name.as_deref(), Some("test"));
97 assert_eq!(f.arguments.len(), 0);
98 assert!(f.result.is_none());
99 assert_eq!(f.body.len(), 0);
100 assert_eq!(f.expressions.len(), 0);
101 }
102
103 #[test]
104 fn function_with_local_vars() {
105 let mut types = crate::arena::UniqueArena::new();
106 let f32_ty = types.insert(Type {
107 name: None,
108 inner: TypeInner::Scalar(Scalar::F32),
109 });
110
111 let mut f = Function::new("test");
112 let init = f.expressions.append(Expression::Literal(Literal::F32(0.0)));
113 let _var = f.local_variables.append(LocalVariable {
114 name: Some("sum".into()),
115 ty: f32_ty,
116 init: Some(init),
117 });
118 assert_eq!(f.local_variables.len(), 1);
119 }
120
121 #[test]
122 fn entry_point() {
123 let ep = EntryPoint {
124 name: "main".into(),
125 workgroup_size: [256, 1, 1],
126 function: Function::new("main"),
127 };
128 assert_eq!(ep.workgroup_size, [256, 1, 1]);
129 }
130}