Skip to content

Commit

Permalink
add some basic ffi
Browse files Browse the repository at this point in the history
  • Loading branch information
kaiserthe13th committed May 29, 2022
1 parent 977a41f commit 7bb65d8
Show file tree
Hide file tree
Showing 13 changed files with 342 additions and 21 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ locale_config = "0.3"
rustyline = { version = "9.1.2", optional = true }
regex = { version = "1.5", optional = true }
lazy_static = { version = "1.4.0", optional = true }
dlopen = "0.1"
dyn-clonable = "0.9"

[features]
interactive = ["rustyline", "regex", "lazy_static"]
Expand Down
5 changes: 3 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use crate::util::{get_lang, SupportedLanguage};
use std::error;
use std::fmt;
use std::process::exit;
use serde::{Serialize, Deserialize};

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Position {
line: usize,
col: usize,
Expand All @@ -18,7 +19,7 @@ impl Position {
}
}

#[derive(Debug)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Error {
name: String,
explanation: String,
Expand Down
141 changes: 141 additions & 0 deletions src/ffi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use std::{error, any::Any};

use dyn_clonable::*;

use dlopen::symbor::Library;

use crate::{
mem::{StackMemory, HashMemory, Object},
runtime::Trace, error::Error,
};

pub fn load_library(name: &str, stack: &mut StackMemory, hashs: &mut HashMemory) -> Result<Library, Box<dyn error::Error>> {
let lib = Library::open(name)?;
let trl_init = unsafe { lib.symbol::<fn(&mut StackMemory, &mut HashMemory)>("trl_init")? };
trl_init(stack, hashs);
Ok(lib)
}

pub fn terminate_library(name: &str, lib: Library, stack: &mut StackMemory, hashs: &mut HashMemory) -> Result<(), Box<dyn error::Error>> {
let trl_term_s = unsafe { lib.symbol::<fn(&mut StackMemory, &mut HashMemory)>("trl_term") };
match trl_term_s {
Ok(trl_term) => {
trl_term(stack, hashs);
}
Err(dlopen::Error::SymbolGettingError(e)) if format!("{}", e) == format!("{}: undefined symbol: trl_term", name) => (),
Err(e) => {
return Err(Box::new(e));
}
}
Ok(())
}

