#include <stdio.h>
#include <stdint.h>
#include <assert.h>
typedef int64_t s64;
typedef int32_t s32;
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint8_t u8;
typedef double f64;
typedef float f32;
struct nil{};
#define DY_TYPE_DEFINE \
X(f64, f64, 1) \
X(s64, s64, 2) \
X(bool, bool, 3) \
X(const char *, string, 4) \
X(nil, nil, 5)
#define DY_TYPE_OTHER_DEFINE \
X(s32, f64, 1) \
X(u32, f64, 1) \
X(u64, s64, 2) \
X(f32, f64, 1) \
X(char *, string, 4)
enum{
#define X(x, y, z) DY_TYPE_ENUM_##y = z,
DY_TYPE_DEFINE
#undef X
};
struct DyType{
union{
#define X(x, y, z) x value_##y; x value_##z;
DY_TYPE_DEFINE
#undef X
};
u8 type;
#define X(x, y, z) \
DyType(x a) \
{ \
value_##z = a; \
type = z; \
}
DY_TYPE_DEFINE
DY_TYPE_OTHER_DEFINE
#undef X
DyType()
{
type = DY_TYPE_ENUM_nil;
}
};
DyType dy_cast(u8 type, DyType a)
{
switch(type)
{
case DY_TYPE_ENUM_s64:{
switch(a.type)
{
case DY_TYPE_ENUM_s64:{
}break;
case DY_TYPE_ENUM_f64:{
a.value_s64 = (s64)a.value_f64;
}break;
case DY_TYPE_ENUM_bool:{
a.value_s64 = (s64)a.value_bool;
}break;
case DY_TYPE_ENUM_string:{
assert(0);
}break;
}
}break;
case DY_TYPE_ENUM_f64:{
switch(a.type)
{
case DY_TYPE_ENUM_s64:{
a.value_f64 = (f64)a.value_s64;
}break;
case DY_TYPE_ENUM_f64:{
}break;
case DY_TYPE_ENUM_bool:{
a.value_f64 = (f64)a.value_bool;
}break;
case DY_TYPE_ENUM_string:{
assert(0);
}break;
}
}break;
case DY_TYPE_ENUM_bool:{
switch(a.type)
{
case DY_TYPE_ENUM_s64:{
a.value_bool = (bool)a.value_s64;
}break;
case DY_TYPE_ENUM_f64:{
a.value_bool = (bool)a.value_f64;
}break;
case DY_TYPE_ENUM_bool:{
}break;
case DY_TYPE_ENUM_string:{
assert(0);
}break;
}
}break;
case DY_TYPE_ENUM_string:{
switch(a.type)
{
case DY_TYPE_ENUM_s64:{
}break;
case DY_TYPE_ENUM_f64:{
}break;
case DY_TYPE_ENUM_bool:{
}break;
case DY_TYPE_ENUM_string:{
}break;
}
}break;
}
a.type = type;
return a;
}
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
DyType operator +(DyType a, DyType b)
{
u32 to_type = MIN(a.type, b.type);
a = dy_cast(to_type, a);
b = dy_cast(to_type, b);
switch(to_type)
{
case DY_TYPE_ENUM_f64:{a.value_f64 = a.value_f64 + b.value_f64;}break;
case DY_TYPE_ENUM_s64:{a.value_s64 = a.value_s64 + b.value_s64;}break;
case DY_TYPE_ENUM_bool:{a.value_bool = a.value_bool + b.value_bool;}break;
default:{assert(0);}break;
}
return a;
}
void dy_print(DyType a)
{
switch(a.type)
{
case DY_TYPE_ENUM_s64:{printf("s64 %li\n",a.value_s64);}break;
case DY_TYPE_ENUM_f64:{printf("f64 %g\n",a.value_f64);}break;
case DY_TYPE_ENUM_bool:{a.value_bool ? printf("bool true\n") : printf("bool false\n");}break;
case DY_TYPE_ENUM_string:{printf("string %s\n",a.value_string);}break;
case DY_TYPE_ENUM_nil:{printf("nil\n");}break;
}
}
int main()
{
DyType ter = true;
ter = ter + ter;
dy_print(ter); // bool true
dy_print(ter + 99); // f64 100
DyType nil_variable;
dy_print(nil_variable); // nil
dy_print(true); // bool true
dy_print("terga"); // string terga
return 0;
}