示例#1
0
// loadInclude tries to load the given reference as an include file.
// Parses it into the supplied AST and verifies that it contains what
// we are looking for.
func loadInclude(ast *parser.AST, includes []string, r *parser.Name) (err error) {
	var file string

	name := r.Data + ".dasm"
	walker := func(f string, info os.FileInfo, e error) (err error) {
		if info.IsDir() {
			return
		}

		parts := strings.Split(f, string(filepath.Separator))
		for i := range parts {
			if len(parts[i]) == 0 {
				continue
			}

			if parts[i][0] == '_' {
				return nil
			}
		}

		fb := parts[len(parts)-1]
		if fb == name {
			file, err = filepath.Abs(f)
			if err != nil {
				return
			}
			return io.EOF // Signal walker to stop.
		}

		return nil
	}

	for i := range includes {
		filepath.Walk(includes[i], walker)

		if len(file) > 0 {
			break
		}
	}

	if len(file) == 0 {
		return parser.NewParseError(ast.Files[r.File()], r.Line(), r.Col(),
			"Undefined reference: %q", r.Data)
	}

	if err = readSource(ast, file); err != nil {
		return
	}

	// Test if the code actually contains the label we are looking for.
	if !includeHasLabel(ast, file, r.Data) {
		return parser.NewParseError(ast.Files[r.File()], r.Line(), r.Col(),
			"Undefined reference: %q. Include file was found, but "+
				"it did not define the desired label.", r.Data)
	}

	// This new file may hold its own include requirements.
	return resolveIncludes(ast, includes)
}
示例#2
0
// resolveIncludes finds references to undefined labels.
// It then tries to find the code for these labels in the supplied
// include paths. Files should be defined as '<labelname>.dasm'.
func resolveIncludes(ast *parser.AST, includes []string) (err error) {
	var labels []*parser.Label
	var refs []*parser.Name
	var consts []*parser.Name
	var funcs []*parser.Function

	FindLabels(ast.Root.Children(), &labels)
	FindReferences(ast.Root.Children(), &refs)
	FindConstants(ast.Root.Children(), &consts)
	FindFunctions(ast.Root.Children(), &funcs)

	refs = findUndefinedRefs(refs, consts, labels, funcs)

	if len(refs) == 0 {
		// No undefined references. We're done here.
		return
	}

	if len(includes) == 0 {
		// We have unresolved references, but no places to look
		// for their implementation. This constitutes a booboo.
		return parser.NewParseError(ast.Files[refs[0].File()], refs[0].Line(), refs[0].Col(),
			"Undefined reference: %q", refs[0].Data)
	}

	for i := range refs {
		if err = loadInclude(ast, includes, refs[i]); err != nil {
			return
		}
	}

	return
}