mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:02:44 +00:00 
			
		
		
		
	 dc495e299e
			
		
	
	
		dc495e299e
		
	
	
	
	
		
			
			This is currently only allowed in assignments, where x=(...) is parsed as the assignment of the list (...) to the variable x.
		
			
				
	
	
		
			1558 lines
		
	
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1558 lines
		
	
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2020, the SerenityOS developers.
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include "Forward.h"
 | |
| #include "Job.h"
 | |
| #include "NodeVisitor.h"
 | |
| #include <AK/Format.h>
 | |
| #include <AK/NonnullRefPtr.h>
 | |
| #include <AK/RefCounted.h>
 | |
| #include <AK/RefPtr.h>
 | |
| #include <AK/String.h>
 | |
| #include <AK/Types.h>
 | |
| #include <AK/Vector.h>
 | |
| #include <LibLine/Editor.h>
 | |
| #include <LibRegex/Regex.h>
 | |
| 
 | |
| namespace Shell::AST {
 | |
| 
 | |
| using AK::make_ref_counted;
 | |
| 
 | |
| template<typename T>
 | |
| static inline NonnullRefPtr<T> make_ref_counted(std::initializer_list<NonnullRefPtr<Value>> arg)
 | |
| {
 | |
|     return adopt_ref(*new T(arg));
 | |
| }
 | |
| 
 | |
| struct HighlightMetadata {
 | |
|     bool is_first_in_list { true };
 | |
| };
 | |
| 
 | |
| struct Position {
 | |
|     size_t start_offset { 0 };
 | |
|     size_t end_offset { 0 };
 | |
|     struct Line {
 | |
|         size_t line_number { 0 };
 | |
|         size_t line_column { 0 };
 | |
| 
 | |
|         bool operator==(Line const& other) const
 | |
|         {
 | |
|             return line_number == other.line_number && line_column == other.line_column;
 | |
|         }
 | |
|     } start_line, end_line;
 | |
| 
 | |
|     bool contains(size_t offset) const { return start_offset <= offset && offset <= end_offset; }
 | |
| 
 | |
|     Position with_end(Position const& end) const
 | |
|     {
 | |
|         return {
 | |
|             .start_offset = start_offset,
 | |
|             .end_offset = end.end_offset,
 | |
|             .start_line = start_line,
 | |
|             .end_line = end.end_line,
 | |
|         };
 | |
|     }
 | |
| };
 | |
| 
 | |
| struct NameWithPosition {
 | |
|     String name;
 | |
|     Position position;
 | |
| };
 | |
| 
 | |
| struct FdRedirection;
 | |
| struct Rewiring : public RefCounted<Rewiring> {
 | |
|     int old_fd { -1 };
 | |
|     int new_fd { -1 };
 | |
|     FdRedirection* other_pipe_end { nullptr };
 | |
|     enum class Close {
 | |
|         None,
 | |
|         Old,
 | |
|         New,
 | |
|         RefreshNew,
 | |
|         RefreshOld,
 | |
|         ImmediatelyCloseNew,
 | |
|     } fd_action { Close::None };
 | |
| 
 | |
|     Rewiring(int source, int dest, Close close = Close::None)
 | |
|         : old_fd(source)
 | |
|         , new_fd(dest)
 | |
|         , fd_action(close)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Rewiring(int source, int dest, FdRedirection* other_end, Close close)
 | |
|         : old_fd(source)
 | |
|         , new_fd(dest)
 | |
|         , other_pipe_end(other_end)
 | |
|         , fd_action(close)
 | |
|     {
 | |
|     }
 | |
| };
 | |
| 
 | |
| struct Redirection : public RefCounted<Redirection> {
 | |
|     virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const = 0;
 | |
|     virtual ~Redirection();
 | |
|     virtual bool is_path_redirection() const { return false; }
 | |
|     virtual bool is_fd_redirection() const { return false; }
 | |
|     virtual bool is_close_redirection() const { return false; }
 | |
| };
 | |
| 
 | |
| struct CloseRedirection : public Redirection {
 | |
|     int fd { -1 };
 | |
| 
 | |
|     virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const override;
 | |
|     virtual ~CloseRedirection();
 | |
|     CloseRedirection(int fd)
 | |
|         : fd(fd)
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     virtual bool is_close_redirection() const override { return true; }
 | |
| };
 | |
| 
 | |
| struct PathRedirection : public Redirection {
 | |
|     String path;
 | |
|     int fd { -1 };
 | |
|     enum {
 | |
|         Read,
 | |
|         Write,
 | |
|         WriteAppend,
 | |
|         ReadWrite,
 | |
|     } direction { Read };
 | |
| 
 | |
|     static NonnullRefPtr<PathRedirection> create(String path, int fd, decltype(direction) direction)
 | |
|     {
 | |
|         return adopt_ref(*new PathRedirection(move(path), fd, direction));
 | |
|     }
 | |
| 
 | |
|     virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const override;
 | |
|     virtual ~PathRedirection();
 | |
| 
 | |
| private:
 | |
|     PathRedirection(String path, int fd, decltype(direction) direction)
 | |
|         : path(move(path))
 | |
|         , fd(fd)
 | |
|         , direction(direction)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     virtual bool is_path_redirection() const override { return true; }
 | |
| };
 | |
| 
 | |
| struct FdRedirection : public Redirection {
 | |
| public:
 | |
|     static NonnullRefPtr<FdRedirection> create(int old_fd, int new_fd, Rewiring::Close close)
 | |
|     {
 | |
|         return adopt_ref(*new FdRedirection(old_fd, new_fd, close));
 | |
|     }
 | |
| 
 | |
|     static NonnullRefPtr<FdRedirection> create(int old_fd, int new_fd, FdRedirection* pipe_end, Rewiring::Close close)
 | |
|     {
 | |
|         return adopt_ref(*new FdRedirection(old_fd, new_fd, pipe_end, close));
 | |
|     }
 | |
| 
 | |
|     virtual ~FdRedirection();
 | |
| 
 | |
|     virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const override
 | |
|     {
 | |
|         return adopt_ref(*new Rewiring(old_fd, new_fd, other_pipe_end, action));
 | |
|     }
 | |
| 
 | |
|     int old_fd { -1 };
 | |
|     int new_fd { -1 };
 | |
|     FdRedirection* other_pipe_end { nullptr };
 | |
|     Rewiring::Close action { Rewiring::Close::None };
 | |
| 
 | |
| private:
 | |
|     FdRedirection(int source, int dest, Rewiring::Close close)
 | |
|         : FdRedirection(source, dest, nullptr, close)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     FdRedirection(int old_fd, int new_fd, FdRedirection* pipe_end, Rewiring::Close close)
 | |
|         : old_fd(old_fd)
 | |
|         , new_fd(new_fd)
 | |
|         , other_pipe_end(pipe_end)
 | |
|         , action(close)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     virtual bool is_fd_redirection() const override { return true; }
 | |
| };
 | |
| 
 | |
| class Pipeline : public RefCounted<Pipeline> {
 | |
| public:
 | |
|     pid_t pgid { -1 };
 | |
| };
 | |
| 
 | |
| struct NodeWithAction {
 | |
|     mutable NonnullRefPtr<Node> node;
 | |
|     enum Action {
 | |
|         And,
 | |
|         Or,
 | |
|         Sequence,
 | |
|     } action;
 | |
| 
 | |
|     NodeWithAction(Node& node, Action action)
 | |
|         : node(node)
 | |
|         , action(action)
 | |
|     {
 | |
|     }
 | |
| };
 | |
| 
 | |
| struct Command {
 | |
|     Vector<String> argv;
 | |
|     Vector<NonnullRefPtr<Redirection>> redirections;
 | |
|     bool should_wait { true };
 | |
|     bool is_pipe_source { false };
 | |
|     bool should_notify_if_in_background { true };
 | |
|     bool should_immediately_execute_next { false };
 | |
| 
 | |
|     mutable RefPtr<Pipeline> pipeline;
 | |
|     Vector<NodeWithAction> next_chain;
 | |
|     Optional<Position> position;
 | |
| };
 | |
| 
 | |
| struct HitTestResult {
 | |
|     RefPtr<Node const> matching_node;
 | |
|     RefPtr<Node const> closest_node_with_semantic_meaning; // This is used if matching_node is a bareword
 | |
|     RefPtr<Node const> closest_command_node;               // This is used if matching_node is a bareword, and it is not the first in a list
 | |
| };
 | |
| 
 | |
| class Value : public RefCounted<Value> {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) = 0;
 | |
|     virtual ErrorOr<String> resolve_as_string(RefPtr<Shell> shell);
 | |
|     virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>);
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) { return *this; }
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const = 0;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> with_slices(NonnullRefPtr<Slice> slice) const&;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> with_slices(Vector<NonnullRefPtr<Slice>> slices) const&;
 | |
