package processing.mode.cpp;
import java.util.List;
/*
* Consolidated core AST support types -- Node (the base interface every
* AST node implements for position/comment tracking), TypeRef and its
* three variants, and Param (shared by FunctionDecl and LambdaExpr).
* Formerly 6 separate files; merged for the same reason as AstExpr.java.
*/
/**
* Common contract for every AST node: source position (for diagnostics and
* #line-directive emission during codegen) and any comment tokens that
* lexically preceded this node and were attached to it by the parser.
*
* Comments are attached at parse time (not stripped, not handled by a separate
* regex pass) specifically so semantic passes walking the tree never need to
* worry about comment text being mistaken for code -- see CppLexer's COMMENT
* handling notes.
*/
interface Node {
int line();
int col();
List leadingComments();
}
/**
* Represents a C++ type as it appears in source: in a variable/field declaration,
* a function return type, a parameter type, a template argument, etc.
*
* This is a sealed hierarchy with three concrete shapes, confirmed necessary by
* walking the real CppMode test corpus:
*
* - {@link NamedType}: the common case. Covers everything from "int" to
* "ArrayList*" to "const std::string&" to the outer "std::function"
* wrapper of "std::function" (the inner "void(int)" signature
* becomes a {@link FunctionSignatureType} nested inside this type's templateArgs).
*
* - {@link FunctionPointerType}: the raw C-style function pointer declarator
* shape, e.g. "int (*funcPtr)(int, int)". This does NOT fit NamedType at all --
* there is no single "name" being qualified by pointer/template syntax; the
* pointer-ness applies to an entire function signature. Confirmed as a genuine
* structural fork during corpus validation.
*
* - {@link FunctionSignatureType}: a bare function signature with no pointer
* declarator, used only as a template argument inside std::function<...>.
*
* Note on std::function: this parses as a NamedType with
* baseName="std::function" and a single templateArg that is itself a
* FunctionSignatureType -- NOT a FunctionPointerType (no '(*)' declarator is
* present in std::function's syntax, it's purely a template argument).
*/
sealed interface TypeRef permits NamedType, FunctionPointerType, FunctionSignatureType {
/** Plain-English rendering for diagnostics; not used for codegen fidelity. */
String describe();
}
/**
* The common-case type reference.
*
* @param baseName e.g. "int", "ArrayList", "std::string", "T", "auto"
* @param templateArgs empty for non-template types; each element is itself a
* TypeRef so nested templates (Pair<int, ArrayList<T>>)
* and function-signature template args (std::function<...>)
* both work without a separate node
* @param pointerDepth number of '*' suffixes; 0 for a plain value type
* @param isReference true for a '&' suffix
* @param isConst true if a leading 'const' qualifier was present
*/
record NamedType(
String baseName,
List templateArgs,
int pointerDepth,
boolean isReference,
boolean isConst,
boolean isRvalueRef
) implements TypeRef {
public static NamedType simple(String baseName) {
return new NamedType(baseName, List.of(), 0, false, false, false);
}
@Override
public String describe() {
StringBuilder sb = new StringBuilder();
if (isConst) sb.append("const ");
sb.append(baseName);
if (!templateArgs.isEmpty()) {
sb.append("<");
for (int i = 0; i < templateArgs.size(); i++) {
if (i > 0) sb.append(", ");
sb.append(templateArgs.get(i).describe());
}
sb.append(">");
}
sb.append("*".repeat(pointerDepth));
if (isReference) sb.append("&");
return sb.toString();
}
}
/**
* The raw C-style function pointer declarator: "ReturnType (*)(ParamType, ...)".
* Confirmed necessary by the corpus's useRawFunctionPointer fixture
* ("int (*funcPtr)(int, int) = someFunc;") -- this does not fit NamedType's shape,
* since the pointer applies to an entire function signature, not a named type.
*/
record FunctionPointerType(
TypeRef returnType,
List paramTypes
) implements TypeRef {
@Override
public String describe() {
StringBuilder sb = new StringBuilder(returnType.describe());
sb.append(" (*)(");
for (int i = 0; i < paramTypes.size(); i++) {
if (i > 0) sb.append(", ");
sb.append(paramTypes.get(i).describe());
}
sb.append(")");
return sb.toString();
}
}
/**
* A bare function signature with no pointer declarator, used only as a template
* argument inside std::function<...> (e.g. the "void(int)" inside
* "std::function<void(int)>"). Distinct from FunctionPointerType because no
* '(*)' appears in the source -- confirmed as a separate shape during corpus
* validation rather than reusing FunctionPointerType for both cases.
*/
record FunctionSignatureType(
TypeRef returnType,
List paramTypes
) implements TypeRef {
@Override
public String describe() {
StringBuilder sb = new StringBuilder(returnType.describe());
sb.append("(");
for (int i = 0; i < paramTypes.size(); i++) {
if (i > 0) sb.append(", ");
sb.append(paramTypes.get(i).describe());
}
sb.append(")");
return sb.toString();
}
}
/**
* A single function/lambda parameter: type, name, and an optional default
* value. Confirmed necessary by the corpus's withDefaultParam fixture
* ("void withDefaultParam(int x, int y = 5)") -- defaultValue is null when
* absent.
*
* Shared between FunctionDecl and LambdaExpr since both need identical shape;
* confirmed by corpus that lambda parameter lists ("[](int n) { ... }") use
* the same grammar as ordinary function parameter lists, just without default
* values being exercised in practice (though nothing in the grammar forbids
* them on a lambda either).
*/
record Param(TypeRef type, String name, Expr defaultValue, List innerArrayDims, boolean isVariadic) {
Param(TypeRef type, String name, Expr defaultValue) {
this(type, name, defaultValue, List.of(), false);
}
}