Skip to content

Commit b46149e

Browse files
committed
Rounds 4-6: peek fix, mutable lambda, isDefault/isDelete, pack expansion
Critical bug fix: - peek() was mutating pos via skipCommentsAt(), causing wrong token visibility when comments separated tokens from checkKeyword calls Parser: - consteval/constinit added to keyword set and qualifier loops - Explicit template instantiation: template class Foo<int>; - Concept-constrained template params: Numeric T - Global structured binding at top level - Bit field declarations: unsigned int x : 1 - __attribute__((...)): consumed in trailing qualifier position - Args&&... variadic params: isVariadic set from type-level pack expansion - args... pack expansion in function call arguments -> PostfixExpr - Local struct definition: emits via CodeGen.generateNode - isDefault/isDelete properly set in parseFunctionOrConstructorOrDestructor - mutable lambda: stored in LambdaExpr.isMutable AstDecl/AstExpr: - FunctionDecl.isDefault, FunctionDecl.isDelete - LambdaExpr.isMutable CodeGen: - Emit = default / = delete for function declarations - Emit mutable after lambda params, before -> - Trailing return type: auto name(params) -> decltype(...) CppBuild: - TopLevelStatements hoisted to namespace scope (structured bindings) - Explicit template instantiations emitted before namespace Processing
1 parent 3fe0117 commit b46149e

5 files changed

Lines changed: 40 additions & 14 deletions

File tree

mode/CppMode.jar

578 Bytes
Binary file not shown.

