Skip to content

Commit

Permalink
Merge pull request #107 from calcit-lang/program-global
Browse files Browse the repository at this point in the history
refactor to put program_code_data at global
  • Loading branch information
soyaine authored Oct 19, 2021
2 parents 7d3b5a0 + a5838cf commit df2bc44
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 307 deletions.
49 changes: 20 additions & 29 deletions src/bin/cr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,28 +87,32 @@ fn main() -> Result<(), String> {
snapshot.files.insert(k.to_owned(), v.to_owned());
}

let mut program_code = program::extract_program_data(&snapshot)?;
// now global states
{
let mut prgm = { program::PROGRAM_CODE_DATA.write().unwrap() };
*prgm = program::extract_program_data(&snapshot)?;
}

let check_warnings: &RefCell<Vec<String>> = &RefCell::new(vec![]);

// make sure builtin classes are touched
runner::preprocess::preprocess_ns_def(
calcit_runner::primes::CORE_NS,
calcit_runner::primes::BUILTIN_CLASSES_ENTRY,
&program_code,
calcit_runner::primes::BUILTIN_CLASSES_ENTRY,
None,
check_warnings,
)
.map_err(|e| e.msg)?;

let task = if settings.emit_js {
run_codegen(init_fn, reload_fn, &program_code, &settings.emit_path, false)
run_codegen(init_fn, reload_fn, &settings.emit_path, false)
} else if settings.emit_ir {
run_codegen(init_fn, reload_fn, &program_code, &settings.emit_path, true)
run_codegen(init_fn, reload_fn, &settings.emit_path, true)
} else {
let started_time = Instant::now();

let v = calcit_runner::run_program(init_fn, im::vector![], &program_code).map_err(|e| {
let v = calcit_runner::run_program(init_fn, im::vector![]).map_err(|e| {
for w in e.warnings {
println!("{}", w);
}
Expand Down Expand Up @@ -173,21 +177,17 @@ fn main() -> Result<(), String> {
println!("failed re-compiling, got empty inc file");
continue;
}
recall_program(&mut program_code, &content, init_fn, reload_fn, &settings)?;
recall_program(&content, init_fn, reload_fn, &settings)?;
}
}
} else {
Ok(())
}
}

fn recall_program(
program_code: &mut program::ProgramCodeData,
content: &str,
init_fn: &str,
reload_fn: &str,
settings: &ProgramSettings,
) -> Result<(), String> {
// overwrite previous state

fn recall_program(content: &str, init_fn: &str, reload_fn: &str, settings: &ProgramSettings) -> Result<(), String> {
println!("\n-------- file change --------\n");
call_stack::clear_stack();

Expand All @@ -201,21 +201,21 @@ fn recall_program(

// println!("\ndata: {}", &data);
// println!("\nchanges: {:?}", changes);
let new_code = program::apply_code_changes(program_code, &changes)?;
program::apply_code_changes(&changes)?;
// println!("\nprogram code: {:?}", new_code);

// clear data in evaled states
program::clear_all_program_evaled_defs(init_fn, reload_fn, settings.reload_libs)?;
builtins::meta::force_reset_gensym_index()?;

let task = if settings.emit_js {
run_codegen(init_fn, reload_fn, &new_code, &settings.emit_path, false)
run_codegen(init_fn, reload_fn, &settings.emit_path, false)
} else if settings.emit_ir {
run_codegen(init_fn, reload_fn, &new_code, &settings.emit_path, true)
run_codegen(init_fn, reload_fn, &settings.emit_path, true)
} else {
// run from `reload_fn` after reload
let started_time = Instant::now();
let v = calcit_runner::run_program(reload_fn, im::vector![], &new_code).map_err(|e| {
let v = calcit_runner::run_program(reload_fn, im::vector![]).map_err(|e| {
for w in e.warnings {
println!("{}", w);
}
Expand All @@ -233,19 +233,10 @@ fn recall_program(
}
}

// overwrite previous state
*program_code = new_code;

Ok(())
}

fn run_codegen(
init_fn: &str,
reload_fn: &str,
program_code: &program::ProgramCodeData,
emit_path: &str,
ir_mode: bool,
) -> Result<(), String> {
fn run_codegen(init_fn: &str, reload_fn: &str, emit_path: &str, ir_mode: bool) -> Result<(), String> {
let started_time = Instant::now();

let (init_ns, init_def) = util::string::extract_ns_def(init_fn)?;
Expand All @@ -267,7 +258,7 @@ fn run_codegen(
let check_warnings: &RefCell<Vec<String>> = &RefCell::new(vec![]);

// preprocess to init
match runner::preprocess::preprocess_ns_def(&init_ns, &init_def, program_code, &init_def, None, check_warnings) {
match runner::preprocess::preprocess_ns_def(&init_ns, &init_def, &init_def, None, check_warnings) {
Ok(_) => (),
Err(failure) => {
println!("\nfailed preprocessing, {}", failure);
Expand All @@ -285,7 +276,7 @@ fn run_codegen(
}

// preprocess to reload
match runner::preprocess::preprocess_ns_def(&reload_ns, &reload_def, program_code, &init_def, None, check_warnings) {
match runner::preprocess::preprocess_ns_def(&reload_ns, &reload_def, &init_def, None, check_warnings) {
Ok(_) => (),
Err(failure) => {
println!("\nfailed preprocessing, {}", failure);
Expand Down
67 changes: 66 additions & 1 deletion src/bin/injection/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::runner;
use cirru_edn::Edn;
use std::thread;

use calcit_runner::{
builtins,
Expand All @@ -13,11 +15,12 @@ pub fn inject_platform_apis() {
builtins::register_import_proc("&call-dylib-edn", call_dylib_edn);
builtins::register_import_proc("echo", echo);
builtins::register_import_proc("println", echo);
builtins::register_import_proc("&callback-dylib-edn", callback_dylib_edn);
}

// &call-dylib-edn
pub fn call_dylib_edn(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
if xs.is_empty() {
if xs.len() < 2 {
return Err(CalcitErr::use_string(format!(
"&call-dylib-edn expected >2 arguments, got {}",
CrListWrap(xs.to_owned())
Expand Down Expand Up @@ -63,3 +66,65 @@ pub fn echo(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
println!("{}", s);
Ok(Calcit::Nil)
}

// &call-dylib-edn

pub fn callback_dylib_edn(xs: &CalcitItems) -> Result<Calcit, CalcitErr> {
if xs.len() < 3 {
return Err(CalcitErr::use_string(format!(
"&callback-dylib-edn expected >3 arguments, got {}",
CrListWrap(xs.to_owned())
)));
}

let lib_name = if let Calcit::Str(s) = &xs[0] {
s.to_owned()
} else {
return Err(CalcitErr::use_string(format!("&call-dylib-edn expected a lib_name, got {}", xs[0])));
};

let method: String = if let Calcit::Str(s) = &xs[1] {
s.to_owned()
} else {
return Err(CalcitErr::use_string(format!(
"&call-dylib-edn expected a method name, got {}",
xs[1]
)));
};
let mut ys: Vec<Edn> = vec![];
let callback = xs[xs.len() - 1].clone();
for (idx, v) in xs.iter().enumerate() {
if idx > 1 && idx < xs.len() - 1 {
ys.push(calcit_to_edn(v).map_err(CalcitErr::use_string)?);
}
}
if let Calcit::Fn(..) = callback {
} else {
return Err(CalcitErr::use_string(format!(
"expected last argument to be callback fn, got: {}",
callback
)));
}

let result = unsafe {
let lib = libloading::Library::new(&lib_name).expect("dylib not found");
let func: libloading::Symbol<EdnFfi> = lib.get(method.as_bytes()).expect("dy function not found");
let ret = func(ys.to_owned()).map_err(CalcitErr::use_string)?;
edn_to_calcit(&ret)
};

if let Calcit::Fn(_, def_ns, _, def_scope, args, body) = callback {
let handle = thread::spawn(move || {
let r = runner::run_fn(&im::vector![result], &def_scope, &args, &body, &def_ns);
println!("callback {:?}", r);
});

handle.join().unwrap();
Ok(Calcit::Nil)
} else {
return Err(CalcitErr::use_string(format!(
"expected last argument to be callback fn, got: {}",
callback
)));
}
}
44 changes: 19 additions & 25 deletions src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use std::collections::HashMap;
use std::sync::RwLock;

use crate::primes::{Calcit, CalcitErr, CalcitItems, CalcitScope, CalcitSyntax};
use crate::program::ProgramCodeData;

pub type FnType = fn(xs: &CalcitItems) -> Result<Calcit, CalcitErr>;
pub type SyntaxType = fn(expr: &CalcitItems, scope: &CalcitScope, file_ns: &str) -> Result<Calcit, CalcitErr>;

lazy_static! {
static ref IMPORTED_PROCS: RwLock<HashMap<String, FnType>> = RwLock::new(HashMap::new());
Expand Down Expand Up @@ -365,32 +365,26 @@ pub fn register_import_proc(name: &str, f: FnType) {
(*ps).insert(name.to_owned(), f);
}

pub fn handle_syntax(
name: &CalcitSyntax,
nodes: &CalcitItems,
scope: &CalcitScope,
file_ns: &str,
program: &ProgramCodeData,
) -> Result<Calcit, CalcitErr> {
pub fn handle_syntax(name: &CalcitSyntax, nodes: &CalcitItems, scope: &CalcitScope, file_ns: &str) -> Result<Calcit, CalcitErr> {
match name {
CalcitSyntax::Defn => syntax::defn(nodes, scope, file_ns, program),
CalcitSyntax::Eval => syntax::eval(nodes, scope, file_ns, program),
CalcitSyntax::Defmacro => syntax::defmacro(nodes, scope, file_ns, program),
CalcitSyntax::Quote => syntax::quote(nodes, scope, file_ns, program),
CalcitSyntax::Quasiquote => syntax::quasiquote(nodes, scope, file_ns, program),
CalcitSyntax::If => syntax::syntax_if(nodes, scope, file_ns, program),
CalcitSyntax::CoreLet => syntax::syntax_let(nodes, scope, file_ns, program),
CalcitSyntax::Foldl => lists::foldl(nodes, scope, file_ns, program),
CalcitSyntax::FoldlShortcut => lists::foldl_shortcut(nodes, scope, file_ns, program),
CalcitSyntax::FoldrShortcut => lists::foldr_shortcut(nodes, scope, file_ns, program),
CalcitSyntax::Macroexpand => syntax::macroexpand(nodes, scope, file_ns, program),
CalcitSyntax::Macroexpand1 => syntax::macroexpand_1(nodes, scope, file_ns, program),
CalcitSyntax::MacroexpandAll => syntax::macroexpand_all(nodes, scope, file_ns, program),
CalcitSyntax::Try => syntax::call_try(nodes, scope, file_ns, program),
CalcitSyntax::Sort => lists::sort(nodes, scope, file_ns, program),
CalcitSyntax::Defn => syntax::defn(nodes, scope, file_ns),
CalcitSyntax::Eval => syntax::eval(nodes, scope, file_ns),
CalcitSyntax::Defmacro => syntax::defmacro(nodes, scope, file_ns),
CalcitSyntax::Quote => syntax::quote(nodes, scope, file_ns),
CalcitSyntax::Quasiquote => syntax::quasiquote(nodes, scope, file_ns),
CalcitSyntax::If => syntax::syntax_if(nodes, scope, file_ns),
CalcitSyntax::CoreLet => syntax::syntax_let(nodes, scope, file_ns),
CalcitSyntax::Foldl => lists::foldl(nodes, scope, file_ns),
CalcitSyntax::FoldlShortcut => lists::foldl_shortcut(nodes, scope, file_ns),
CalcitSyntax::FoldrShortcut => lists::foldr_shortcut(nodes, scope, file_ns),
CalcitSyntax::Macroexpand => syntax::macroexpand(nodes, scope, file_ns),
CalcitSyntax::Macroexpand1 => syntax::macroexpand_1(nodes, scope, file_ns),
CalcitSyntax::MacroexpandAll => syntax::macroexpand_all(nodes, scope, file_ns),
CalcitSyntax::Try => syntax::call_try(nodes, scope, file_ns),
CalcitSyntax::Sort => lists::sort(nodes, scope, file_ns),
// "define reference" although it uses a confusing name "atom"
CalcitSyntax::Defatom => refs::defatom(nodes, scope, file_ns, program),
CalcitSyntax::Reset => refs::reset_bang(nodes, scope, file_ns, program),
CalcitSyntax::Defatom => refs::defatom(nodes, scope, file_ns),
CalcitSyntax::Reset => refs::reset_bang(nodes, scope, file_ns),
// different behavoirs, in Rust interpreter it's nil, in js codegen it's nothing
CalcitSyntax::HintFn => meta::no_op(),
}
Expand Down
Loading

0 comments on commit df2bc44

Please sign in to comment.