Commit Graph

428 Commits

Author SHA1 Message Date
Steven Fackler
0f2d46f396 Docify std::vec_ng
I also removed a couple of methods that were silly and added sort.
2014-03-18 22:03:17 -07:00
Eduard Burtescu
e2ebc8f811 Fix rustdoc and tests. 2014-03-17 09:55:41 +02:00
Eduard Burtescu
90cbe0cad2 De-@ ParseSess uses. 2014-03-17 09:53:07 +02:00
Alex Crichton
cc6ec8df95 log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:

* The crate map has always been a bit of a code smell among rust programs. It
  has difficulty being loaded on almost all platforms, and it's used almost
  exclusively for logging and only logging. Removing the crate map is one of the
  end goals of this movement.

* The compiler has a fair bit of special support for logging. It has the
  __log_level() expression as well as generating a global word per module
  specifying the log level. This is unfairly favoring the built-in logging
  system, and is much better done purely in libraries instead of the compiler
  itself.

* Initialization of logging is much easier to do if there is no reliance on a
  magical crate map being available to set module log levels.

* If the logging library can be written outside of the standard library, there's
  no reason that it shouldn't be. It's likely that we're not going to build the
  highest quality logging library of all time, so third-party libraries should
  be able to provide just as high-quality logging systems as the default one
  provided in the rust distribution.

With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:

