Skip to content

Commit

Permalink
Add ffi and repl features
Browse files Browse the repository at this point in the history
  • Loading branch information
Skallwar committed Dec 13, 2021
1 parent 31aa2ae commit be1191c
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 408 deletions.
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)
}
14 changes: 13 additions & 1 deletion 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 @@ -72,6 +73,7 @@ fn string_equals(ctx: &mut Context, args: Args) -> Option<ObjectInstance> {
}

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

Expand Down Expand Up @@ -131,6 +133,7 @@ impl Builtins {
builtins.add("__builtin_string_display_err", string_display_err);
builtins.add("__builtin_string_is_empty", string_is_empty);
builtins.add("__builtin_string_equals", string_equals);
#[cfg(feature = "ffi")]
builtins.add("__builtin_ffi_link_with", ffi_link_with);
builtins.add("__builtin_arg_get", arg_get);
builtins.add("__builtin_arg_amount", arg_amount);
Expand All @@ -156,7 +159,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 +174,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",
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

0 comments on commit be1191c

Please sign in to comment.