|     virtual ~Value();
 | |
|     virtual bool is_command() const { return false; }
 | |
|     virtual bool is_glob() const { return false; }
 | |
|     virtual bool is_job() const { return false; }
 | |
|     virtual bool is_list() const { return false; }
 | |
|     virtual bool is_string() const { return false; }
 | |
|     virtual bool is_list_without_resolution() const { return false; }
 | |
| 
 | |
| protected:
 | |
|     Value& set_slices(Vector<NonnullRefPtr<Slice>> slices)
 | |
|     {
 | |
|         m_slices = move(slices);
 | |
|         return *this;
 | |
|     }
 | |
|     Vector<NonnullRefPtr<Slice>> m_slices;
 | |
| };
 | |
| 
 | |
| class CommandValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<CommandValue>(m_command))->set_slices(m_slices); }
 | |
|     virtual ~CommandValue();
 | |
|     virtual bool is_command() const override { return true; }
 | |
|     CommandValue(Command command)
 | |
|         : m_command(move(command))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     CommandValue(Vector<String> argv, Position position)
 | |
|         : m_command({ move(argv), {}, true, false, true, false, nullptr, {}, move(position) })
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     Command m_command;
 | |
| };
 | |
| 
 | |
| class CommandSequenceValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<CommandSequenceValue>(m_contained_values))->set_slices(m_slices); }
 | |
|     virtual ~CommandSequenceValue();
 | |
|     virtual bool is_command() const override { return true; }
 | |
|     CommandSequenceValue(Vector<Command> commands)
 | |
|         : m_contained_values(move(commands))
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     Vector<Command> m_contained_values;
 | |
| };
 | |
| 
 | |
| class JobValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); }
 | |
|     virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override { return String::formatted("%{}", m_job->job_id()); }
 | |
|     virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); }
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<JobValue>(m_job))->set_slices(m_slices); }
 | |
|     virtual ~JobValue();
 | |
|     virtual bool is_job() const override { return true; }
 | |
|     JobValue(RefPtr<Job> job)
 | |
|         : m_job(move(job))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     RefPtr<Job> const job() const { return m_job; }
 | |
| 
 | |
| private:
 | |
|     RefPtr<Job> m_job;
 | |
| };
 | |
| 
 | |
| class ListValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<ListValue>(m_contained_values))->set_slices(m_slices); }
 | |
|     virtual ~ListValue();
 | |
|     virtual bool is_list() const override { return true; }
 | |
|     virtual bool is_list_without_resolution() const override { return true; }
 | |
|     ListValue(Vector<String> values);
 | |
|     ListValue(Vector<NonnullRefPtr<Value>> values)
 | |
|         : m_contained_values(move(values))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Vector<NonnullRefPtr<Value>> const& values() const { return m_contained_values; }
 | |
|     Vector<NonnullRefPtr<Value>>& values() { return m_contained_values; }
 | |
| 
 | |
| private:
 | |
|     Vector<NonnullRefPtr<Value>> m_contained_values;
 | |
| };
 | |
| 
 | |
| class StringValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<String> resolve_as_string(RefPtr<Shell> shell) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<StringValue>(m_string, m_split, m_keep_empty))->set_slices(m_slices); }
 | |
|     virtual ~StringValue();
 | |
|     virtual bool is_string() const override { return m_split.is_empty(); }
 | |
