@@ -424,6 +424,7 @@ impl<'ctx> Evaluator<'ctx> {
424
424
for i in 0 ..scopes_len {
425
425
let index = scopes_len - i - 1 ;
426
426
let variables = & scopes[ index] . variables ;
427
+
427
428
if let Some ( var) = variables. get ( name) {
428
429
// Closure vars, 2 denotes the builtin scope and the global scope, here is a closure scope.
429
430
result = if let Some ( lambda_ctx) = self . last_lambda_ctx ( ) {
@@ -458,6 +459,81 @@ impl<'ctx> Evaluator<'ctx> {
458
459
}
459
460
}
460
461
462
+ fn get_variable_in_pkgpath_from_last_scope ( & self , name : & str , pkgpath : & str ) -> ValueRef {
463
+ let pkg_scopes = self . pkg_scopes . borrow ( ) ;
464
+ let pkgpath =
465
+ if !pkgpath. starts_with ( kclvm_runtime:: PKG_PATH_PREFIX ) && pkgpath != MAIN_PKG_PATH {
466
+ format ! ( "{}{}" , kclvm_runtime:: PKG_PATH_PREFIX , pkgpath)
467
+ } else {
468
+ pkgpath. to_string ( )
469
+ } ;
470
+ let mut result = self . undefined_value ( ) ;
471
+ // System module
472
+ if builtin:: STANDARD_SYSTEM_MODULE_NAMES_WITH_AT . contains ( & pkgpath. as_str ( ) ) {
473
+ let pkgpath = & pkgpath[ 1 ..] ;
474
+
475
+ if pkgpath == builtin:: system_module:: UNITS
476
+ && builtin:: system_module:: UNITS_FIELD_NAMES . contains ( & name)
477
+ {
478
+ let value_float: f64 = kclvm_runtime:: f64_unit_value ( name) ;
479
+ let value_int: u64 = kclvm_runtime:: u64_unit_value ( name) ;
480
+ if value_int != 1 {
481
+ self . int_value ( value_int as i64 )
482
+ } else {
483
+ self . float_value ( value_float)
484
+ }
485
+ } else {
486
+ let func_name = format ! (
487
+ "{}{}_{}" ,
488
+ builtin:: KCL_SYSTEM_MODULE_MANGLE_PREFIX ,
489
+ pkgpath,
490
+ name
491
+ ) ;
492
+ let function_ptr = _kclvm_get_fn_ptr_by_name ( & func_name) ;
493
+ self . function_value_with_ptr ( function_ptr)
494
+ }
495
+ }
496
+ // Plugin pkgpath
497
+ else if pkgpath. starts_with ( plugin:: PLUGIN_PREFIX_WITH_AT ) {
498
+ // Strip the @kcl_plugin to kcl_plugin.
499
+ let name = format ! ( "{}.{}" , & pkgpath[ 1 ..] , name) ;
500
+ ValueRef :: func ( 0 , 0 , self . undefined_value ( ) , & name, "" , true )
501
+ // User pkgpath
502
+ } else {
503
+ // Global or local variables.
504
+ let scopes = pkg_scopes
505
+ . get ( & pkgpath)
506
+ . unwrap_or_else ( || panic ! ( "package {} is not found" , pkgpath) ) ;
507
+ // Scopes 0 is builtin scope, Scopes 1 is the global scope, Scopes 2~ are the local scopes
508
+ let scopes_len = scopes. len ( ) ;
509
+
510
+ let index = scopes_len - 1 ;
511
+ let variables = & scopes[ index] . variables ;
512
+
513
+ if let Some ( var) = variables. get ( name) {
514
+ // Closure vars, 2 denotes the builtin scope and the global scope, here is a closure scope.
515
+ result = if let Some ( lambda_ctx) = self . last_lambda_ctx ( ) {
516
+ let last_lambda_scope = lambda_ctx. level ;
517
+ // Local scope variable or lambda closure variable.
518
+ let ignore = if let Some ( ( start, end) ) = self . scope_covers . borrow ( ) . last ( ) {
519
+ * start <= index && index <= * end
520
+ } else {
521
+ false
522
+ } ;
523
+ if index >= last_lambda_scope && !ignore {
524
+ var. clone ( )
525
+ } else {
526
+ lambda_ctx. closure . get ( name) . unwrap_or ( var) . clone ( )
527
+ }
528
+ } else {
529
+ // Not in the lambda, maybe a local variable.
530
+ var. clone ( )
531
+ } ;
532
+ }
533
+ result
534
+ }
535
+ }
536
+
461
537
/// Get closure map in the current inner scope.
462
538
pub ( crate ) fn get_current_closure_map ( & self ) -> ClosureMap {
463
539
// Get variable map in the current scope.
@@ -571,7 +647,45 @@ impl<'ctx> Evaluator<'ctx> {
571
647
{
572
648
match self . resolve_variable_level ( name) {
573
649
// Closure variable or local variables
574
- Some ( level) if level > GLOBAL_LEVEL => self . get_variable ( name) ,
650
+ Some ( level) if level > GLOBAL_LEVEL => {
651
+ let ctx_stack = self . ctx_stack . borrow ( ) ;
652
+ let mut result = self . undefined_value ( ) ;
653
+ let mut found = false ;
654
+ for i in 0 ..ctx_stack. len ( ) {
655
+ let index = ctx_stack. len ( ) - i - 1 ;
656
+ match & ctx_stack[ index] {
657
+ crate :: LambdaOrSchemaEvalContext :: Schema ( _) => {
658
+ let res = self . get_variable_in_schema_or_rule ( name) ;
659
+
660
+ if !res. is_undefined ( ) {
661
+ result = res;
662
+ found = true ;
663
+ break ;
664
+ }
665
+ }
666
+ crate :: LambdaOrSchemaEvalContext :: Lambda ( _) => {
667
+ let current_pkgpath = self . current_pkgpath ( ) ;
668
+ let res = self . get_variable_in_pkgpath_from_last_scope (
669
+ name,
670
+ & current_pkgpath,
671
+ ) ;
672
+ if !res. is_undefined ( ) {
673
+ result = res;
674
+ found = true ;
675
+ break ;
676
+ }
677
+ }
678
+ }
679
+ }
680
+ if found {
681
+ result
682
+ } else {
683
+ // Not found variable in the scope, maybe lambda closures captured in other package scopes.
684
+ self . last_lambda_ctx ( )
685
+ . map ( |ctx| ctx. closure . get ( name) . cloned ( ) . unwrap_or ( result. clone ( ) ) )
686
+ . unwrap_or ( result)
687
+ }
688
+ }
575
689
// Schema closure or global variables
576
690
_ => self . get_variable_in_schema_or_rule ( name) ,
577
691
}
0 commit comments