From 2a7c22373bf13852807c69491f6013e77adf3b82 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 13 Oct 2021 06:50:06 +0800 Subject: [PATCH] new engine: igo --- README.md | 3 +- cmd/igop/internal/lib/default_igo.go | 20 ++++++ cmd/igop/internal/run/run_igo.go | 43 ++++++++++++ go.mod | 5 +- go.sum | 2 + igop_igo.go | 99 ++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 cmd/igop/internal/lib/default_igo.go create mode 100644 cmd/igop/internal/run/run_igo.go create mode 100644 igop_igo.go diff --git a/README.md b/README.md index 5b01e3c..2e489cf 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,12 @@ igop - The Go+ interpreter (still in beta version) * [yaegi](https://github.com/traefik/yaegi) * [gomacro](https://github.com/cosmos72/gomacro) +* [igo](https://github.com/goplus/igo) ## How to build ```bash git clone git@github.com:goplus/igop.git cd igop -go install -tags yaegi -v ./... # you can replace `yaegi` to `gomacro` or other engines +go install -tags yaegi -v ./... # you can replace `yaegi` to `igo` or other engines ``` diff --git a/cmd/igop/internal/lib/default_igo.go b/cmd/igop/internal/lib/default_igo.go new file mode 100644 index 0000000..9b5f169 --- /dev/null +++ b/cmd/igop/internal/lib/default_igo.go @@ -0,0 +1,20 @@ +//go:build igo +// +build igo + +/* + Copyright 2021 The GoPlus Authors (goplus.org) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package lib diff --git a/cmd/igop/internal/run/run_igo.go b/cmd/igop/internal/run/run_igo.go new file mode 100644 index 0000000..9038c74 --- /dev/null +++ b/cmd/igop/internal/run/run_igo.go @@ -0,0 +1,43 @@ +//go:build igo +// +build igo + +/* + Copyright 2020 The GoPlus Authors (goplus.org) + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package run + +import ( + "os" + + "github.com/goplus/igo/interp" + "github.com/goplus/igop" + "github.com/qiniu/x/log" + + _ "github.com/goplus/igo/lib" +) + +// ----------------------------------------------------------------------------- + +func runDir(srcDir string, asm bool) { + app, err := igop.CompileDir(srcDir) + if err != nil { + log.Fatalln(err) + } + if asm { + app.Dump(os.Stdout) + return + } + interp.New().RunProgram(app) +} + +// ----------------------------------------------------------------------------- diff --git a/go.mod b/go.mod index 45a9dd5..418f500 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,7 @@ require ( github.com/cosmos72/gomacro v0.0.0-20210624153544-b4935e406a41 github.com/goplus/gop v1.0.14 github.com/goplus/gox v1.7.10 + github.com/goplus/igo v0.3.0 github.com/qiniu/x v1.11.5 github.com/traefik/yaegi v0.10.0 ) - -replace ( - github.com/traefik/yaegi => /Users/xushiwei/work/yaegi -) \ No newline at end of file diff --git a/go.sum b/go.sum index 3534089..31bebec 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/goplus/gop v1.0.14 h1:tjsnvzROVe3Z1wUnAk42irwvAG5N9KR6D36mo9CaTJg= github.com/goplus/gop v1.0.14/go.mod h1:oo5V2tps5zZxzPXqnO1ENeXOVBIjQnMRI8ZIRCQ72rk= github.com/goplus/gox v1.7.10 h1:gjJSI7h80BfmyuuZE9YJX7xZPrd8MxipirqcI3exoyE= github.com/goplus/gox v1.7.10/go.mod h1:orZ6Mr9qqB4BVaVCMp/cypMtkn0Fp5XUE7e5uqjZATA= +github.com/goplus/igo v0.3.0 h1:InN/Ol4xHD1/EMBEtZpB1EG1RWUccGNY75DsYrWnrsE= +github.com/goplus/igo v0.3.0/go.mod h1:uOwR7R+d95+X9zfc7W9WqpUQKNij1ITnyCPEIn3lozY= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= diff --git a/igop_igo.go b/igop_igo.go new file mode 100644 index 0000000..46025bf --- /dev/null +++ b/igop_igo.go @@ -0,0 +1,99 @@ +//go:build igo +// +build igo + +/* + Copyright 2021 The GoPlus Authors (goplus.org) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package igop + +import ( + "errors" + "fmt" + "go/ast" + "go/token" + "log" + "os" + "path/filepath" + + "github.com/goplus/gop/cl" + "github.com/goplus/gop/parser" + "github.com/goplus/gox" + "github.com/goplus/igo/interp" +) + +// ----------------------------------------------------------------------------- + +func CompileDir(srcDir string) (app *interp.Program, err error) { + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, srcDir, nil, 0) + if err != nil { + return + } + mainPkg, ok := pkgs["main"] + if !ok { + return nil, errors.New("not a main package") + } + + modDir, noCacheFile := findGoModDir(srcDir) + conf := &cl.Config{ + Dir: modDir, TargetDir: srcDir, Fset: fset, CacheLoadPkgs: true, PersistLoadPkgs: !noCacheFile} + out, err := cl.NewPackage("", mainPkg, conf) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(11) + } + conf.PkgsLoader.Save() + file := gox.ASTFile(out, false) + pkg := astFileToPkg(file, "gop_autogen.go") + fsetGo := token.NewFileSet() + return interp.CompileAST(pkg, fsetGo) +} + +// astFileToPkg translate ast.File to ast.Package +func astFileToPkg(file *ast.File, fileName string) (pkg *ast.Package) { + pkg = &ast.Package{ + Name: file.Name.Name, + Files: make(map[string]*ast.File), + } + pkg.Files[fileName] = file + return +} + +func findGoModFile(dir string) (modfile string, noCacheFile bool, err error) { + modfile, err = cl.FindGoModFile(dir) + if err != nil { + home := os.Getenv("HOME") + modfile = home + "/gop/go.mod" + if fi, e := os.Lstat(modfile); e == nil && !fi.IsDir() { + return modfile, true, nil + } + modfile = home + "/goplus/go.mod" + if fi, e := os.Lstat(modfile); e == nil && !fi.IsDir() { + return modfile, true, nil + } + } + return +} + +func findGoModDir(dir string) (string, bool) { + modfile, nocachefile, err := findGoModFile(dir) + if err != nil { + log.Fatalln("findGoModFile:", err) + } + return filepath.Dir(modfile), nocachefile +} + +// -----------------------------------------------------------------------------