Skip to content

Latest commit

 

History

History
129 lines (89 loc) · 4.74 KB

File metadata and controls

129 lines (89 loc) · 4.74 KB

14. Future Thinking

14.1 Metaprogramming Implementation

For a purely static language without runtime, metaprogramming is essential for business applications.

Two major use cases:

  • JSON decoding to struct
  • Database ORM, dynamically generating structs and SQL

These requirements are challenging for purely static languages without runtime. Most implementations are based on macros.

Most language macros operate on token streams, not ASTs, which limits their effectiveness. Rust's declarative macros can access expression trees, but still have limitations and strong code intrusion.

Drawing from C#'s approach, we consider whether compile-time annotations combined with compile-time reflection and code generation could achieve capabilities comparable to dynamic languages, with generated code that is visible, debuggable, and predictable to developers.

14.2 Heterogeneous Collections

For languages that abstract Interfaces/Traits and can use them as types, heterogeneous collections become an implicit black magic box, relying on virtual tables and fat pointers. This is essentially wrapping different objects because the actual object sizes are unpredictable, preventing collection size allocation. However, pointer sizes are fixed.

Clearly, this violates solid-lang's design philosophy.

Heterogeneous collections are typically used when objects of different types but with common characteristics need unified interface handling in a polymorphic manner.

interface IDrawable<T> {
    func draw(self: *T);
}

struct Circle {}
struct Rectangle {}
struct Triangle {}

func Circle::draw(self: *Circle) {}
func Rectangle::draw(self: *Rectangle) {}
func Triangle::draw(self: *Triangle) {}

Implementation approaches for purely static languages:

  1. Tagged Unions: High performance and elegant implementation. However, this lacks extensibility - all variants must be explicitly declared in the union. Adding a large object widens all element sizes uncontrollably.

  2. Manual Virtual Tables: Developers can manually maintain virtual tables and use fat pointers + vtables. However, this results in high code redundancy and lacks safety guarantees.

  3. Code-Generated Virtual Tables: Developers use code generation to automatically create virtual table and fat pointer structures. This simplifies development while keeping everything explicit without black magic. However, function pointer jumps still incur performance overhead.

14.3 Range Type

Range is a first-class value type Range<T> representing a half-open interval [start, end). It is an expression, not a for-loop-specific syntax construct — this keeps it orthogonal.

Type:

struct Range<T> {
    start: T,
    end: T,
}

Usage contexts (planned):

Context Example Mechanism
Creation var r = 0..10; Literal expression T..T
For iteration for var i in 0..arr.len() Range<T>: IIterable<T>
Array slicing arr[0..5] IIndexGet<T, Range<usize>, Slice<T>>
Pattern matching switch x { 0..10 => ... } Compiler intrinsic range check

Orthogonality: All contexts except pattern matching are interface-driven — Range<T> is consumed by for, [], and function parameters through standard interface implementations. Pattern matching is the sole context requiring compiler-internal knowledge of range semantics, comparable to how switch already understands enum constructors.

Outstanding design questions:

  • Half-open a..b vs. inclusive a..=b — adopt half-open only, consistent with slicing and iteration conventions, or support both
  • Step — a..b by 2 sugar, or defer to iterator adaptors ((0..10).step_by(2))
  • Reverse — 10..0 produce empty range or compile error
  • Type resolution — a..b takes T from operands; mixed types rejected (no implicit widening)

14.4 Compilt-Time Reflection

@typename(T)
@sizeof(T)
@alignof(T)
@typeid(T)


...

// struct
@struct_field_count
@struct_field_name
@struct_field_type
@struct_field_offset
...

// union

// variant

// enum

// interface

// function

// type
@castable
@is_integer
@is_float
@is_bool
@is_pointer
@is_array
@is_struct
@is_enum
@is_union
@is_function

@zero_value(T)
  • 可以实现初步的代码生成,且比rust更加透明
  • 零开销的通用序列化、反序列化
  • 类型特化,同一个算法,适应不同数据
  • 自动构建FFI绑定或者编译器辅助工具
  • 零开销的通用错误信息与断言
  • 安全的通用空置与极值构造
  • 编译期类型关系检查,实现真正的能力匹配
  • 自动生成enum到字符串映射表