Commit Graph

211 Commits

Author SHA1 Message Date
ridiculousfish
21e31c9b59 Remove C++ builtin test implementation
Now that builtin test is in Rust, remove the C++ bits.
2023-05-21 11:50:24 -07:00
Johannes Altmanninger
1df64a4891 Replace maybe_t::missing_or_empty with a more Rust-friendly helper
There are many places where we want to treat a missing variable the same as
a variable with an empty value.

In C++ we handle this by branching on maybe_t<env_var_t>::missing_or_empty().
If it returns false, we go on to access maybe_t<env_var_t>::value() aka
operator*.

In Rust, Environment::get() will return an Option<EnvVar>.
We could define a MissingOrEmpty trait and implement it for Option<EnvVar>.

However that will still leave us with ugly calls to Option::unwrap()
(by convention Rust does use shorthands like *).

Let's add a variable getter that returns none for empty variables.
2023-04-21 13:57:29 +02:00
Johannes Altmanninger
82a797db9c clang-format C++ builtins 2023-04-21 13:57:29 +02:00
Johannes Altmanninger
33f51b45e4 Tease apart parser.eval() overloads
The most common overload takes a string and an io chain so let that one keep
its name.
2023-04-21 13:57:29 +02:00
Johannes Altmanninger
6ede7f8009 Delete wcstring_list_t
We don't want it in Rust. Remove it to smoothen the transition.
2023-04-19 01:03:16 +02:00
Xiretza
aab2f660a7 Port math builtin, tinyexpr and wcstod_underscores to Rust 2023-04-16 22:26:46 +02:00
Johannes Altmanninger
971d257e67 Port AST to Rust
The translation is fairly direct though it adds some duplication, for example
there are multiple "match" statements that mimic function overloading.

Rust has no overloading, and we cannot have generic methods in the Node trait
(due to a Rust limitation, the error is like "cannot be made into an object")
so we include the type name in method names.

Give clients like "indent_visitor_t" a Rust companion ("IndentVisitor")
that takes care of the AST traversal while the AST consumption remains
in C++ for now.  In future, "IndentVisitor" should absorb the entirety of
"indent_visitor_t".  This pattern requires that "fish_indent" be exposed
includable header to the CXX bridge.

Alternatively, we could define FFI wrappers for recursive AST traversal.

Rust requires we separate the AST visitors for "mut" and "const"
scenarios. Take this opportunity to concretize both visitors:

The only client that requires mutable access is the populator.  To match the
structure of the C++ populator which makes heavy use of function overloading,
we need to add a bunch of functions to the trait. Since there is no other
mutable visit, this seems acceptable.

The "const" visitors never use "will_visit_fields_of()" or
"did_visit_fields_of()", so remove them (though this is debatable).

Like in the C++ implementation, the AST nodes themselves are largely defined
via macros.  Union fields like "Statement" and "ArgumentOrRedirection"
do currently not use macros but may in future.

This commit also introduces a precedent for a type that is defined in one
CXX bridge and used in another one - "ParseErrorList".  To make this work
we need to manually define "ExternType".

There is one annoyance with CXX: functions that take explicit lifetime
parameters require to be marked as unsafe. This makes little sense
because functions that return `&Foo` with implicit lifetime can be
misused the same way on the C++ side.

One notable change is that we cannot directly port "find_block_open_keyword()"
(which is used to compute an error) because it relies on the stack of visited
nodes. We cannot modify a stack of node references while we do the "mut"
walk. Happily, an idiomatic solution is easy: we can tell the AST visitor
to backtrack to the parent node and create the error there.

Since "node_t::accept_base" is no longer a template we don't need the
"node_visitation_t" trampoline anymore.

The added copying at the FFI boundary makes things slower (memcpy dominates
the profile) but it's not unusable, which is good news:

    $ hyperfine ./fish.{old,new}" -c 'source ../share/completions/git.fish'"
    Benchmark 1: ./fish.old -c 'source ../share/completions/git.fish'
      Time (mean ± σ):     195.5 ms ±   2.9 ms    [User: 190.1 ms, System: 4.4 ms]
      Range (min … max):   193.2 ms … 205.1 ms    15 runs

    Benchmark 2: ./fish.new -c 'source ../share/completions/git.fish'
      Time (mean ± σ):     677.5 ms ±  62.0 ms    [User: 665.4 ms, System: 10.0 ms]
      Range (min … max):   611.7 ms … 805.5 ms    10 runs

    Summary
      './fish.old -c 'source ../share/completions/git.fish'' ran
        3.47 ± 0.32 times faster than './fish.new -c 'source ../share/completions/git.fish''

Leftovers:
- Enum variants are still snakecase; I didn't get around to changing this yet.
- "ast_type_to_string()" still returns a snakecase name. This could be
  changed since  it's not user visible.
2023-04-16 17:46:56 +02:00
Johannes Altmanninger
a848877e65 Remove an overload in io, to prepare for Rust 2023-04-16 17:21:54 +02:00
Fabian Boehm
72a32f1a12 Rewrite "builtin" builtin in Rust
This is very simple and basically a subset of type.
2023-04-16 11:30:31 +02:00
Fabian Boehm
b65a53a2a6 Rewrite "command" builtin in Rust
This is basically a subset of type, so we might as well.

