value.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  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 <iostream>
  7. #include "common/check.h"
  8. #include "executable_semantics/interpreter/interpreter.h"
  9. namespace Carbon {
  10. auto Value::GetIntValue() const -> int {
  11. return std::get<IntValue>(value).value;
  12. }
  13. auto Value::GetBoolValue() const -> bool {
  14. return std::get<BoolValue>(value).value;
  15. }
  16. auto Value::GetFunctionValue() const -> const FunctionValue& {
  17. return std::get<FunctionValue>(value);
  18. }
  19. auto Value::GetStructValue() const -> const StructValue& {
  20. return std::get<StructValue>(value);
  21. }
  22. auto Value::GetAlternativeConstructorValue() const
  23. -> const AlternativeConstructorValue& {
  24. return std::get<AlternativeConstructorValue>(value);
  25. }
  26. auto Value::GetAlternativeValue() const -> const AlternativeValue& {
  27. return std::get<AlternativeValue>(value);
  28. }
  29. auto Value::GetTupleValue() const -> const TupleValue& {
  30. return std::get<TupleValue>(value);
  31. }
  32. auto Value::GetPointerValue() const -> Address {
  33. return std::get<PointerValue>(value).value;
  34. }
  35. auto Value::GetBindingPlaceholderValue() const
  36. -> const BindingPlaceholderValue& {
  37. return std::get<BindingPlaceholderValue>(value);
  38. }
  39. auto Value::GetFunctionType() const -> const FunctionType& {
  40. return std::get<FunctionType>(value);
  41. }
  42. auto Value::GetPointerType() const -> const PointerType& {
  43. return std::get<PointerType>(value);
  44. }
  45. auto Value::GetStructType() const -> const StructType& {
  46. return std::get<StructType>(value);
  47. }
  48. auto Value::GetChoiceType() const -> const ChoiceType& {
  49. return std::get<ChoiceType>(value);
  50. }
  51. auto Value::GetContinuationValue() const -> const ContinuationValue& {
  52. return std::get<ContinuationValue>(value);
  53. }
  54. auto FindInVarValues(const std::string& field, const VarValues& inits)
  55. -> const Value* {
  56. for (auto& i : inits) {
  57. if (i.first == field) {
  58. return i.second;
  59. }
  60. }
  61. return nullptr;
  62. }
  63. auto FieldsEqual(const VarValues& ts1, const VarValues& ts2) -> bool {
  64. if (ts1.size() == ts2.size()) {
  65. for (auto& iter1 : ts1) {
  66. auto t2 = FindInVarValues(iter1.first, ts2);
  67. if (t2 == nullptr) {
  68. return false;
  69. }
  70. if (!TypeEqual(iter1.second, t2)) {
  71. return false;
  72. }
  73. }
  74. return true;
  75. } else {
  76. return false;
  77. }
  78. }
  79. auto TupleValue::FindField(const std::string& name) const -> const Value* {
  80. for (const TupleElement& element : elements) {
  81. if (element.name == name) {
  82. return element.value;
  83. }
  84. }
  85. return nullptr;
  86. }
  87. auto Value::MakeIntValue(int i) -> const Value* {
  88. auto* v = new Value();
  89. v->value = IntValue({.value = i});
  90. return v;
  91. }
  92. auto Value::MakeBoolValue(bool b) -> const Value* {
  93. auto* v = new Value();
  94. v->value = BoolValue({.value = b});
  95. return v;
  96. }
  97. auto Value::MakeFunctionValue(std::string name, const Value* param,
  98. const Statement* body) -> const Value* {
  99. auto* v = new Value();
  100. v->value =
  101. FunctionValue({.name = std::move(name), .param = param, .body = body});
  102. return v;
  103. }
  104. auto Value::MakePointerValue(Address addr) -> const Value* {
  105. auto* v = new Value();
  106. v->value = PointerValue({.value = addr});
  107. return v;
  108. }
  109. auto Value::MakeStructValue(const Value* type, const Value* inits)
  110. -> const Value* {
  111. auto* v = new Value();
  112. v->value = StructValue({.type = type, .inits = inits});
  113. return v;
  114. }
  115. auto Value::MakeTupleValue(std::vector<TupleElement> elements) -> const Value* {
  116. auto* v = new Value();
  117. v->value = TupleValue({.elements = std::move(elements)});
  118. return v;
  119. }
  120. auto Value::MakeAlternativeValue(std::string alt_name, std::string choice_name,
  121. const Value* argument) -> const Value* {
  122. auto* v = new Value();
  123. v->value = AlternativeValue({.alt_name = std::move(alt_name),
  124. .choice_name = std::move(choice_name),
  125. .argument = argument});
  126. return v;
  127. }
  128. auto Value::MakeAlternativeConstructorValue(std::string alt_name,
  129. std::string choice_name)
  130. -> const Value* {
  131. auto* v = new Value();
  132. v->value = AlternativeConstructorValue(
  133. {.alt_name = std::move(alt_name), .choice_name = std::move(choice_name)});
  134. return v;
  135. }
  136. // Return a first-class continuation represented a fragment
  137. // of the stack.
  138. auto Value::MakeContinuationValue(std::vector<Frame*> stack) -> Value* {
  139. auto* v = new Value();
  140. v->value = ContinuationValue({.stack = std::move(stack)});
  141. return v;
  142. }
  143. auto Value::MakeBindingPlaceholderValue(std::string name, const Value* type)
  144. -> const Value* {
  145. auto* v = new Value();
  146. v->value = BindingPlaceholderValue({.name = std::move(name), .type = type});
  147. return v;
  148. }
  149. auto Value::MakeIntType() -> const Value* {
  150. auto* v = new Value();
  151. v->value = IntType();
  152. return v;
  153. }
  154. auto Value::MakeBoolType() -> const Value* {
  155. auto* v = new Value();
  156. v->value = BoolType();
  157. return v;
  158. }
  159. auto Value::MakeTypeType() -> const Value* {
  160. auto* v = new Value();
  161. v->value = TypeType();
  162. return v;
  163. }
  164. // Return a Continuation type.
  165. auto Value::MakeContinuationType() -> const Value* {
  166. auto* v = new Value();
  167. v->value = ContinuationType();
  168. return v;
  169. }
  170. auto Value::MakeAutoType() -> const Value* {
  171. auto* v = new Value();
  172. v->value = AutoType();
  173. return v;
  174. }
  175. auto Value::MakeFunctionType(const Value* param, const Value* ret)
  176. -> const Value* {
  177. auto* v = new Value();
  178. v->value = FunctionType({.param = param, .ret = ret});
  179. return v;
  180. }
  181. auto Value::MakePointerType(const Value* type) -> const Value* {
  182. auto* v = new Value();
  183. v->value = PointerType({.type = type});
  184. return v;
  185. }
  186. auto Value::MakeStructType(std::string name, VarValues fields,
  187. VarValues methods) -> const Value* {
  188. auto* v = new Value();
  189. v->value = StructType({.name = std::move(name),
  190. .fields = std::move(fields),
  191. .methods = std::move(methods)});
  192. return v;
  193. }
  194. auto Value::MakeUnitTypeVal() -> const Value* {
  195. auto* v = new Value();
  196. v->value = TupleValue({.elements = {}});
  197. return v;
  198. }
  199. auto Value::MakeChoiceType(std::string name, VarValues alts) -> const Value* {
  200. auto* v = new Value();
  201. v->value =
  202. ChoiceType({.name = std::move(name), .alternatives = std::move(alts)});
  203. return v;
  204. }
  205. namespace {
  206. auto GetMember(const Value* v, const std::string& f, int line_num)
  207. -> const Value* {
  208. switch (v->tag()) {
  209. case ValKind::StructValue: {
  210. const Value* field =
  211. v->GetStructValue().inits->GetTupleValue().FindField(f);
  212. if (field == nullptr) {
  213. std::cerr << "runtime error, member " << f << " not in ";
  214. PrintValue(v, std::cerr);
  215. std::cerr << std::endl;
  216. exit(-1);
  217. }
  218. return field;
  219. }
  220. case ValKind::TupleValue: {
  221. const Value* field = v->GetTupleValue().FindField(f);
  222. if (field == nullptr) {
  223. std::cerr << "field " << f << " not in ";
  224. PrintValue(v, std::cerr);
  225. std::cerr << std::endl;
  226. exit(-1);
  227. }
  228. return field;
  229. }
  230. case ValKind::ChoiceType: {
  231. if (FindInVarValues(f, v->GetChoiceType().alternatives) == nullptr) {
  232. std::cerr << "alternative " << f << " not in ";
  233. PrintValue(v, std::cerr);
  234. std::cerr << std::endl;
  235. exit(-1);
  236. }
  237. return Value::MakeAlternativeConstructorValue(f, v->GetChoiceType().name);
  238. }
  239. default:
  240. std::cerr << "field access not allowed for value ";
  241. PrintValue(v, std::cerr);
  242. std::cerr << std::endl;
  243. exit(-1);
  244. }
  245. }
  246. } // namespace
  247. auto Value::GetField(const FieldPath& path, int line_num) const
  248. -> const Value* {
  249. const Value* value = this;
  250. for (const std::string& field : path.components) {
  251. value = GetMember(value, field, line_num);
  252. }
  253. return value;
  254. }
  255. namespace {
  256. auto SetFieldImpl(const Value* value,
  257. std::vector<std::string>::const_iterator path_begin,
  258. std::vector<std::string>::const_iterator path_end,
  259. const Value* field_value, int line_num) -> const Value* {
  260. if (path_begin == path_end) {
  261. return field_value;
  262. }
  263. switch (value->tag()) {
  264. case ValKind::StructValue: {
  265. return SetFieldImpl(value->GetStructValue().inits, path_begin, path_end,
  266. field_value, line_num);
  267. }
  268. case ValKind::TupleValue: {
  269. std::vector<TupleElement> elements = value->GetTupleValue().elements;
  270. auto it = std::find_if(elements.begin(), elements.end(),
  271. [path_begin](const TupleElement& element) {
  272. return element.name == *path_begin;
  273. });
  274. if (it == elements.end()) {
  275. std::cerr << "field " << *path_begin << " not in ";
  276. PrintValue(value, std::cerr);
  277. std::cerr << std::endl;
  278. exit(-1);
  279. }
  280. it->value = SetFieldImpl(it->value, path_begin + 1, path_end, field_value,
  281. line_num);
  282. return Value::MakeTupleValue(elements);
  283. }
  284. default:
  285. std::cerr << "field access not allowed for value ";
  286. PrintValue(value, std::cerr);
  287. std::cerr << std::endl;
  288. exit(-1);
  289. }
  290. }
  291. } // namespace
  292. auto Value::SetField(const FieldPath& path, const Value* field_value,
  293. int line_num) const -> const Value* {
  294. return SetFieldImpl(this, path.components.begin(), path.components.end(),
  295. field_value, line_num);
  296. }
  297. auto PrintValue(const Value* val, std::ostream& out) -> void {
  298. switch (val->tag()) {
  299. case ValKind::AlternativeConstructorValue: {
  300. out << val->GetAlternativeConstructorValue().choice_name << "."
  301. << val->GetAlternativeConstructorValue().alt_name;
  302. break;
  303. }
  304. case ValKind::BindingPlaceholderValue: {
  305. PrintValue(val->GetBindingPlaceholderValue().type, out);
  306. out << ": " << val->GetBindingPlaceholderValue().name;
  307. break;
  308. }
  309. case ValKind::AlternativeValue: {
  310. out << "alt " << val->GetAlternativeValue().choice_name << "."
  311. << val->GetAlternativeValue().alt_name << " ";
  312. PrintValue(val->GetAlternativeValue().argument, out);
  313. break;
  314. }
  315. case ValKind::StructValue: {
  316. out << val->GetStructValue().type->GetStructType().name;
  317. PrintValue(val->GetStructValue().inits, out);
  318. break;
  319. }
  320. case ValKind::TupleValue: {
  321. out << "(";
  322. bool add_commas = false;
  323. for (const TupleElement& element : val->GetTupleValue().elements) {
  324. if (add_commas) {
  325. out << ", ";
  326. } else {
  327. add_commas = true;
  328. }
  329. out << element.name << " = ";
  330. PrintValue(element.value, out);
  331. }
  332. out << ")";
  333. break;
  334. }
  335. case ValKind::IntValue:
  336. out << val->GetIntValue();
  337. break;
  338. case ValKind::BoolValue:
  339. out << std::boolalpha << val->GetBoolValue();
  340. break;
  341. case ValKind::FunctionValue:
  342. out << "fun<" << val->GetFunctionValue().name << ">";
  343. break;
  344. case ValKind::PointerValue:
  345. out << "ptr<" << val->GetPointerValue() << ">";
  346. break;
  347. case ValKind::BoolType:
  348. out << "Bool";
  349. break;
  350. case ValKind::IntType:
  351. out << "Int";
  352. break;
  353. case ValKind::TypeType:
  354. out << "Type";
  355. break;
  356. case ValKind::AutoType:
  357. out << "auto";
  358. break;
  359. case ValKind::ContinuationType:
  360. out << "Continuation";
  361. break;
  362. case ValKind::PointerType:
  363. PrintValue(val->GetPointerType().type, out);
  364. out << "*";
  365. break;
  366. case ValKind::FunctionType:
  367. out << "fn ";
  368. PrintValue(val->GetFunctionType().param, out);
  369. out << " -> ";
  370. PrintValue(val->GetFunctionType().ret, out);
  371. break;
  372. case ValKind::StructType:
  373. out << "struct " << val->GetStructType().name;
  374. break;
  375. case ValKind::ChoiceType:
  376. out << "choice " << val->GetChoiceType().name;
  377. break;
  378. case ValKind::ContinuationValue:
  379. out << "continuation[[";
  380. for (Frame* frame : val->GetContinuationValue().stack) {
  381. PrintFrame(frame, out);
  382. out << " :: ";
  383. }
  384. out << "]]";
  385. break;
  386. }
  387. }
  388. auto TypeEqual(const Value* t1, const Value* t2) -> bool {
  389. if (t1->tag() != t2->tag()) {
  390. return false;
  391. }
  392. switch (t1->tag()) {
  393. case ValKind::PointerType:
  394. return TypeEqual(t1->GetPointerType().type, t2->GetPointerType().type);
  395. case ValKind::FunctionType:
  396. return TypeEqual(t1->GetFunctionType().param,
  397. t2->GetFunctionType().param) &&
  398. TypeEqual(t1->GetFunctionType().ret, t2->GetFunctionType().ret);
  399. case ValKind::StructType:
  400. return t1->GetStructType().name == t2->GetStructType().name;
  401. case ValKind::ChoiceType:
  402. return t1->GetChoiceType().name == t2->GetChoiceType().name;
  403. case ValKind::TupleValue: {
  404. if (t1->GetTupleValue().elements.size() !=
  405. t2->GetTupleValue().elements.size()) {
  406. return false;
  407. }
  408. for (size_t i = 0; i < t1->GetTupleValue().elements.size(); ++i) {
  409. if (t1->GetTupleValue().elements[i].name !=
  410. t2->GetTupleValue().elements[i].name) {
  411. return false;
  412. }
  413. if (!TypeEqual(t1->GetTupleValue().elements[i].value,
  414. t2->GetTupleValue().elements[i].value)) {
  415. return false;
  416. }
  417. }
  418. return true;
  419. }
  420. case ValKind::IntType:
  421. case ValKind::BoolType:
  422. case ValKind::ContinuationType:
  423. case ValKind::TypeType:
  424. return true;
  425. default:
  426. std::cerr << "TypeEqual used to compare non-type values" << std::endl;
  427. PrintValue(t1, std::cerr);
  428. std::cerr << std::endl;
  429. PrintValue(t2, std::cerr);
  430. exit(-1);
  431. }
  432. }
  433. // Returns true if all the fields of the two tuples contain equal values
  434. // and returns false otherwise.
  435. static auto FieldsValueEqual(const std::vector<TupleElement>& ts1,
  436. const std::vector<TupleElement>& ts2, int line_num)
  437. -> bool {
  438. if (ts1.size() != ts2.size()) {
  439. return false;
  440. }
  441. for (const TupleElement& element : ts1) {
  442. auto iter = std::find_if(
  443. ts2.begin(), ts2.end(),
  444. [&](const TupleElement& e2) { return e2.name == element.name; });
  445. if (iter == ts2.end()) {
  446. return false;
  447. }
  448. if (!ValueEqual(element.value, iter->value, line_num)) {
  449. return false;
  450. }
  451. }
  452. return true;
  453. }
  454. // Returns true if the two values are equal and returns false otherwise.
  455. //
  456. // This function implements the `==` operator of Carbon.
  457. auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
  458. if (v1->tag() != v2->tag()) {
  459. return false;
  460. }
  461. switch (v1->tag()) {
  462. case ValKind::IntValue:
  463. return v1->GetIntValue() == v2->GetIntValue();
  464. case ValKind::BoolValue:
  465. return v1->GetBoolValue() == v2->GetBoolValue();
  466. case ValKind::PointerValue:
  467. return v1->GetPointerValue() == v2->GetPointerValue();
  468. case ValKind::FunctionValue:
  469. return v1->GetFunctionValue().body == v2->GetFunctionValue().body;
  470. case ValKind::TupleValue:
  471. return FieldsValueEqual(v1->GetTupleValue().elements,
  472. v2->GetTupleValue().elements, line_num);
  473. default:
  474. case ValKind::IntType:
  475. case ValKind::BoolType:
  476. case ValKind::TypeType:
  477. case ValKind::FunctionType:
  478. case ValKind::PointerType:
  479. case ValKind::AutoType:
  480. case ValKind::StructType:
  481. case ValKind::ChoiceType:
  482. case ValKind::ContinuationType:
  483. return TypeEqual(v1, v2);
  484. case ValKind::StructValue:
  485. case ValKind::AlternativeValue:
  486. case ValKind::BindingPlaceholderValue:
  487. case ValKind::AlternativeConstructorValue:
  488. case ValKind::ContinuationValue:
  489. std::cerr << "ValueEqual does not support this kind of value."
  490. << std::endl;
  491. exit(-1);
  492. }
  493. }
  494. auto ToInteger(const Value* v) -> int {
  495. switch (v->tag()) {
  496. case ValKind::IntValue:
  497. return v->GetIntValue();
  498. default:
  499. std::cerr << "expected an integer, not ";
  500. PrintValue(v, std::cerr);
  501. exit(-1);
  502. }
  503. }
  504. } // namespace Carbon