ast_to_proto.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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/fuzzing/ast_to_proto.h"
  5. #include <optional>
  6. #include "executable_semantics/ast/declaration.h"
  7. #include "executable_semantics/ast/expression.h"
  8. #include "llvm/Support/Casting.h"
  9. namespace Carbon {
  10. using ::llvm::cast;
  11. static auto ExpressionToProto(const Expression& expression)
  12. -> Fuzzing::Expression;
  13. static auto PatternToProto(const Pattern& pattern) -> Fuzzing::Pattern;
  14. static auto StatementToProto(const Statement& statement) -> Fuzzing::Statement;
  15. static auto DeclarationToProto(const Declaration& declaration)
  16. -> Fuzzing::Declaration;
  17. static auto LibraryNameToProto(const LibraryName& library_name)
  18. -> Fuzzing::LibraryName {
  19. Fuzzing::LibraryName library_name_proto;
  20. library_name_proto.set_package_name(library_name.package);
  21. if (!library_name.path.empty()) {
  22. library_name_proto.set_path(library_name.path);
  23. }
  24. return library_name_proto;
  25. }
  26. static auto OperatorToProtoEnum(const Operator op)
  27. -> Fuzzing::PrimitiveOperatorExpression::Operator {
  28. switch (op) {
  29. case Operator::AddressOf:
  30. return Fuzzing::PrimitiveOperatorExpression::AddressOf;
  31. case Operator::Deref:
  32. return Fuzzing::PrimitiveOperatorExpression::Deref;
  33. case Operator::Neg:
  34. return Fuzzing::PrimitiveOperatorExpression::Neg;
  35. case Operator::Not:
  36. return Fuzzing::PrimitiveOperatorExpression::Not;
  37. case Operator::Ptr:
  38. return Fuzzing::PrimitiveOperatorExpression::Ptr;
  39. case Operator::Add:
  40. return Fuzzing::PrimitiveOperatorExpression::Add;
  41. case Operator::And:
  42. return Fuzzing::PrimitiveOperatorExpression::And;
  43. case Operator::Eq:
  44. return Fuzzing::PrimitiveOperatorExpression::Eq;
  45. case Operator::Mul:
  46. return Fuzzing::PrimitiveOperatorExpression::Mul;
  47. case Operator::Or:
  48. return Fuzzing::PrimitiveOperatorExpression::Or;
  49. case Operator::Sub:
  50. return Fuzzing::PrimitiveOperatorExpression::Sub;
  51. }
  52. }
  53. static auto FieldInitializerToProto(const FieldInitializer& field)
  54. -> Fuzzing::FieldInitializer {
  55. Fuzzing::FieldInitializer field_proto;
  56. field_proto.set_name(field.name());
  57. *field_proto.mutable_expression() = ExpressionToProto(field.expression());
  58. return field_proto;
  59. }
  60. static auto TupleLiteralExpressionToProto(const TupleLiteral& tuple_literal)
  61. -> Fuzzing::TupleLiteralExpression {
  62. Fuzzing::TupleLiteralExpression tuple_literal_proto;
  63. for (Nonnull<const Expression*> field : tuple_literal.fields()) {
  64. *tuple_literal_proto.add_fields() = ExpressionToProto(*field);
  65. }
  66. return tuple_literal_proto;
  67. }
  68. static auto ExpressionToProto(const Expression& expression)
  69. -> Fuzzing::Expression {
  70. Fuzzing::Expression expression_proto;
  71. switch (expression.kind()) {
  72. case ExpressionKind::CallExpression: {
  73. const auto& call = cast<CallExpression>(expression);
  74. auto* call_proto = expression_proto.mutable_call();
  75. *call_proto->mutable_function() = ExpressionToProto(call.function());
  76. *call_proto->mutable_argument() = ExpressionToProto(call.argument());
  77. break;
  78. }
  79. case ExpressionKind::FunctionTypeLiteral: {
  80. const auto& fun_type = cast<FunctionTypeLiteral>(expression);
  81. auto* fun_type_proto = expression_proto.mutable_function_type();
  82. *fun_type_proto->mutable_parameter() =
  83. ExpressionToProto(fun_type.parameter());
  84. *fun_type_proto->mutable_return_type() =
  85. ExpressionToProto(fun_type.return_type());
  86. break;
  87. }
  88. case ExpressionKind::FieldAccessExpression: {
  89. const auto& field_access = cast<FieldAccessExpression>(expression);
  90. auto* field_access_proto = expression_proto.mutable_field_access();
  91. field_access_proto->set_field(field_access.field());
  92. *field_access_proto->mutable_aggregate() =
  93. ExpressionToProto(field_access.aggregate());
  94. break;
  95. }
  96. case ExpressionKind::IndexExpression: {
  97. const auto& index = cast<IndexExpression>(expression);
  98. auto* index_proto = expression_proto.mutable_index();
  99. *index_proto->mutable_aggregate() = ExpressionToProto(index.aggregate());
  100. *index_proto->mutable_offset() = ExpressionToProto(index.offset());
  101. break;
  102. }
  103. case ExpressionKind::PrimitiveOperatorExpression: {
  104. const auto& primitive_operator =
  105. cast<PrimitiveOperatorExpression>(expression);
  106. auto* operator_proto = expression_proto.mutable_primitive_operator();
  107. operator_proto->set_op(OperatorToProtoEnum(primitive_operator.op()));
  108. for (Nonnull<const Expression*> arg : primitive_operator.arguments()) {
  109. *operator_proto->add_arguments() = ExpressionToProto(*arg);
  110. }
  111. break;
  112. }
  113. case ExpressionKind::TupleLiteral:
  114. *expression_proto.mutable_tuple_literal() =
  115. TupleLiteralExpressionToProto(cast<TupleLiteral>(expression));
  116. break;
  117. case ExpressionKind::StructLiteral: {
  118. const auto& struct_literal = cast<StructLiteral>(expression);
  119. auto* struct_literal_proto = expression_proto.mutable_struct_literal();
  120. for (const FieldInitializer& field : struct_literal.fields()) {
  121. *struct_literal_proto->add_fields() = FieldInitializerToProto(field);
  122. }
  123. break;
  124. }
  125. case ExpressionKind::StructTypeLiteral: {
  126. const auto& struct_type_literal = cast<StructTypeLiteral>(expression);
  127. auto* struct_type_literal_proto =
  128. expression_proto.mutable_struct_type_literal();
  129. for (const FieldInitializer& field : struct_type_literal.fields()) {
  130. *struct_type_literal_proto->add_fields() =
  131. FieldInitializerToProto(field);
  132. }
  133. break;
  134. }
  135. case ExpressionKind::IdentifierExpression: {
  136. const auto& identifier = cast<IdentifierExpression>(expression);
  137. auto* identifier_proto = expression_proto.mutable_identifier();
  138. identifier_proto->set_name(identifier.name());
  139. break;
  140. }
  141. case ExpressionKind::IntrinsicExpression: {
  142. const auto& intrinsic = cast<IntrinsicExpression>(expression);
  143. auto* intrinsic_proto = expression_proto.mutable_intrinsic();
  144. switch (intrinsic.intrinsic()) {
  145. case IntrinsicExpression::Intrinsic::Print:
  146. intrinsic_proto->set_intrinsic(Fuzzing::IntrinsicExpression::Print);
  147. break;
  148. }
  149. *intrinsic_proto->mutable_argument() =
  150. TupleLiteralExpressionToProto(intrinsic.args());
  151. break;
  152. }
  153. case ExpressionKind::IfExpression: {
  154. const auto& if_expression = cast<IfExpression>(expression);
  155. auto* if_proto = expression_proto.mutable_if_expression();
  156. if (if_expression.condition()) {
  157. *if_proto->mutable_condition() =
  158. ExpressionToProto(*if_expression.condition());
  159. }
  160. if (if_expression.then_expression()) {
  161. *if_proto->mutable_then_expression() =
  162. ExpressionToProto(*if_expression.then_expression());
  163. }
  164. if (if_expression.else_expression()) {
  165. *if_proto->mutable_else_expression() =
  166. ExpressionToProto(*if_expression.else_expression());
  167. }
  168. break;
  169. }
  170. case ExpressionKind::BoolTypeLiteral:
  171. expression_proto.mutable_bool_type_literal();
  172. break;
  173. case ExpressionKind::BoolLiteral:
  174. expression_proto.mutable_bool_literal()->set_value(
  175. cast<BoolLiteral>(expression).value());
  176. break;
  177. case ExpressionKind::IntTypeLiteral:
  178. expression_proto.mutable_int_type_literal();
  179. break;
  180. case ExpressionKind::IntLiteral:
  181. expression_proto.mutable_int_literal()->set_value(
  182. cast<IntLiteral>(expression).value());
  183. break;
  184. case ExpressionKind::StringLiteral:
  185. expression_proto.mutable_string_literal()->set_value(
  186. cast<StringLiteral>(expression).value());
  187. break;
  188. case ExpressionKind::StringTypeLiteral:
  189. expression_proto.mutable_string_type_literal();
  190. break;
  191. case ExpressionKind::ContinuationTypeLiteral:
  192. expression_proto.mutable_continuation_type_literal();
  193. break;
  194. case ExpressionKind::TypeTypeLiteral:
  195. expression_proto.mutable_type_type_literal();
  196. break;
  197. case ExpressionKind::UnimplementedExpression:
  198. expression_proto.mutable_unimplemented_expression();
  199. break;
  200. case ExpressionKind::ArrayTypeLiteral: {
  201. const auto& array_literal = cast<ArrayTypeLiteral>(expression);
  202. Fuzzing::ArrayTypeLiteral* array_literal_proto =
  203. expression_proto.mutable_array_type_literal();
  204. *array_literal_proto->mutable_element_type() =
  205. ExpressionToProto(array_literal.element_type_expression());
  206. *array_literal_proto->mutable_size() =
  207. ExpressionToProto(array_literal.size_expression());
  208. break;
  209. }
  210. }
  211. return expression_proto;
  212. }
  213. static auto BindingPatternToProto(const BindingPattern& pattern)
  214. -> Fuzzing::BindingPattern {
  215. Fuzzing::BindingPattern pattern_proto;
  216. pattern_proto.set_name(pattern.name());
  217. *pattern_proto.mutable_type() = PatternToProto(pattern.type());
  218. return pattern_proto;
  219. }
  220. static auto GenericBindingToProto(const GenericBinding& binding)
  221. -> Fuzzing::GenericBinding {
  222. Fuzzing::GenericBinding binding_proto;
  223. binding_proto.set_name(binding.name());
  224. *binding_proto.mutable_type() = ExpressionToProto(binding.type());
  225. return binding_proto;
  226. }
  227. static auto TuplePatternToProto(const TuplePattern& tuple_pattern)
  228. -> Fuzzing::TuplePattern {
  229. Fuzzing::TuplePattern tuple_pattern_proto;
  230. for (Nonnull<const Pattern*> field : tuple_pattern.fields()) {
  231. *tuple_pattern_proto.add_fields() = PatternToProto(*field);
  232. }
  233. return tuple_pattern_proto;
  234. }
  235. static auto PatternToProto(const Pattern& pattern) -> Fuzzing::Pattern {
  236. Fuzzing::Pattern pattern_proto;
  237. switch (pattern.kind()) {
  238. case PatternKind::GenericBinding: {
  239. const auto& binding = cast<GenericBinding>(pattern);
  240. *pattern_proto.mutable_generic_binding() = GenericBindingToProto(binding);
  241. break;
  242. }
  243. case PatternKind::BindingPattern: {
  244. const auto& binding = cast<BindingPattern>(pattern);
  245. *pattern_proto.mutable_binding_pattern() = BindingPatternToProto(binding);
  246. break;
  247. }
  248. case PatternKind::TuplePattern:
  249. *pattern_proto.mutable_tuple_pattern() =
  250. TuplePatternToProto(cast<TuplePattern>(pattern));
  251. break;
  252. case PatternKind::AlternativePattern: {
  253. const auto& alternative = cast<AlternativePattern>(pattern);
  254. auto* alternative_proto = pattern_proto.mutable_alternative_pattern();
  255. alternative_proto->set_alternative_name(alternative.alternative_name());
  256. *alternative_proto->mutable_choice_type() =
  257. ExpressionToProto(alternative.choice_type());
  258. *alternative_proto->mutable_arguments() =
  259. TuplePatternToProto(alternative.arguments());
  260. break;
  261. }
  262. case PatternKind::ExpressionPattern:
  263. *pattern_proto.mutable_expression_pattern()->mutable_expression() =
  264. ExpressionToProto(cast<ExpressionPattern>(pattern).expression());
  265. break;
  266. case PatternKind::AutoPattern:
  267. pattern_proto.mutable_auto_pattern();
  268. break;
  269. case PatternKind::VarPattern:
  270. *pattern_proto.mutable_var_pattern()->mutable_pattern() =
  271. PatternToProto(cast<VarPattern>(pattern).pattern());
  272. break;
  273. }
  274. return pattern_proto;
  275. }
  276. static auto BlockStatementToProto(const Block& block)
  277. -> Fuzzing::BlockStatement {
  278. Fuzzing::BlockStatement block_proto;
  279. for (Nonnull<const Statement*> statement : block.statements()) {
  280. *block_proto.add_statements() = StatementToProto(*statement);
  281. }
  282. return block_proto;
  283. }
  284. static auto StatementToProto(const Statement& statement) -> Fuzzing::Statement {
  285. Fuzzing::Statement statement_proto;
  286. switch (statement.kind()) {
  287. case StatementKind::ExpressionStatement:
  288. *statement_proto.mutable_expression_statement()->mutable_expression() =
  289. ExpressionToProto(cast<ExpressionStatement>(statement).expression());
  290. break;
  291. case StatementKind::Assign: {
  292. const auto& assign = cast<Assign>(statement);
  293. auto* assign_proto = statement_proto.mutable_assign();
  294. *assign_proto->mutable_lhs() = ExpressionToProto(assign.lhs());
  295. *assign_proto->mutable_rhs() = ExpressionToProto(assign.rhs());
  296. break;
  297. }
  298. case StatementKind::VariableDefinition: {
  299. const auto& def = cast<VariableDefinition>(statement);
  300. auto* def_proto = statement_proto.mutable_variable_definition();
  301. *def_proto->mutable_pattern() = PatternToProto(def.pattern());
  302. *def_proto->mutable_init() = ExpressionToProto(def.init());
  303. break;
  304. }
  305. case StatementKind::If: {
  306. const auto& if_stmt = cast<If>(statement);
  307. auto* if_proto = statement_proto.mutable_if_statement();
  308. *if_proto->mutable_condition() = ExpressionToProto(if_stmt.condition());
  309. *if_proto->mutable_then_block() =
  310. BlockStatementToProto(if_stmt.then_block());
  311. if (if_stmt.else_block().has_value()) {
  312. *if_proto->mutable_else_block() =
  313. BlockStatementToProto(**if_stmt.else_block());
  314. }
  315. break;
  316. }
  317. case StatementKind::Return: {
  318. const auto& ret = cast<Return>(statement);
  319. auto* ret_proto = statement_proto.mutable_return_statement();
  320. if (!ret.is_omitted_expression()) {
  321. *ret_proto->mutable_expression() = ExpressionToProto(ret.expression());
  322. } else {
  323. ret_proto->set_is_omitted_expression(true);
  324. }
  325. break;
  326. }
  327. case StatementKind::Block:
  328. *statement_proto.mutable_block() =
  329. BlockStatementToProto(cast<Block>(statement));
  330. break;
  331. case StatementKind::While: {
  332. const auto& while_stmt = cast<While>(statement);
  333. auto* while_proto = statement_proto.mutable_while_statement();
  334. *while_proto->mutable_condition() =
  335. ExpressionToProto(while_stmt.condition());
  336. *while_proto->mutable_body() = BlockStatementToProto(while_stmt.body());
  337. break;
  338. }
  339. case StatementKind::Match: {
  340. const auto& match = cast<Match>(statement);
  341. auto* match_proto = statement_proto.mutable_match();
  342. *match_proto->mutable_expression() =
  343. ExpressionToProto(match.expression());
  344. for (const Match::Clause& clause : match.clauses()) {
  345. auto* clause_proto = match_proto->add_clauses();
  346. const bool is_default_clause =
  347. clause.pattern().kind() == PatternKind::BindingPattern &&
  348. cast<BindingPattern>(clause.pattern()).name() == AnonymousName;
  349. if (is_default_clause) {
  350. clause_proto->set_is_default(true);
  351. } else {
  352. *clause_proto->mutable_pattern() = PatternToProto(clause.pattern());
  353. }
  354. *clause_proto->mutable_statement() =
  355. StatementToProto(clause.statement());
  356. }
  357. break;
  358. }
  359. case StatementKind::Continuation: {
  360. const auto& continuation = cast<Continuation>(statement);
  361. auto* continuation_proto = statement_proto.mutable_continuation();
  362. continuation_proto->set_name(continuation.name());
  363. *continuation_proto->mutable_body() =
  364. BlockStatementToProto(continuation.body());
  365. break;
  366. }
  367. case StatementKind::Run:
  368. *statement_proto.mutable_run()->mutable_argument() =
  369. ExpressionToProto(cast<Run>(statement).argument());
  370. break;
  371. case StatementKind::Await:
  372. // Initializes with the default value; there's nothing to set.
  373. statement_proto.mutable_await_statement();
  374. break;
  375. case StatementKind::Break:
  376. // Initializes with the default value; there's nothing to set.
  377. statement_proto.mutable_break_statement();
  378. break;
  379. case StatementKind::Continue:
  380. // Initializes with the default value; there's nothing to set.
  381. statement_proto.mutable_continue_statement();
  382. break;
  383. }
  384. return statement_proto;
  385. }
  386. static auto ReturnTermToProto(const ReturnTerm& return_term)
  387. -> Fuzzing::ReturnTerm {
  388. Fuzzing::ReturnTerm return_term_proto;
  389. if (return_term.is_omitted()) {
  390. return_term_proto.set_kind(Fuzzing::ReturnTerm::Omitted);
  391. } else if (return_term.is_auto()) {
  392. return_term_proto.set_kind(Fuzzing::ReturnTerm::Auto);
  393. } else {
  394. return_term_proto.set_kind(Fuzzing::ReturnTerm::Expression);
  395. *return_term_proto.mutable_type() =
  396. ExpressionToProto(**return_term.type_expression());
  397. }
  398. return return_term_proto;
  399. }
  400. static auto DeclarationToProto(const Declaration& declaration)
  401. -> Fuzzing::Declaration {
  402. Fuzzing::Declaration declaration_proto;
  403. switch (declaration.kind()) {
  404. case DeclarationKind::FunctionDeclaration: {
  405. const auto& function = cast<FunctionDeclaration>(declaration);
  406. auto* function_proto = declaration_proto.mutable_function();
  407. function_proto->set_name(function.name());
  408. for (Nonnull<const GenericBinding*> binding :
  409. function.deduced_parameters()) {
  410. *function_proto->add_deduced_parameters() =
  411. GenericBindingToProto(*binding);
  412. }
  413. if (function.is_method()) {
  414. *function_proto->mutable_me_pattern() =
  415. BindingPatternToProto(function.me_pattern());
  416. }
  417. *function_proto->mutable_param_pattern() =
  418. TuplePatternToProto(function.param_pattern());
  419. *function_proto->mutable_return_term() =
  420. ReturnTermToProto(function.return_term());
  421. if (function.body().has_value()) {
  422. *function_proto->mutable_body() =
  423. BlockStatementToProto(**function.body());
  424. }
  425. break;
  426. }
  427. case DeclarationKind::ClassDeclaration: {
  428. const auto& class_decl = cast<ClassDeclaration>(declaration);
  429. auto* class_proto = declaration_proto.mutable_class_declaration();
  430. class_proto->set_name(class_decl.name());
  431. if (class_decl.type_params().has_value()) {
  432. *class_proto->mutable_type_params() =
  433. TuplePatternToProto(**class_decl.type_params());
  434. }
  435. for (Nonnull<const Declaration*> member : class_decl.members()) {
  436. *class_proto->add_members() = DeclarationToProto(*member);
  437. }
  438. break;
  439. }
  440. case DeclarationKind::ChoiceDeclaration: {
  441. const auto& choice = cast<ChoiceDeclaration>(declaration);
  442. auto* choice_proto = declaration_proto.mutable_choice();
  443. choice_proto->set_name(choice.name());
  444. for (Nonnull<const AlternativeSignature*> alternative :
  445. choice.alternatives()) {
  446. auto* alternative_proto = choice_proto->add_alternatives();
  447. alternative_proto->set_name(alternative->name());
  448. *alternative_proto->mutable_signature() =
  449. ExpressionToProto(alternative->signature());
  450. }
  451. break;
  452. }
  453. case DeclarationKind::VariableDeclaration: {
  454. const auto& var = cast<VariableDeclaration>(declaration);
  455. auto* var_proto = declaration_proto.mutable_variable();
  456. *var_proto->mutable_binding() = BindingPatternToProto(var.binding());
  457. if (var.has_initializer()) {
  458. *var_proto->mutable_initializer() =
  459. ExpressionToProto(var.initializer());
  460. }
  461. break;
  462. }
  463. case DeclarationKind::InterfaceDeclaration: {
  464. const auto& interface = cast<InterfaceDeclaration>(declaration);
  465. auto* interface_proto = declaration_proto.mutable_interface();
  466. interface_proto->set_name(interface.name());
  467. for (const auto& member : interface.members()) {
  468. *interface_proto->add_members() = DeclarationToProto(*member);
  469. }
  470. *interface_proto->mutable_self() =
  471. GenericBindingToProto(*interface.self());
  472. break;
  473. }
  474. case DeclarationKind::ImplDeclaration: {
  475. const auto& impl = cast<ImplDeclaration>(declaration);
  476. auto* impl_proto = declaration_proto.mutable_impl();
  477. switch (impl.kind()) {
  478. case ImplKind::InternalImpl:
  479. impl_proto->set_kind(Fuzzing::ImplDeclaration::InternalImpl);
  480. break;
  481. case ImplKind::ExternalImpl:
  482. impl_proto->set_kind(Fuzzing::ImplDeclaration::ExternalImpl);
  483. break;
  484. }
  485. *impl_proto->mutable_impl_type() = ExpressionToProto(*impl.impl_type());
  486. *impl_proto->mutable_interface() = ExpressionToProto(impl.interface());
  487. for (const auto& member : impl.members()) {
  488. *impl_proto->add_members() = DeclarationToProto(*member);
  489. }
  490. break;
  491. }
  492. }
  493. return declaration_proto;
  494. }
  495. Fuzzing::CompilationUnit AstToProto(const AST& ast) {
  496. Fuzzing::CompilationUnit compilation_unit;
  497. *compilation_unit.mutable_package_statement() =
  498. LibraryNameToProto(ast.package);
  499. compilation_unit.set_is_api(ast.is_api);
  500. for (const Declaration* declaration : ast.declarations) {
  501. *compilation_unit.add_declarations() = DeclarationToProto(*declaration);
  502. }
  503. return compilation_unit;
  504. }
  505. } // namespace Carbon