@@ -1234,7 +1234,7 @@ private File writeSketchImpl(RunnerListener listener) throws IOException {
12341234 out .append ("using std::decay_t; using std::remove_reference_t; using std::common_type_t;\n " );
12351235 out .append ("using std::declval; using std::void_t;\n " );
12361236 out .append ("using std::index_sequence; using std::make_index_sequence;\n " );
1237- out .append ("using std::tuple_size; using std::tuple_element; using std::get; \n " );
1237+ out .append ("using std::tuple_size; using std::tuple_element; // std::get intentionally omitted -- shadows PApplet::get() \n " );
12381238 out .append ("using std::make_tuple; using std::tie; using std::apply;\n " );
12391239 out .append ("using std::runtime_error; using std::logic_error; using std::exception;\n " );
12401240 out .append ("using std::numeric_limits;\n " );
@@ -1335,16 +1335,34 @@ private File writeSketchImpl(RunnerListener listener) throws IOException {
13351335 fileScopeOnly .append (CodeGen .generateNode (item , 0 ));
13361336 continue ;
13371337 }
1338- // Template declarations, free functions, and ALL variables must be at
1339- // file scope in static sketches -- main() cannot access Sketch members.
1338+ // Template declarations and free functions go to file scope.
1339+ // Variables: only those with no initializer or a simple literal/nullptr
1340+ // go to file scope. Variables with Processing API calls in their initializer
1341+ // must go into setup() body -- calling API functions at static init time
1342+ // crashes because g_papplet is null before PApplet is constructed.
13401343 boolean isAnyFn = item instanceof FunctionDecl ;
1341- boolean isAnyVar = item instanceof VariableDecl ;
1342- boolean isTemplateTd = item instanceof TypeDef td
1343- && (!td .templateParams ().isEmpty () || td .name ().contains ("<" ));
1344- if (isAnyFn || isAnyVar || isTemplateTd ) {
1344+ boolean isTemplateTd = item instanceof TypeDef td2
1345+ && (!td2 .templateParams ().isEmpty () || td2 .name ().contains ("<" ));
1346+ if (isAnyFn || isTemplateTd ) {
13451347 fileScopeOnly .append (CodeGen .generateNode (item , 0 ));
13461348 continue ;
13471349 }
1350+ if (item instanceof VariableDecl vd2 ) {
1351+ // Safe at file scope: no initializer, nullptr, or numeric/string literal
1352+ Expr _init = vd2 .initializer ();
1353+ boolean safeAtFileScope = _init == null
1354+ || (_init instanceof Literal lit &&
1355+ (lit .kind () == Literal .Kind .INT || lit .kind () == Literal .Kind .FLOAT
1356+ || lit .kind () == Literal .Kind .STRING || lit .kind () == Literal .Kind .BOOL
1357+ || lit .kind () == Literal .Kind .CHAR ))
1358+ || (_init instanceof Identifier id && id .name ().equals ("nullptr" ));
1359+ if (safeAtFileScope ) {
1360+ fileScopeOnly .append (CodeGen .generateNode (item , 0 ));
1361+ } else {
1362+ body .append (CodeGen .generateNode (item , 2 ));
1363+ }
1364+ continue ;
1365+ }
13481366 String rendered = CodeGen .generateNode (item , 2 );
13491367 String trimmed = rendered .strip ();
13501368 if (trimmed .startsWith ("size(" ) || trimmed .startsWith ("fullScreen(" )) {
@@ -2876,10 +2894,29 @@ private String javaToC(String code) {
28762894 // ââ 11. API-conflicting variable names: scale/fill/stroke/etc. âââââââââââ
28772895 // If used as a variable (after a type keyword), rename to avoid shadowing API
28782896 String [] apiConflicts = {
2879- "scale" , "stroke" , "background" , "translate" , "rotate" ,
2880- "map" , "dist" , "noise"
2897+ // Drawing
2898+ "arc" , "box" , "circle" , "ellipse" , "line" , "point" , "rect" ,
2899+ "square" , "triangle" , "vertex" , "curve" , "bezier" ,
2900+ // Color
2901+ "alpha" , "blue" , "brightness" , "green" , "hue" , "red" , "saturation" ,
2902+ "fill" , "stroke" , "background" , "tint" , "filter" ,
2903+ // Transform
2904+ "scale" , "translate" , "rotate" , "push" , "pop" ,
2905+ // Math
2906+ "map" , "dist" , "noise" , "norm" , "lerp" , "mag" , "sq" ,
2907+ "constrain" , "degrees" , "radians" , "max" , "min" ,
2908+ // Image/pixel
2909+ "image" , "get" , "set" , "save" ,
2910+ // Text
2911+ "text" ,
2912+ // Lighting
2913+ "lights" , "ambient" , "specular" , "emissive" , "shininess" ,
2914+ // Camera
2915+ "camera" , "perspective" , "ortho" ,
2916+ // Misc
2917+ "smooth" , "cursor" , "loop" , "random" , "clear"
28812918 };
2882- String typeKw = "(?:int|float|double|bool|char|long|unsigned|auto|color|PVector)\\ s+" ;
2919+ String typeKw = "(?:int|float|double|bool|char|long|unsigned|auto|color|PVector\\ *?|ArrayList \\ s*<[^>]+> \\ *?|Array \\ s*<[^>]+> \\ *? )\\ s+" ;
28832920 for (String word : apiConflicts ) {
28842921 // Only rename if it appears as a variable declaration
28852922 if (java .util .regex .Pattern .compile (typeKw + word + "\\ b(?!\\ s*\\ ()" , java .util .regex .Pattern .MULTILINE ).matcher (code ).find ()) {
0 commit comments