abouttreesummaryrefslogcommitdiff
path: root/src/find.h
blob: 1876a1e0a59c0c29459de0b41aea468a746bded6 (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
#pragma once

#include "repr.h"
#include "typeInfo.h"

#include <functional>
#include <optional>

template<typename T>
using opt = std::optional<T>;

template<typename T>
opt<T> find(const std::vector<T> & ts, std::function<bool(T)> f)
{
  for (auto t : ts)
    if (f(t))
      return t;
  return nullopt;
}

opt<Function> findFunction(
  const Program & p,
  const std::string & name,
  const std::vector<std::string> & namespacePrefixes)
{
  if (namespacePrefixes.empty())
  {
    return find<Function>(p.functions, [&](Function f) { return f.name == name; });
  }
  
  auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });

  if (!n.has_value())
    return nullopt;

  std::vector<Namespace> namespaces = { n.value() };

  for (int i = 1; i < namespacePrefixes.size(); i++)
  {
    n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });
    
    if (!n.has_value())
      return nullopt;

    namespaces.push_back(n.value());
  }

  for (int i = namespaces.size()-1; i >= 0; i--)
  {
    auto f = find<Function>(namespaces[i].functions, [&](Function f) { return f.name == name; });
    if (f.has_value())
      return f.value();
  }

  return find<Function>(p.functions, [&](Function f) { return f.name == name; });
}

opt<Struct> findStruct(
  const Program & p,
  const std::string & name,
  const std::vector<std::string> & namespacePrefixes)
{
  if (namespacePrefixes.empty())
  {
    return find<Struct>(p.structs, [&](Struct s) { return s.name == name; });
  }
  
  auto n = find<Namespace>(p.namespaces, [&](Namespace n) { return n.name == namespacePrefixes[0]; });
  
  if (!n.has_value())
    return nullopt;
    
  for (int i = 1; i < namespacePrefixes.size(); i++)
  {
    n = find<Namespace>(n.value().namespaces, [&](Namespace n) { return n.name == namespacePrefixes[i]; });

    if (!n.has_value())
      return nullopt;
  }
  return find<Struct>(n.value().structs, [&](Struct s) { return s.name == name; });
}

opt<Variable> findVariable(
  const Program & p,
  const std::string & name,
  std::shared_ptr<Context> ctx)
{
  auto it = ctx;
  while (it != nullptr)
  {
    auto v = find<Variable>(it->variables, [&](Variable v) { return v.name == name; });
    if (v.has_value())
      return v;
    it = it->parent;
  }
  return nullopt;
}

opt<Function> findStructMethod(
  const Program & p,
  const std::string & name,
  TypeInfo ti)
{
  if (!ti.isStruct)
    return nullopt;
  auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);
  if (!s.has_value())
    return nullopt;
  return find<StructMember<Function>>(s.value().methods, [&](Function f) { return f.name == name; });
}

opt<Variable> findStructMember(
  const Program & p,
  TypeInfo ti,
  const std::string & name)
{
  auto s = findStruct(p, ti.type.name, ti.type.namespacePrefixes);
  if (!s.has_value())
    return nullopt;
  return find<StructMember<Variable>>(s.value().members, [&](Variable v) { return v.name == name; });
}