Skip to content

Commit 817b936

Browse files
fourlscirras
authored andcommitted
Fix single statement resolution in if, for, and with
1 parent 69fdcf2 commit 817b936

File tree

2 files changed

+62
-16
lines changed

2 files changed

+62
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3838

3939
- Exception when parsing fully qualified attribute references.
4040
- `DuplicatedDeclarationException` errors caused by some local scopes being modeled incorrectly.
41+
- Name resolution issues around `if`, `else`, `for`, and `with` constructs when the body contains a single statement.
4142

4243
## [1.4.0] - 2024-04-02
4344

delphi-frontend/src/main/java/au/com/integradev/delphi/antlr/ast/visitors/SymbolTableVisitor.java

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ public Data visit(CompoundStatementNode node, Data data) {
343343
|| node.getParent() instanceof ForStatementNode) {
344344
return DelphiParserVisitor.super.visit(node, data);
345345
}
346-
return createLocalScope(node, data);
346+
return visitNewLocalScope(node, data);
347347
}
348348

349349
@Override
@@ -541,16 +541,16 @@ public Data visit(AnonymousMethodNode node, Data data) {
541541

542542
@Override
543543
public Data visit(TryStatementNode node, Data data) {
544-
createLocalScope(node.getStatementList(), data);
544+
visitNewLocalScope(node.getStatementList(), data);
545545
if (node.hasExceptBlock()) {
546546
ExceptBlockNode exceptBlock = node.getExceptBlock();
547547
if (exceptBlock.isBareExcept()) {
548-
createLocalScope(exceptBlock.getStatementList(), data);
548+
visitNewLocalScope(exceptBlock.getStatementList(), data);
549549
} else {
550550
DelphiParserVisitor.super.visit(exceptBlock, data);
551551
}
552552
} else if (node.hasFinallyBlock()) {
553-
return createLocalScope(node.getFinallyBlock().getStatementList(), data);
553+
return visitNewLocalScope(node.getFinallyBlock().getStatementList(), data);
554554
}
555555
return data;
556556
}
@@ -561,24 +561,26 @@ public Data visit(IfStatementNode node, Data data) {
561561

562562
StatementNode thenStatement = node.getThenStatement();
563563
if (thenStatement instanceof CompoundStatementNode) {
564+
// A local scope already gets created for CompoundStatements
564565
thenStatement.accept(this, data);
565566
} else if (thenStatement != null) {
566-
createLocalScope(thenStatement, data);
567+
visitNewLocalScopeFromRoot(thenStatement, data);
567568
}
568569

569570
StatementNode elseStatement = node.getElseStatement();
570571
if (elseStatement instanceof CompoundStatementNode) {
572+
// A local scope already gets created for CompoundStatements
571573
elseStatement.accept(this, data);
572574
} else if (elseStatement != null) {
573-
createLocalScope(elseStatement, data);
575+
visitNewLocalScopeFromRoot(elseStatement, data);
574576
}
575577

576578
return data;
577579
}
578580

579581
@Override
580582
public Data visit(ElseBlockNode node, Data data) {
581-
return createLocalScope(node, data);
583+
return visitNewLocalScope(node, data);
582584
}
583585

584586
@Override
@@ -590,7 +592,7 @@ public Data visit(ForToStatementNode node, Data data) {
590592
node.getTargetExpression().accept(this, data);
591593
node.getVariable().accept(this, data);
592594

593-
return visitScope(node.getStatement(), data);
595+
return visitScopeFromRoot(node.getStatement(), data);
594596
}
595597

596598
@Override
@@ -601,7 +603,7 @@ public Data visit(ForInStatementNode node, Data data) {
601603
node.getEnumerable().accept(this, data);
602604
node.getVariable().accept(this, data);
603605

604-
return visitScope(node.getStatement(), data);
606+
return visitScopeFromRoot(node.getStatement(), data);
605607
}
606608

607609
@Override
@@ -612,12 +614,12 @@ public Data visit(ForLoopVarReferenceNode node, Data data) {
612614

613615
@Override
614616
public Data visit(WhileStatementNode node, Data data) {
615-
return createLocalScope(node, data);
617+
return visitNewLocalScope(node, data);
616618
}
617619

618620
@Override
619621
public Data visit(RepeatStatementNode node, Data data) {
620-
return createLocalScope(node, data);
622+
return visitNewLocalScope(node, data);
621623
}
622624

623625
@Override
@@ -637,7 +639,7 @@ public Data visit(WithStatementNode node, Data data) {
637639
data.addScope(scope, node);
638640
scope.setParent(parent);
639641

640-
return visitScope(node.getStatement(), data);
642+
return visitScopeFromRoot(node.getStatement(), data);
641643
}
642644

643645
private static DelphiScope getTargetScope(ExpressionNode target) {
@@ -658,12 +660,12 @@ private static DelphiScope getTargetScope(ExpressionNode target) {
658660

659661
@Override
660662
public Data visit(CaseStatementNode node, Data data) {
661-
return createLocalScope(node, data);
663+
return visitNewLocalScope(node, data);
662664
}
663665

664666
@Override
665667
public Data visit(CaseItemStatementNode node, Data data) {
666-
return createLocalScope(node, data);
668+
return visitNewLocalScope(node, data);
667669
}
668670

669671
@Override
@@ -673,7 +675,7 @@ public Data visit(LabelStatementNode node, Data data) {
673675
// doesn't get its own local scope!
674676
// This is probably a poorly thought-out compiler optimization.
675677
if (node.getChildIndex() > 0) {
676-
return createLocalScope(node, data);
678+
return visitNewLocalScope(node, data);
677679
}
678680
return DelphiParserVisitor.super.visit(node, data);
679681
}
@@ -802,11 +804,30 @@ private Data createDeclarationScope(DelphiNode node, Data data) {
802804
return visitScope(node, data);
803805
}
804806

805-
private Data createLocalScope(DelphiNode node, Data data) {
807+
/**
808+
* Creates a new local scope attached to a node, visits that node's children, then pops the scope.
809+
*
810+
* @param node the node to attach the scope to, then visit the children of.
811+
* @param data the symbol table data.
812+
* @return the symbol table data.
813+
*/
814+
private Data visitNewLocalScope(DelphiNode node, Data data) {
806815
data.addScope(new LocalScopeImpl(), node);
807816
return visitScope(node, data);
808817
}
809818

819+
/**
820+
* Creates a new local scope attached to a node, visits that node, then pops the scope.
821+
*
822+
* @param node the node to attach the scope to, then visit.
823+
* @param data the symbol table data.
824+
* @return the symbol table data.
825+
*/
826+
private Data visitNewLocalScopeFromRoot(DelphiNode node, Data data) {
827+
data.addScope(new LocalScopeImpl(), node);
828+
return visitScopeFromRoot(node, data);
829+
}
830+
810831
private Data createTypeScope(TypeDeclarationNode node, Data data) {
811832
TypeScopeImpl typeScope = new TypeScopeImpl();
812833
data.addScope(typeScope, node.getTypeNode());
@@ -863,14 +884,38 @@ private Data createUnitScope(DelphiAst node, Data data) {
863884
return visitScope(node, data);
864885
}
865886

887+
/**
888+
* Visits all children of a node, then pops the innermost scope.
889+
*
890+
* @param node the node to visit the children of (generally the root node of the innermost scope).
891+
* @param data the symbol table data.
892+
* @return the symbol table data.
893+
*/
866894
private Data visitScope(DelphiNode node, Data data) {
867895
if (node != null) {
896+
// Visits all children of this node
868897
DelphiParserVisitor.super.visit(node, data);
869898
}
870899
data.scopes.pop();
871900
return data;
872901
}
873902

903+
/**
904+
* Visits a node, then pops the innermost scope.
905+
*
906+
* @param node the node to visit (generally the root node of the innermost scope).
907+
* @param data the symbol table data.
908+
* @return the symbol table data.
909+
*/
910+
private Data visitScopeFromRoot(DelphiNode node, Data data) {
911+
if (node != null) {
912+
// Visits this node
913+
node.accept(this, data);
914+
}
915+
data.scopes.pop();
916+
return data;
917+
}
918+
874919
private static void handleImplementationDeclaration(
875920
NameDeclaration declaration, DelphiNode node) {
876921
if (node.getFirstParentOfType(ImplementationSectionNode.class) != null) {

0 commit comments

Comments
 (0)