#[clonable]
pub trait FfiObject: Clone + 'static {
fn repr(&self) -> String;
fn as_any(&'static self) -> &'static dyn Any where Self: Sized {
self
}
fn extract<T>(&'static self) -> Option<&T>
where
T: FfiObject + 'static,
Self: Sized
{
self.as_any().downcast_ref::<T>()
}
fn destroy(&mut self);

fn add(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn substract(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn multiply(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn divide(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn modulo(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}

fn equal(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn not_equal(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn greater(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn lesser(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn greater_eq(&self, o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
let gt = self.greater(o.clone(), trace)?;
let eq = self.equal(o, trace)?;
Ok(if matches!(gt, Object::Bool(true))
|| matches!(eq, Object::Bool(true)) {
Object::Bool(true)
} else { Object::Bool(false) })
}
fn lesser_eq(&self, o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
let gt = self.lesser(o.clone(), trace)?;
let eq = self.equal(o, trace)?;
Ok(if matches!(gt, Object::Bool(true))
|| matches!(eq, Object::Bool(true)) {
Object::Bool(true)
} else { Object::Bool(false) })
}
fn not(&self, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}

fn and(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}
fn or(&self, _o: Object, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new("DesteklenmeyenOperasyon", "operasyon desteklenmiyor", trace.clone(), None))
}

fn access(&self, s: String, trace: &Vec<Trace>) -> Result<Object, Error> {
Err(Error::new(
"BilinmeyenTanımlayıcı",
&format!(
"bilinmeyen değişken: `{}`, bu değişken bulunamamıştır",
s,
),
trace.clone(),
None,
))
}
}

#[derive(Clone)]
pub struct FfiFunction(pub Box<fn(&mut StackMemory, &mut HashMemory) -> Result<Option<Object>, Error>>);

impl FfiFunction {
pub fn call(&self, s: &mut StackMemory, h: &mut HashMemory) -> Result<Option<Object>, Error> {
self.fun()(s, h)
}
pub fn fun(&self) -> &Box<fn(&mut StackMemory, &mut HashMemory) -> Result<Option<Object>, Error>> {
&self.0
}
}

#[macro_export]
macro_rules! make_function {
($f:expr) => {
$crate::mem::Object::FfiFunction($crate::ffi::FfiFunction(Box::new($f)))
};
}

#[macro_export]
macro_rules! make_object {
($o:expr) => {
$crate::mem::Object::FfiObject(Box::new($o))
};
}

2 changes: 1 addition & 1 deletion src/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ impl Interactive {
None,
),
SupportedLanguage::English => Error::new(
"EditorError",
"EditörHatası",
&format!("{}", e),
vec![(self.line, 0, "<trli>".to_string(), None)],
None,
Expand Down
22 changes: 19 additions & 3 deletions src/lexer/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ impl Lexer {
} else {
path.set_file_name(next_token.lexeme);
}
let mut so_lookup = false;
let source = match read_file(&path) {
Ok(f) => {
tmp_visited.push(path.display().to_string());
Expand Down Expand Up @@ -106,6 +107,10 @@ impl Lexer {
}),
}
},
Err(FSErr::Other(std::io::ErrorKind::InvalidData)) => {
so_lookup = true;
"".to_string()
},
Err(e) => return Err(match get_lang() {
SupportedLanguage::Turkish => Error::new(
"DosyaHatası",
Expand All @@ -122,8 +127,19 @@ impl Lexer {
}),
};
if !in_vec(&path.display().to_string(), &visited.clone()) {
let mut nl = Lexer::new(source);
let res = nl.tokenize(visited, path.display().to_string());
let res = if !so_lookup {
let mut nl = Lexer::new(source);
nl.tokenize(visited, path.display().to_string())
} else {
Ok(vec![Token::new(
TokenType::LibSymbol(path.display().to_string()),
"".to_string(),
0,
0,
file.clone(),
Precedence::Reserved,
)])
};

let next_token = match prog.get(current + 2) {
Some(e) => e.clone(),
Expand Down Expand Up @@ -293,7 +309,7 @@ impl Lexer {
}
/// The tokenizer; it will try to tokenize the source code,
///
/// If it encounters errors it will send `Err(tr_lang::errwarn::Error)` back
/// If it encounters errors it will send `Err(tr_lang::error::Error)` back
pub fn tokenize(&mut self, visited: &mut Vec<String>, file: String) -> Result<Vec<Token>, Error> {
let mut tokens: Vec<Token> = vec![];

Expand Down
49 changes: 43 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
#![feature(io_error_more)]
#![feature(associated_type_defaults)]

//! tr-lang programming language is a language that aims to make programming simpler for
//! turkish speaking groups
pub mod lexer;
pub use lexer::Lexer;

pub mod parser;
pub use parser::Parser;

pub mod bytecode;
pub mod error;
pub mod mem;
Expand All @@ -17,8 +14,48 @@ pub mod token;
pub(crate) mod util;
#[cfg(feature = "fmt")]
pub mod fmt;

pub mod runtime;
pub use runtime::Run;
#[cfg(feature = "interactive")]
pub mod interactive;
pub mod ffi;

pub mod prelude {
use crate::*;

pub use lexer::Lexer;
pub use parser::Parser;
pub use runtime::Run;
pub use crate::ffi as tffi;
}

#[macro_export]
macro_rules! run {
($fl:expr; $($x:tt)*) => {
let mut buf = String::new();
$(
buf.push_str(stringify!($x));
buf.push(' ');
)*
let p = $crate::parser::Parser::from_lexer(&mut $crate::lexer::Lexer::new(buf), $fl)
.map(|mut a| a.parse().map(|b| $crate::runtime::Run::new(b).run($crate::runtime::RunConfig::default())));
};
($fl:ident; $($x:tt)*) => {
let mut buf = String::new();
$(
buf.push_str(stringify!($x));
buf.push(' ');
)*
let p = $crate::parser::Parser::from_lexer(&mut $crate::lexer::Lexer::new(buf), stringify!($fl).to_string())
.map(|mut a| a.parse().map(|b| $crate::runtime::Run::new(b).run($crate::runtime::RunConfig::default())));
};
($($x:tt)*) => {
let mut buf = String::new();
$(
buf.push_str(stringify!($x));
buf.push(' ');
)*
let p = $crate::parser::Parser::from_lexer(&mut $crate::lexer::Lexer::new(buf), "rust".to_string())
.map(|mut a| a.parse().map(|b| $crate::runtime::Run::new(b).run($crate::runtime::RunConfig::default())));
};
}

2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub mod error;
use error::Error;
pub mod runtime;

pub mod ffi;

mod argsparser;
#[cfg(feature = "interactive")]
mod interactive;
Expand Down
8 changes: 8 additions & 0 deletions src/mem/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ impl StackMemory {
}
s
}

pub fn destroy_ffi_objects(&mut self) {
for i in self.iter_vec().iter_mut() {
if let Object::FfiObject(o) = i {
o.destroy();
}
}
}
}

impl HashMemory {
Expand Down
Loading

0 comments on commit 7bb65d8

Please sign in to comment.