Skip to content

Commit 4db3549

Browse files
committed
Sync desktop changes: parser fixes, CppBuild updates, bundle gcc runtime DLLs
1 parent 239c193 commit 4db3549

8 files changed

Lines changed: 118 additions & 10 deletions

File tree

148 KB
Binary file not shown.

libs/windows-x64/libstdc++-6.dll

2.54 MB
Binary file not shown.
64.4 KB
Binary file not shown.

mode/CppMode.jar

115 Bytes
Binary file not shown.

src/java/AstPasses.java

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,28 +102,73 @@ public static Result hoist(List<TopLevelItem> items) {
102102
classBlocks = new ArrayList<>();
103103
for (String n : order) classBlocks.add(best.get(n));
104104

105+
// Build set of class names for dependency detection
106+
java.util.Set<String> classNames = new java.util.HashSet<>();
107+
for (TypeDef td : classBlocks) classNames.add(td.name());
108+
// Sort: base classes and member-access dependencies before dependent classes
105109
boolean changed = true;
106110
for (int pass = 0; pass < classBlocks.size() * 2 && changed; pass++) {
107111
changed = false;
108112
for (int a = 0; a < classBlocks.size(); a++) {
109113
TypeDef blockA = classBlocks.get(a);
110-
if (blockA.baseClasses().isEmpty()) continue;
111-
String aBase = blockA.baseClasses().get(0);
114+
// Check base class ordering
115+
for (String aBase : blockA.baseClasses()) {
116+
String baseName = aBase.replaceAll("\b(virtual|public|protected|private)\b\s*", "").trim();
117+
int lt = baseName.indexOf('<'); if (lt >= 0) baseName = baseName.substring(0, lt).trim();
118+
for (int b = a + 1; b < classBlocks.size(); b++) {
119+
if (classBlocks.get(b).name().equals(baseName)) {
120+
classBlocks.add(a, classBlocks.remove(b));
121+
changed = true; break;
122+
}
123+
}
124+
if (changed) break;
125+
}
126+
if (changed) break;
127+
// Check member-access dependency: if A uses B's members, B must come first
112128
for (int b = a + 1; b < classBlocks.size(); b++) {
113129
TypeDef blockB = classBlocks.get(b);
114-
if (blockB.name().equals(aBase)) {
115-
classBlocks.set(a, blockB);
116-
classBlocks.set(b, blockA);
117-
changed = true;
118-
break;
130+
if (classDependsOnFull(blockA, blockB.name())) {
131+
classBlocks.add(a, classBlocks.remove(b));
132+
changed = true; break;
119133
}
120134
}
121135
if (changed) break;
122136
}
123137
}
124-
125138
return new Result(classBlocks, rest);
126139
}
140+
/** True if class A accesses members of class B via a B* or B& parameter. */
141+
private static boolean classDependsOnFull(TypeDef a, String bName) {
142+
for (TopLevelItem member : a.members()) {
143+
if (!(member instanceof FunctionDecl fd)) continue;
144+
boolean hasBParam = false;
145+
for (Param p : fd.params()) {
146+
if (p.type() instanceof NamedType nt && nt.baseName().equals(bName)) {
147+
hasBParam = true; break;
148+
}
149+
}
150+
if (!hasBParam) continue;
151+
if (fd.body() != null && containsMemberAccess(fd.body())) return true;
152+
}
153+
return false;
154+
}
155+
private static boolean containsMemberAccess(Node n) {
156+
if (n == null) return false;
157+
if (n instanceof MemberAccessExpr) return true;
158+
if (n instanceof Block b) { for (Statement s : b.statements()) if (containsMemberAccess(s)) return true; return false; }
159+
if (n instanceof ExprStatement es) return containsMemberAccess(es.expr());
160+
if (n instanceof ReturnStatement rs) return containsMemberAccess(rs.value());
161+
if (n instanceof IfStatement ifs) return containsMemberAccess(ifs.condition()) || containsMemberAccess(ifs.thenBranch()) || containsMemberAccess(ifs.elseBranch());
162+
if (n instanceof ForStatement fs) return containsMemberAccess(fs.init()) || containsMemberAccess(fs.condition()) || containsMemberAccess(fs.update()) || containsMemberAccess(fs.body());
163+
if (n instanceof WhileStatement ws) return containsMemberAccess(ws.condition()) || containsMemberAccess(ws.body());
164+
if (n instanceof BinaryExpr be) return containsMemberAccess(be.left()) || containsMemberAccess(be.right());
165+
if (n instanceof AssignExpr ae) return containsMemberAccess(ae.target()) || containsMemberAccess(ae.value());
166+
if (n instanceof CallExpr c) { if (containsMemberAccess(c.callee())) return true; for (Expr a2 : c.args()) if (containsMemberAccess(a2)) return true; return false; }
167+
if (n instanceof DeclStatement ds) return containsMemberAccess(ds.initializer());
168+
if (n instanceof UnaryExpr u) return containsMemberAccess(u.operand());
169+
if (n instanceof TernaryExpr t) return containsMemberAccess(t.condition()) || containsMemberAccess(t.thenExpr()) || containsMemberAccess(t.elseExpr());
170+
return false;
171+
}
127172
}
128173