* The core change of this migration is that there is no longer a physical
  log-level per module. This concept is still emulated (it is quite useful), but
  there is now only a global log level, not a local one. This global log level
  is a reflection of the maximum of all log levels specified. The previously
  generated logging code looked like:

    if specified_level <= __module_log_level() {
        println!(...)
    }

  The newly generated code looks like:

    if specified_level <= ::log::LOG_LEVEL {
        if ::log::module_enabled(module_path!()) {
            println!(...)
        }
    }

  Notably, the first layer of checking is still intended to be "super fast" in
  that it's just a load of a global word and a compare. The second layer of
  checking is executed to determine if the current module does indeed have
  logging turned on.

  This means that if any module has a debug log level turned on, all modules
  with debug log levels get a little bit slower (they all do more expensive
  dynamic checks to determine if they're turned on or not).

  Semantically, this migration brings no change in this respect, but
  runtime-wise, this will have a perf impact on some code.

* A `RUST_LOG=::help` directive will no longer print out a list of all modules
  that can be logged. This is because the crate map will no longer specify the
  log levels of all modules, so the list of modules is not known. Additionally,
  warnings can no longer be provided if a malformed logging directive was
  supplied.

The new "hello world" for logging looks like:

    #[phase(syntax, link)]
    extern crate log;

    fn main() {
        debug!("Hello, world!");
    }
2014-03-15 22:26:36 -07:00
Steven Fackler
eb4cbd55a8 Add an ItemModifier syntax extension type
Where ItemDecorator creates new items given a single item, ItemModifier
alters the tagged item in place. The expansion rules for this are a bit
weird, but I think are the most reasonable option available.

When an item is expanded, all ItemModifier attributes are stripped from
it and the item is folded through all ItemModifiers. At that point, the
process repeats until there are no ItemModifiers in the new item.
2014-03-11 00:28:25 -07:00
Liigo Zhuang
2271860af1 rename ast::ViewItemExternMod to ast::ViewItemExternCrate, and clean::ExternMod to clean::ExternCrate 2014-03-07 15:57:45 +08:00
Alex Crichton
0a84132928 syntax: Conditionally deriving(Hash) with Writers
If #[feature(default_type_parameters)] is enabled for a crate, then
deriving(Hash) will expand with Hash<W: Writer> instead of Hash<SipState> so
more hash algorithms can be used.
2014-03-06 18:11:02 -08:00
Edward Wang
2302ce903d Refactor and fix FIXME's in mtwt hygiene code
- Moves mtwt hygiene code into its own file
- Fixes FIXME's which leads to ~2x speed gain in expansion pass
- It is now @-free
2014-03-05 22:45:51 +08:00
Nick Cameron
4a891fe80d Expand nested items within a backtrace.
Fixes a regression from #4913 which causes items to be exanded with spans lacking expn_info from the context's current backtrace.
2014-03-04 18:04:16 -08:00
Steven Fackler
4c2353adee Make visible types public in rustc 2014-03-02 15:26:39 -08:00
Patrick Walton
198cc3d850 libsyntax: Fix errors arising from the automated ~[T] conversion 2014-03-01 22:40:52 -08:00
Patrick Walton
58fd6ab90d libsyntax: Mechanically change ~[T] to Vec<T> 2014-03-01 22:40:52 -08:00
Edward Wang
386db05df8 Make break and continue hygienic
Makes labelled loops hygiene by performing renaming of the labels
defined in e.g. `'x: loop { ... }` and then used in break and continue
statements within loop body so that they act hygienically when used with
macros.

Closes #12262.
2014-02-23 21:20:37 +08:00
Patrick Walton
33923f47e3 librustc: Remove unique vector patterns from the language.
Preparatory work for removing unique vectors from the language, which is
itself preparatory work for dynamically sized types.
2014-02-19 16:35:31 -08:00
Douglas Young
0bdfd0f4c7 Avoid returning original macro if expansion fails.
Closes #11692. Instead of returning the original expression, a dummy expression
(with identical span) is returned. This prevents infinite loops of failed
expansions as well as odd double error messages in certain situations.
2014-02-18 16:17:51 +00:00
Steven Fackler
07ea23e15d Expand ItemDecorator extensions in all contexts
Now that fold_item can return multiple items, this is pretty trivial. It
also recursively expands generated items so ItemDecorators can generate
items that are tagged with ItemDecorators!

Closes #4913
2014-02-14 07:48:00 -08:00
bors
18477ac68a auto merge of #12234 : sfackler/rust/restructure-item-decorator, r=huonw
The old method of building up a list of items and threading it through
all of the decorators was unwieldy and not really scalable as
non-deriving ItemDecorators become possible. The API is now that the
decorator gets an immutable reference to the item it's attached to, and
a callback that it can pass new items to. If we want to add syntax
extensions that can modify the item they're attached to, we can add that
later, but I think it'll have to be separate from ItemDecorator to avoid
strange ordering issues.

@huonw
2014-02-14 06:11:43 -08:00
Eduard Burtescu
a02b10a062 Refactored ast_map and friends, mainly to have Paths without storing them. 2014-02-14 08:43:29 +02:00
Steven Fackler
3c02749ad8 Tweak ItemDecorator API
The old method of building up a list of items and threading it through
all of the decorators was unwieldy and not really scalable as
non-deriving ItemDecorators become possible. The API is now that the
decorator gets an immutable reference to the item it's attached to, and
a callback that it can pass new items to. If we want to add syntax
extensions that can modify the item they're attached to, we can add that
later, but I think it'll have to be separate from ItemDecorator to avoid
strange ordering issues.
2014-02-13 21:53:06 -08:00
bors
89b1686bd7 auto merge of #12017 : FlaPer87/rust/replace-mod-crate, r=alexcrichton
The first setp for #9880 is to add a new `crate` keyword. This PR does exactly that. I took a chance to refactor `parse_item_foreign_mod` and I broke it down into 2 separate methods to isolate each feature.

The next step will be to push a new stage0 snapshot and then get rid of all `extern mod` around the code.
2014-02-13 16:32:01 -08:00
Steven Fackler
6b429d07c9 Stop unloading syntax libraries
Externally loaded libraries are able to do things that cause references
to them to survive past the expansion phase (e.g. creating @-box cycles,
launching a task or storing something in task local data). As such, the
library has to stay loaded for the lifetime of the process.
2014-02-13 12:50:24 -08:00
Flavio Percoco
968633b60a Replace crate usage with krate
This patch replaces all `crate` usage with `krate` before introducing the
new keyword. This ensures that after introducing the keyword, there
won't be any compilation errors.

krate might not be the most expressive substitution for crate but it's a
very close abbreviation for it. `module` was already used in several
places already.
2014-02-13 20:52:07 +01:00
Niko Matsakis
ec6d122826 libsyntax -- combine two iter ops into one so that fld does not need to be mutably shared between them both 2014-02-11 16:55:24 -05:00
Steven Fackler
ccd1cda10e Ignore #[phase] on use view items
Closes #11806
2014-02-10 20:10:17 -08:00
OGINO Masanori
e107121e34 Remove unnecessary parentheses.
Signed-off-by: OGINO Masanori <masanori.ogino@gmail.com>
2014-02-08 15:08:45 +09:00
OGINO Masanori
f7eb705248 Fix unused import warnings.
Signed-off-by: OGINO Masanori <masanori.ogino@gmail.com>
2014-02-08 15:08:44 +09:00
Eduard Burtescu
b2d30b72bf Removed @self and @Trait. 2014-02-07 00:38:33 +02:00
Seo Sanghyeon
5719ff73bf Fix expansion tests 2014-02-07 00:28:50 +09:00
Seo Sanghyeon
b653fa0c4a Avoid cloning ast::CrateConfig 2014-02-06 02:26:00 +09:00
Alex Crichton
2a7c5e0b72 syntax: Remove usage of io_error in tests 2014-02-03 09:32:35 -08:00
Patrick Walton
c594e675eb librustc: Remove @str from the language 2014-02-02 01:44:50 +11:00
Patrick Walton
875c9ce30b libsyntax: Remove many uses of token::ident_to_str 2014-02-02 01:44:49 +11:00
Patrick Walton
b890237e79 libsyntax: Fix tests. 2014-02-02 01:44:48 +11:00
Patrick Walton
c5cbfe89f8 librustc: De-@str NameAndSpan 2014-02-02 01:44:48 +11:00
Patrick Walton
a4dd3fe2f2 librustc: Fix merge fallout. 2014-02-02 01:44:48 +11:00
Patrick Walton
e68108b3e8 librustc: Stop using @str for source. 2014-02-02 01:44:48 +11:00
Patrick Walton
70c5a0fbf7 libsyntax: Introduce an InternedString type to reduce @str in the
compiler and use it for attributes
2014-02-02 01:44:47 +11:00
Salem Talha
cc61fc0994 Removed all instances of XXX in preparation for relaxing of FIXME rule 2014-01-26 14:42:53 -05:00
Steven Fackler
ab5bbd3c17 Simplify and rename macro API
Now that procedural macros can be implemented outside of the compiler,
it's more important to have a reasonable API to work with. Here are the
basic changes:

* Rename SyntaxExpanderTTTrait to MacroExpander, SyntaxExpanderTT to
    BasicMacroExpander, etc. I think "procedural macro" is the right
    term for these now, right? The other option would be SynExtExpander
    or something like that.

* Stop passing the SyntaxContext to extensions. This was only ever used
    by macro_rules, which doesn't even use it anymore. I can't think of
    a context in which an external extension would need it, and removal
    allows the API to be significantly simpler - no more
    SyntaxExpanderTTItemExpanderWithoutContext wrappers to worry about.
2014-01-25 13:55:39 -08:00
Steven Fackler
86a8b031f5 Move macro_rules! macros to libstd
They all have to go into a single module at the moment unfortunately.
Ideally, the logging macros would live in std::logging, condition! would
live in std::condition, format! in std::fmt, etc. However, this
introduces cyclic dependencies between those modules and the macros they
use which the current expansion system can't deal with. We may be able
to get around this by changing the expansion phase to a two-pass system
but that's for a later PR.

Closes #2247
cc #11763
2014-01-24 08:35:39 -08:00
Steven Fackler
d908e97da3 Redo exported macro serialization
The old method of serializing the AST gives totally bogus spans if the
expansion of an imported macro causes compilation errors. The best
solution seems to be to serialize the actual textual macro definition
and load it the same way the std-macros are. I'm not totally confident
that getting the source from the CodeMap will always do the right thing,
but it seems to work in simple cases.
2014-01-23 09:01:36 -08:00
Huon Wilson
39713b8295 Remove unnecessary parentheses. 2014-01-21 22:00:18 +11:00
bors
7c33df0dbb auto merge of #11644 : huonw/rust/less-fatality, r=cmr
This means that compilation continues for longer, and so we can see more
errors per compile. This is mildly more user-friendly because it stops
users having to run rustc n times to see n macro errors: just run it
once to see all of them.
2014-01-19 16:56:40 -08:00
Steven Fackler
1e20960f79 Actually force a / in the path for ext crates
If the library is in the working directory, its path won't have a "/"
which will cause dlopen to search /usr/lib etc. It turns out that Path
auto-normalizes during joins so Path::new(".").join(path) is actually a
no-op.
2014-01-17 21:51:38 -08:00
bors
4098327b1f auto merge of #11585 : nikomatsakis/rust/issue-3511-rvalue-lifetimes, r=pcwalton
Major changes:

- Define temporary scopes in a syntax-based way that basically defaults
  to the innermost statement or conditional block, except for in
  a `let` initializer, where we default to the innermost block. Rules
  are documented in the code, but not in the manual (yet).
  See new test run-pass/cleanup-value-scopes.rs for examples.
- Refactors Datum to better define cleanup roles.
- Refactor cleanup scopes to not be tied to basic blocks, permitting
  us to have a very large number of scopes (one per AST node).
- Introduce nascent documentation in trans/doc.rs covering datums and
  cleanup in a more comprehensive way.

r? @pcwalton
2014-01-17 07:56:45 -08:00
Huon Wilson
4be3262058 syntax::ext: replace span_fatal with span_err in many places.
This means that compilation continues for longer, and so we can see more
errors per compile. This is mildly more user-friendly because it stops
users having to run rustc n times to see n macro errors: just run it
once to see all of them.
2014-01-18 02:03:04 +11:00
Niko Matsakis
b1da8c618f Change expansion of for loop to use a match statement
so that the "innermost enclosing statement" used for rvalue
temporaries matches up with user expectations
2014-01-17 08:30:06 -05:00
Steven Fackler
328b47d837 Load macros from external modules 2014-01-16 15:01:48 -08:00
Patrick Walton
119c6141f5 librustc: Remove @ pointer patterns from the language 2014-01-13 14:45:21 -08:00
Brendan Zabarauskas
4fc0452ace Remove re-exports of std::io::stdio::{print, println} in the prelude.
The `print!` and `println!` macros are now the preferred method of printing, and so there is no reason to export the `stdio` functions in the prelude. The functions have also been replaced by their macro counterparts in the tutorial and other documentation so that newcomers don't get confused about what they should be using.
2014-01-11 10:46:00 +11:00
Eduard Burtescu
6b221768cf libsyntax: Renamed types, traits and enum variants to CamelCase. 2014-01-09 22:25:28 +02:00
Brendan Zabarauskas
ceea85a148 Remove ApproxEq and assert_approx_eq!
This trait seems to stray too far from the mandate of a standard library as implementations may vary between use cases.
2014-01-09 15:41:46 +11:00
Alex Crichton
0547fb9cad Fixup the rest of the tests in the compiler 2014-01-07 23:51:38 -08:00
bors
bae091e517 auto merge of #11332 : sfackler/rust/de-at-se, r=huonw
This is necessary for #11151 to make sure dtors run before the libraries
are unloaded.
2014-01-06 07:26:48 -08:00
Eduard Burtescu
3119d18e55 Disowned the Visitor. 2014-01-06 14:00:46 +02:00
Steven Fackler
bb49916d21 Use ~-objects instead of @-objects for syntax exts
This is necessary for #11151 to make sure dtors run before the libraries
are unloaded.
2014-01-05 18:02:57 -08:00
Patrick Walton
8092153634 libsyntax: Fix tests. 2014-01-03 22:22:40 -08:00
Patrick Walton
901df8a63b libsyntax: Remove unused MultiRenamer 2014-01-03 14:02:00 -08:00
Patrick Walton
6043957d8d libsyntax: De-@mut ps::boxes 2014-01-03 14:02:00 -08:00
Patrick Walton
ada9150abf libsyntax: Correctly de-@mut the pretty printer writer 2014-01-03 14:01:59 -08:00
Patrick Walton
be17a1b08c libsyntax: De-@mut SCTable::table 2014-01-03 14:01:59 -08:00
Patrick Walton
3aa19a6b86 librustc: De-@mut the parse session 2014-01-03 14:01:56 -08:00
bors
b9c39c6a27 auto merge of #11228 : sfackler/rust/syntaxenv, r=pcwalton
I'd really like to be able to do something like

```rust
struct MapChain<'next, K, V> {
    info: BlockInfo,
    map: HashMap<K, V>,
    next: Option<&'next mut MapChain<'next, K, V>
}
```

but I can't get the lifetimes to work out.
2014-01-03 04:32:07 -08:00
klutzy
9cdad685a3 syntax::codemap: Add static DUMMY_SP
It replaces `dummy_sp()`.
2014-01-01 19:51:35 +09:00
Steven Fackler
b74613bdc4 Rewrite SyntaxEnv
I'd really like to be able to do something like

struct MapChain<'next, K, V> {
    info: BlockInfo,
    map: HashMap<K, V>,
    next: Option<&'next mut MapChain<'next, K, V>
}

