initop.hpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* Declarations for init operations.
  2. This file is part of khipu.
  3. khipu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #ifndef __KP_INITOP__
  14. #define __KP_INITOP__ 1
  15. #include "defs.hpp"
  16. KP_DECLS_BEGIN
  17. struct interpreter;
  18. struct init_op;
  19. struct init_op_list
  20. {
  21. dlist ops;
  22. const char *errmsg;
  23. init_op_list ()
  24. {
  25. this->ops.init_head ();
  26. this->errmsg = nullptr;
  27. }
  28. inline void add (init_op *op);
  29. static init_op_list& global_ops ();
  30. bool call (interpreter *interp);
  31. };
  32. struct init_op
  33. {
  34. enum
  35. {
  36. st_init,
  37. st_wip,
  38. st_done
  39. };
  40. enum
  41. {
  42. result_ok,
  43. result_circular,
  44. result_failed
  45. };
  46. int state;
  47. int (*cb) (interpreter *);
  48. const char *name;
  49. dlist link;
  50. template <typename ...Args>
  51. static int call_deps (interpreter *interp, Args... args)
  52. {
  53. init_op *deps[] = { args... };
  54. int ret = result_ok;
  55. for (auto p : deps)
  56. if ((ret = p->call (interp)) != result_ok)
  57. break;
  58. return (ret);
  59. }
  60. init_op (int (*cb) (interpreter *), const char *nm) :
  61. state (st_init), cb (cb), name (nm)
  62. {
  63. init_op_list::global_ops().add (this);
  64. }
  65. static int fail (const char *msg)
  66. {
  67. init_op_list::global_ops().errmsg = msg;
  68. return (init_op::result_failed);
  69. }
  70. int call (interpreter *interp)
  71. {
  72. if (this->state == st_wip)
  73. return (result_circular);
  74. else if (this->state == st_done)
  75. return (result_ok);
  76. this->state = st_wip;
  77. int ret = this->cb (interp);
  78. if (ret == result_ok)
  79. this->state = st_done;
  80. return (ret);
  81. }
  82. };
  83. void init_op_list::add (init_op *op)
  84. {
  85. this->ops.add (&op->link);
  86. }
  87. // Initialize the full khipu API.
  88. KP_EXPORT bool khipu_init ();
  89. KP_DECLS_END
  90. #endif