@@ -14,7 +14,6 @@ use nom::combinator::{eof, map};
1414use nom:: sequence:: terminated;
1515use notify:: { Event , EventKind , RecursiveMode , Watcher } ;
1616use rustc_hash:: { FxHashMap , FxHashSet } ;
17- use rustyline:: config:: Configurer ;
1817use rustyline:: error:: ReadlineError ;
1918use ustr:: { ustr, Ustr } ;
2019
@@ -50,7 +49,9 @@ lazy_static::lazy_static! {
5049 pub static ref LOADED_SET : Arc <Mutex <FxHashSet <PathBuf >>> = Arc :: new( Mutex :: new( FxHashSet :: default ( ) ) ) ;
5150}
5251
53- pub fn start_repl ( ) {
52+ pub mod editor;
53+
54+ pub fn start_repl < E : editor:: TermEditor > ( mut rl : E ) {
5455 let mut db = Database :: default ( ) ;
5556 let mut db2 = Database :: default ( ) ;
5657
@@ -130,10 +131,9 @@ project = "repl"
130131
131132 // `()` can be used when no completer is required
132133 let completer = REPLCompleter :: new ( & mut db2 as _ , mem_check) ;
133- let mut rl =
134- rustyline:: Editor :: < REPLCompleter , rustyline:: history:: FileHistory > :: new ( ) . unwrap ( ) ;
134+ // let mut rl =
135+ // rustyline::Editor::<REPLCompleter, rustyline::history::FileHistory>::new().unwrap();
135136 rl. set_helper ( Some ( completer) ) ;
136- rl. set_completion_type ( rustyline:: CompletionType :: Circular ) ;
137137 let _ = rl. load_history ( & PathBuf :: from ( & root) . join ( "history.txt" ) ) ;
138138
139139 loop {
@@ -151,6 +151,13 @@ project = "repl"
151151 if try_parse_commands ( & line)
152152 . map ( |repl| match repl. command {
153153 repl_cmd:: Commands :: Load { proj_path, _as } => {
154+ let proj_path = match crate :: utils:: canonicalize ( proj_path) {
155+ Ok ( p) => p,
156+ Err ( e) => {
157+ eprintln ! ( "Error: {:?}" , e) ;
158+ return ;
159+ }
160+ } ;
154161 if let ControlFlow :: Break ( _) =
155162 validate_proj_cfg ( & proj_path, & db2, & docs2)
156163 {
@@ -170,6 +177,13 @@ project = "repl"
170177 ) ;
171178 }
172179 repl_cmd:: Commands :: LoadDeps { proj_path } => {
180+ let proj_path = match crate :: utils:: canonicalize ( proj_path) {
181+ Ok ( p) => p,
182+ Err ( e) => {
183+ eprintln ! ( "Error: {:?}" , e) ;
184+ return ;
185+ }
186+ } ;
173187 match validate_proj_cfg ( & proj_path, & db2, & docs2) {
174188 ControlFlow :: Continue ( cfg) => {
175189 for ( as_name, path) in & cfg. deps . unwrap_or_default ( ) {
@@ -181,14 +195,57 @@ project = "repl"
181195 }
182196 repl_cmd:: Commands :: Reload { file_path } => {
183197 let file_path = file_path. to_str ( ) . unwrap ( ) ;
184- docs2. lock ( ) . unwrap ( ) . remove ( file_path) ;
185- docs. lock ( ) . unwrap ( ) . remove ( file_path) ;
198+ let file_path = match crate :: utils:: canonicalize ( file_path) {
199+ Ok ( p) => p. to_str ( ) . unwrap ( ) . to_owned ( ) ,
200+ Err ( e) => {
201+ eprintln ! ( "Error: {:?}" , e) ;
202+ return ;
203+ }
204+ } ;
205+ docs2. lock ( ) . unwrap ( ) . remove ( & file_path) ;
206+ docs. lock ( ) . unwrap ( ) . remove ( & file_path) ;
186207 }
187208 repl_cmd:: Commands :: Watch { dir } => {
209+ let dir = match crate :: utils:: canonicalize ( dir) {
210+ Ok ( p) => p. to_str ( ) . unwrap ( ) . to_owned ( ) ,
211+ Err ( e) => {
212+ eprintln ! ( "Error: {:?}" , e) ;
213+ return ;
214+ }
215+ } ;
188216 watcher
189217 . watch ( Path :: new ( & dir) , RecursiveMode :: Recursive )
190218 . expect ( "watch failed" ) ;
191219 }
220+ repl_cmd:: Commands :: Config => {
221+ let src = docs2. lock ( ) . unwrap ( ) ;
222+ let conf = src. get ( REPL_VIRTUAL_CONF ) . unwrap ( ) ;
223+ println ! ( "{}" , conf. text( & db2) ) ;
224+ }
225+ repl_cmd:: Commands :: Symbol => {
226+ let vars = REPL_VARIABLES . lock ( ) . unwrap ( ) ;
227+ let mut src = "" . to_string ( ) ;
228+ for ( k, _) in vars. iter ( ) {
229+ src. push_str ( & format ! ( "println!(\" {}: \" , {});\n " , k, k) ) ;
230+ }
231+ drop ( vars) ;
232+ let id =
233+ REPL_COUNTER . fetch_add ( 1 , std:: sync:: atomic:: Ordering :: SeqCst ) ;
234+ let anon_fn = format ! (
235+ "{}\n pub fn __anon__{}() void {{ \n {};\n return; }}" ,
236+ used_headers, id, src
237+ ) ;
238+ docs. lock ( )
239+ . unwrap ( )
240+ . get ( REPL_VIRTUAL_ENTRY )
241+ . unwrap ( )
242+ . set_text ( & mut db)
243+ . to ( anon_fn. clone ( ) ) ;
244+ mem. set_docs ( & mut db)
245+ . to ( Arc :: new ( Mutex :: new ( docs. lock ( ) . unwrap ( ) . clone ( ) ) ) ) ;
246+ let _ = compiler:: compile_dry ( & db, mem) . unwrap ( ) ;
247+ load_mod_and_evaluate ( & db, mem, & ctx) ;
248+ }
192249 } )
193250 . is_some ( )
194251 {
@@ -268,6 +325,10 @@ project = "repl"
268325 let mut errs_num = 0 ;
269326 let mut warn_num = 0 ;
270327 print_diags ( diags, mem_check, & db2, & mut errs_num, & mut warn_num, true ) ;
328+ #[ cfg( test) ]
329+ {
330+ rl. assert_err ( errs_num > 0 ) ;
331+ }
271332 if errs_num > 0 {
272333 REPL_COUNTER . fetch_sub ( 1 , std:: sync:: atomic:: Ordering :: SeqCst ) ;
273334 continue ;
@@ -300,55 +361,7 @@ project = "repl"
300361 . unwrap ( )
301362 . extend ( plmodule. global_table . clone ( ) ) ;
302363
303- let mods = compiler:: compile_dry:: accumulated :: < ModBuffer > ( & db, mem) ;
304-
305- for m in & mods {
306- if !m. name . starts_with ( "__anon__" ) {
307- if LOADED_SET . lock ( ) . unwrap ( ) . contains ( & m. path ) {
308- continue ;
309- }
310- unsafe {
311- let mo = Module :: parse_bitcode_from_buffer (
312- & MemoryBuffer :: create_from_memory_range (
313- & m. buf ,
314- m. path . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ,
315- ) ,
316- & ctx,
317- )
318- . unwrap ( ) ;
319- let p = mo. as_mut_ptr ( ) ;
320- mo. strip_debug_info ( ) ;
321- log:: trace!( "Loaded module, content:\n {}" , mo. to_string( ) ) ;
322- LOADED_SET . lock ( ) . unwrap ( ) . insert ( m. path . clone ( ) ) ;
323- immix:: AddModuleToOrcJIT ( p as _ ) ;
324- // Owned by the JIT now
325- std:: mem:: forget ( mo) ;
326-
327- log:: info!( "Loaded module: {:?}" , m. name) ;
328- } ;
329- }
330- }
331- for m in & mods {
332- if m. name . starts_with ( "__anon__" ) {
333- unsafe {
334- let m = Module :: parse_bitcode_from_buffer (
335- & MemoryBuffer :: create_from_memory_range (
336- & m. buf ,
337- m. path . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ,
338- ) ,
339- & ctx,
340- )
341- . unwrap ( ) ;
342-
343- let p = m. as_mut_ptr ( ) ;
344- m. strip_debug_info ( ) ;
345- log:: trace!( "Evaluate module, content:\n {}" , m. to_string( ) ) ;
346- immix:: RunExpr ( p as _ ) ;
347- // Owned by the JIT now
348- std:: mem:: forget ( m) ;
349- }
350- }
351- }
364+ load_mod_and_evaluate ( & db, mem, & ctx) ;
352365 }
353366 Err ( ReadlineError :: Interrupted ) => {
354367 println ! ( "CTRL-C" ) ;
@@ -368,6 +381,58 @@ project = "repl"
368381 // exit(0);
369382}
370383
384+ fn load_mod_and_evaluate ( db : & Database , mem : MemDocsInput , ctx : & Context ) {
385+ let mods = compiler:: compile_dry:: accumulated :: < ModBuffer > ( db, mem) ;
386+
387+ for m in & mods {
388+ if !m. name . starts_with ( "__anon__" ) {
389+ if LOADED_SET . lock ( ) . unwrap ( ) . contains ( & m. path ) {
390+ continue ;
391+ }
392+ unsafe {
393+ let mo = Module :: parse_bitcode_from_buffer (
394+ & MemoryBuffer :: create_from_memory_range (
395+ & m. buf ,
396+ m. path . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ,
397+ ) ,
398+ ctx,
399+ )
400+ . unwrap ( ) ;
401+ let p = mo. as_mut_ptr ( ) ;
402+ mo. strip_debug_info ( ) ;
403+ log:: trace!( "Loaded module, content:\n {}" , mo. to_string( ) ) ;
404+ LOADED_SET . lock ( ) . unwrap ( ) . insert ( m. path . clone ( ) ) ;
405+ immix:: AddModuleToOrcJIT ( p as _ ) ;
406+ // Owned by the JIT now
407+ std:: mem:: forget ( mo) ;
408+
409+ log:: info!( "Loaded module: {:?}" , m. name) ;
410+ } ;
411+ }
412+ }
413+ for m in & mods {
414+ if m. name . starts_with ( "__anon__" ) {
415+ unsafe {
416+ let m = Module :: parse_bitcode_from_buffer (
417+ & MemoryBuffer :: create_from_memory_range (
418+ & m. buf ,
419+ m. path . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ,
420+ ) ,
421+ ctx,
422+ )
423+ . unwrap ( ) ;
424+
425+ let p = m. as_mut_ptr ( ) ;
426+ m. strip_debug_info ( ) ;
427+ log:: trace!( "Evaluate module, content:\n {}" , m. to_string( ) ) ;
428+ immix:: RunExpr ( p as _ ) ;
429+ // Owned by the JIT now
430+ std:: mem:: forget ( m) ;
431+ }
432+ }
433+ }
434+ }
435+
371436fn validate_proj_cfg (
372437 proj_path : & PathBuf ,
373438 db2 : & Database ,
@@ -477,3 +542,6 @@ fn new_watcher(sender: Sender<PathBuf>) -> notify::RecommendedWatcher {
477542 } )
478543 . expect ( "create watcher failed" )
479544}
545+
546+ #[ cfg( test) ]
547+ mod test;
0 commit comments