blob: 33323e4eb8e560289faac453b23934b8a5340565 (
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
|
#pragma once
#include "repr.h"
#include "typeInfo.h"
#include "visit.h"
// add a generic instantiation if its not in the vector already
void addGenericInstantiation(
std::vector<std::vector<Type>> & insts,
const std::vector<Type> & newInst)
{
if (insts.empty())
{
insts.push_back(newInst);
return;
}
for (auto inst : insts)
{
for (int i = 0; i < inst.size(); i++)
{
if (inst[i] != newInst[i])
{
insts.push_back(newInst);
return;
}
}
}
}
Program instantiateGenerics(const Program & p)
{
Program result = p;
// Find generic instantiations
// visit expressions (only function calls are considered) and types,
// find the function/struct by pointer and add an instantiation
Visitor findGenericInstantiations;
findGenericInstantiations.onExpr =
[&](const Expr & e, const std::shared_ptr<Context> ctx)
{
if (e.type == ExprType::Func && !e._func.genericInstantiation.empty())
{
auto f = findFunctionPtr(e._func.functionName, e._func.namespacePrefixes, ctx);
if (f.has_value())
{
if (std::get<0>(*f)->genericTypeNames.empty())
throw "Trying to instantiate non-generic function";
if (e._func.genericInstantiation.size() != std::get<0>(*f)->genericTypeNames.size())
throw "Trying to instantiate function with wrong number of types";
addGenericInstantiation(std::get<0>(*f)->genericInstantiations, e._func.genericInstantiation);
}
}
};
findGenericInstantiations.onType =
[&](const Type & t, const std::shared_ptr<Context> ctx)
{
if (!t.genericInstantiation.empty())
{
auto s = findStructPtr(t.name, t.namespacePrefixes, ctx);
if (s.has_value())
{
if (std::get<0>(*s)->genericTypeNames.empty())
throw "Trying to instantiate non-generic struct";
if (t.genericInstantiation.size() != std::get<0>(*s)->genericTypeNames.size())
throw "Trying to instantiate struct with wrong number of types";
addGenericInstantiation(std::get<0>(*s)->genericInstantiations, t.genericInstantiation);
}
}
};
Visit v(findGenericInstantiations);
v.visit(result);
return result;
}
// generate the appendix for C struct/function names
// including array/pointer indicators because
// there might be distinct instantiations
// for int and int* for example
std::string genericAppendix(const std::vector<Type> & ts)
{
std::stringstream sstr;
for (auto t : ts)
{
sstr << "_";
sstr << t.name;
for (auto m : t.modifiers)
{
if (m.type == TypeModifierType::Array)
{
sstr << "_arr";
if (m._staticArray)
sstr << m._arraySize;
}
else if (m.type == TypeModifierType::Pointer)
{
sstr << "_ptr";
}
}
if (!t.genericInstantiation.empty())
{
sstr << genericAppendix(t.genericInstantiation);
}
}
return sstr.str();
}
|