@@ -424,6 +424,7 @@ impl<'ctx> Evaluator<'ctx> {
424424 for i in 0 ..scopes_len {
425425 let index = scopes_len - i - 1 ;
426426 let variables = & scopes[ index] . variables ;
427+
427428 if let Some ( var) = variables. get ( name) {
428429 // Closure vars, 2 denotes the builtin scope and the global scope, here is a closure scope.
429430 result = if let Some ( lambda_ctx) = self . last_lambda_ctx ( ) {
@@ -458,6 +459,81 @@ impl<'ctx> Evaluator<'ctx> {
458459 }
459460 }
460461
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+
461537 /// Get closure map in the current inner scope.
462538 pub ( crate ) fn get_current_closure_map ( & self ) -> ClosureMap {
463539 // Get variable map in the current scope.
@@ -571,7 +647,45 @@ impl<'ctx> Evaluator<'ctx> {
571647 {
572648 match self . resolve_variable_level ( name) {
573649 // 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+ }
575689 // Schema closure or global variables
576690 _ => self . get_variable_in_schema_or_rule ( name) ,
577691 }
0 commit comments