value.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "executable_semantics/interpreter/value.h"
  5. #include <algorithm>
  6. #include <cassert>
  7. #include <iostream>
  8. #include "executable_semantics/interpreter/interpreter.h"
  9. namespace Carbon {
  10. auto FindInVarValues(const std::string& field, VarValues* inits)
  11. -> const Value* {
  12. for (auto& i : *inits) {
  13. if (i.first == field) {
  14. return i.second;
  15. }
  16. }
  17. return nullptr;
  18. }
  19. auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool {
  20. if (ts1->size() == ts2->size()) {
  21. for (auto& iter1 : *ts1) {
  22. auto t2 = FindInVarValues(iter1.first, ts2);
  23. if (t2 == nullptr) {
  24. return false;
  25. }
  26. if (!TypeEqual(iter1.second, t2)) {
  27. return false;
  28. }
  29. }
  30. return true;
  31. } else {
  32. return false;
  33. }
  34. }
  35. auto FindTupleField(const std::string& name, const Value* tuple)
  36. -> std::optional<Address> {
  37. assert(tuple->tag == ValKind::TupleV);
  38. for (const auto& i : *tuple->u.tuple.elts) {
  39. if (i.first == name) {
  40. return i.second;
  41. }
  42. }
  43. return std::nullopt;
  44. }
  45. auto MakeIntVal(int i) -> const Value* {
  46. auto* v = new Value();
  47. v->tag = ValKind::IntV;
  48. v->u.integer = i;
  49. return v;
  50. }
  51. auto MakeBoolVal(bool b) -> const Value* {
  52. auto* v = new Value();
  53. v->tag = ValKind::BoolV;
  54. v->u.boolean = b;
  55. return v;
  56. }
  57. auto MakeFunVal(std::string name, const Value* param, const Statement* body)
  58. -> const Value* {
  59. auto* v = new Value();
  60. v->tag = ValKind::FunV;
  61. v->u.fun.name = new std::string(std::move(name));
  62. v->u.fun.param = param;
  63. v->u.fun.body = body;
  64. return v;
  65. }
  66. auto MakePtrVal(Address addr) -> const Value* {
  67. auto* v = new Value();
  68. v->tag = ValKind::PtrV;
  69. v->u.ptr = addr;
  70. return v;
  71. }
  72. auto MakeStructVal(const Value* type, const Value* inits) -> const Value* {
  73. auto* v = new Value();
  74. v->tag = ValKind::StructV;
  75. v->u.struct_val.type = type;
  76. v->u.struct_val.inits = inits;
  77. return v;
  78. }
  79. auto MakeTupleVal(std::vector<std::pair<std::string, Address>>* elts)
  80. -> const Value* {
  81. auto* v = new Value();
  82. v->tag = ValKind::TupleV;
  83. v->u.tuple.elts = elts;
  84. return v;
  85. }
  86. auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument)
  87. -> const Value* {
  88. auto* v = new Value();
  89. v->tag = ValKind::AltV;
  90. v->u.alt.alt_name = new std::string(std::move(alt_name));
  91. v->u.alt.choice_name = new std::string(std::move(choice_name));
  92. v->u.alt.argument = argument;
  93. return v;
  94. }
  95. auto MakeAltCons(std::string alt_name, std::string choice_name)
  96. -> const Value* {
  97. auto* v = new Value();
  98. v->tag = ValKind::AltConsV;
  99. v->u.alt.alt_name = new std::string(std::move(alt_name));
  100. v->u.alt.choice_name = new std::string(std::move(choice_name));
  101. return v;
  102. }
  103. // Return a first-class continuation represented a fragment
  104. // of the stack.
  105. auto MakeContinuation(std::vector<Frame*> stack) -> Value* {
  106. auto* v = new Value();
  107. v->tag = ValKind::ContinuationV;
  108. v->u.continuation.stack = new std::vector<Frame*>(stack);
  109. return v;
  110. }
  111. auto MakeVarPatVal(std::string name, const Value* type) -> const Value* {
  112. auto* v = new Value();
  113. v->tag = ValKind::VarPatV;
  114. v->u.var_pat.name = new std::string(std::move(name));
  115. v->u.var_pat.type = type;
  116. return v;
  117. }
  118. auto MakeVarTypeVal(std::string name) -> const Value* {
  119. auto* v = new Value();
  120. v->tag = ValKind::VarTV;
  121. v->u.var_type = new std::string(std::move(name));
  122. return v;
  123. }
  124. auto MakeIntTypeVal() -> const Value* {
  125. auto* v = new Value();
  126. v->tag = ValKind::IntTV;
  127. return v;
  128. }
  129. auto MakeBoolTypeVal() -> const Value* {
  130. auto* v = new Value();
  131. v->tag = ValKind::BoolTV;
  132. return v;
  133. }
  134. auto MakeTypeTypeVal() -> const Value* {
  135. auto* v = new Value();
  136. v->tag = ValKind::TypeTV;
  137. return v;
  138. }
  139. // Return a Continuation type.
  140. auto MakeContinuationTypeVal() -> const Value* {
  141. auto* v = new Value();
  142. v->tag = ValKind::ContinuationTV;
  143. return v;
  144. }
  145. auto MakeAutoTypeVal() -> const Value* {
  146. auto* v = new Value();
  147. v->tag = ValKind::AutoTV;
  148. return v;
  149. }
  150. auto MakeFunTypeVal(const Value* param, const Value* ret) -> const Value* {
  151. auto* v = new Value();
  152. v->tag = ValKind::FunctionTV;
  153. v->u.fun_type.param = param;
  154. v->u.fun_type.ret = ret;
  155. return v;
  156. }
  157. auto MakePtrTypeVal(const Value* type) -> const Value* {
  158. auto* v = new Value();
  159. v->tag = ValKind::PointerTV;
  160. v->u.ptr_type.type = type;
  161. return v;
  162. }
  163. auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods)
  164. -> const Value* {
  165. auto* v = new Value();
  166. v->tag = ValKind::StructTV;
  167. v->u.struct_type.name = new std::string(std::move(name));
  168. v->u.struct_type.fields = fields;
  169. v->u.struct_type.methods = methods;
  170. return v;
  171. }
  172. auto MakeVoidTypeVal() -> const Value* {
  173. auto* v = new Value();
  174. v->tag = ValKind::TupleV;
  175. v->u.tuple.elts = new std::vector<std::pair<std::string, Address>>();
  176. return v;
  177. }
  178. auto MakeChoiceTypeVal(std::string name,
  179. std::list<std::pair<std::string, const Value*>>* alts)
  180. -> const Value* {
  181. auto* v = new Value();
  182. v->tag = ValKind::ChoiceTV;
  183. // Transitional leak: when we get rid of all pointers, this will disappear.
  184. v->u.choice_type.name = new std::string(name);
  185. v->u.choice_type.alternatives = alts;
  186. return v;
  187. }
  188. auto State::PrintAddress(Address a, std::ostream& out) -> void {
  189. if (!this->alive[a]) {
  190. out << "!!";
  191. }
  192. PrintValue(this->heap[a], out);
  193. }
  194. auto PrintValue(const Value* val, std::ostream& out) -> void {
  195. switch (val->tag) {
  196. case ValKind::AltConsV: {
  197. out << *val->u.alt_cons.choice_name << "." << *val->u.alt_cons.alt_name;
  198. break;
  199. }
  200. case ValKind::VarPatV: {
  201. PrintValue(val->u.var_pat.type, out);
  202. out << ": " << *val->u.var_pat.name;
  203. break;
  204. }
  205. case ValKind::AltV: {
  206. out << "alt " << *val->u.alt.choice_name << "." << *val->u.alt.alt_name
  207. << " ";
  208. state->PrintAddress(val->u.alt.argument, out);
  209. break;
  210. }
  211. case ValKind::StructV: {
  212. out << *val->u.struct_val.type->u.struct_type.name;
  213. PrintValue(val->u.struct_val.inits, out);
  214. break;
  215. }
  216. case ValKind::TupleV: {
  217. out << "(";
  218. bool add_commas = false;
  219. for (const auto& elt : *val->u.tuple.elts) {
  220. if (add_commas) {
  221. out << ", ";
  222. } else {
  223. add_commas = true;
  224. }
  225. out << elt.first << " = ";
  226. state->PrintAddress(elt.second, out);
  227. out << "@" << elt.second;
  228. }
  229. out << ")";
  230. break;
  231. }
  232. case ValKind::IntV:
  233. out << val->u.integer;
  234. break;
  235. case ValKind::BoolV:
  236. out << std::boolalpha << val->u.boolean;
  237. break;
  238. case ValKind::FunV:
  239. out << "fun<" << *val->u.fun.name << ">";
  240. break;
  241. case ValKind::PtrV:
  242. out << "ptr<" << val->u.ptr << ">";
  243. break;
  244. case ValKind::BoolTV:
  245. out << "Bool";
  246. break;
  247. case ValKind::IntTV:
  248. out << "Int";
  249. break;
  250. case ValKind::TypeTV:
  251. out << "Type";
  252. break;
  253. case ValKind::AutoTV:
  254. out << "auto";
  255. break;
  256. case ValKind::ContinuationTV:
  257. out << "Continuation";
  258. break;
  259. case ValKind::PointerTV:
  260. out << "Ptr(";
  261. PrintValue(val->u.ptr_type.type, out);
  262. out << ")";
  263. break;
  264. case ValKind::FunctionTV:
  265. out << "fn ";
  266. PrintValue(val->u.fun_type.param, out);
  267. out << " -> ";
  268. PrintValue(val->u.fun_type.ret, out);
  269. break;
  270. case ValKind::VarTV:
  271. out << *val->u.var_type;
  272. break;
  273. case ValKind::StructTV:
  274. out << "struct " << *val->u.struct_type.name;
  275. break;
  276. case ValKind::ChoiceTV:
  277. out << "choice " << *val->u.choice_type.name;
  278. break;
  279. case ValKind::ContinuationV:
  280. out << "continuation[[";
  281. for (Frame* frame : *val->u.continuation.stack) {
  282. PrintFrame(frame, out);
  283. out << " :: ";
  284. }
  285. out << "]]";
  286. break;
  287. }
  288. }
  289. auto TypeEqual(const Value* t1, const Value* t2) -> bool {
  290. if (t1->tag != t2->tag) {
  291. return false;
  292. }
  293. switch (t1->tag) {
  294. case ValKind::VarTV:
  295. return *t1->u.var_type == *t2->u.var_type;
  296. case ValKind::PointerTV:
  297. return TypeEqual(t1->u.ptr_type.type, t2->u.ptr_type.type);
  298. case ValKind::FunctionTV:
  299. return TypeEqual(t1->u.fun_type.param, t2->u.fun_type.param) &&
  300. TypeEqual(t1->u.fun_type.ret, t2->u.fun_type.ret);
  301. case ValKind::StructTV:
  302. return *t1->u.struct_type.name == *t2->u.struct_type.name;
  303. case ValKind::ChoiceTV:
  304. return *t1->u.choice_type.name == *t2->u.choice_type.name;
  305. case ValKind::TupleV: {
  306. if (t1->u.tuple.elts->size() != t2->u.tuple.elts->size()) {
  307. return false;
  308. }
  309. for (size_t i = 0; i < t1->u.tuple.elts->size(); ++i) {
  310. std::optional<Address> t2_field =
  311. FindTupleField((*t1->u.tuple.elts)[i].first, t2);
  312. if (t2_field == std::nullopt) {
  313. return false;
  314. }
  315. if (!TypeEqual(state->ReadFromMemory((*t1->u.tuple.elts)[i].second, 0),
  316. state->ReadFromMemory(*t2_field, 0))) {
  317. return false;
  318. }
  319. }
  320. return true;
  321. }
  322. case ValKind::IntTV:
  323. case ValKind::BoolTV:
  324. case ValKind::ContinuationTV:
  325. return true;
  326. default:
  327. std::cerr << "TypeEqual used to compare non-type values" << std::endl;
  328. exit(-1);
  329. }
  330. }
  331. // Returns true if all the fields of the two tuples contain equal values
  332. // and returns false otherwise.
  333. static auto FieldsValueEqual(VarAddresses* ts1, VarAddresses* ts2, int line_num)
  334. -> bool {
  335. if (ts1->size() != ts2->size()) {
  336. return false;
  337. }
  338. for (const auto& [name, address] : *ts1) {
  339. auto iter =
  340. std::find_if(ts2->begin(), ts2->end(),
  341. [name = name](const auto& p) { return p.first == name; });
  342. if (iter == ts2->end()) {
  343. return false;
  344. }
  345. if (!ValueEqual(state->heap[address], state->heap[iter->second],
  346. line_num)) {
  347. return false;
  348. }
  349. }
  350. return true;
  351. }
  352. // Returns true if the two values are equal and returns false otherwise.
  353. //
  354. // This function implements the `==` operator of Carbon.
  355. auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
  356. if (v1->tag != v2->tag) {
  357. return false;
  358. }
  359. switch (v1->tag) {
  360. case ValKind::IntV:
  361. return v1->u.integer == v2->u.integer;
  362. case ValKind::BoolV:
  363. return v1->u.boolean == v2->u.boolean;
  364. case ValKind::PtrV:
  365. return v1->u.ptr == v2->u.ptr;
  366. case ValKind::FunV:
  367. return v1->u.fun.body == v2->u.fun.body;
  368. case ValKind::TupleV:
  369. return FieldsValueEqual(v1->u.tuple.elts, v2->u.tuple.elts, line_num);
  370. default:
  371. case ValKind::VarTV:
  372. case ValKind::IntTV:
  373. case ValKind::BoolTV:
  374. case ValKind::TypeTV:
  375. case ValKind::FunctionTV:
  376. case ValKind::PointerTV:
  377. case ValKind::AutoTV:
  378. case ValKind::StructTV:
  379. case ValKind::ChoiceTV:
  380. case ValKind::ContinuationTV:
  381. return TypeEqual(v1, v2);
  382. case ValKind::StructV:
  383. case ValKind::AltV:
  384. case ValKind::VarPatV:
  385. case ValKind::AltConsV:
  386. case ValKind::ContinuationV:
  387. std::cerr << "ValueEqual does not support this kind of value."
  388. << std::endl;
  389. exit(-1);
  390. }
  391. }
  392. auto ToInteger(const Value* v) -> int {
  393. switch (v->tag) {
  394. case ValKind::IntV:
  395. return v->u.integer;
  396. default:
  397. std::cerr << "expected an integer, not ";
  398. PrintValue(v, std::cerr);
  399. exit(-1);
  400. }
  401. }
  402. } // namespace Carbon