Skip to content

Commit 05603dc

Browse files
cirrasfourls
authored andcommitted
Defer the injection of intrinsic routines into System
Some intrinsic routines reference types that are declared in the `interface` section of `System`, meaning they shouldn't be injected until the `implementation` section is reached. However, intrinsic types and constants are referenced within the `interface` section and should be injected at the beginning.
1 parent 2c1bd08 commit 05603dc

File tree

4 files changed

+96
-35
lines changed

4 files changed

+96
-35
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import au.com.integradev.delphi.type.TypeUtils;
5555
import au.com.integradev.delphi.type.factory.ClassReferenceTypeImpl;
5656
import au.com.integradev.delphi.type.factory.PointerTypeImpl;
57+
import au.com.integradev.delphi.type.intrinsic.IntrinsicsInjector;
5758
import com.google.common.base.Preconditions;
5859
import com.google.common.collect.Iterables;
5960
import java.nio.file.Path;
@@ -269,6 +270,22 @@ public Data visit(DelphiAst node, Data data) {
269270
return super.visit(node, data);
270271
}
271272

273+
@Override
274+
public Data visit(InterfaceSectionNode node, Data data) {
275+
DelphiScope scope = Objects.requireNonNull(data.getUnitDeclaration()).getScope();
276+
277+
if (scope instanceof SystemScope) {
278+
IntrinsicsInjector injector = new IntrinsicsInjector(data.typeFactory);
279+
injector.injectTypes(scope);
280+
injector.injectConstants(scope);
281+
super.visit(node, data);
282+
injector.injectRoutines(scope);
283+
return data;
284+
}
285+
286+
return super.visit(node, data);
287+
}
288+
272289
@Override
273290
public Data visit(ImplementationSectionNode node, Data data) {
274291
return data;

delphi-frontend/src/main/java/au/com/integradev/delphi/symbol/scope/SystemScopeImpl.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
*/
1919
package au.com.integradev.delphi.symbol.scope;
2020

21-
import au.com.integradev.delphi.type.intrinsic.IntrinsicsInjector;
2221
import org.sonar.plugins.communitydelphi.api.symbol.declaration.NameDeclaration;
2322
import org.sonar.plugins.communitydelphi.api.symbol.declaration.TypeNameDeclaration;
2423
import org.sonar.plugins.communitydelphi.api.symbol.scope.SystemScope;
@@ -32,12 +31,6 @@ public class SystemScopeImpl extends FileScopeImpl implements SystemScope {
3231

3332
public SystemScopeImpl(TypeFactory typeFactory) {
3433
super("System");
35-
injectIntrinsics(typeFactory);
36-
}
37-
38-
private void injectIntrinsics(TypeFactory typeFactory) {
39-
IntrinsicsInjector injector = new IntrinsicsInjector(typeFactory);
40-
injector.inject(this);
4134
}
4235

4336
@Override
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Sonar Delphi Plugin
3+
* Copyright (C) 2025 Integrated Application Development
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this program; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
18+
*/
19+
package au.com.integradev.delphi.type.intrinsic;
20+
21+
import org.sonar.plugins.communitydelphi.api.type.IntrinsicType;
22+
23+
final class IntrinsicConstant {
24+
private final String name;
25+
private final IntrinsicType type;
26+
27+
public IntrinsicConstant(String name, IntrinsicType type) {
28+
this.name = name;
29+
this.type = type;
30+
}
31+
32+
public String getName() {
33+
return name;
34+
}
35+
36+
public IntrinsicType getType() {
37+
return type;
38+
}
39+
}

delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,32 +56,45 @@
5656
import au.com.integradev.delphi.symbol.scope.DelphiScopeImpl;
5757
import au.com.integradev.delphi.type.factory.TypeFactoryImpl;
5858
import java.util.ArrayList;
59-
import java.util.Arrays;
6059
import java.util.List;
6160
import org.sonar.plugins.communitydelphi.api.symbol.declaration.RoutineNameDeclaration;
6261
import org.sonar.plugins.communitydelphi.api.symbol.declaration.TypeNameDeclaration;
62+
import org.sonar.plugins.communitydelphi.api.symbol.declaration.VariableNameDeclaration;
6363
import org.sonar.plugins.communitydelphi.api.symbol.scope.DelphiScope;
6464
import org.sonar.plugins.communitydelphi.api.type.IntrinsicType;
6565
import org.sonar.plugins.communitydelphi.api.type.Type;
6666
import org.sonar.plugins.communitydelphi.api.type.TypeFactory;
6767

6868
public final class IntrinsicsInjector {
6969
private final TypeFactory typeFactory;
70+
private final List<IntrinsicConstant> constants;
7071
private final List<IntrinsicRoutine.Builder> routines;
71-
private DelphiScopeImpl scope;
7272

7373
public IntrinsicsInjector(TypeFactory typeFactory) {
7474
this.typeFactory = typeFactory;
75+
this.constants = new ArrayList<>();
7576
this.routines = new ArrayList<>();
7677

78+
buildConstants();
7779
buildRoutines();
7880
}
7981

80-
public void inject(DelphiScope scope) {
81-
this.scope = (DelphiScopeImpl) scope;
82-
injectTypes();
83-
injectRoutines();
84-
injectConstants();
82+
public void injectTypes(DelphiScope scope) {
83+
for (IntrinsicType type : IntrinsicType.values()) {
84+
injectType(type, (DelphiScopeImpl) scope);
85+
}
86+
}
87+
88+
public void injectConstants(DelphiScope scope) {
89+
for (IntrinsicConstant constant : constants) {
90+
injectConstant(constant, (DelphiScopeImpl) scope);
91+
}
92+
}
93+
94+
public void injectRoutines(DelphiScope scope) {
95+
for (IntrinsicRoutine.Builder routine : routines) {
96+
injectRoutine(routine, (DelphiScopeImpl) scope);
97+
}
8598
}
8699

87100
private Type type(IntrinsicType type) {
@@ -96,6 +109,16 @@ private Type dynamicArraySizeType() {
96109
return ((TypeFactoryImpl) typeFactory).dynamicArraySizeType();
97110
}
98111

112+
private void buildConstants() {
113+
constant("CompilerVersion", EXTENDED);
114+
constant("MaxInt", INTEGER);
115+
constant("MaxLongInt", LONGINT);
116+
constant("True", BOOLEAN);
117+
constant("False", BOOLEAN);
118+
constant("ReturnAddress", POINTER);
119+
constant("AddressOfReturnAddress", POINTER);
120+
}
121+
99122
private void buildRoutines() {
100123
routine("Abs").param(type(REAL)).returns(type(REAL));
101124
routine("Abs").param(type(INTEGER)).returns(type(INTEGER));
@@ -344,17 +367,17 @@ private void buildRoutines() {
344367
routine("WriteLn").variadic(TypeFactory.untypedType());
345368
}
346369

370+
private void constant(String name, IntrinsicType type) {
371+
constants.add(new IntrinsicConstant(name, type));
372+
}
373+
347374
private IntrinsicRoutine.Builder routine(String name) {
348375
IntrinsicRoutine.Builder builder = IntrinsicRoutine.builder(name);
349376
routines.add(builder);
350377
return builder;
351378
}
352379

353-
private void injectTypes() {
354-
Arrays.stream(IntrinsicType.values()).forEach(this::injectType);
355-
}
356-
357-
private void injectType(IntrinsicType intrinsic) {
380+
private void injectType(IntrinsicType intrinsic, DelphiScopeImpl scope) {
358381
SymbolicNode node = SymbolicNode.imaginary(intrinsic.simpleName(), scope);
359382
Type type = typeFactory.getIntrinsic(intrinsic);
360383
TypeNameDeclaration declaration =
@@ -363,11 +386,7 @@ private void injectType(IntrinsicType intrinsic) {
363386
scope.addDeclaration(declaration);
364387
}
365388

366-
private void injectRoutines() {
367-
routines.forEach(this::injectRoutine);
368-
}
369-
370-
private void injectRoutine(IntrinsicRoutine.Builder builder) {
389+
private void injectRoutine(IntrinsicRoutine.Builder builder, DelphiScopeImpl scope) {
371390
IntrinsicRoutine routine = builder.build();
372391
SymbolicNode node = SymbolicNode.imaginary(routine.simpleName(), scope);
373392
RoutineNameDeclaration declaration =
@@ -376,18 +395,11 @@ private void injectRoutine(IntrinsicRoutine.Builder builder) {
376395
scope.addDeclaration(declaration);
377396
}
378397

379-
private void injectConstants() {
380-
injectConstant("CompilerVersion", EXTENDED);
381-
injectConstant("MaxInt", INTEGER);
382-
injectConstant("MaxLongInt", LONGINT);
383-
injectConstant("True", BOOLEAN);
384-
injectConstant("False", BOOLEAN);
385-
injectConstant("ReturnAddress", POINTER);
386-
injectConstant("AddressOfReturnAddress", POINTER);
387-
}
398+
private void injectConstant(IntrinsicConstant constant, DelphiScopeImpl scope) {
399+
String name = constant.getName();
400+
Type type = type(constant.getType());
401+
VariableNameDeclaration declaration = VariableNameDeclarationImpl.constant(name, type, scope);
388402

389-
private void injectConstant(String image, IntrinsicType intrinsic) {
390-
var declaration = VariableNameDeclarationImpl.constant(image, type(intrinsic), scope);
391403
scope.addDeclaration(declaration);
392404
}
393405
}

0 commit comments

Comments
 (0)