|     virtual bool is_list() const override { return !m_split.is_empty(); }
 | |
|     ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
 | |
|     StringValue(String string, String split_by = {}, bool keep_empty = false)
 | |
|         : m_string(move(string))
 | |
|         , m_split(move(split_by))
 | |
|         , m_keep_empty(keep_empty)
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     String m_string;
 | |
|     String m_split;
 | |
|     bool m_keep_empty { false };
 | |
| };
 | |
| 
 | |
| class GlobValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<GlobValue>(m_glob, m_generation_position))->set_slices(m_slices); }
 | |
|     virtual ~GlobValue();
 | |
|     virtual bool is_glob() const override { return true; }
 | |
|     GlobValue(String glob, Position position)
 | |
|         : m_glob(move(glob))
 | |
|         , m_generation_position(move(position))
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     String m_glob;
 | |
|     Position m_generation_position;
 | |
| };
 | |
| 
 | |
| class SimpleVariableValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<SimpleVariableValue>(m_name))->set_slices(m_slices); }
 | |
|     virtual ~SimpleVariableValue();
 | |
|     SimpleVariableValue(String name)
 | |
|         : m_name(move(name))
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     String m_name;
 | |
| };
 | |
| 
 | |
| class SpecialVariableValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<SpecialVariableValue>(m_name))->set_slices(m_slices); }
 | |
|     virtual ~SpecialVariableValue();
 | |
|     SpecialVariableValue(char name)
 | |
|         : m_name(name)
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     char m_name { 0 };
 | |
| };
 | |
| 
 | |
| class TildeValue final : public Value {
 | |
| public:
 | |
|     virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<TildeValue>(m_username))->set_slices(m_slices); }
 | |
|     virtual ~TildeValue();
 | |
|     virtual bool is_string() const override { return true; }
 | |
|     TildeValue(String name)
 | |
|         : m_username(move(name))
 | |
|     {
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     String m_username;
 | |
| };
 | |
| 
 | |
| class Node : public RefCounted<Node> {
 | |
|     AK_MAKE_NONCOPYABLE(Node);
 | |
|     AK_MAKE_NONMOVABLE(Node);
 | |
| 
 | |
| public:
 | |
|     virtual ErrorOr<void> dump(int level) const = 0;
 | |
|     virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback);
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) = 0;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) = 0;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const;
 | |
|     ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell& shell, size_t offset);
 | |
|     virtual HitTestResult hit_test_position(size_t offset) const
 | |
|     {
 | |
|         if (m_position.contains(offset))
 | |
|             return { this, nullptr, nullptr };
 | |
|         return { nullptr, nullptr, nullptr };
 | |
|     }
 | |
|     virtual StringView class_name() const { return "Node"sv; }
 | |
|     Node(Position);
 | |
|     virtual ~Node() = default;
 | |
| 
 | |
|     virtual bool is_bareword() const { return false; }
 | |
|     virtual bool is_command() const { return false; }
 | |
|     virtual bool is_execute() const { return false; }
 | |
|     virtual bool is_glob() const { return false; }
 | |
|     virtual bool is_tilde() const { return false; }
 | |
|     virtual bool is_variable_decls() const { return false; }
 | |
|     virtual bool is_simple_variable() const { return false; }
 | |
|     virtual bool is_syntax_error() const;
 | |
| 
 | |
|     virtual bool is_list() const { return false; }
 | |
|     virtual bool would_execute() const { return false; }
 | |
|     virtual bool should_override_execution_in_current_process() const { return false; }
 | |
| 
 | |
|     Position const& position() const { return m_position; }
 | |
|     Position& position() { return m_position; }
 | |
|     virtual void clear_syntax_error();
 | |
|     virtual void set_is_syntax_error(SyntaxError& error_node);
 | |
|     virtual SyntaxError& syntax_error_node()
 | |
|     {
 | |
|         VERIFY(is_syntax_error());
 | |
|         return *m_syntax_error_node;
 | |
|     }
 | |
| 
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const { return nullptr; }
 | |
| 
 | |
|     ErrorOr<Vector<Command>> to_lazy_evaluated_commands(RefPtr<Shell> shell);
 | |
| 
 | |
|     virtual void visit(NodeVisitor&) { VERIFY_NOT_REACHED(); }
 | |
|     virtual void visit(NodeVisitor& visitor) const { const_cast<Node*>(this)->visit(visitor); }
 | |
| 
 | |
|     enum class Kind : u32 {
 | |
|         And,
 | |
|         Background,
 | |
|         BarewordLiteral,
 | |
|         BraceExpansion,
 | |
|         CastToCommand,
 | |
|         CastToList,
 | |
|         CloseFdRedirection,
 | |
|         CommandLiteral,
 | |
|         Comment,
 | |
|         ContinuationControl,
 | |
|         DoubleQuotedString,
 | |
|         DynamicEvaluate,
 | |
|         Execute,
 | |
|         Fd2FdRedirection,
 | |
|         ForLoop,
 | |
|         FunctionDeclaration,
 | |
|         Glob,
 | |
|         Heredoc,
 | |
|         HistoryEvent,
 | |
|         IfCond,
 | |
|         ImmediateExpression,
 | |
|         Join,
 | |
|         Juxtaposition,
 | |
|         ListConcatenate,
 | |
|         MatchExpr,
 | |
|         Or,
 | |
|         Pipe,
 | |
|         Range,
 | |
|         ReadRedirection,
 | |
|         ReadWriteRedirection,
 | |
|         Sequence,
 | |
|         Slice,
 | |
|         SimpleVariable,
 | |
|         SpecialVariable,
 | |
|         StringLiteral,
 | |
|         StringPartCompose,
 | |
|         Subshell,
 | |
|         SyntaxError,
 | |
|         SyntheticValue,
 | |
|         Tilde,
 | |
|         VariableDeclarations,
 | |
|         WriteAppendRedirection,
 | |
|         WriteRedirection,
 | |
|         __Count,
 | |
|     };
 | |
| 
 | |
|     virtual Kind kind() const = 0;
 | |
| 
 | |
