Skip to content

Commit

Permalink
Ready to replace
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Jul 22, 2024
1 parent 637cc6f commit da8ba63
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -659,8 +659,8 @@ class ScopeManager : ScopeProvider {
}

/**
<<<<<<< HEAD
=======
* <<<<<<< HEAD
* =======
* This function tries to resolve a [CallExpression] into its matching [FunctionDeclaration] (or
* multiple functions, if applicable). The result is returned in the form of a
* [CallResolutionResult] which holds detail information about intermediate results as well as
Expand Down Expand Up @@ -758,8 +758,8 @@ class ScopeManager : ScopeProvider {
}

/**
>>>>>>> 1cde93a3c6 (Preparing to use CallResolutionResult in member call resolution)
* This function extracts a scope for the [Name], e.g. if the name is fully qualified. `null` is
* >>>>>>> 1cde93a3c6 (Preparing to use CallResolutionResult in member call resolution) This
* function extracts a scope for the [Name], e.g. if the name is fully qualified. `null` is
* returned, if no scope can be extracted.
*
* The pair returns the extracted scope and a name that is adjusted by possible import aliases.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ interface HasScope {
* Specifies that this node (e.g. a [BinaryOperator] contains an operation that can be overloaded by
* an [OperatorDeclaration].
*/
interface HasOverloadedOperation : HasLanguage, HasOperatorCode {
interface HasOverloadedOperation : HasLanguage, HasOperatorCode, HasNameAndLocation {

/**
* Arguments forwarded to the operator. This might not necessarily be all of the regular
Expand All @@ -147,5 +147,5 @@ interface HasOverloadedOperation : HasLanguage, HasOperatorCode {
* The base expression this operator works on. The [Type] of this is also the source where the
* [SymbolResolver] is looking for an overloaded [OperatorDeclaration].
*/
val operatorBase: HasType
val operatorBase: Expression
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ open class BinaryOperator :
get() = listOf(rhs)

/** The binary operator operators on the [lhs]. [rhs] is part of the [operatorArguments]. */
override val operatorBase: HasType
override val operatorBase: Expression
get() = lhs

override fun equals(other: Any?): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ open class CallExpression :
* is overloaded. In this case we want the [operatorBase] to point to [callee], so we can take
* its type to lookup the necessary [OperatorDeclaration].
*/
override val operatorBase: HasType
override val operatorBase: Expression
get() = callee

override fun equals(other: Any?): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class MemberExpression : Reference(), HasOverloadedOperation, ArgumentHolder, Ha
override val operatorArguments: List<Expression>
get() = listOf()

override val operatorBase: HasType
override val operatorBase: Expression
get() = base

override fun toString(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class UnaryOperator : Expression(), HasOverloadedOperation, ArgumentHolder, HasT
get() = listOf()

/** The unary operator operates on [input]. */
override val operatorBase = input
override val operatorBase
get() = input

/** The operator code. */
override var operatorCode: String? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,34 +343,25 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
var member: ValueDeclaration? = null
var type = containingClass

// Check for a possible overloaded operator-> (C++ only?!)
/*if (
// Check for a possible overloaded operator->
if (
reference.language is HasOperatorOverloading &&
reference is MemberExpression &&
reference.operatorCode == "->" &&
reference.base.type !is PointerType
) {
var op =
resolveCalleeByName("operator->", reference)
.filterIsInstance<OperatorDeclaration>()
.singleOrNull()
if (op != null) {
type = op.returnTypes.singleOrNull()?.root ?: unknownType()
// We need to insert a new operator call expression in between
val ref =
newMemberExpression(op.name, reference.base, operatorCode = ".")
.implicit(op.name.localName, location = reference.location)
ref.refersTo = op
var call =
newOperatorCallExpression(operatorCode = "->", ref).codeAndLocationFrom(ref)
call.invokes = listOf(op)
// Make the call our new base
reference.base = call
}
}*/
val result = resolveOperator(reference)
val op = result?.bestViable?.singleOrNull()
if (result?.success == SUCCESSFUL && op is OperatorDeclaration) {
type = op.returnTypes.singleOrNull()?.root ?: unknownType()

// We need to insert a new operator call expression in between
val call = operatorCallFromDeclaration(op, reference)

// Make the call our new base
reference.base = call
}
}

val record = type.recordDeclaration
if (record != null) {
Expand Down Expand Up @@ -422,6 +413,22 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
}
}

private fun operatorCallFromDeclaration(
decl: OperatorDeclaration,
op: HasOverloadedOperation
): OperatorCallExpression {
val ref =
newMemberExpression(decl.name, op.operatorBase, operatorCode = ".")
.implicit(decl.name.localName, location = op.location)
ref.refersTo = decl
val call =
newOperatorCallExpression(operatorCode = op.operatorCode ?: "", ref)
.codeAndLocationFrom(ref)
call.invokes = listOf(decl)

return call
}

// TODO(oxisto): Move to inference class
protected fun handleUnknownField(base: Type, ref: Reference): FieldDeclaration? {
val name = ref.name
Expand Down Expand Up @@ -477,6 +484,7 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
is Reference -> handleReference(currClass, node)
is ConstructExpression -> handleConstructExpression(node)
is CallExpression -> handleCallExpression(node)
is HasOverloadedOperation -> handleOverloadedOperator(node)
}
}

