Added some math opcodes. (0.37.42)
This commit is contained in:
parent
2a20b6f01a
commit
194c06e4aa
14 changed files with 413 additions and 2 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(fun VERSION 0.37.41 LANGUAGES C)
|
project(fun VERSION 0.37.42 LANGUAGES C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
|
@ -468,6 +468,12 @@ if(Threads_FOUND)
|
||||||
target_link_libraries(fun_core PUBLIC Threads::Threads)
|
target_link_libraries(fun_core PUBLIC Threads::Threads)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Link libm for C99 math functions if available
|
||||||
|
find_library(M_LIB m)
|
||||||
|
if(M_LIB)
|
||||||
|
target_link_libraries(fun_core PUBLIC ${M_LIB})
|
||||||
|
endif()
|
||||||
|
|
||||||
# Interpreter /usr/bin/fun
|
# Interpreter /usr/bin/fun
|
||||||
option(FUN_WITH_REPL "Enable interactive REPL in the fun CLI" OFF)
|
option(FUN_WITH_REPL "Enable interactive REPL in the fun CLI" OFF)
|
||||||
add_executable(fun
|
add_executable(fun
|
||||||
|
|
|
||||||
36
examples/math_ceil.fun
Normal file
36
examples/math_ceil.fun
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of C99-like ceil(x)
|
||||||
|
|
||||||
|
print("=== math ceil demo start ===")
|
||||||
|
|
||||||
|
print("ceil(3.2) -> " + to_string(ceil(3.2))) // 4
|
||||||
|
print("ceil(3.0) -> " + to_string(ceil(3.0))) // 3
|
||||||
|
print("ceil(-3.2) -> " + to_string(ceil(-3.2))) // -3
|
||||||
|
print("ceil(-3.0) -> " + to_string(ceil(-3.0))) // -3
|
||||||
|
print("ceil(0.5) -> " + to_string(ceil(0.5))) // 1
|
||||||
|
print("ceil(-0.5) -> " + to_string(ceil(-0.5))) // 0
|
||||||
|
|
||||||
|
print("=== math ceil demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (values):
|
||||||
|
=== math ceil demo start ===
|
||||||
|
ceil(3.2) -> 4
|
||||||
|
ceil(3.0) -> 3
|
||||||
|
ceil(-3.2) -> -3
|
||||||
|
ceil(-3.0) -> -3
|
||||||
|
ceil(0.5) -> 1
|
||||||
|
ceil(-0.5) -> 0
|
||||||
|
=== math ceil demo end ===
|
||||||
|
*/
|
||||||
36
examples/math_floor.fun
Normal file
36
examples/math_floor.fun
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of C99-like floor(x)
|
||||||
|
|
||||||
|
print("=== math floor demo start ===")
|
||||||
|
|
||||||
|
print("floor(3.7) -> " + to_string(floor(3.7))) // 3
|
||||||
|
print("floor(3.0) -> " + to_string(floor(3.0))) // 3
|
||||||
|
print("floor(-3.2) -> " + to_string(floor(-3.2))) // -4
|
||||||
|
print("floor(-3.0) -> " + to_string(floor(-3.0))) // -3
|
||||||
|
print("floor(0.5) -> " + to_string(floor(0.5))) // 0
|
||||||
|
print("floor(-0.5) -> " + to_string(floor(-0.5))) // -1
|
||||||
|
|
||||||
|
print("=== math floor demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (values):
|
||||||
|
=== math floor demo start ===
|
||||||
|
floor(3.7) -> 3
|
||||||
|
floor(3.0) -> 3
|
||||||
|
floor(-3.2) -> -4
|
||||||
|
floor(-3.0) -> -3
|
||||||
|
floor(0.5) -> 0
|
||||||
|
floor(-0.5) -> -1
|
||||||
|
=== math floor demo end ===
|
||||||
|
*/
|
||||||
36
examples/math_round.fun
Normal file
36
examples/math_round.fun
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of C99-like round(x) — half away from zero
|
||||||
|
|
||||||
|
print("=== math round demo start ===")
|
||||||
|
|
||||||
|
print("round(3.2) -> " + to_string(round(3.2))) // 3
|
||||||
|
print("round(3.5) -> " + to_string(round(3.5))) // 4
|
||||||
|
print("round(3.8) -> " + to_string(round(3.8))) // 4
|
||||||
|
print("round(-3.2) -> " + to_string(round(-3.2))) // -3
|
||||||
|
print("round(-3.5) -> " + to_string(round(-3.5))) // -4
|
||||||
|
print("round(-3.8) -> " + to_string(round(-3.8))) // -4
|
||||||
|
|
||||||
|
print("=== math round demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (values):
|
||||||
|
=== math round demo start ===
|
||||||
|
round(3.2) -> 3
|
||||||
|
round(3.5) -> 4
|
||||||
|
round(3.8) -> 4
|
||||||
|
round(-3.2) -> -3
|
||||||
|
round(-3.5) -> -4
|
||||||
|
round(-3.8) -> -4
|
||||||
|
=== math round demo end ===
|
||||||
|
*/
|
||||||
36
examples/math_trunc.fun
Normal file
36
examples/math_trunc.fun
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of C99-like trunc(x) — rounds toward zero
|
||||||
|
|
||||||
|
print("=== math trunc demo start ===")
|
||||||
|
|
||||||
|
print("trunc(3.7) -> " + to_string(trunc(3.7))) // 3
|
||||||
|
print("trunc(3.0) -> " + to_string(trunc(3.0))) // 3
|
||||||
|
print("trunc(-3.7) -> " + to_string(trunc(-3.7))) // -3
|
||||||
|
print("trunc(-3.0) -> " + to_string(trunc(-3.0))) // -3
|
||||||
|
print("trunc(0.5) -> " + to_string(trunc(0.5))) // 0
|
||||||
|
print("trunc(-0.5) -> " + to_string(trunc(-0.5))) // 0
|
||||||
|
|
||||||
|
print("=== math trunc demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (values):
|
||||||
|
=== math trunc demo start ===
|
||||||
|
trunc(3.7) -> 3
|
||||||
|
trunc(3.0) -> 3
|
||||||
|
trunc(-3.7) -> -3
|
||||||
|
trunc(-3.0) -> -3
|
||||||
|
trunc(0.5) -> 0
|
||||||
|
trunc(-0.5) -> 0
|
||||||
|
=== math trunc demo end ===
|
||||||
|
*/
|
||||||
|
|
@ -189,6 +189,10 @@ static const char *opcode_name(OpCode op) {
|
||||||
case OP_TK_LABEL: return "TK_LABEL";
|
case OP_TK_LABEL: return "TK_LABEL";
|
||||||
case OP_TK_BUTTON: return "TK_BUTTON";
|
case OP_TK_BUTTON: return "TK_BUTTON";
|
||||||
case OP_TK_PACK: return "TK_PACK";
|
case OP_TK_PACK: return "TK_PACK";
|
||||||
|
case OP_FLOOR: return "FLOOR";
|
||||||
|
case OP_CEIL: return "CEIL";
|
||||||
|
case OP_TRUNC: return "TRUNC";
|
||||||
|
case OP_ROUND: return "ROUND";
|
||||||
default: return "???";
|
default: return "???";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,13 @@ typedef enum {
|
||||||
// exceptions (minimal)
|
// exceptions (minimal)
|
||||||
OP_TRY_PUSH, // operand = handler ip; push handler onto try-stack
|
OP_TRY_PUSH, // operand = handler ip; push handler onto try-stack
|
||||||
OP_TRY_POP, // pop current handler
|
OP_TRY_POP, // pop current handler
|
||||||
OP_THROW // pops error value; if handler -> jump to it (push err), else print and terminate
|
OP_THROW, // pops error value; if handler -> jump to it (push err), else print and terminate
|
||||||
|
|
||||||
|
// C99 math.h rounding family (float-aware)
|
||||||
|
OP_FLOOR, // pops x (int/float); pushes floor(x) (int if integral else float)
|
||||||
|
OP_CEIL, // pops x (int/float); pushes ceil(x) (int if integral else float)
|
||||||
|
OP_TRUNC, // pops x (int/float); pushes trunc(x) (int if integral else float)
|
||||||
|
OP_ROUND // pops x (int/float); pushes round(x) (half away from zero)
|
||||||
} OpCode;
|
} OpCode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,12 @@ int main(void) {
|
||||||
int c3 = bytecode_add_constant(bc, make_int(3));
|
int c3 = bytecode_add_constant(bc, make_int(3));
|
||||||
int c10 = bytecode_add_constant(bc, make_int(10));
|
int c10 = bytecode_add_constant(bc, make_int(10));
|
||||||
int c42 = bytecode_add_constant(bc, make_int(42));
|
int c42 = bytecode_add_constant(bc, make_int(42));
|
||||||
|
int cf3_2 = bytecode_add_constant(bc, make_float(3.2));
|
||||||
|
int cf3_5 = bytecode_add_constant(bc, make_float(3.5));
|
||||||
|
int cf3_8 = bytecode_add_constant(bc, make_float(3.8));
|
||||||
|
int cfn3_2 = bytecode_add_constant(bc, make_float(-3.2));
|
||||||
|
int cfn3_5 = bytecode_add_constant(bc, make_float(-3.5));
|
||||||
|
int cfn3_8 = bytecode_add_constant(bc, make_float(-3.8));
|
||||||
|
|
||||||
// ---------- Arithmetic ----------
|
// ---------- Arithmetic ----------
|
||||||
bytecode_add_instruction(bc, OP_LOAD_CONST, c42);
|
bytecode_add_instruction(bc, OP_LOAD_CONST, c42);
|
||||||
|
|
@ -120,6 +126,48 @@ int main(void) {
|
||||||
bytecode_add_instruction(bc, OP_LOAD_CONST, c1);
|
bytecode_add_instruction(bc, OP_LOAD_CONST, c1);
|
||||||
bytecode_add_instruction(bc, OP_POP, 0); // dApache-2.0ard 1 (stack now empty)
|
bytecode_add_instruction(bc, OP_POP, 0); // dApache-2.0ard 1 (stack now empty)
|
||||||
|
|
||||||
|
// ---------- Rounding (math.h) demo ----------
|
||||||
|
// floor/ceil/trunc/round on representative values
|
||||||
|
int start_round_demo = bc->instr_count;
|
||||||
|
(void)start_round_demo;
|
||||||
|
|
||||||
|
// +3.2
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf3_2);
|
||||||
|
bytecode_add_instruction(bc, OP_FLOOR, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf3_2);
|
||||||
|
bytecode_add_instruction(bc, OP_CEIL, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf3_2);
|
||||||
|
bytecode_add_instruction(bc, OP_TRUNC, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf3_2);
|
||||||
|
bytecode_add_instruction(bc, OP_ROUND, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
|
||||||
|
// +3.5
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf3_5);
|
||||||
|
bytecode_add_instruction(bc, OP_ROUND, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
|
||||||
|
// -3.5
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cfn3_5);
|
||||||
|
bytecode_add_instruction(bc, OP_ROUND, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
|
||||||
|
// -3.2
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cfn3_2);
|
||||||
|
bytecode_add_instruction(bc, OP_FLOOR, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cfn3_2);
|
||||||
|
bytecode_add_instruction(bc, OP_CEIL, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
|
||||||
|
// integers should be unchanged
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, c10);
|
||||||
|
bytecode_add_instruction(bc, OP_FLOOR, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
|
||||||
// ---------- HALT ----------
|
// ---------- HALT ----------
|
||||||
bytecode_add_instruction(bc, OP_HALT, 0);
|
bytecode_add_instruction(bc, OP_HALT, 0);
|
||||||
|
|
||||||
|
|
|
||||||
28
src/parser.c
28
src/parser.c
|
|
@ -1758,6 +1758,34 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos)
|
||||||
free(name);
|
free(name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (strcmp(name, "floor") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "floor expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_FLOOR, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "ceil") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "ceil expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_CEIL, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "trunc") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "trunc expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_TRUNC, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "round") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "round expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_ROUND, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (strcmp(name, "pow") == 0) {
|
if (strcmp(name, "pow") == 0) {
|
||||||
(*pos)++; /* '(' */
|
(*pos)++; /* '(' */
|
||||||
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ',')) { parser_fail(*pos, "pow expects 2 args"); free(name); return 0; }
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ',')) { parser_fail(*pos, "pow expects 2 args"); free(name); return 0; }
|
||||||
|
|
|
||||||
4
src/vm.c
4
src/vm.c
|
|
@ -674,6 +674,10 @@ void vm_run(VM *vm, Bytecode *entry) {
|
||||||
#include "vm/math/min.c"
|
#include "vm/math/min.c"
|
||||||
#include "vm/math/mod.c"
|
#include "vm/math/mod.c"
|
||||||
#include "vm/math/pow.c"
|
#include "vm/math/pow.c"
|
||||||
|
#include "vm/math/floor.c"
|
||||||
|
#include "vm/math/ceil.c"
|
||||||
|
#include "vm/math/trunc.c"
|
||||||
|
#include "vm/math/round.c"
|
||||||
#include "vm/math/random_int.c"
|
#include "vm/math/random_int.c"
|
||||||
#include "vm/math/random_seed.c"
|
#include "vm/math/random_seed.c"
|
||||||
|
|
||||||
|
|
|
||||||
43
src/vm/math/ceil.c
Normal file
43
src/vm/math/ceil.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: CEIL expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
43
src/vm/math/floor.c
Normal file
43
src/vm/math/floor.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: FLOOR expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
43
src/vm/math/round.c
Normal file
43
src/vm/math/round.c
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file round.c
|
||||||
|
* @brief Implements the OP_ROUND opcode using C99 math.h round().
|
||||||
|
* C99 round() rounds half away from zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: ROUND expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
42
src/vm/math/trunc.c
Normal file
42
src/vm/math/trunc.c
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* This file is part of the Fun programming language.
|
||||||
|
* https://fun-lang.xyz/
|
||||||
|
*
|
||||||
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
||||||
|
* Licensed under the terms of the Apache-2.0 license.
|
||||||
|
* https://opensource.org/license/apache-2-0
|
||||||
|
*
|
||||||
|
* Added: 2026-01-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: TRUNC expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue