Skip to content

Commit 37023e6

Browse files
committed
ST6-ST13: parser fixes, constexpr tracking, ArrayList semantics, E0005
Parser fixes: - Member pointer params: int Widget::* dp, int (Widget::*mp)(int) const - Ref-to-array params: int (&arr)[10], int (*arr)[10] - ->* operator as single token - Template non-type params: int T::* Field, int (T::*Method)(int) const - &Widget::value as template arg (non-type template arg) - sizeof in parsePrimary with full expression preservation - Wide string literals: L"...", u"...", U"...", u8"..." - Adjacent string literal concatenation - enum underlying type: enum class Color : int - enum value initializers: Red = 1, Green = 2 - if constexpr - for-loop multi-decl init: for (int i=0, j=10; ...) - for-loop comma update: i++, j-- - volatile qualifier in all contexts - Variable templates: pi<float> - template<typename T> using Alias = ... (template aliases) - static_assert passthrough - constexpr constructor detection in struct body - parsePrimary: sizeof renders actual content CodeGen fixes: - FunctionDecl.isConstexpr field added to AstDecl - constexpr functions emitted with constexpr keyword - constexpr functions hoisted to namespace scope - new Foo() in value context strips new (emitDeclaratorTail) - emitForStmt: Block init for multi-decl for-loop - emitParamList: ref-to-array and member fn ptr param decoding - decltype(expr) preserved verbatim (not converted to auto) - using X = ... type aliases deferred after struct definitions - static_assert emitted as TopLevelStatement (inside namespace) - enum forward decls emitted before function forward decls CppBuild fixes: - constexpr functions hoisted to namespace scope - auto/std::function variables hoisted to namespace scope - diamond operator expansion: new ArrayList<>() -> ArrayList<T>() - E0005: ArrayList.get() value-copy detection with website URL - getWebsiteBaseUrl() reads from config/cppmode.properties - expandDiamondOperator() in javaToC Processing.h fixes: - #include <climits> for INT_MAX/INT_MIN - color template constructors for mixed int/float args - ArrayList<T,true> add(T v) by-value overload - ArrayList<T,true> get() returns T* (pointer semantics)
1 parent e2b5426 commit 37023e6

9 files changed

Lines changed: 2376 additions & 328 deletions

File tree

config/cppmode.properties

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
mkdir -p ~/sketchbook/modes/CppMode/config
2-
cat > ~/sketchbook/modes/CppMode/config/cppmode.properties << 'EOF'
31
# Single source of truth for CppMode-wide settings. Both CppBuild.java
42
# and scripts/rebuild-engine.sh read this file directly, so changing
53
# either value here updates behavior everywhere at once instead of

mode/CppMode.jar

20.8 KB
Binary file not shown.

src/Processing.h

Lines changed: 347 additions & 32 deletions
Large diffs are not rendered by default.

src/java/AstDecl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,17 @@ record VariableDecl(
5858
Expr initializer,
5959
boolean isConst,
6060
boolean isStatic,
61+
List<String> templateParams,
6162
int line,
6263
int col,
6364
List<CppLexerToken> leadingComments
6465
) implements TopLevelItem {
66+
VariableDecl(TypeRef type, String name, List<Expr> arrayDims,
67+
Expr initializer, boolean isConst, boolean isStatic,
68+
int line, int col, List<CppLexerToken> leadingComments) {
69+
this(type, name, arrayDims, initializer, isConst, isStatic,
70+
List.of(), line, col, leadingComments);
71+
}
6572
}
6673

6774

@@ -109,6 +116,7 @@ record FunctionDecl(
109116
boolean isVirtual,
110117
boolean isOverride,
111118
boolean isConst,
119+
boolean isConstexpr,
112120
boolean isStatic,
113121
boolean isPureVirtual, // "= 0" specifier -- distinct from body==null (an ordinary forward
114122
// declaration also has a null body but should NOT render "= 0")

src/java/AstPasses.java

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ public static Result hoist(List<TopLevelItem> items) {
8080
}
8181
}
8282

