diff --git a/api/api.go b/api/api.go index 46ca5a3863df86370686d9240bcd0c6c652b82c8..124ea35231848c2eb109f1c780cb81c9312b7e15 100644 --- a/api/api.go +++ b/api/api.go @@ -42,9 +42,9 @@ func LoadProgram(cfg *config.Config, appPath string) (*Program, error) { // 基于 VFS 加载程序 // 入口 pkgPath 是包路径, 必须是 vfs.App 子包 -func LoadProgramVFS(vfs config.PkgVFS, cfg *config.Config, pkgPath string) (*Program, error) { - panic("TODO") +func LoadProgramVFS(vfs *config.PkgVFS, cfg *config.Config, pkgPath string) (*Program, error) { + return loader.LoadProgramVFS(vfs, cfg, pkgPath) } -// TODO: 解析 ast/语义/SSA 分阶段解析 +// TODO: 解析 ast/语义/SSA 分阶段解析, 放到 Program 中 // TODO: Program 编译到不同后端的函数 diff --git a/internal/config/manifest.go b/internal/config/manifest.go index 74ba05c95d3d654a96644e8cd57abc72ff2f579f..a1771c6aa91d6a488c9845a6e9b65fd050ff4ceb 100644 --- a/internal/config/manifest.go +++ b/internal/config/manifest.go @@ -54,6 +54,18 @@ func (p *Manifest) Clone() *Manifest { return &v } +// 简版 Manifest +func SimpleManifest(mainPkg, appName string) *Manifest { + p := &Manifest{ + MainPkg: mainPkg, + Pkg: Manifest_package{ + Name: appName, + Pkgpath: mainPkg, + }, + } + return p +} + // 加载 WaModFile 文件 // 如果 vfs 为空则从本地文件系统读取 func LoadManifest(vfs fs.FS, appPath string) (p *Manifest, err error) { diff --git a/internal/loader/api.go b/internal/loader/api.go index 461423beeda499ca1f26860a0c08ad5fc9571860..691c988cd56a546071f68a2adc48a75399bea979 100644 --- a/internal/loader/api.go +++ b/internal/loader/api.go @@ -37,3 +37,9 @@ type Package struct { func LoadProgram(cfg *config.Config, appPath string) (*Program, error) { return newLoader(cfg).LoadProgram(appPath) } + +// 基于 VFS 加载程序 +// 入口 pkgPath 是包路径, 必须是 vfs.App 子包 +func LoadProgramVFS(vfs *config.PkgVFS, cfg *config.Config, pkgPath string) (*Program, error) { + return newLoader(cfg).LoadProgramVFS(vfs, pkgPath) +} diff --git a/internal/loader/loader.go b/internal/loader/loader.go index c0a06ef71e7bb2499aa6ce662a86dee40c6fb38f..183894b9838ab7b29aa0a7cc71d082b3df1e7a44 100644 --- a/internal/loader/loader.go +++ b/internal/loader/loader.go @@ -1,16 +1,12 @@ // 版权 @2021 凹语言 作者。保留所有权利。 -// TODO: 解析 ast/语义/SSA 分阶段解析 - package loader import ( "io/fs" - "os" "path/filepath" "sort" "strings" - "testing/fstest" "github.com/wa-lang/wa/internal/ast" "github.com/wa-lang/wa/internal/config" @@ -29,53 +25,47 @@ type _Loader struct { } func newLoader(cfg *config.Config) *_Loader { - p := &_Loader{ + return &_Loader{ cfg: *cfg.Clone(), prog: &Program{ Pkgs: make(map[string]*Package), }, } - - return p } -// 加载程序 func (p *_Loader) LoadProgram(appPath string) (*Program, error) { logger.Tracef(&config.EnableTrace_loader, "cfg: %+v", p.cfg) logger.Tracef(&config.EnableTrace_loader, "appPath: %s", appPath) + vfs, manifest, err := loadProgramMeta(&p.cfg, appPath) + if err != nil { + logger.Tracef(&config.EnableTrace_loader, "err: %v", err) + return nil, err + } + + return p.loadProgram(vfs, manifest) +} + +func (p *_Loader) LoadProgramVFS(vfs *config.PkgVFS, appPath string) (*Program, error) { manifest, err := config.LoadManifest(nil, appPath) if err != nil { logger.Tracef(&config.EnableTrace_loader, "err: %v", err) return nil, err } + return p.loadProgram(vfs, manifest) +} + +// 加载程序 +func (p *_Loader) loadProgram(vfs *config.PkgVFS, manifest *config.Manifest) (*Program, error) { + logger.DumpFS(&config.EnableTrace_loader, "vfs.app", vfs.App, ".") logger.Tracef(&config.EnableTrace_loader, "manifest: %s", manifest.JSONString()) + p.vfs = *vfs p.prog.Cfg = &p.cfg p.prog.Manifest = manifest p.prog.Fset = token.NewFileSet() - if p.vfs.App == nil { - p.vfs.App = os.DirFS(filepath.Join(p.prog.Manifest.Root, "src")) - } - - logger.DumpFS(&config.EnableTrace_loader, "p.vfs.App", p.vfs.App, ".") - - if p.vfs.Std == nil { - if p.cfg.WaRoot != "" { - p.vfs.Std = os.DirFS(filepath.Join(p.cfg.WaRoot, "src")) - } else { - p.vfs.Std = waroot.GetFS() - } - } - if p.vfs.Vendor == nil { - p.vfs.Vendor = os.DirFS(filepath.Join(p.prog.Manifest.Root, "vendor")) - if p.vfs.Vendor == nil { - p.vfs.Vendor = make(fstest.MapFS) // empty fs - } - } - // import "runtime" logger.Trace(&config.EnableTrace_loader, "import runtime") if _, err := p.Import("runtime"); err != nil { diff --git a/internal/loader/vfs.go b/internal/loader/vfs.go new file mode 100644 index 0000000000000000000000000000000000000000..e772cfccc040f4a57c43612144d41819ad6dc69e --- /dev/null +++ b/internal/loader/vfs.go @@ -0,0 +1,52 @@ +// 版权 @2021 凹语言 作者。保留所有权利。 + +package loader + +import ( + "os" + "path/filepath" + "testing/fstest" + + "github.com/wa-lang/wa/internal/config" + "github.com/wa-lang/wa/internal/logger" + "github.com/wa-lang/wa/internal/waroot" +) + +// 根据路径加载需要的 vfs 和 manifest +func loadProgramMeta(cfg *config.Config, appPath string) ( + vfs *config.PkgVFS, + manifest *config.Manifest, + err error, +) { + logger.Tracef(&config.EnableTrace_loader, "cfg: %+v", cfg) + logger.Tracef(&config.EnableTrace_loader, "appPath: %s", appPath) + + manifest, err = config.LoadManifest(nil, appPath) + if err != nil { + logger.Tracef(&config.EnableTrace_loader, "err: %v", err) + return nil, nil, err + } + + logger.Tracef(&config.EnableTrace_loader, "manifest: %s", manifest.JSONString()) + + vfs = new(config.PkgVFS) + if vfs.App == nil { + vfs.App = os.DirFS(filepath.Join(manifest.Root, "src")) + } + + if vfs.Std == nil { + if cfg.WaRoot != "" { + vfs.Std = os.DirFS(filepath.Join(cfg.WaRoot, "src")) + } else { + vfs.Std = waroot.GetFS() + } + } + if vfs.Vendor == nil { + vfs.Vendor = os.DirFS(filepath.Join(manifest.Root, "vendor")) + if vfs.Vendor == nil { + vfs.Vendor = make(fstest.MapFS) // empty fs + } + } + + return +}