Инструменты пользователя

Инструменты сайта


bug_ref_fn

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
bug_ref_fn [2025/12/14 03:26] – создано snegovickbug_ref_fn [2025/12/15 11:29] (текущий) – [Workaround] snegovick
Строка 1: Строка 1:
-Эта страница посвящена поиску бага связанного с вызовом функции init в произвольном модуле из модуля, в котором используются ссылки на функции.+Эта страница посвящена поиску бага связанного с вызовом функции init в произвольном модуле из другого модуля, в котором используются ссылки на функции.
  
 +[[https://github.com/inferno-os/inferno-os/issues/31]]
  
 +====== Описание ======
 +
 +В коде приведённом ниже есть есть функции empty и init. В init производится попытка вызова функции init из модуля echo (как это происходит в шелле). В случае если раскоментирован блок
 +<code>
 +#fp:= empty;
 +</code>
 +
 +или любой из if (0) включен, вызов не срабатывает:
 +<code>
 +link typecheck Echo->empty() 0/9cd71c5e
 +echo: link typecheck Echo->empty() 0/9cd71c5e
 +</code>
 +
 +Очевидно, что вместо init вызывается empty, которого в модуле echo нет.
 +
 +<code>
 +implement Sh93;
 +
 +include "sys.m";
 +  sys: Sys;
 +
 +include "draw.m";
 +
 +Sh93: module
 +{
 +  init: fn(ctxt: ref Draw->Context, argv: list of string);
 +};
 +
 +SomeT: adt {
 +  f: ref fn();
 +};
 +
 +empty() {
 +  sys->print("empty\n");
 +}
 +
 +init(ctxt: ref Draw->Context, argv: list of string)
 +{
 +  sys = load Sys Sys->PATH;
 +
 +  #fp:= empty;
 +
 +  if (0)
 +  {
 +    st:= ref SomeT;
 +    st.f = empty;
 +    st.f();
 +  }
 +
 +  file := "echo.dis";
 +
 +  args : list of string;
 +  args = "\"test\"" :: args;
 +  args = "echo" :: args;
 +  
 +  c := load Sh93 file;
 +  if(c == nil) {
 +    err := sys->sprint("%r");
 +    if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){
 +      c = load Sh93 "/dis/"+file;
 +      if(c == nil) {
 +        err = sys->sprint("%r");
 +      }
 +    }
 +    if(c == nil) {
 +      sys->print("%s: %s\n", "echo", err);
 +      return;
 +    }
 +  }
 +  
 +  c->init(ctxt, args);
 +
 +  if (0)
 +  {
 +    st:= ref SomeT;
 +    st.f = empty;
 +    st.f();
 +  }
 +}
 +</code>
 +
 +====== Workaround ======
 +
 +Добавление проблемной функции в объявление модуля помогает решить проблему:
 +
 +<code>
 +Sh93: module
 +{
 +  init: fn(ctxt: ref Draw->Context, argv: list of string);
 +  empty: fn();
 +};
 +</code>
 +
 +Lets check libinterp/link.c. The error manifests itself in linkm proc (thats where "link typecheck" message comes from), for some reason empty is in m->ext array (interp.h / struct Module comment calls m->ext: "External dynamic links") and this loop:
 +[ for(l = m->ext; l->name; l++)](https://github.com/inferno-os/inferno-os/blob/d7b29f497205f48247d2bab33340bd7ace64de4d/libinterp/link.c#L41)
 +iterates over init and empty.
 +
 +When you add empty to module definition explicitly, then this loop only makes single iteration with init.
 +
 +Limbo does not have anonymous functions (lambdas) as far as I know, so this issue just leads to inconvenience of declaration of functions you normally would prefer not to declare.
bug_ref_fn.1765682798.txt.gz · Последнее изменение: snegovick