parse_tree_test.cpp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  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 "toolchain/parser/parse_tree.h"
  5. #include <forward_list>
  6. #include "gmock/gmock.h"
  7. #include "gtest/gtest.h"
  8. #include "llvm/ADT/Sequence.h"
  9. #include "llvm/Support/SourceMgr.h"
  10. #include "toolchain/common/yaml_test_helpers.h"
  11. #include "toolchain/diagnostics/diagnostic_emitter.h"
  12. #include "toolchain/lexer/tokenized_buffer.h"
  13. #include "toolchain/parser/parse_node_kind.h"
  14. #include "toolchain/parser/parse_test_helpers.h"
  15. namespace Carbon {
  16. namespace {
  17. using Carbon::Testing::ExpectedNode;
  18. using Carbon::Testing::MatchParseTreeNodes;
  19. using namespace Carbon::Testing::NodeMatchers;
  20. using ::testing::ElementsAre;
  21. using ::testing::Eq;
  22. using ::testing::Ne;
  23. using ::testing::NotNull;
  24. using ::testing::StrEq;
  25. namespace Yaml = Carbon::Testing::Yaml;
  26. struct ParseTreeTest : ::testing::Test {
  27. std::forward_list<SourceBuffer> source_storage;
  28. std::forward_list<TokenizedBuffer> token_storage;
  29. DiagnosticConsumer& consumer = ConsoleDiagnosticConsumer();
  30. auto GetSourceBuffer(llvm::Twine t) -> SourceBuffer& {
  31. source_storage.push_front(SourceBuffer::CreateFromText(t.str()));
  32. return source_storage.front();
  33. }
  34. auto GetTokenizedBuffer(llvm::Twine t) -> TokenizedBuffer& {
  35. token_storage.push_front(
  36. TokenizedBuffer::Lex(GetSourceBuffer(t), consumer));
  37. return token_storage.front();
  38. }
  39. };
  40. TEST_F(ParseTreeTest, Empty) {
  41. TokenizedBuffer tokens = GetTokenizedBuffer("");
  42. ParseTree tree = ParseTree::Parse(tokens, consumer);
  43. EXPECT_FALSE(tree.HasErrors());
  44. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFileEnd()}));
  45. }
  46. TEST_F(ParseTreeTest, EmptyDeclaration) {
  47. TokenizedBuffer tokens = GetTokenizedBuffer(";");
  48. ParseTree tree = ParseTree::Parse(tokens, consumer);
  49. EXPECT_FALSE(tree.HasErrors());
  50. auto it = tree.Postorder().begin();
  51. auto end = tree.Postorder().end();
  52. ASSERT_THAT(it, Ne(end));
  53. ParseTree::Node n = *it++;
  54. ASSERT_THAT(it, Ne(end));
  55. ParseTree::Node eof = *it++;
  56. EXPECT_THAT(it, Eq(end));
  57. // Directly test the main API so that we get easier to understand errors in
  58. // simple cases than what the custom matcher will produce.
  59. EXPECT_FALSE(tree.HasErrorInNode(n));
  60. EXPECT_FALSE(tree.HasErrorInNode(eof));
  61. EXPECT_THAT(tree.GetNodeKind(n), Eq(ParseNodeKind::EmptyDeclaration()));
  62. EXPECT_THAT(tree.GetNodeKind(eof), Eq(ParseNodeKind::FileEnd()));
  63. auto t = tree.GetNodeToken(n);
  64. ASSERT_THAT(tokens.Tokens().begin(), Ne(tokens.Tokens().end()));
  65. EXPECT_THAT(t, Eq(*tokens.Tokens().begin()));
  66. EXPECT_THAT(tokens.GetTokenText(t), Eq(";"));
  67. EXPECT_THAT(tree.Children(n).begin(), Eq(tree.Children(n).end()));
  68. EXPECT_THAT(tree.Children(eof).begin(), Eq(tree.Children(eof).end()));
  69. EXPECT_THAT(tree.Postorder().begin(), Eq(tree.Postorder(n).begin()));
  70. EXPECT_THAT(tree.Postorder(n).end(), Eq(tree.Postorder(eof).begin()));
  71. EXPECT_THAT(tree.Postorder(eof).end(), Eq(tree.Postorder().end()));
  72. }
  73. TEST_F(ParseTreeTest, BasicFunctionDeclaration) {
  74. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  75. ParseTree tree = ParseTree::Parse(tokens, consumer);
  76. EXPECT_FALSE(tree.HasErrors());
  77. EXPECT_THAT(tree, MatchParseTreeNodes(
  78. {MatchFunctionDeclaration("fn", MatchDeclaredName("F"),
  79. MatchParameters(),
  80. MatchDeclarationEnd(";")),
  81. MatchFileEnd()}));
  82. }
  83. TEST_F(ParseTreeTest, NoDeclarationIntroducerOrSemi) {
  84. TokenizedBuffer tokens = GetTokenizedBuffer("foo bar baz");
  85. ParseTree tree = ParseTree::Parse(tokens, consumer);
  86. EXPECT_TRUE(tree.HasErrors());
  87. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFileEnd()}));
  88. }
  89. TEST_F(ParseTreeTest, NoDeclarationIntroducerWithSemi) {
  90. TokenizedBuffer tokens = GetTokenizedBuffer("foo;");
  91. ParseTree tree = ParseTree::Parse(tokens, consumer);
  92. EXPECT_TRUE(tree.HasErrors());
  93. EXPECT_THAT(tree, MatchParseTreeNodes({MatchEmptyDeclaration(";", HasError),
  94. MatchFileEnd()}));
  95. }
  96. TEST_F(ParseTreeTest, JustFunctionIntroducerAndSemi) {
  97. TokenizedBuffer tokens = GetTokenizedBuffer("fn;");
  98. ParseTree tree = ParseTree::Parse(tokens, consumer);
  99. EXPECT_TRUE(tree.HasErrors());
  100. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  101. HasError, MatchDeclarationEnd()),
  102. MatchFileEnd()}));
  103. }
  104. TEST_F(ParseTreeTest, RepeatedFunctionIntroducerAndSemi) {
  105. TokenizedBuffer tokens = GetTokenizedBuffer("fn fn;");
  106. ParseTree tree = ParseTree::Parse(tokens, consumer);
  107. EXPECT_TRUE(tree.HasErrors());
  108. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  109. HasError, MatchDeclarationEnd()),
  110. MatchFileEnd()}));
  111. }
  112. TEST_F(ParseTreeTest, FunctionDeclarationWithNoSignatureOrSemi) {
  113. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo");
  114. ParseTree tree = ParseTree::Parse(tokens, consumer);
  115. EXPECT_TRUE(tree.HasErrors());
  116. EXPECT_THAT(tree,
  117. MatchParseTreeNodes(
  118. {MatchFunctionDeclaration(HasError, MatchDeclaredName("foo")),
  119. MatchFileEnd()}));
  120. }
  121. TEST_F(ParseTreeTest,
  122. FunctionDeclarationWithIdentifierInsteadOfSignatureAndSemi) {
  123. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo bar;");
  124. ParseTree tree = ParseTree::Parse(tokens, consumer);
  125. EXPECT_TRUE(tree.HasErrors());
  126. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  127. HasError, MatchDeclaredName("foo"),
  128. MatchDeclarationEnd()),
  129. MatchFileEnd()}));
  130. }
  131. TEST_F(ParseTreeTest, FunctionDeclarationWithParameterList) {
  132. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo(bar: Int, baz: Int);");
  133. ParseTree tree = ParseTree::Parse(tokens, consumer);
  134. EXPECT_FALSE(tree.HasErrors());
  135. EXPECT_THAT(tree,
  136. MatchParseTreeNodes(
  137. {MatchFunctionDeclaration(
  138. MatchDeclaredName("foo"),
  139. MatchParameterList(
  140. MatchPatternBinding(MatchDeclaredName("bar"), ":",
  141. MatchNameReference("Int")),
  142. MatchParameterListComma(),
  143. MatchPatternBinding(MatchDeclaredName("baz"), ":",
  144. MatchNameReference("Int")),
  145. MatchParameterListEnd()),
  146. MatchDeclarationEnd()),
  147. MatchFileEnd()}));
  148. }
  149. TEST_F(ParseTreeTest, FunctionDefinitionWithParameterList) {
  150. TokenizedBuffer tokens = GetTokenizedBuffer(
  151. "fn foo(bar: Int, baz: Int) {\n"
  152. " foo(baz, bar + baz);\n"
  153. "}");
  154. ParseTree tree = ParseTree::Parse(tokens, consumer);
  155. EXPECT_FALSE(tree.HasErrors());
  156. EXPECT_THAT(
  157. tree,
  158. MatchParseTreeNodes(
  159. {MatchFunctionDeclaration(
  160. MatchDeclaredName("foo"),
  161. MatchParameterList(
  162. MatchPatternBinding(MatchDeclaredName("bar"), ":",
  163. MatchNameReference("Int")),
  164. MatchParameterListComma(),
  165. MatchPatternBinding(MatchDeclaredName("baz"), ":",
  166. MatchNameReference("Int")),
  167. MatchParameterListEnd()),
  168. MatchCodeBlock(
  169. MatchExpressionStatement(MatchCallExpression(
  170. MatchNameReference("foo"), MatchNameReference("baz"),
  171. MatchCallExpressionComma(),
  172. MatchInfixOperator(MatchNameReference("bar"), "+",
  173. MatchNameReference("baz")),
  174. MatchCallExpressionEnd())),
  175. MatchCodeBlockEnd())),
  176. MatchFileEnd()}));
  177. }
  178. TEST_F(ParseTreeTest, FunctionDeclarationWithReturnType) {
  179. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo() -> Int;");
  180. ParseTree tree = ParseTree::Parse(tokens, consumer);
  181. EXPECT_FALSE(tree.HasErrors());
  182. EXPECT_THAT(
  183. tree,
  184. MatchParseTreeNodes(
  185. {MatchFunctionDeclaration(MatchDeclaredName("foo"), MatchParameters(),
  186. MatchReturnType(MatchNameReference("Int")),
  187. MatchDeclarationEnd()),
  188. MatchFileEnd()}));
  189. }
  190. TEST_F(ParseTreeTest, FunctionDefinitionWithReturnType) {
  191. TokenizedBuffer tokens = GetTokenizedBuffer(
  192. "fn foo() -> Int {\n"
  193. " return 42;\n"
  194. "}");
  195. ParseTree tree = ParseTree::Parse(tokens, consumer);
  196. EXPECT_FALSE(tree.HasErrors());
  197. EXPECT_THAT(tree,
  198. MatchParseTreeNodes(
  199. {MatchFunctionDeclaration(
  200. MatchDeclaredName("foo"), MatchParameters(),
  201. MatchReturnType(MatchNameReference("Int")),
  202. MatchCodeBlock(MatchReturnStatement(MatchLiteral("42"),
  203. MatchStatementEnd()),
  204. MatchCodeBlockEnd())),
  205. MatchFileEnd()}));
  206. }
  207. TEST_F(ParseTreeTest, FunctionDeclarationWithSingleIdentifierParameterList) {
  208. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo(bar);");
  209. ParseTree tree = ParseTree::Parse(tokens, consumer);
  210. // Note: this might become valid depending on the parameter syntax, this test
  211. // shouldn't be taken as a sign it should remain invalid.
  212. EXPECT_TRUE(tree.HasErrors());
  213. EXPECT_THAT(tree,
  214. MatchParseTreeNodes(
  215. {MatchFunctionDeclaration(
  216. MatchDeclaredName("foo"),
  217. MatchParameterList(HasError, MatchParameterListEnd()),
  218. MatchDeclarationEnd()),
  219. MatchFileEnd()}));
  220. }
  221. TEST_F(ParseTreeTest, FunctionDeclarationWithoutName) {
  222. TokenizedBuffer tokens = GetTokenizedBuffer("fn ();");
  223. ParseTree tree = ParseTree::Parse(tokens, consumer);
  224. EXPECT_TRUE(tree.HasErrors());
  225. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  226. HasError, MatchDeclarationEnd()),
  227. MatchFileEnd()}));
  228. }
  229. TEST_F(ParseTreeTest,
  230. FunctionDeclarationWithoutNameAndManyTokensToSkipInGroupedSymbols) {
  231. TokenizedBuffer tokens = GetTokenizedBuffer(
  232. "fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);");
  233. ParseTree tree = ParseTree::Parse(tokens, consumer);
  234. EXPECT_TRUE(tree.HasErrors());
  235. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  236. HasError, MatchDeclarationEnd()),
  237. MatchFileEnd()}));
  238. }
  239. TEST_F(ParseTreeTest, FunctionDeclarationSkipToNewlineWithoutSemi) {
  240. TokenizedBuffer tokens = GetTokenizedBuffer(
  241. "fn ()\n"
  242. "fn F();");
  243. ParseTree tree = ParseTree::Parse(tokens, consumer);
  244. EXPECT_TRUE(tree.HasErrors());
  245. EXPECT_THAT(
  246. tree, MatchParseTreeNodes({MatchFunctionDeclaration(HasError),
  247. MatchFunctionDeclaration(
  248. MatchDeclaredName("F"), MatchParameters(),
  249. MatchDeclarationEnd()),
  250. MatchFileEnd()}));
  251. }
  252. TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineWithSemi) {
  253. TokenizedBuffer tokens = GetTokenizedBuffer(
  254. "fn (x,\n"
  255. " y,\n"
  256. " z);\n"
  257. "fn F();");
  258. ParseTree tree = ParseTree::Parse(tokens, consumer);
  259. EXPECT_TRUE(tree.HasErrors());
  260. EXPECT_THAT(
  261. tree,
  262. MatchParseTreeNodes(
  263. {MatchFunctionDeclaration(HasError, MatchDeclarationEnd()),
  264. MatchFunctionDeclaration(MatchDeclaredName("F"), MatchParameters(),
  265. MatchDeclarationEnd()),
  266. MatchFileEnd()}));
  267. }
  268. TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineWithoutSemi) {
  269. TokenizedBuffer tokens = GetTokenizedBuffer(
  270. "fn (x,\n"
  271. " y,\n"
  272. " z)\n"
  273. "fn F();");
  274. ParseTree tree = ParseTree::Parse(tokens, consumer);
  275. EXPECT_TRUE(tree.HasErrors());
  276. EXPECT_THAT(
  277. tree, MatchParseTreeNodes({MatchFunctionDeclaration(HasError),
  278. MatchFunctionDeclaration(
  279. MatchDeclaredName("F"), MatchParameters(),
  280. MatchDeclarationEnd()),
  281. MatchFileEnd()}));
  282. }
  283. TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineUntilOutdent) {
  284. TokenizedBuffer tokens = GetTokenizedBuffer(
  285. " fn (x,\n"
  286. " y,\n"
  287. " z)\n"
  288. "fn F();");
  289. ParseTree tree = ParseTree::Parse(tokens, consumer);
  290. EXPECT_TRUE(tree.HasErrors());
  291. EXPECT_THAT(
  292. tree, MatchParseTreeNodes({MatchFunctionDeclaration(HasError),
  293. MatchFunctionDeclaration(
  294. MatchDeclaredName("F"), MatchParameters(),
  295. MatchDeclarationEnd()),
  296. MatchFileEnd()}));
  297. }
  298. TEST_F(ParseTreeTest, FunctionDeclarationSkipWithoutSemiToCurly) {
  299. // FIXME: We don't have a grammar construct that uses curlies yet so this just
  300. // won't parse at all. Once it does, we should ensure that the close brace
  301. // gets properly parsed for the struct (or whatever other curly-braced syntax
  302. // we have grouping function declarations) despite the invalid function
  303. // declaration missing a semicolon.
  304. TokenizedBuffer tokens = GetTokenizedBuffer(
  305. "struct X { fn () }\n"
  306. "fn F();");
  307. ParseTree tree = ParseTree::Parse(tokens, consumer);
  308. EXPECT_TRUE(tree.HasErrors());
  309. }
  310. TEST_F(ParseTreeTest, BasicFunctionDefinition) {
  311. TokenizedBuffer tokens = GetTokenizedBuffer(
  312. "fn F() {\n"
  313. "}");
  314. ParseTree tree = ParseTree::Parse(tokens, consumer);
  315. EXPECT_FALSE(tree.HasErrors());
  316. EXPECT_THAT(tree, MatchParseTreeNodes(
  317. {MatchFunctionDeclaration(
  318. MatchDeclaredName("F"), MatchParameters(),
  319. MatchCodeBlock("{", MatchCodeBlockEnd("}"))),
  320. MatchFileEnd()}));
  321. }
  322. TEST_F(ParseTreeTest, FunctionDefinitionWithIdenifierInStatements) {
  323. TokenizedBuffer tokens = GetTokenizedBuffer(
  324. "fn F() {\n"
  325. " bar\n"
  326. "}");
  327. ParseTree tree = ParseTree::Parse(tokens, consumer);
  328. // Note: this might become valid depending on the expression syntax. This test
  329. // shouldn't be taken as a sign it should remain invalid.
  330. EXPECT_TRUE(tree.HasErrors());
  331. EXPECT_THAT(tree, MatchParseTreeNodes(
  332. {MatchFunctionDeclaration(
  333. MatchDeclaredName("F"), MatchParameters(),
  334. MatchCodeBlock(HasError, MatchNameReference("bar"),
  335. MatchCodeBlockEnd())),
  336. MatchFileEnd()}));
  337. }
  338. TEST_F(ParseTreeTest, FunctionDefinitionWithFunctionCall) {
  339. TokenizedBuffer tokens = GetTokenizedBuffer(
  340. "fn F() {\n"
  341. " a.b.f(c.d, (e)).g();\n"
  342. "}");
  343. ParseTree tree = ParseTree::Parse(tokens, consumer);
  344. EXPECT_FALSE(tree.HasErrors());
  345. ExpectedNode call_to_f = MatchCallExpression(
  346. MatchDesignator(MatchDesignator(MatchNameReference("a"), "b"), "f"),
  347. MatchDesignator(MatchNameReference("c"), "d"), MatchCallExpressionComma(),
  348. MatchParenExpression(MatchNameReference("e"), MatchParenExpressionEnd()),
  349. MatchCallExpressionEnd());
  350. ExpectedNode statement = MatchExpressionStatement(MatchCallExpression(
  351. MatchDesignator(call_to_f, "g"), MatchCallExpressionEnd()));
  352. EXPECT_THAT(tree, MatchParseTreeNodes(
  353. {MatchFunctionWithBody(statement), MatchFileEnd()}));
  354. }
  355. TEST_F(ParseTreeTest, InvalidDesignators) {
  356. TokenizedBuffer tokens = GetTokenizedBuffer(
  357. "fn F() {\n"
  358. " a.;\n"
  359. " a.fn;\n"
  360. " a.42;\n"
  361. "}");
  362. ParseTree tree = ParseTree::Parse(tokens, consumer);
  363. EXPECT_TRUE(tree.HasErrors());
  364. EXPECT_THAT(tree, MatchParseTreeNodes(
  365. {MatchFunctionWithBody(
  366. MatchExpressionStatement(
  367. MatchDesignatorExpression(
  368. MatchNameReference("a"), ".", HasError),
  369. ";"),
  370. MatchExpressionStatement(
  371. MatchDesignatorExpression(
  372. MatchNameReference("a"), ".", HasError),
  373. ";"),
  374. MatchExpressionStatement(
  375. MatchDesignatorExpression(
  376. MatchNameReference("a"), ".", HasError),
  377. HasError, ";")),
  378. MatchFileEnd()}));
  379. }
  380. TEST_F(ParseTreeTest, Operators) {
  381. TokenizedBuffer tokens = GetTokenizedBuffer(
  382. "fn F() {\n"
  383. " n = a * b + c * d = d * d << e & f - not g;\n"
  384. " ++++n;\n"
  385. " n++++;\n"
  386. " a and b and c;\n"
  387. " a and b or c;\n"
  388. " a or b and c;\n"
  389. " not a and not b and not c;\n"
  390. "}");
  391. ParseTree tree = ParseTree::Parse(tokens, consumer);
  392. EXPECT_TRUE(tree.HasErrors());
  393. EXPECT_THAT(
  394. tree,
  395. MatchParseTreeNodes(
  396. {MatchFunctionWithBody(
  397. MatchExpressionStatement(MatchInfixOperator(
  398. MatchNameReference("n"), "=",
  399. MatchInfixOperator(
  400. MatchInfixOperator(
  401. MatchInfixOperator(MatchNameReference("a"), "*",
  402. MatchNameReference("b")),
  403. "+",
  404. MatchInfixOperator(MatchNameReference("c"), "*",
  405. MatchNameReference("d"))),
  406. "=",
  407. MatchInfixOperator(
  408. HasError,
  409. MatchInfixOperator(
  410. HasError,
  411. MatchInfixOperator(
  412. HasError,
  413. MatchInfixOperator(MatchNameReference("d"),
  414. "*",
  415. MatchNameReference("d")),
  416. "<<", MatchNameReference("e")),
  417. "&", MatchNameReference("f")),
  418. "-",
  419. MatchPrefixOperator("not",
  420. MatchNameReference("g")))))),
  421. MatchExpressionStatement(MatchPrefixOperator(
  422. "++", MatchPrefixOperator("++", MatchNameReference("n")))),
  423. MatchExpressionStatement(MatchPostfixOperator(
  424. MatchPostfixOperator(MatchNameReference("n"), "++"), "++")),
  425. MatchExpressionStatement(MatchInfixOperator(
  426. MatchInfixOperator(MatchNameReference("a"), "and",
  427. MatchNameReference("b")),
  428. "and", MatchNameReference("c"))),
  429. MatchExpressionStatement(MatchInfixOperator(
  430. HasError,
  431. MatchInfixOperator(MatchNameReference("a"), "and",
  432. MatchNameReference("b")),
  433. "or", MatchNameReference("c"))),
  434. MatchExpressionStatement(MatchInfixOperator(
  435. HasError,
  436. MatchInfixOperator(MatchNameReference("a"), "or",
  437. MatchNameReference("b")),
  438. "and", MatchNameReference("c"))),
  439. MatchExpressionStatement(MatchInfixOperator(
  440. MatchInfixOperator(
  441. MatchPrefixOperator("not", MatchNameReference("a")),
  442. "and",
  443. MatchPrefixOperator("not", MatchNameReference("b"))),
  444. "and",
  445. MatchPrefixOperator("not", MatchNameReference("c"))))),
  446. MatchFileEnd()}));
  447. }
  448. TEST_F(ParseTreeTest, OperatorFixity) {
  449. TokenizedBuffer tokens = GetTokenizedBuffer(
  450. "fn F(p: Int*, n: Int) {\n"
  451. " var q: Int* = p;\n"
  452. " var t: Type = Int*;\n"
  453. " t = t**;\n"
  454. " n = n * n;\n"
  455. " n = n * *p;\n"
  456. " n = n*n;\n"
  457. " G(Int*, n * n);\n"
  458. "}");
  459. ParseTree tree = ParseTree::Parse(tokens, consumer);
  460. EXPECT_FALSE(tree.HasErrors());
  461. EXPECT_THAT(
  462. tree,
  463. MatchParseTreeNodes(
  464. {MatchFunctionDeclaration(
  465. MatchDeclaredName("F"),
  466. MatchParameters(
  467. MatchPatternBinding(
  468. MatchDeclaredName("p"),
  469. MatchPostfixOperator(MatchNameReference("Int"), "*")),
  470. MatchParameterListComma(),
  471. MatchPatternBinding(MatchDeclaredName("n"),
  472. MatchNameReference("Int"))),
  473. MatchCodeBlock(
  474. MatchVariableDeclaration(
  475. MatchPatternBinding(MatchDeclaredName("q"),
  476. MatchPostfixOperator(
  477. MatchNameReference("Int"), "*")),
  478. MatchVariableInitializer(MatchNameReference("p")),
  479. MatchDeclarationEnd()),
  480. MatchVariableDeclaration(
  481. MatchPatternBinding(MatchDeclaredName("t"),
  482. MatchNameReference("Type")),
  483. MatchVariableInitializer(MatchPostfixOperator(
  484. MatchNameReference("Int"), "*")),
  485. MatchDeclarationEnd()),
  486. MatchExpressionStatement(MatchInfixOperator(
  487. MatchNameReference("t"), "=",
  488. MatchPostfixOperator(
  489. MatchPostfixOperator(MatchNameReference("t"), "*"),
  490. "*"))),
  491. MatchExpressionStatement(MatchInfixOperator(
  492. MatchNameReference("n"), "=",
  493. MatchInfixOperator(MatchNameReference("n"), "*",
  494. MatchNameReference("n")))),
  495. MatchExpressionStatement(MatchInfixOperator(
  496. MatchNameReference("n"), "=",
  497. MatchInfixOperator(
  498. MatchNameReference("n"), "*",
  499. MatchPrefixOperator("*", MatchNameReference("p"))))),
  500. MatchExpressionStatement(MatchInfixOperator(
  501. MatchNameReference("n"), "=",
  502. MatchInfixOperator(MatchNameReference("n"), "*",
  503. MatchNameReference("n")))),
  504. MatchExpressionStatement(MatchCallExpression(
  505. MatchNameReference("G"),
  506. MatchPostfixOperator(MatchNameReference("Int"), "*"),
  507. MatchCallExpressionComma(),
  508. MatchInfixOperator(MatchNameReference("n"), "*",
  509. MatchNameReference("n")),
  510. MatchCallExpressionEnd())),
  511. MatchCodeBlockEnd())),
  512. MatchFileEnd()}));
  513. }
  514. TEST_F(ParseTreeTest, OperatorWhitespaceErrors) {
  515. // Test dispositions: Recovered means we issued an error but recovered a
  516. // proper parse tree; Failed means we didn't fully recover from the error.
  517. enum Kind { Valid, Recovered, Failed };
  518. struct Testcase {
  519. const char* input;
  520. Kind kind;
  521. } testcases[] = {
  522. {"var v: Type = Int*;", Valid},
  523. {"var v: Type = Int *;", Recovered},
  524. {"var v: Type = Int* ;", Valid},
  525. {"var v: Type = Int * ;", Recovered},
  526. {"var n: Int = n * n;", Valid},
  527. {"var n: Int = n*n;", Valid},
  528. {"var n: Int = (n)*3;", Valid},
  529. {"var n: Int = 3*(n);", Valid},
  530. {"var n: Int = n *n;", Recovered},
  531. // FIXME: We could figure out that this first Failed example is infix
  532. // with one-token lookahead.
  533. {"var n: Int = n* n;", Failed},
  534. {"var n: Int = n* -n;", Failed},
  535. {"var n: Int = n* *p;", Failed},
  536. // FIXME: We try to form (n*)*p and reject due to missing parentheses
  537. // before we notice the missing whitespace around the second `*`.
  538. // It'd be better to (somehow) form n*(*p) and reject due to the missing
  539. // whitespace around the first `*`.
  540. {"var n: Int = n**p;", Failed},
  541. {"var n: Int = -n;", Valid},
  542. {"var n: Int = - n;", Recovered},
  543. {"var n: Int =-n;", Valid},
  544. {"var n: Int =- n;", Recovered},
  545. {"var n: Int = F(Int *);", Recovered},
  546. {"var n: Int = F(Int *, 0);", Recovered},
  547. };
  548. for (auto [input, kind] : testcases) {
  549. TokenizedBuffer tokens = GetTokenizedBuffer(input);
  550. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  551. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  552. EXPECT_THAT(tree.HasErrors(), Eq(kind == Failed)) << input;
  553. EXPECT_THAT(error_tracker.SeenError(), Eq(kind != Valid)) << input;
  554. }
  555. }
  556. TEST_F(ParseTreeTest, VariableDeclarations) {
  557. TokenizedBuffer tokens = GetTokenizedBuffer(
  558. "var v: Int = 0;\n"
  559. "var w: Int;\n"
  560. "fn F() {\n"
  561. " var s: String = \"hello\";\n"
  562. "}");
  563. ParseTree tree = ParseTree::Parse(tokens, consumer);
  564. EXPECT_FALSE(tree.HasErrors());
  565. EXPECT_THAT(tree,
  566. MatchParseTreeNodes(
  567. {MatchVariableDeclaration(
  568. MatchPatternBinding(MatchDeclaredName("v"), ":",
  569. MatchNameReference("Int")),
  570. MatchVariableInitializer(MatchLiteral("0")),
  571. MatchDeclarationEnd()),
  572. MatchVariableDeclaration(
  573. MatchPatternBinding(MatchDeclaredName("w"), ":",
  574. MatchNameReference("Int")),
  575. MatchDeclarationEnd()),
  576. MatchFunctionWithBody(MatchVariableDeclaration(
  577. MatchPatternBinding(MatchDeclaredName("s"), ":",
  578. MatchNameReference("String")),
  579. MatchVariableInitializer(MatchLiteral("\"hello\"")),
  580. MatchDeclarationEnd())),
  581. MatchFileEnd()}));
  582. }
  583. TEST_F(ParseTreeTest, IfNoElse) {
  584. TokenizedBuffer tokens = GetTokenizedBuffer(
  585. "fn F() {\n"
  586. " if (a) {\n"
  587. " if (b) {\n"
  588. " if (c) {\n"
  589. " d;\n"
  590. " }\n"
  591. " }\n"
  592. " }\n"
  593. "}");
  594. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  595. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  596. EXPECT_FALSE(tree.HasErrors());
  597. EXPECT_FALSE(error_tracker.SeenError());
  598. EXPECT_THAT(
  599. tree,
  600. MatchParseTreeNodes(
  601. {MatchFunctionWithBody(MatchIfStatement(
  602. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  603. MatchCodeBlock(
  604. MatchIfStatement(
  605. MatchCondition(MatchNameReference("b"),
  606. MatchConditionEnd()),
  607. MatchCodeBlock(
  608. MatchIfStatement(
  609. MatchCondition(MatchNameReference("c"),
  610. MatchConditionEnd()),
  611. MatchCodeBlock(MatchExpressionStatement(
  612. MatchNameReference("d")),
  613. MatchCodeBlockEnd())),
  614. MatchCodeBlockEnd())),
  615. MatchCodeBlockEnd()))),
  616. MatchFileEnd()}));
  617. }
  618. TEST_F(ParseTreeTest, IfNoElseUnbraced) {
  619. TokenizedBuffer tokens = GetTokenizedBuffer(
  620. "fn F() {\n"
  621. " if (a)\n"
  622. " if (b)\n"
  623. " if (c)\n"
  624. " d;\n"
  625. "}");
  626. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  627. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  628. // The missing braces are invalid, but we should be able to recover.
  629. EXPECT_FALSE(tree.HasErrors());
  630. EXPECT_TRUE(error_tracker.SeenError());
  631. EXPECT_THAT(
  632. tree,
  633. MatchParseTreeNodes(
  634. {MatchFunctionWithBody(MatchIfStatement(
  635. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  636. MatchIfStatement(
  637. MatchCondition(MatchNameReference("b"), MatchConditionEnd()),
  638. MatchIfStatement(
  639. MatchCondition(MatchNameReference("c"),
  640. MatchConditionEnd()),
  641. MatchExpressionStatement(MatchNameReference("d")))))),
  642. MatchFileEnd()}));
  643. }
  644. TEST_F(ParseTreeTest, IfElse) {
  645. TokenizedBuffer tokens = GetTokenizedBuffer(
  646. "fn F() {\n"
  647. " if (a) {\n"
  648. " if (b) {\n"
  649. " c;\n"
  650. " } else {\n"
  651. " d;\n"
  652. " }\n"
  653. " } else {\n"
  654. " e;\n"
  655. " }\n"
  656. " if (x) { G(1); }\n"
  657. " else if (x) { G(2); }\n"
  658. " else { G(3); }\n"
  659. "}");
  660. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  661. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  662. EXPECT_FALSE(tree.HasErrors());
  663. EXPECT_FALSE(error_tracker.SeenError());
  664. EXPECT_THAT(
  665. tree,
  666. MatchParseTreeNodes(
  667. {MatchFunctionWithBody(
  668. MatchIfStatement(
  669. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  670. MatchCodeBlock(
  671. MatchIfStatement(
  672. MatchCondition(MatchNameReference("b"),
  673. MatchConditionEnd()),
  674. MatchCodeBlock(MatchExpressionStatement(
  675. MatchNameReference("c")),
  676. MatchCodeBlockEnd()),
  677. MatchIfStatementElse(),
  678. MatchCodeBlock(MatchExpressionStatement(
  679. MatchNameReference("d")),
  680. MatchCodeBlockEnd())),
  681. MatchCodeBlockEnd()),
  682. MatchIfStatementElse(),
  683. MatchCodeBlock(
  684. MatchExpressionStatement(MatchNameReference("e")),
  685. MatchCodeBlockEnd())),
  686. MatchIfStatement(
  687. MatchCondition(MatchNameReference("x"), MatchConditionEnd()),
  688. MatchCodeBlock(
  689. MatchExpressionStatement(MatchCallExpression(
  690. MatchNameReference("G"), MatchLiteral("1"),
  691. MatchCallExpressionEnd())),
  692. MatchCodeBlockEnd()),
  693. MatchIfStatementElse(),
  694. MatchIfStatement(
  695. MatchCondition(MatchNameReference("x"),
  696. MatchConditionEnd()),
  697. MatchCodeBlock(
  698. MatchExpressionStatement(MatchCallExpression(
  699. MatchNameReference("G"), MatchLiteral("2"),
  700. MatchCallExpressionEnd())),
  701. MatchCodeBlockEnd()),
  702. MatchIfStatementElse(),
  703. MatchCodeBlock(
  704. MatchExpressionStatement(MatchCallExpression(
  705. MatchNameReference("G"), MatchLiteral("3"),
  706. MatchCallExpressionEnd())),
  707. MatchCodeBlockEnd())))),
  708. MatchFileEnd()}));
  709. }
  710. TEST_F(ParseTreeTest, IfElseUnbraced) {
  711. TokenizedBuffer tokens = GetTokenizedBuffer(
  712. "fn F() {\n"
  713. " if (a)\n"
  714. " if (b)\n"
  715. " c;\n"
  716. " else\n"
  717. " d;\n"
  718. " else\n"
  719. " e;\n"
  720. " if (x) { G(1); }\n"
  721. " else if (x) { G(2); }\n"
  722. " else { G(3); }\n"
  723. "}");
  724. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  725. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  726. // The missing braces are invalid, but we should be able to recover.
  727. EXPECT_FALSE(tree.HasErrors());
  728. EXPECT_TRUE(error_tracker.SeenError());
  729. EXPECT_THAT(
  730. tree,
  731. MatchParseTreeNodes(
  732. {MatchFunctionWithBody(
  733. MatchIfStatement(
  734. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  735. MatchIfStatement(
  736. MatchCondition(MatchNameReference("b"),
  737. MatchConditionEnd()),
  738. MatchExpressionStatement(MatchNameReference("c")),
  739. MatchIfStatementElse(),
  740. MatchExpressionStatement(MatchNameReference("d"))),
  741. MatchIfStatementElse(),
  742. MatchExpressionStatement(MatchNameReference("e"))),
  743. MatchIfStatement(
  744. MatchCondition(MatchNameReference("x"), MatchConditionEnd()),
  745. MatchCodeBlock(
  746. MatchExpressionStatement(MatchCallExpression(
  747. MatchNameReference("G"), MatchLiteral("1"),
  748. MatchCallExpressionEnd())),
  749. MatchCodeBlockEnd()),
  750. MatchIfStatementElse(),
  751. MatchIfStatement(
  752. MatchCondition(MatchNameReference("x"),
  753. MatchConditionEnd()),
  754. MatchCodeBlock(
  755. MatchExpressionStatement(MatchCallExpression(
  756. MatchNameReference("G"), MatchLiteral("2"),
  757. MatchCallExpressionEnd())),
  758. MatchCodeBlockEnd()),
  759. MatchIfStatementElse(),
  760. MatchCodeBlock(
  761. MatchExpressionStatement(MatchCallExpression(
  762. MatchNameReference("G"), MatchLiteral("3"),
  763. MatchCallExpressionEnd())),
  764. MatchCodeBlockEnd())))),
  765. MatchFileEnd()}));
  766. }
  767. TEST_F(ParseTreeTest, IfError) {
  768. TokenizedBuffer tokens = GetTokenizedBuffer(
  769. "fn F() {\n"
  770. " if a {}\n"
  771. " if () {}\n"
  772. " if (b c) {}\n"
  773. " if (d)\n"
  774. "}");
  775. ParseTree tree = ParseTree::Parse(tokens, consumer);
  776. EXPECT_TRUE(tree.HasErrors());
  777. EXPECT_THAT(
  778. tree,
  779. MatchParseTreeNodes(
  780. {MatchFunctionWithBody(
  781. MatchIfStatement(HasError, MatchNameReference("a"),
  782. MatchCodeBlock(MatchCodeBlockEnd())),
  783. MatchIfStatement(MatchCondition(HasError, MatchConditionEnd()),
  784. MatchCodeBlock(MatchCodeBlockEnd())),
  785. MatchIfStatement(
  786. MatchCondition(HasError, MatchNameReference("b"),
  787. MatchConditionEnd()),
  788. MatchCodeBlock(MatchCodeBlockEnd())),
  789. MatchIfStatement(HasError,
  790. MatchCondition(MatchNameReference("d"),
  791. MatchConditionEnd()))),
  792. MatchFileEnd()}));
  793. }
  794. TEST_F(ParseTreeTest, WhileBreakContinue) {
  795. TokenizedBuffer tokens = GetTokenizedBuffer(
  796. "fn F() {\n"
  797. " while (a) {\n"
  798. " if (b) {\n"
  799. " break;\n"
  800. " }\n"
  801. " if (c) {\n"
  802. " continue;\n"
  803. " }\n"
  804. "}");
  805. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  806. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  807. EXPECT_FALSE(tree.HasErrors());
  808. EXPECT_FALSE(error_tracker.SeenError());
  809. EXPECT_THAT(
  810. tree,
  811. MatchParseTreeNodes(
  812. {MatchFunctionWithBody(MatchWhileStatement(
  813. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  814. MatchCodeBlock(
  815. MatchIfStatement(
  816. MatchCondition(MatchNameReference("b"),
  817. MatchConditionEnd()),
  818. MatchCodeBlock(MatchBreakStatement(MatchStatementEnd()),
  819. MatchCodeBlockEnd())),
  820. MatchIfStatement(MatchCondition(MatchNameReference("c"),
  821. MatchConditionEnd()),
  822. MatchCodeBlock(MatchContinueStatement(
  823. MatchStatementEnd()),
  824. MatchCodeBlockEnd())),
  825. MatchCodeBlockEnd()))),
  826. MatchFileEnd()}));
  827. }
  828. TEST_F(ParseTreeTest, WhileUnbraced) {
  829. TokenizedBuffer tokens = GetTokenizedBuffer(
  830. "fn F() {\n"
  831. " while (a) \n"
  832. " break;\n"
  833. "}");
  834. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  835. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  836. EXPECT_FALSE(tree.HasErrors());
  837. EXPECT_TRUE(error_tracker.SeenError());
  838. EXPECT_THAT(
  839. tree,
  840. MatchParseTreeNodes(
  841. {MatchFunctionWithBody(MatchWhileStatement(
  842. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  843. MatchBreakStatement(MatchStatementEnd()))),
  844. MatchFileEnd()}));
  845. }
  846. TEST_F(ParseTreeTest, Return) {
  847. TokenizedBuffer tokens = GetTokenizedBuffer(
  848. "fn F() {\n"
  849. " if (c) {\n"
  850. " return;\n"
  851. " }\n"
  852. "}\n"
  853. "fn G(x: Int) -> Int {\n"
  854. " return x;\n"
  855. "}");
  856. ParseTree tree = ParseTree::Parse(tokens, consumer);
  857. EXPECT_FALSE(tree.HasErrors());
  858. EXPECT_THAT(
  859. tree,
  860. MatchParseTreeNodes(
  861. {MatchFunctionWithBody(MatchIfStatement(
  862. MatchCondition(MatchNameReference("c"), MatchConditionEnd()),
  863. MatchCodeBlock(MatchReturnStatement(MatchStatementEnd()),
  864. MatchCodeBlockEnd()))),
  865. MatchFunctionDeclaration(
  866. MatchDeclaredName(),
  867. MatchParameters(MatchPatternBinding(MatchDeclaredName("x"), ":",
  868. MatchNameReference("Int"))),
  869. MatchReturnType(MatchNameReference("Int")),
  870. MatchCodeBlock(MatchReturnStatement(MatchNameReference("x"),
  871. MatchStatementEnd()),
  872. MatchCodeBlockEnd())),
  873. MatchFileEnd()}));
  874. }
  875. auto GetAndDropLine(llvm::StringRef& s) -> std::string {
  876. auto newline_offset = s.find_first_of('\n');
  877. llvm::StringRef line = s.slice(0, newline_offset);
  878. if (newline_offset != llvm::StringRef::npos) {
  879. s = s.substr(newline_offset + 1);
  880. } else {
  881. s = "";
  882. }
  883. return line.str();
  884. }
  885. TEST_F(ParseTreeTest, Printing) {
  886. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  887. ParseTree tree = ParseTree::Parse(tokens, consumer);
  888. EXPECT_FALSE(tree.HasErrors());
  889. std::string print_storage;
  890. llvm::raw_string_ostream print_stream(print_storage);
  891. tree.Print(print_stream);
  892. llvm::StringRef print = print_stream.str();
  893. EXPECT_THAT(GetAndDropLine(print), StrEq("["));
  894. EXPECT_THAT(GetAndDropLine(print),
  895. StrEq("{node_index: 4, kind: 'FunctionDeclaration', text: 'fn', "
  896. "subtree_size: 5, children: ["));
  897. EXPECT_THAT(GetAndDropLine(print),
  898. StrEq(" {node_index: 0, kind: 'DeclaredName', text: 'F'},"));
  899. EXPECT_THAT(GetAndDropLine(print),
  900. StrEq(" {node_index: 2, kind: 'ParameterList', text: '(', "
  901. "subtree_size: 2, children: ["));
  902. EXPECT_THAT(GetAndDropLine(print),
  903. StrEq(" {node_index: 1, kind: 'ParameterListEnd', "
  904. "text: ')'}]},"));
  905. EXPECT_THAT(GetAndDropLine(print),
  906. StrEq(" {node_index: 3, kind: 'DeclarationEnd', text: ';'}]},"));
  907. EXPECT_THAT(GetAndDropLine(print),
  908. StrEq("{node_index: 5, kind: 'FileEnd', text: ''},"));
  909. EXPECT_THAT(GetAndDropLine(print), StrEq("]"));
  910. EXPECT_TRUE(print.empty()) << print;
  911. }
  912. TEST_F(ParseTreeTest, PrintingAsYAML) {
  913. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  914. ParseTree tree = ParseTree::Parse(tokens, consumer);
  915. EXPECT_FALSE(tree.HasErrors());
  916. std::string print_output;
  917. llvm::raw_string_ostream print_stream(print_output);
  918. tree.Print(print_stream);
  919. print_stream.flush();
  920. EXPECT_THAT(
  921. Yaml::Value::FromText(print_output),
  922. ElementsAre(Yaml::SequenceValue{
  923. Yaml::MappingValue{
  924. {"node_index", "4"},
  925. {"kind", "FunctionDeclaration"},
  926. {"text", "fn"},
  927. {"subtree_size", "5"},
  928. {"children",
  929. Yaml::SequenceValue{
  930. Yaml::MappingValue{{"node_index", "0"},
  931. {"kind", "DeclaredName"},
  932. {"text", "F"}},
  933. Yaml::MappingValue{{"node_index", "2"},
  934. {"kind", "ParameterList"},
  935. {"text", "("},
  936. {"subtree_size", "2"},
  937. {"children", //
  938. Yaml::SequenceValue{Yaml::MappingValue{
  939. {"node_index", "1"},
  940. {"kind", "ParameterListEnd"},
  941. {"text", ")"}}}}},
  942. Yaml::MappingValue{{"node_index", "3"},
  943. {"kind", "DeclarationEnd"},
  944. {"text", ";"}}}}},
  945. Yaml::MappingValue{{"node_index", "5"}, //
  946. {"kind", "FileEnd"},
  947. {"text", ""}}}));
  948. }
  949. } // namespace
  950. } // namespace Carbon