From f957941ce7dfeb9dc9881c87d05dc6635698785b Mon Sep 17 00:00:00 2001
From: Vincent Lafeychine <vincent.lafeychine@proton.me>
Date: Thu, 29 Dec 2022 13:09:36 +0100
Subject: [PATCH] feat(loc): Specify localisation for Command

---
 parser/src/command/mod.rs   | 13 +++++++------
 parser/src/command/parse.rs | 35 +++++++++++++++++++++++------------
 proost/src/evaluator.rs     |  8 ++++----
 proost/src/main.rs          |  1 +
 4 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/parser/src/command/mod.rs b/parser/src/command/mod.rs
index dd6d6f65..afd0d555 100644
--- a/parser/src/command/mod.rs
+++ b/parser/src/command/mod.rs
@@ -8,15 +8,16 @@ use core::fmt;
 
 use kernel::memory::declaration::builder as declaration;
 use kernel::memory::term::builder::Builder;
+use utils::location::Location;
 
 /// The type of commands that can be received by the kernel.
 #[derive(Debug, Eq, PartialEq)]
 pub enum Command<'build> {
     /// Define the given term
-    Define(&'build str, Option<Builder<'build>>, Builder<'build>),
+    Define((Location, &'build str), Option<Builder<'build>>, Builder<'build>),
 
     /// Define the given declaration
-    Declaration(&'build str, Option<declaration::Builder<'build>>, declaration::Builder<'build>),
+    Declaration((Location, &'build str), Option<declaration::Builder<'build>>, declaration::Builder<'build>),
 
     /// Infer the type of a term and check that it matches the given one.
     CheckType(Builder<'build>, Builder<'build>),
@@ -40,13 +41,13 @@ impl<'build> fmt::Display for Command<'build> {
         use Command::{CheckType, Declaration, Define, Eval, GetType, Import, Search};
 
         match *self {
-            Define(name, None, ref t) => write!(f, "def {name} := {t}"),
+            Define((_, name), None, ref t) => write!(f, "def {name} := {t}"),
 
-            Define(name, Some(ref ty), ref t) => write!(f, "def {name}: {ty} := {t}"),
+            Define((_, name), Some(ref ty), ref t) => write!(f, "def {name}: {ty} := {t}"),
 
-            Declaration(name, None, ref t) => write!(f, "def {name} := {t}"),
+            Declaration((_, name), None, ref t) => write!(f, "def {name} := {t}"),
 
-            Declaration(name, Some(ref ty), ref t) => write!(f, "def {name}: {ty} := {t}"),
+            Declaration((_, name), Some(ref ty), ref t) => write!(f, "def {name}: {ty} := {t}"),
 
             CheckType(ref t, ref ty) => write!(f, "check {t}: {ty}"),
 
diff --git a/parser/src/command/parse.rs b/parser/src/command/parse.rs
index 891ad780..7c43b0a2 100644
--- a/parser/src/command/parse.rs
+++ b/parser/src/command/parse.rs
@@ -144,6 +144,7 @@ fn parse_expr(pair: Pair<Rule>) -> Command {
         Rule::GetType => {
             let mut iter = pair.into_inner();
             let t = parse_term(iter.next().unwrap());
+
             Command::GetType(t)
         },
 
@@ -151,39 +152,41 @@ fn parse_expr(pair: Pair<Rule>) -> Command {
             let mut iter = pair.into_inner();
             let t1 = parse_term(iter.next().unwrap());
             let t2 = parse_term(iter.next().unwrap());
+
             Command::CheckType(t1, t2)
         },
 
         Rule::Define => {
             let mut iter = pair.into_inner();
-            let s = iter.next().unwrap().as_str();
+            let s = iter.next().unwrap();
             let term = parse_term(iter.next().unwrap());
-            Command::Define(s, None, term)
+
+            Command::Define((convert_span(s.as_span()), s.as_str()), None, term)
         },
 
         Rule::DefineCheckType => {
             let mut iter = pair.into_inner();
-            let s = iter.next().unwrap().as_str();
+            let s = iter.next().unwrap();
             let ty = parse_term(iter.next().unwrap());
             let term = parse_term(iter.next().unwrap());
 
-            Command::Define(s, Some(ty), term)
+            Command::Define((convert_span(s.as_span()), s.as_str()), Some(ty), term)
         },
 
         Rule::Declaration => {
             let mut iter = pair.into_inner();
             let mut string_decl = iter.next().unwrap().into_inner();
-            let s = string_decl.next().unwrap().as_str();
+            let s = string_decl.next().unwrap();
             let vars: Vec<&str> = string_decl.next().unwrap().into_inner().map(|name| name.as_str()).collect();
             let body = iter.next().map(parse_term).unwrap();
 
-            Command::Declaration(s, None, declaration::Builder::Decl(box body, vars))
+            Command::Declaration((convert_span(s.as_span()), s.as_str()), None, declaration::Builder::Decl(box body, vars))
         },
 
         Rule::DeclarationCheckType => {
             let mut iter = pair.into_inner();
             let mut string_decl = iter.next().unwrap().into_inner();
-            let s = string_decl.next().unwrap().as_str();
+            let s = string_decl.next().unwrap();
             let vars: Vec<&str> = string_decl.next().unwrap().into_inner().map(|name| name.as_str()).collect();
 
             let ty = parse_term(iter.next().unwrap());
@@ -191,7 +194,8 @@ fn parse_expr(pair: Pair<Rule>) -> Command {
 
             let ty = declaration::Builder::Decl(box ty, vars.clone());
             let decl = declaration::Builder::Decl(box decl, vars);
-            Command::Declaration(s, Some(ty), decl)
+
+            Command::Declaration((convert_span(s.as_span()), s.as_str()), Some(ty), decl)
         },
 
         Rule::Eval => {
@@ -343,7 +347,7 @@ mod tests {
         assert_eq!(
             line("def x : Type := Prop"),
             Ok(Define(
-                "x",
+                (Location::new((1, 5), (1, 6)), "x"),
                 Some(Builder::new(Location::new((1, 9), (1, 14)), Type(box level::Builder::Const(0)))),
                 Builder::new(Location::new((1, 17), (1, 21)), Prop)
             ))
@@ -355,7 +359,7 @@ mod tests {
         assert_eq!(
             line("def x.{u} : Type u := foo.{u}"),
             Ok(Declaration(
-                "x",
+                (Location::new((1, 5), (1, 6)), "x"),
                 Some(declaration::Builder::Decl(
                     box Builder::new(Location::new((1, 13), (1, 19)), Type(box level::Builder::Var("u"))),
                     ["u"].to_vec()
@@ -389,14 +393,21 @@ mod tests {
 
     #[test]
     fn successful_define() {
-        assert_eq!(line("def x := Prop"), Ok(Define("x", None, Builder::new(Location::new((1, 10), (1, 14)), Prop))));
+        assert_eq!(
+            line("def x := Prop"),
+            Ok(Define((Location::new((1, 5), (1, 6)), "x"), None, Builder::new(Location::new((1, 10), (1, 14)), Prop)))
+        );
     }
 
     #[test]
     fn successful_declare() {
         assert_eq!(
             line("def x.{} := Prop"),
-            Ok(Declaration("x", None, declaration::Builder::Decl(box Builder::new(Location::new((1, 13), (1, 17)), Prop), vec![])))
+            Ok(Declaration(
+                (Location::new((1, 5), (1, 6)), "x"),
+                None,
+                declaration::Builder::Decl(box Builder::new(Location::new((1, 13), (1, 17)), Prop), vec![])
+            ))
         );
     }
 
diff --git a/proost/src/evaluator.rs b/proost/src/evaluator.rs
index 0a536e44..7159398f 100644
--- a/proost/src/evaluator.rs
+++ b/proost/src/evaluator.rs
@@ -169,11 +169,11 @@ impl<'arena> Evaluator {
         importing: &mut Vec<PathBuf>,
     ) -> Result<'arena, 'build, Option<Term<'arena>>> {
         match *command {
-            Command::Define(s, ref type_builder, ref term_builder) => {
+            Command::Define((location, s), ref type_builder, ref term_builder) => {
                 if arena.get_binding(s).is_some() {
                     return Err(TopLevel(Error {
                         kind: ErrorKind::BoundVariable(s.to_owned()),
-                        location: Location::default(), // TODO (see #38)
+                        location,
                     }));
                 }
 
@@ -194,11 +194,11 @@ impl<'arena> Evaluator {
                 Ok(None)
             },
 
-            Command::Declaration(s, ref type_builder, ref decl_builder) => {
+            Command::Declaration((location, s), ref type_builder, ref decl_builder) => {
                 if arena.get_binding_decl(s).is_some() {
                     return Err(TopLevel(Error {
                         kind: ErrorKind::BoundVariable(s.to_owned()),
-                        location: Location::default(), // TODO (see #38)
+                        location,
                     }));
                 }
 
diff --git a/proost/src/main.rs b/proost/src/main.rs
index 2723b42b..88e152bf 100644
--- a/proost/src/main.rs
+++ b/proost/src/main.rs
@@ -149,6 +149,7 @@ pub fn display<'arena>(res: Result<'arena, '_, Option<Term<'arena>>>) {
             let location = match err {
                 Error::Kernel(ref builder, ref err) => Some(builder.apply_trace(&err.trace)),
                 Error::Parser(ref err) => Some(err.loc),
+                Error::TopLevel(ref err) => Some(err.location),
 
                 _ => None,
             };
-- 
GitLab