Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ffi and repl features #430

Merged
merged 2 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
406 changes: 1 addition & 405 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@ repository = "https://github.com/cohenarthur/jinko"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html


[dependencies]
structopt = "0.3"
colored = "2.0"
nom = "7.0"
linefeed = "0.6"
linefeed = { version = "0.6", optional = true }
downcast-rs = "1.2"
anyhow = "1.0"
libloading = "0.7"
libloading = { version = "0.7", optional = true }
lazy_static = "1.4"

[features]
default = ["repl", "ffi"]
repl = ["linefeed"]
ffi = ["libloading"]

[dev-dependencies]
libc = "0.2"

Expand Down
12 changes: 12 additions & 0 deletions interpreter/jinko.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// FIXME: Add #![warn(missing_docs)]

mod args;
#[cfg(feature = "repl")]
mod repl;

use colored::Colorize;
Expand All @@ -10,6 +11,7 @@ use jinko::{
};

use args::Args;
#[cfg(feature = "repl")]
use repl::Repl;
use std::{fs, path::Path};

Expand Down Expand Up @@ -105,7 +107,10 @@ fn handle_input(args: &Args, file: &Path) -> InteractResult {

match args.test() {
false => match args.interactive() {
#[cfg(feature = "repl")]
true => Repl::new()?.with_context(ctx).launch(),
#[cfg(not(feature = "repl"))]
true => panic!("Jinko is not compiled with repl support"),
false => {
let res = ctx.execute()?;
ctx.emit_errors();
Expand All @@ -132,10 +137,17 @@ fn main() -> anyhow::Result<()> {
jinko::log::enable();
}

#[cfg(feature = "repl")]
let result = args.input().map_or_else(
|| Repl::new()?.launch(),
|filename| handle_input(&args, filename),
)?;

#[cfg(not(feature = "repl"))]
let result = args
.input()
.map(|filename| handle_input(&args, filename))
.unwrap()?;

handle_exit_code(result.0)
}
34 changes: 29 additions & 5 deletions src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::collections::HashMap;
use std::path::PathBuf;

#[cfg(feature = "ffi")]
use crate::ffi;
use crate::instance::{FromObjectInstance, ToObjectInstance};
use crate::{Context, Instruction, JkBool, JkInt, JkString, ObjectInstance};
Expand Down Expand Up @@ -73,13 +74,27 @@ fn string_equals(ctx: &mut Context, args: Args) -> Option<ObjectInstance> {

/// Link with a given library at runtime
fn ffi_link_with(ctx: &mut Context, args: Args) -> Option<ObjectInstance> {
let lib_path = JkString::from_instance(&args[0].execute(ctx).unwrap()).0;
#[cfg(feature = "ffi")]
{
let lib_path = JkString::from_instance(&args[0].execute(ctx).unwrap()).0;

if let Err(e) = ffi::link_with(ctx, PathBuf::from(&lib_path)) {
ctx.error(e.with_msg(format!("couldn't link with library `{}`", &lib_path)));
if let Err(e) = ffi::link_with(ctx, PathBuf::from(&lib_path)) {
ctx.error(e.with_msg(format!("couldn't link with library `{}`", &lib_path)));
}

None
}

None
#[cfg(not(feature = "ffi"))]
{
use crate::{ErrKind, Error};

ctx.error(Error::new(ErrKind::Context).with_msg(format!(
"Jinko is not compiled with FFI support. `t_call_invalid_builtin` is disable"
Skallwar marked this conversation as resolved.
Show resolved Hide resolved
)));

None
}
}

// Get an argument from the argument vector at a certain index
Expand Down Expand Up @@ -156,7 +171,7 @@ impl Default for Builtins {

#[cfg(test)]
mod tests {
use crate::jinko;
use crate::{jinko, jinko_fail};

#[test]
fn t_string_builtins_are_valid() {
Expand All @@ -171,12 +186,21 @@ mod tests {
}

#[test]
#[cfg(feature = "ffi")]
fn t_ffi_builtins_are_valid() {
jinko! {
__builtin_ffi_link_with("tests/fixtures/clib/lib.so");
};
}

#[test]
#[cfg(not(feature = "ffi"))]
fn t_ffi_builtins_are_valid_no_ffi() {
jinko_fail! {
__builtin_ffi_link_with("tests/fixtures/clib/lib.so");
};
}

#[test]
fn t_args_builtins_are_valid() {
jinko! {
Expand Down
4 changes: 4 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub struct Context {
included: HashSet<PathBuf>,

/// External libraries to use via FFI
#[cfg(feature = "ffi")]
external_libs: Vec<libloading::Library>,

/// Errors being kept by the context
Expand Down Expand Up @@ -91,6 +92,7 @@ impl Context {
builtins: Builtins::new(),
tests: HashMap::new(),
included: HashSet::new(),
#[cfg(feature = "ffi")]
external_libs: Vec::new(),
error_handler: ErrorHandler::default(),
};
Expand Down Expand Up @@ -324,11 +326,13 @@ impl Context {
}

/// Add a library to the interpreter
#[cfg(feature = "ffi")]
pub fn add_lib(&mut self, lib: libloading::Library) {
self.external_libs.push(lib)
}

/// Get a reference on all shared libraries loaded in the interpreter
#[cfg(feature = "ffi")]
pub fn libs(&self) -> &Vec<libloading::Library> {
&self.external_libs
}
Expand Down
1 change: 1 addition & 0 deletions src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ impl Display for Error {
}
}

#[cfg(feature = "ffi")]
impl std::convert::From<libloading::Error> for Error {
fn from(e: libloading::Error) -> Self {
Error::new(ErrKind::ExternFunc).with_msg(e.to_string())
Expand Down
10 changes: 10 additions & 0 deletions src/instruction/function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,23 @@ impl FunctionCall {
}
}
} else {
#[cfg(feature = "ffi")]
match crate::ffi::execute(dec, self, ctx) {
Ok(value) => value,
Err(e) => {
ctx.error(e);
None
}
}

#[cfg(not(feature = "ffi"))]
{
ctx.error(Error::new(ErrKind::Context).with_msg(format!(
"Jinko is not compiled with FFI support. Cannot call `{}` external function",
Skallwar marked this conversation as resolved.
Show resolved Hide resolved
dec.name()
)));
None
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod builtins;
mod context;
mod error;
#[cfg(feature = "ffi")]
mod ffi;
mod indent;
pub mod instance;
Expand Down