| protected:
 | |
|     Position m_position;
 | |
|     RefPtr<SyntaxError> m_syntax_error_node;
 | |
| };
 | |
| 
 | |
| #define NODE(name)                                 \
 | |
|     virtual StringView class_name() const override \
 | |
|     {                                              \
 | |
|         return #name##sv;                          \
 | |
|     }                                              \
 | |
|     virtual Kind kind() const override             \
 | |
|     {                                              \
 | |
|         return Kind::name;                         \
 | |
|     }
 | |
| 
 | |
| class PathRedirectionNode : public Node {
 | |
| public:
 | |
|     PathRedirectionNode(Position, int, NonnullRefPtr<Node>);
 | |
|     virtual ~PathRedirectionNode();
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual HitTestResult hit_test_position(size_t offset) const override;
 | |
|     virtual bool is_command() const override { return true; }
 | |
|     virtual bool is_list() const override { return true; }
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& path() const { return m_path; }
 | |
|     int fd() const { return m_fd; }
 | |
| 
 | |
| protected:
 | |
|     int m_fd { -1 };
 | |
|     NonnullRefPtr<Node> m_path;
 | |
| };
 | |
| 
 | |
| class And final : public Node {
 | |
| public:
 | |
|     And(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>, Position and_position);
 | |
|     virtual ~And() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& left() const { return m_left; }
 | |
|     NonnullRefPtr<Node> const& right() const { return m_right; }
 | |
|     Position const& and_position() const { return m_and_position; }
 | |
| 
 | |
| private:
 | |
|     NODE(And);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_left;
 | |
|     NonnullRefPtr<Node> m_right;
 | |
|     Position m_and_position;
 | |
| };
 | |
| 
 | |
| class ListConcatenate final : public Node {
 | |
| public:
 | |
|     ListConcatenate(Position, Vector<NonnullRefPtr<Node>>);
 | |
|     virtual ~ListConcatenate() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
|     Vector<NonnullRefPtr<Node>> const list() const { return m_list; }
 | |
| 
 | |
| private:
 | |
|     NODE(ListConcatenate);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback) override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_list() const override { return true; }
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override;
 | |
| 
 | |
|     Vector<NonnullRefPtr<Node>> m_list;
 | |
| };
 | |
| 
 | |
| class Background final : public Node {
 | |
| public:
 | |
|     Background(Position, NonnullRefPtr<Node>);
 | |
|     virtual ~Background() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& command() const { return m_command; }
 | |
| 
 | |
| private:
 | |
|     NODE(Background);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_command;
 | |
| };
 | |
| 
 | |
| class BarewordLiteral final : public Node {
 | |
| public:
 | |
|     BarewordLiteral(Position, String);
 | |
|     virtual ~BarewordLiteral() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     String const& text() const { return m_text; }
 | |
| 
 | |
| private:
 | |
|     NODE(BarewordLiteral);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual bool is_bareword() const override { return true; }
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }
 | |
| 
 | |
|     String m_text;
 | |
| };
 | |
| 
 | |
| class BraceExpansion final : public Node {
 | |
| public:
 | |
|     BraceExpansion(Position, Vector<NonnullRefPtr<Node>>);
 | |
|     virtual ~BraceExpansion() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     Vector<NonnullRefPtr<Node>> const& entries() const { return m_entries; }
 | |
| 
 | |
| private:
 | |
|     NODE(BraceExpansion);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     Vector<NonnullRefPtr<Node>> m_entries;
 | |
| };
 | |
| 
 | |
| class CastToCommand final : public Node {
 | |
| public:
 | |
|     CastToCommand(Position, NonnullRefPtr<Node>);
 | |
|     virtual ~CastToCommand() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& inner() const { return m_inner; }
 | |
| 
 | |
| private:
 | |
|     NODE(CastToCommand);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual bool is_command() const override { return true; }
 | |
|     virtual bool is_list() const override { return true; }
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_inner;
 | |
| };
 | |
| 
 | |
| class CastToList final : public Node {
 | |
| public:
 | |
|     CastToList(Position, RefPtr<Node>);
 | |
|     virtual ~CastToList() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     RefPtr<Node> const& inner() const { return m_inner; }
 | |
| 
 | |
| private:
 | |
|     NODE(CastToList);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_list() const override { return true; }
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override;
 | |
| 
 | |
|     RefPtr<Node> m_inner;
 | |
| };
 | |
| 
 | |
| class CloseFdRedirection final : public Node {
 | |
| public:
 | |
|     CloseFdRedirection(Position, int);
 | |
|     virtual ~CloseFdRedirection();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     int fd() const { return m_fd; }
 | |
| 
 | |
| private:
 | |
|     NODE(CloseFdRedirection);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual bool is_command() const override { return true; }
 | |
| 
 | |
|     int m_fd { -1 };
 | |
| };
 | |
| 
 | |
| class CommandLiteral final : public Node {
 | |
| public:
 | |
|     CommandLiteral(Position, Command);
 | |
|     virtual ~CommandLiteral();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     Command const& command() const { return m_command; }
 | |
| 
 | |
| private:
 | |
|     NODE(CommandLiteral);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override { VERIFY_NOT_REACHED(); }
 | |
|     virtual bool is_command() const override { return true; }
 | |
|     virtual bool is_list() const override { return true; }
 | |
| 
 | |
|     Command m_command;
 | |
| };
 | |
| 
 | |
| class Comment : public Node {
 | |
| public:
 | |
|     Comment(Position, String);
 | |
|     virtual ~Comment();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     String const& text() const { return m_text; }
 | |
| 
 | |
| private:
 | |
|     NODE(Comment);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
| 
 | |
|     String m_text;
 | |
| };
 | |
| 
 | |
| class ContinuationControl final : public Node {
 | |
| public:
 | |
|     enum ContinuationKind {
 | |
|         Break,
 | |
|         Continue,
 | |
|     };
 | |
|     ContinuationControl(Position position, ContinuationKind kind)
 | |
|         : Node(move(position))
 | |
|         , m_kind(kind)
 | |
|     {
 | |
|     }
 | |
|     virtual ~ContinuationControl() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     ContinuationKind continuation_kind() const { return m_kind; }
 | |
| 
 | |
| private:
 | |
|     NODE(ContinuationControl);
 | |
| 
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
| 
 | |
|     ContinuationKind m_kind { ContinuationKind::Break };
 | |
| };
 | |