To be clear this is `command -s` and friends, if you do `command grep` that's
handled as a keyword.

One issue here is that we can't get "one path or not" because I don't
know how to translate a maybe_t? Do we need to make it a shared_ptr instead?
2023-04-16 11:27:08 +02:00
Fabian Boehm
662a4740e2 Rewrite the type builtin in rust 2023-04-16 11:27:08 +02:00
ridiculousfish
a487b1ecf2 Revert "Revert "Implement builtin_printf in Rust""
This reverts commit 9f7e6a6cd1.

Add additional fixes from code review.
2023-04-06 15:54:09 -07:00
Johannes Altmanninger
05bad5eda1 Port common.{h,cpp} to Rust
Most of it is duplicated, hence untested.

Functions like mbrtowc are not exposed by the libc crate, so declare them
ourselves.
Since we don't know the definition of C macros, add two big hacks to make
this work:
1. Replace MB_LEN_MAX and mbstate_t with values (resp types) that should
   be large enough for any implementation.
2. Detect the definition of MB_CUR_MAX in the build script. This requires
   more changes for each new libc. We could also use this approach for 1.

Additionally, this commit brings a small behavior change to
read_unquoted_escape(): we cannot decode surrogate code points like \UDE01
into a Rust char, so use � (\UFFFD, replacement character) instead.
Previously, we added such code points to a wcstring; looks like they were
ignored when printed.
2023-04-02 15:17:06 +02:00
ridiculousfish
9f7e6a6cd1 Revert "Implement builtin_printf in Rust"
This reverts PR #9666. This had outstanding review comments and should
not have been committed.
2023-03-27 22:03:30 -07:00
ridiculousfish
f096841e4d Remove C++ printf bits
This removes the builtin printf C++ implementation, as it is now in
Rust.
2023-03-26 17:40:24 -07:00
ridiculousfish
57f4571a01 Rewrite wait handles and wait handle store in Rust 2023-03-18 18:53:04 -07:00
Victor Song
ca494778e4 builtins: Port realpath to Rust 2023-03-12 19:50:35 -07:00
Victor Song
77fe9933e2 builtins: Rewrite pwd in Rust
Closes #9625.
2023-03-12 15:18:15 -05:00
Xiretza
9ac6cbefb1 Port event.cpp to rust
Port src/event.cpp to fish-rust/event.rs and some needed functions.