Expand Down Expand Up @@ -758,28 +766,42 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
}
}

private fun handleOverloadedOperator(operator: HasOverloadedOperation) {
val language = operator.language
val base = operator.operatorBase
private fun handleOverloadedOperator(op: HasOverloadedOperation) {
val result = resolveOperator(op)
val decl = result?.bestViable?.singleOrNull() ?: return

// If the result was successful, we can replace the node
if (result.success == SUCCESSFUL && decl is OperatorDeclaration) {
val call = operatorCallFromDeclaration(decl, op)
// TOOD: we do not have the parent :(
}
}

private fun resolveOperator(op: HasOverloadedOperation): CallResolutionResult? {
val language = op.language
val base = op.operatorBase
if (language !is HasOperatorOverloading || language.isPrimitive(base.type)) {
return
return null
}

val symbol = language.overloadedOperatorNames[Pair(operator::class, operator.operatorCode)]
val symbol = language.overloadedOperatorNames[Pair(op::class, op.operatorCode)]
if (symbol == null) {
log.warn(
"Could not resolve operator overloading for unknown operatorCode ${operator.operatorCode}"
"Could not resolve operator overloading for unknown operatorCode ${op.operatorCode}"
)
return
return null
}

// operator.invokes =
// resolveCalleeByName(symbol, operator).filterIsInstance<OperatorDeclaration>()
// TODO: replace with call
/*val ops =
resolveCalleeByName(symbol, null, operator as Expression, base as Expression)
val possibleTypes = mutableSetOf<Type>()
possibleTypes.add(op.operatorBase.type)
possibleTypes.addAll(op.operatorBase.assignedTypes)

val candidates =
resolveMemberByName(symbol, possibleTypes)
.filterIsInstance<OperatorDeclaration>()
println(ops)*/
.toSet()

return resolveWithArguments(candidates, op.operatorArguments, op as Expression)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ open class CPPLanguage :
// There is a sort of weird workaround in C++ to select a prefix vs. postfix operator for
// increment and decrement operators. See
// https://en.cppreference.com/w/cpp/language/operator_incdec
val expr = result.call
val expr = result.source
if (expr is UnaryOperator && (expr.operatorCode == "++" || expr.operatorCode == "--")) {
// If it is a postfix, we need to match for a function with a fake "int" parameter
if (expr.isPostfix) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ class CXXDeclarationTest {
}

@Test
fun testMemberAccess() {
fun testMemberAccessOperator() {
val file = File("src/test/resources/cxx/operators/member_access.cpp")
val result =
analyze(listOf(file), file.parentFile.toPath(), true) {
Expand Down

0 comments on commit da8ba63

Please sign in to comment.