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