83+
// Deduplicate: drop empty forward declarations when a full definition exists.
84+
java.util.Map<String, TypeDef> best = new java.util.LinkedHashMap<>();
85+
for (TypeDef td : classBlocks) {
86+
String name = td.name();
87+
TypeDef existing = best.get(name);
88+
if (existing == null) {
89+
best.put(name, td);
90+
} else if (!td.members().isEmpty() && existing.members().isEmpty()) {
91+
best.put(name, td); // full definition beats forward declaration
92+
}
93+
}
94+
classBlocks = new ArrayList<>(best.values());
95+
8396
boolean changed = true;
8497
for (int pass = 0; pass < classBlocks.size() * 2 && changed; pass++) {
8598
changed = false;
@@ -293,6 +306,35 @@ public static boolean containsCall(Node root, String name) {
293306
return new Finder(name, true).visit(root);
294307
}
295308

309+
public static boolean containsBareFunctionCall(Node root) {
310+
return new BareFunctionCallFinder().visit(root);
311+
}
312+
313+
private static final class BareFunctionCallFinder {
314+
boolean visit(Node n) {
315+
if (n == null) return false;
316+
if (n instanceof CallExpr c) {
317+
if (c.callee() instanceof Identifier) return true;
318+
for (var arg : c.args()) if (visit(arg)) return true;
319+
return visit(c.callee());
320+
}
321+
if (n instanceof Block b) { for (var s : b.statements()) if (visit(s)) return true; }
322+
if (n instanceof ExprStatement es) return visit(es.expr());
323+
if (n instanceof ReturnStatement rs) return visit(rs.value());
324+
if (n instanceof IfStatement ifs) return visit(ifs.condition()) || visit(ifs.thenBranch()) || visit(ifs.elseBranch());
325+
if (n instanceof WhileStatement ws) return visit(ws.condition()) || visit(ws.body());
326+
if (n instanceof ForStatement fs) return visit(fs.init()) || visit(fs.condition()) || visit(fs.update()) || visit(fs.body());
327+
if (n instanceof DeclStatement ds) return visit(ds.initializer());
328+
if (n instanceof BinaryExpr b) return visit(b.left()) || visit(b.right());
329+
if (n instanceof UnaryExpr u) return visit(u.operand());
330+
if (n instanceof AssignExpr ae) return visit(ae.target()) || visit(ae.value());
331+
if (n instanceof MemberAccessExpr m) return visit(m.target());
332+
if (n instanceof TernaryExpr t) return visit(t.condition()) || visit(t.thenExpr()) || visit(t.elseExpr());
333+
if (n instanceof FunctionDecl fd) return visit(fd.body());
334+
return false;
335+
}
336+
}
337+
296338
private static final class Finder {
297339
final String name;
298340
final boolean callOnly;
@@ -471,13 +513,30 @@ private static Result inject(TypeDef td) {
471513
if (!hasAnyMethod(td)) {
472514
return new Result(td, false);
473515
}
516+
// Only inject _PSketch if the class actually uses Processing API.
517+
// Classes that only use operators and member access (like Vec3) are
518+
// pure data types -- injecting _PSketch breaks aggregate initialization.
519+
if (!usesBareFunctionCalls(td)) {
520+
return new Result(td, false);
521+
}
474522
List<String> newBases = new ArrayList<>(td.baseClasses());
475-
newBases.add("virtual _PSketch"); // codegen renders "public " prefix; see CodeGen notes if/when wired in
523+
newBases.add("virtual _PSketch");
476524
TypeDef injected = new TypeDef(td.kind(), td.name(), td.templateParams(), newBases, td.members(),
477525
td.line(), td.col(), td.leadingComments());
478526
return new Result(injected, true);
479527
}
480528

529+
private static boolean usesBareFunctionCalls(TypeDef td) {
530+
for (TopLevelItem member : td.members()) {
531+
if (member instanceof FunctionDecl fd && fd.body() != null) {
532+
if (NameUsageScanner.containsBareFunctionCall(fd)) {
533+
return true;
534+
}
535+
}
536+
}
537+
return false;
538+
}
539+
481540
/**
482541
* True if this TypeDef has at least one FunctionDecl member. The
483542
* original's "&& !body.contains(\"constexpr\")" exclusion is not
@@ -539,7 +598,7 @@ public static List<FunctionDecl> generate(List<FunctionDecl> hoistedFunctions) {
539598
fd.returnType(), fd.name(), fd.templateParams(), fd.params(),
540599
fd.initializerList(), null /* body -- this is what makes it a forward decl */,
541600
fd.isConstructor(), fd.isDestructor(), fd.isVirtual(), fd.isOverride(),
542-
fd.isConst(), fd.isStatic(), false /* isPureVirtual -- never applies to a hoisted free function */,
601+
fd.isConst(), fd.isConstexpr(), fd.isStatic(), false /* isPureVirtual -- never applies to a hoisted free function */,
543602
fd.line(), fd.col(), List.of() /* no comments on the forward decl */
544603
));
545604
}

0 commit comments

Comments
 (0)