Skip to content

Commit 43ecc58

Browse files
committed
Fix typechecker bug for chained field access primary prefix
1 parent 7441d11 commit 43ecc58

File tree

4 files changed

+46
-12
lines changed

4 files changed

+46
-12
lines changed

src/types/ast/astExtractor/expression-extractor.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ import {
4646
DimensionExpression,
4747
Expression,
4848
ExpressionName,
49-
FieldAccess,
5049
Primary
5150
} from '../types/blocks-and-statements'
5251
import { Location } from '../types'
@@ -317,13 +316,17 @@ export class ExpressionExtractor extends BaseJavaCstVisitorWithDefaults {
317316
fqnOrRefType(ctx: FqnOrRefTypeCtx) {
318317
const firstPart = this.visit(ctx.fqnOrRefTypePartFirst)
319318
if (ctx.Dot && ctx.fqnOrRefTypePartRest) {
320-
const expressionName = this.visit(ctx.fqnOrRefTypePartRest) as ExpressionName
321-
return {
322-
kind: 'FieldAccess',
323-
identifier: expressionName.name,
324-
primary: firstPart,
325-
location: expressionName.location
326-
} as FieldAccess
319+
let result: Primary = firstPart
320+
for (const fqnOrRefTypePartRest of ctx.fqnOrRefTypePartRest) {
321+
const expressionName = this.visit(fqnOrRefTypePartRest) as ExpressionName
322+
result = {
323+
kind: 'FieldAccess',
324+
identifier: expressionName.name,
325+
primary: result,
326+
location: expressionName.location
327+
}
328+
}
329+
return result
327330
}
328331
return firstPart
329332
}

src/types/checker/__tests__/classes.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,21 @@ const testcases: {
119119
}
120120
`,
121121
result: { type: null, errors: [] }
122+
},
123+
{
124+
input: `
125+
class StaticMember {
126+
static String staticVariable = "Static Variable";
127+
static void staticMethod() { System.out.println("Static method."); }
128+
}
129+
public class Main {
130+
public static void main(String[] args) {
131+
System.out.println(StaticMember.staticVariable); // Access static variable
132+
StaticMember.staticMethod(); // Call static method
133+
}
134+
}
135+
`,
136+
result: { type: null, errors: [] }
122137
}
123138
]
124139

src/types/checker/environment.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
import * as NonPrimitives from '../types/nonPrimitives'
22
import * as Primitives from '../types/primitives'
3-
import { Method } from '../types/methods'
3+
import { Method, MethodSignature, Parameter } from '../types/methods'
44
import { Type } from '../types/type'
55
import { CannotFindSymbolError, VariableAlreadyDefinedError } from '../errors'
66
import { Array } from '../types/arrays'
7+
import { ClassImpl } from '../types/classes'
78
import { isArrayType, removeArraySuffix } from './arrays'
89

10+
const SYSTEM_CLASS = new ClassImpl('System')
11+
const PRINTSTREAM_CLASS = new ClassImpl('PrintStream')
12+
SYSTEM_CLASS.setField('out', PRINTSTREAM_CLASS)
13+
const PRINTLN_METHOD_SIGNATURE = new MethodSignature()
14+
PRINTLN_METHOD_SIGNATURE.parameters.addParameter(
15+
new Parameter('message', new NonPrimitives.String())
16+
)
17+
const PRINTLN_METHOD = new Method(PRINTLN_METHOD_SIGNATURE)
18+
PRINTSTREAM_CLASS.setMethod('println', PRINTLN_METHOD)
19+
920
const GLOBAL_TYPE_ENVIRONMENT: { [key: string]: Type } = {
1021
boolean: new Primitives.Boolean(),
1122
byte: new Primitives.Byte(),
@@ -25,8 +36,9 @@ const GLOBAL_TYPE_ENVIRONMENT: { [key: string]: Type } = {
2536
Long: new NonPrimitives.Long(),
2637
Short: new NonPrimitives.Short(),
2738
String: new NonPrimitives.String(),
28-
// TODO: Fix to array type
29-
'String[]': new NonPrimitives.String()
39+
40+
// Hard coded variables
41+
System: SYSTEM_CLASS
3042
}
3143

3244
export class Frame {

src/types/checker/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Type } from '../types/type'
55
import {
66
ArrayRequiredError,
77
BadOperandTypesError,
8+
CannotFindSymbolError,
89
IncompatibleTypesError,
910
NotApplicableToExpressionTypeError,
1011
VariableAlreadyDefinedError
@@ -272,7 +273,10 @@ export const typeCheckBody = (node: Node, frame: Frame = Frame.globalFrame()): R
272273
return OK_RESULT
273274
}
274275
case 'ExpressionName': {
275-
const type = frame.getVariable(node.name)
276+
const variable = frame.getVariable(node.name)
277+
if (!(variable instanceof Error)) return newResult(variable)
278+
if (!(variable instanceof CannotFindSymbolError)) return newResult(null, [variable])
279+
const type = frame.getType(node.name)
276280
if (type instanceof Error) return newResult(null, [type])
277281
return newResult(type)
278282
}

0 commit comments

Comments
 (0)