Beispiel #1
0
func newBuilder(path string, scope *sym8.Scope) *builder {
	return &builder{
		ErrorList: lex8.NewErrorList(),
		path:      path,
		scope:     scope,
	}
}
Beispiel #2
0
// 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("main")
	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
}
Beispiel #3
0
func runPkgTests(c *context, p *pkg) []*lex8.Error {
	lib := p.pkg.Lib
	tests := p.pkg.Tests
	testMain := p.pkg.TestMain
	if testMain != "" && lib.HasFunc(testMain) {
		log := lex8.NewErrorList()
		if len(tests) > 0 {
			bs := new(bytes.Buffer)
			lex8.LogError(log, link(c, bs, p, testMain))
			fout := c.output.TestBin(p.path)

			img := bs.Bytes()
			_, err := fout.Write(img)
			lex8.LogError(log, err)
			lex8.LogError(log, fout.Close())
			if es := log.Errs(); es != nil {
				return es
			}

			runTests(log, tests, img, c.Options)
			if es := log.Errs(); es != nil {
				return es
			}
		}
	}

	return nil
}
Beispiel #4
0
func (b *Builder) runTests(p *pkg) []*lex8.Error {
	lib := p.pkg.Lib
	tests := p.pkg.Tests
	testMain := p.pkg.TestMain
	if testMain != "" && lib.HasFunc(testMain) {
		log := lex8.NewErrorList()
		if len(tests) > 0 {
			bs := new(bytes.Buffer)
			lex8.LogError(log, b.link(bs, p, testMain))
			fout := b.home.CreateTestBin(p.path)

			img := bs.Bytes()
			_, err := fout.Write(img)
			lex8.LogError(log, err)
			lex8.LogError(log, fout.Close())
			if es := log.Errs(); es != nil {
				return es
			}

			runTests(log, tests, img, b.Verbose)
			if es := log.Errs(); es != nil {
				return es
			}
		}
	}

	return nil
}
Beispiel #5
0
func newBuilder(path string) *builder {
	return &builder{
		ErrorList: lex8.NewErrorList(),
		scope:     sym8.NewScope(),
		path:      path,
		imports:   make(map[string]string),
		pkgUsed:   make(map[string]struct{}),
	}
}
Beispiel #6
0
func newBuilder(path string) *builder {
	s := sym8.NewScope()
	return &builder{
		ErrorList: lex8.NewErrorList(),
		path:      path,
		p:         ir.NewPkg(path),
		scope:     s, // package scope

		continues: newBlockStack(),
		breaks:    newBlockStack(),
	}
}
Beispiel #7
0
func (lang) Compile(pinfo *build8.PkgInfo, opts *build8.Options) (
	*build8.Package, []*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.Package == nil {
				errs.Errorf(stmt.Path.Pos, "import missing")
				continue
			}

			if imp.Lang != "asm8" {
				errs.Errorf(stmt.Path.Pos, "can only import asm8 package")
				continue
			}

			stmt.pkg = imp.Package
			if stmt.pkg == nil {
				panic("import missing")
			}
		}

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

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

	ret := &build8.Package{
		Lang:    "asm8",
		Lib:     lib.Pkg,
		Main:    "main",
		Symbols: buildSymTable(lib),
	}
	return ret, nil
}
Beispiel #8
0
func (b *Builder) buildMain(p *pkg) []*lex8.Error {
	lib := p.pkg.Lib
	main := p.pkg.Main

	if main == "" || !lib.HasFunc(main) {
		return nil
	}

	log := lex8.NewErrorList()

	fout := b.output.Bin(p.path)
	lex8.LogError(log, b.link(fout, p, main))
	lex8.LogError(log, fout.Close())

	return log.Errs()
}
Beispiel #9
0
func buildMain(c *context, p *pkg) []*lex8.Error {
	lib := p.pkg.Lib
	main := p.pkg.Main

	if main == "" || !lib.HasFunc(main) {
		return nil
	}

	log := lex8.NewErrorList()

	fout := c.output.Bin(p.path)
	lex8.LogError(log, link(c, fout, p, main))
	lex8.LogError(log, fout.Close())

	return log.Errs()
}
Beispiel #10
0
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
}
Beispiel #11
0
func listImport(
	f string, rc io.ReadCloser, imp build8.Importer, golike bool,
) []*lex8.Error {
	fast, _, es := parse.File(f, rc, golike)
	if es != nil {
		return es
	}

	if fast.Imports == nil {
		return nil
	}

	m := make(map[string]*importDecl)
	log := lex8.NewErrorList()

	for _, d := range fast.Imports.Decls {
		p, as, e := ast.ImportPathAs(d)
		if e != nil {
			log.Errorf(d.Path.Pos, "invalid path string %s", d.Path.Lit)
			continue
		}

		pos := ast.ImportPos(d)
		if other, found := m[as]; found {
			log.Errorf(pos, "%s already imported", as)
			log.Errorf(other.pos, "  previously imported here")
			continue
		}

		m[as] = &importDecl{as: as, path: p, pos: pos}
	}

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

	for as, d := range m {
		imp.Import(as, d.path, d.pos)
	}

	return nil
}
Beispiel #12
0
// CheckRect checks if a program is within a rectangular area.
func CheckRect(file string, r io.Reader, h, w int) []*lex8.Error {
	br := bufio.NewReader(r)
	row := 0
	col := 0

	errs := lex8.NewErrorList()

	pos := func() *lex8.Pos { return &lex8.Pos{file, row + 1, col + 1} }
	newLine := func() {
		if col > w {
			errs.Errorf(pos(), "line too wide")
		}
		row++
		col = 0
	}

	for {
		r, _, e := br.ReadRune()
		if e == io.EOF {
			if col > 0 {
				newLine()
			}
			break
		} else if lex8.LogError(errs, e) {
			break
		}

		if r == '\n' {
			newLine()
		} else {
			col += runeWidth(r)
		}
	}

	if row > h {
		errs.Errorf(pos(), "too many lines")
	}

	return errs.Errs()
}
Beispiel #13
0
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
}
Beispiel #14
0
func newGener() *gener {
	return &gener{
		ErrorList: lex8.NewErrorList(),
	}
}