Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.5.1 #209

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

2.5.1 #209

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# TON Plugin for the IntelliJ IDEs Changelog

## [2.5.1]

### Added
- Tolk 0.8 support

## [2.5.0]

### Added
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
org.gradle.jvmargs=-Xmx4096m
pluginGroup=org.ton
pluginVersion=2.5.0
pluginVersion=2.5.1
publishChannel=release
publishToken=token
enableBuildSearchableOptions=false
Expand All @@ -9,7 +9,7 @@ enableBuildSearchableOptions=false
# https://www.jetbrains.com/intellij-repository/snapshots/
ideaVersion=2024.3
kotlin.stdlib.default.dependency=false
buildNumber=17
buildNumber=1

platformType=IC
platformVersion=2024.3
Expand Down
10 changes: 6 additions & 4 deletions modules/tolk/src/org/ton/intellij/tolk/parser/TolkParser.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,7 @@ Var ::= IDENTIFIER (':' TypeExpression)? {
extends = VarDefinition
}

DotExpression ::= Expression '.' CallExpression {
pin=2
DotExpression ::= Expression '.' (IntegerExpression|CallExpression) {
methods=[
left="/Expression[0]"
right="/Expression[1]"
Expand Down Expand Up @@ -570,7 +569,7 @@ private TupleElement ::= Expression {
}
private TupleElement_recovery ::= !(','|']'|';')

private IntegerExpression ::= INTEGER_LITERAL
IntegerExpression ::= INTEGER_LITERAL
private BoolExpression ::= 'true' | 'false'
private NullExpression ::= 'null' !'('

Expand Down Expand Up @@ -626,8 +625,11 @@ TypeExpression ::= FunType | UnionType | AtomicType {
]
}

private AtomicType ::= AutoType | VoidType | TensorOrParenType | TupleType | NullType | TypeIdentifier
private AtomicType ::= NullableType | AutoType | VoidType | TensorOrParenType | TupleType | NullType | TypeIdentifier

NullableType ::= (TensorOrParenType|TupleType|TypeIdentifier) '?' {
mixin="org.ton.intellij.tolk.psi.impl.TolkNullableTypeMixin"
}
UnionType ::= unionType1 | unionType2
NullType ::= 'null' {
mixin="org.ton.intellij.tolk.psi.impl.TolkNullTypeMixin"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.lang.ASTNode
import org.ton.intellij.tolk.psi.TolkDotExpression
import org.ton.intellij.tolk.type.TolkType
import org.ton.intellij.tolk.type.infer.inference

abstract class TolkDotExpressionMixin(node: ASTNode) : ASTWrapperPsiElement(node), TolkDotExpression {
override val type: TolkType? get() = right?.type
override val type: TolkType? get() = inference?.getType(this)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.ton.intellij.tolk.psi.impl

import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.lang.ASTNode
import org.ton.intellij.tolk.psi.TolkFieldExpression
import org.ton.intellij.tolk.type.TolkType
import org.ton.intellij.tolk.type.infer.inference

abstract class TolkFieldExpressionMixin(node: ASTNode) : ASTWrapperPsiElement(node), TolkFieldExpression {
override val type: TolkType? get() = inference?.getType(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import org.ton.intellij.tolk.psi.TolkNullType
import org.ton.intellij.tolk.type.TolkType

abstract class TolkNullTypeMixin(node: ASTNode) : ASTWrapperPsiElement(node), TolkNullType {
override val type: TolkType get() = TolkType.Unknown
override val type: TolkType get() = TolkType.Null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.ton.intellij.tolk.psi.impl

import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.lang.ASTNode
import org.ton.intellij.tolk.psi.TolkNullableType
import org.ton.intellij.tolk.type.TolkType

abstract class TolkNullableTypeMixin(node: ASTNode) : ASTWrapperPsiElement(node), TolkNullableType {
override val type: TolkType? get() {
return TolkType.nullable(typeExpression.type ?: return null)
}
}
27 changes: 26 additions & 1 deletion modules/tolk/src/org/ton/intellij/tolk/type/TolkType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,19 @@ sealed interface TolkType {
class UnionType(
val elements: List<TolkType>
) : TolkType {
override fun toString(): String = elements.joinToString(" | ")
init {
check(elements.size > 1) { "UnionType must have at least two elements, got ${elements.size}: $elements" }
}
val hasNull = elements.any { it == Null }
val isNullable = elements.size == 2 && hasNull && !elements.all { it == Null }

override fun toString(): String {
return if (isNullable) {
"${elements.first { it != Null }}?"
} else {
elements.joinToString(" | ")
}
}
}

companion object {
Expand All @@ -64,6 +76,18 @@ sealed interface TolkType {
val Tuple = TolkPrimitiveType.Tuple
val Unit = TolkPrimitiveType.Unit
val Bool = TolkPrimitiveType.Bool
val Null = TolkPrimitiveType.Null

fun nullable(element: TolkType): TolkType {
return if (element is UnionType) {
if (element.hasNull) element
else UnionType(element.elements + Null)
} else if (element != Null) {
UnionType(listOf(element, Null))
} else {
element
}
}

fun create(vararg elements: TolkType): TolkType {
return create(elements.toList())
Expand Down Expand Up @@ -100,6 +124,7 @@ sealed class TolkPrimitiveType(
object Tuple : TolkPrimitiveType("tuple")
object Unit : TolkPrimitiveType("()")
object Bool : TolkPrimitiveType("bool")
object Null : TolkPrimitiveType("null")

override fun toString(): String = name
}
Expand Down
35 changes: 30 additions & 5 deletions modules/tolk/src/org/ton/intellij/tolk/type/infer/TypeInference.kt
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ class TolkInferenceWalker(
is TolkTupleExpression -> infer(element, expectedType)
is TolkParenExpression -> infer(element, expectedType)
is TolkTensorExpression -> infer(element, expectedType)
is TolkFieldExpression -> infer(element, expectedType)
is TolkReferenceExpression -> infer(element)
is TolkLiteralExpression -> element.type
is TolkUnitExpression -> TolkType.Unit
Expand Down Expand Up @@ -551,12 +552,20 @@ class TolkInferenceWalker(
element: TolkDotExpression,
expectedType: TolkType? = null,
): TolkType? {
infer(element.left)
val leftType = infer(element.left)
val type = element.right?.let { expression ->
if (expression is TolkCallExpression) {
infer(expression, expectedType, withFirstArg = element.left)
} else {
infer(expression, expectedType)
when (expression) {
is TolkCallExpression -> infer(expression, expectedType, withFirstArg = element.left)
is TolkIntegerExpression -> {
val typeElementIndex = expression.integerLiteral.text.toIntOrNull() ?: return@let null
val typeElements = when (leftType) {
is TolkType.TypedTuple -> leftType.elements
is TolkType.Tensor -> leftType.elements
else -> null
}
typeElements?.getOrNull(typeElementIndex)
}
else -> null
}
}
return ctx.setType(element, type ?: expectedType)
Expand Down Expand Up @@ -604,16 +613,19 @@ class TolkInferenceWalker(
unify(paramType.inputType, argType.inputType)
unify(paramType.returnType, argType.returnType)
}

paramType is TolkType.TypedTuple && argType is TolkType.TypedTuple -> {
paramType.elements.zip(argType.elements).forEach { (param, arg) ->
unify(param, arg)
}
}

paramType is TolkType.Tensor && argType is TolkType.Tensor -> {
paramType.elements.zip(argType.elements).forEach { (param, arg) ->
unify(param, arg)
}
}

paramType is TolkType.ParameterType && argType != null && argType !is TolkType.ParameterType -> {
typeMapping[paramType.psiElement] = argType
}
Expand Down Expand Up @@ -659,6 +671,19 @@ class TolkInferenceWalker(
)
}

// private fun infer(element: TolkFieldExpression, expectedType: TolkType? = null): TolkType? {
// val expressions = element.expressionList
// val left = expressions.getOrNull(0) ?: return null
// val leftType = infer(left) ?: return null
// val typeElements = when (leftType) {
// is TolkType.Tensor -> leftType.elements
// is TolkType.TypedTuple -> leftType.elements
// else -> return null
// }
// val rightIndex = element.integerLiteral?.text?.toIntOrNull() ?: return null
// return ctx.setType(element, typeElements.getOrNull(rightIndex) ?: expectedType)
// }

private fun infer(element: TolkTupleExpression, expectedType: TolkType? = null): TolkType? {
val expectedTypes = (expectedType as? TolkType.TypedTuple)?.elements
val expressions = element.expressionList
Expand Down
5 changes: 5 additions & 0 deletions modules/tolk/src/org/ton/intellij/tolk/type/printTolkType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ fun PresentationTreeBuilder.printTolkType(type: TolkType) {
}

is TolkType.UnionType -> {
if (type.isNullable) {
printTolkType(type.elements.first { it != TolkType.Null })
text("?")
return
}
val iterator = type.elements.iterator()
while (iterator.hasNext()) {
val element = iterator.next()
Expand Down