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