LINUX.ORG.RU

История изменений

Исправление shdown, (текущая версия) :

Факториал в функциональном стиле:

Чуть-чуть изменяем пример (4 → 4 + 1):

#include <metalang99.h>

#define factorial(n)          ML99_natMatch(n, v(factorial_))
#define factorial_Z_IMPL(...) v(1)
#define factorial_S_IMPL(n)   ML99_mul(ML99_inc(v(n)), factorial(v(n)))

ML99_ASSERT_EQ(factorial(v(4 + 1)), v(24)); // (!)
Компиятор зависает, отжирая всё больше и больше памяти (!!!), приходит OOM killer либо systemd-oomd, либо система зависает.

Алгебраические типы:

Чуть-чуть изменяем пример, чтобы в случае tree == NULL обходил другое дерево:

#include <datatype99.h>

datatype(
    BinaryTree,
    (Leaf, int),
    (Node, BinaryTree *, int, BinaryTree *)
);

int sum(const BinaryTree *tree) {
    BinaryTree zero = {.tag = LeafTag, .data = {0}}; // (!)
    match(tree ? *tree : zero) {                     // (!)
        of(Leaf, x) return *x;
        of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
    }

    return -1;
}

Не компилируется:

In file included from ../metalang99/include/metalang99/gen.h:21,
                 from ../metalang99/include/metalang99.h:12,
                 from ./datatype99.h:30,
                 from foo.c:1:
foo.c: In function ‘sum’:
./datatype99.h:244:84: error: lvalue required as unary ‘&’ operand
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |                                                                                    ^
../metalang99/include/metalang99/stmt.h:162:5: note: in definition of macro ‘ML99_PRIV_SHADOWS’
  162 |     __VA_ARGS__                                                                                    \
      |     ^~~~~~~~~~~
./datatype99.h:244:5: note: in expansion of macro ‘ML99_INTRODUCE_NON_NULL_PTR_TO_STMT’
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./datatype99.h:41:27: note: in expansion of macro ‘match99’
   41 | #define match(val)        match99(val)
      |                           ^~~~~~~
foo.c:11:5: note: in expansion of macro ‘match’
   11 |     match(tree ? *tree : zero) {
      |     ^~~~~

Интерфейсы (почти как трейты в Rust):

Чуть-чуть изменяем пример (вместо переменной передаём в VCALL compound literal, который имеет точно такой же тип):

#include <interface99.h>

#include <stdio.h>

#define Shape_IFACE                      \
    vfunc( int, perim, const VSelf)      \
    vfunc(void, scale, VSelf, int factor)

interface(Shape);

typedef struct {
    int a, b;
} Rectangle;

int  Rectangle_perim(const VSelf) { /* ... */ }
void Rectangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Rectangle);

typedef struct {
    int a, b, c;
} Triangle;

int  Triangle_perim(const VSelf) { /* ... */ }
void Triangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Triangle);

void test(void) {                                              // (!)
    Rectangle rect = {.a = 3, .b = 4};                         // (!)
    VCALL(                                                     // (!)
        (Shape) {.self = &rect, .vptr = &Rectangle_Shape_impl}, // (!)
        scale,                                                 // (!)
        5);                                                    // (!)
}
Не компилируется:
In file included from bar.c:1:
bar.c: In function ‘test’:
./interface99.h:251:10: error: expected ‘}’ before ‘)’ token
  251 |     ((obj).vptr->IFACE99_PRIV_VCALL_OVERLOAD(__VA_ARGS__)((obj).self, __VA_ARGS__))
      |          ^
[слишком много выхлопа, остальное не привожу]

Исправление shdown, :

Факториал в функциональном стиле:

Чуть-чуть изменяем пример (4 → 4 + 1):

#include <metalang99.h>

#define factorial(n)          ML99_natMatch(n, v(factorial_))
#define factorial_Z_IMPL(...) v(1)
#define factorial_S_IMPL(n)   ML99_mul(ML99_inc(v(n)), factorial(v(n)))

ML99_ASSERT_EQ(factorial(v(4 + 1)), v(24)); // (!)
Компиятор зависает, отжирая всё больше и больше памяти (!!!), приходит OOM killer либо systemd-oomd, либо система зависает.

Алгебраические типы:

Чуть-чуть изменяем пример, чтобы в случае tree == NULL обходил другое дерево:

#include <datatype99.h>

datatype(
    BinaryTree,
    (Leaf, int),
    (Node, BinaryTree *, int, BinaryTree *)
);

int sum(const BinaryTree *tree) {
    BinaryTree zero = {.tag = LeafTag, .data = {0}}; // (!)
    match(tree ? *tree : zero) {                     // (!)
        of(Leaf, x) return *x;
        of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
    }

    return -1;
}