src/java/AstExpr.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ record LambdaExpr(
379379
List<Capture> captures,
380380
List<Param> params,
381381
TypeRef returnType,
382+
boolean isMutable,
382383
Block body,
383384
int line,
384385
int col,

src/java/CodeGen.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ public static String renderExpr(Expr e) {
979979
if (p.name() != null) sb.append(' ').append(p.name());
980980
}
981981
sb.append(")");
982+
if (l.isMutable()) sb.append(" mutable");
982983
if (l.returnType() != null) sb.append(" -> ").append(renderTypeRef(l.returnType()));
983984
sb.append(" ");
984985
StringBuilder bodySb = new StringBuilder();

src/java/CppBuild.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,9 @@ private File writeSketchImpl(RunnerListener listener) throws IOException {
12311231
boolean isDeductionGuide = rt.contains("->") && rt.contains("(") && !rt.startsWith("#");
12321232
if (isTypeAlias || isDeductionGuide) {
12331233
deferredAliases.add(item);
1234+
} else if (rt.startsWith("template ") && !rt.startsWith("template<") && !rt.startsWith("template <")) {
1235+
// Explicit template instantiation: must be outside namespace Processing
1236+
preNs.append(CodeGen.generateNode(item, 0));
12341237
} else {
12351238
out.append(CodeGen.generateNode(item, 0));
12361239
}
@@ -1331,8 +1334,19 @@ private File writeSketchImpl(RunnerListener listener) throws IOException {
13311334
&& definedFunctions.contains(fd.name() + "/" + fd.params().size())
13321335
);
13331336

1334-
out.append("struct Sketch : public PApplet {\n");
1337+
// Hoist TopLevelStatements (structured bindings, explicit instantiations) to namespace scope
1338+
List<TopLevelItem> nsHoisted = new ArrayList<>();
1339+
List<TopLevelItem> realMembers = new ArrayList<>();
13351340
for (TopLevelItem item : sketchMembers) {
1341+
if (item instanceof TopLevelStatement) {
1342+
nsHoisted.add(item);
1343+
} else {
1344+
realMembers.add(item);
1345+
}
1346+
}
1347+
for (TopLevelItem item : nsHoisted) out.append(CodeGen.generateNode(item, 0));
1348+
out.append("struct Sketch : public PApplet {\n");
1349+
for (TopLevelItem item : realMembers) {
13361350
out.append(CodeGen.generateNode(item, 1));
13371351
}
13381352
out.append("};\n");

src/java/Parser.java

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -922,9 +922,9 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
922922
int save = pos;
923923
advance();
924924
if (checkKeyword("default")) {
925-
advance(); // = default
925+
advance(); isDefault = true;
926926
} else if (checkKeyword("delete")) {
927-
advance(); // = delete
927+
advance(); isDelete = true;
928928
} else if (checkLiteralZero()) {
929929
advance();
930930
isPureVirtual = true;
@@ -2274,12 +2274,14 @@ private List<Expr> parseArgList() {
22742274
expectPunct("(");
22752275
List<Expr> args = new ArrayList<>();
22762276
if (!checkPunct(")")) {
2277-
args.add(parseExpr());
2278-
matchPunct("..."); // pack expansion: "f(args...)"
2277+
Expr a0 = parseExpr();
2278+
if (matchPunct("...")) a0 = new PostfixExpr("...", a0, a0.line(), a0.col(), List.of());
2279+
args.add(a0);
22792280
while (matchPunct(",")) {
22802281
if (checkPunct(")")) break;
2281-
args.add(parseExpr());
2282-
matchPunct("..."); // pack expansion
2282+
Expr ai = parseExpr();
2283+
if (matchPunct("...")) ai = new PostfixExpr("...", ai, ai.line(), ai.col(), List.of());
2284+
args.add(ai);
22832285
}
22842286
}
22852287
expectPunct(")");
@@ -2671,7 +2673,7 @@ private Expr parseLambda() {
26712673
}
26722674

26732675
// mutable, noexcept, attributes
2674-
matchKeyword("mutable");
2676+
boolean isMutable = matchKeyword("mutable");
26752677
if (checkKeyword("noexcept")) { advance(); if(checkPunct("(")){advance();int _d=1;while(!isAtEnd()&&_d>0){if(checkPunct("("))_d++;else if(checkPunct(")"))_d--;advance();}} }
26762678
consumeAttributes();
26772679

@@ -2681,7 +2683,7 @@ private Expr parseLambda() {
26812683
}
26822684

26832685
Block body = parseBlock();
2684-
return new LambdaExpr(captures, params, returnType, body, start.line(), start.col(), List.of());
2686+
return new LambdaExpr(captures, params, returnType, isMutable, body, start.line(), start.col(), List.of());
26852687
}
26862688

26872689
private Capture parseCapture() {
@@ -2749,7 +2751,7 @@ private Param parseParam() {
27492751
}
27502752

27512753
TypeRef type = parseTypeRef();
2752-
matchPunct("..."); // pack expansion after type: "Rest... rest"
2754+
boolean isTypePackExpansion = matchPunct("..."); // pack expansion after type: "Rest... rest"
27532755

27542756
// Member pointer parameter: "int Widget::* dp" or "int (Widget::* mp)(int) const"
27552757
if (check(CppLexerTokenType.IDENTIFIER) && pos + 1 < tokens.size()
@@ -2825,7 +2827,7 @@ private Param parseParam() {
28252827
}
28262828

28272829
// Variadic pack expansion after the type: "Args... args" or "Ts&&... ts"
2828-
boolean isVariadic = false;
2830+
boolean isVariadic = isTypePackExpansion;
28292831
if (checkPunct("...")) { advance(); isVariadic = true; }
28302832

28312833
String name;
@@ -2936,11 +2938,19 @@ private List<Statement> parseStatementOrMultiDecl(List<CppLexerToken> leadingCom
29362938
|| tokens.get(pos + 1).isPunct("{"))) {
29372939
TypeDef td = parseTypeDef(leadingComments, List.of());
29382940
matchPunct(";");
2939-
// If a variable declaration follows, parse it
2941+
// Emit struct as verbatim text via CodeGen
2942+
String structCode = processing.mode.cpp.CodeGen.generateNode(td, 0).stripTrailing();
2943+
ExprStatement structStmt = new ExprStatement(
2944+
new Identifier(structCode, td.line(), td.col(), List.of()),
2945+
td.line(), td.col(), leadingComments);
2946+
// If a variable declaration follows, parse it too
29402947
if (looksLikeDeclaration()) {
2941-
return new java.util.ArrayList<>(parseDeclStatementsDesugared(List.of()));
2948+
List<Statement> result = new java.util.ArrayList<>();
2949+
result.add(structStmt);
2950+
result.addAll(parseDeclStatementsDesugared(List.of()));
2951+
return result;
29422952
}
2943-
return List.of(new ExprStatement(new Identifier("", td.line(), td.col(), List.of()), td.line(), td.col(), leadingComments));
2953+
return List.of(structStmt);
29442954
}
29452955
if (looksLikeDeclaration()) {
29462956
return new ArrayList<Statement>(parseDeclStatementsDesugared(leadingComments));

0 commit comments

Comments
 (0)