1 #include <../../nrnconf.h>
34 #define EXTERNAL_TYPE 2
57 auto const code =
hoc_oc(
"objref hoc_obj_[2]\n");
93 for (
i = a->
nsub - 1;
i >= 0; --
i) {
118 for (
i = a->
nsub - 1;
i >= 0; --
i) {
157 if (sym->
type != UNDEF) {
177 OPSTR(sym) = (
char**) 0;
200 #define NTEMPLATESTACK 20
211 #define pushtemplatesym(arg) \
213 (templatestackp++)->sym = arg
214 #define pushtemplatesymlist(arg) \
216 (templatestackp++)->symlist = arg
217 #define pushtemplatei(arg) \
219 (templatestackp++)->i = arg
220 #define pushtemplateodata(arg) \
222 (templatestackp++)->odata = arg
223 #define pushtemplateo(arg) \
225 (templatestackp++)->o = arg
237 #define OBJ_STACK_SIZE 10
244 hoc_execerror(
"Can't do object_push for built-in class",
nullptr);
247 hoc_execerror(
"too many object context stack depth",
nullptr);
333 hoc_execerror(
"Can't execute in a built-in class context",
nullptr);
363 auto pbuf_size = 256;
364 if (strlen(cmd) > 256 - 10) {
367 pbuf_size = hs->
size + 1;
370 std::snprintf(pbuf, pbuf_size,
"%s\n", cmd + 1);
372 std::snprintf(pbuf, pbuf_size,
"{%s}\n", cmd);
458 printf(
"new object from template %s created.\n", symtemp->
name);
518 if (
s->cpublic != 2) {
522 ++
s->arayinfo->refcount;
525 obd[
s->u.oboff].
pval = (
double*)
emalloc(total *
sizeof(
double));
526 for (
i = 0;
i < total;
i++) {
527 (obd[
s->u.oboff].
pval)[
i] = 0.;
534 **(obd[
s->u.oboff].
ppstr) =
'\0';
538 ++
s->arayinfo->refcount;
542 for (
i = 0;
i < total;
i++) {
545 if (strcmp(
s->name,
"this") == 0) {
546 obd[
s->u.oboff].
pobj[0] = ob;
551 ++
s->arayinfo->refcount;
599 Object** obp = hoc_look_inside_stack<Object**>(
narg);
608 hoc_execerror(
"Assignment to $o only allowed if caller arg was declared as objref",
627 [ob]() -> std::string {
629 rval.append(
" constructor");
654 Inst *pcsav, callcode[4];
669 auto const error_prefix_generator = [ob, sym]() {
672 rval.append(sym->
name);
675 if (sym->
type == OBFUNCTION) {
687 }
else if (sym->
type == STRFUNCTION) {
703 callcode[1].
sym = sym;
704 callcode[2].
i =
narg;
711 if (sym->
type == PROCEDURE) {
731 Inst *stmtbegin, *stmtend;
741 stmtobj = hoc_look_inside_stack<Object*>(
narg + 1);
742 stmtbegin =
pc +
pc->i;
744 stmtend =
pc +
pc->i;
763 printf(
"declareing %s as objectvar\n", sym->
name);
765 if (sym->
type == OBJECTVAR) {
768 for (
i = 0;
i < total;
i++) {
774 sym->
type = OBJECTVAR;
784 for (
i = 0;
i < size;
i++) {
805 printf(
"code for hoc_objectvar()\n");
835 printf(
"code for hoc_objectarg()\n");
874 if (!sym || sym->
type != TEMPLATE) {
929 if (sym->
type == RANGEVAR) {
984 int nindex,
narg, cplus, isfunc;
991 printf(
"code for hoc_object_component()\n");
1009 int expect_stack_nsub{0};
1012 hoc_execerror(
"[...](...) syntax only allowed for array range variables:", sym0->
name);
1017 expect_stack_nsub = 1;
1056 auto err = fmt::format(
"'{}' not a public member of '{}'",
1059 Fprintf(stderr, fmt::format(
"{}\n", err).c_str());
1077 switch (sym->
type) {
1156 if (expect_stack_nsub) {
1172 case HOCOBJFUNCTION:
1175 if (expect_stack_nsub) {
1275 if ((
pc++)->
i != ITERATOR) {
1320 auto dh = hoc_pop_handle<double>();
1349 printf(
"code for hoc_object_eval\n");
1355 auto* d_sym = hoc_look_inside_stack<Symbol*>(0);
1356 if (d_sym->type == RANGEVAR) {
1367 }
else if (d_sym->type == VAR && d_sym->subtype ==
USERPROPERTY) {
1375 printf(
"code for hoc_ob_pointer\n");
1380 auto* d_sym = hoc_look_inside_stack<Symbol*>(0);
1381 if (d_sym->type == RANGEVAR) {
1385 double x = nindex ?
hoc_xpop() : .5;
1387 }
else if (d_sym->type == VAR && d_sym->subtype ==
USERPROPERTY) {
1409 auto* sym = hoc_look_inside_stack<Symbol*>(1);
1410 if (sym->type == RANGEVAR) {
1412 }
else if (sym->type == VAR && sym->subtype ==
USERPROPERTY) {
1416 if (type2 == RANGEVAR && type1 == NUMBER) {
1455 hoc_execerror(
"Invalid assignment operator for object",
nullptr);
1472 hoc_execerror(
"Invalid assignment operator for string",
nullptr);
1484 hoc_execerror(
"Invalid assignment operator for PythonObject",
nullptr);
1498 if (
s->type != TEMPLATE) {
1501 if (!s1 || s1->
type != TEMPLATE) {
1521 printf(
"begin template %s\n",
t->name);
1524 if (
type == TEMPLATE) {
1528 }
else if (
type != UNDEF) {
1529 hoc_execerror(
t->name,
"already used as something besides template");
1533 t->u.ctemplate->sym =
t;
1534 t->u.ctemplate->symtable = (
Symlist*) 0;
1535 t->u.ctemplate->dataspace_size = 0;
1536 t->u.ctemplate->constructor = 0;
1537 t->u.ctemplate->destructor = 0;
1538 t->u.ctemplate->is_point_ = 0;
1539 t->u.ctemplate->steer = 0;
1556 printf(
"end template %s\n",
t->name);
1559 if (strcmp(ts->
name,
t->name) != 0) {
1575 if (
s &&
s->type != PROCEDURE) {
1576 hoc_execerror(
"'init' can only be used as the initialization procedure for new objects",
1580 if (
s &&
s->type != PROCEDURE) {
1582 "'unref' can only be used as the callback procedure when the reference count is "
1610 t->constructor =
cons;
1617 s->u.u_proc->defn.pfd_vp = m[
i].
member;
1621 for (
i = 0; mobjret[
i].
name; ++
i) {
1623 s->u.u_proc->defn.pfo_vp = mobjret[
i].
member;
1627 for (
i = 0; strret[
i].
name; ++
i) {
1629 s->u.u_proc->defn.pfs_vp = strret[
i].
member;
1664 printf(
"public name %s with type %d\n",
s->name,
s->type);
1692 case HOCOBJFUNCTION:
1715 if (
t == OBJECTVAR) {
1720 if (
t == OBJECTVAR) {
1722 printf(
"dymnamic checking of type=%d\n",
type);
1726 }
else if (
type !=
t) {
1730 if (
t != OBJECTVAR) {
1746 if (
s->type == OBJECTVAR &&
s->cpublic != 2) {
1748 for (
i = 0;
i < total;
i++) {
1749 obp =
data[
s->u.oboff].pobj +
i;
1752 if ((*obp)->ctemplate == ctemplate) {
1758 (*obp)->u.dataspace);
1765 (*obp)->u.dataspace);
1767 if ((*obp)->ctemplate == ctemplate) {
1777 #define objectpath hoc_objectpath_impl
1778 #define pathprepend hoc_path_prepend
1819 if (
s->type == OBJECTVAR &&
s->cpublic != 2) {
1821 for (
i = 0;
i < total;
i++) {
1822 obp = od[
s->u.oboff].
pobj +
i;
1823 if (*obp && *obp != oblook &&
objectpath(ob, *obp, path, depth)) {
1840 hoc_warning(
"Couldn't find a pathname to the object pointer",
1859 if (obj == (
Object*) 0) {
1868 struct helper_in_case_dtor_throws {
1869 helper_in_case_dtor_throws(
Object* obj)
1871 ~helper_in_case_dtor_throws() {
1872 if (--m_obj->ctemplate->count <= 0) {
1875 m_obj->ctemplate =
nullptr;
1915 helper_in_case_dtor_throws _{obj};
1921 rval.append(
" destructor");
1947 if (
s->cpublic != 2) {
1960 if (strcmp(
"this",
s->name) != 0) {
1962 for (
i = 0;
i < total;
i++) {
1971 for (
i = 0;
i < total; ++
i) {
2024 if (
s->type == TEMPLATE) {
2028 for (
i = 0;
i < nspace; ++
i) {
2043 if (
s &&
s->type == TEMPLATE) {
2047 for (
i = 0;
i < nspace; ++
i) {
2072 if (
s->type == OBJECTVAR &&
s->cpublic != 2) {
2074 for (
i = 0;
i < total;
i++) {
2075 obp =
data[
s->u.oboff].pobj +
i;
2076 for (
id = 0;
id < depth;
id++) {
2080 Printf(
"obp %s[%d] -> %s with %d refs.\n",
2086 Printf(
"obp %s[%d] -> NULL\n",
s->name,
i);
2089 (*obp)->u.dataspace !=
data
2092 (*obp)->recurse = 1;
2094 (*obp)->u.dataspace,
2096 (*obp)->recurse = 0;
2109 Sprintf(
buf,
"object type is nullptr instead of");
2139 Object* obj1 = *obj1_ptr;
2140 Object* obj2 = *obj2_ptr;
2143 hoc_execerror(
"Object arithmetic: first operand is null",
nullptr);
2178 hoc_execerror(
"Object arithmetic: object operand is null",
nullptr);
2211 hoc_execerror(
"Object arithmetic: object operand is null",
nullptr);
2265 const char* method_name,
2274 if (!obj1 || !obj2) {
2275 double result = is_equality ? ((*obj1_ptr == *obj2_ptr) ? 1.0 : 0.0)
2276 : ((*obj1_ptr != *obj2_ptr) ? 1.0 : 0.0);
2307 double result = is_equality ? ((*obj1_ptr == *obj2_ptr) ? 1.0 : 0.0)
2308 : ((*obj1_ptr != *obj2_ptr) ? 1.0 : 0.0);
void nrn_pushsec(Section *sec)
double cable_prop_eval(Symbol *sym)
void cable_prop_assign(Symbol *sym, double *pd, int op)
void nrn_rangeconst(Section *sec, Symbol *s, neuron::container::data_handle< double > pd, int op)
int node_index(Section *sec, double x)
returns nearest index to x
void new_sections(Object *ob, Symbol *sym, Item **pitm, int size)
Prop * nrn_mechanism_check(int type, Section *sec, int inode)
returns prop given mech type, section, and inode error if mech not at this position
neuron::container::data_handle< double > nrn_rangepointer(Section *sec, Symbol *s, double d)
void ob_sec_access_push(hoc_Item *qsec)
double * cable_prop_eval_pointer(Symbol *sym)
Symbol * hoc_table_lookup(const char *, Symlist *)
void hoc_iterator_object(Symbol *sym, int argcount, Inst *beginpc, Inst *endpc, Object *ob)
double chkarg(int, double low, double high)
static void destruct(void *v)
static void * cons(Object *o)
char * hoc_object_pathname(Object *ob)
void hoc_push_frame(Symbol *sp, int narg)
Object * hoc_name2obj(const char *name, int index)
void hoc_obj_set(int i, Object *obj)
void hoc_push_ndim(int d)
void hoc_construct_point(Object *, int)
int hoc_obj_run(const char *cmd, Object *ob)
Brief explanation of hoc_obj_run.
void * nrn_opaque_obj2pyobj(Object *ho)
void hoc_pushstr(char **d)
Object * nrn_nmodlrandom_wrap(Prop *prop, Symbol *sym)
double hoc_call_func(Symbol *s, int narg)
int ivoc_list_look(Object *ob, Object *oblook, char *path, int)
void hoc_new_object_asgn(Object **obp, Symbol *st, void *v)
size_t hoc_total_array_data(const Symbol *s, Objectdata *obd)
int hoc_arayinfo_install(Symbol *sp, int nsub)
Object ** hoc_temp_objvar(Symbol *symtemp, void *v)
void hoc_template_notify(Object *ob, int message)
void hoc_pushpx(double *d)
int hoc_inside_stacktype(int i)
void hoc_pushobj(Object **d)
int hoc_errno_check(void)
void hoc_call_ob_proc(Object *ob, Symbol *sym, int narg)
Object * hoc_obj_get(int i)
void hoc_freearay(Symbol *sp)
Symbol * hoc_install(const char *, int, double, Symlist **)
void hoc_free_object(Object *)
int hoc_is_str_arg(int narg)
void hoc_free_pstring(char **)
bool hoc_stack_type_is_ndim()
void hoc_oop_initaftererror(void)
Object * nrn_pntproc_nmodlrandom_wrap(void *v, Symbol *sym)
Objectdata * hoc_objectdata
void hoc_assign_str(char **cpp, const char *buf)
double hoc_opasgn(int op, double dest, double src)
double hoc_call_objfunc(Symbol *s, int narg, Object *ob)
Object * hoc_new_object(Symbol *symtemp, void *v)
int is_obj_type(Object *obj, const char *type_name)
int hoc_oc(const char *buf)
void check_obj_type(Object *obj, const char *type_name)
void hoc_obj_disconnect(Object *ob)
void hoc_obj_ref(Object *obj)
char * hoc_object_name(Object *ob)
void ivoc_free_alias(Object *ob)
void hoc_dec_refcount(Object **pobj)
void hoc_free_val_array(double *, std::size_t)
void hoc_install_object_data_index(Symbol *sp)
size_t hoc_total_array(Symbol *s)
Symbol * hoc_lookup(const char *)
void hoc_free_arrayinfo(Arrayinfo *a)
void hoc_obj_unref(Object *obj)
Symbol * ivoc_alias_lookup(const char *name, Object *ob)
void hoc_free_allobjects(cTemplate *ctemplate, Symlist *sl, Objectdata *data)
char * hoc_araystr(Symbol *sym, int index, Objectdata *obd)
void hoc_push_object(Object *d)
void hoc_push(neuron::container::generic_data_handle handle)
HocStr * hocstr_create(size_t size)
void hocstr_delete(HocStr *hs)
void hoc_number_mul_object()
#define pushtemplatesym(arg)
void oc_save_hoc_oop(Object **a1, Objectdata **a2, int *a4, Symlist **a5)
Objectdata * hoc_objectdata_restore(Objectdata *obdsav)
static void call_constructor(Object *, Symbol *, int)
#define pushtemplatesymlist(arg)
void hoc_allobjects(void)
static bool hoc_object_comparison_setup(Object **&obj1_ptr, Object **&obj2_ptr, Object *&obj1, Object *&obj2, const char *method_name, bool is_equality)
#define pushtemplatei(arg)
static Object * obj_stack_[OBJ_STACK_SIZE+1]
static void hoc_number_object_binary_op_helper(const char *method_name)
static Templatedatum * poptemplate(void)
int(* nrnpy_call_obj_method_double)(Object *obj, const char *method, double value)
static int connect_obsec_
void hoc_allobjectvars(void)
static Templatedatum templatestack[NTEMPLATESTACK]
void hoc_object_pow_number()
void hoc_install_hoc_obj(void)
static void call_ob_iter(Object *ob, Symbol *sym, int narg)
Symbol * hoc_decl(Symbol *s)
Objectdata * hoc_objectdata_save(void)
void hoc_external_var(Symbol *s)
void hoc_number_div_object()
Symbol * nrnpy_pyobj_sym_
void hoc_asgn_obj_to_str(void)
int hoc_max_builtin_class_id
static void hoc_object_comparison_fallback(Object **obj1_ptr, Object **obj2_ptr, bool is_equality)
Symbol * hoc_which_template(Symbol *s)
void hoc_constobject(void)
void hoc_number_sub_object()
static void free_objectdata(Objectdata *, cTemplate *)
void hoc_obvar_declare(Symbol *sym, int type, int pmes)
std::vector< const char * > py_exposed_classes
int hoc_print_first_instance
void class2oc_base(const char *name, ctor_f *cons, dtor_f *destruct, Member_func *m, Member_ret_obj_func *mobjret, Member_ret_str_func *strret)
void hoc_number_add_object()
struct Section * nrn_sec_pop()
static void hoc_list_allobjref(Symlist *, Objectdata *, int)
void hoc_object_add_number()
#define pushtemplateo(arg)
void hoc_ob_check(int type)
void hoc_endtemplate(Symbol *t)
void hoc_object_sub_number()
Object * hoc_newobj1(Symbol *sym, int narg)
static Templatedatum * templatestackp
static void hoc_object_binary_op_helper(const char *method_name)
int(* nrnpy_call_obj_method)(Object *obj, const char *method, Object *obj2)
void hoc_object_push(void)
void hoc_newobj_ret(void)
void hoc_object_component()
static void hoc_allobjects2(Symbol *s, int nspace)
static void hoc_object_number_binary_op_helper(const char *method_name)
void hoc_object_eval(void)
void hoc_object_pushed(void)
static int icntobjectdata
Object * nrn_get_gui_redirect_obj()
static void chktemplate(void)
void hoc_begintemplate(Symbol *t1)
void class2oc(const char *name, ctor_f *cons, dtor_f *destruct, Member_func *m, Member_ret_obj_func *mobjret, Member_ret_str_func *strret)
void oc_restore_hoc_oop(Object **a1, Objectdata **a2, int *a4, Symlist **a5)
void hoc_object_pop(void)
void hoc_objvardecl(void)
void hoc_ob_pointer(void)
static void range_suffix(Symbol *sym, int nindex, int narg)
void hoc_add_publiclist(Symbol *s)
void connect_obsec_syntax(void)
void hoc_object_div_number()
constexpr std::size_t hoc_object_pathname_bufsize
static void hoc_allobjects1(Symlist *sl, int nspace)
void hoc_number_pow_object()
Objectdata * hoc_top_level_data
void hoc_newobj_arg(void)
#define pushtemplateodata(arg)
void hoc_push_current_object(void)
void hoc_known_type(void)
void hoc_object_mul_number()
int hoc_resize_toplevel(int more)
static Object * gui_redirect_obj_
static void hoc_object_comparison_call(Object **obj1_ptr, Object **obj2_ptr, Object *obj1, Symbol *method_sym)
bool is_array(const Symbol &sym)
hoc_List * hoc_l_newlist()
hoc_Item * hoc_l_lappendobj(hoc_List *, struct Object *)
void hoc_l_delete(hoc_Item *)
int special_pnt_call(Object *ob, Symbol *sym, int narg)
Object ** hoc_objgetarg(int)
Symlist * hoc_top_level_symlist
int hoc_araypt(Symbol *, int)
#define ITERATE(itm, lst)
void move(Item *q1, Item *q2, Item *q3)
void hoc_execerror(const char *s1, const char *s2)
void * erealloc(void *ptr, size_t size)
void * ecalloc(size_t n, size_t size)
static void * emalloc(size_t size)
void hoc_warning(const char *s1, const char *s2)
constexpr do_not_search_t do_not_search
decltype(auto) invoke_method_that_may_throw(Callable message_prefix, Args &&... args)
Execute C++ code that may throw and propagate HOC information.
impl_ptrs methods
Collection of pointers to functions with python-version-specific implementations.
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Type-safe sprintf replacement using snprintf with automatic buffer size deduction.
void nrn_method_call(Object *obj, Symbol *method_sym, int narg)
Symbol * nrn_method_symbol(const Object *obj, char const *const name)
void sec_free(hoc_Item *)
int const size_t const size_t n
void destroy_point_process(void *)
Object * hoc_obj_look_inside_stack(int)
Object ** hoc_objpop()
Pop pointer to object pointer and return top elem from stack.
void hoc_tobj_unref(Object **)
static void * opaque_obj2pyobj(Object *ho)
Section * nrn_sectionref_steer(Section *sec, Symbol *sym, int *pnindex)
Object ** hoc_temp_objptr(Object *)
void hoc_free_symspace(Symbol *)
Symlist * hoc_built_in_symlist
struct Object **(* member)(void *)
const char **(* member)(void *)
struct Symbol::@45::@46 rng
void(* destructor)(void *)
void *(* constructor)(struct Object *)
void(* hpoasgn)(Object *, int)
void *(* opaque_obj2pyobj)(Object *)
void(* py2n_component)(Object *, Symbol *, int, int)
int Fprintf(FILE *stream, const char *fmt, Args... args)
int Printf(const char *fmt, Args... args)