1
0
Fork 0
forked from fun/fun

Fixed the code style in *.c files to two spaces indentation and add a linter named funstx to Fun. (0.39.0)

This commit is contained in:
Johannes Findeisen 2026-03-18 20:52:00 +01:00
commit 03b2532474
237 changed files with 17550 additions and 13911 deletions

View file

@ -8,7 +8,7 @@
*/
/**
* @file abs.c
* @file abs.c
* @brief Implements the OP_ABS opcode for absolute value in the VM.
*
* This file handles the OP_ABS instruction, which computes the absolute value
@ -26,11 +26,14 @@
*/
case OP_ABS: {
Value x = pop_value(vm);
if (x.type != VAL_INT) { fprintf(stderr, "ABS expects int\n"); exit(1); }
int64_t v = x.i;
if (v < 0) v = -v;
push_value(vm, make_int(v));
free_value(x);
break;
Value x = pop_value(vm);
if (x.type != VAL_INT) {
fprintf(stderr, "ABS expects int\n");
exit(1);
}
int64_t v = x.i;
if (v < 0) v = -v;
push_value(vm, make_int(v));
free_value(x);
break;
}

View file

@ -10,34 +10,34 @@
*/
/**
* @file ceil.c
* @file ceil.c
* @brief Implements the OP_CEIL opcode using C99 math.h ceil().
*/
#include <math.h>
case OP_CEIL: {
Value v = pop_value(vm);
if (v.type == VAL_INT) {
/* ceil(n) == n for integers */
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = ceil(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
push_value(vm, make_float(r));
}
free_value(v);
Value v = pop_value(vm);
if (v.type == VAL_INT) {
/* ceil(n) == n for integers */
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = ceil(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
fprintf(stderr, "Runtime type error: CEIL expects number, got %s\n", value_type_name(v.type));
exit(1);
push_value(vm, make_float(r));
}
break;
free_value(v);
} else {
fprintf(stderr, "Runtime type error: CEIL expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -8,7 +8,7 @@
*/
/**
* @file clamp.c
* @file clamp.c
* @brief Implements the OP_CLAMP opcode for value clamping in the VM.
*
* This file handles the OP_CLAMP instruction, which clamps a value between
@ -27,19 +27,19 @@
*/
case OP_CLAMP: {
Value hi = pop_value(vm);
Value lo = pop_value(vm);
Value x = pop_value(vm);
if (x.type != VAL_INT || lo.type != VAL_INT || hi.type != VAL_INT) {
fprintf(stderr, "CLAMP expects ints\n");
exit(1);
}
int64_t v = x.i;
if (v < lo.i) v = lo.i;
if (v > hi.i) v = hi.i;
push_value(vm, make_int(v));
free_value(x);
free_value(lo);
free_value(hi);
break;
Value hi = pop_value(vm);
Value lo = pop_value(vm);
Value x = pop_value(vm);
if (x.type != VAL_INT || lo.type != VAL_INT || hi.type != VAL_INT) {
fprintf(stderr, "CLAMP expects ints\n");
exit(1);
}
int64_t v = x.i;
if (v < lo.i) v = lo.i;
if (v > hi.i) v = hi.i;
push_value(vm, make_int(v));
free_value(x);
free_value(lo);
free_value(hi);
break;
}

View file

@ -10,22 +10,22 @@
*/
/**
* @file cos.c
* @file cos.c
* @brief Implements the OP_COS opcode using C99 math.h cos().
*/
#include <math.h>
case OP_COS: {
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = cos(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: COS expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = cos(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: COS expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,22 +10,22 @@
*/
/**
* @file exp.c
* @file exp.c
* @brief Implements the OP_EXP opcode using C99 math.h exp().
*/
#include <math.h>
case OP_EXP: {
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = exp(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: EXP expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = exp(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: EXP expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,34 +10,34 @@
*/
/**
* @file floor.c
* @file floor.c
* @brief Implements the OP_FLOOR opcode using C99 math.h floor().
*/
#include <math.h>
case OP_FLOOR: {
Value v = pop_value(vm);
if (v.type == VAL_INT) {
/* floor(n) == n for integers */
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = floor(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
push_value(vm, make_float(r));
}
free_value(v);
Value v = pop_value(vm);
if (v.type == VAL_INT) {
/* floor(n) == n for integers */
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = floor(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
fprintf(stderr, "Runtime type error: FLOOR expects number, got %s\n", value_type_name(v.type));
exit(1);
push_value(vm, make_float(r));
}
break;
free_value(v);
} else {
fprintf(stderr, "Runtime type error: FLOOR expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,7 +10,7 @@
*/
/**
* @file fmax.c
* @file fmax.c
* @brief Implements the OP_FMAX opcode using C99 math.h fmax().
* Accepts int or float; follows IEEE-754 NaN handling per fmax.
*/
@ -18,24 +18,28 @@
#include <math.h>
case OP_FMAX: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (!((a.type == VAL_INT || a.type == VAL_FLOAT) && (b.type == VAL_INT || b.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: FMAX expects numbers, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
double r = fmax(da, db);
Value out;
if (!isnan(r) && !isinf(r) && r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) out = make_int(ii); else out = make_float(r);
} else {
out = make_float(r);
}
free_value(a); free_value(b);
push_value(vm, out);
break;
Value b = pop_value(vm);
Value a = pop_value(vm);
if (!((a.type == VAL_INT || a.type == VAL_FLOAT) && (b.type == VAL_INT || b.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: FMAX expects numbers, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
double r = fmax(da, db);
Value out;
if (!isnan(r) && !isinf(r) && r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r)
out = make_int(ii);
else
out = make_float(r);
} else {
out = make_float(r);
}
free_value(a);
free_value(b);
push_value(vm, out);
break;
}

View file

@ -10,7 +10,7 @@
*/
/**
* @file fmin.c
* @file fmin.c
* @brief Implements the OP_FMIN opcode using C99 math.h fmin().
* Accepts int or float; follows IEEE-754 NaN handling per fmin.
*/
@ -18,24 +18,28 @@
#include <math.h>
case OP_FMIN: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (!((a.type == VAL_INT || a.type == VAL_FLOAT) && (b.type == VAL_INT || b.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: FMIN expects numbers, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
double r = fmin(da, db);
Value out;
if (!isnan(r) && !isinf(r) && r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) out = make_int(ii); else out = make_float(r);
} else {
out = make_float(r);
}
free_value(a); free_value(b);
push_value(vm, out);
break;
Value b = pop_value(vm);
Value a = pop_value(vm);
if (!((a.type == VAL_INT || a.type == VAL_FLOAT) && (b.type == VAL_INT || b.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: FMIN expects numbers, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
double r = fmin(da, db);
Value out;
if (!isnan(r) && !isinf(r) && r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r)
out = make_int(ii);
else
out = make_float(r);
} else {
out = make_float(r);
}
free_value(a);
free_value(b);
push_value(vm, out);
break;
}

View file

@ -10,31 +10,37 @@
*/
/**
* @file gcd.c
* @file gcd.c
* @brief Implements the OP_GCD opcode for greatest common divisor.
*/
case OP_GCD: {
Value vb = pop_value(vm);
Value va = pop_value(vm);
if (!((va.type == VAL_INT) || (va.type == VAL_FLOAT)) ||
!((vb.type == VAL_INT) || (vb.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: GCD expects numbers, got %s and %s\n",
value_type_name(va.type), value_type_name(vb.type));
exit(1);
}
int64_t a = (va.type == VAL_INT) ? va.i : (int64_t)va.d;
int64_t b = (vb.type == VAL_INT) ? vb.i : (int64_t)vb.d;
if (a == INT64_MIN) a = (int64_t)INT64_MAX; else if (a < 0) a = -a;
if (b == INT64_MIN) b = (int64_t)INT64_MAX; else if (b < 0) b = -b;
while (b != 0) {
int64_t t = a % b;
a = b;
b = t;
}
Value res = make_int(a);
free_value(va);
free_value(vb);
push_value(vm, res);
break;
Value vb = pop_value(vm);
Value va = pop_value(vm);
if (!((va.type == VAL_INT) || (va.type == VAL_FLOAT)) ||
!((vb.type == VAL_INT) || (vb.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: GCD expects numbers, got %s and %s\n",
value_type_name(va.type), value_type_name(vb.type));
exit(1);
}
int64_t a = (va.type == VAL_INT) ? va.i : (int64_t)va.d;
int64_t b = (vb.type == VAL_INT) ? vb.i : (int64_t)vb.d;
if (a == INT64_MIN)
a = (int64_t)INT64_MAX;
else if (a < 0)
a = -a;
if (b == INT64_MIN)
b = (int64_t)INT64_MAX;
else if (b < 0)
b = -b;
while (b != 0) {
int64_t t = a % b;
a = b;
b = t;
}
Value res = make_int(a);
free_value(va);
free_value(vb);
push_value(vm, res);
break;
}

View file

@ -10,38 +10,39 @@
*/
/**
* @file isqrt.c
* @file isqrt.c
* @brief Implements the OP_ISQRT opcode for integer square root (floor).
*/
case OP_ISQRT: {
Value v = pop_value(vm);
if (!((v.type == VAL_INT) || (v.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: ISQRT expects number, got %s\n", value_type_name(v.type));
exit(1);
}
int64_t a = (v.type == VAL_INT) ? v.i : (int64_t)v.d;
if (a <= 0) {
free_value(v);
push_value(vm, make_int(0));
break;
}
/* Binary isqrt inline */
uint64_t n = (uint64_t)a;
uint64_t x = 0;
uint64_t bit = (uint64_t)1 << 62; /* highest even bit set */
while (bit > n) bit >>= 2;
while (bit != 0) {
if (n >= x + bit) {
n -= x + bit;
x = (x >> 1) + bit;
} else {
x >>= 1;
}
bit >>= 2;
}
int64_t r = (int64_t)x;
Value v = pop_value(vm);
if (!((v.type == VAL_INT) || (v.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: ISQRT expects number, got %s\n", value_type_name(v.type));
exit(1);
}
int64_t a = (v.type == VAL_INT) ? v.i : (int64_t)v.d;
if (a <= 0) {
free_value(v);
push_value(vm, make_int(r));
push_value(vm, make_int(0));
break;
}
/* Binary isqrt inline */
uint64_t n = (uint64_t)a;
uint64_t x = 0;
uint64_t bit = (uint64_t)1 << 62; /* highest even bit set */
while (bit > n)
bit >>= 2;
while (bit != 0) {
if (n >= x + bit) {
n -= x + bit;
x = (x >> 1) + bit;
} else {
x >>= 1;
}
bit >>= 2;
}
int64_t r = (int64_t)x;
free_value(v);
push_value(vm, make_int(r));
break;
}

View file

@ -10,39 +10,48 @@
*/
/**
* @file lcm.c
* @file lcm.c
* @brief Implements the OP_LCM opcode for least common multiple.
*/
case OP_LCM: {
Value vb = pop_value(vm);
Value va = pop_value(vm);
if (!((va.type == VAL_INT) || (va.type == VAL_FLOAT)) ||
!((vb.type == VAL_INT) || (vb.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: LCM expects numbers, got %s and %s\n",
value_type_name(va.type), value_type_name(vb.type));
exit(1);
}
int64_t a = (va.type == VAL_INT) ? va.i : (int64_t)va.d;
int64_t b = (vb.type == VAL_INT) ? vb.i : (int64_t)vb.d;
if (a == INT64_MIN) a = (int64_t)INT64_MAX; else if (a < 0) a = -a;
if (b == INT64_MIN) b = (int64_t)INT64_MAX; else if (b < 0) b = -b;
if (a == 0 || b == 0) {
free_value(va); free_value(vb);
push_value(vm, make_int(0));
break;
}
/* gcd(a,b) */
int64_t x = a, y = b;
while (y != 0) {
int64_t t = x % y; x = y; y = t;
}
int64_t g = x;
/* lcm = (a/g)*b (attempt to reduce overflow) */
int64_t l = (a / g) * b;
Value res = make_int(l);
Value vb = pop_value(vm);
Value va = pop_value(vm);
if (!((va.type == VAL_INT) || (va.type == VAL_FLOAT)) ||
!((vb.type == VAL_INT) || (vb.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: LCM expects numbers, got %s and %s\n",
value_type_name(va.type), value_type_name(vb.type));
exit(1);
}
int64_t a = (va.type == VAL_INT) ? va.i : (int64_t)va.d;
int64_t b = (vb.type == VAL_INT) ? vb.i : (int64_t)vb.d;
if (a == INT64_MIN)
a = (int64_t)INT64_MAX;
else if (a < 0)
a = -a;
if (b == INT64_MIN)
b = (int64_t)INT64_MAX;
else if (b < 0)
b = -b;
if (a == 0 || b == 0) {
free_value(va);
free_value(vb);
push_value(vm, res);
push_value(vm, make_int(0));
break;
}
/* gcd(a,b) */
int64_t x = a, y = b;
while (y != 0) {
int64_t t = x % y;
x = y;
y = t;
}
int64_t g = x;
/* lcm = (a/g)*b (attempt to reduce overflow) */
int64_t l = (a / g) * b;
Value res = make_int(l);
free_value(va);
free_value(vb);
push_value(vm, res);
break;
}

View file

@ -10,27 +10,27 @@
*/
/**
* @file log.c
* @file log.c
* @brief Implements the OP_LOG opcode using C99 math.h log() (natural logarithm).
*/
#include <math.h>
case OP_LOG: {
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
if (x <= 0.0) {
/* Domain error: return NaN to signal invalid input */
push_value(vm, make_float(NAN));
} else {
double r = log(x);
push_value(vm, make_float(r));
}
free_value(v);
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
if (x <= 0.0) {
/* Domain error: return NaN to signal invalid input */
push_value(vm, make_float(NAN));
} else {
fprintf(stderr, "Runtime type error: LOG expects number, got %s\n", value_type_name(v.type));
exit(1);
double r = log(x);
push_value(vm, make_float(r));
}
break;
free_value(v);
} else {
fprintf(stderr, "Runtime type error: LOG expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,26 +10,26 @@
*/
/**
* @file log10.c
* @file log10.c
* @brief Implements the OP_LOG10 opcode using C99 math.h log10().
*/
#include <math.h>
case OP_LOG10: {
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
if (x <= 0.0) {
push_value(vm, make_float(NAN));
} else {
double r = log10(x);
push_value(vm, make_float(r));
}
free_value(v);
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
if (x <= 0.0) {
push_value(vm, make_float(NAN));
} else {
fprintf(stderr, "Runtime type error: LOG10 expects number, got %s\n", value_type_name(v.type));
exit(1);
double r = log10(x);
push_value(vm, make_float(r));
}
break;
free_value(v);
} else {
fprintf(stderr, "Runtime type error: LOG10 expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -8,7 +8,7 @@
*/
/**
* @file max.c
* @file max.c
* @brief Implements the OP_MAX opcode for finding the maximum of two values in the VM.
*
* This file handles the OP_MAX instruction, which finds the maximum of two integer values.
@ -32,10 +32,14 @@
*/
case OP_MAX: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) { fprintf(stderr, "MAX expects ints\n"); exit(1); }
push_value(vm, make_int(a.i > b.i ? a.i : b.i));
free_value(a); free_value(b);
break;
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) {
fprintf(stderr, "MAX expects ints\n");
exit(1);
}
push_value(vm, make_int(a.i > b.i ? a.i : b.i));
free_value(a);
free_value(b);
break;
}

View file

@ -8,7 +8,7 @@
*/
/**
* @file min.c
* @file min.c
* @brief Implements the OP_MIN opcode for finding the minimum of two values in the VM.
*
* This file handles the OP_MIN instruction, which finds the minimum of two integer values.
@ -32,10 +32,14 @@
*/
case OP_MIN: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) { fprintf(stderr, "MIN expects ints\n"); exit(1); }
push_value(vm, make_int(a.i < b.i ? a.i : b.i));
free_value(a); free_value(b);
break;
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) {
fprintf(stderr, "MIN expects ints\n");
exit(1);
}
push_value(vm, make_int(a.i < b.i ? a.i : b.i));
free_value(a);
free_value(b);
break;
}

View file

@ -8,7 +8,7 @@
*/
/**
* @file mod.c
* @file mod.c
* @brief Implements the OP_MOD opcode for modulo operation in the VM.
*
* This file handles the OP_MOD instruction, which computes the modulo of two integer values.
@ -33,20 +33,20 @@
*/
case OP_MOD: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) {
fprintf(stderr, "Runtime type error: MOD expects ints, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
if (b.i == 0) {
fprintf(stderr, "Runtime error: modulo by zero\n");
exit(1);
}
Value res = make_int(a.i % b.i);
free_value(a);
free_value(b);
push_value(vm, res);
break;
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) {
fprintf(stderr, "Runtime type error: MOD expects ints, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
if (b.i == 0) {
fprintf(stderr, "Runtime error: modulo by zero\n");
exit(1);
}
Value res = make_int(a.i % b.i);
free_value(a);
free_value(b);
push_value(vm, res);
break;
}

View file

@ -8,7 +8,7 @@
*/
/**
* @file pow.c
* @file pow.c
* @brief Implements the OP_POW opcode for exponentiation in the VM.
*
* This file handles the OP_POW instruction, which computes the power of two integer values.
@ -32,20 +32,26 @@
*/
case OP_POW: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) { fprintf(stderr, "POW expects ints\n"); exit(1); }
int64_t base = a.i;
int64_t exp = b.i;
int64_t res = 1;
if (exp < 0) { res = 0; } else {
while (exp > 0) {
if (exp & 1) res *= base;
base *= base;
exp >>= 1;
}
Value b = pop_value(vm);
Value a = pop_value(vm);
if (a.type != VAL_INT || b.type != VAL_INT) {
fprintf(stderr, "POW expects ints\n");
exit(1);
}
int64_t base = a.i;
int64_t exp = b.i;
int64_t res = 1;
if (exp < 0) {
res = 0;
} else {
while (exp > 0) {
if (exp & 1) res *= base;
base *= base;
exp >>= 1;
}
push_value(vm, make_int(res));
free_value(a); free_value(b);
break;
}
push_value(vm, make_int(res));
free_value(a);
free_value(b);
break;
}

View file

@ -8,7 +8,7 @@
*/
/**
* @file random_int.c
* @file random_int.c
* @brief Implements the OP_RANDOM_INT opcode for generating random integers in the VM.
*
* This file handles the OP_RANDOM_INT instruction, which generates a random integer
@ -34,14 +34,23 @@
*/
case OP_RANDOM_INT: {
Value hi = pop_value(vm);
Value lo = pop_value(vm);
if (lo.type != VAL_INT || hi.type != VAL_INT) { fprintf(stderr, "RANDOM_INT expects (int, int)\n"); exit(1); }
int64_t a = lo.i, b = hi.i;
if (b <= a) { push_value(vm, make_int((int64_t)a)); free_value(lo); free_value(hi); break; }
int64_t span = b - a;
int64_t r = (int64_t)(rand() % (span));
push_value(vm, make_int(a + r));
free_value(lo); free_value(hi);
Value hi = pop_value(vm);
Value lo = pop_value(vm);
if (lo.type != VAL_INT || hi.type != VAL_INT) {
fprintf(stderr, "RANDOM_INT expects (int, int)\n");
exit(1);
}
int64_t a = lo.i, b = hi.i;
if (b <= a) {
push_value(vm, make_int((int64_t)a));
free_value(lo);
free_value(hi);
break;
}
int64_t span = b - a;
int64_t r = (int64_t)(rand() % (span));
push_value(vm, make_int(a + r));
free_value(lo);
free_value(hi);
break;
}

View file

@ -8,7 +8,7 @@
*/
/**
* @file random_seed.c
* @file random_seed.c
* @brief Implements the OP_RANDOM_SEED opcode for seeding the random number generator in the VM.
*
* This file handles the OP_RANDOM_SEED instruction, which seeds the random number generator
@ -31,10 +31,13 @@
*/
case OP_RANDOM_SEED: {
Value seed = pop_value(vm);
if (seed.type != VAL_INT) { fprintf(stderr, "RANDOM_SEED expects int\n"); exit(1); }
srand((unsigned int)seed.i);
free_value(seed);
push_value(vm, make_int(0));
break;
Value seed = pop_value(vm);
if (seed.type != VAL_INT) {
fprintf(stderr, "RANDOM_SEED expects int\n");
exit(1);
}
srand((unsigned int)seed.i);
free_value(seed);
push_value(vm, make_int(0));
break;
}

View file

@ -10,7 +10,7 @@
*/
/**
* @file round.c
* @file round.c
* @brief Implements the OP_ROUND opcode using C99 math.h round().
* C99 round() rounds half away from zero.
*/
@ -18,26 +18,26 @@
#include <math.h>
case OP_ROUND: {
Value v = pop_value(vm);
if (v.type == VAL_INT) {
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = round(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
push_value(vm, make_float(r));
}
free_value(v);
Value v = pop_value(vm);
if (v.type == VAL_INT) {
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = round(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
fprintf(stderr, "Runtime type error: ROUND expects number, got %s\n", value_type_name(v.type));
exit(1);
push_value(vm, make_float(r));
}
break;
free_value(v);
} else {
fprintf(stderr, "Runtime type error: ROUND expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,24 +10,27 @@
*/
/**
* @file sign.c
* @file sign.c
* @brief Implements the OP_SIGN opcode returning -1, 0, or 1.
*/
case OP_SIGN: {
Value v = pop_value(vm);
int out = 0;
if (v.type == VAL_INT) {
out = (v.i > 0) - (v.i < 0);
} else if (v.type == VAL_FLOAT) {
if (v.d > 0.0) out = 1;
else if (v.d < 0.0) out = -1;
else out = 0;
} else {
fprintf(stderr, "Runtime type error: SIGN expects number, got %s\n", value_type_name(v.type));
exit(1);
}
free_value(v);
push_value(vm, make_int(out));
break;
Value v = pop_value(vm);
int out = 0;
if (v.type == VAL_INT) {
out = (v.i > 0) - (v.i < 0);
} else if (v.type == VAL_FLOAT) {
if (v.d > 0.0)
out = 1;
else if (v.d < 0.0)
out = -1;
else
out = 0;
} else {
fprintf(stderr, "Runtime type error: SIGN expects number, got %s\n", value_type_name(v.type));
exit(1);
}
free_value(v);
push_value(vm, make_int(out));
break;
}

View file

@ -10,22 +10,22 @@
*/
/**
* @file sin.c
* @file sin.c
* @brief Implements the OP_SIN opcode using C99 math.h sin().
*/
#include <math.h>
case OP_SIN: {
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = sin(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: SIN expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = sin(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: SIN expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,36 +10,36 @@
*/
/**
* @file sqrt.c
* @file sqrt.c
* @brief Implements the OP_SQRT opcode using C99 math.h sqrt().
*/
#include <math.h>
case OP_SQRT: {
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
if (x < 0.0) {
push_value(vm, make_float(NAN));
} else {
double r = sqrt(x);
/* preserve int if exactly integral */
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
push_value(vm, make_float(r));
}
}
free_value(v);
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
if (x < 0.0) {
push_value(vm, make_float(NAN));
} else {
fprintf(stderr, "Runtime type error: SQRT expects number, got %s\n", value_type_name(v.type));
exit(1);
double r = sqrt(x);
/* preserve int if exactly integral */
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
push_value(vm, make_float(r));
}
}
break;
free_value(v);
} else {
fprintf(stderr, "Runtime type error: SQRT expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,22 +10,22 @@
*/
/**
* @file tan.c
* @file tan.c
* @brief Implements the OP_TAN opcode using C99 math.h tan().
*/
#include <math.h>
case OP_TAN: {
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = tan(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: TAN expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
Value v = pop_value(vm);
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
double r = tan(x);
push_value(vm, make_float(r));
free_value(v);
} else {
fprintf(stderr, "Runtime type error: TAN expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}

View file

@ -10,33 +10,33 @@
*/
/**
* @file trunc.c
* @file trunc.c
* @brief Implements the OP_TRUNC opcode using C99 math.h trunc().
*/
#include <math.h>
case OP_TRUNC: {
Value v = pop_value(vm);
if (v.type == VAL_INT) {
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = trunc(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
push_value(vm, make_float(r));
}
free_value(v);
Value v = pop_value(vm);
if (v.type == VAL_INT) {
push_value(vm, make_int(v.i));
free_value(v);
} else if (v.type == VAL_FLOAT) {
double r = trunc(v.d);
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) {
push_value(vm, make_int(ii));
} else {
push_value(vm, make_float(r));
}
} else {
fprintf(stderr, "Runtime type error: TRUNC expects number, got %s\n", value_type_name(v.type));
exit(1);
push_value(vm, make_float(r));
}
break;
free_value(v);
} else {
fprintf(stderr, "Runtime type error: TRUNC expects number, got %s\n", value_type_name(v.type));
exit(1);
}
break;
}