| 
 | |
| class DynamicEvaluate final : public Node {
 | |
| public:
 | |
|     DynamicEvaluate(Position, NonnullRefPtr<Node>);
 | |
|     virtual ~DynamicEvaluate();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& inner() const { return m_inner; }
 | |
| 
 | |
| private:
 | |
|     NODE(DynamicEvaluate);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     virtual bool is_bareword() const override { return m_inner->is_bareword(); }
 | |
|     virtual bool is_command() const override { return is_list(); }
 | |
|     virtual bool is_execute() const override { return true; }
 | |
|     virtual bool is_glob() const override { return m_inner->is_glob(); }
 | |
|     virtual bool is_list() const override
 | |
|     {
 | |
|         return m_inner->is_list() || m_inner->is_command() || m_inner->is_glob(); // Anything that generates a list.
 | |
|     }
 | |
| 
 | |
|     NonnullRefPtr<Node> m_inner;
 | |
| };
 | |
| 
 | |
| class DoubleQuotedString final : public Node {
 | |
| public:
 | |
|     DoubleQuotedString(Position, RefPtr<Node>);
 | |
|     virtual ~DoubleQuotedString();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     RefPtr<Node> const& inner() const { return m_inner; }
 | |
| 
 | |
| private:
 | |
|     NODE(DoubleQuotedString);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     RefPtr<Node> m_inner;
 | |
| };
 | |
| 
 | |
| class Fd2FdRedirection final : public Node {
 | |
| public:
 | |
|     Fd2FdRedirection(Position, int, int);
 | |
|     virtual ~Fd2FdRedirection();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     int source_fd() const { return m_old_fd; }
 | |
|     int dest_fd() const { return m_new_fd; }
 | |
| 
 | |
| private:
 | |
|     NODE(Fd2FdRedirection);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual bool is_command() const override { return true; }
 | |
| 
 | |
|     int m_old_fd { -1 };
 | |
|     int m_new_fd { -1 };
 | |
| };
 | |
| 
 | |
| class FunctionDeclaration final : public Node {
 | |
| public:
 | |
|     FunctionDeclaration(Position, NameWithPosition name, Vector<NameWithPosition> argument_names, RefPtr<AST::Node> body);
 | |
|     virtual ~FunctionDeclaration();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NameWithPosition const& name() const { return m_name; }
 | |
|     Vector<NameWithPosition> const arguments() const { return m_arguments; }
 | |
|     RefPtr<Node> const& block() const { return m_block; }
 | |
| 
 | |
| private:
 | |
|     NODE(FunctionDeclaration);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual bool would_execute() const override { return true; }
 | |
|     virtual bool should_override_execution_in_current_process() const override { return true; }
 | |
| 
 | |
|     NameWithPosition m_name;
 | |
|     Vector<NameWithPosition> m_arguments;
 | |
|     RefPtr<AST::Node> m_block;
 | |
| };
 | |
| 
 | |
| class ForLoop final : public Node {
 | |
| public:
 | |
|     ForLoop(Position, Optional<NameWithPosition> variable, Optional<NameWithPosition> index_variable, RefPtr<AST::Node> iterated_expr, RefPtr<AST::Node> block, Optional<Position> in_kw_position = {}, Optional<Position> index_kw_position = {});
 | |
|     virtual ~ForLoop();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     Optional<NameWithPosition> const& variable() const { return m_variable; }
 | |
|     Optional<NameWithPosition> const& index_variable() const { return m_index_variable; }
 | |
|     RefPtr<Node> const& iterated_expression() const { return m_iterated_expression; }
 | |
|     RefPtr<Node> const& block() const { return m_block; }
 | |
|     Optional<Position> const index_keyword_position() const { return m_index_kw_position; }
 | |
|     Optional<Position> const in_keyword_position() const { return m_in_kw_position; }
 | |
| 
 | |
| private:
 | |
|     NODE(ForLoop);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool would_execute() const override { return true; }
 | |
|     virtual bool should_override_execution_in_current_process() const override { return true; }
 | |
| 
 | |
|     Optional<NameWithPosition> m_variable;
 | |
|     Optional<NameWithPosition> m_index_variable;
 | |
|     RefPtr<AST::Node> m_iterated_expression;
 | |
|     RefPtr<AST::Node> m_block;
 | |
|     Optional<Position> m_in_kw_position;
 | |
|     Optional<Position> m_index_kw_position;
 | |
| };
 | |
| 
 | |
| class Glob final : public Node {
 | |
| public:
 | |
|     Glob(Position, String);
 | |
|     virtual ~Glob();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     String const& text() const { return m_text; }
 | |
| 
 | |
| private:
 | |
|     NODE(Glob);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual bool is_glob() const override { return true; }
 | |
|     virtual bool is_list() const override { return true; }
 | |
| 
 | |
|     String m_text;
 | |
| };
 | |
| 
 | |
| struct HistorySelector {
 | |
|     enum EventKind {
 | |
|         IndexFromStart,
 | |
|         IndexFromEnd,
 | |
|         StartingStringLookup,
 | |
|         ContainingStringLookup,
 | |
|     };
 | |
|     enum WordSelectorKind {
 | |
|         Index,
 | |
|         Last,
 | |
|     };
 | |
| 
 | |
|     struct {
 | |
|         EventKind kind { IndexFromStart };
 | |
|         size_t index { 0 };
 | |
|         Position text_position;
 | |
|         String text;
 | |
|     } event;
 | |
| 
 | |
|     struct WordSelector {
 | |
|         WordSelectorKind kind { Index };
 | |
|         size_t selector { 0 };
 | |
|         Position position;
 | |
|         RefPtr<AST::SyntaxError> syntax_error_node;
 | |
| 
 | |
|         size_t resolve(size_t size) const
 | |
|         {
 | |
|             if (kind == Index)
 | |
|                 return selector;
 | |
|             if (kind == Last)
 | |
|                 return size - selector - 1;
 | |
|             VERIFY_NOT_REACHED();
 | |
|         }
 | |
|     };
 | |
|     struct {
 | |
|         WordSelector start;
 | |
|         Optional<WordSelector> end;
 | |
|     } word_selector_range;
 | |
| };
 | |
