mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-23 13:38:35 +00:00
e319c6c638
Make inspect work with avms by default and with go files if told so. In the end this makes our CLI interface more consistent and usable. Drop useless CompileAndInspect() compiler method along the way.
108 lines
2 KiB
Go
108 lines
2 KiB
Go
package compiler
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"go/ast"
|
|
"go/build"
|
|
"go/parser"
|
|
"go/types"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
|
|
"golang.org/x/tools/go/loader"
|
|
)
|
|
|
|
const fileExt = "avm"
|
|
|
|
// Options contains all the parameters that affect the behaviour of the compiler.
|
|
type Options struct {
|
|
// The extension of the output file default set to .avm
|
|
Ext string
|
|
|
|
// The name of the output file.
|
|
Outfile string
|
|
|
|
// Debug outputs a hex encoded string of the generated bytecode.
|
|
Debug bool
|
|
}
|
|
|
|
type buildInfo struct {
|
|
initialPackage string
|
|
program *loader.Program
|
|
}
|
|
|
|
// Compile compiles a Go program into bytecode that can run on the NEO virtual machine.
|
|
func Compile(r io.Reader, o *Options) ([]byte, error) {
|
|
conf := loader.Config{ParserMode: parser.ParseComments}
|
|
f, err := conf.ParseFile("", r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
conf.CreateFromFiles("", f)
|
|
|
|
prog, err := conf.Load()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ctx := &buildInfo{
|
|
initialPackage: f.Name.Name,
|
|
program: prog,
|
|
}
|
|
|
|
buf, err := CodeGen(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
type archive struct {
|
|
f *ast.File
|
|
typeInfo *types.Info
|
|
}
|
|
|
|
// CompileAndSave will compile and save the file to disk.
|
|
func CompileAndSave(src string, o *Options) error {
|
|
if !strings.HasSuffix(src, ".go") {
|
|
return fmt.Errorf("%s is not a Go file", src)
|
|
}
|
|
o.Outfile = strings.TrimSuffix(o.Outfile, fmt.Sprintf(".%s", fileExt))
|
|
if len(o.Outfile) == 0 {
|
|
o.Outfile = strings.TrimSuffix(src, ".go")
|
|
}
|
|
if len(o.Ext) == 0 {
|
|
o.Ext = fileExt
|
|
}
|
|
b, err := ioutil.ReadFile(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b, err = Compile(bytes.NewReader(b), o)
|
|
if err != nil {
|
|
return fmt.Errorf("error while trying to compile smart contract file: %v", err)
|
|
}
|
|
|
|
log.Println(hex.EncodeToString(b))
|
|
|
|
out := fmt.Sprintf("%s.%s", o.Outfile, o.Ext)
|
|
return ioutil.WriteFile(out, b, os.ModePerm)
|
|
}
|
|
|
|
func gopath() string {
|
|
gopath := os.Getenv("GOPATH")
|
|
if len(gopath) == 0 {
|
|
gopath = build.Default.GOPATH
|
|
}
|
|
return gopath
|
|
}
|
|
|
|
func init() {
|
|
log.SetFlags(0)
|
|
}
|