but I can't get the lifetimes to work out.
2013-12-30 17:50:05 -08:00
Steven Fackler
8143662836 Start passing around &mut ExtCtxt 2013-12-29 23:41:09 -08:00
Steven Fackler
3965dddf49 Make ast_fold take &mut self 2013-12-29 23:41:05 -08:00
Steven Fackler
933def408c Stop passing duplicate parameters in expand 2013-12-28 21:16:03 -07:00
Steven Fackler
0607c138ca Stop using @ExtCtxt 2013-12-28 21:16:03 -07:00
Alex Crichton
51abdee5f1 green: Rip the bandaid off, introduce libgreen
This extracts everything related to green scheduling from libstd and introduces
a new libgreen crate. This mostly involves deleting most of std::rt and moving
it to libgreen.

Along with the movement of code, this commit rearchitects many functions in the
scheduler in order to adapt to the fact that Local::take now *only* works on a
Task, not a scheduler. This mostly just involved threading the current green
task through in a few locations, but there were one or two spots where things
got hairy.

There are a few repercussions of this commit:

* tube/rc have been removed (the runtime implementation of rc)
* There is no longer a "single threaded" spawning mode for tasks. This is now
  encompassed by 1:1 scheduling + communication. Convenience methods have been
  introduced that are specific to libgreen to assist in the spawning of pools of
  schedulers.