| 
 | |
| class HistoryEvent final : public Node {
 | |
| public:
 | |
|     HistoryEvent(Position, HistorySelector);
 | |
|     virtual ~HistoryEvent();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     HistorySelector const& selector() const { return m_selector; }
 | |
| 
 | |
| private:
 | |
|     NODE(HistoryEvent);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
| 
 | |
|     HistorySelector m_selector;
 | |
| };
 | |
| 
 | |
| class Execute final : public Node {
 | |
| public:
 | |
|     Execute(Position, NonnullRefPtr<Node>, bool capture_stdout = false);
 | |
|     virtual ~Execute();
 | |
|     void capture_stdout() { m_capture_stdout = true; }
 | |
|     NonnullRefPtr<Node>& command() { return m_command; }
 | |
|     virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback) override;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& command() const { return m_command; }
 | |
|     bool does_capture_stdout() const { return m_capture_stdout; }
 | |
| 
 | |
| private:
 | |
|     NODE(Execute);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual bool is_execute() const override { return true; }
 | |
|     virtual bool would_execute() const override { return true; }
 | |
| 
 | |
|     NonnullRefPtr<Node> m_command;
 | |
|     bool m_capture_stdout { false };
 | |
| };
 | |
| 
 | |
| class IfCond final : public Node {
 | |
| public:
 | |
|     IfCond(Position, Optional<Position> else_position, NonnullRefPtr<AST::Node> cond_expr, RefPtr<AST::Node> true_branch, RefPtr<AST::Node> false_branch);
 | |
|     virtual ~IfCond();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& condition() const { return m_condition; }
 | |
|     RefPtr<Node> const& true_branch() const { return m_true_branch; }
 | |
|     RefPtr<Node> const& false_branch() const { return m_false_branch; }
 | |
|     RefPtr<Node>& false_branch() { return m_false_branch; }
 | |
|     Optional<Position> const else_position() const { return m_else_position; }
 | |
| 
 | |
| private:
 | |
|     NODE(IfCond);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool should_override_execution_in_current_process() const override { return true; }
 | |
| 
 | |
|     NonnullRefPtr<AST::Node> m_condition;
 | |
|     RefPtr<AST::Node> m_true_branch;
 | |
|     RefPtr<AST::Node> m_false_branch;
 | |
| 
 | |
|     Optional<Position> m_else_position;
 | |
| };
 | |
| 
 | |
| class ImmediateExpression final : public Node {
 | |
| public:
 | |
|     ImmediateExpression(Position, NameWithPosition function, Vector<NonnullRefPtr<AST::Node>> arguments, Optional<Position> closing_brace_position);
 | |
|     virtual ~ImmediateExpression();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     Vector<NonnullRefPtr<Node>> const& arguments() const { return m_arguments; }
 | |
|     auto const& function() const { return m_function; }
 | |
|     String const& function_name() const { return m_function.name; }
 | |
|     Position const& function_position() const { return m_function.position; }
 | |
|     bool has_closing_brace() const { return m_closing_brace_position.has_value(); }
 | |
| 
 | |
| private:
 | |
|     NODE(ImmediateExpression);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     Vector<NonnullRefPtr<AST::Node>> m_arguments;
 | |
|     NameWithPosition m_function;
 | |
|     Optional<Position> m_closing_brace_position;
 | |
| };
 | |
| 
 | |
