1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![warn(missing_docs, intra_doc_link_resolution_failure)]
#![warn(missing_debug_implementations)]
#![warn(rust_2018_idioms)]

//! Artichoke Ruby
//!
//! This crate is a Rust and Ruby implementation of the [Ruby programming
//! language][rubylang]. Artichoke is not production-ready, but intends to be a
//! [MRI-compliant][rubyspec] implementation of Ruby 2.6.3.
//!
//! This crate provides:
//!
//! - An embeddable Ruby interpreter, which can be created with the
//!   [`interpreter`] function.
//! - A Rust and Ruby implementation of Ruby Core and Standard Library using
//!   high-quality Rust dependencies and modern Ruby.
//! - Support for injecting Rust code and types into the interpreter with a
//!   rubygems-style [`File`](backend::prelude::core::File) API.
//! - The ability to disable parts of the interpreter VM or library functions at
//!   compile time. For example, deny access to the system environ by disabling
//!   the `core-env-system` feature.
//!
//! ## Usage
//!
//! You can create an interpreter and begin executing code on it:
//!
//! ```
//! # use artichoke::prelude::core::*;
//! # use artichoke::prelude::*;
//! # fn main() -> Result<(), Exception> {
//! let mut interp = artichoke::interpreter()?;
//! let result = interp.eval(b"2 + 5")?;
//! # Ok(())
//! # }
//! ```
//!
//! Artichoke supports calling Ruby functions from Rust and converting between
//! Ruby boxed values and Rust native types:
//!
//! ```
//! # use artichoke::prelude::core::*;
//! # use artichoke::prelude::*;
//! # fn main() -> Result<(), Exception> {
//! let mut interp = artichoke::interpreter()?;
//! let s = interp.convert_mut("💎");
//! let codepoint = s.funcall(&mut interp, "ord", &[] /* args */, None /* block */)?;
//! let codepoint = codepoint.try_into::<u32>(&interp)?;
//! assert_eq!(128142, codepoint);
//! # Ok(())
//! # }
//! ```
//!
//! ## Crate Features
//!
//! - `core-env-system` - **Enabled** by default. This activates the `std::env`
//!   backend for the [`ENV` object][core-obj-env]. When this feature is
//!   disabled, access to the environ is emulated with an in-memory store.
//! - `core-math-extra` - **Enabled** by default. This enables additional
//!   dependencies to implement some functions in the
//!   [`Math` module][core-mod-math].  When this feature is disabled, these
//!   functions raise `NotImplementedError`.
//! - `core-random` - **Enabled** by default. This includes an implementation of
//!   the [`Random` class][core-class-random]. This feature includes additional
//!   dependencies. When this feature is disabled, Artichoke does not have
//!   support for generating psuedorandom numbers.
//! - `stdlib-securerandom` - **Enabled** by default. This feature includes an
//!   implementation of a CSPRNG for the
//!   [`SecureRandom` module][stdlib-mod-securerandom]. This feature includes
//!   additional dependencies.  When this feature is disabled, the
//!   `SecureRandom` module is not present.
//!
//! [rubylang]: https://www.ruby-lang.org/
//! [rubyspec]: https://github.com/ruby/spec
//! [core-obj-env]: https://ruby-doc.org/core-2.6.3/ENV.html
//! [core-mod-math]: https://ruby-doc.org/core-2.6.3/Math.html
//! [core-class-random]: https://ruby-doc.org/core-2.6.3/Random.html
//! [stdlib-mod-securerandom]: https://ruby-doc.org/stdlib-2.6.3/libdoc/securerandom/rdoc/SecureRandom.html

#![doc(html_root_url = "https://docs.rs/artichoke/0.1.0-pre.0")]
#![doc(html_favicon_url = "https://www.artichokeruby.org/favicon.ico")]
#![doc(html_logo_url = "https://www.artichokeruby.org/artichoke-logo.svg")]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");
#[cfg(doctest)]
doc_comment::doctest!("../artichoke-backend/README.md");
#[cfg(doctest)]
doc_comment::doctest!("../artichoke-core/README.md");
#[cfg(doctest)]
doc_comment::doctest!("../spec-runner/README.md");

pub use artichoke_backend as backend;

pub mod backtrace;
pub mod parser;
pub mod repl;
pub mod ruby;

/// A "prelude" for users of the `artichoke-backend` crate.
///
/// This prelude is similar to the standard library's prelude in that you'll
/// almost always want to import its entire contents, but unlike the standard
/// library's prelude, you'll have to do so manually:
///
/// ```
/// use artichoke::prelude::*;
/// ```
///
/// The prelude may grow over time as additional items see ubiquitous use.
pub mod prelude {
    pub use artichoke_backend::prelude::*;

    pub use crate::interpreter;
}

pub use artichoke_backend::{Artichoke, Exception};

/// Create a new Artichoke Ruby interpreter.
///
/// # Errors
///
/// If the underlying Artichoke VM backend cannot be initialized, an error is
/// returned.
///
/// If Artichoke Ruby Core or Standard Library cannot be initialized, an error
/// is returned.
pub fn interpreter() -> Result<Artichoke, Exception> {
    let release = prelude::ReleaseMetadata::new()
        .with_ruby_copyright(env!("RUBY_COPYRIGHT"))
        .with_ruby_description(env!("RUBY_DESCRIPTION"))
        .with_ruby_engine_version(env!("CARGO_PKG_VERSION"))
        .with_ruby_patchlevel("0")
        .with_ruby_platform(env!("RUBY_PLATFORM"))
        .with_ruby_release_date(env!("RUBY_RELEASE_DATE"))
        .with_ruby_revision(env!("RUBY_REVISION"))
        .with_ruby_version("2.6.3") // Artichoke targets MRI Ruby 2.6.3
        .with_artichoke_compiler_version(Some(env!("ARTICHOKE_COMPILER_VERSION")));
    artichoke_backend::interpreter_with_config(release)
}