Skip to content

Commit 045d883

Browse files
authored
Merge pull request #41 from neilccbrown/bug-fixes
Fix a couple of bugs in type inference
2 parents 85ea3e8 + 31f7b4e commit 045d883

9 files changed

Lines changed: 53 additions & 6 deletions

File tree

tpParser/shared/src/main/scala/tigerpython/parser/ast/AstNode.scala

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,9 @@ object AstNode {
459459
override def isValidAssignTarget: Boolean = true
460460
override def toString: String = "(%s)".format(names.mkString(", "))
461461
}
462-
case class BooleanValue(pos: Int, value: Boolean) extends Expression(AstNodeKind.CONSTANT) {
462+
case class BooleanValue(pos: Int, value: Boolean) extends Expression(AstNodeKind.CONSTANT) with Span {
463+
// `True`/`False` are fixed-width keywords, so the end position needs no extra state to track.
464+
def endPos: Int = pos + (if (value) 4 else 5)
463465
def notToString: String = if (value) "False" else "True"
464466
override def toString: String = if (value) "True" else "False"
465467
}
@@ -471,26 +473,34 @@ object AstNode {
471473
def apply(token: Token): Value = {
472474
val result = new Value(token.pos, ValueType.fromTokenType(token.tokenType))
473475
result.value = token.value
476+
result.endPos = token.endPos
474477
result
475478
}
476479
def apply(pos: Int, intValue: Int): Value = {
477480
val result = new Value(pos, ValueType.INTEGER)
478481
result.value = intValue.toString
482+
result.endPos = pos + result.value.length
479483
result
480484
}
481485
}
482-
case class Value(pos: Int, valueType: ValueType.Value) extends Expression(AstNodeKind.CONSTANT) {
486+
case class Value(pos: Int, valueType: ValueType.Value) extends Expression(AstNodeKind.CONSTANT) with Span {
483487
var value: String = _
488+
// Defaults to a zero-width span at `pos` for values not constructed from a real source token
489+
// (e.g. synthetic placeholders inserted during error recovery); real construction sites set
490+
// this from the originating token's `endPos`.
491+
var endPos: Int = pos
484492
def createNegative(): Value =
485493
if (value != null && value != "" &&
486494
(valueType == ValueType.INTEGER || valueType == ValueType.FLOAT)) {
487495
if (value(0) == '-') {
488496
val result = Value(pos + 1, valueType)
489497
result.value = value.drop(1)
498+
result.endPos = result.pos + result.value.length
490499
result
491500
} else {
492501
val result = Value(pos - 1, valueType)
493502
result.value = "-" + value
503+
result.endPos = result.pos + result.value.length
494504
result
495505
}
496506
} else

tpParser/shared/src/main/scala/tigerpython/parser/parsing/ExpressionParser.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -648,16 +648,24 @@ class ExpressionParser(val parser: Parser, val parserState: ParserState) {
648648
checkMissingOperator(tokens)
649649
val result = AstNode.Value(token.pos, ValueType.FLOAT)
650650
result.value = token.value
651+
result.endPos = token.endPos
651652
result
652653
case TokenType.INT | TokenType.LONG =>
653654
checkMissingOperator(tokens)
654655
val result = AstNode.Value(token.pos, ValueType.INTEGER)
655656
result.value = token.value
657+
result.endPos = token.endPos
656658
result
657659
case TokenType.COMPLEX =>
658-
AstNode.Value(token.pos, ValueType.COMPLEX)
660+
val result = AstNode.Value(token.pos, ValueType.COMPLEX)
661+
result.value = token.value
662+
result.endPos = token.endPos
663+
result
659664
case TokenType.NONE =>
660-
AstNode.Value(token.pos, ValueType.NONE)
665+
val result = AstNode.Value(token.pos, ValueType.NONE)
666+
result.value = token.value
667+
result.endPos = token.endPos
668+
result
661669
case TokenType.TRUE =>
662670
AstNode.BooleanValue(token.pos, value = true)
663671
case TokenType.FALSE =>
@@ -679,7 +687,9 @@ class ExpressionParser(val parser: Parser, val parserState: ParserState) {
679687
case TokenType.BYTEARRAY =>
680688
while (tokens.hasType(TokenType.BYTEARRAY))
681689
tokens.next()
682-
AstNode.Value(token.pos, ValueType.BYTE_ARRAY)
690+
val result = AstNode.Value(token.pos, ValueType.BYTE_ARRAY)
691+
result.endPos = tokens.prevEndPos
692+
result
683693
case TokenType.LEFT_PARENS =>
684694
// Check for Lisp-Syntax
685695
if (tokens.getIndex <= 1 && tokens.peekType(1) == TokenType.NAME)

tpParser/shared/src/main/scala/tigerpython/utilities/completer/Completer.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,12 @@ class Completer(val moduleName: String,
116116
}
117117
nameWalker.getNodeForPosition(caretPos) match {
118118
case Some(prefixName) =>
119-
val tokenRange = tokenLine.getTokenRange(prefixName.endPos, caretPos)
119+
// `getTokenRange` includes tokens whose `pos` equals `caretPos` (its upper bound is
120+
// inclusive), but a token starting exactly at the caret lies after it, not within the
121+
// range up to it -- e.g. the `)` closing an enclosing call immediately after the caret
122+
// in `wrap((expr).<caret>)`. Left in, that stray token breaks the length/last-token
123+
// checks below, so it's filtered out here.
124+
val tokenRange = tokenLine.getTokenRange(prefixName.endPos, caretPos).filter(_.pos < caretPos)
120125
if (0 < tokenRange.length && tokenRange.length <= 2 && tokenRange(0).tokenType == TokenType.DOT) {
121126
val n = if (filterType == FilterType.IMPORT_FROM)
122127
scope.findName(moduleBase, prefixName)

tpParser/shared/src/main/scala/tigerpython/utilities/scopes/Scope.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ abstract class Scope {
148148
Some(types.BuiltinTypes.LIST)
149149
case _: AstNode.StringValue =>
150150
Some(types.BuiltinTypes.STRING)
151+
case expr: AstNode.Expression =>
152+
// Catch-all for literal/expression kinds with no bespoke case above (int/float/complex/none
153+
// literals, booleans, unary/binary ops, comparisons, ...): TypeAstWalker.getType already
154+
// knows how to resolve these, so delegate rather than falling through to None, which would
155+
// make e.g. `(5).bit_length` unresolvable and fall back to a full builtin-name dump.
156+
Some(typeAstWalker.getType(expr))
151157
case _ =>
152158
None
153159
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 4
2+
# bit_length
3+
(5).
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 9
2+
# bit_length
3+
wrap((5).)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 19
2+
# capitalize;center;count;decode;encode;endswith;expandtabs;find;format;index;isalnum;isalpha;isdigit;islower;isspace;istitle;isupper;join;ljust;lower;lstrip;partition;replace;rfind;rindex;rjust;rpartition;rsplit;rstrip;split;splitlines;startswith;strip;swapcase;title;translate;upper;zfill
3+
wrap(("a".upper()).)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 11
2+
# capitalize;center;count;decode;encode;endswith;expandtabs;find;format;index;isalnum;isalpha;isdigit;islower;isspace;istitle;isupper;join;ljust;lower;lstrip;partition;replace;rfind;rindex;rjust;rpartition;rsplit;rstrip;split;splitlines;startswith;strip;swapcase;title;translate;upper;zfill
3+
wrap(("a").)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# 47
2+
# capitalize;center;count;decode;encode;endswith;expandtabs;find;format;index;isalnum;isalpha;isdigit;islower;isspace;istitle;isupper;join;ljust;lower;lstrip;partition;replace;rfind;rindex;rjust;rpartition;rsplit;rstrip;split;splitlines;startswith;strip;swapcase;title;translate;upper;zfill
3+
myString = "Hello from Strype"
4+
wrap((myString).)

0 commit comments

Comments
 (0)