예제 #1
0
// FindReferencesInScope finds all identifier expressions that refer to the given name, under the given
// scope.
func (g *SRG) FindReferencesInScope(name string, node compilergraph.GraphNode) compilergraph.NodeIterator {
	// Note: This filter ensures that the name is accessible in the scope of the given node by checking that
	// the node referencing the name is contained by the given node.
	containingFilter := func(q compilergraph.GraphQuery) compilergraph.Query {
		startRune := node.GetValue(parser.NodePredicateStartRune).Int()
		endRune := node.GetValue(parser.NodePredicateEndRune).Int()

		return q.
			HasWhere(parser.NodePredicateStartRune, compilergraph.WhereGT, startRune).
			HasWhere(parser.NodePredicateEndRune, compilergraph.WhereLT, endRune)
	}

	return g.layer.StartQuery(name).
		In(parser.NodeIdentifierExpressionName).
		IsKind(parser.NodeTypeIdentifierExpression).
		Has(parser.NodePredicateSource, node.Get(parser.NodePredicateSource)).
		FilterBy(containingFilter).
		BuildNodeIterator()
}
예제 #2
0
// OutOfScope returns any resources that will be out of scope when context changes to the given reference
// node. Used to determine which resources need to be popped off of the stack when jumps occurr. Note that
// the reference node *must be an SRG node*.
func (s *ResourceStack) OutOfScope(referenceNode compilergraph.GraphNode) []resource {
	resources := make([]resource, 0)

	// Find the start and end location for the reference node.
	referenceStart := referenceNode.GetValue(parser.NodePredicateStartRune).Int()
	referenceEnd := referenceNode.GetValue(parser.NodePredicateEndRune).Int()

	var current = s.top
	for index := 0; index < s.size; index++ {
		currentResource := current.value

		// Find the start and end location for the resource node.
		resourceStart := currentResource.basis.GetValue(parser.NodePredicateStartRune).Int()
		resourceEnd := currentResource.basis.GetValue(parser.NodePredicateEndRune).Int()

		if !(referenceStart >= resourceStart && referenceEnd <= resourceEnd) {
			resources = append(resources, currentResource)
		}

		current = current.next
	}

	return resources
}
예제 #3
0
파일: util.go 프로젝트: Serulian/compiler
// salForNode returns a SourceAndLocation for the given graph node.
func salForNode(node compilergraph.GraphNode) compilercommon.SourceAndLocation {
	return compilercommon.NewSourceAndLocation(
		compilercommon.InputSource(node.Get(parser.NodePredicateSource)),
		node.GetValue(parser.NodePredicateStartRune).Int())
}
예제 #4
0
// findAddedNameInScope finds the {parameter, with, loop, var} node exposing the given name, if any.
func (g *SRG) findAddedNameInScope(name string, node compilergraph.GraphNode) (compilergraph.GraphNode, bool) {
	nodeSource := node.Get(parser.NodePredicateSource)
	nodeStartIndex := node.GetValue(parser.NodePredicateStartRune).Int()

	// Note: This filter ensures that the name is accessible in the scope of the given node by checking that
	// the node adding the name contains the given node.
	containingFilter := func(q compilergraph.GraphQuery) compilergraph.Query {
		startRune := node.GetValue(parser.NodePredicateStartRune).Int()
		endRune := node.GetValue(parser.NodePredicateEndRune).Int()

		return q.
			In(parser.NodePredicateTypeMemberParameter,
				parser.NodeLambdaExpressionInferredParameter,
				parser.NodeLambdaExpressionParameter,
				parser.NodePredicateTypeMemberGeneric,
				parser.NodeStatementNamedValue,
				parser.NodeAssignedDestination,
				parser.NodeAssignedRejection,
				parser.NodePredicateChild,
				parser.NodeStatementBlockStatement).
			InIfKind(parser.NodeStatementBlockStatement, parser.NodeTypeResolveStatement).
			HasWhere(parser.NodePredicateStartRune, compilergraph.WhereLTE, startRune).
			HasWhere(parser.NodePredicateEndRune, compilergraph.WhereGTE, endRune)
	}

	nit := g.layer.StartQuery(name).
		In("named").
		Has(parser.NodePredicateSource, nodeSource).
		IsKind(parser.NodeTypeParameter, parser.NodeTypeNamedValue, parser.NodeTypeAssignedValue,
			parser.NodeTypeVariableStatement, parser.NodeTypeLambdaParameter, parser.NodeTypeGeneric).
		FilterBy(containingFilter).
		BuildNodeIterator(parser.NodePredicateStartRune, parser.NodePredicateEndRune)

	// Sort the nodes found by location and choose the closest node.
	var results = make(scopeResultNodes, 0)
	for nit.Next() {
		node := nit.Node()
		startIndex := nit.GetPredicate(parser.NodePredicateStartRune).Int()

		// If the node is a variable statement or assigned value, we have do to additional checks
		// (since they are not block scoped but rather statement scoped).
		if node.Kind() == parser.NodeTypeVariableStatement || node.Kind() == parser.NodeTypeAssignedValue {
			endIndex := nit.GetPredicate(parser.NodePredicateEndRune).Int()
			if node.Kind() == parser.NodeTypeAssignedValue {
				if parentNode, ok := node.TryGetIncomingNode(parser.NodeAssignedDestination); ok {
					endIndex = parentNode.GetValue(parser.NodePredicateEndRune).Int()
				} else if parentNode, ok := node.TryGetIncomingNode(parser.NodeAssignedRejection); ok {
					endIndex = parentNode.GetValue(parser.NodePredicateEndRune).Int()
				} else {
					panic("Missing assigned parent")
				}
			}

			// Check that the startIndex of the variable statement is <= the startIndex of the parent node
			if startIndex > nodeStartIndex {
				continue
			}

			// Ensure that the scope starts after the end index of the variable. Otherwise, the variable
			// name could be used in its initializer expression (which is expressly disallowed).
			if nodeStartIndex <= endIndex {
				continue
			}
		}

		results = append(results, scopeResultNode{node, startIndex})
	}

	if len(results) == 1 {
		// If there is a single result, return it.
		return results[0].node, true
	} else if len(results) > 1 {
		// Otherwise, sort the list by startIndex and choose the one closest to the scope node.
		sort.Sort(results)
		return results[0].node, true
	}

	return compilergraph.GraphNode{}, false
}
예제 #5
0
파일: srg.go 프로젝트: Serulian/compiler
// GetUniqueId returns a unique hash ID for the SRG node that is stable across compilations.
func GetUniqueId(srgNode compilergraph.GraphNode) string {
	hashBytes := []byte(srgNode.Get(parser.NodePredicateSource) + ":" + strconv.Itoa(srgNode.GetValue(parser.NodePredicateStartRune).Int()))
	sha256bytes := sha256.Sum256(hashBytes)
	return hex.EncodeToString(sha256bytes[:])[0:8]
}