2013-12-24 19:59:52 -08:00
Kiet Tran
c06dd0e0af Add dead-code warning pass 2013-12-08 02:55:27 -05:00
Huon Wilson
3ef933647a syntax: print expansion info from #[attribute] macros in the correct
format.

Previously, any attempt to use this information from inside something
like #[deriving(Foo)] would result in it printing like `deriving(Foo)!`.
2013-12-07 13:41:11 +11:00
Philipp Brüschweiler
a75f72d45a Add a macro to check if logging at a given label is enabled
This is useful when the information that is needed to do useful logging
is expensive to produce.
2013-12-02 21:47:57 +01:00
Eduard Burtescu
a9c4b18b18 Box Block, fn_decl, variant and Ty in the AST, as they were inflating critical enum sizes. 2013-12-01 00:00:39 +02:00
Alex Crichton
ab387a6838 Register new snapshots 2013-11-28 20:27:56 -08:00
Steven Fackler
c403c1f18e Clean up SmallVector use a bit 2013-11-26 13:56:02 -08:00
Steven Fackler
c144752a2d Support multiple item macros
Closes #4375
2013-11-26 13:56:02 -08:00
Patrick Walton
efc512362b libsyntax: Remove all non-proc do syntax. 2013-11-26 08:24:18 -08:00
Seo Sanghyeon
9028330f39 Take &Pat in visit_pat 2013-11-26 03:22:21 +09:00
Alex Crichton
dab8fec4af Forbid privacy in inner functions
Closes #10111
2013-11-17 21:28:18 -08:00
Alex Crichton
49ee49296b Move std::rt::io to std::io 2013-11-11 20:44:07 -08:00
Alex Crichton
7755ffd013 Remove #[fixed_stack_segment] and #[rust_stack]
These two attributes are no longer useful now that Rust has decided to leave
segmented stacks behind. It is assumed that the rust task's stack is always
large enough to make an FFI call (due to the stack being very large).

