@@ -1870,65 +1870,13 @@ func (e *Executor) dispatch(session *StackContext, task Task) error {
18701870 prog , err := e .Loader (path )
18711871 if err == nil {
18721872 session .LoadingModules [path ] = true
1873- modExecutor , err := NewExecutor (prog )
1873+ res , err := e .executeImportedProgram (session , path , prog )
1874+ delete (session .LoadingModules , path )
18741875 if err != nil {
1875- delete (session .LoadingModules , path )
18761876 return err
18771877 }
1878- modExecutor .Loader = e .Loader
1879- modExecutor .routes = e .routes
1880-
1881- modSession := & StackContext {
1882- Context : session .Context ,
1883- Executor : modExecutor ,
1884- Stack : & Stack {MemoryPtr : make (map [string ]* Var ), Globals : make (map [string ]* Var ), Frame : & SlotFrame {}, Scope : "global" , Depth : 1 },
1885- StepLimit : session .StepLimit ,
1886- StepCount : session .StepCount ,
1887- ModuleCache : session .ModuleCache ,
1888- LoadingModules : session .LoadingModules ,
1889- Debugger : session .Debugger ,
1890- ValueStack : & ValueStack {},
1891- LHSStack : & LHSStack {},
1892- }
1893-
1894- // Push Done task to current stack (restore context later)
1895- session .TaskStack = append (session .TaskStack , Task {
1896- Op : OpImportDone ,
1897- Data : & ImportData {
1898- Path : path ,
1899- OldExecutor : session .Executor ,
1900- OldStack : session .Stack ,
1901- OldTaskStack : session .TaskStack ,
1902- OldValueStack : session .ValueStack ,
1903- OldLHSStack : session .LHSStack ,
1904- ModSession : modSession ,
1905- },
1906- })
1907-
1908- // Switch current session fields
1909- session .Executor = modExecutor
1910- session .Stack = modSession .Stack
1911- session .ValueStack = modSession .ValueStack
1912- session .LHSStack = modSession .LHSStack
1913- session .UnwindMode = UnwindNone
1914-
1915- // Push Global variables init
1916- for i := len (modExecutor .globalInitOrder ) - 1 ; i >= 0 ; i -- {
1917- name := modExecutor .globalInitOrder [i ]
1918- global , ok := modExecutor .lookupGlobal (name )
1919- if ! ok {
1920- continue
1921- }
1922- if global == nil || ! global .HasInit {
1923- continue
1924- }
1925- session .TaskStack = append (session .TaskStack , Task {Op : OpInitVar , Data : string (name )})
1926- session .TaskStack = append (session .TaskStack , cloneTasks (global .InitPlan )... )
1927- }
1928-
1929- // Push Main block execution
1930- session .TaskStack = append (session .TaskStack , cloneTasks (modExecutor .mainTasks )... )
1931-
1878+ session .ModuleCache [path ] = res
1879+ session .ValueStack .Push (res )
19321880 return nil
19331881 }
19341882 }
@@ -1977,73 +1925,7 @@ func (e *Executor) dispatch(session *StackContext, task Task) error {
19771925 return fmt .Errorf ("failed to load module %s" , path )
19781926
19791927 case OpImportDone :
1980- data := task .Data .(* ImportData )
1981- path := data .Path
1982- modSession := data .ModSession
1983- modExec := modSession .Executor .(* Executor )
1984-
1985- delete (session .LoadingModules , path )
1986-
1987- exports := make (map [string ]* Var )
1988- for name := range modExec .globals {
1989- if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
1990- v , err := modSession .Load (string (name ))
1991- if err == nil {
1992- exports [string (name )] = v
1993- }
1994- }
1995- }
1996- for name , fn := range modExec .functions {
1997- if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
1998- exports [string (name )] = & Var {
1999- VType : TypeClosure ,
2000- Ref : & VMClosure {
2001- FunctionType : fn .FunctionType ,
2002- BodyTasks : cloneTasks (fn .BodyTasks ),
2003- UpvalueSlots : nil ,
2004- UpvalueNames : nil ,
2005- Context : modSession ,
2006- },
2007- }
2008- }
2009- }
2010- for name , val := range modExec .consts {
2011- if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
2012- exports [name ] = NewString (val )
2013- }
2014- }
2015- for name , s := range modExec .metadata .structsByName {
2016- if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
2017- exports [string (name )] = & Var {
2018- VType : TypeAny ,
2019- Ref : cloneRuntimeStructSpec (s ),
2020- }
2021- }
2022- }
2023-
2024- // modSession.Stack should remain its own global stack for future member access to module variables
2025- // modSession.Stack = session.Stack <--- REMOVED THIS LINE
2026-
2027- // Restore session
2028- session .Executor = data .OldExecutor .(ExecutorAPI )
2029- session .Stack = data .OldStack
2030- session .TaskStack = data .OldTaskStack
2031- session .ValueStack = data .OldValueStack
2032- session .LHSStack = data .OldLHSStack
2033- session .UnwindMode = UnwindNone
2034-
2035- res := & Var {
2036- VType : TypeModule ,
2037- Ref : & VMModule {
2038- Name : path ,
2039- Data : exports ,
2040- Context : modSession ,
2041- },
2042- }
2043-
2044- session .ModuleCache [path ] = res
2045- session .ValueStack .Push (res )
2046- return nil
1928+ return fmt .Errorf ("OpImportDone should not be reached in synchronous import mode" )
20471929 case OpPush :
20481930 if v , ok := task .Data .(* Var ); ok {
20491931 session .ValueStack .Push (v )
@@ -2711,6 +2593,78 @@ func (e *Executor) GetProgram() *ast.ProgramStmt {
27112593 return e .program
27122594}
27132595
2596+ func (e * Executor ) buildImportedModuleValue (path string , modExec * Executor , modSession * StackContext ) * Var {
2597+ exports := make (map [string ]* Var )
2598+ for name := range modExec .globals {
2599+ if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
2600+ v , err := modSession .Load (string (name ))
2601+ if err == nil {
2602+ exports [string (name )] = v
2603+ }
2604+ }
2605+ }
2606+ for name , fn := range modExec .functions {
2607+ if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
2608+ exports [string (name )] = & Var {
2609+ VType : TypeClosure ,
2610+ Ref : & VMClosure {
2611+ FunctionType : fn .FunctionType ,
2612+ BodyTasks : cloneTasks (fn .BodyTasks ),
2613+ UpvalueSlots : nil ,
2614+ UpvalueNames : nil ,
2615+ Context : modSession ,
2616+ },
2617+ }
2618+ }
2619+ }
2620+ for name , val := range modExec .consts {
2621+ if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
2622+ exports [name ] = NewString (val )
2623+ }
2624+ }
2625+ for name , s := range modExec .metadata .structsByName {
2626+ if len (name ) > 0 && name [0 ] >= 'A' && name [0 ] <= 'Z' {
2627+ exports [string (name )] = & Var {
2628+ VType : TypeAny ,
2629+ Ref : cloneRuntimeStructSpec (s ),
2630+ }
2631+ }
2632+ }
2633+
2634+ return & Var {
2635+ VType : TypeModule ,
2636+ Ref : & VMModule {
2637+ Name : path ,
2638+ Data : exports ,
2639+ Context : modSession ,
2640+ },
2641+ }
2642+ }
2643+
2644+ func (e * Executor ) executeImportedProgram (parent * StackContext , path string , prog * ast.ProgramStmt ) (* Var , error ) {
2645+ modExecutor , err := NewExecutor (prog )
2646+ if err != nil {
2647+ return nil , err
2648+ }
2649+ modExecutor .Loader = e .Loader
2650+ modExecutor .StepLimit = e .StepLimit
2651+ modExecutor .routes = e .routes
2652+
2653+ modSession := modExecutor .NewSession (parent .Context , "global" )
2654+ modSession .StepLimit = parent .StepLimit
2655+ modSession .StepCount = parent .StepCount
2656+ modSession .ModuleCache = parent .ModuleCache
2657+ modSession .LoadingModules = parent .LoadingModules
2658+ modSession .Debugger = parent .Debugger
2659+
2660+ if err := modExecutor .InitializeSession (modSession , nil , false ); err != nil {
2661+ parent .StepCount = modSession .StepCount
2662+ return nil , err
2663+ }
2664+ parent .StepCount = modSession .StepCount
2665+ return e .buildImportedModuleValue (path , modExecutor , modSession ), nil
2666+ }
2667+
27142668func (e * Executor ) ExecuteStmts (session * StackContext , stmts []ast.Stmt ) error {
27152669 oldTasks := session .TaskStack
27162670 oldValues := session .ValueStack
0 commit comments