@@ -420,7 +420,7 @@ static jl_module_t *call_require(jl_sym_t *var)
420
420
// either:
421
421
// - sets *name and returns the module to import *name from
422
422
// - sets *name to NULL and returns a module to import
423
- static jl_module_t * eval_import_path (jl_module_t * from , jl_array_t * args , jl_sym_t * * name , const char * keyword )
423
+ static jl_module_t * eval_import_path (jl_module_t * where , jl_module_t * from , jl_array_t * args , jl_sym_t * * name , const char * keyword )
424
424
{
425
425
jl_sym_t * var = (jl_sym_t * )jl_array_ptr_ref (args , 0 );
426
426
size_t i = 1 ;
@@ -429,7 +429,11 @@ static jl_module_t *eval_import_path(jl_module_t *from, jl_array_t *args, jl_sym
429
429
if (!jl_is_symbol (var ))
430
430
jl_type_error (keyword , (jl_value_t * )jl_sym_type , (jl_value_t * )var );
431
431
432
- if (var != dot_sym ) {
432
+ if (from != NULL ) {
433
+ m = from ;
434
+ i = 0 ;
435
+ }
436
+ else if (var != dot_sym ) {
433
437
// `A.B`: call the loader to obtain the root A in the current environment.
434
438
if (jl_core_module && var == jl_core_module -> name ) {
435
439
m = jl_core_module ;
@@ -445,7 +449,7 @@ static jl_module_t *eval_import_path(jl_module_t *from, jl_array_t *args, jl_sym
445
449
}
446
450
else {
447
451
// `.A.B.C`: strip off leading dots by following parent links
448
- m = from ;
452
+ m = where ;
449
453
while (1 ) {
450
454
if (i >= jl_array_len (args ))
451
455
jl_error ("invalid module path" );
@@ -461,6 +465,8 @@ static jl_module_t *eval_import_path(jl_module_t *from, jl_array_t *args, jl_sym
461
465
var = (jl_sym_t * )jl_array_ptr_ref (args , i );
462
466
if (!jl_is_symbol (var ))
463
467
jl_type_error (keyword , (jl_value_t * )jl_sym_type , (jl_value_t * )var );
468
+ if (var == dot_sym )
469
+ jl_errorf ("invalid %s path: \".\" in identifier path" , keyword );
464
470
if (i == jl_array_len (args )- 1 )
465
471
break ;
466
472
m = (jl_module_t * )jl_eval_global_var (m , var );
@@ -522,6 +528,31 @@ static jl_module_t *deprecation_replacement_module(jl_module_t *parent, jl_sym_t
522
528
return NULL ;
523
529
}
524
530
531
+ // in `import A.B: x, y, ...`, evaluate the `A.B` part if it exists
532
+ static jl_module_t * eval_import_from (jl_module_t * m , jl_expr_t * ex , const char * keyword )
533
+ {
534
+ if (jl_expr_nargs (ex ) == 1 && jl_is_expr (jl_exprarg (ex , 0 ))) {
535
+ jl_expr_t * fr = (jl_expr_t * )jl_exprarg (ex , 0 );
536
+ if (fr -> head == colon_sym ) {
537
+ if (jl_expr_nargs (fr ) > 0 && jl_is_expr (jl_exprarg (fr , 0 ))) {
538
+ jl_expr_t * path = (jl_expr_t * )jl_exprarg (fr , 0 );
539
+ if (((jl_expr_t * )path )-> head == dot_sym ) {
540
+ jl_sym_t * name = NULL ;
541
+ jl_module_t * from = eval_import_path (m , NULL , path -> args , & name , "import" );
542
+ if (name != NULL ) {
543
+ from = (jl_module_t * )jl_eval_global_var (from , name );
544
+ if (!jl_is_module (from ))
545
+ jl_errorf ("invalid %s path: \"%s\" does not name a module" , keyword , jl_symbol_name (name ));
546
+ }
547
+ return from ;
548
+ }
549
+ }
550
+ jl_errorf ("malformed \"%s:\" expression" , keyword );
551
+ }
552
+ }
553
+ return NULL ;
554
+ }
555
+
525
556
static jl_code_info_t * expr_to_code_info (jl_value_t * expr )
526
557
{
527
558
jl_code_info_t * src = jl_new_code_info_uninit ();
@@ -569,50 +600,86 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int e
569
600
jl_sym_t * name = NULL ;
570
601
jl_depwarn ("`importall` is deprecated, use `using` or individual `import` statements instead" ,
571
602
(jl_value_t * )jl_symbol ("importall" ));
572
- jl_module_t * import = eval_import_path (m , ex -> args , & name , "importall" );
573
- if (name != NULL ) {
574
- import = (jl_module_t * )jl_eval_global_var (import , name );
575
- if (!jl_is_module (import ))
576
- jl_errorf ("invalid %s statement: name exists but does not refer to a module" , jl_symbol_name (ex -> head ));
603
+ jl_module_t * from = eval_import_from (m , ex , "importall" );
604
+ size_t i = 0 ;
605
+ if (from ) {
606
+ i = 1 ;
607
+ ex = (jl_expr_t * )jl_exprarg (ex , 0 );
608
+ }
609
+ for (; i < jl_expr_nargs (ex ); i ++ ) {
610
+ jl_value_t * a = jl_exprarg (ex , i );
611
+ if (jl_is_expr (a ) && ((jl_expr_t * )a )-> head == dot_sym ) {
612
+ name = NULL ;
613
+ jl_module_t * import = eval_import_path (m , from , ((jl_expr_t * )a )-> args , & name , "importall" );
614
+ if (name != NULL ) {
615
+ import = (jl_module_t * )jl_eval_global_var (import , name );
616
+ if (!jl_is_module (import ))
617
+ jl_errorf ("invalid %s statement: name exists but does not refer to a module" , jl_symbol_name (ex -> head ));
618
+ }
619
+ jl_module_importall (m , import );
620
+ }
577
621
}
578
- jl_module_importall (m , import );
579
622
return jl_nothing ;
580
623
}
581
624
else if (ex -> head == using_sym ) {
582
625
jl_sym_t * name = NULL ;
583
- jl_module_t * import = eval_import_path (m , ex -> args , & name , "using" );
584
- jl_module_t * u = import ;
585
- if (name != NULL )
586
- u = (jl_module_t * )jl_eval_global_var (import , name );
587
- if (jl_is_module (u )) {
588
- jl_module_using (m , u );
589
- if (m == jl_main_module && name == NULL ) {
590
- // TODO: for now, `using A` in Main also creates an explicit binding for `A`
591
- // This will possibly be extended to all modules.
592
- import_module (m , u );
593
- }
626
+ jl_module_t * from = eval_import_from (m , ex , "using" );
627
+ size_t i = 0 ;
628
+ if (from ) {
629
+ i = 1 ;
630
+ ex = (jl_expr_t * )jl_exprarg (ex , 0 );
594
631
}
595
- else {
596
- jl_module_t * replacement = deprecation_replacement_module (import , name );
597
- if (replacement )
598
- jl_module_using (m , replacement );
599
- else
600
- jl_module_use (m , import , name );
632
+ for (; i < jl_expr_nargs (ex ); i ++ ) {
633
+ jl_value_t * a = jl_exprarg (ex , i );
634
+ if (jl_is_expr (a ) && ((jl_expr_t * )a )-> head == dot_sym ) {
635
+ name = NULL ;
636
+ jl_module_t * import = eval_import_path (m , from , ((jl_expr_t * )a )-> args , & name , "using" );
637
+ jl_module_t * u = import ;
638
+ if (name != NULL )
639
+ u = (jl_module_t * )jl_eval_global_var (import , name );
640
+ if (jl_is_module (u )) {
641
+ jl_module_using (m , u );
642
+ if (m == jl_main_module && name == NULL ) {
643
+ // TODO: for now, `using A` in Main also creates an explicit binding for `A`
644
+ // This will possibly be extended to all modules.
645
+ import_module (m , u );
646
+ }
647
+ }
648
+ else {
649
+ jl_module_t * replacement = deprecation_replacement_module (import , name );
650
+ if (replacement )
651
+ jl_module_using (m , replacement );
652
+ else
653
+ jl_module_use (m , import , name );
654
+ }
655
+ }
601
656
}
602
657
return jl_nothing ;
603
658
}
604
659
else if (ex -> head == import_sym ) {
605
660
jl_sym_t * name = NULL ;
606
- jl_module_t * import = eval_import_path (m , ex -> args , & name , "import" );
607
- if (name == NULL ) {
608
- import_module (m , import );
661
+ jl_module_t * from = eval_import_from (m , ex , "import" );
662
+ size_t i = 0 ;
663
+ if (from ) {
664
+ i = 1 ;
665
+ ex = (jl_expr_t * )jl_exprarg (ex , 0 );
609
666
}
610
- else {
611
- jl_module_t * replacement = deprecation_replacement_module (import , name );
612
- if (replacement )
613
- import_module (m , replacement );
614
- else
615
- jl_module_import (m , import , name );
667
+ for (; i < jl_expr_nargs (ex ); i ++ ) {
668
+ jl_value_t * a = jl_exprarg (ex , i );
669
+ if (jl_is_expr (a ) && ((jl_expr_t * )a )-> head == dot_sym ) {
670
+ name = NULL ;
671
+ jl_module_t * import = eval_import_path (m , from , ((jl_expr_t * )a )-> args , & name , "import" );
672
+ if (name == NULL ) {
673
+ import_module (m , import );
674
+ }
675
+ else {
676
+ jl_module_t * replacement = deprecation_replacement_module (import , name );
677
+ if (replacement )
678
+ import_module (m , replacement );
679
+ else
680
+ jl_module_import (m , import , name );
681
+ }
682
+ }
616
683
}
617
684
return jl_nothing ;
618
685
}
0 commit comments