Не компилируется:

In file included from ../metalang99/include/metalang99/gen.h:21,
                 from ../metalang99/include/metalang99.h:12,
                 from ./datatype99.h:30,
                 from foo.c:1:
foo.c: In function ‘sum’:
./datatype99.h:244:84: error: lvalue required as unary ‘&’ operand
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |                                                                                    ^
../metalang99/include/metalang99/stmt.h:162:5: note: in definition of macro ‘ML99_PRIV_SHADOWS’
  162 |     __VA_ARGS__                                                                                    \
      |     ^~~~~~~~~~~
./datatype99.h:244:5: note: in expansion of macro ‘ML99_INTRODUCE_NON_NULL_PTR_TO_STMT’
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./datatype99.h:41:27: note: in expansion of macro ‘match99’
   41 | #define match(val)        match99(val)
      |                           ^~~~~~~
foo.c:11:5: note: in expansion of macro ‘match’
   11 |     match(tree ? *tree : zero) {
      |     ^~~~~

Интерфейсы (почти как трейты в Rust):

Чуть-чуть изменяем пример (вместо переменной передаём в VCALL compound literal, который имеет точно такой же тип):

#include <interface99.h>

#include <stdio.h>

#define Shape_IFACE                      \
    vfunc( int, perim, const VSelf)      \
    vfunc(void, scale, VSelf, int factor)

interface(Shape);

typedef struct {
    int a, b;
} Rectangle;

int  Rectangle_perim(const VSelf) { /* ... */ }
void Rectangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Rectangle);

typedef struct {
    int a, b, c;
} Triangle;

int  Triangle_perim(const VSelf) { /* ... */ }
void Triangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Triangle);

void test(void) {                                              // (!)
    Rectangle rect = {.a = 3, .b = 4};                         // (!)
    VCALL(                                                     // (!)
        (Shape) {.self = &rect, .vptr = Rectangle_Shape_impl}, // (!)
        scale,                                                 // (!)
        5);                                                    // (!)
}
Не компилируется:
In file included from bar.c:1:
bar.c: In function ‘test’:
./interface99.h:251:10: error: expected ‘}’ before ‘)’ token
  251 |     ((obj).vptr->IFACE99_PRIV_VCALL_OVERLOAD(__VA_ARGS__)((obj).self, __VA_ARGS__))
      |          ^
[слишком много выхлопа, остальное не привожу]

Исправление shdown, :

Факториал в функциональном стиле:

Чуть-чуть изменяем пример (4 → 4 + 1):

#include <metalang99.h>

#define factorial(n)          ML99_natMatch(n, v(factorial_))
#define factorial_Z_IMPL(...) v(1)
#define factorial_S_IMPL(n)   ML99_mul(ML99_inc(v(n)), factorial(v(n)))

ML99_ASSERT_EQ(factorial(v(4 + 1)), v(24)); // (!)
Компиятор зависает, отжирая всё больше и больше памяти (!!!), приходит OOM killer либо systemd-oomd, либо система зависает.

Алгебраические типы:

Чуть-чуть изменяем пример, чтобы в случае tree == NULL обходил другое дерево:

#include <datatype99.h>

datatype(
    BinaryTree,
    (Leaf, int),
    (Node, BinaryTree *, int, BinaryTree *)
);

int sum(const BinaryTree *tree) {
    BinaryTree zero = {.tag = LeafTag, .data = {0}}; // (!)
    match(tree ? *tree : zero) {                     // (!)
        of(Leaf, x) return *x;
        of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
    }

    return -1;
}

Не компилируется:

In file included from ../metalang99/include/metalang99/gen.h:21,
                 from ../metalang99/include/metalang99.h:12,
                 from ./datatype99.h:30,
                 from foo.c:1:
foo.c: In function ‘sum’:
./datatype99.h:244:84: error: lvalue required as unary ‘&’ operand
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |                                                                                    ^
../metalang99/include/metalang99/stmt.h:162:5: note: in definition of macro ‘ML99_PRIV_SHADOWS’
  162 |     __VA_ARGS__                                                                                    \
      |     ^~~~~~~~~~~
./datatype99.h:244:5: note: in expansion of macro ‘ML99_INTRODUCE_NON_NULL_PTR_TO_STMT’
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./datatype99.h:41:27: note: in expansion of macro ‘match99’
   41 | #define match(val)        match99(val)
      |                           ^~~~~~~
