SuperC documentation

⚠️ This is a PROPOSAL DRAFT. Generics are currently not implemented. Syntax may change

Generics meta-programming

The compiler automatically duplicates and generates at compile-time all the type-specific implementations for the template region you defined as a generic implementation template.

Define template region

When Not to Use Generics

Generics programming is meant to be a last resource tool when there’s no other option; or you want a more type safe, but more verbose solution.

Many cases can be covered with one of the following before using generics:

  Macros Overloads Generics
Compile-time âś… âś… âś…
Type safety ❌ ✅ ✅
Flexible types ✅ ❌ ✅
Code duplication ❌ ❌ ⚠️
Symbol control ❎* ✅ ⚠️

(*) macros are preprocessed so they don’t have a symbol, but that’s not bad.

Symbol mangle

When a type is used inside square brackets next to an identifier, that makes it part of the identifier. So math::sum[int] is a whole identifier, just like math_sum_int.

To differentiate the assembly identifiers, the compiler uses ”$$“ for namespaces and “G<type>.” for generics, so math::sum[int] will be “math$$sumGi.” and does not conflict with math::sum::int (“math$$sum$$int”).

Note that unlike ::, the compiler will transform the type inside square brackets to it’s assembly type name (i.e., int=>i, float=>f, char*=>Pc, struct Point[int]=>S8PointGi., etc), so the symbol of math::sum[int] will be math$$sumG.i..

#include <stdio.h>

#definefor T int, float

T math::sum[T](T a, T b); // No problem
T math::sum::T(T a, T b); // Caution!

struct Point[T] { T x, y; };
void (struct Point[T] *this) add(T other);

void control::symbol[T](T a, T b) __attribute__((symbol("control_" T)));
void caution::symbol[T](T a, T b) __attribute__((symbol("caution_" #T)));

#undef T

// math::sum[int]   => "math$$sumGi."
// math::sum[float] => "math$$sumGf."
// math::sum::int   => "math$$sum$$int"
// math::sum::float => "math$$sum$$float"

// Caution! because "math$$sum$$float" has no problem, but
// something like: "math$$sum$$char*", would break the assembler or linker,
// or even worse: "math$$sum$$struct Point".

// point_i.add(1)   => "add$PS8PointGi.i"
// point_f.add(1.0) => "add$PS8PointGf.f"

// math::sum[struct Point[int]]   => "math$$sumGS8PointGi.."
// math::sum[struct Point[float]] => "math$$sumGS8PointGf.."

// control::symbol[int]   => "control_i"
// control::symbol[float] => "control_f"
// caution::symbol[int]   => "caution_int"
// caution::symbol[float] => "caution_float"

// Same warning as before, because "caution_int" won't have a problem,
// but "caution_char*" would break the assembler or linker.

Examples


Previous

(DRAFT) #definefor macro

Next

(DRAFT) become keyword
Playground