История изменений
Исправление 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)); // (!)
Алгебраические типы:
Чуть-чуть изменяем пример, чтобы в случае 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)); // (!)
Алгебраические типы:
Чуть-чуть изменяем пример, чтобы в случае 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)); // (!)
Алгебраические типы:
Чуть-чуть изменяем пример, чтобы в случае 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)); // (!)
Алгебраические типы:
Чуть-чуть изменяем пример, чтобы в случае 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__))
| ^
[слишком много выхлопа, остальное не привожу]