Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e119bb7
fixed-array rework stage 1a: additive Type::tFixedArray core machinery
borisbat Jun 10, 2026
1918ba1
fixed-array 1b-i: typeMacro/typeDecl/tag payload moves dimExpr -> typ…
borisbat Jun 10, 2026
c39423f
fixed-array plan: the third parser (utils/dasFormatter gen1->gen2 con…
borisbat Jun 10, 2026
da22318
fixed-array 1b-ii: parsers + mangled-name parse build tFixedArray chains
borisbat Jun 10, 2026
235832e
fixed-array 1c: typeFactory/interop produce tFixedArray; makeTypeInfo…
borisbat Jun 10, 2026
5f276cd
fixed-array 1d: infer produces/consumes tFixedArray; dim-vector reads…
borisbat Jun 10, 2026
bc0029b
fixed-array 1e: simulate lowers tFixedArray; the world boots again
borisbat Jun 10, 2026
bab18ff
fixed-array 1f: alias peel + .dim flattened view; emitter/JIT ride co…
borisbat Jun 10, 2026
0251ea8
lint ride-along: STYLE030 generic-body false positive + glsl self-> s…
borisbat Jun 10, 2026
792413b
fixed-array: generic aliases bind the WHOLE matched type
borisbat Jun 10, 2026
b7098da
fixed-array 1g: delete container-FA [] overload families; natural arc…
borisbat Jun 10, 2026
75ad9e6
fixed-array stage 2: aot_cpp structural port (natural TDim recursion)…
borisbat Jun 10, 2026
b9ffb2a
fixed-array: auto(TT)[] binding inherits param constness (match plain…
borisbat Jun 11, 2026
37ead95
fixed-array stage 3: llvm_jit structural port; new Handle[N] registra…
borisbat Jun 11, 2026
9c36700
fixed-array stage 4: row-sort transform one-peel fix; dead dim-reject…
borisbat Jun 11, 2026
c5191ec
fixed-array stage 5: macro/tooling structural ports; typeMacroExpr ex…
borisbat Jun 11, 2026
8d0dd7f
fixed-array stage 6: delete TypeDecl dim/dimExpr + compat properties;…
borisbat Jun 11, 2026
68f9a82
fixed-array stage 7: RST docs - fixed-array section in arrays.rst; na…
borisbat Jun 11, 2026
9139917
fixed-array: port style_lint rules added on master to structural read…
borisbat Jun 11, 2026
18c120a
fixed-array docs: update handmade RST for das2rst (docs CI)
borisbat Jun 11, 2026
ba9f5d9
fixed-array: review fixes + clang/gcc tests-cpp compile fix
borisbat Jun 11, 2026
26c8e4b
fixed-array: safe_addr overloads for fixed arrays (C-style decay)
borisbat Jun 11, 2026
33b54e9
fixed-array docs: group make_fixed_array_type under Type generation
borisbat Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
436 changes: 406 additions & 30 deletions FIXED_ARRAY_REWORK.md

Large diffs are not rendered by default.

96 changes: 59 additions & 37 deletions daslib/aot_cpp.das
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def das_to_cppCTypeString(t : Type) {


def isConstRedundantForCpp(typeDecl : TypeDeclPtr) {
if (!empty(typeDecl.dim)) return false;
if (typeDecl.baseType == Type.tFixedArray) return false;
if (typeDecl.isVectorType) return true;
match (typeDecl.baseType) {
if (Type.tBool || Type.tInt8 || Type.tUInt8 || Type.tInt16 || Type.tUInt16 ||
Expand Down Expand Up @@ -279,6 +279,17 @@ def aotEnumValueName(name : das_string) {
}


def fa_element(t : TypeDeclPtr) {
// element of a tFixedArray chain (a clone of t itself when not dim'd) - structural
// reads (argTypes/annotation/variant offsets) live on the element, not the chain
// head. Clone-walks so the result is non-const whatever the caller's view is.
var e = clone_type(t)
while (e.baseType == Type.tFixedArray && e.firstType != null) {
e = clone_type(e.firstType)
}
return e
}

def describeCppTypeEx(typeDecl : TypeDeclPtr;
in_cfg : DescribeConfig;
useAlias : CpptUseAlias) {
Expand All @@ -295,10 +306,10 @@ def describeCppTypeEx(typeDecl : TypeDeclPtr;
let baseType = typeDecl.baseType;

return build_string() $(writer) {
for (_ in range(length(typeDecl.dim))) {
write(writer, "TDim<");
}
if (useAlias == CpptUseAlias.yes && typeDecl.flags.aotAlias && !typeDecl.alias.empty()) {
if (baseType == Type.tFixedArray && typeDecl.firstType != null) {
// natural recursion; inner chain nodes are canonically bare (qualifiers live on the head)
write(writer, "TDim<{describeCppTypeEx(typeDecl.firstType,DescribeConfig(cross_platform=cfg.cross_platform),useAlias)},{typeDecl.fixedDim}>")
} elif (useAlias == CpptUseAlias.yes && typeDecl.flags.aotAlias && !typeDecl.alias.empty()) {
write(writer, "{typeDecl.alias}");
} elif (baseType == Type.alias) {
write(writer, "DAS_COMMENT(alias)");
Expand Down Expand Up @@ -400,7 +411,7 @@ def describeCppTypeEx(typeDecl : TypeDeclPtr;
write(writer, "Sequence")
}
} elif (baseType == Type.tBlock || baseType == Type.tFunction || baseType == Type.tLambda) {
let maybe_const = !typeDecl.flags.constant && typeDecl.baseType == Type.tBlock ? "const " : ""
let maybe_const = !typeDecl.flags.constant && baseType == Type.tBlock ? "const " : ""
var type_name = "void"
if (typeDecl.firstType != null) {
type_name = describeCppTypeEx(typeDecl.firstType, DescribeConfig(redundant_const = true, cross_platform = cfg.cross_platform), useAlias)
Expand All @@ -414,13 +425,6 @@ def describeCppTypeEx(typeDecl : TypeDeclPtr;
} else {
write(writer, das_to_cppString(baseType));
}
// dim is stored outer-first; C++ TDim<TDim<base,inner>,outer> emits dims
// inner-first, so walk dim in reverse.
let dim_count = length(typeDecl.dim)
for (i in 0..dim_count) {
write(writer, ",{typeDecl.dim[dim_count - 1 - i]}>")
}

if (!cfg.skip_const && typeDecl.flags.constant) {
write(writer, " const ");
}
Expand Down Expand Up @@ -951,8 +955,8 @@ class public AotDebugInfoHelper {
};

def public isLocalVec(vtype : TypeDeclPtr) {
//! Returns true if the type is a non-reference vector type without dimensions.
return empty(vtype.dim) && vtype.isVectorType && !vtype.flags.ref;
//! Returns true if the type is a non-reference vector type.
return vtype.isVectorType && !vtype.flags.ref;
}

def public describeLocalCppType(var writer : StringBuilderWriter?; vtype : TypeDeclPtr; cross_platform : bool; substituteRef : CpptSubstitureRef = CpptSubstitureRef.yes; skipConst : CpptSkipConst = CpptSkipConst.no) {
Expand Down Expand Up @@ -2078,7 +2082,8 @@ class public CppAot : AstVisitor {
._fold()) |> join(",")
}

def get_variant_field(field_type : TypeDeclPtr; index : int; is_pointer : bool = false) {
def get_variant_field(in_field_type : TypeDeclPtr; index : int; is_pointer : bool = false) {
let field_type = fa_element(in_field_type)
let type_str = describeCppType(field_type.argTypes[index], DescribeConfig(cross_platform = cross_platform));
let maybe_ptr = is_pointer ? "_ptr" : "";
if (cross_platform) {
Expand Down Expand Up @@ -2182,7 +2187,8 @@ class public CppAot : AstVisitor {
return field;
}
// field
def get_tuple_field(field_type : TypeDeclPtr; index : int; is_pointer : bool = false) {
def get_tuple_field(in_field_type : TypeDeclPtr; index : int; is_pointer : bool = false) {
let field_type = fa_element(in_field_type)
let field_tp = describeCppType(field_type.argTypes[index], DescribeConfig(cross_platform = cross_platform));
let maybe_ptr = is_pointer ? "_ptr" : "";
if (cross_platform) {
Expand Down Expand Up @@ -2213,6 +2219,10 @@ class public CppAot : AstVisitor {
write(*ss, "(({describeCppType(field._type, DescribeConfig(cross_platform=cross_platform))})(");
}
}
if (field._type.flags.isNativeDim) {
// native C-array member: pun to the TDim view so iterate/pass/copy/safe-at consumers compile (issue #3077)
write(*ss, "das_reinterpret<{describeCppType(field._type, DescribeConfig(skip_ref=true,cross_platform=cross_platform))}>::pass(");
}
aot_previsit_get_field(field_type.annotation, ss, string(field.name));
} elif (field_type.baseType == Type.tPointer) {
if (field_type.firstType.isHandle) {
Expand All @@ -2224,6 +2234,9 @@ class public CppAot : AstVisitor {
write(*ss, "(({describeCppType(field._type, DescribeConfig(cross_platform=cross_platform))})(");
}
}
if (field._type.flags.isNativeDim) {
write(*ss, "das_reinterpret<{describeCppType(field._type, DescribeConfig(skip_ref=true,cross_platform=cross_platform))}>::pass(");
}
aot_previsit_get_field_ptr(field_type.firstType.annotation, ss, string(field.name));
} elif (field.value._type.firstType.isTuple) {
write(*ss, "{get_tuple_field(field_type.firstType, field.fieldIndex, true)}::get(")
Expand All @@ -2245,13 +2258,19 @@ class public CppAot : AstVisitor {
if (field._type.isString) {
write(*ss, "))");
}
if (field._type.flags.isNativeDim) {
write(*ss, ")");
}
} elif (field.value._type.baseType == Type.tPointer) {
if (field.value._type.firstType.isHandle) {
aot_type_ann_get_field_ptr(field.value._type.firstType.annotation, ss, string(field.name));
write(*ss, " /*{field.name}*/");
if (field._type.isString) {
write(*ss, "))")
}
if (field._type.flags.isNativeDim) {
write(*ss, ")");
}
} elif (field.value._type.firstType.isTuple) {
write(*ss, ")");
} elif (field.value._type.firstType.isVariant) {
Expand All @@ -2272,13 +2291,13 @@ class public CppAot : AstVisitor {
if (expr._type.flags.aotAlias) {
write(*ss, "das_alias<{expr._type.alias}>::from(");
}
if (!(!expr.subexpr._type.dim |> empty() || expr.subexpr._type.isGoodArrayType || expr.subexpr._type.isGoodTableType)) {
if (!(expr.subexpr._type.baseType == Type.tFixedArray || expr.subexpr._type.isGoodArrayType || expr.subexpr._type.isGoodTableType)) {
let type_str = describeCppType(expr.subexpr._type, DescribeConfig(skip_ref = true, cross_platform = cross_platform));
write(*ss, "das_index<{type_str}>::at(");
}
}
def override preVisitExprAtIndex(var expr : ExprAt?; index : ExpressionPtr) {
if (!expr.subexpr._type.dim |> empty() || expr.subexpr._type.isGoodArrayType || expr.subexpr._type.isGoodTableType) {
if (expr.subexpr._type.baseType == Type.tFixedArray || expr.subexpr._type.isGoodArrayType || expr.subexpr._type.isGoodTableType) {
if (expr.subexpr._type.flags.isNativeDim) {
write(*ss, "[");
} else {
Expand All @@ -2304,7 +2323,7 @@ class public CppAot : AstVisitor {
def override preVisitExprSafeAt(expr : ExprSafeAt?) {
let isPtr : bool = expr.subexpr._type.isPointer;
assume seT = isPtr ? expr.subexpr._type.firstType : expr.subexpr._type;
if ((!seT.dim |> empty() || seT.isGoodArrayType || seT.isGoodTableType)) {
if ((seT.baseType == Type.tFixedArray || seT.isGoodArrayType || seT.isGoodTableType)) {
let type_str = describeCppType(seT, DescribeConfig(skip_ref = true, skip_const = true, cross_platform = cross_platform))
write(*ss, "{type_str}::safe_index(");
} elif (isPtr && !seT.isVectorType) {
Expand Down Expand Up @@ -2896,21 +2915,21 @@ class public CppAot : AstVisitor {
write(*ss, "(memset((void*)&{nm},0,sizeof({nm})), &{nm}");
return
}
if (!enew._type.dim |> empty()) {
if (enew._type.firstType.isHandle) {
let type_str = describeCppType(enew._type.firstType, DescribeConfig(skip_ref = true, skip_const = true, cross_platform = cross_platform));
write(*ss, "das_new_dim_handle<{type_str},{enew._type.dim[0]},{enew._type.flags.smartPtr}");
if (enew._type.baseType == Type.tFixedArray) {
let ptrType = fa_element(enew._type) // the fixed-array chain wraps the pointer node; pointee is its firstType
if (ptrType.firstType.isHandle) {
let type_str = describeCppType(ptrType.firstType, DescribeConfig(skip_ref = true, skip_const = true, cross_platform = cross_platform));
write(*ss, "das_new_dim_handle<{type_str},{enew._type.fixedDim},{ptrType.flags.smartPtr}");
if (enew.initializer) {
panic("internal error. initializer for enew is not supported");
} else {
write(*ss, ">::make(__context__");
}
} else {
let type_str = describeCppType(enew._type.firstType, DescribeConfig(skip_ref = true, skip_const = true, cross_platform = cross_platform));
write(*ss, "das_new_dim<{type_str},{enew._type.dim[0]}");
let type_str = describeCppType(ptrType.firstType, DescribeConfig(skip_ref = true, skip_const = true, cross_platform = cross_platform));
write(*ss, "das_new_dim<{type_str},{enew._type.fixedDim}");
if (enew.initializer) {
write(*ss, ">::make_and_init(__context__,[&]() \{ return ");
// << " . " << describeCppType(enew._type.firstType,DescribeConfig(skip_ref=true,skip_const=true,cross_platform=cross_platform))
CallFunc_preVisit(enew);
} else {
write(*ss, ">::make(__context__");
Expand Down Expand Up @@ -2990,22 +3009,24 @@ class public CppAot : AstVisitor {
}
}
def override preVisitExprMakeVariantField(expr : ExprMakeVariant?; index : int; decl : MakeFieldDeclPtr; last : bool) {
let variantIndex = find_argument_index(expr._type, string(decl.name));
let variantType = fa_element(expr._type) // dim'd make-variant carries the variant on the chain element
let variantIndex = find_argument_index(variantType, string(decl.name));
if (variantIndex == -1) {
panic("should not infer otherwise");
}
let type_str = describeCppType(expr._type.argTypes[variantIndex], DescribeConfig(cross_platform = cross_platform));
write(*ss, "{tabs()}{get_variant_field(expr._type, variantIndex)}::set(");
let type_str = describeCppType(variantType.argTypes[variantIndex], DescribeConfig(cross_platform = cross_platform));
write(*ss, "{tabs()}{get_variant_field(variantType, variantIndex)}::set(");
write(*ss, "{mkvName(expr)}");
if (length(expr.variants) != 1) write(*ss, "({index},__context__)");
write(*ss, ") = ");
if (expr._type.argTypes[variantIndex].isPointer && decl.value._type.isPointer && expr._type.argTypes[variantIndex].firstType != null && decl.value._type.firstType != null && !is_same_type(expr._type.argTypes[variantIndex].firstType, decl.value._type.firstType, false, false, false, false)) {
if (variantType.argTypes[variantIndex].isPointer && decl.value._type.isPointer && variantType.argTypes[variantIndex].firstType != null && decl.value._type.firstType != null && !is_same_type(variantType.argTypes[variantIndex].firstType, decl.value._type.firstType, false, false, false, false)) {
write(*ss, "das_auto_cast<{type_str}>::cast(");
}
}
def override visitExprMakeVariantField(expr : ExprMakeVariant?; index : int; decl : MakeFieldDeclPtr; last : bool) {
let variantIndex = find_argument_index(expr._type, string(decl.name))
if (expr._type.argTypes[variantIndex].isPointer && decl.value._type.isPointer && expr._type.argTypes[variantIndex].firstType != null && decl.value._type.firstType != null && !is_same_type(expr._type.argTypes[variantIndex].firstType, decl.value._type.firstType, false, false, false, false)) {
let variantType = fa_element(expr._type)
let variantIndex = find_argument_index(variantType, string(decl.name))
if (variantType.argTypes[variantIndex].isPointer && decl.value._type.isPointer && variantType.argTypes[variantIndex].firstType != null && decl.value._type.firstType != null && !is_same_type(variantType.argTypes[variantIndex].firstType, decl.value._type.firstType, false, false, false, false)) {
write(*ss, ")");
}
write(*ss, ";\n");
Expand Down Expand Up @@ -3080,15 +3101,16 @@ class public CppAot : AstVisitor {
}
}
def override preVisitExprMakeStructField(expr : ExprMakeStruct?; index : int; decl : MakeFieldDeclPtr; last : bool) {
let mkType = fa_element(expr.makeType) // dim'd make-struct carries the record on the chain element
write(*ss, "{tabs()}");
write(*ss, "{decl.flags.moveSemantics ? "das_move((" : "das_copy(("}");
if (expr.makeType.baseType == Type.tHandle) {
aot_previsit_get_field(expr.makeType.annotation, ss, string(decl.name));
if (mkType.baseType == Type.tHandle) {
aot_previsit_get_field(mkType.annotation, ss, string(decl.name));
}
write(*ss, "{mksName(expr)}");
if (length(expr.structs) != 1) write(*ss, "({index},__context__)");
if (expr.makeType.baseType == Type.tHandle) {
aot_visit_get_field(expr.makeType.annotation, ss, string(decl.name));
if (mkType.baseType == Type.tHandle) {
aot_visit_get_field(mkType.annotation, ss, string(decl.name));
write(*ss, " /*{decl.name}*/");
} else {
write(*ss, ".{aotFieldName(string(decl.name))}");
Expand Down
5 changes: 0 additions & 5 deletions daslib/apply.das
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ def private inline_apply_field(nameStr : string; var access : ExpressionPtr; fie
[macro_function]
def generateApplyVisitStruct(stype : TypeDeclPtr; frange : range; fnname : string; at : LineInfo; var names : array<string>; hasExtraArg : bool) {
assert(stype.baseType == Type.tStructure)
assert(empty(stype.dim))
let nfields = frange.y - frange.x
var selfT = clone_type(stype)
selfT.flags |= TypeDeclFlags.isExplicit | TypeDeclFlags.explicitConst
Expand Down Expand Up @@ -164,7 +163,6 @@ def generateApplyVisitStruct(stype : TypeDeclPtr; fnname : string; at : LineInfo
[macro_function]
def generateApplyVisitTuple(stype : TypeDeclPtr; frange : range; fnname : string; at : LineInfo; var names : array<string>) {
assert(stype.baseType == Type.tTuple)
assert(empty(stype.dim))
let nfields = frange.y - frange.x
var selfT = clone_type(stype)
selfT.flags |= TypeDeclFlags.isExplicit | TypeDeclFlags.explicitConst
Expand Down Expand Up @@ -215,7 +213,6 @@ def generateApplyVisitTuple(stype : TypeDeclPtr; fnname : string; at : LineInfo)
[macro_function]
def generateApplyVisitVariant(stype : TypeDeclPtr; frange : range; fnname : string; at : LineInfo; var names : array<string>) {
assert(stype.baseType == Type.tVariant)
assert(empty(stype.dim))
let nfields = frange.y - frange.x
var selfT = clone_type(stype)
selfT.flags |= TypeDeclFlags.isExplicit | TypeDeclFlags.explicitConst
Expand Down Expand Up @@ -348,7 +345,6 @@ class ApplyMacro : AstCallMacro {
return null
}
var argT = clone_type(expr.arguments[0]._type)
macro_verify(empty(argT.dim), prog, expr.at, "can't apply to dim")
macro_verify(argT.baseType == Type.tStructure || argT.baseType == Type.tTuple || argT.baseType == Type.tVariant,
prog, expr.at, "can only apply to {describe(expr.arguments[0]._type)}")
macro_verify(expr.arguments[1] is ExprMakeBlock, prog, expr.at, "expecting make block, i.e. $(..)")
Expand Down Expand Up @@ -531,7 +527,6 @@ class ApplyImmMacro : AstCallMacro {
return null
}
var argT = clone_type(expr.arguments[0]._type)
macro_verify(empty(argT.dim), prog, expr.at, "can't apply_imm to dim")
macro_verify(argT.baseType == Type.tStructure, prog, expr.at, "apply_imm supports struct only")
macro_verify(expr.arguments[1] is ExprMakeBlock, prog, expr.at, "expecting make block, i.e. $(..)")
macro_verify(apply_block_inline_safe(expr.arguments[1]), prog, expr.at,
Expand Down
Loading
Loading