There's always the case of stack overflow, however, to consider. This does not
change the behavior of stack overflow in Rust. This is still normally triggered
by the __morestack function and aborts the whole process.

C stack overflow will continue to corrupt the stack, however (as it did before
this commit as well). The future improvement of a guard page at the end of every
rust stack is still unimplemented and is intended to be the mechanism through
which we attempt to detect C stack overflow.

Closes #8822
Closes #10155
2013-11-11 10:40:34 -08:00
Niko Matsakis
1f4faaee40 Generalize AST and ty::Generics to accept multiple lifetimes. 2013-11-08 19:42:46 -05:00
Alex Crichton
a49e65c2ed Implement a concat!() format extension
This extension can be used to concatenate string literals at compile time. C has
this useful ability when placing string literals lexically next to one another,
but this needs to be handled at the syntax extension level to recursively expand
macros.

The major use case for this is something like:

    macro_rules! mylog( ($fmt:expr $($arg:tt)*) => {
        error2!(concat!(file!(), ":", line!(), " - ", $fmt) $($arg)*);
    })

Where the mylog macro will automatically prepend the filename/line number to the
beginning of every log message.
2013-10-31 13:46:10 -07:00
Marvin Löbel
54f4dcd76a Prepared std::sys for removal, and made begin_unwind simpler
- `begin_unwind` is now generic over any `T: Any + Send`.
- Every value you fail with gets boxed as an `~Any`.
- Because of implementation details, `&'static str` and `~str` are still
  handled specially behind the scenes.
