value.cpp 10 KB

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