// 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 }
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 }
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 }
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 }
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 }
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 }
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 }