aboutsummaryrefslogtreecommitdiff
path: root/build/variable
blob: 393ad47c1121f797e42581ea13dc653df0d6a12a (plain)
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
116
117
118
119
120
121
122
123
// file      : build/variable -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD_VARIABLE
#define BUILD_VARIABLE

#include <string>
#include <memory>        // unique_ptr
#include <utility>       // move()
#include <typeindex>
#include <unordered_set>

#include <build/name>
#include <build/prefix-map>

namespace build
{
  class scope;
  struct value;

  struct value_type
  {
    std::type_index id;
    value* (*const factory) ();
  };

  // variable
  //
  // The two variables are considered the same if they have the same name.
  //
  struct variable
  {
    explicit
    variable (std::string n): name (std::move (n)), type (nullptr) {}

    std::string name;
    const value_type* type; // If NULL, then this variable has no fixed type.
  };

  inline bool
  operator== (const variable& x, const variable& y) {return x.name == y.name;}

  typedef std::reference_wrapper<const variable> variable_cref;

  // value
  //
  struct value
  {
    typedef build::scope scope_type;

    virtual
    ~value () = default;

    value (scope_type& s): scope (s) {}

    scope_type& scope; // Scope to which this value belongs.
  };
  typedef std::unique_ptr<value> value_ptr;

  struct list_value: value
  {
    list_value (scope_type& s, names d): value (s), data (std::move (d)) {}

    names data;
  };
  typedef std::unique_ptr<list_value> list_value_ptr;
}

namespace std
{
  template <>
  struct hash<build::variable>: hash<string>
  {
    size_t
    operator() (const build::variable& v) const noexcept
    {
      return hash<string>::operator() (v.name);
    }
  };
}

namespace build
{
  // variable_pool
  //
  struct variable_set: std::unordered_set<variable>
  {
    // @@ Need to check/set type?
    //
    const variable&
    find (std::string name) {return *emplace (std::move (name)).first;}
  };

  extern variable_set variable_pool;

  // variable_map
  //
  template <>
  struct compare_prefix<variable_cref>: compare_prefix<std::string>
  {
    typedef compare_prefix<std::string> base;

    explicit
    compare_prefix (char d): base (d) {}

    bool
    operator() (const variable& x, const variable& y) const
    {
      return base::operator() (x.name, y.name);
    }

    bool
    prefix (const variable& p, const variable& k) const
    {
      return base::prefix (p.name, k.name);
    }
  };

  typedef prefix_map<variable_cref, value_ptr, '.'> variable_map;
}

#endif // BUILD_VARIABLE