PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/vintage/xvm/tcomp.c

http://github.com/maximk/teeterl
C | 293 lines | 221 code | 25 blank | 47 comment | 170 complexity | f1bf535bfeb65464eb4deb53d2510275 MD5 | raw file
  1. /*
  2. * Copyright (c) 2009, Maxim Kharchenko
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the author nor the names of his contributors
  13. * may be used to endorse or promote products derived from this software
  14. * without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY Maxim Kharchenko ''AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL Maxim Kharchenko BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "tcomp.h"
  28. // to make local pids compare correctly
  29. extern term_t my_node;
  30. extern term_t my_prev_node;
  31. extern apr_uint32_t my_creation;
  32. int terms_are_equal(term_t a, term_t b, int exact)
  33. {
  34. //Literals are coalesced on module load
  35. //if (is_pinned(a) && is_pinned(b))
  36. // return a == b;
  37. //but,
  38. //not always, e.g. 52.00 and {52.00}
  39. //coalescing subterms may increase loading
  40. //time but let us revisit this some day
  41. //TODO: see above
  42. return terms_are_equal0(a, b, exact);
  43. }
  44. //same as above but with no regard to pinning
  45. int terms_are_equal0(term_t a, term_t b, int exact)
  46. {
  47. if (a == b)
  48. return 1;
  49. if (is_bignum(a) && is_bignum(b))
  50. return bignum_are_equal(bn_value(a), bn_value(b));
  51. if (is_float(a) && is_float(b))
  52. return dbl_value(a) == dbl_value(b);
  53. else if (is_cons(a) && is_cons(b))
  54. {
  55. //const char *s1;
  56. //const char *s2;
  57. //apr_pool_t *p;
  58. //apr_pool_create(&p, 0);
  59. //s1 = stringify_term(a, 0, p);
  60. //s2 = stringify_term(b, 0, p);
  61. do {
  62. if (terms_are_equal(lst_value(a), lst_value(b), exact) != 1)
  63. return 0;
  64. a = lst_next(a);
  65. b = lst_next(b);
  66. } while (is_cons(a) && is_cons(b));
  67. return is_nil(a) && is_nil(b);
  68. }
  69. else if (is_tuple(a) && is_tuple(b))
  70. {
  71. int i;
  72. if (tup_size(a) != tup_size(b))
  73. return 0;
  74. for (i = 0; i < int_value2(tup_size(a)); i++)
  75. if (terms_are_equal(tup_elts(a)[i], tup_elts(b)[i], exact) != 1)
  76. return 0;
  77. return 1;
  78. }
  79. else if (is_binary(a) && is_binary(b))
  80. {
  81. int d;
  82. if (bin_size(a) != bin_size(b))
  83. return 0;
  84. d = memcmp(bin_data(a), bin_data(b), int_value2(bin_size(a)));
  85. return d == 0;
  86. }
  87. else if (is_fun(a) && is_fun(b))
  88. {
  89. if (fun_amod(a) != fun_amod(b))
  90. return 0;
  91. if (fun_afun(a) != fun_afun(b))
  92. return 0;
  93. if (fun_arity(a) != fun_arity(b))
  94. return 0;
  95. return terms_are_equal(fun_fridge(a), fun_fridge(b), exact);
  96. }
  97. else if (is_pid(a) && is_pid(b))
  98. {
  99. term_t n1 = pid_node(a);
  100. term_t n2 = pid_node(b);
  101. if (n1 == my_node || n1 == my_prev_node) n1 = A_LOCAL;
  102. if (n2 == my_node || n2 == my_prev_node) n2 = A_LOCAL;
  103. if (n1 != n2)
  104. return 0;
  105. if (pid_serial(a) != pid_serial(b))
  106. return 0;
  107. return pid_creation(a) == pid_creation(b);
  108. }
  109. else if (is_ref(a) && is_ref(b) || is_port(a) && is_port(b))
  110. {
  111. term_t n1 = prp_node(a);
  112. term_t n2 = prp_node(b);
  113. if (n1 == my_node || n1 == my_prev_node) n1 = A_LOCAL;
  114. if (n2 == my_node || n2 == my_prev_node) n2 = A_LOCAL;
  115. if (n1 != n2)
  116. return 0;
  117. if (prp_serial(a) != prp_serial(b))
  118. return 0;
  119. return prp_creation(a) == prp_creation(b);
  120. }
  121. else if (exact)
  122. return 0;
  123. else if (is_int(a) && is_float(b))
  124. return (double)int_value(a) == dbl_value(b);
  125. else if (is_float(a) && is_int(b))
  126. return dbl_value(a) == (double)int_value(b);
  127. else if (is_bignum(a) && is_float(b))
  128. return bignum_to_double(bn_value(a)) == dbl_value(b);
  129. else if (is_float(a) && is_bignum(b))
  130. return dbl_value(a) == bignum_to_double(bn_value(b));
  131. else
  132. return 0;
  133. }
  134. int terms_are_more(term_t a, term_t b, atoms_t *atoms)
  135. {
  136. return terms_are_less(b, a, atoms);
  137. }
  138. int terms_are_less(term_t a, term_t b, atoms_t *atoms)
  139. {
  140. if (is_int(a) && is_bignum(b)) // int is always less than bignum (unless bignum is negative)
  141. return !bn_sign(bn_value(b));
  142. else if (is_bignum(a) && is_int(b))
  143. return bn_sign(bn_value(a));
  144. else if (is_bignum(a) && is_bignum(b))
  145. return bignum_are_less(bn_value(a), bn_value(b));
  146. else if (is_int(a) && is_int(b))
  147. return int_value(a) < int_value(b);
  148. else if (is_float(a) && is_float(b))
  149. return dbl_value(a) < dbl_value(b);
  150. else if (is_atom(a) && is_atom(b))
  151. {
  152. cstr_t *print1 = atoms_get(atoms, index(a));
  153. cstr_t *print2 = atoms_get(atoms, index(b));
  154. int short_len = (print1->size < print2->size)
  155. ?print1->size
  156. :print2->size;
  157. int d = memcmp(print1->data, print2->data, short_len);
  158. if (d == 0)
  159. return print1->size < print2->size;
  160. return d < 0;
  161. }
  162. else if (is_cons(a) && is_cons(b))
  163. {
  164. while (a != nil && b != nil)
  165. {
  166. term_t r = terms_are_less(lst_value(a), lst_value(b), atoms);
  167. if (r == 1)
  168. return r;
  169. r = terms_are_more(lst_value(a), lst_value(b), atoms);
  170. if (r == 1)
  171. return 0;
  172. a = lst_next(a);
  173. b = lst_next(b);
  174. }
  175. return a == nil && b != nil;
  176. }
  177. else if (is_tuple(a) && is_tuple(b))
  178. {
  179. int i;
  180. int na = int_value2(tup_size(a));
  181. int nb = int_value2(tup_size(b));
  182. if (na < nb)
  183. return 1;
  184. if (na > nb)
  185. return 0;
  186. for (i = 0; i < na; i++)
  187. {
  188. term_t ea = tup_elts(a)[i];
  189. term_t eb = tup_elts(b)[i];
  190. if (terms_are_less(ea, eb, atoms))
  191. return 1;
  192. if (terms_are_more(ea, eb, atoms))
  193. return 0;
  194. }
  195. return 0;
  196. }
  197. else if (is_pid(a) && is_pid(b))
  198. {
  199. term_t n1 = pid_node(a);
  200. term_t n2 = pid_node(b);
  201. if (n1 == my_node || n1 == my_prev_node) n1 = A_LOCAL;
  202. if (n2 == my_node || n2 == my_prev_node) n2 = A_LOCAL;
  203. if (terms_are_less(n1, n2, atoms))
  204. return 1;
  205. if (terms_are_more(n1, n2, atoms))
  206. return 0;
  207. return pid_serial(a) < pid_serial(b);
  208. }
  209. else if (is_ref(a) && is_ref(b) || is_port(a) && is_port(b))
  210. {
  211. term_t n1 = prp_node(a);
  212. term_t n2 = prp_node(b);
  213. if (n1 == my_node || n1 == my_prev_node) n1 = A_LOCAL;
  214. if (n2 == my_node || n2 == my_prev_node) n2 = A_LOCAL;
  215. if (terms_are_less(n1, n2, atoms))
  216. return 1;
  217. if (terms_are_more(n1, n2, atoms))
  218. return 0;
  219. return prp_serial(a) < prp_serial(b);
  220. }
  221. else if (is_binary(a) && is_binary(b))
  222. {
  223. // binaries compared by values first
  224. // if one binary is prefix of the other
  225. // then sizes are compared
  226. int sa = int_value2(bin_size(a));
  227. int sb = int_value2(bin_size(b));
  228. int ss = (sa > sb) ?sb :sa;
  229. int cmp = memcmp(bin_data(a), bin_data(b), ss);
  230. if (cmp < 0)
  231. return 1;
  232. if (cmp > 0)
  233. return 0;
  234. return sa < sb;
  235. }
  236. else if (is_int(a) && is_float(b))
  237. return (double)int_value(a) < dbl_value(b);
  238. else if (is_float(a) && is_int(b))
  239. return dbl_value(a) < (double)int_value(b);
  240. else
  241. {
  242. //number < atom < reference < port < pid < tuple < empty_list < list < binary
  243. int oa = is_int(a)? 1:
  244. is_float(a)? 1:
  245. is_atom(a)? 2:
  246. is_ref(a)? 3:
  247. is_port(a)? 4:
  248. is_pid(a)? 5:
  249. is_tuple(a)? 6:
  250. is_nil(a)? 7:
  251. is_cons(a)? 8:
  252. is_binary(a)? 9:
  253. -1;
  254. int ob = is_int(b)? 1:
  255. is_float(b)? 1:
  256. is_atom(b)? 2:
  257. is_ref(b)? 3:
  258. is_port(b)? 4:
  259. is_pid(b)? 5:
  260. is_tuple(b)? 6:
  261. is_nil(b)? 7:
  262. is_cons(b)? 8:
  263. is_binary(b)? 9:
  264. -1;
  265. return oa < ob;
  266. }
  267. }
  268. //EOF