Skip to content

Commit

Permalink
Add support for long numeric type
Browse files Browse the repository at this point in the history
  • Loading branch information
waleedyaseen committed Nov 24, 2023
1 parent 5201b7e commit 7d499c3
Show file tree
Hide file tree
Showing 13 changed files with 362 additions and 220 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# intellij-runescript Changelog

## [Unreleased]
- Add support for long numeric type.

## [1.4.1] - 2023-10-16

Expand Down
401 changes: 206 additions & 195 deletions src/main/gen/io/runescript/plugin/lang/lexer/_RsLexer.java

Large diffs are not rendered by default.

20 changes: 17 additions & 3 deletions src/main/gen/io/runescript/plugin/lang/parser/RsParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ static boolean parse_root_(IElementType t, PsiBuilder b, int l) {
create_token_set_(ARITHMETIC_EXPRESSION, ARITHMETIC_VALUE_EXPRESSION, ARRAY_ACCESS_EXPRESSION, BOOLEAN_LITERAL_EXPRESSION,
CALC_EXPRESSION, COMMAND_EXPRESSION, CONDITION_EXPRESSION, CONSTANT_EXPRESSION,
COORD_LITERAL_EXPRESSION, DYNAMIC_EXPRESSION, EXPRESSION, GOSUB_EXPRESSION,
INTEGER_LITERAL_EXPRESSION, LOCAL_VARIABLE_EXPRESSION, NULL_LITERAL_EXPRESSION, PAR_EXPRESSION,
RELATIONAL_VALUE_EXPRESSION, SCOPED_VARIABLE_EXPRESSION, STRING_INTERPOLATION_EXPRESSION, STRING_LITERAL_EXPRESSION,
SWITCH_CASE_DEFAULT_EXPRESSION),
INTEGER_LITERAL_EXPRESSION, LOCAL_VARIABLE_EXPRESSION, LONG_LITERAL_EXPRESSION, NULL_LITERAL_EXPRESSION,
PAR_EXPRESSION, RELATIONAL_VALUE_EXPRESSION, SCOPED_VARIABLE_EXPRESSION, STRING_INTERPOLATION_EXPRESSION,
STRING_LITERAL_EXPRESSION, SWITCH_CASE_DEFAULT_EXPRESSION),
};

/* ********************************************************** */
Expand Down Expand Up @@ -776,6 +776,7 @@ public static boolean IntegerLiteralExpression(PsiBuilder b, int l) {

/* ********************************************************** */
// IntegerLiteralExpression
// | LongLiteralExpression
// | CoordLiteralExpression
// | BooleanLiteralExpression
// | NullLiteralExpression
Expand All @@ -785,6 +786,7 @@ static boolean LiteralExpression(PsiBuilder b, int l) {
boolean r;
Marker m = enter_section_(b, l, _NONE_, null, "<Expression>");
r = IntegerLiteralExpression(b, l + 1);
if (!r) r = LongLiteralExpression(b, l + 1);
if (!r) r = CoordLiteralExpression(b, l + 1);
if (!r) r = BooleanLiteralExpression(b, l + 1);
if (!r) r = NullLiteralExpression(b, l + 1);
Expand Down Expand Up @@ -936,6 +938,18 @@ private static boolean LogicalOrWrapper_1(PsiBuilder b, int l) {
return true;
}

/* ********************************************************** */
// LONG
public static boolean LongLiteralExpression(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "LongLiteralExpression")) return false;
if (!nextTokenIs(b, "<Expression>", LONG)) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, LONG_LITERAL_EXPRESSION, "<Expression>");
r = consumeToken(b, LONG);
exit_section_(b, l, m, r, false, null);
return r;
}