foo.c:11:5: note: in expansion of macro ‘match’
   11 |     match(tree ? *tree : zero) {
      |     ^~~~~

Интерфейсы (почти как трейты в Rust):

Чуть-чуть изменяем пример (вместо переменной передаём в VCALL compound literal, который имеет точно такой же тип:

#include <interface99.h>

#include <stdio.h>

#define Shape_IFACE                      \
    vfunc( int, perim, const VSelf)      \
    vfunc(void, scale, VSelf, int factor)

interface(Shape);

typedef struct {
    int a, b;
} Rectangle;

int  Rectangle_perim(const VSelf) { /* ... */ }
void Rectangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Rectangle);

typedef struct {
    int a, b, c;
} Triangle;

int  Triangle_perim(const VSelf) { /* ... */ }
void Triangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Triangle);

void test(void) {                                              // (!)
    Rectangle rect = {.a = 3, .b = 4};                         // (!)
    VCALL(                                                     // (!)
        (Shape) {.self = &rect, .vptr = Rectangle_Shape_impl}, // (!)
        scale,                                                 // (!)
        5);                                                    // (!)
}
Не компилируется:
In file included from bar.c:1:
bar.c: In function ‘test’:
./interface99.h:251:10: error: expected ‘}’ before ‘)’ token
  251 |     ((obj).vptr->IFACE99_PRIV_VCALL_OVERLOAD(__VA_ARGS__)((obj).self, __VA_ARGS__))
      |          ^
[слишком много выхлопа, остальное не привожу]

Исходная версия shdown, :

Факториал в функциональном стиле:

Чуть-чуть изменяем пример (4 → 4 + 1):

#include <metalang99.h>

#define factorial(n)          ML99_natMatch(n, v(factorial_))
#define factorial_Z_IMPL(...) v(1)
#define factorial_S_IMPL(n)   ML99_mul(ML99_inc(v(n)), factorial(v(n)))

ML99_ASSERT_EQ(factorial(v(4 + 1)), v(24)); // (!)
Компиятор зависает, отжирая всё больше и больше памяти. Приходит OOM killer либо systemd-oomd, либо система зависает.

Алгебраические типы:

Чуть-чуть изменяем пример, чтобы в случае tree == NULL обходил другое дерево:

#include <datatype99.h>

datatype(
    BinaryTree,
    (Leaf, int),
    (Node, BinaryTree *, int, BinaryTree *)
);

int sum(const BinaryTree *tree) {
    BinaryTree zero = {.tag = LeafTag, .data = {0}}; // (!)
    match(tree ? *tree : zero) {                     // (!)
        of(Leaf, x) return *x;
        of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
    }

    return -1;
}

Не компилируется:

In file included from ../metalang99/include/metalang99/gen.h:21,
                 from ../metalang99/include/metalang99.h:12,
                 from ./datatype99.h:30,
                 from foo.c:1:
foo.c: In function ‘sum’:
./datatype99.h:244:84: error: lvalue required as unary ‘&’ operand
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |                                                                                    ^
../metalang99/include/metalang99/stmt.h:162:5: note: in definition of macro ‘ML99_PRIV_SHADOWS’
  162 |     __VA_ARGS__                                                                                    \
      |     ^~~~~~~~~~~
./datatype99.h:244:5: note: in expansion of macro ‘ML99_INTRODUCE_NON_NULL_PTR_TO_STMT’
  244 |     ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./datatype99.h:41:27: note: in expansion of macro ‘match99’
   41 | #define match(val)        match99(val)
      |                           ^~~~~~~
foo.c:11:5: note: in expansion of macro ‘match’
   11 |     match(tree ? *tree : zero) {
      |     ^~~~~

Интерфейсы (почти как трейты в Rust):

Чуть-чуть изменяем пример (вместо переменной передаём в VCALL compound literal, который имеет точно такой же тип:

#include <interface99.h>

#include <stdio.h>

#define Shape_IFACE                      \
    vfunc( int, perim, const VSelf)      \
    vfunc(void, scale, VSelf, int factor)

interface(Shape);

typedef struct {
    int a, b;
} Rectangle;

int  Rectangle_perim(const VSelf) { /* ... */ }
void Rectangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Rectangle);

typedef struct {
    int a, b, c;
} Triangle;

int  Triangle_perim(const VSelf) { /* ... */ }
void Triangle_scale(VSelf, int factor) { /* ... */ }

impl(Shape, Triangle);

void test(void) {                                              // (!)
    Rectangle rect = {.a = 3, .b = 4};                         // (!)
    VCALL(                                                     // (!)
        (Shape) {.self = &rect, .vptr = Rectangle_Shape_impl}, // (!)
        scale,                                                 // (!)
        5);                                                    // (!)
}
Не компилируется:
In file included from bar.c:1:
bar.c: In function ‘test’:
./interface99.h:251:10: error: expected ‘}’ before ‘)’ token
  251 |     ((obj).vptr->IFACE99_PRIV_VCALL_OVERLOAD(__VA_ARGS__)((obj).self, __VA_ARGS__))
      |          ^
[слишком много выхлопа, остальное не привожу]