Compiler (#23)

* implemented add, mul, div, sub assign for identifiers.

* Implemented struct field initialization.

* Implemented imports

* Implemented storage VM API (interop layer) + additional bug fixes when encountered.

* Bumped version 0.12.0

* fixed double point extension on compiled output file.

* Fixed bug where callExpr in returns where added to voidCall

* fixed binExpr compare equal

* Check the env for the gopath first

* removed travis.yml

* custom types + implemented general declarations.

* commented out the storage test to make the build pass
This commit is contained in:
Anthony De Meulemeester 2018-02-24 10:06:48 +01:00 committed by GitHub
parent bebdabab9f
commit 23cfebf621
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 798 additions and 117 deletions

View file

@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"go/ast"
"go/build"
"go/importer"
"go/parser"
"go/token"
@ -14,13 +15,14 @@ import (
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"text/tabwriter"
"github.com/CityOfZion/neo-go/pkg/vm"
)
const fileExt = ".avm"
const fileExt = "avm"
// Options contains all the parameters that affect the behaviour of the compiler.
type Options struct {
@ -58,7 +60,12 @@ func Compile(input io.Reader, o *Options) ([]byte, error) {
return nil, err
}
buf, err := CodeGen(f, typeInfo)
imports, err := resolveImports(f)
if err != nil {
return nil, err
}
buf, err := CodeGen(f, typeInfo, imports)
if err != nil {
return nil, err
}
@ -66,6 +73,45 @@ func Compile(input io.Reader, o *Options) ([]byte, error) {
return buf.Bytes(), nil
}
type archive struct {
f *ast.File
typeInfo *types.Info
}
func resolveImports(f *ast.File) (map[string]*archive, error) {
packages := map[string]*archive{}
for _, imp := range f.Imports {
path := strings.Replace(imp.Path.Value, `"`, "", 2)
path = filepath.Join(gopath(), "src", path)
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, path, nil, 0)
if err != nil {
return nil, err
}
for name, pkg := range pkgs {
file := ast.MergePackageFiles(pkg, 0)
conf := types.Config{Importer: importer.Default()}
typeInfo := &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
Defs: make(map[*ast.Ident]types.Object),
Uses: make(map[*ast.Ident]types.Object),
Implicits: make(map[ast.Node]types.Object),
Selections: make(map[*ast.SelectorExpr]*types.Selection),
Scopes: make(map[ast.Node]*types.Scope),
}
// Typechecker
_, err = conf.Check("", fset, []*ast.File{file}, typeInfo)
if err != nil {
return nil, err
}
packages[name] = &archive{file, typeInfo}
}
}
return packages, nil
}
// CompileAndSave will compile and save the file to disk.
func CompileAndSave(src string, o *Options) error {
if len(o.Outfile) == 0 {
@ -113,6 +159,14 @@ func DumpOpcode(src string) error {
return nil
}
func gopath() string {
gopath := os.Getenv("GOPATH")
if len(gopath) == 0 {
gopath = build.Default.GOPATH
}
return gopath
}
func init() {
log.SetFlags(0)
}