/* ********************************************************** */
// IDENTIFIER | DEFINE_TYPE | TYPE_LITERAL | ARRAY_TYPE_LITERAL | WHILE | IF | TRUE | FALSE | NULL | SWITCH
public static boolean NameLiteral(PsiBuilder b, int l) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public interface RsElementTypes {
IElementType INTEGER_LITERAL_EXPRESSION = new RsElementType("INTEGER_LITERAL_EXPRESSION");
IElementType LOCAL_VARIABLE_DECLARATION_STATEMENT = new RsElementType("LOCAL_VARIABLE_DECLARATION_STATEMENT");
IElementType LOCAL_VARIABLE_EXPRESSION = StubElementTypeFactory.create("LOCAL_VARIABLE_EXPRESSION");
IElementType LONG_LITERAL_EXPRESSION = new RsElementType("LONG_LITERAL_EXPRESSION");
IElementType NAME_LITERAL = StubElementTypeFactory.create("NAME_LITERAL");
IElementType NULL_LITERAL_EXPRESSION = new RsElementType("NULL_LITERAL_EXPRESSION");
IElementType PARAMETER = StubElementTypeFactory.create("PARAMETER");
Expand Down Expand Up @@ -80,6 +81,7 @@ public interface RsElementTypes {
IElementType INTEGER = new RsElementType("INTEGER");
IElementType LBRACE = new RsElementType("{");
IElementType LBRACKET = new RsElementType("[");
IElementType LONG = new RsElementType("LONG");
IElementType LPAREN = new RsElementType("(");
IElementType LT = new RsElementType("<");
IElementType LTE = new RsElementType("<=");
Expand Down Expand Up @@ -187,6 +189,9 @@ else if (type == LOCAL_VARIABLE_DECLARATION_STATEMENT) {
else if (type == LOCAL_VARIABLE_EXPRESSION) {
return new RsLocalVariableExpressionImpl(node);
}
else if (type == LONG_LITERAL_EXPRESSION) {
return new RsLongLiteralExpressionImpl(node);
}
else if (type == NAME_LITERAL) {
return new RsNameLiteralImpl(node);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This class is automatically generated. Do not edit.
package io.runescript.plugin.lang.psi;

import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;

public interface RsLongLiteralExpression extends RsExpression {

@NotNull
PsiElement getLong();

}
4 changes: 4 additions & 0 deletions src/main/gen/io/runescript/plugin/lang/psi/RsVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ public void visitLocalVariableExpression(@NotNull RsLocalVariableExpression o) {
// visitNamedElement(o);
}

public void visitLongLiteralExpression(@NotNull RsLongLiteralExpression o) {
visitExpression(o);
}

public void visitNameLiteral(@NotNull RsNameLiteral o) {
visitPsiElement(o);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This class is automatically generated. Do not edit.
package io.runescript.plugin.lang.psi.impl;

import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import static io.runescript.plugin.lang.psi.RsElementTypes.*;
import io.runescript.plugin.lang.psi.*;

public class RsLongLiteralExpressionImpl extends RsExpressionImpl implements RsLongLiteralExpression {

public RsLongLiteralExpressionImpl(@NotNull ASTNode node) {
super(node);
}

@Override
public void accept(@NotNull RsVisitor visitor) {
visitor.visitLongLiteralExpression(this);
}

@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof RsVisitor) accept((RsVisitor)visitor);
else super.accept(visitor);
}

@Override
@NotNull
public PsiElement getLong() {
return notNullChild(findChildByType(LONG));
}

}
2 changes: 2 additions & 0 deletions src/main/grammars/RuneScript.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,13 @@ ScopedVariableExpression ::= '%' NameLiteral {
}

private LiteralExpression ::= IntegerLiteralExpression
| LongLiteralExpression
| CoordLiteralExpression
| BooleanLiteralExpression
| NullLiteralExpression
| StringLiteralExpression
IntegerLiteralExpression ::= INTEGER
LongLiteralExpression ::= LONG
CoordLiteralExpression ::= COORDGRID
BooleanLiteralExpression ::= TRUE | FALSE
NullLiteralExpression ::= NULL
Expand Down
4 changes: 4 additions & 0 deletions src/main/grammars/RuneScript.flex
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ IDENTIFIER = ({IDENTIFIER_PART})+
DECIMAL_DIGIT = [0-9]
HEX_DIGIT = [0-9a-fA-F]
HEX_INTEGER = 0[xX]({HEX_DIGIT})+
LONG_HEX_INTEGER = 0[xX]({HEX_DIGIT})+ [lL]
DECIMAL_INTEGER = (({DECIMAL_DIGIT})+)
LONG_DECIMAL_INTEGER = (({DECIMAL_DIGIT})+) [lL]
COORDGRID = {DECIMAL_INTEGER}_{DECIMAL_INTEGER}_{DECIMAL_INTEGER}_{DECIMAL_INTEGER}_{DECIMAL_INTEGER}
INTEGER = ([-+]?)(({DECIMAL_INTEGER})|({HEX_INTEGER}))
LONG = ([-+]?)(({LONG_DECIMAL_INTEGER})|({LONG_HEX_INTEGER}))
STRING_ESCAPE_SEQUENCE=\\([abfnrtv\'\"\\])
STRING_PART = [^\"\r\n<\\]+

Expand Down Expand Up @@ -99,6 +102,7 @@ INCOMPLETE_TAG = "<"(shad|col|str|u|img)"="
\" { pushState(STRING); return STRING_START; }

{COORDGRID} { return COORDGRID; }
{LONG} { return LONG; }
{INTEGER} { return INTEGER; }


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class RsInlayParameterHintsProvider : InlayParameterHintsProvider {
unwrappedExpression = unwrappedExpression.expression
}
return unwrappedExpression !is RsIntegerLiteralExpression
&& unwrappedExpression !is RsLongLiteralExpression
&& unwrappedExpression !is RsBooleanLiteralExpression
&& unwrappedExpression !is RsStringLiteralExpression
&& unwrappedExpression !is RsNullLiteralExpression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ class RsControlFlowBuilder : ControlFlowBuilder() {
addInstruction(o)
}

override fun visitLongLiteralExpression(o: RsLongLiteralExpression) {
addInstruction(o)
}

override fun visitCoordLiteralExpression(o: RsCoordLiteralExpression) {
addInstruction(o)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class RsSyntaxHighlighter(private val lexerInfo: RsLexerInfo) : SyntaxHighlighte
init {
attributes[IDENTIFIER] = RsSyntaxHighlighterColors.IDENTIFIER
attributes[INTEGER] = RsSyntaxHighlighterColors.NUMBER
attributes[LONG] = RsSyntaxHighlighterColors.NUMBER
fillMap(attributes, KEYWORDS, RsSyntaxHighlighterColors.KEYWORD)
attributes[TYPE_LITERAL] = RsSyntaxHighlighterColors.TYPE_LITERAL
attributes[ARRAY_TYPE_LITERAL] = RsSyntaxHighlighterColors.ARRAY_TYPE_LITERAL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,38 +117,51 @@ class RsTypeInferenceVisitor(private val myInferenceData: RsTypeInference) : RsV
return RsTupleType(flatten())
}

private fun checkTypeMismatch(context: PsiElement, actualType: RsType?, expectedType: RsType?) {
private fun checkTypeMismatchAll(context: PsiElement, actualType: RsType?, expectedTypes: List<RsType>): Boolean {

Check warning on line 120 in src/main/kotlin/io/runescript/plugin/lang/psi/type/inference/RsTypeInferenceVisitor.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Function "checkTypeMismatchAll" is never used
return expectedTypes.all { checkTypeMismatch(context, actualType, it, false) }
}

private fun checkTypeMismatch(
context: PsiElement,
actualType: RsType?,
expectedType: RsType?,
reportError: Boolean = true
): Boolean {
val unfoldedActualType = actualType.unfold() ?: RsErrorType
val unfoldedExpectedType = expectedType.unfold() ?: RsErrorType
if (unfoldedActualType is RsErrorType || unfoldedExpectedType is RsErrorType) {
return
return false
}
if (unfoldedActualType is RsTupleType && RsErrorType in unfoldedActualType.types) {
return
return false
}
if (unfoldedExpectedType is RsTupleType && RsErrorType in unfoldedExpectedType.types) {
return
return false
}
if (unfoldedExpectedType == RsPrimitiveType.OBJ && unfoldedActualType == RsPrimitiveType.NAMEDOBJ) {
// namedobj extends obj
return
return true
}
if (unfoldedExpectedType == RsPrimitiveType.FONTMETRICS && unfoldedActualType == RsPrimitiveType.GRAPHIC) {
// graphic extends fontmetrics
return
return true
}
if (unfoldedExpectedType.isHookType() && unfoldedActualType == RsPrimitiveType.STRING) {
// hooks are just strings that are parsed different.
return
return true
}
if (unfoldedActualType != unfoldedExpectedType) {
context.error(
"Type mismatch: '%s' was given but '%s' was expected".format(
unfoldedActualType.representation,
unfoldedExpectedType.representation
if (reportError) {
context.error(
"Type mismatch: '%s' was given but '%s' was expected".format(
unfoldedActualType.representation,
unfoldedExpectedType.representation
)
)
)
}
return false
}
return true
}

override fun visitGosubExpression(o: RsGosubExpression) {
Expand Down Expand Up @@ -280,10 +293,19 @@ class RsTypeInferenceVisitor(private val myInferenceData: RsTypeInference) : RsV
o.left.accept(this)

if (valueRequiredType != null) {
o.right.typeHint = o.right.typeHint ?: o.left.type
o.right.typeHint = o.left.type ?: o.right.typeHint
o.right.accept(this)
checkTypeMismatch(o.left, valueRequiredType)
checkTypeMismatch(o.right, valueRequiredType)
if (op.isRelational()) {
var expectedType = o.left.type ?: o.right.type
if (expectedType != RsPrimitiveType.LONG) {
expectedType = valueRequiredType
}
checkTypeMismatch(o.left, expectedType)
checkTypeMismatch(o.right, expectedType)
} else {
checkTypeMismatch(o.left, valueRequiredType)
checkTypeMismatch(o.right, valueRequiredType)
}
} else {
o.right.typeHint = o.left.type
o.right.accept(this)
Expand Down Expand Up @@ -416,11 +438,10 @@ class RsTypeInferenceVisitor(private val myInferenceData: RsTypeInference) : RsV
o.statementList.accept(this)
}


override fun visitCalcExpression(o: RsCalcExpression) {
o.type = RsPrimitiveType.INT
o.type = o.typeHint ?: RsPrimitiveType.INT

o.expression.typeHint = RsPrimitiveType.INT
o.expression.typeHint = o.typeHint ?: RsPrimitiveType.INT
o.expression.accept(this)
}

Expand Down Expand Up @@ -485,10 +506,10 @@ class RsTypeInferenceVisitor(private val myInferenceData: RsTypeInference) : RsV
}

override fun visitArithmeticExpression(o: RsArithmeticExpression) {
o.left.typeHint = RsPrimitiveType.INT
o.left.typeHint = o.typeHint ?: RsPrimitiveType.INT
o.left.accept(this)

o.right.typeHint = RsPrimitiveType.INT
o.right.typeHint = o.typeHint ?: RsPrimitiveType.INT
o.right.accept(this)
}

Expand Down Expand Up @@ -540,16 +561,31 @@ class RsTypeInferenceVisitor(private val myInferenceData: RsTypeInference) : RsV
val trimmedValue: String
if (value.startsWith("0x")) {
radix = 16
trimmedValue = value.substring(2)
trimmedValue = value.substring(2, value.length)
} else {
radix = 10
trimmedValue = value
trimmedValue = value.substring(0, value.length)
}
if (trimmedValue.toIntOrNull(radix) == null) {
o.error("Could not convert constant value '${value}' to an integer number.")
}
}

RsPrimitiveType.LONG -> {
val radix: Int
val trimmedValue: String
val endIndex = if (value.endsWith('L', ignoreCase = true)) value.length - 1 else value.length
if (value.startsWith("0x")) {
radix = 16
trimmedValue = value.substring(2, endIndex)
} else {
radix = 10
trimmedValue = value.substring(0, endIndex)
}
if (trimmedValue.toLongOrNull(radix) == null) {
o.error("Could not convert constant value '${value}' to a long number.")
}
}
else -> {
val configReference = RsSymbolIndex.lookup(o.project, type, value)
if (configReference == null) {
Expand Down Expand Up @@ -578,6 +614,10 @@ class RsTypeInferenceVisitor(private val myInferenceData: RsTypeInference) : RsV
o.type = RsPrimitiveType.INT
}

override fun visitLongLiteralExpression(o: RsLongLiteralExpression) {
o.type = RsPrimitiveType.LONG
}

override fun visitCoordLiteralExpression(o: RsCoordLiteralExpression) {
o.type = RsPrimitiveType.COORD
}
Expand Down Expand Up @@ -624,6 +664,12 @@ class RsTypeInferenceVisitor(private val myInferenceData: RsTypeInference) : RsV
?.toTypedArray<RsType>()
checkExpressionList(o, o.expressionList, expectedReturnList ?: emptyArray<RsType>())
}
companion object {
private val ALLOWED_RELATIONAL_TYPES = arrayOf(

Check warning on line 668 in src/main/kotlin/io/runescript/plugin/lang/psi/type/inference/RsTypeInferenceVisitor.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "ALLOWED_RELATIONAL_TYPES" is never used
RsPrimitiveType.INT,
RsPrimitiveType.LONG
)
}
}

private fun RsScript.findCommandHandler(): CommandHandler {
Expand Down

0 comments on commit 7d499c3

Please sign in to comment.