From 27e5ab0a44af715d94bc0662577c409ec7ae703b Mon Sep 17 00:00:00 2001 From: chai2010 Date: Sun, 14 Aug 2022 16:58:28 +0800 Subject: [PATCH] =?UTF-8?q?loader:=20=E9=87=8D=E6=9E=84=20vfs=20=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api.go | 6 ++--- internal/config/manifest.go | 12 +++++++++ internal/loader/api.go | 6 +++++ internal/loader/loader.go | 46 +++++++++++++------------------- internal/loader/vfs.go | 52 +++++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 31 deletions(-) create mode 100644 internal/loader/vfs.go diff --git a/api/api.go b/api/api.go index 46ca5a3..124ea35 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 74ba05c..a1771c6 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 461423b..691c988 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 c0a06ef..183894b 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 0000000..e772cfc --- /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 +} -- GitLab