value.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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::optional<std::string> name,
  144. const Value* type) -> 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. const BindingPlaceholderValue& placeholder =
  306. val->GetBindingPlaceholderValue();
  307. if (placeholder.name.has_value()) {
  308. out << *placeholder.name;
  309. } else {
  310. out << "_";
  311. }
  312. out << ": ";
  313. PrintValue(val->GetBindingPlaceholderValue().type, out);
  314. break;
  315. }
  316. case ValKind::AlternativeValue: {
  317. out << "alt " << val->GetAlternativeValue().choice_name << "."
  318. << val->GetAlternativeValue().alt_name << " ";
  319. PrintValue(val->GetAlternativeValue().argument, out);
  320. break;
  321. }
  322. case ValKind::StructValue: {
  323. out << val->GetStructValue().type->GetStructType().name;
  324. PrintValue(val->GetStructValue().inits, out);
  325. break;
  326. }
  327. case ValKind::TupleValue: {
  328. out << "(";
  329. bool add_commas = false;
  330. for (const TupleElement& element : val->GetTupleValue().elements) {
  331. if (add_commas) {
  332. out << ", ";
  333. } else {
  334. add_commas = true;
  335. }
  336. out << element.name << " = ";
  337. PrintValue(element.value, out);
  338. }
  339. out << ")";
  340. break;
  341. }
  342. case ValKind::IntValue:
  343. out << val->GetIntValue();
  344. break;
  345. case ValKind::BoolValue:
  346. out << std::boolalpha << val->GetBoolValue();
  347. break;
  348. case ValKind::FunctionValue:
  349. out << "fun<" << val->GetFunctionValue().name << ">";
  350. break;
  351. case ValKind::PointerValue:
  352. out << "ptr<" << val->GetPointerValue() << ">";
  353. break;
  354. case ValKind::BoolType:
  355. out << "Bool";
  356. break;
  357. case ValKind::IntType:
  358. out << "Int";
  359. break;
  360. case ValKind::TypeType:
  361. out << "Type";
  362. break;
  363. case ValKind::AutoType:
  364. out << "auto";
  365. break;
  366. case ValKind::ContinuationType:
  367. out << "Continuation";
  368. break;
  369. case ValKind::PointerType:
  370. PrintValue(val->GetPointerType().type, out);
  371. out << "*";
  372. break;
  373. case ValKind::FunctionType:
  374. out << "fn ";
  375. PrintValue(val->GetFunctionType().param, out);
  376. out << " -> ";
  377. PrintValue(val->GetFunctionType().ret, out);
  378. break;
  379. case ValKind::StructType:
  380. out << "struct " << val->GetStructType().name;
  381. break;
  382. case ValKind::ChoiceType:
  383. out << "choice " << val->GetChoiceType().name;
  384. break;
  385. case ValKind::ContinuationValue:
  386. out << "continuation[[";
  387. for (Frame* frame : val->GetContinuationValue().stack) {
  388. PrintFrame(frame, out);
  389. out << " :: ";
  390. }
  391. out << "]]";
  392. break;
  393. }
  394. }
  395. auto TypeEqual(const Value* t1, const Value* t2) -> bool {
  396. if (t1->tag() != t2->tag()) {
  397. return false;
  398. }
  399. switch (t1->tag()) {
  400. case ValKind::PointerType:
  401. return TypeEqual(t1->GetPointerType().type, t2->GetPointerType().type);
  402. case ValKind::FunctionType:
  403. return TypeEqual(t1->GetFunctionType().param,
  404. t2->GetFunctionType().param) &&
  405. TypeEqual(t1->GetFunctionType().ret, t2->GetFunctionType().ret);
  406. case ValKind::StructType:
  407. return t1->GetStructType().name == t2->GetStructType().name;
  408. case ValKind::ChoiceType:
  409. return t1->GetChoiceType().name == t2->GetChoiceType().name;
  410. case ValKind::TupleValue: {
  411. if (t1->GetTupleValue().elements.size() !=
  412. t2->GetTupleValue().elements.size()) {
  413. return false;
  414. }
  415. for (size_t i = 0; i < t1->GetTupleValue().elements.size(); ++i) {
  416. if (t1->GetTupleValue().elements[i].name !=
  417. t2->GetTupleValue().elements[i].name) {
  418. return false;
  419. }
  420. if (!TypeEqual(t1->GetTupleValue().elements[i].value,
  421. t2->GetTupleValue().elements[i].value)) {
  422. return false;
  423. }
  424. }
  425. return true;
  426. }
  427. case ValKind::IntType:
  428. case ValKind::BoolType:
  429. case ValKind::ContinuationType:
  430. case ValKind::TypeType:
  431. return true;
  432. default:
  433. std::cerr << "TypeEqual used to compare non-type values" << std::endl;
  434. PrintValue(t1, std::cerr);
  435. std::cerr << std::endl;
  436. PrintValue(t2, std::cerr);
  437. exit(-1);
  438. }
  439. }
  440. // Returns true if all the fields of the two tuples contain equal values
  441. // and returns false otherwise.
  442. static auto FieldsValueEqual(const std::vector<TupleElement>& ts1,
  443. const std::vector<TupleElement>& ts2, int line_num)
  444. -> bool {
  445. if (ts1.size() != ts2.size()) {
  446. return false;
  447. }
  448. for (const TupleElement& element : ts1) {
  449. auto iter = std::find_if(
  450. ts2.begin(), ts2.end(),
  451. [&](const TupleElement& e2) { return e2.name == element.name; });
  452. if (iter == ts2.end()) {
  453. return false;
  454. }
  455. if (!ValueEqual(element.value, iter->value, line_num)) {
  456. return false;
  457. }
  458. }
  459. return true;
  460. }
  461. // Returns true if the two values are equal and returns false otherwise.
  462. //
  463. // This function implements the `==` operator of Carbon.
  464. auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
  465. if (v1->tag() != v2->tag()) {
  466. return false;
  467. }
  468. switch (v1->tag()) {
  469. case ValKind::IntValue:
  470. return v1->GetIntValue() == v2->GetIntValue();
  471. case ValKind::BoolValue:
  472. return v1->GetBoolValue() == v2->GetBoolValue();
  473. case ValKind::PointerValue:
  474. return v1->GetPointerValue() == v2->GetPointerValue();
  475. case ValKind::FunctionValue:
  476. return v1->GetFunctionValue().body == v2->GetFunctionValue().body;
  477. case ValKind::TupleValue:
  478. return FieldsValueEqual(v1->GetTupleValue().elements,
  479. v2->GetTupleValue().elements, line_num);
  480. default:
  481. case ValKind::IntType:
  482. case ValKind::BoolType:
  483. case ValKind::TypeType:
  484. case ValKind::FunctionType:
  485. case ValKind::PointerType:
  486. case ValKind::AutoType:
  487. case ValKind::StructType:
  488. case ValKind::ChoiceType:
  489. case ValKind::ContinuationType:
  490. return TypeEqual(v1, v2);
  491. case ValKind::StructValue:
  492. case ValKind::AlternativeValue:
  493. case ValKind::BindingPlaceholderValue:
  494. case ValKind::AlternativeConstructorValue:
  495. case ValKind::ContinuationValue:
  496. std::cerr << "ValueEqual does not support this kind of value."
  497. << std::endl;
  498. exit(-1);
  499. }
  500. }
  501. } // namespace Carbon