ImmediateFunctions.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410
  1. /*
  2. * Copyright (c) 2021, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Formatter.h"
  7. #include "Shell.h"
  8. #include <LibRegex/Regex.h>
  9. #include <math.h>
  10. namespace Shell {
  11. ErrorOr<RefPtr<AST::Node>> Shell::immediate_length_impl(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments, bool across)
  12. {
  13. auto name = across ? "length_across" : "length";
  14. if (arguments.size() < 1 || arguments.size() > 2) {
  15. raise_error(ShellError::EvaluatedSyntaxError, DeprecatedString::formatted("Expected one or two arguments to `{}'", name), invoking_node.position());
  16. return nullptr;
  17. }
  18. enum {
  19. Infer,
  20. String,
  21. List,
  22. } mode { Infer };
  23. bool is_inferred = false;
  24. const AST::Node* expr_node;
  25. if (arguments.size() == 2) {
  26. // length string <expr>
  27. // length list <expr>
  28. auto& mode_arg = arguments.first();
  29. if (!mode_arg->is_bareword()) {
  30. raise_error(ShellError::EvaluatedSyntaxError, DeprecatedString::formatted("Expected a bareword (either 'string' or 'list') in the two-argument form of the `{}' immediate", name), mode_arg->position());
  31. return nullptr;
  32. }
  33. auto const& mode_name = static_cast<const AST::BarewordLiteral&>(*mode_arg).text();
  34. if (mode_name == "list") {
  35. mode = List;
  36. } else if (mode_name == "string") {
  37. mode = String;
  38. } else if (mode_name == "infer") {
  39. mode = Infer;
  40. } else {
  41. raise_error(ShellError::EvaluatedSyntaxError, DeprecatedString::formatted("Expected either 'string' or 'list' (and not {}) in the two-argument form of the `{}' immediate", mode_name, name), mode_arg->position());
  42. return nullptr;
  43. }
  44. expr_node = arguments[1];
  45. } else {
  46. expr_node = arguments[0];
  47. }
  48. if (mode == Infer) {
  49. is_inferred = true;
  50. if (expr_node->is_list())
  51. mode = List;
  52. else if (expr_node->is_simple_variable()) // "Look inside" variables
  53. mode = TRY(TRY(const_cast<AST::Node*>(expr_node)->run(this))->resolve_without_cast(this))->is_list_without_resolution() ? List : String;
  54. else if (is<AST::ImmediateExpression>(expr_node))
  55. mode = List;
  56. else
  57. mode = String;
  58. }
  59. auto value_with_number = [&](auto number) -> ErrorOr<NonnullRefPtr<AST::Node>> {
  60. return AST::make_ref_counted<AST::BarewordLiteral>(invoking_node.position(), TRY(String::number(number)));
  61. };
  62. auto do_across = [&](StringView mode_name, auto& values) -> ErrorOr<RefPtr<AST::Node>> {
  63. if (is_inferred)
  64. mode_name = "infer"sv;
  65. // Translate to a list of applications of `length <mode_name>`
  66. Vector<NonnullRefPtr<AST::Node>> resulting_nodes;
  67. resulting_nodes.ensure_capacity(values.size());
  68. for (auto& entry : values) {
  69. // ImmediateExpression(length <mode_name> <entry>)
  70. resulting_nodes.unchecked_append(AST::make_ref_counted<AST::ImmediateExpression>(
  71. expr_node->position(),
  72. AST::NameWithPosition { "length"_string, invoking_node.function_position() },
  73. Vector<NonnullRefPtr<AST::Node>> { Vector<NonnullRefPtr<AST::Node>> {
  74. static_cast<NonnullRefPtr<AST::Node>>(AST::make_ref_counted<AST::BarewordLiteral>(expr_node->position(), TRY(String::from_utf8(mode_name)))),
  75. AST::make_ref_counted<AST::SyntheticNode>(expr_node->position(), NonnullRefPtr<AST::Value>(entry)),
  76. } },
  77. expr_node->position()));
  78. }
  79. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(resulting_nodes));
  80. };
  81. switch (mode) {
  82. default:
  83. case Infer:
  84. VERIFY_NOT_REACHED();
  85. case List: {
  86. auto value = TRY(const_cast<AST::Node*>(expr_node)->run(this));
  87. if (!value)
  88. return value_with_number(0);
  89. value = TRY(value->resolve_without_cast(this));
  90. if (auto list = dynamic_cast<AST::ListValue*>(value.ptr())) {
  91. if (across)
  92. return do_across("list"sv, list->values());
  93. return value_with_number(list->values().size());
  94. }
  95. auto list = TRY(value->resolve_as_list(this));
  96. if (!across)
  97. return value_with_number(list.size());
  98. dbgln("List has {} entries", list.size());
  99. auto values = AST::make_ref_counted<AST::ListValue>(move(list));
  100. return do_across("list"sv, values->values());
  101. }
  102. case String: {
  103. // 'across' will only accept lists, and '!across' will only accept non-lists here.
  104. if (expr_node->is_list()) {
  105. if (!across) {
  106. raise_no_list_allowed:;
  107. Formatter formatter { *expr_node };
  108. if (is_inferred) {
  109. raise_error(ShellError::EvaluatedSyntaxError,
  110. DeprecatedString::formatted("Could not infer expression type, please explicitly use `{0} string' or `{0} list'", name),
  111. invoking_node.position());
  112. return nullptr;
  113. }
  114. auto source = formatter.format();
  115. raise_error(ShellError::EvaluatedSyntaxError,
  116. source.is_empty()
  117. ? "Invalid application of `length' to a list"
  118. : DeprecatedString::formatted("Invalid application of `length' to a list\nperhaps you meant `{1}length \"{0}\"{2}' or `{1}length_across {0}{2}'?", source, "\x1b[32m", "\x1b[0m"),
  119. expr_node->position());
  120. return nullptr;
  121. }
  122. }
  123. auto value = TRY(const_cast<AST::Node*>(expr_node)->run(this));
  124. if (!value)
  125. return value_with_number(0);
  126. value = TRY(value->resolve_without_cast(*this));
  127. if (auto list = dynamic_cast<AST::ListValue*>(value.ptr())) {
  128. if (!across)
  129. goto raise_no_list_allowed;
  130. return do_across("string"sv, list->values());
  131. }
  132. if (across && !value->is_list()) {
  133. Formatter formatter { *expr_node };
  134. auto source = formatter.format();
  135. raise_error(ShellError::EvaluatedSyntaxError,
  136. DeprecatedString::formatted("Invalid application of `length_across' to a non-list\nperhaps you meant `{1}length {0}{2}'?", source, "\x1b[32m", "\x1b[0m"),
  137. expr_node->position());
  138. return nullptr;
  139. }
  140. // Evaluate the nodes and substitute with the lengths.
  141. auto list = TRY(value->resolve_as_list(this));
  142. if (!expr_node->is_list()) {
  143. if (list.size() == 1) {
  144. if (across)
  145. goto raise_no_list_allowed;
  146. // This is the normal case, the expression is a normal non-list expression.
  147. return value_with_number(list.first().bytes_as_string_view().length());
  148. }
  149. // This can be hit by asking for the length of a command list (e.g. `(>/dev/null)`)
  150. // raise an error about misuse of command lists for now.
  151. // FIXME: What's the length of `(>/dev/null)` supposed to be?
  152. raise_error(ShellError::EvaluatedSyntaxError, "Length of meta value (or command list) requested, this is currently not supported.", expr_node->position());
  153. return nullptr;
  154. }
  155. auto values = AST::make_ref_counted<AST::ListValue>(move(list));
  156. return do_across("string"sv, values->values());
  157. }
  158. }
  159. }
  160. ErrorOr<RefPtr<AST::Node>> Shell::immediate_length(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  161. {
  162. return immediate_length_impl(invoking_node, arguments, false);
  163. }
  164. ErrorOr<RefPtr<AST::Node>> Shell::immediate_length_across(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  165. {
  166. return immediate_length_impl(invoking_node, arguments, true);
  167. }
  168. ErrorOr<RefPtr<AST::Node>> Shell::immediate_regex_replace(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  169. {
  170. if (arguments.size() != 3) {
  171. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 3 arguments to regex_replace", invoking_node.position());
  172. return nullptr;
  173. }
  174. auto pattern = TRY(const_cast<AST::Node&>(*arguments[0]).run(this));
  175. auto replacement = TRY(const_cast<AST::Node&>(*arguments[1]).run(this));
  176. auto value = TRY(TRY(const_cast<AST::Node&>(*arguments[2]).run(this))->resolve_without_cast(this));
  177. if (!pattern->is_string()) {
  178. raise_error(ShellError::EvaluatedSyntaxError, "Expected the regex_replace pattern to be a string", arguments[0]->position());
  179. return nullptr;
  180. }
  181. if (!replacement->is_string()) {
  182. raise_error(ShellError::EvaluatedSyntaxError, "Expected the regex_replace replacement string to be a string", arguments[1]->position());
  183. return nullptr;
  184. }
  185. if (!value->is_string()) {
  186. raise_error(ShellError::EvaluatedSyntaxError, "Expected the regex_replace target value to be a string", arguments[2]->position());
  187. return nullptr;
  188. }
  189. Regex<PosixExtendedParser> re { TRY(pattern->resolve_as_list(this)).first().to_deprecated_string() };
  190. auto result = re.replace(
  191. TRY(value->resolve_as_list(this))[0],
  192. TRY(replacement->resolve_as_list(this))[0],
  193. PosixFlags::Global | PosixFlags::Multiline | PosixFlags::Unicode);
  194. return AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), TRY(String::from_deprecated_string(result)), AST::StringLiteral::EnclosureType::None);
  195. }
  196. ErrorOr<RefPtr<AST::Node>> Shell::immediate_remove_suffix(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  197. {
  198. if (arguments.size() != 2) {
  199. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to remove_suffix", invoking_node.position());
  200. return nullptr;
  201. }
  202. auto suffix = TRY(const_cast<AST::Node&>(*arguments[0]).run(this));
  203. auto value = TRY(TRY(const_cast<AST::Node&>(*arguments[1]).run(this))->resolve_without_cast(this));
  204. if (!suffix->is_string()) {
  205. raise_error(ShellError::EvaluatedSyntaxError, "Expected the remove_suffix suffix string to be a string", arguments[0]->position());
  206. return nullptr;
  207. }
  208. auto suffix_str = TRY(suffix->resolve_as_list(this))[0];
  209. auto values = TRY(value->resolve_as_list(this));
  210. Vector<NonnullRefPtr<AST::Node>> nodes;
  211. for (auto& value_str : values) {
  212. String removed = TRY(String::from_utf8(value_str));
  213. if (value_str.bytes_as_string_view().ends_with(suffix_str))
  214. removed = TRY(removed.substring_from_byte_offset(0, value_str.bytes_as_string_view().length() - suffix_str.bytes_as_string_view().length()));
  215. nodes.append(AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), move(removed), AST::StringLiteral::EnclosureType::None));
  216. }
  217. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(nodes));
  218. }
  219. ErrorOr<RefPtr<AST::Node>> Shell::immediate_remove_prefix(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  220. {
  221. if (arguments.size() != 2) {
  222. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to remove_prefix", invoking_node.position());
  223. return nullptr;
  224. }
  225. auto prefix = TRY(const_cast<AST::Node&>(*arguments[0]).run(this));
  226. auto value = TRY(TRY(const_cast<AST::Node&>(*arguments[1]).run(this))->resolve_without_cast(this));
  227. if (!prefix->is_string()) {
  228. raise_error(ShellError::EvaluatedSyntaxError, "Expected the remove_prefix prefix string to be a string", arguments[0]->position());
  229. return nullptr;
  230. }
  231. auto prefix_str = TRY(prefix->resolve_as_list(this))[0];
  232. auto values = TRY(value->resolve_as_list(this));
  233. Vector<NonnullRefPtr<AST::Node>> nodes;
  234. for (auto& value_str : values) {
  235. String removed = TRY(String::from_utf8(value_str));
  236. if (value_str.bytes_as_string_view().starts_with(prefix_str))
  237. removed = TRY(removed.substring_from_byte_offset(prefix_str.bytes_as_string_view().length()));
  238. nodes.append(AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), move(removed), AST::StringLiteral::EnclosureType::None));
  239. }
  240. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(nodes));
  241. }
  242. ErrorOr<RefPtr<AST::Node>> Shell::immediate_split(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  243. {
  244. if (arguments.size() != 2) {
  245. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to split", invoking_node.position());
  246. return nullptr;
  247. }
  248. auto delimiter = TRY(const_cast<AST::Node&>(*arguments[0]).run(this));
  249. auto value = TRY(TRY(const_cast<AST::Node&>(*arguments[1]).run(this))->resolve_without_cast(this));
  250. if (!delimiter->is_string()) {
  251. raise_error(ShellError::EvaluatedSyntaxError, "Expected the split delimiter string to be a string", arguments[0]->position());
  252. return nullptr;
  253. }
  254. auto delimiter_str = TRY(delimiter->resolve_as_list(this))[0];
  255. auto transform = [&](auto const& values) {
  256. // Translate to a list of applications of `split <delimiter>`
  257. Vector<NonnullRefPtr<AST::Node>> resulting_nodes;
  258. resulting_nodes.ensure_capacity(values.size());
  259. for (auto& entry : values) {
  260. // ImmediateExpression(split <delimiter> <entry>)
  261. resulting_nodes.unchecked_append(AST::make_ref_counted<AST::ImmediateExpression>(
  262. arguments[1]->position(),
  263. invoking_node.function(),
  264. Vector<NonnullRefPtr<AST::Node>> { Vector<NonnullRefPtr<AST::Node>> {
  265. arguments[0],
  266. AST::make_ref_counted<AST::SyntheticNode>(arguments[1]->position(), NonnullRefPtr<AST::Value>(entry)),
  267. } },
  268. arguments[1]->position()));
  269. }
  270. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(resulting_nodes));
  271. };
  272. if (auto list = dynamic_cast<AST::ListValue*>(value.ptr())) {
  273. return transform(list->values());
  274. }
  275. // Otherwise, just resolve to a list and transform that.
  276. auto list = TRY(value->resolve_as_list(this));
  277. if (!value->is_list()) {
  278. if (list.is_empty())
  279. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), Vector<NonnullRefPtr<AST::Node>> {});
  280. auto& value = list.first();
  281. Vector<String> split_strings;
  282. if (delimiter_str.is_empty()) {
  283. StringBuilder builder;
  284. for (auto code_point : Utf8View { value }) {
  285. builder.append_code_point(code_point);
  286. split_strings.append(TRY(builder.to_string()));
  287. builder.clear();
  288. }
  289. } else {
  290. auto split = StringView { value }.split_view(delimiter_str, options.inline_exec_keep_empty_segments ? SplitBehavior::KeepEmpty : SplitBehavior::Nothing);
  291. split_strings.ensure_capacity(split.size());
  292. for (auto& entry : split)
  293. split_strings.append(TRY(String::from_utf8(entry)));
  294. }
  295. return AST::make_ref_counted<AST::SyntheticNode>(invoking_node.position(), AST::make_ref_counted<AST::ListValue>(move(split_strings)));
  296. }
  297. return transform(AST::make_ref_counted<AST::ListValue>(list)->values());
  298. }
  299. ErrorOr<RefPtr<AST::Node>> Shell::immediate_concat_lists(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  300. {
  301. Vector<NonnullRefPtr<AST::Node>> result;
  302. for (auto& argument : arguments) {
  303. if (auto* list = dynamic_cast<AST::ListConcatenate const*>(argument.ptr())) {
  304. result.extend(list->list());
  305. } else {
  306. auto list_of_values = TRY(TRY(const_cast<AST::Node&>(*argument).run(this))->resolve_without_cast(this));
  307. if (auto* list = dynamic_cast<AST::ListValue*>(list_of_values.ptr())) {
  308. for (auto& entry : static_cast<Vector<NonnullRefPtr<AST::Value>>&>(list->values()))
  309. result.append(AST::make_ref_counted<AST::SyntheticNode>(argument->position(), entry));
  310. } else {
  311. auto values = TRY(list_of_values->resolve_as_list(this));
  312. for (auto& entry : values)
  313. result.append(AST::make_ref_counted<AST::StringLiteral>(argument->position(), entry, AST::StringLiteral::EnclosureType::None));
  314. }
  315. }
  316. }
  317. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(result));
  318. }
  319. ErrorOr<RefPtr<AST::Node>> Shell::immediate_filter_glob(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  320. {
  321. // filter_glob string list
  322. if (arguments.size() != 2) {
  323. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly two arguments to filter_glob (<glob> <list>)", invoking_node.position());
  324. return nullptr;
  325. }
  326. auto glob_list = TRY(TRY(const_cast<AST::Node&>(*arguments[0]).run(*this))->resolve_as_list(*this));
  327. if (glob_list.size() != 1) {
  328. raise_error(ShellError::EvaluatedSyntaxError, "Expected the <glob> argument to filter_glob to be a single string", arguments[0]->position());
  329. return nullptr;
  330. }
  331. auto& glob = glob_list.first();
  332. auto& list_node = arguments[1];
  333. Vector<NonnullRefPtr<AST::Node>> result;
  334. TRY(const_cast<AST::Node&>(*list_node).for_each_entry(*this, [&](NonnullRefPtr<AST::Value> entry) -> ErrorOr<IterationDecision> {
  335. auto value = TRY(entry->resolve_as_list(*this));
  336. if (value.size() == 0)
  337. return IterationDecision::Continue;
  338. if (value.size() == 1) {
  339. if (!value.first().bytes_as_string_view().matches(glob))
  340. return IterationDecision::Continue;
  341. result.append(AST::make_ref_counted<AST::StringLiteral>(arguments[1]->position(), value.first(), AST::StringLiteral::EnclosureType::None));
  342. return IterationDecision::Continue;
  343. }
  344. for (auto& entry : value) {
  345. if (entry.bytes_as_string_view().matches(glob)) {
  346. Vector<NonnullRefPtr<AST::Node>> nodes;
  347. for (auto& string : value)
  348. nodes.append(AST::make_ref_counted<AST::StringLiteral>(arguments[1]->position(), string, AST::StringLiteral::EnclosureType::None));
  349. result.append(AST::make_ref_counted<AST::ListConcatenate>(arguments[1]->position(), move(nodes)));
  350. return IterationDecision::Continue;
  351. }
  352. }
  353. return IterationDecision::Continue;
  354. }));
  355. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(result));
  356. }
  357. ErrorOr<RefPtr<AST::Node>> Shell::immediate_join(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  358. {
  359. if (arguments.size() != 2) {
  360. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to join", invoking_node.position());
  361. return nullptr;
  362. }
  363. auto delimiter = TRY(const_cast<AST::Node&>(*arguments[0]).run(this));
  364. if (!delimiter->is_string()) {
  365. raise_error(ShellError::EvaluatedSyntaxError, "Expected the join delimiter string to be a string", arguments[0]->position());
  366. return nullptr;
  367. }
  368. auto value = TRY(TRY(const_cast<AST::Node&>(*arguments[1]).run(this))->resolve_without_cast(this));
  369. if (!value->is_list()) {
  370. raise_error(ShellError::EvaluatedSyntaxError, "Expected the joined list to be a list", arguments[1]->position());
  371. return nullptr;
  372. }
  373. auto delimiter_str = TRY(delimiter->resolve_as_list(this))[0];
  374. StringBuilder builder;
  375. builder.join(delimiter_str, TRY(value->resolve_as_list(*this)));
  376. return AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), TRY(builder.to_string()), AST::StringLiteral::EnclosureType::None);
  377. }
  378. ErrorOr<RefPtr<AST::Node>> Shell::immediate_value_or_default(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  379. {
  380. if (arguments.size() != 2) {
  381. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to value_or_default", invoking_node.position());
  382. return nullptr;
  383. }
  384. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  385. if (!TRY(local_variable_or(name, ""sv)).is_empty())
  386. return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  387. return arguments.last();
  388. }
  389. ErrorOr<RefPtr<AST::Node>> Shell::immediate_assign_default(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  390. {
  391. if (arguments.size() != 2) {
  392. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to assign_default", invoking_node.position());
  393. return nullptr;
  394. }
  395. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  396. if (!TRY(local_variable_or(name, ""sv)).is_empty())
  397. return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  398. auto value = TRY(TRY(const_cast<AST::Node&>(*arguments.last()).run(*this))->resolve_without_cast(*this));
  399. set_local_variable(name.to_deprecated_string(), value);
  400. return make_ref_counted<AST::SyntheticNode>(invoking_node.position(), value);
  401. }
  402. ErrorOr<RefPtr<AST::Node>> Shell::immediate_error_if_empty(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  403. {
  404. if (arguments.size() != 2) {
  405. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to error_if_empty", invoking_node.position());
  406. return nullptr;
  407. }
  408. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  409. if (!TRY(local_variable_or(name, ""sv)).is_empty())
  410. return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  411. auto error_value = TRY(TRY(const_cast<AST::Node&>(*arguments.last()).run(*this))->resolve_as_string(*this));
  412. if (error_value.is_empty())
  413. error_value = TRY(String::formatted("Expected {} to be non-empty", name));
  414. raise_error(ShellError::EvaluatedSyntaxError, error_value.bytes_as_string_view(), invoking_node.position());
  415. return nullptr;
  416. }
  417. ErrorOr<RefPtr<AST::Node>> Shell::immediate_null_or_alternative(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  418. {
  419. if (arguments.size() != 2) {
  420. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to null_or_alternative", invoking_node.position());
  421. return nullptr;
  422. }
  423. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  424. auto frame = find_frame_containing_local_variable(name);
  425. if (!frame)
  426. return make_ref_counted<AST::StringLiteral>(invoking_node.position(), ""_string, AST::StringLiteral::EnclosureType::None);
  427. auto value = frame->local_variables.get(name.bytes_as_string_view()).value();
  428. if ((value->is_string() && TRY(value->resolve_as_string(*this)).is_empty()) || (value->is_list() && TRY(value->resolve_as_list(*this)).is_empty()))
  429. return make_ref_counted<AST::SyntheticNode>(invoking_node.position(), *value);
  430. return arguments.last();
  431. }
  432. ErrorOr<RefPtr<AST::Node>> Shell::immediate_defined_value_or_default(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  433. {
  434. if (arguments.size() != 2) {
  435. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to defined_value_or_default", invoking_node.position());
  436. return nullptr;
  437. }
  438. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  439. if (!find_frame_containing_local_variable(name))
  440. return arguments.last();
  441. return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  442. }
  443. ErrorOr<RefPtr<AST::Node>> Shell::immediate_assign_defined_default(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  444. {
  445. if (arguments.size() != 2) {
  446. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to assign_defined_default", invoking_node.position());
  447. return nullptr;
  448. }
  449. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  450. if (find_frame_containing_local_variable(name))
  451. return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  452. auto value = TRY(TRY(const_cast<AST::Node&>(*arguments.last()).run(*this))->resolve_without_cast(*this));
  453. set_local_variable(name.to_deprecated_string(), value);
  454. return make_ref_counted<AST::SyntheticNode>(invoking_node.position(), value);
  455. }
  456. ErrorOr<RefPtr<AST::Node>> Shell::immediate_error_if_unset(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  457. {
  458. if (arguments.size() != 2) {
  459. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to error_if_unset", invoking_node.position());
  460. return nullptr;
  461. }
  462. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  463. if (find_frame_containing_local_variable(name))
  464. return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  465. auto error_value = TRY(TRY(const_cast<AST::Node&>(*arguments.last()).run(*this))->resolve_as_string(*this));
  466. if (error_value.is_empty())
  467. error_value = TRY(String::formatted("Expected {} to be set", name));
  468. raise_error(ShellError::EvaluatedSyntaxError, error_value.bytes_as_string_view(), invoking_node.position());
  469. return nullptr;
  470. }
  471. ErrorOr<RefPtr<AST::Node>> Shell::immediate_null_if_unset_or_alternative(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  472. {
  473. if (arguments.size() != 2) {
  474. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 2 arguments to null_if_unset_or_alternative", invoking_node.position());
  475. return nullptr;
  476. }
  477. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  478. if (!find_frame_containing_local_variable(name))
  479. return arguments.last();
  480. return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  481. }
  482. ErrorOr<RefPtr<AST::Node>> Shell::immediate_reexpand(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  483. {
  484. if (arguments.size() != 1) {
  485. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 1 argument to reexpand", invoking_node.position());
  486. return nullptr;
  487. }
  488. auto values = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_list(*this));
  489. auto result = Vector<NonnullRefPtr<AST::Node>> {};
  490. for (auto& value : values) {
  491. if (auto node = parse(value, m_is_interactive, false))
  492. result.append(node.release_nonnull());
  493. }
  494. if (values.size() == 1)
  495. return result.take_first();
  496. return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(result));
  497. }
  498. ErrorOr<RefPtr<AST::Node>> Shell::immediate_length_of_variable(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  499. {
  500. if (arguments.size() != 1) {
  501. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 1 argument to length_of_variable", invoking_node.position());
  502. return nullptr;
  503. }
  504. auto name = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_string(*this));
  505. auto variable = make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name);
  506. return immediate_length_impl(
  507. invoking_node,
  508. { move(variable) },
  509. false);
  510. }
  511. namespace Arithmetic {
  512. struct BinaryOperationNode;
  513. struct UnaryOperationNode;
  514. struct TernaryOperationNode;
  515. struct ErrorNode;
  516. struct Node {
  517. Variant<String, i64, NonnullOwnPtr<BinaryOperationNode>, NonnullOwnPtr<UnaryOperationNode>, NonnullOwnPtr<TernaryOperationNode>, NonnullOwnPtr<ErrorNode>> value;
  518. };
  519. struct ErrorNode {
  520. String error;
  521. };
  522. enum class Operator {
  523. Add, // +
  524. Subtract, // -
  525. Multiply, // *
  526. Quotient, // /
  527. Remainder, // %
  528. Power, // **
  529. Equal, // ==
  530. GreaterThan, // >
  531. LessThan, // <
  532. NotEqual, // !=
  533. GreaterThanOrEqual, // >=
  534. LessThanOrEqual, // <=
  535. BitwiseAnd, // &
  536. BitwiseOr, // |
  537. BitwiseXor, // ^
  538. ShiftLeft, // <<
  539. ShiftRight, // >>
  540. ArithmeticAnd, // &&
  541. ArithmeticOr, // ||
  542. Comma, // ,
  543. Negate, // !
  544. BitwiseNegate, // ~
  545. TernaryQuestion, // ?
  546. TernaryColon, // :
  547. Assignment, // =
  548. PlusAssignment, // +=
  549. MinusAssignment, // -=
  550. MultiplyAssignment, // *=
  551. DivideAssignment, // /=
  552. ModuloAssignment, // %=
  553. AndAssignment, // &=
  554. OrAssignment, // |=
  555. XorAssignment, // ^=
  556. LeftShiftAssignment, // <<=
  557. RightShiftAssignment, // >>=
  558. OpenParen, // (
  559. CloseParen, // )
  560. };
  561. static Operator assignment_operation_of(Operator op)
  562. {
  563. switch (op) {
  564. case Operator::PlusAssignment:
  565. return Operator::Add;
  566. case Operator::MinusAssignment:
  567. return Operator::Subtract;
  568. case Operator::MultiplyAssignment:
  569. return Operator::Multiply;
  570. case Operator::DivideAssignment:
  571. return Operator::Quotient;
  572. case Operator::ModuloAssignment:
  573. return Operator::Remainder;
  574. case Operator::AndAssignment:
  575. return Operator::BitwiseAnd;
  576. case Operator::OrAssignment:
  577. return Operator::BitwiseOr;
  578. case Operator::XorAssignment:
  579. return Operator::BitwiseXor;
  580. case Operator::LeftShiftAssignment:
  581. return Operator::ShiftLeft;
  582. case Operator::RightShiftAssignment:
  583. return Operator::ShiftRight;
  584. default:
  585. VERIFY_NOT_REACHED();
  586. }
  587. }
  588. static bool is_assignment_operator(Operator op)
  589. {
  590. switch (op) {
  591. case Operator::Assignment:
  592. case Operator::PlusAssignment:
  593. case Operator::MinusAssignment:
  594. case Operator::MultiplyAssignment:
  595. case Operator::DivideAssignment:
  596. case Operator::ModuloAssignment:
  597. case Operator::AndAssignment:
  598. case Operator::OrAssignment:
  599. case Operator::XorAssignment:
  600. case Operator::LeftShiftAssignment:
  601. case Operator::RightShiftAssignment:
  602. return true;
  603. default:
  604. return false;
  605. }
  606. }
  607. using Token = Variant<String, i64, Operator>;
  608. struct BinaryOperationNode {
  609. BinaryOperationNode(Operator op, Node lhs, Node rhs)
  610. : op(op)
  611. , lhs(move(lhs))
  612. , rhs(move(rhs))
  613. {
  614. }
  615. Operator op;
  616. Node lhs;
  617. Node rhs;
  618. };
  619. struct UnaryOperationNode {
  620. UnaryOperationNode(Operator op, Node rhs)
  621. : op(op)
  622. , rhs(move(rhs))
  623. {
  624. }
  625. Operator op;
  626. Node rhs;
  627. };
  628. struct TernaryOperationNode {
  629. TernaryOperationNode(Node condition, Node true_value, Node false_value)
  630. : condition(move(condition))
  631. , true_value(move(true_value))
  632. , false_value(move(false_value))
  633. {
  634. }
  635. Node condition;
  636. Node true_value;
  637. Node false_value;
  638. };
  639. static ErrorOr<Node> parse_expression(Span<Token>);
  640. static ErrorOr<Node> parse_assignment_expression(Span<Token>&);
  641. static ErrorOr<Node> parse_comma_expression(Span<Token>&);
  642. static ErrorOr<Node> parse_ternary_expression(Span<Token>&);
  643. static ErrorOr<Node> parse_logical_or_expression(Span<Token>&);
  644. static ErrorOr<Node> parse_logical_and_expression(Span<Token>&);
  645. static ErrorOr<Node> parse_bitwise_or_expression(Span<Token>&);
  646. static ErrorOr<Node> parse_bitwise_xor_expression(Span<Token>&);
  647. static ErrorOr<Node> parse_bitwise_and_expression(Span<Token>&);
  648. static ErrorOr<Node> parse_equality_expression(Span<Token>&);
  649. static ErrorOr<Node> parse_comparison_expression(Span<Token>&);
  650. static ErrorOr<Node> parse_shift_expression(Span<Token>&);
  651. static ErrorOr<Node> parse_additive_expression(Span<Token>&);
  652. static ErrorOr<Node> parse_multiplicative_expression(Span<Token>&);
  653. static ErrorOr<Node> parse_exponential_expression(Span<Token>&);
  654. static ErrorOr<Node> parse_unary_expression(Span<Token>&);
  655. static ErrorOr<Node> parse_primary_expression(Span<Token>&);
  656. template<size_t N>
  657. static ErrorOr<Node> parse_binary_expression_using_operators(Span<Token>&, Array<Operator, N>, Function<ErrorOr<Node>(Span<Token>&)> const& parse_rhs);
  658. static ErrorOr<Node> parse_binary_expression_using_operator(Span<Token>& tokens, Operator op, Function<ErrorOr<Node>(Span<Token>&)> const& parse_rhs)
  659. {
  660. return parse_binary_expression_using_operators(tokens, Array { op }, parse_rhs);
  661. }
  662. static bool next_token_is_operator(Span<Token>& tokens, Operator op)
  663. {
  664. if (tokens.is_empty())
  665. return false;
  666. return tokens.first().has<Operator>() && tokens.first().get<Operator>() == op;
  667. }
  668. ErrorOr<Node> parse_expression(Span<Token> tokens)
  669. {
  670. return parse_comma_expression(tokens);
  671. }
  672. ErrorOr<Node> parse_comma_expression(Span<Token>& tokens)
  673. {
  674. return parse_binary_expression_using_operator(tokens, Operator::Comma, &parse_assignment_expression);
  675. }
  676. ErrorOr<Node> parse_assignment_expression(Span<Token>& tokens)
  677. {
  678. auto lhs = TRY(parse_ternary_expression(tokens));
  679. if (tokens.is_empty())
  680. return lhs;
  681. auto is_assignment_operator = [](Operator op) {
  682. return op == Operator::Assignment
  683. || op == Operator::PlusAssignment
  684. || op == Operator::MinusAssignment
  685. || op == Operator::MultiplyAssignment
  686. || op == Operator::DivideAssignment
  687. || op == Operator::ModuloAssignment
  688. || op == Operator::AndAssignment
  689. || op == Operator::OrAssignment
  690. || op == Operator::XorAssignment
  691. || op == Operator::LeftShiftAssignment
  692. || op == Operator::RightShiftAssignment;
  693. };
  694. auto& token = tokens.first();
  695. if (auto op = token.get_pointer<Operator>(); op && is_assignment_operator(*op)) {
  696. if (!lhs.value.has<String>()) {
  697. return Node {
  698. make<ErrorNode>("Left-hand side of assignment must be a variable"_string)
  699. };
  700. }
  701. tokens = tokens.slice(1);
  702. auto rhs = TRY(parse_assignment_expression(tokens));
  703. return Node {
  704. make<BinaryOperationNode>(*op, move(lhs), move(rhs))
  705. };
  706. }
  707. return lhs;
  708. }
  709. ErrorOr<Node> parse_ternary_expression(Span<Token>& tokens)
  710. {
  711. auto condition = TRY(parse_logical_or_expression(tokens));
  712. if (!next_token_is_operator(tokens, Operator::TernaryQuestion))
  713. return condition;
  714. tokens = tokens.slice(1);
  715. auto true_value = TRY(parse_comma_expression(tokens));
  716. if (!next_token_is_operator(tokens, Operator::TernaryColon)) {
  717. return Node {
  718. make<ErrorNode>("Expected ':' after true value in ternary expression"_string)
  719. };
  720. }
  721. tokens = tokens.slice(1);
  722. auto false_value = TRY(parse_ternary_expression(tokens));
  723. return Node {
  724. make<TernaryOperationNode>(move(condition), move(true_value), move(false_value))
  725. };
  726. }
  727. ErrorOr<Node> parse_logical_or_expression(Span<Token>& tokens)
  728. {
  729. return parse_binary_expression_using_operator(tokens, Operator::ArithmeticOr, &parse_logical_and_expression);
  730. }
  731. ErrorOr<Node> parse_logical_and_expression(Span<Token>& tokens)
  732. {
  733. return parse_binary_expression_using_operator(tokens, Operator::ArithmeticAnd, &parse_bitwise_or_expression);
  734. }
  735. ErrorOr<Node> parse_bitwise_or_expression(Span<Token>& tokens)
  736. {
  737. return parse_binary_expression_using_operator(tokens, Operator::BitwiseOr, &parse_bitwise_xor_expression);
  738. }
  739. ErrorOr<Node> parse_bitwise_xor_expression(Span<Token>& tokens)
  740. {
  741. return parse_binary_expression_using_operator(tokens, Operator::BitwiseXor, &parse_bitwise_and_expression);
  742. }
  743. ErrorOr<Node> parse_bitwise_and_expression(Span<Token>& tokens)
  744. {
  745. return parse_binary_expression_using_operator(tokens, Operator::BitwiseAnd, &parse_equality_expression);
  746. }
  747. ErrorOr<Node> parse_equality_expression(Span<Token>& tokens)
  748. {
  749. return parse_binary_expression_using_operators(tokens, Array { Operator::Equal, Operator::NotEqual }, &parse_comparison_expression);
  750. }
  751. ErrorOr<Node> parse_comparison_expression(Span<Token>& tokens)
  752. {
  753. return parse_binary_expression_using_operators(tokens, Array { Operator::LessThan, Operator::GreaterThan, Operator::LessThanOrEqual, Operator::GreaterThanOrEqual }, &parse_shift_expression);
  754. }
  755. ErrorOr<Node> parse_shift_expression(Span<Token>& tokens)
  756. {
  757. return parse_binary_expression_using_operators(tokens, Array { Operator::ShiftLeft, Operator::ShiftRight }, &parse_additive_expression);
  758. }
  759. ErrorOr<Node> parse_additive_expression(Span<Token>& tokens)
  760. {
  761. return parse_binary_expression_using_operators(tokens, Array { Operator::Add, Operator::Subtract }, &parse_multiplicative_expression);
  762. }
  763. ErrorOr<Node> parse_multiplicative_expression(Span<Token>& tokens)
  764. {
  765. return parse_binary_expression_using_operators(tokens, Array { Operator::Multiply, Operator::Quotient, Operator::Remainder }, &parse_exponential_expression);
  766. }
  767. ErrorOr<Node> parse_exponential_expression(Span<Token>& tokens)
  768. {
  769. auto lhs = TRY(parse_unary_expression(tokens));
  770. if (!next_token_is_operator(tokens, Operator::Power))
  771. return lhs;
  772. tokens = tokens.slice(1);
  773. auto rhs = TRY(parse_exponential_expression(tokens));
  774. return Node {
  775. make<BinaryOperationNode>(Operator::Power, move(lhs), move(rhs))
  776. };
  777. }
  778. ErrorOr<Node> parse_unary_expression(Span<Token>& tokens)
  779. {
  780. if (tokens.is_empty()) {
  781. return Node {
  782. make<ErrorNode>("Expected expression, got end of input"_string)
  783. };
  784. }
  785. auto& token = tokens.first();
  786. if (auto op = token.get_pointer<Operator>()) {
  787. if (*op == Operator::Add || *op == Operator::Subtract || *op == Operator::Negate || *op == Operator::BitwiseNegate) {
  788. tokens = tokens.slice(1);
  789. auto rhs = TRY(parse_unary_expression(tokens));
  790. return Node {
  791. make<UnaryOperationNode>(*op, move(rhs))
  792. };
  793. }
  794. }
  795. return parse_primary_expression(tokens);
  796. }
  797. ErrorOr<Node> parse_primary_expression(Span<Token>& tokens)
  798. {
  799. if (tokens.is_empty())
  800. return Node { make<ErrorNode>("Expected expression, got end of input"_string) };
  801. auto& token = tokens.first();
  802. return token.visit(
  803. [&](String const& var) -> ErrorOr<Node> {
  804. tokens = tokens.slice(1);
  805. return Node { var };
  806. },
  807. [&](i64 value) -> ErrorOr<Node> {
  808. tokens = tokens.slice(1);
  809. return Node { value };
  810. },
  811. [&](Operator op) -> ErrorOr<Node> {
  812. switch (op) {
  813. case Operator::OpenParen: {
  814. tokens = tokens.slice(1);
  815. auto value = TRY(parse_expression(tokens));
  816. if (!next_token_is_operator(tokens, Operator::CloseParen)) {
  817. return Node {
  818. make<ErrorNode>("Expected ')' after expression in parentheses"_string)
  819. };
  820. }
  821. tokens = tokens.slice(1);
  822. return value;
  823. }
  824. default:
  825. return Node {
  826. make<ErrorNode>("Expected expression, got operator"_string)
  827. };
  828. }
  829. });
  830. }
  831. template<size_t N>
  832. ErrorOr<Node> parse_binary_expression_using_operators(Span<Token>& tokens, Array<Operator, N> operators, Function<ErrorOr<Node>(Span<Token>&)> const& parse_rhs)
  833. {
  834. auto lhs = TRY(parse_rhs(tokens));
  835. for (;;) {
  836. Optional<Operator> op;
  837. for (auto candidate : operators) {
  838. if (next_token_is_operator(tokens, candidate)) {
  839. op = candidate;
  840. break;
  841. }
  842. }
  843. if (!op.has_value())
  844. return lhs;
  845. tokens = tokens.slice(1);
  846. auto rhs = TRY(parse_rhs(tokens));
  847. lhs = Node {
  848. make<BinaryOperationNode>(*op, move(lhs), move(rhs))
  849. };
  850. }
  851. }
  852. }
  853. ErrorOr<RefPtr<AST::Node>> Shell::immediate_math(AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  854. {
  855. if (arguments.size() != 1) {
  856. raise_error(ShellError::EvaluatedSyntaxError, "Expected exactly 1 argument to math", invoking_node.position());
  857. return nullptr;
  858. }
  859. auto expression_parts = TRY(TRY(const_cast<AST::Node&>(*arguments.first()).run(*this))->resolve_as_list(*this));
  860. auto expression = TRY(String::join(' ', expression_parts));
  861. using Arithmetic::Operator;
  862. using Arithmetic::Token;
  863. Vector<Token> tokens;
  864. auto view = expression.code_points();
  865. Optional<size_t> integer_or_word_start_offset;
  866. for (auto it = view.begin(); it != view.end(); ++it) {
  867. auto code_point = *it;
  868. if (is_ascii_alphanumeric(code_point) || code_point == U'_') {
  869. if (!integer_or_word_start_offset.has_value())
  870. integer_or_word_start_offset = view.byte_offset_of(it);
  871. continue;
  872. }
  873. if (integer_or_word_start_offset.has_value()) {
  874. auto integer_or_word = view.substring_view(
  875. *integer_or_word_start_offset,
  876. view.byte_offset_of(it) - *integer_or_word_start_offset);
  877. if (all_of(integer_or_word, is_ascii_digit))
  878. tokens.append(*integer_or_word.as_string().to_int());
  879. else
  880. tokens.append(TRY(expression.substring_from_byte_offset_with_shared_superstring(*integer_or_word_start_offset, integer_or_word.length())));
  881. integer_or_word_start_offset.clear();
  882. }
  883. switch (code_point) {
  884. case U'!':
  885. if (it.peek(1) == U'=') {
  886. ++it;
  887. tokens.append(Operator::NotEqual);
  888. } else {
  889. tokens.append(Operator::Negate);
  890. }
  891. break;
  892. case U'=':
  893. if (it.peek(1) == U'=') {
  894. ++it;
  895. tokens.append(Operator::Equal);
  896. } else {
  897. tokens.append(Operator::Assignment);
  898. }
  899. break;
  900. case U'~':
  901. tokens.append(Operator::BitwiseNegate);
  902. break;
  903. case U'(':
  904. tokens.append(Operator::OpenParen);
  905. break;
  906. case U')':
  907. tokens.append(Operator::CloseParen);
  908. break;
  909. case U'&':
  910. switch (it.peek(1).value_or(0)) {
  911. case U'&':
  912. ++it;
  913. tokens.append(Operator::ArithmeticAnd);
  914. break;
  915. case U'=':
  916. ++it;
  917. tokens.append(Operator::AndAssignment);
  918. break;
  919. default:
  920. tokens.append(Operator::BitwiseAnd);
  921. break;
  922. }
  923. break;
  924. case U'|':
  925. switch (it.peek(1).value_or(0)) {
  926. case U'|':
  927. ++it;
  928. tokens.append(Operator::ArithmeticOr);
  929. break;
  930. case U'=':
  931. ++it;
  932. tokens.append(Operator::OrAssignment);
  933. break;
  934. default:
  935. tokens.append(Operator::BitwiseOr);
  936. break;
  937. }
  938. break;
  939. case U'^':
  940. if (it.peek(1) == U'=') {
  941. ++it;
  942. tokens.append(Operator::XorAssignment);
  943. } else {
  944. tokens.append(Operator::BitwiseXor);
  945. }
  946. break;
  947. case U',':
  948. tokens.append(Operator::Comma);
  949. break;
  950. case U'?':
  951. tokens.append(Operator::TernaryQuestion);
  952. break;
  953. case U':':
  954. tokens.append(Operator::TernaryColon);
  955. break;
  956. case U'+':
  957. switch (it.peek(1).value_or(0)) {
  958. case U'=':
  959. ++it;
  960. tokens.append(Operator::PlusAssignment);
  961. break;
  962. default:
  963. tokens.append(Operator::Add);
  964. break;
  965. }
  966. break;
  967. case U'-':
  968. switch (it.peek(1).value_or(0)) {
  969. case U'=':
  970. ++it;
  971. tokens.append(Operator::MinusAssignment);
  972. break;
  973. default:
  974. tokens.append(Operator::Subtract);
  975. break;
  976. }
  977. break;
  978. case U'*':
  979. switch (it.peek(1).value_or(0)) {
  980. case U'=':
  981. ++it;
  982. tokens.append(Operator::MultiplyAssignment);
  983. break;
  984. case U'*':
  985. ++it;
  986. tokens.append(Operator::Power);
  987. break;
  988. default:
  989. tokens.append(Operator::Multiply);
  990. break;
  991. }
  992. break;
  993. case U'/':
  994. if (it.peek(1) == U'=') {
  995. ++it;
  996. tokens.append(Operator::DivideAssignment);
  997. } else {
  998. tokens.append(Operator::Quotient);
  999. }
  1000. break;
  1001. case U'%':
  1002. if (it.peek(1) == U'=') {
  1003. ++it;
  1004. tokens.append(Operator::ModuloAssignment);
  1005. } else {
  1006. tokens.append(Operator::Remainder);
  1007. }
  1008. break;
  1009. case U'<':
  1010. switch (it.peek(1).value_or(0)) {
  1011. case U'<':
  1012. ++it;
  1013. if (it.peek(1) == U'=') {
  1014. ++it;
  1015. tokens.append(Operator::LeftShiftAssignment);
  1016. } else {
  1017. tokens.append(Operator::ShiftLeft);
  1018. }
  1019. break;
  1020. case U'=':
  1021. ++it;
  1022. tokens.append(Operator::LessThanOrEqual);
  1023. break;
  1024. default:
  1025. tokens.append(Operator::LessThan);
  1026. break;
  1027. }
  1028. break;
  1029. case U'>':
  1030. switch (it.peek(1).value_or(0)) {
  1031. case U'>':
  1032. ++it;
  1033. if (it.peek(1) == U'=') {
  1034. ++it;
  1035. tokens.append(Operator::RightShiftAssignment);
  1036. } else {
  1037. tokens.append(Operator::ShiftRight);
  1038. }
  1039. break;
  1040. case U'=':
  1041. ++it;
  1042. tokens.append(Operator::GreaterThanOrEqual);
  1043. break;
  1044. default:
  1045. tokens.append(Operator::GreaterThan);
  1046. break;
  1047. }
  1048. break;
  1049. case U' ':
  1050. case U'\t':
  1051. case U'\n':
  1052. case U'\r':
  1053. break;
  1054. default:
  1055. raise_error(ShellError::EvaluatedSyntaxError, DeprecatedString::formatted("Unexpected character '{:c}' in math expression", code_point), arguments.first()->position());
  1056. return nullptr;
  1057. }
  1058. }
  1059. if (integer_or_word_start_offset.has_value()) {
  1060. auto integer_or_word = view.substring_view(*integer_or_word_start_offset);
  1061. if (all_of(integer_or_word, is_ascii_digit))
  1062. tokens.append(*integer_or_word.as_string().to_int());
  1063. else
  1064. tokens.append(TRY(expression.substring_from_byte_offset_with_shared_superstring(*integer_or_word_start_offset, integer_or_word.length())));
  1065. integer_or_word_start_offset.clear();
  1066. }
  1067. auto ast = TRY(Arithmetic::parse_expression(tokens));
  1068. // Now interpret that.
  1069. Function<ErrorOr<i64>(Arithmetic::Node const&)> interpret = [&](Arithmetic::Node const& node) -> ErrorOr<i64> {
  1070. return node.value.visit(
  1071. [&](String const& name) -> ErrorOr<i64> {
  1072. size_t resolution_attempts_remaining = 100;
  1073. for (auto resolved_name = name; resolution_attempts_remaining > 0; --resolution_attempts_remaining) {
  1074. auto value = TRY(look_up_local_variable(resolved_name.bytes_as_string_view()));
  1075. if (!value)
  1076. break;
  1077. StringBuilder builder;
  1078. builder.join(' ', TRY(const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this))));
  1079. resolved_name = TRY(builder.to_string());
  1080. auto integer = resolved_name.bytes_as_string_view().to_int<i64>();
  1081. if (integer.has_value())
  1082. return *integer;
  1083. }
  1084. if (resolution_attempts_remaining == 0)
  1085. raise_error(ShellError::EvaluatedSyntaxError, DeprecatedString::formatted("Too many indirections when resolving variable '{}'", name), arguments.first()->position());
  1086. return 0;
  1087. },
  1088. [&](i64 value) -> ErrorOr<i64> {
  1089. return value;
  1090. },
  1091. [&](NonnullOwnPtr<Arithmetic::BinaryOperationNode> const& node) -> ErrorOr<i64> {
  1092. if (Arithmetic::is_assignment_operator(node->op)) {
  1093. // lhs must be a variable name.
  1094. auto name = node->lhs.value.get_pointer<String>();
  1095. if (!name) {
  1096. raise_error(ShellError::EvaluatedSyntaxError, "Invalid left-hand side of assignment", arguments.first()->position());
  1097. return 0;
  1098. }
  1099. auto rhs = TRY(interpret(node->rhs));
  1100. if (node->op != Arithmetic::Operator::Assignment) {
  1101. // Evaluate the new value
  1102. rhs = TRY(interpret(Arithmetic::Node {
  1103. .value = make<Arithmetic::BinaryOperationNode>(
  1104. Arithmetic::assignment_operation_of(node->op),
  1105. Arithmetic::Node { *name },
  1106. Arithmetic::Node { rhs }),
  1107. }));
  1108. }
  1109. set_local_variable(name->to_deprecated_string(), make_ref_counted<AST::StringValue>(TRY(String::number(rhs))));
  1110. return rhs;
  1111. }
  1112. auto lhs = TRY(interpret(node->lhs));
  1113. auto rhs = TRY(interpret(node->rhs));
  1114. using Arithmetic::Operator;
  1115. switch (node->op) {
  1116. case Operator::Add:
  1117. return lhs + rhs;
  1118. case Operator::Subtract:
  1119. return lhs - rhs;
  1120. case Operator::Multiply:
  1121. return lhs * rhs;
  1122. case Operator::Quotient:
  1123. return lhs / rhs;
  1124. case Operator::Remainder:
  1125. return lhs % rhs;
  1126. case Operator::ShiftLeft:
  1127. return lhs << rhs;
  1128. case Operator::ShiftRight:
  1129. return lhs >> rhs;
  1130. case Operator::BitwiseAnd:
  1131. return lhs & rhs;
  1132. case Operator::BitwiseOr:
  1133. return lhs | rhs;
  1134. case Operator::BitwiseXor:
  1135. return lhs ^ rhs;
  1136. case Operator::ArithmeticAnd:
  1137. return lhs != 0 && rhs != 0;
  1138. case Operator::ArithmeticOr:
  1139. return lhs != 0 || rhs != 0;
  1140. case Operator::LessThan:
  1141. return lhs < rhs;
  1142. case Operator::LessThanOrEqual:
  1143. return lhs <= rhs;
  1144. case Operator::GreaterThan:
  1145. return lhs > rhs;
  1146. case Operator::GreaterThanOrEqual:
  1147. return lhs >= rhs;
  1148. case Operator::Equal:
  1149. return lhs == rhs;
  1150. case Operator::NotEqual:
  1151. return lhs != rhs;
  1152. case Operator::Power:
  1153. return trunc(pow(static_cast<double>(lhs), static_cast<double>(rhs)));
  1154. case Operator::Comma:
  1155. return rhs;
  1156. default:
  1157. VERIFY_NOT_REACHED();
  1158. }
  1159. },
  1160. [&](NonnullOwnPtr<Arithmetic::UnaryOperationNode> const& node) -> ErrorOr<i64> {
  1161. auto value = TRY(interpret(node->rhs));
  1162. switch (node->op) {
  1163. case Arithmetic::Operator::Negate:
  1164. return value == 0;
  1165. case Arithmetic::Operator::BitwiseNegate:
  1166. return ~value;
  1167. case Arithmetic::Operator::Add:
  1168. return value;
  1169. case Arithmetic::Operator::Subtract:
  1170. return -value;
  1171. default:
  1172. VERIFY_NOT_REACHED();
  1173. }
  1174. },
  1175. [&](NonnullOwnPtr<Arithmetic::TernaryOperationNode> const& node) -> ErrorOr<i64> {
  1176. auto condition = TRY(interpret(node->condition));
  1177. if (condition != 0)
  1178. return TRY(interpret(node->true_value));
  1179. return TRY(interpret(node->false_value));
  1180. },
  1181. [&](NonnullOwnPtr<Arithmetic::ErrorNode> const& node) -> ErrorOr<i64> {
  1182. raise_error(ShellError::EvaluatedSyntaxError, node->error.to_deprecated_string(), arguments.first()->position());
  1183. return 0;
  1184. });
  1185. };
  1186. auto result = TRY(interpret(ast));
  1187. return make_ref_counted<AST::StringLiteral>(arguments.first()->position(), TRY(String::number(result)), AST::StringLiteral::EnclosureType::None);
  1188. }
  1189. ErrorOr<RefPtr<AST::Node>> Shell::run_immediate_function(StringView str, AST::ImmediateExpression& invoking_node, Vector<NonnullRefPtr<AST::Node>> const& arguments)
  1190. {
  1191. #define __ENUMERATE_SHELL_IMMEDIATE_FUNCTION(name) \
  1192. if (str == #name) \
  1193. return immediate_##name(invoking_node, arguments);
  1194. ENUMERATE_SHELL_IMMEDIATE_FUNCTIONS()
  1195. #undef __ENUMERATE_SHELL_IMMEDIATE_FUNCTION
  1196. raise_error(ShellError::EvaluatedSyntaxError, DeprecatedString::formatted("Unknown immediate function {}", str), invoking_node.position());
  1197. return nullptr;
  1198. }
  1199. bool Shell::has_immediate_function(StringView str)
  1200. {
  1201. #define __ENUMERATE_SHELL_IMMEDIATE_FUNCTION(name) \
  1202. if (str == #name) \
  1203. return true;
  1204. ENUMERATE_SHELL_IMMEDIATE_FUNCTIONS()
  1205. #undef __ENUMERATE_SHELL_IMMEDIATE_FUNCTION
  1206. return false;
  1207. }
  1208. }