- Changed the big macro source string in libsyntax to a raw string
  literal, and enabled doc comments there.
2013-10-30 21:19:18 +01:00
Huon Wilson
17b87d2030 syntax: remove dead @mut Visitor impl (only used in tests).
Also, move some code only uses in the tests into the test module, and
replace some needless @mut ~[] with plain ~[].
2013-10-28 22:39:08 +11:00
Luqman Aden
12308db3d2 libsyntax/librustc: Allow mut qualifier in patterns. 2013-10-25 01:21:07 -04:00
Alex Crichton
61ed2cfb55 Remove even more of std::io
Big fish fried here:

    extra::json
    most of the compiler
    extra::io_util removed
    extra::fileinput removed

Fish left to fry

    extra::ebml
2013-10-24 14:21:57 -07:00
Alex Crichton
7aa32f7d8e Remove the now-duplicate logging macros 2013-10-22 08:09:56 -07:00
Alex Crichton
daf5f5a4d1 Drop the '2' suffix from logging macros
Who doesn't like a massive renaming?
2013-10-22 08:09:56 -07:00
Alex Crichton
df6225b8c3 Don't allocate a string when calling println
Instead use format_args! to pass around a struct to pass along into std::fmt
2013-10-20 15:42:24 -07:00
Alex Crichton
29c58c473f Remove the fmt! syntax extension
It lived a good life, but its time has come. The groundwork is set for the
official transition after the next snapshot (removal of XXX2 macros)
2013-10-18 16:01:40 -07:00
Alex Crichton
a84c2999c9 Require module documentation with missing_doc
Closes #9824
2013-10-15 22:27:10 -07:00
Steve Klabnik
16fc6a694c Remove unused abi attributes.
They've been replaced by putting the name on the extern block.

  #[abi = "foo"]

goes to

  extern "foo" { }

Closes #9483.
2013-10-14 13:10:36 +02:00
Daniel Micay
6a90e80b62 option: rewrite the API to use composition 2013-10-09 09:17:29 -04:00
Alex Crichton
de7d143176 Fix existing privacy/visibility violations
This commit fixes all of the fallout of the previous commit which is an attempt
to refine privacy. There were a few unfortunate leaks which now must be plugged,
and the most horrible one is the current `shouldnt_be_public` module now inside
`std::rt`. I think that this either needs a slight reorganization of the
runtime, or otherwise it needs to just wait for the external users of these
modules to get replaced with their `rt` implementations.

Other fixes involve making things pub which should be pub, and otherwise
updating error messages that now reference privacy instead of referencing an
"unresolved name" (yay!).
2013-10-07 13:00:52 -07:00
Alex Crichton
62855e2c08 Fix usage of the old debug! macros 2013-10-01 10:01:14 -07:00
Huon Wilson
6f166894ba Fix typo with format migration: s/oldformat/oldfmt/. 2013-10-01 19:45:17 +10:00
Alex Crichton
af3b132285 syntax: Remove usage of fmt! 2013-09-30 23:21:19 -07:00
Alex Crichton
aaf6cc3a84 Prevent leakage of fmt! into the compiler
We're not outright removing fmt! just yet, but this prevents it from leaking
into the compiler further (it's still turned on by default for all other code).
2013-09-30 23:21:18 -07:00