예제 #1
0
// buildBinaryOperatorExpression builds the CodeDOM for a binary operator.
func (db *domBuilder) buildBinaryOperatorExpression(node compilergraph.GraphNode, modifier exprModifier) codedom.Expression {
	scope, _ := db.scopegraph.GetScope(node)
	operator, _ := scope.CalledOperator(db.scopegraph.TypeGraph())

	if operator.IsNative() {
		return db.buildNativeBinaryExpression(node, operatorMap[node.Kind()])
	}

	leftExpr := db.getExpression(node, parser.NodeBinaryExpressionLeftExpr)
	rightExpr := db.getExpression(node, parser.NodeBinaryExpressionRightExpr)

	leftScope, _ := db.scopegraph.GetScope(node.GetNode(parser.NodeBinaryExpressionLeftExpr))
	parentType := leftScope.ResolvedTypeRef(db.scopegraph.TypeGraph())

	optimized, wasOptimized := db.buildOptimizedBinaryOperatorExpression(node, parentType, leftExpr, rightExpr)
	if wasOptimized {
		return optimized
	}

	callExpr := codedom.MemberCall(codedom.StaticMemberReference(operator, parentType, node), operator, []codedom.Expression{leftExpr, rightExpr}, node)
	if modifier != nil {
		return modifier(callExpr)
	}

	return callExpr
}
예제 #2
0
// buildTemplateStringExpression builds the CodeDOM for a template string expression.
func (db *domBuilder) buildTemplateStringExpression(node compilergraph.GraphNode) codedom.Expression {
	member, found := db.scopegraph.TypeGraph().StringType().ParentModule().FindMember("formatTemplateString")
	if !found {
		panic("Missing formatTemplateString under String's module")
	}

	return db.buildTemplateStringCall(node, codedom.StaticMemberReference(member, db.scopegraph.TypeGraph().StringTypeReference(), node), false)
}
예제 #3
0
// buildLoopExpression builds the CodeDOM for a loop expression.
func (db *domBuilder) buildLoopExpression(node compilergraph.GraphNode) codedom.Expression {
	member, found := db.scopegraph.TypeGraph().StreamType().ParentModule().FindMember("MapStream")
	if !found {
		panic("Missing MapStream function under Stream's module")
	}

	// Retrieve the item type for the members of the stream and the mapped values.
	mapExpr := node.GetNode(parser.NodeLoopExpressionMapExpression)
	namedValue := node.GetNode(parser.NodeLoopExpressionNamedValue)

	namedScope, _ := db.scopegraph.GetScope(namedValue)
	namedItemType := namedScope.AssignableTypeRef(db.scopegraph.TypeGraph())

	mapScope, _ := db.scopegraph.GetScope(mapExpr)
	mappedItemType := mapScope.ResolvedTypeRef(db.scopegraph.TypeGraph())

	// Build a reference to the Map function.
	mapFunctionReference := codedom.FunctionCall(
		codedom.StaticMemberReference(member, db.scopegraph.TypeGraph().StreamTypeReference(mappedItemType), node),
		[]codedom.Expression{
			codedom.TypeLiteral(namedItemType, node),
			codedom.TypeLiteral(mappedItemType, node),
		},
		node)

	// A loop expression is replaced with a call to the Map function, with the stream as the first parameter
	// and a mapper function which resolves the mapped value as the second.
	builtMapExpr := db.buildExpression(mapExpr)
	builtStreamExpr := db.getExpression(node, parser.NodeLoopExpressionStreamExpression)

	loopValueName := namedValue.Get(parser.NodeNamedValueName)
	mapperFunction := codedom.FunctionDefinition(
		[]string{},
		[]string{loopValueName},
		codedom.Resolution(builtMapExpr, builtMapExpr.BasisNode()),
		false,
		codedom.NormalFunction,
		builtMapExpr.BasisNode())

	return codedom.AwaitPromise(
		codedom.FunctionCall(mapFunctionReference,
			[]codedom.Expression{builtStreamExpr, mapperFunction},
			node),
		node)
}
예제 #4
0
// buildUnaryOperatorExpression builds the CodeDOM for a unary operator.
func (db *domBuilder) buildUnaryOperatorExpression(node compilergraph.GraphNode, modifier exprModifier) codedom.Expression {
	scope, _ := db.scopegraph.GetScope(node)
	operator, _ := scope.CalledOperator(db.scopegraph.TypeGraph())

	if operator.IsNative() {
		return db.buildNativeUnaryExpression(node, operatorMap[node.Kind()])
	}

	childScope, _ := db.scopegraph.GetScope(node.GetNode(parser.NodeUnaryExpressionChildExpr))
	parentType := childScope.ResolvedTypeRef(db.scopegraph.TypeGraph())

	childExpr := db.getExpression(node, parser.NodeUnaryExpressionChildExpr)
	callExpr := codedom.MemberCall(codedom.StaticMemberReference(operator, parentType, node), operator, []codedom.Expression{childExpr}, node)
	if modifier != nil {
		return modifier(callExpr)
	}

	return callExpr
}
예제 #5
0
// buildNamedAccess builds the CodeDOM for a member access expression.
func (db *domBuilder) buildNamedAccess(node compilergraph.GraphNode, name string, childExprNode *compilergraph.GraphNode) codedom.Expression {
	scope, _ := db.scopegraph.GetScope(node)
	namedReference, hasNamedReference := db.scopegraph.GetReferencedName(scope)

	// Reference to an unknown name or a nullable member access must be a dynamic access.
	if !hasNamedReference || node.Kind() == parser.NodeNullableMemberAccessExpression {
		return codedom.DynamicAccess(db.buildExpression(*childExprNode), name, node)
	}

	// Reference to a local name is a var or parameter.
	if namedReference.IsLocal() {
		return codedom.LocalReference(namedReference.Name(), node)
	}

	// Check for a reference to a type.
	if typeRef, isType := namedReference.Type(); isType {
		return codedom.StaticTypeReference(typeRef, node)
	}

	// Check for a reference to a member.
	if memberRef, isMember := namedReference.Member(); isMember {
		// If the member is under a child expression, build as an access expression.
		if childExprNode != nil {
			childExpr := db.buildExpression(*childExprNode)

			_, underFuncCall := node.TryGetIncomingNode(parser.NodeFunctionCallExpressionChildExpr)
			isAliasedFunctionReference := scope.ResolvedTypeRef(db.scopegraph.TypeGraph()).HasReferredType(db.scopegraph.TypeGraph().FunctionType())

			if isAliasedFunctionReference && !underFuncCall {
				return codedom.DynamicAccess(childExpr, memberRef.Name(), node)
			} else {
				return codedom.MemberReference(childExpr, memberRef, node)
			}
		} else {
			// This is a direct access of a static member. Generate an access under the module.
			return codedom.StaticMemberReference(memberRef, db.scopegraph.TypeGraph().AnyTypeReference(), node)
		}
	}

	panic("Unknown kind of named access")
	return nil
}
예제 #6
0
// generateMemberReference generates the expression for a reference to a module or type member.
func (eg *expressionGenerator) generateMemberReference(memberReference *codedom.MemberReferenceNode, context generationContext) esbuilder.ExpressionBuilder {
	// If the target member is implicitly called, then this is a property that needs to be accessed via a call.
	if memberReference.Member.IsImplicitlyCalled() {
		basisNode := memberReference.BasisNode()
		memberCall := codedom.MemberCall(
			codedom.NativeAccess(memberReference.ChildExpression, memberReference.Member.Name(), basisNode),
			memberReference.Member,
			[]codedom.Expression{},
			basisNode)

		return eg.generateExpression(memberCall, context)
	}

	// This handles the native new case for WebIDL. We should probably handle this directly.
	if memberReference.Member.IsStatic() && !memberReference.Member.IsPromising() {
		return eg.generateExpression(codedom.StaticMemberReference(memberReference.Member, eg.scopegraph.TypeGraph().AnyTypeReference(), memberReference.BasisNode()), context)
	}

	childExpr := eg.generateExpression(memberReference.ChildExpression, context)
	return childExpr.Member(eg.pather.GetMemberName(memberReference.Member))
}