예제 #1
0
파일: bare_func.go 프로젝트: yingmsky/e8vm
// BuildBareFunc builds a function body into an image.
func BuildBareFunc(f string, rc io.ReadCloser) ([]byte, []*lex8.Error) {
	fn, es := parse.BareFunc(f, rc)
	if es != nil {
		return nil, es
	}

	// resolving pass
	log := lex8.NewErrorList()
	rfunc := resolveFunc(log, fn)
	if es := log.Errs(); es != nil {
		return nil, es
	}

	// building pass
	b := newBuilder()
	fobj := buildFunc(b, rfunc)
	if es := b.Errs(); es != nil {
		return nil, es
	}

	ret, e := link8.LinkBareFunc(fobj)
	if e != nil {
		return nil, lex8.SingleErr(e)
	}

	return ret, nil
}
예제 #2
0
파일: builder.go 프로젝트: yingmsky/e8vm
func newBuilder() *builder {
	ret := new(builder)
	ret.ErrorList = lex8.NewErrorList()
	ret.scope = sym8.NewScope()
	ret.indices = make(map[string]uint32)
	ret.pkgUsed = make(map[string]struct{})

	return ret
}
예제 #3
0
파일: builder.go 프로젝트: yingmsky/e8vm
func newBuilder(path string) *builder {
	ret := new(builder)
	ret.ErrorList = lex8.NewErrorList()
	ret.path = path
	ret.p = ir.NewPkg(path)
	ret.scope = sym8.NewScope() // package scope

	ret.continues = newBlockStack()
	ret.breaks = newBlockStack()

	return ret
}
예제 #4
0
파일: pkg.go 프로젝트: yingmsky/e8vm
func resolvePkg(p string, src map[string]*build8.File) (*pkg, []*lex8.Error) {
	log := lex8.NewErrorList()
	ret := new(pkg)
	ret.path = p

	asts := make(map[string]*ast.File)

	// parse all the files first
	var parseErrs []*lex8.Error
	for name, f := range src {
		astFile, es := parse.File(f.Path, f)
		if es != nil {
			parseErrs = append(parseErrs, es...)
		}
		asts[name] = astFile
	}
	if len(parseErrs) > 0 {
		return nil, parseErrs
	}

	for name, astFile := range asts {
		// then resolve the file
		file := resolveFile(log, astFile)
		ret.files = append(ret.files, file)

		// enforce import policy
		if len(src) == 1 || name == "import.s" {
			if ret.imports != nil {
				log.Errorf(file.imports.Kw.Pos,
					"double valid import stmt; two import.s?",
				)
			} else {
				ret.imports = file.imports
			}
		} else if file.imports != nil {
			log.Errorf(file.imports.Kw.Pos,
				"invalid import outside import.s in a multi-file package",
			)
		}
	}

	if es := log.Errs(); es != nil {
		return nil, es
	}
	return ret, nil
}
예제 #5
0
파일: lang.go 프로젝트: yingmsky/e8vm
func (lang) Compile(pinfo *build8.PkgInfo) (
	compiled build8.Linkable, es []*lex8.Error,
) {
	// resolve pass, will also parse the files
	pkg, es := resolvePkg(pinfo.Path, pinfo.Src)
	if es != nil {
		return nil, es
	}

	// import
	errs := lex8.NewErrorList()
	if pkg.imports != nil {
		for _, stmt := range pkg.imports.stmts {
			imp := pinfo.Import[stmt.as]
			if imp == nil || imp.Compiled == nil {
				errs.Errorf(stmt.Path.Pos, "import missing")
				continue
			}

			stmt.linkable = imp.Compiled
			if stmt.linkable == nil {
				panic("import missing")
			}

			stmt.lib = stmt.linkable.Lib()
		}

		if es := errs.Errs(); es != nil {
			return nil, es
		}
	}

	// library building
	b := newBuilder()
	lib := buildLib(b, pkg)
	if es := b.Errs(); es != nil {
		return nil, es
	}

	return lib, nil
}
예제 #6
0
파일: imports.go 프로젝트: yingmsky/e8vm
func listImport(
	f string, rc io.ReadCloser, imp build8.Importer,
) []*lex8.Error {
	astFile, es := parse.File(f, rc)
	if es != nil {
		return es
	}

	if astFile.Imports == nil {
		return nil
	}

	log := lex8.NewErrorList()
	impDecl := resolveImportDecl(log, astFile.Imports)
	if es := log.Errs(); es != nil {
		return es
	}

	for as, stmt := range impDecl.stmts {
		imp.Import(as, stmt.path, stmt.Path.Pos)
	}

	return nil
}
예제 #7
0
파일: builder.go 프로젝트: yingmsky/e8vm
func (b *Builder) build(p string) (*pkg, []*lex8.Error) {
	ret := b.pkgs[p]
	if ret == nil {
		panic("build without prepare")
	}

	// already compiled
	if ret.compiled != nil {
		return ret, nil
	}

	if ret.buildStarted {
		e := fmt.Errorf("package %q circular depends itself", p)
		return ret, lex8.SingleErr(e)
	}

	ret.buildStarted = true
	lang := ret.lang

	for _, imp := range ret.imports {
		built, es := b.build(imp.Path)
		if es != nil {
			return nil, es
		}
		imp.Compiled = built.compiled
	}

	// ready to build this one
	if b.Verbose {
		fmt.Println(p)
	}

	// compile now
	pinfo := &PkgInfo{
		Path:   p,
		Src:    ret.srcMap(),
		Import: ret.imports,
		CreateLog: func(name string) io.WriteCloser {
			return b.home.CreateLog(p, name)
		},
	}
	compiled, es := lang.Compile(pinfo)
	if es != nil {
		return nil, es
	}
	ret.compiled = compiled

	lib := ret.compiled.Lib() // the linkable lib
	// a package with main entrance, build the bin

	main := ret.compiled.Main()
	if main != "" && lib.HasFunc(main) {
		log := lex8.NewErrorList()

		fout := b.home.CreateBin(p)
		lex8.LogError(log, link8.LinkMain(lib, fout, main))
		lex8.LogError(log, fout.Close())

		if es := log.Errs(); es != nil {
			return nil, es
		}
	}

	return ret, nil
}