erple.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #include "erplb.c" // builtin functions
  2. // TODO rethink stack pushing mechanism
  3. // expressions evaluation:
  4. void* (builtin_lookup) (int* name) {
  5. for (int a = 0; builtin_commands[a].name[0] != 0; a++) {
  6. if (symbols_are_equal(builtin_commands[a].name, name)) {
  7. return builtin_commands[a].operation;
  8. }
  9. }
  10. return NULL;
  11. }
  12. Table* atom_lookup (int* name, Table* context) {
  13. Table *t = table_lookup(context, name);
  14. if (!t) t = table_lookup(globals, name);
  15. return t;
  16. }
  17. Atom* eval (Atom* expr, Table** context) {
  18. if (!expr)
  19. return NULL;
  20. if (is_simple(expr)) {
  21. if (is_symbol(expr))
  22. return eval_symbol(expr->symb, NULL, context);
  23. return expr;
  24. }
  25. if (is_list(expr))
  26. return eval_application(expr->list, context);
  27. return expr;
  28. }
  29. Atom* eval_symbol (int* symb, List* args, Table** context) {
  30. Atom *newhead = NULL, *value = NULL;
  31. Atom *(*fn)(List*,Table**);
  32. Table *t = table_lookup(*context, symb);
  33. if (!t) t = table_lookup(globals, symb);
  34. if (t) {
  35. if (!t->value)
  36. goto error;
  37. switch (t->value->type) {
  38. case SYMB:
  39. fn = builtin_lookup(t->value->symb);
  40. if (!fn)
  41. goto error;
  42. value = fn(args, context);
  43. break;
  44. case LIST:
  45. newhead = eval_application(t->value->list, context);
  46. if (!newhead)
  47. goto error;
  48. switch (newhead->type) {
  49. case LAMBDA:
  50. value = eval_lambda(newhead->list, args, context);
  51. break;
  52. case SYMB:
  53. fn = builtin_lookup(newhead->symb);
  54. if (!fn)
  55. goto error;
  56. value = fn(args, context);
  57. break;
  58. default:
  59. goto error;
  60. }
  61. goto end;
  62. case LAMBDA:
  63. value = eval_lambda(t->value->list, args, context);
  64. break;
  65. default:
  66. goto error;
  67. }
  68. goto end;
  69. }
  70. fn = builtin_lookup(symb);
  71. if (!fn)
  72. goto error;
  73. value = fn(args, context);
  74. goto end;
  75. error:
  76. free_atom(newhead);
  77. return _warning("EVAL(symbol)" INVALID_ARGS);
  78. end:
  79. free_atom(newhead);
  80. return value;
  81. }
  82. Atom* eval_application (List* appl, Table** context) {
  83. Atom *newhead = NULL, *value = NULL;
  84. if (!appl || !appl->head)
  85. goto error;
  86. switch (appl->head->type) {
  87. case LAMBDA:
  88. value = eval_lambda(appl->head->list, appl->tail, context);
  89. break;
  90. case SYMB:
  91. value = eval_symbol(appl->head->symb, appl->tail, context);
  92. break;
  93. case LIST:
  94. newhead = eval_application(appl->head->list, context);
  95. if (!newhead)
  96. goto error;
  97. switch (newhead->type) {
  98. case SYMB:
  99. value = eval_symbol(newhead->symb, appl->tail, context);
  100. break;
  101. default:
  102. goto error;
  103. }
  104. default:
  105. goto error;
  106. }
  107. free_atom(newhead);
  108. return value;
  109. error:
  110. free_atom(newhead);
  111. return _warning("EVAL(application)" INVALID_ARGS);
  112. }
  113. Atom* eval_lambda (List* body, List* arguments, Table** context) {
  114. #warning TODO
  115. if (!valid_lambda(body))
  116. return _warning("EVAL(lambda)" INVALID_ARGS);
  117. if (!define_local_vars(body->head->list, arguments, context))
  118. return _warning("EVAL(lambda)" INSUFFICIENT_ARGS_STK);
  119. //
  120. //
  121. destroy_local_vars(body, context);
  122. }
  123. unsigned define_local_vars (List* arg_names, List* values, Table** context) {
  124. Table *local_vars = NULL;
  125. // normal application
  126. while (arg_names && values) {
  127. table_set(&local_vars, arg_names->head->symb, values->head);
  128. arg_names = arg_names->tail;
  129. values = values->tail;
  130. }
  131. // partial application
  132. while (arg_names) {
  133. if (!stack) {
  134. free_table(local_vars);
  135. return 0;
  136. }
  137. table_set(&local_vars, arg_names->head->symb, stack->head);
  138. arg_names = arg_names->tail;
  139. }
  140. table_union(local_vars, context);
  141. return 1;
  142. }
  143. void destroy_local_vars (List* arg_names, Table** context) {
  144. while (arg_names) {
  145. table_unset(context, arg_names->head->symb);
  146. arg_names = arg_names->tail;
  147. }
  148. }