1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright 2017 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `Environment` is constituted of a state named `env` that is never lost (even if the partial data is equal to `Nothing`).
//! It behaves similarly to `Partial` but the binders (e.g. `and_then`) take two parameters: the environment and the unwrapped partial data.
//! This structure is useful to implement compiler where `env` contains the configuration and `data` the compilation context.

use Partial;
use Partial::*;
use std::ops::{Deref, DerefMut};

#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub struct Environment<T, U>
{
  env: T,
  data: Partial<U>
}

impl<T, U> Environment<T, U>
{
  pub fn new(env: T, data: Partial<U>) -> Self {
    Environment {
      env: env,
      data: data
    }
  }

  pub fn value(env: T, data: U) -> Self {
    Self::new(env, Partial::Value(data))
  }

  pub fn fake(env: T, data: U) -> Self {
    Self::new(env, Partial::Fake(data))
  }

  pub fn nothing(env: T) -> Self {
    Self::new(env, Partial::Nothing)
  }

  pub fn unwrap(self) -> U {
    self.data.unwrap()
  }

  pub fn decompose(self) -> (T, Partial<U>) {
    (self.env, self.data)
  }

  pub fn expect(self, msg: &str) -> U {
    self.data.expect(msg)
  }

  pub fn ensure(self, msg: &str) -> Self {
    Environment::new(self.env, self.data.ensure(msg))
  }

  pub fn unwrap_or_else<F>(self, f: F) -> U where
   F: FnOnce() -> U
  {
    self.data.unwrap_or_else(f)
  }

  pub fn map<R, F: FnOnce(U) -> R>(self, f: F) -> Environment<T, R> {
    match self.data {
      Value(x) => Environment::value(self.env, f(x)),
      Fake(x) => Environment::fake(self.env, f(x)),
      Nothing => Environment::nothing(self.env)
    }
  }

  pub fn and_then<R, F: FnOnce(T, U) -> Environment<T, R>>(self, f: F) -> Environment<T, R> {
    match self.data {
      Value(x) => f(self.env, x),
      Fake(x) => {
        let r = f(self.env, x);
        match r.data {
          Value(x) => Environment::fake(r.env, x),
          x => Environment::new(r.env, x)
        }
      }
      Nothing => Environment::nothing(self.env)
    }
  }

  pub fn and_next<R, F: FnOnce(T, U) -> Environment<T, R>>(self, f: F) -> Environment<T, R> {
    match self.data {
      Value(x) => f(self.env, x),
      _ => Environment::nothing(self.env)
    }
  }
}

impl<T, U> Deref for Environment<T, U> {
  type Target = T;

  fn deref(&self) -> &T {
    &self.env
  }
}

impl<T, U> DerefMut for Environment<T, U> {
  fn deref_mut(&mut self) -> &mut T {
    &mut self.env
  }
}