Co-authored-by: Mahmoud Al-Qudsi <mqudsi@neosmart.net>
2023-03-12 14:55:50 -05:00
Xiretza
dd7b177d72 builtins: set_color: remove unhandled -v/--version flag
Invoking `set_color -v` crashes fish.
2023-03-05 16:09:36 +01:00
Clemens Wasser
17c1fa9d64
Port bg builtin to Rust (#9621)
* bg: Port bg builtin to Rust
2023-02-28 16:42:12 -06:00
Clemens Wasser
6f5be9bae4 block: Port block builtin to Rust
Closes #9612.
2023-02-26 14:16:55 -06:00
Clemens Wasser
330e8a86c7 block: Use an integer to count blocks 2023-02-26 14:12:57 -06:00
Mahmoud Al-Qudsi
562eeac43e
Port job_group to rust (#9608)
More ugliness with types that cxx bridge can't recognize as being POD. Using
pointers to get/set `termios` values with an assert to make sure we're using
identical definitions on both sides (in cpp from the system headers and in rust
from the libc crate as exported).

I don't know why cxx bridge doesn't allow `SharedPtr<OpaqueRustType>` but we can
work around it in C++ by converting a `Box<T>` to a `shared_ptr<T>` then convert
it back when it needs to be destructed. I can't find a clean way of doing it
from the cxx bridge wrapper so for now it needs to be done manually in the C++
code.

Types/values that are drop-in ready over ffi are renamed to match the old cpp
names but for types that now differ due to ffi difficulties I've left the `_ffi`
in the function names to indicate that this isn't the "correct" way of using the
types/methods.
2023-02-25 16:42:45 -06:00
Neeraj Jaiswal
f52569a800 abbr: port abbreviation and abbr builtin to rust 2023-02-25 12:24:58 +01:00
Neeraj Jaiswal
3b60bc1de0 contains: port contains builtin to rust 2023-02-22 18:32:27 +01:00
Fabian Boehm
4fd1458d85 Port random to rust 2023-02-19 21:01:46 +01:00
ridiculousfish
27f5490a55 Merge branch 'riir'
This merges the Rust bits.
2023-02-19 08:57:47 -08:00
Neeraj Jaiswal
1adfce18ee builtins: port return/exit to rust 2023-02-18 18:53:40 +01:00
esdmr
a607421912
functions --copy: store file and lineno (#9542)
Keeps the location of original function definition, and also stores
where it was copied. `functions` and `type` show both locations,
instead of none. It also retains the line numbers in the stack trace.
2023-02-13 09:59:28 -06:00
Xiretza
5a76c7d3b1 Port emit builtin to rust 2023-02-11 15:04:57 +01:00
Johannes Altmanninger
39f3c894d7 Port tokenizer.cpp to Rust
In hindsight, I should probably have split this into three different commits.
2023-02-09 00:37:22 +01:00
Johannes Altmanninger
7f8d247211 Port parse_constants.h to Rust 2023-02-09 00:37:22 +01:00
Johannes Altmanninger
4639f7ec40 Follow Rust naming convention for some types
But don't do it for enum variants just yet.
2023-02-08 21:49:54 +01:00
Xiretza
a16e2ecb1b Port echo builtin to Rust 2023-02-07 22:25:47 +01:00
Johannes Altmanninger
83fd7ea7c4 Port future_feature_flags.cpp to Rust
This is early work but I guess there's no harm in pushing it?
Some thoughts on the conventions:

Types that live only inside Rust follow Rust naming convention
("FeatureMetadata").

Types that live on both sides of the language boundary follow the existing
naming ("feature_flag_t").
The alternative is to define a type alias ("using feature_flag_t =
rust::FeatureFlag") but that doesn't seem to be supported in "[cxx::bridge]"
blocks. We could put it in a header ("future_feature_flags.h").

"feature_metadata_t" is a variant of "FeatureMetadata" that can cross
the language boundary. This has the advantage that we can avoid tainting
"FeatureMetadata" with "CxxString" and such. This is an experimental approach,
probably not what we should do in general.
2023-02-03 18:55:06 +01:00
ridiculousfish
76adfed0e7 Implement builtin_wait in Rust
This implements builtin_wait in Rust.
2023-02-02 19:34:48 -07:00
ridiculousfish
d843b67d2d Initial Rust commit 2023-02-02 19:34:47 -07:00
Fabian Boehm
9043008933 abbr: Clarify universal variable message
And give explicit upgrade instructions.
2023-01-21 16:53:59 +01:00
Fabian Boehm
077118d983 abbr: Fix crash when no name has been given
This crashed for

```fish
abbr --add --regex '{\d+..\d+}' --function foo
```

i.e. a regex and a function but no name - that's 0 additional
arguments.
2023-01-15 10:50:09 +01:00
Fabian Boehm
da0c640750 abbr: Warn when -U is given
This prints a warning to stderr and then still does the thing.

Because of the error trailer, it points to the abbr help page.
2023-01-14 22:27:28 +01:00
Fabian Boehm
dad8c527e0 read: Error on read-only variables
Fixes #9346
2023-01-13 17:56:28 +01:00
Fabian Boehm
1b1cf73b60 abbr: Stop escaping the name for abbr --list
This is so we can pass it to `abbr --erase`.

Fixes #9470
2023-01-13 16:38:34 +01:00
Fabian Boehm
572a568268 abbr: Erase the old universal variable with abbr --erase
This means cleaning out old universal variables is now just:

```fish
abbr --erase (abbr --list)
```

which makes upgrading much easier.

Note that this erases the currently defined variable and/or any
universal. It doesn't stop at the former because that makes it *easy*
to remove the universals (no running `abbr --erase` twice), and it
doesn't care about globals because, well, they would be gone on
restart anyway.

Fixes #9468.
2023-01-13 16:09:53 +01:00
ridiculousfish
30c708e8a5 builtin_print_help to take its error argument by reference
This fixes a confusing use of pointers.
2022-12-31 10:13:03 -08:00
Fabian Boehm
4c39aeed87 abbr: Let --function use a mandatory argument
This now means `abbr --add` has two modes:

```fish
abbr --add name --function foo --regex regex
```

```fish
abbr --add name --regex regex replacement
```

This is because `--function` was seen to be confusing as a boolean flag.
2022-12-24 10:29:26 +01:00
Fabian Boehm
3005adebd5 Revert "Remove print_hints from builtin_missing_argument and builtin_unknown_option"
Unfortunately print_hints was true *by default* - so for all builtins
that didn't pass it it would now be false instead.

This resulted in the trailer missing, which includes the line number
and context. So if you ran a script that includes `bind -M` the error
message would now just be "bind: -M: option requires an argument",
with no indication as to where.

This reverts commit 8a50d47a46.
2022-12-22 17:24:47 +01:00
ridiculousfish
8a50d47a46 Remove print_hints from builtin_missing_argument and builtin_unknown_option
The print_hints variable was always false, so just remove it.

This caused a cascade of other changes where the parser_t variable
becomes unused, so remove it from the call sites.

No functional change expected here.
2022-12-19 15:05:51 -08:00
Fabian Boehm
bb98cb01c7 abbr: Also show --position
(if not the default)
2022-12-14 18:06:24 +01:00
Fabian Boehm
30a37d9433 abbr: Make show output actually work
This would print

```
abbr -a -- dotdot --regex ^\\.\\.+\$ --function multicd
```

which expands "dotdot" to "--regex ^\\.\\.+\$...".

Instead, we move the name to right before the replacement, and move
the `--` before that:

```
abbr -a --regex ^\\.\\.+\$ --function -- dotdot multicd
```

It might be possible to improve that, but this at least round-trips.
2022-12-13 19:38:58 +01:00