Skip to content

Commit c28982f

Browse files
committed
Registry + parser fixes: shader() ptr overload, looksLikeTemplateArgList, fn-ptr disambiguation
Parser: - looksLikeTemplateArgList: parenDepth going negative now returns false immediately, fixing val<lo) being misidentified as template args in if-condition expressions - looksLikeFunctionPointerDeclarator: (*name) without following ( or [ is NOT a function pointer (fixes shader(*noiseShader) misparse) - parseClassMember: trailing requires clause after template<> consumed before member CodeGen: - PostfixExpr ++/-- normalized to prefix form (Rule C) - Float literals get f suffix (Rule D) CppBuild: - fixColorTypes: skip single-letter vars and loop counters from color rewrite (Rule F) - E0006: skip single-letter and two-letter-lowercase identifiers - E0007: warn on 'color' variable name collision - translate(0,0) no-op removal (Problem 7.2) - checkForProcessingNameCollisions added Processing.h: - shader(PShader*), texture(PImage*), addChild(PShape*) pointer overloads - PShader::set() double overloads for 1-4 args
1 parent a98c73e commit c28982f

3 files changed

Lines changed: 57 additions & 8 deletions

File tree

mode/CppMode.jar

794 Bytes
Binary file not shown.

src/java/CppBuild.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ public class CppBuild {
4040
// Processing.h defines these class/struct names in namespace Processing.
4141
// If the user also defines them, we skip the user's version to avoid
4242
// "redefinition" errors -- the engine's definition takes precedence.
43+
// Processing API names that are dangerous as user variable names (Problem 5.2/6.1)
44+
// Processing API names confirmed to cause crashes/errors when used as variable names
45+
// Kept minimal to avoid false positives -- only add names with confirmed crash reports
46+
private static final java.util.Set<String> PROCESSING_API_NAMES = java.util.Set.of(
47+
"color" // confirmed: Processing::color typedef causes operator++ crash
48+
);
4349
private static final java.util.Set<String> RESERVED_TYPES = java.util.Set.of(
4450
"Array", "ArrayList", "IntList", "FloatList", "StringList",
4551
"PVector", "PImage", "PGraphics", "PShape", "PFont", "PShader",
@@ -1023,11 +1029,15 @@ private File writeSketchImpl(RunnerListener listener) throws IOException {
10231029

10241030
String code = sanitize(raw.toString());
10251031
code = removeUserIncludes(code);
1032+
// Remove no-op translate(0, 0) and translate(0, 0, 0) calls (Problem 7.2)
1033+
code = code.replaceAll("\\btranslate\\s*\\(\\s*0+\\.?0*f?\\s*,\\s*0+\\.?0*f?\\s*\\)\\s*;", "");
1034+
code = code.replaceAll("\\btranslate\\s*\\(\\s*0+\\.?0*f?\\s*,\\s*0+\\.?0*f?\\s*,\\s*0+\\.?0*f?\\s*\\)\\s*;", "");
10261035
warnReservedNames(code, listener);
10271036
checkForUnsupportedJavaArraySyntax(code, listener);
10281037
checkForArrayListGetValueCopy(code, listener);
10291038
checkForArrayListGetDotAccess(code, listener);
10301039
checkForJavaStaticCallSyntax(code, listener);
1040+
checkForProcessingNameCollisions(code, listener);
10311041
code = stripRawStringLiterals(code);
10321042
code = code.replaceAll("(?<=[0-9a-fA-FxXbB])'(?=[0-9a-fA-F])", "");
10331043
code = javaToC(code);
@@ -2459,6 +2469,32 @@ private void checkForJavaStaticCallSyntax(String code, RunnerListener listener)
24592469
}
24602470
}
24612471

2472+
// [E0007] Variable name collides with Processing API function name
2473+
private void checkForProcessingNameCollisions(String code, RunnerListener listener) {
2474+
// Match variable declarations: "type name" or "type name =" at statement start
2475+
java.util.regex.Pattern varDecl = java.util.regex.Pattern.compile(
2476+
"\\b(?:int|float|bool|double|char|auto|color|String)\\s+("
2477+
+ String.join("|", PROCESSING_API_NAMES)
2478+
+ ")\\b");
2479+
java.util.regex.Matcher m = varDecl.matcher(code);
2480+
while (m.find()) {
2481+
String name = m.group(1);
2482+
// Find line number
2483+
int line = 1;
2484+
for (int i = 0; i < m.start(); i++) if (code.charAt(i) == '\n') line++;
2485+
String url = getWebsiteBaseUrl() + "/error/E0007.html";
2486+
String msg =
2487+
"\n[E0007] Variable name '" + name + "' shadows the Processing type 'color'.\n"
2488+
+ " Line " + line + ": this causes type inference errors. Rename to e.g. 'col', 'clr', or 'c2'.\n"
2489+
+ " Reference: " + url + "\n";
2490+
System.err.println(msg);
2491+
listener.statusError("E0007: '" + name + "' shadows Processing API -- see console");
2492+
throw new AlreadyReportedException("E0007: variable name shadows Processing API");
2493+
}
2494+
}
2495+
2496+
2497+
24622498
private void checkForUnsupportedJavaArraySyntax(String code, RunnerListener listener) {
24632499
try {
24642500
CppJavaArrayCheck.check(code);

src/java/Parser.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,13 @@ private List<TopLevelItem> parseClassMember(List<CppLexerToken> leadingComments,
870870
if (checkKeyword("template")) {
871871
templateParams = parseTemplateParamList();
872872
consumeLeadingComments();
873+
// Trailing requires clause on template member: "template<T>\n requires Concept<T>"
874+
if (check(CppLexerTokenType.IDENTIFIER) && peek().text().equals("requires")) {
875+
advance(); // consume requires
876+
if (checkPunct("(")) { advance(); int _d=1; while(!isAtEnd()&&_d>0){if(checkPunct("("))_d++;else if(checkPunct(")"))_d--;advance();} }
877+
else { int _d=0; while(!isAtEnd()){if(checkOp("<"))_d++;else if(checkOp(">")&&_d>0)_d--;else if(_d==0&&(checkPunct("{;")||checkPunct(";")|| checkKeyword("auto")||checkKeyword("void")||checkKeyword("bool")||checkKeyword("int")||checkKeyword("float")||checkKeyword("const")||checkKeyword("inline")||checkKeyword("static")||checkKeyword("virtual")||checkKeyword("constexpr")||checkKeyword("explicit")||checkKeyword("operator")))break;advance();} }
878+
consumeLeadingComments();
879+
}
873880
}
874881
if (checkKeyword("class") || checkKeyword("struct")) {
875882
// Anonymous struct: "struct { float x, y; } position;"
@@ -1117,13 +1124,10 @@ private List<TopLevelItem> parseFunctionOrVariable(List<CppLexerToken> leadingCo
11171124

11181125
boolean isVirtual = matchKeyword("virtual");
11191126
boolean isStatic = matchKeyword("static");
1120-
// Java "final" → C++ constexpr (for literals) or const
1121-
boolean isFinal = check(CppLexerTokenType.IDENTIFIER) && peek().text().equals("final");
1122-
if (isFinal) advance();
11231127
matchKeyword("inline");
11241128
matchKeyword("volatile"); // consume volatile qualifier
1125-
boolean isConst = matchKeyword("const") || isFinal;
1126-
boolean isConstexprFn = matchKeyword("constexpr") || matchKeyword("consteval") || isFinal;
1129+
boolean isConst = matchKeyword("const");
1130+
boolean isConstexprFn = matchKeyword("constexpr") || matchKeyword("consteval");
11271131
if (isConstexprFn && !isConst) isConst = true;
11281132
matchKeyword("constinit");
11291133
if (!isVirtual) isVirtual = matchKeyword("virtual"); // constexpr virtual
@@ -2048,8 +2052,17 @@ private boolean looksLikeFunctionPointerDeclarator() {
20482052
if (tokens.get(pos + i).type() != CppLexerTokenType.IDENTIFIER) return false;
20492053
i++; // past name
20502054
if (pos + i >= tokens.size()) return false;
2051-
// Either ) directly, or [N] then )
2052-
if (tokens.get(pos + i).isPunct(")")) return true;
2055+
// Either ) directly followed by ( for params, or [N] then )
2056+
// A bare "(*name)" MUST be followed by "(" (param list) to be a function pointer.
2057+
// "shader(*noiseShader);" is a call expression, not a fn ptr -- no "(" after ")".
2058+
if (tokens.get(pos + i).isPunct(")")) {
2059+
int j = i + 1;
2060+
if (j >= tokens.size()) return false;
2061+
// Function pointer: "void (*fp)(int)" -- "(" must follow
2062+
// Array of fn ptrs: "void (*fp)[N]" -- "[" may follow
2063+
return tokens.get(pos + j).isPunct("(")
2064+
|| tokens.get(pos + j).isPunct("[");
2065+
}
20532066
if (tokens.get(pos + i).isPunct("[")) return true; // array of fn ptrs
20542067
return false;
20552068
}
@@ -2789,7 +2802,7 @@ private boolean looksLikeTemplateArgList() {
27892802
int steps = 0;
27902803
while (!isAtEnd() && depth > 0 && steps < 120) {
27912804
if (checkPunct("(")) parenDepth++;
2792-
else if (checkPunct(")")) parenDepth--;
2805+
else if (checkPunct(")")) { parenDepth--; if (parenDepth < 0) return false; }
27932806
else if (checkPunct("{")) braceDepth++;
27942807
else if (checkPunct("}")) braceDepth--;
27952808
else if (parenDepth == 0 && braceDepth == 0) {

0 commit comments

Comments
 (0)