コード例 #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
ファイル: single_file.go プロジェクト: yingmsky/e8vm
// BuildSingleFile builds a package named "main" from a single file.
func BuildSingleFile(f string, rc io.ReadCloser) ([]byte, []*lex8.Error) {
	pinfo := build8.SimplePkg("_", f, rc)

	compiled, es := Lang().Compile(pinfo)
	if es != nil {
		return nil, es
	}

	buf := new(bytes.Buffer)
	e := link8.LinkMain(compiled.Lib(), buf, "main")
	if e != nil {
		return nil, lex8.SingleErr(e)
	}

	return buf.Bytes(), nil
}
コード例 #3
0
ファイル: file.go プロジェクト: yingmsky/e8vm
// FileResult returns a parsing result.
func FileResult(f string, rc io.ReadCloser) (*Result, []*lex8.Error) {
	p, rec := newParser(f, rc)
	parsed := parseFile(p)
	e := rc.Close()

	if e != nil {
		return nil, lex8.SingleErr(e)
	}
	if es := p.Errs(); es != nil {
		return nil, es
	}

	res := &Result{
		File:   parsed,
		Tokens: rec.Tokens(),
	}
	return res, nil
}
コード例 #4
0
ファイル: lang.go プロジェクト: yingmsky/e8vm
func (lang) Compile(pinfo *build8.PkgInfo) (
	compiled build8.Linkable, es []*lex8.Error,
) {
	asts, es := parsePkg(pinfo)
	if es != nil {
		return nil, es
	}

	// need to load these two builtin functions here
	b := newBuilder(pinfo.Path)
	initBuilder(b, pinfo.Import)
	if es = b.Errs(); es != nil {
		return nil, es
	}

	b.scope.Push() // package scope
	defer b.scope.Pop()
	for _, fileAST := range asts {
		buildFile(b, fileAST)
	}

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

	addStart(b)

	irLog := pinfo.CreateLog("ir")
	ir.PrintPkg(irLog, b.p)
	if e := irLog.Close(); e != nil {
		return nil, lex8.SingleErr(e)
	}

	lib := ir.BuildPkg(b.p)
	return &pkg{lib}, nil
}
コード例 #5
0
ファイル: bare_func.go プロジェクト: yingmsky/e8vm
func (bareFunc) Compile(pinfo *build8.PkgInfo) (
	compiled build8.Linkable, es []*lex8.Error,
) {
	b := newBuilder(pinfo.Path)

	initBuilder(b, pinfo.Import)
	if es = b.Errs(); es != nil {
		return nil, es
	}

	if len(pinfo.Src) == 0 {
		panic("no source file")
	} else if len(pinfo.Src) > 1 {
		e := fmt.Errorf("bare func %q has too many files", pinfo.Path)
		return nil, lex8.SingleErr(e)
	}

	b.irLog = pinfo.CreateLog("ir")
	defer b.irLog.Close()

	for _, r := range pinfo.Src {
		stmts, es := parse.Stmts(r.Path, r)
		if es != nil {
			return nil, es
		}

		lib := buildBareFunc(b, stmts)
		if es = b.Errs(); es != nil {
			return nil, es
		}

		return &pkg{lib}, nil
	}

	panic("unreachable")
}
コード例 #6
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
}