NEURON
seclist.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #define HOC_L_LIST 1
4 #include "section.h"
5 #include "neuron.h"
6 #include "nrnpy.h"
7 #include "parse.hpp"
8 #include "hocparse.h"
9 #include "code.h"
10 #include "classreg.h"
11 
12 template <typename F>
13 bool seclist_iterate_remove_until(List* sl, F fun, const Section* sec) {
14  Item* q2 = nullptr;
15  for (Item* q1 = sl->next; q1 != sl; q1 = q2) {
16  q2 = q1->next;
17  if (q1->element.sec->prop == nullptr) {
18  hoc_l_delete(q1);
19  continue;
20  }
21  if (q1->element.sec == sec) {
22  fun(q1);
23  return true;
24  }
25  }
26  return false;
27 }
28 
29 template <typename F>
30 void seclist_iterate_remove(List* sl, F fun) {
31  Item* q2 = nullptr;
32  for (Item* q1 = sl->next; q1 != sl; q1 = q2) {
33  q2 = q1->next;
34  if (q1->element.sec->prop == nullptr) {
35  hoc_l_delete(q1);
36  continue;
37  }
38  fun(q1->element.sec);
39  }
40 }
41 
42 Section* (*nrnpy_o2sec_p_)(Object* o);
43 
45 
46 void lvappendsec_and_ref(void* sl, Section* sec) {
47  lappendsec((List*) sl, sec);
49 }
50 
51 /*ARGSUSED*/
52 static void* constructor(Object* ho) {
53  List* sl;
54  sl = newlist();
55  if (nrnpy_sectionlist_helper_ && ifarg(1)) {
57  }
58  return (void*) sl;
59 }
60 
61 static void destructor(void* v) {
62  Item* q;
63  List* sl = static_cast<List*>(v);
64  ITERATE(q, sl) {
65  section_unref(q->element.sec);
66  }
67  freelist(&sl);
68 }
69 
71 #if USE_PYTHON
72  if (ifarg(i) && nrnpy_o2sec_p_) {
73  Object* o = *hoc_objgetarg(i);
74  return (*nrnpy_o2sec_p_)(o);
75  }
76 #endif
77  return chk_access();
78 }
79 
80 static double append(void* v) {
81  Section* sec = nrn_secarg(1);
82  if (ifarg(2)) {
83  hoc_execerror("Too many parameters. SectionList.append takes 0 or 1 arguments", (char*) 0);
84  }
86  return 1.;
87 }
88 
89 static void children1(List* sl, Section* sec) {
90  for (Section* ch = sec->child; ch; ch = ch->sibling) {
91  lappendsec(sl, ch);
92  section_ref(ch);
93  }
94 }
95 
96 static double children(void* v) {
97  Section* sec = nrn_secarg(1);
98  List* sl = static_cast<List*>(v);
99  children1(sl, sec);
100  return 1.;
101 }
102 
103 // Create a list of section from the subtree with root `sec` by
104 // doing breadth-first traversal.
105 static void subtree1(List* sl, Section* sec) {
106  const Item* end = sl;
107  // The pointer `sl` points to a past-the-end
108  // marker. Therefore, appending items means
109  // they appear immediately before `sl`.
110  Item* current = lappendsec(sl, sec);
111  section_ref(sec);
112  while (current != end) {
113  children1(sl, hocSEC(current));
114  current = current->next;
115  }
116 }
117 
118 static double subtree(void* v) {
119  Section* sec = nrn_secarg(1);
120  List* sl = static_cast<List*>(v);
121  subtree1(sl, sec);
122  return 1.;
123 }
124 
125 static double wholetree(void* v) {
126  Section* sec = nrn_secarg(1);
127  List* sl = static_cast<List*>(v);
128  /*find root*/
129  Section* s = nullptr;
130  for (s = sec; s->parentsec; s = s->parentsec) {
131  }
132 
133  subtree1(sl, s);
134  return 1.;
135 }
136 
137 static double allroots(void* v) {
138  List* sl = static_cast<List*>(v);
139  Item* qsec;
140  ITERATE(qsec, section_list) {
141  Section* sec = hocSEC(qsec);
142  if (!sec->parentsec) {
143  lappendsec(sl, sec);
144  section_ref(sec);
145  }
146  }
147 
148  return 1.;
149 }
150 
151 static double seclist_remove(void* v) {
152  List* sl = static_cast<List*>(v);
153  int i = 0;
154 #if USE_PYTHON
155  if (!ifarg(1) || (*hoc_objgetarg(1))->ctemplate->sym == nrnpy_pyobj_sym_) {
156 #else
157  if (!ifarg(1)) {
158 #endif
159  Section* sec = nrn_secarg(1);
161  sl,
162  [](Item* q) {
163  Section* s = q->element.sec;
164  hoc_l_delete(q);
165  section_unref(s);
166  },
167  sec)) {
168  return 1.;
169  }
170  hoc_warning(secname(sec), "not in this section list");
171  } else {
172  Object* o;
173  o = *hoc_objgetarg(1);
174  check_obj_type(o, "SectionList");
175  seclist_iterate_remove(sl, [](Section* s) { s->volatile_mark = 0; });
176  sl = static_cast<List*>(o->u.this_pointer);
177  seclist_iterate_remove(sl, [](Section* s) { s->volatile_mark = 1; });
178  sl = static_cast<List*>(v);
179  Item* q1;
180  for (Item* q = sl->next; q != sl; q = q1) {
181  q1 = q->next;
182  Section* s = hocSEC(q);
183  if (s->volatile_mark) {
184  hoc_l_delete(q);
185  section_unref(s);
186  ++i;
187  }
188  }
189  }
190  return (double) i;
191 }
192 
193 static double unique(void* v) {
194  Item* q1 = nullptr;
195  List* sl = static_cast<List*>(v);
197  seclist_iterate_remove(sl, [](Section* s) { s->volatile_mark = 0; });
198  int i = 0; /* number deleted */
199  for (Item* q = sl->next; q != sl; q = q1) {
200  q1 = q->next;
201  Section* s = hocSEC(q);
202  if (s->volatile_mark++) {
203  hoc_l_delete(q);
204  section_unref(s);
205  ++i;
206  }
207  }
208  return (double) i;
209 }
210 
211 static double contains(void* v) {
212  List* sl = static_cast<List*>(v);
214  Section* s = nrn_secarg(1);
216  sl, [](Item*) {}, s)
217  ? 1.
218  : 0.;
219 }
220 
221 static double printnames(void* v) {
222  List* sl = static_cast<List*>(v);
223  seclist_iterate_remove(sl, [](Section* s) {
224  if (s->prop) {
225  Printf("%s\n", secname(s));
226  }
227  });
228  return 1.;
229 }
230 
231 double seclist_size(void* v) {
232  double count = 0.;
233  List* sl = static_cast<List*>(v);
234  Item* q2 = nullptr;
235  for (Item* q1 = sl->next; q1 != sl; q1 = q2) {
236  q2 = q1->next;
237  if (q1->element.sec->prop == nullptr) {
238  hoc_l_delete(q1);
239  continue;
240  }
241  count++;
242  }
244  return count;
245 }
246 
247 static Member_func members[] = {{"append", append},
248  {"remove", seclist_remove},
249  {"wholetree", wholetree},
250  {"subtree", subtree},
251  {"children", children},
252  {"unique", unique},
253  {"printnames", printnames},
254  {"contains", contains},
255  {"allroots", allroots},
256  {"size", seclist_size},
257  {nullptr, nullptr}};
258 
259 void SectionList_reg(void) {
260  /* printf("SectionList_reg\n");*/
261  class2oc("SectionList", constructor, destructor, members, nullptr, nullptr);
262 }
263 
264 #define relative(pc) (pc + (pc)->i)
265 extern int hoc_returning;
266 
267 static void check(Object* ob) {
268  if (!ob) {
269  hoc_execerror("nullptr object is not a SectionList", nullptr);
270  }
271  if (ob->ctemplate->constructor != constructor) {
272  hoc_execerror(ob->ctemplate->sym->name, " is not a SectionList");
273  }
274 }
275 
277  /* if arg is a string use forall_section */
278  if (hoc_stacktype() == STRING) {
279  forall_section();
280  return;
281  }
282 
283  Inst* savepc = pc;
284  Object** obp = hoc_objpop();
285  Object* ob = *obp;
286  check(ob);
287  List* sl = static_cast<List*>(ob->u.this_pointer);
288  int istk = nrn_isecstack();
289 
290  Item* q1;
291  for (Item* q = sl->next; q != sl; q = q1) {
292  q1 = q->next;
293  Section* sec = q->element.sec;
294  if (!sec->prop) {
295  hoc_l_delete(q);
297  continue;
298  }
299  nrn_pushsec(sec);
300  hoc_execute(relative(savepc));
301  nrn_popsec();
302  if (hoc_returning) {
303  nrn_secstack(istk);
304  }
305  if (hoc_returning == 1 || hoc_returning == 4) {
306  break;
307  } else if (hoc_returning == 2) {
308  hoc_returning = 0;
309  break;
310  } else {
311  hoc_returning = 0;
312  }
313  }
314  hoc_tobj_unref(obp);
315  if (!hoc_returning) {
316  pc = relative(savepc + 1);
317  }
318 }
319 
321  /* if arg is a string use forall_section */
322  if (hoc_stacktype() == STRING) {
323  hoc_ifsec();
324  return;
325  }
326 
327  Inst* savepc = pc;
328  Section* sec = chk_access();
329  Object** obp = hoc_objpop();
330  Object* ob = *obp;
331  check(ob);
332  List* sl = static_cast<List*>(ob->u.this_pointer);
334  sl,
335  [&](Item*) {
336  hoc_execute(relative(savepc));
337  if (!hoc_returning) {
338  pc = relative(savepc + 1);
339  }
340  hoc_tobj_unref(obp);
341  },
342  sec)) {
343  return;
344  }
345  hoc_tobj_unref(obp);
346  if (!hoc_returning) {
347  pc = relative(savepc + 1);
348  }
349 }
#define STRING
Definition: bbslsrv.cpp:9
Section * chk_access()
Definition: cabcode.cpp:449
const char * secname(Section *sec)
name of section (for use in error messages)
Definition: cabcode.cpp:1674
void nrn_secstack(int i)
Definition: cabcode.cpp:89
void nrn_pushsec(Section *sec)
Definition: cabcode.cpp:130
void forall_section(void)
Definition: cabcode.cpp:1963
int nrn_isecstack(void)
Definition: cabcode.cpp:85
void hoc_ifsec(void)
Definition: cabcode.cpp:2036
void nrn_popsec(void)
Definition: cabcode.cpp:154
void class2oc(const char *, ctor_f *cons, dtor_f *destruct, Member_func *, Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1631
HocReturnType hoc_return_type_code
Definition: code.cpp:42
#define v
Definition: md1redef.h:11
#define sec
Definition: md1redef.h:20
#define i
Definition: md1redef.h:19
int hoc_stacktype()
Definition: code.cpp:774
void check_obj_type(Object *obj, const char *type_name)
Definition: hoc_oop.cpp:2098
#define hocSEC(q)
Definition: hoclist.h:87
void hoc_l_delete(hoc_Item *)
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
#define ITERATE(itm, lst)
Definition: model.h:18
List * newlist()
The following routines support the concept of a list.
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
void section_ref(Section *)
Definition: solve.cpp:520
void section_unref(Section *)
Definition: solve.cpp:509
size_t q
s
Definition: multisend.cpp:521
int ifarg(int)
Definition: code.cpp:1607
hoc_List * section_list
Definition: init.cpp:113
Symbol * nrnpy_pyobj_sym_
Definition: hoc_oop.cpp:25
Object ** hoc_objpop()
Pop pointer to object pointer and return top elem from stack.
Definition: code.cpp:943
void hoc_tobj_unref(Object **)
Definition: code.cpp:160
static List * current
Definition: nrnunit.cpp:13
Item * lappendsec(List *list, Section *sec)
Definition: list.cpp:186
void hoc_execute(Inst *)
Definition: code.cpp:2531
static double subtree(void *v)
Definition: seclist.cpp:118
static double seclist_remove(void *v)
Definition: seclist.cpp:151
static void children1(List *sl, Section *sec)
Definition: seclist.cpp:89
static double printnames(void *v)
Definition: seclist.cpp:221
static double allroots(void *v)
Definition: seclist.cpp:137
int hoc_returning
Definition: code.cpp:81
bool seclist_iterate_remove_until(List *sl, F fun, const Section *sec)
Definition: seclist.cpp:13
double seclist_size(void *v)
Definition: seclist.cpp:231
static Member_func members[]
Definition: seclist.cpp:247
Section *(* nrnpy_o2sec_p_)(Object *o)
Definition: seclist.cpp:42
static double unique(void *v)
Definition: seclist.cpp:193
static double children(void *v)
Definition: seclist.cpp:96
static void * constructor(Object *ho)
Definition: seclist.cpp:52
static void subtree1(List *sl, Section *sec)
Definition: seclist.cpp:105
static void destructor(void *v)
Definition: seclist.cpp:61
void hoc_ifseclist()
Definition: seclist.cpp:320
void(* nrnpy_sectionlist_helper_)(List *, Object *)=0
Definition: seclist.cpp:44
void lvappendsec_and_ref(void *sl, Section *sec)
Definition: seclist.cpp:46
static double contains(void *v)
Definition: seclist.cpp:211
#define relative(pc)
Definition: seclist.cpp:264
static void check(Object *ob)
Definition: seclist.cpp:267
void SectionList_reg(void)
Definition: seclist.cpp:259
void seclist_iterate_remove(List *sl, F fun)
Definition: seclist.cpp:30
static double wholetree(void *v)
Definition: seclist.cpp:125
void forall_sectionlist()
Definition: seclist.cpp:276
static double append(void *v)
Definition: seclist.cpp:80
Section * nrn_secarg(int i)
Definition: seclist.cpp:70
#define pc
Definition: section.h:37
Definition: model.h:8
struct Item * next
Definition: model.h:12
Definition: hocdec.h:173
void * this_pointer
Definition: hocdec.h:178
cTemplate * ctemplate
Definition: hocdec.h:180
union Object::@47 u
char * name
Definition: model.h:61
Symbol * sym
Definition: hocdec.h:147
void *(* constructor)(struct Object *)
Definition: hocdec.h:158
Definition: hocdec.h:42