Add function pointer types to syntax tree
diff --git a/syntax/check.rs b/syntax/check.rs
index ef3faff..be61226 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -167,6 +167,7 @@
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
     }
 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 6baa122..57b42d1 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{ExternFn, Ref, Signature, Ty1, Type};
+use crate::syntax::{ExternFn, Receiver, Ref, Signature, Ty1, Type};
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::Deref;
@@ -20,6 +20,7 @@
             Type::UniquePtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
+            Type::Fn(t) => t.hash(state),
             Type::Void(_) => {}
         }
     }
@@ -35,6 +36,7 @@
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
+            (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
             (Type::Void(_), Type::Void(_)) => true,
             (_, _) => false,
         }
@@ -103,3 +105,62 @@
         inner.hash(state);
     }
 }
+
+impl Eq for Signature {}
+
+impl PartialEq for Signature {
+    fn eq(&self, other: &Signature) -> bool {
+        let Signature {
+            fn_token: _,
+            receiver,
+            args,
+            ret,
+            throws,
+        } = self;
+        let Signature {
+            fn_token: _,
+            receiver: receiver2,
+            args: args2,
+            ret: ret2,
+            throws: throws2,
+        } = other;
+        receiver == receiver2 && args == args2 && ret == ret2 && throws == throws2
+    }
+}
+
+impl Hash for Signature {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Signature {
+            fn_token: _,
+            receiver,
+            args,
+            ret,
+            throws,
+        } = self;
+        receiver.hash(state);
+        args.hash(state);
+        ret.hash(state);
+        throws.hash(state);
+    }
+}
+
+impl Eq for Receiver {}
+
+impl PartialEq for Receiver {
+    fn eq(&self, other: &Receiver) -> bool {
+        let Receiver { mutability, ident } = self;
+        let Receiver {
+            mutability: mutability2,
+            ident: ident2,
+        } = other;
+        mutability.is_some() == mutability2.is_some() && ident == ident2
+    }
+}
+
+impl Hash for Receiver {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Receiver { mutability, ident } = self;
+        mutability.is_some().hash(state);
+        ident.hash(state);
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index f2e1c1c..6274cf1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -59,6 +59,7 @@
     pub throws: bool,
 }
 
+#[derive(Eq, PartialEq, Hash)]
 pub struct Var {
     pub ident: Ident,
     pub ty: Type,
@@ -75,6 +76,7 @@
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
+    Fn(Box<Signature>),
     Void(Span),
 }
 
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 52c47d5..3bbe872 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{Derive, ExternFn, Ref, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
-use quote::{quote_spanned, ToTokens};
+use quote::{quote, quote_spanned, ToTokens};
 use syn::Token;
 
 impl ToTokens for Type {
@@ -16,6 +16,21 @@
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Fn(f) => {
+                let fn_token = f.fn_token;
+                let args = &f.args;
+                tokens.extend(quote!(#fn_token(#(#args),*)));
+                let mut ret = match &f.ret {
+                    Some(ret) => quote!(#ret),
+                    None => quote!(()),
+                };
+                if f.throws {
+                    ret = quote!(::std::result::Result<#ret, _>);
+                }
+                if f.ret.is_some() || f.throws {
+                    tokens.extend(quote!(-> #ret));
+                }
+            }
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
     }
diff --git a/syntax/types.rs b/syntax/types.rs
index f9f87f3..f65b12f 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -26,6 +26,14 @@
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Fn(f) => {
+                    if let Some(ret) = &f.ret {
+                        visit(all, ret);
+                    }
+                    for arg in &f.args {
+                        visit(all, &arg.ty);
+                    }
+                }
             }
         }