129174

@@ -332,6 +377,10 @@ public static boolean containsIdentifier(Node root, String name) {
332377
public static boolean containsCall(Node root, String name) {
333378
return new Finder(name, true).visit(root);
334379
}
380+
/** True if name appears as a non-call identifier (value reference, not function call) */
381+
public static boolean containsNonCallIdentifier(Node root, String name) {
382+
return new NonCallFinder(name).visit(root);
383+
}
335384

336385
public static boolean containsBareFunctionCall(Node root) {
337386
return new BareFunctionCallFinder().visit(root);
@@ -362,6 +411,38 @@ boolean visit(Node n) {
362411
}
363412
}
364413

414+
private static final class NonCallFinder {
415+
final String name;
416+
NonCallFinder(String name) { this.name = name; }
417+
boolean visit(Node n) {
418+
if (n == null) return false;
419+
if (n instanceof Identifier id) return id.name().equals(name);
420+
if (n instanceof CallExpr c) {
421+
// Skip callee -- we only want non-call uses
422+
boolean calleeIsTarget = c.callee() instanceof Identifier id && id.name().equals(name);
423+
if (!calleeIsTarget && visit(c.callee())) return true;
424+
for (Expr a : c.args()) if (visit(a)) return true;
425+
return false;
426+
}
427+
if (n instanceof TypeDef td) { for (TopLevelItem m : td.members()) if (visit(m)) return true; return false; }
428+
if (n instanceof FunctionDecl fd) { return fd.body() != null && visit(fd.body()); }
429+
if (n instanceof VariableDecl vd) { return vd.initializer() != null && visit(vd.initializer()); }
430+
if (n instanceof Block b) { for (Statement s : b.statements()) if (visit(s)) return true; return false; }
431+
if (n instanceof ExprStatement es) return visit(es.expr());
432+
if (n instanceof ReturnStatement rs) return visit(rs.value());
433+
if (n instanceof IfStatement ifs) return visit(ifs.condition()) || visit(ifs.thenBranch()) || visit(ifs.elseBranch());
434+
if (n instanceof WhileStatement ws) return visit(ws.condition()) || visit(ws.body());
435+
if (n instanceof ForStatement fs) return visit(fs.init()) || visit(fs.condition()) || visit(fs.update()) || visit(fs.body());
436+
if (n instanceof DeclStatement ds) return ds.initializer() != null && visit(ds.initializer());
437+
if (n instanceof BinaryExpr b) return visit(b.left()) || visit(b.right());
438+
if (n instanceof UnaryExpr u) return visit(u.operand());
439+
if (n instanceof AssignExpr ae) return visit(ae.target()) || visit(ae.value());
440+
if (n instanceof MemberAccessExpr m) return visit(m.target());
441+
if (n instanceof TernaryExpr t) return visit(t.condition()) || visit(t.thenExpr()) || visit(t.elseExpr());
442+
if (n instanceof TopLevelStatement ts) return visit(ts.statement());
443+
return false;
444+
}
445+
}
365446
private static final class Finder {
366447
final String name;
367448
final boolean callOnly;

src/java/CppBuild.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,12 @@ private void checkWindowsDLLs(RunnerListener listener, File binary) throws Excep
670670
dllSources.add(bundledDir);
671671
for (String msysDir : new String[]{"C:\\msys64\\mingw64\\bin","C:\\msys2\\mingw64\\bin"})
672672
dllSources.add(new File(msysDir));
673+
// Also search system PATH entries for gcc runtime DLLs
674+
String syspath = System.getenv("PATH");
675+
if (syspath != null) {
676+
for (String dir : syspath.split(";"))
677+
dllSources.add(new File(dir.trim()));
678+
}
673679

674680
for (String dll : allDlls) {
675681
for (File sourceDir : dllSources) {

src/java/DependencyHoister.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,13 @@ public static Result hoist(List<TopLevelItem> items, List<TypeDef> hoistedClasse
110110
if (lifecycleNames.contains(vd.name())) continue;
111111
if (result.hoistedVariables.contains(vd)) continue;
112112

113-
boolean referencedFromHoisted = isBareIdentifierReferencedByAnyTypeDef(vd.name(), hoistedClasses)
114-
|| isBareIdentifierReferencedByAnyFunctionDecl(vd.name(), result.hoistedFunctions);
113+
// Only hoist if referenced as a VALUE (not as a function call).
114+
// "flock(boids)" is a method call, not a reference to Flock* flock.
115+
boolean referencedFromHoisted =
116+
(isBareIdentifierReferencedByAnyTypeDef(vd.name(), hoistedClasses)
117+
&& !isOnlyCalledByAnyTypeDef(vd.name(), hoistedClasses))
118+
|| (isBareIdentifierReferencedByAnyFunctionDecl(vd.name(), result.hoistedFunctions)
119+
&& !isOnlyCalledByAnyFunctionDecl(vd.name(), result.hoistedFunctions));
115120
if (!referencedFromHoisted) continue;
116121

117122
result.hoistedVariables.add(vd);
@@ -139,6 +144,21 @@ private static boolean isCalledByAnyFunctionDecl(String name, List<FunctionDecl>
139144
return false;
140145
}
141146

147+
private static boolean isOnlyCalledByAnyTypeDef(String name, List<TypeDef> typeDefs) {
148+
// True if name appears ONLY as a callee (never as a bare value reference)
149+
for (TypeDef td : typeDefs) {
150+
if (NameUsageScanner.containsIdentifier(td, name)
151+
&& !NameUsageScanner.containsNonCallIdentifier(td, name)) return true;
152+
}
153+
return false;
154+
}
155+
private static boolean isOnlyCalledByAnyFunctionDecl(String name, List<FunctionDecl> fns) {
156+
for (FunctionDecl fd : fns) {
157+
if (NameUsageScanner.containsIdentifier(fd, name)
158+
&& !NameUsageScanner.containsNonCallIdentifier(fd, name)) return true;
159+
}
160+
return false;
161+
}
142162
private static boolean isBareIdentifierReferencedByAnyTypeDef(String name, List<TypeDef> typeDefs) {
143163
for (TypeDef td : typeDefs) {
144164
if (NameUsageScanner.containsIdentifier(td, name)) return true;

src/java/Parser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,6 +1788,7 @@ private boolean looksLikeParamList() {
17881788
return true; // anonymous param
17891789
}
17901790
return check(CppLexerTokenType.IDENTIFIER)
1791+
|| checkOp("&") || checkOp("*") || checkOp("&&") // ref/ptr param
17911792
|| checkPunct("...") // variadic: "Args... args" or "T..."
17921793
|| checkPunct(",") // next param after anonymous
17931794
|| checkPunct("("); // reference/pointer-to-array param: "int (&arr)[10]"

0 commit comments

Comments
 (0)