| class Join final : public Node {
 | |
| public:
 | |
|     Join(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
 | |
|     virtual ~Join();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& left() const { return m_left; }
 | |
|     NonnullRefPtr<Node> const& right() const { return m_right; }
 | |
| 
 | |
| private:
 | |
|     NODE(Join);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_command() const override { return true; }
 | |
|     virtual bool is_list() const override { return true; }
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_left;
 | |
|     NonnullRefPtr<Node> m_right;
 | |
| };
 | |
| 
 | |
| struct MatchEntry {
 | |
|     Variant<Vector<NonnullRefPtr<Node>>, Vector<Regex<ECMA262>>> options;
 | |
|     Optional<Vector<String>> match_names;
 | |
|     Optional<Position> match_as_position;
 | |
|     Vector<Position> pipe_positions;
 | |
|     RefPtr<Node> body;
 | |
| };
 | |
| 
 | |
| class MatchExpr final : public Node {
 | |
| public:
 | |
|     MatchExpr(Position, NonnullRefPtr<Node> expr, String name, Optional<Position> as_position, Vector<MatchEntry> entries);
 | |
|     virtual ~MatchExpr();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& matched_expr() const { return m_matched_expr; }
 | |
|     String const& expr_name() const { return m_expr_name; }
 | |
|     Vector<MatchEntry> const& entries() const { return m_entries; }
 | |
|     Optional<Position> const& as_position() const { return m_as_position; }
 | |
| 
 | |
| private:
 | |
|     NODE(MatchExpr);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool would_execute() const override { return true; }
 | |
|     virtual bool should_override_execution_in_current_process() const override { return true; }
 | |
| 
 | |
|     NonnullRefPtr<Node> m_matched_expr;
 | |
|     String m_expr_name;
 | |
|     Optional<Position> m_as_position;
 | |
|     Vector<MatchEntry> m_entries;
 | |
| };
 | |
| 
 | |
| class Or final : public Node {
 | |
| public:
 | |
|     Or(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>, Position or_position);
 | |
|     virtual ~Or();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& left() const { return m_left; }
 | |
|     NonnullRefPtr<Node> const& right() const { return m_right; }
 | |
|     Position const& or_position() const { return m_or_position; }
 | |
| 
 | |
| private:
 | |
|     NODE(Or);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_left;
 | |
|     NonnullRefPtr<Node> m_right;
 | |
|     Position m_or_position;
 | |
| };
 | |
| 
 | |
| class Pipe final : public Node {
 | |
| public:
 | |
|     Pipe(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
 | |
|     virtual ~Pipe();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& left() const { return m_left; }
 | |
|     NonnullRefPtr<Node> const& right() const { return m_right; }
 | |
| 
 | |
| private:
 | |
|     NODE(Pipe);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_command() const override { return true; }
 | |
| 
 | |
|     NonnullRefPtr<Node> m_left;
 | |
|     NonnullRefPtr<Node> m_right;
 | |
| };
 | |
| 
 | |
| class Range final : public Node {
 | |
| public:
 | |
|     Range(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
 | |
|     virtual ~Range();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& start() const { return m_start; }
 | |
|     NonnullRefPtr<Node> const& end() const { return m_end; }
 | |
| 
 | |
| private:
 | |
|     NODE(Range);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_start;
 | |
|     NonnullRefPtr<Node> m_end;
 | |
| };
 | |
| 
 | |
| class ReadRedirection final : public PathRedirectionNode {
 | |
| public:
 | |
|     ReadRedirection(Position, int, NonnullRefPtr<Node>);
 | |
|     virtual ~ReadRedirection();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
| private:
 | |
|     NODE(ReadRedirection);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
| };
 | |
| 
 | |
| class ReadWriteRedirection final : public PathRedirectionNode {
 | |
| public:
 | |
|     ReadWriteRedirection(Position, int, NonnullRefPtr<Node>);
 | |
|     virtual ~ReadWriteRedirection();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
| private:
 | |
|     NODE(ReadWriteRedirection);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
| };
 | |
| 
 | |
| class Sequence final : public Node {
 | |
| public:
 | |
|     Sequence(Position, Vector<NonnullRefPtr<Node>>, Vector<Position> separator_positions);
 | |
|     virtual ~Sequence();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     Vector<NonnullRefPtr<Node>> const& entries() const { return m_entries; }
 | |
| 
 | |
|     Vector<Position> const& separator_positions() const { return m_separator_positions; }
 | |
| 
 | |
| private:
 | |
|     NODE(Sequence);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_list() const override { return true; }
 | |
|     virtual bool should_override_execution_in_current_process() const override { return true; }
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override;
 | |
| 
 | |
|     Vector<NonnullRefPtr<Node>> m_entries;
 | |
|     Vector<Position> m_separator_positions;
 | |
| };
 | |
| 
 | |
| class Subshell final : public Node {
 | |
| public:
 | |
|     Subshell(Position, RefPtr<Node> block);
 | |
|     virtual ~Subshell();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     RefPtr<Node> const& block() const { return m_block; }
 | |
| 
 | |
| private:
 | |
|     NODE(Subshell);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool would_execute() const override { return false; }
 | |
|     virtual bool should_override_execution_in_current_process() const override { return true; }
 | |
| 
 | |
|     RefPtr<AST::Node> m_block;
 | |
| };
 | |
| 
 | |
| class Slice final : public Node {
 | |
| public:
 | |
|     Slice(Position, NonnullRefPtr<AST::Node>);
 | |
|     virtual ~Slice() override;
 | |
| 
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<AST::Node> selector() const { return m_selector; }
 | |
| 
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
| protected:
 | |
|     NODE(Slice);
 | |
|     NonnullRefPtr<AST::Node> m_selector;
 | |
| };
 | |
| 
 | |
| class VariableNode : public Node {
 | |
| public:
 | |
|     VariableNode(Position position)
 | |
|         : Node(move(position))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     void set_slice(NonnullRefPtr<Slice>&& slice)
 | |
|     {
 | |
|         VERIFY(!m_slice);
 | |
|         m_slice = move(slice);
 | |
|         if (m_slice->is_syntax_error())
 | |
|             set_is_syntax_error(m_slice->syntax_error_node());
 | |
|     }
 | |
| 
 | |
|     Slice const* slice() const { return m_slice.ptr(); }
 | |
| 
 | |
| protected:
 | |
|     RefPtr<Slice> m_slice;
 | |
| };
 | |
| 
 | |
| class SimpleVariable final : public VariableNode {
 | |
| public:
 | |
|     SimpleVariable(Position, String);
 | |
|     virtual ~SimpleVariable();
 | |
| 
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
|     String const& name() const { return m_name; }
 | |
| 
 | |
| private:
 | |
|     NODE(SimpleVariable);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_simple_variable() const override { return true; }
 | |
| 
 | |
|     String m_name;
 | |
| };
 | |
| 
 | |
| class SpecialVariable final : public VariableNode {
 | |
| public:
 | |
|     SpecialVariable(Position, char);
 | |
|     virtual ~SpecialVariable();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     char name() const { return m_name; }
 | |
| 
 | |
| private:
 | |
|     NODE(SpecialVariable);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     char m_name { 0 };
 | |
| };
 | |
| 
 | |
| class Juxtaposition final : public Node {
 | |
| public:
 | |
|     enum class Mode {
 | |
|         ListExpand,
 | |
|         StringExpand,
 | |
|     };
 | |
|     Juxtaposition(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>, Mode = Mode::ListExpand);
 | |
|     virtual ~Juxtaposition();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& left() const { return m_left; }
 | |
|     NonnullRefPtr<Node> const& right() const { return m_right; }
 | |
| 
 | |
| private:
 | |
|     NODE(Juxtaposition);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_left;
 | |
|     NonnullRefPtr<Node> m_right;
 | |
|     Mode m_mode { Mode::ListExpand };
 | |
| };
 | |
| 
 | |
| class Heredoc final : public Node {
 | |
| public:
 | |
|     Heredoc(Position, String end, bool allow_interpolation, bool deindent, Optional<int> target_fd = {});
 | |
|     virtual ~Heredoc();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     String const& end() const { return m_end; }
 | |
|     bool allow_interpolation() const { return m_allows_interpolation; }
 | |
|     bool deindent() const { return m_deindent; }
 | |
|     Optional<int> target_fd() const { return m_target_fd; }
 | |
|     bool evaluates_to_string() const { return !m_target_fd.has_value(); }
 | |
|     RefPtr<AST::Node> const& contents() const { return m_contents; }
 | |
|     void set_contents(RefPtr<AST::Node> contents)
 | |
|     {
 | |
|         m_contents = move(contents);
 | |
|         if (m_contents->is_syntax_error())
 | |
|             set_is_syntax_error(m_contents->syntax_error_node());
 | |
|         else if (is_syntax_error())
 | |
|             clear_syntax_error();
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     NODE(Heredoc);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }
 | |
| 
 | |
|     String m_end;
 | |
|     bool m_allows_interpolation { false };
 | |
|     bool m_deindent { false };
 | |
|     Optional<int> m_target_fd;
 | |
|     RefPtr<AST::Node> m_contents;
 | |
| };
 | |
| 
 | |
| class StringLiteral final : public Node {
 | |
| public:
 | |
|     enum class EnclosureType {
 | |
|         None,
 | |
|         SingleQuotes,
 | |
|         DoubleQuotes,
 | |
|     };
 | |
| 
 | |
|     StringLiteral(Position, String, EnclosureType);
 | |
|     virtual ~StringLiteral();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     String const& text() const { return m_text; }
 | |
|     EnclosureType enclosure_type() const { return m_enclosure_type; }
 | |
| 
 | |
| private:
 | |
|     NODE(StringLiteral);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }
 | |
| 
 | |
|     String m_text;
 | |
|     EnclosureType m_enclosure_type;
 | |
| };
 | |
| 
 | |
| class StringPartCompose final : public Node {
 | |
| public:
 | |
|     StringPartCompose(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
 | |
|     virtual ~StringPartCompose();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     NonnullRefPtr<Node> const& left() const { return m_left; }
 | |
|     NonnullRefPtr<Node> const& right() const { return m_right; }
 | |
| 
 | |
| private:
 | |
|     NODE(StringPartCompose);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
| 
 | |
|     NonnullRefPtr<Node> m_left;
 | |
|     NonnullRefPtr<Node> m_right;
 | |
| };
 | |
| 
 | |
| class SyntaxError final : public Node {
 | |
| public:
 | |
|     SyntaxError(Position, String, bool is_continuable = false);
 | |
|     virtual ~SyntaxError();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     String const& error_text() const { return m_syntax_error_text; }
 | |
|     bool is_continuable() const { return m_is_continuable; }
 | |
| 
 | |
|     virtual void clear_syntax_error() override
 | |
|     {
 | |
|         m_is_cleared = true;
 | |
|     }
 | |
|     virtual void set_is_syntax_error(SyntaxError& error) override
 | |
|     {
 | |
|         m_position = error.position();
 | |
|         m_is_cleared = error.m_is_cleared;
 | |
|         m_is_continuable = error.m_is_continuable;
 | |
|         m_syntax_error_text = error.error_text();
 | |
|     }
 | |
| 
 | |
|     virtual bool is_syntax_error() const override { return !m_is_cleared; }
 | |
| 
 | |
| private:
 | |
|     NODE(SyntaxError);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override { return { nullptr, nullptr, nullptr }; }
 | |
|     virtual SyntaxError& syntax_error_node() override;
 | |
| 
 | |
|     String m_syntax_error_text;
 | |
|     bool m_is_continuable { false };
 | |
|     bool m_is_cleared { false };
 | |
| };
 | |
| 
 | |
| class SyntheticNode final : public Node {
 | |
| public:
 | |
|     SyntheticNode(Position, NonnullRefPtr<Value>);
 | |
|     virtual ~SyntheticNode() = default;
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     Value const& value() const { return m_value; }
 | |
| 
 | |
| private:
 | |
|     NODE(SyntheticValue);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
| 
 | |
|     NonnullRefPtr<Value> m_value;
 | |
| };
 | |
| 
 | |
| class Tilde final : public Node {
 | |
| public:
 | |
|     Tilde(Position, String);
 | |
|     virtual ~Tilde();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     String text() const;
 | |
| 
 | |
| private:
 | |
|     NODE(Tilde);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_tilde() const override { return true; }
 | |
| 
 | |
|     String m_username;
 | |
| };
 | |
| 
 | |
| class VariableDeclarations final : public Node {
 | |
| public:
 | |
|     struct Variable {
 | |
|         NonnullRefPtr<Node> name;
 | |
|         NonnullRefPtr<Node> value;
 | |
|     };
 | |
|     VariableDeclarations(Position, Vector<Variable> variables);
 | |
|     virtual ~VariableDeclarations();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
|     Vector<Variable> const& variables() const { return m_variables; }
 | |
| 
 | |
| private:
 | |
|     NODE(VariableDeclarations);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
|     virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
 | |
|     virtual HitTestResult hit_test_position(size_t) const override;
 | |
|     virtual bool is_variable_decls() const override { return true; }
 | |
| 
 | |
|     Vector<Variable> m_variables;
 | |
| };
 | |
| 
 | |
| class WriteAppendRedirection final : public PathRedirectionNode {
 | |
| public:
 | |
|     WriteAppendRedirection(Position, int, NonnullRefPtr<Node>);
 | |
|     virtual ~WriteAppendRedirection();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
| private:
 | |
|     NODE(WriteAppendRedirection);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
| };
 | |
| 
 | |
| class WriteRedirection final : public PathRedirectionNode {
 | |
| public:
 | |
|     WriteRedirection(Position, int, NonnullRefPtr<Node>);
 | |
|     virtual ~WriteRedirection();
 | |
|     virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
 | |
| 
 | |
| private:
 | |
|     NODE(WriteRedirection);
 | |
|     virtual ErrorOr<void> dump(int level) const override;
 | |
|     virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| namespace AK {
 | |
| 
 | |
| template<>
 | |
| struct Formatter<Shell::AST::Command> : StandardFormatter {
 | |
|     Formatter() = default;
 | |
|     explicit Formatter(StandardFormatter formatter)
 | |
|         : StandardFormatter(formatter)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     ErrorOr<void> format(FormatBuilder&, Shell::AST::Command const& value);
 | |
| };
 | |
| 
 | |
| }
 |