1 /* Copyright (c) 1997-2021
2 Ewgenij Gawrilow, Michael Joswig, and the polymake team
3 Technische Universität Berlin, Germany
4 https://polymake.org
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version: http://www.gnu.org/licenses/gpl.txt.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 --------------------------------------------------------------------------------
16 */
17
18 #include "polymake/perl/glue.h"
19
20 namespace pm { namespace perl {
21
set_descr(const std::type_info & ti)22 bool type_infos::set_descr(const std::type_info& ti)
23 {
24 dTHX;
25 const char* const type_name = ti.name();
26 if (SV** const descr_p = hv_fetch((HV*)SvRV(PmArray(GvSV(glue::CPP_root))[glue::CPP_typeids_index]),
27 type_name, I32(strlen(type_name)), false)) {
28 descr = *descr_p;
29 return true;
30 }
31 return false;
32 }
33
set_descr()34 void type_infos::set_descr()
35 {
36 dTHX;
37 SV* const opts = PmArray(proto)[glue::PropertyType_cppoptions_index];
38 if (SvROK(opts)) {
39 descr = PmArray(opts)[glue::CPPOptions_descr_index];
40 if (!SvROK(descr)) {
41 descr = nullptr;
42 } else if (SvTYPE(SvRV(descr)) == SVt_PVCV) {
43 PmStartFuncall(0);
44 const int ret = call_sv(descr, G_VOID | G_EVAL);
45 if (__builtin_expect(ret>0, 0)) {
46 descr = nullptr;
47 PmFuncallFailed;
48 }
49 FREETMPS; LEAVE;
50 descr = PmArray(opts)[glue::CPPOptions_descr_index];
51 }
52 }
53 }
54
set_proto(SV * known_proto)55 void type_infos::set_proto(SV* known_proto)
56 {
57 dTHX;
58 if (known_proto) {
59 proto = newSVsv(known_proto);
60 } else {
61 SV** type_gvp = hv_fetch((HV*)SvRV(PmArray(descr)[glue::TypeDescr_pkg_index]), "type", 4, false);
62 if (type_gvp) {
63 PmStartFuncall(0);
64 proto = glue::call_func_scalar(aTHX_ *type_gvp, true);
65 } else {
66 return;
67 }
68 }
69 SV* opts = PmArray(proto)[glue::PropertyType_cppoptions_index];
70 if (SvROK(opts)) {
71 SV* builtin = PmArray(opts)[glue::CPPOptions_builtin_index];
72 magic_allowed = !SvTRUE(builtin);
73 }
74 }
75
set_proto_with_prescribed_pkg(SV * prescribed_pkg,SV * app_stash_ref,const std::type_info & ti,SV * super_proto)76 void type_infos::set_proto_with_prescribed_pkg(SV* prescribed_pkg, SV* app_stash_ref, const std::type_info& ti, SV* super_proto)
77 {
78 dTHX;
79 PmStartFuncall(3);
80 PUSHs(prescribed_pkg);
81 const char* const type_name = ti.name();
82 mPUSHp(type_name, strlen(type_name));
83 if (super_proto) PUSHs(super_proto);
84 PUTBACK;
85 proto = glue::call_func_scalar(aTHX_ glue::fetch_typeof_gv(aTHX_ (HV*)SvRV(app_stash_ref), SvPVX(prescribed_pkg), SvCUR(prescribed_pkg)), true);
86 magic_allowed = true;
87 }
88
89 namespace {
90 SV* resolve_auto_function_cv=nullptr;
91 }
92
get_function_wrapper(SV * src,SV * dst_descr,int auto_func_index)93 char* type_cache_base::get_function_wrapper(SV* src, SV* dst_descr, int auto_func_index)
94 {
95 dTHX; dSP;
96 SV* auto_func = PmArray(GvSV(glue::CPP_root))[auto_func_index];
97 char* ret = nullptr;
98 if (!resolve_auto_function_cv)
99 resolve_auto_function_cv = (SV*)get_cv("Polymake::Core::CPlusPlus::resolve_auto_function", FALSE);
100
101 AV* fake_args = newAV();
102 av_extend(fake_args, 2);
103 AvFILLp(fake_args) = 1;
104 AvREAL_off(fake_args);
105 SV* fake_args_ref = newRV_noinc((SV*)fake_args);
106
107 ENTER; SAVETMPS;
108 PUSHMARK(SP);
109 XPUSHs(auto_func);
110 AvARRAY(fake_args)[0] = dst_descr;
111 AvARRAY(fake_args)[1] = src;
112 XPUSHs(fake_args_ref);
113 PUTBACK;
114 call_sv(resolve_auto_function_cv, G_SCALAR | G_EVAL);
115 SPAGAIN;
116 SV* cv = POPs;
117 if (SvROK(cv) && (cv = SvRV(cv), CvISXSUB(cv))) {
118 AV* func_descr = (AV*)CvXSUBANY(cv).any_ptr;
119 ret = reinterpret_cast<char*>(AvARRAY(func_descr)[glue::FuncDescr_wrapper_index]);
120 }
121 PUTBACK; FREETMPS; LEAVE;
122 SvREFCNT_dec(fake_args_ref);
123
124 if (__builtin_expect(SvTRUE(ERRSV), 0))
125 throw exception();
126 return ret;
127 }
128
get_conversion_operator(SV * src,SV * dst_descr)129 char* type_cache_base::get_conversion_operator(SV* src, SV* dst_descr)
130 {
131 return dst_descr ? get_function_wrapper(src, dst_descr, glue::CPP_auto_conversion_index) : nullptr;
132 }
133
get_assignment_operator(SV * src,SV * dst_descr)134 char* type_cache_base::get_assignment_operator(SV* src, SV* dst_descr)
135 {
136 return dst_descr ? get_function_wrapper(src, dst_descr, glue::CPP_auto_assignment_index) : nullptr;
137 }
138
139 namespace {
140
141 inline
perl_error_text()142 const char* perl_error_text()
143 {
144 dTHX;
145 return SvPV_nolen(ERRSV);
146 }
147
148 }
149
exception()150 exception::exception() :
151 std::runtime_error(perl_error_text()) {}
152
153 } }
154
155 // Local Variables:
156 // mode:C++
157 // c-basic-offset:3
158 // indent-tabs-mode:nil
159 // End:
160