mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-06 12:46:53 +08:00
![Thakee Nathees](/assets/img/avatar_default.png)
pkVar is removed and slots (like wren) are implemented for accessing or passing pocketlang values to C and vice versa. Yet all the slot related functions are callable at runtime (a fiber is associated with the VM) which needs to be refactored to allocate slots even if it's not runtime, to let users make use of the pocketlang values before or without running a function.
219 lines
5.7 KiB
C
219 lines
5.7 KiB
C
/*
|
|
* Copyright (c) 2020-2022 Thakee Nathees
|
|
* Copyright (c) 2021-2022 Pocketlang Contributors
|
|
* Distributed Under The MIT License
|
|
*/
|
|
|
|
#include "modules.h"
|
|
|
|
#include <math.h>
|
|
|
|
// M_PI is non standard. The macro _USE_MATH_DEFINES defining before importing
|
|
// <math.h> will define the constants for MSVC. But for a portable solution,
|
|
// we're defining it ourselves if it isn't already.
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846
|
|
#endif
|
|
|
|
DEF(stdMathFloor,
|
|
"floor(value:num) -> num\n") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
pkSetSlotNumber(vm, 0, floor(num));
|
|
}
|
|
|
|
DEF(stdMathCeil,
|
|
"ceil(value:num) -> num\n") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
pkSetSlotNumber(vm, 0, ceil(num));
|
|
}
|
|
|
|
DEF(stdMathPow,
|
|
"pow(value:num) -> num\n") {
|
|
|
|
double num, ex;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
if (!pkValidateSlotNumber(vm, 2, &ex)) return;
|
|
pkSetSlotNumber(vm, 0, pow(num, ex));
|
|
}
|
|
|
|
DEF(stdMathSqrt,
|
|
"sqrt(value:num) -> num\n") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
pkSetSlotNumber(vm, 0, sqrt(num));
|
|
}
|
|
|
|
DEF(stdMathAbs,
|
|
"abs(value:num) -> num\n") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
if (num < 0) num = -num;
|
|
pkSetSlotNumber(vm, 0, num);
|
|
}
|
|
|
|
DEF(stdMathSign,
|
|
"sign(value:num) -> num\n") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
if (num < 0) num = -1;
|
|
else if (num > 0) num = +1;
|
|
else num = 0;
|
|
pkSetSlotNumber(vm, 0, num);
|
|
}
|
|
|
|
DEF(stdMathSine,
|
|
"sin(rad:num) -> num\n"
|
|
"Return the sine value of the argument [rad] which is an angle expressed "
|
|
"in radians.") {
|
|
|
|
double rad;
|
|
if (!pkValidateSlotNumber(vm, 1, &rad)) return;
|
|
pkSetSlotNumber(vm, 0, sin(rad));
|
|
}
|
|
|
|
DEF(stdMathCosine,
|
|
"cos(rad:num) -> num\n"
|
|
"Return the cosine value of the argument [rad] which is an angle expressed "
|
|
"in radians.") {
|
|
|
|
double rad;
|
|
if (!pkValidateSlotNumber(vm, 1, &rad)) return;
|
|
pkSetSlotNumber(vm, 0, cos(rad));
|
|
}
|
|
|
|
DEF(stdMathTangent,
|
|
"tan(rad:num) -> num\n"
|
|
"Return the tangent value of the argument [rad] which is an angle expressed "
|
|
"in radians.") {
|
|
|
|
double rad;
|
|
if (!pkValidateSlotNumber(vm, 1, &rad)) return;
|
|
pkSetSlotNumber(vm, 0, tan(rad));
|
|
}
|
|
|
|
DEF(stdMathSinh,
|
|
"sinh(val) -> val\n"
|
|
"Return the hyperbolic sine value of the argument [val].") {
|
|
|
|
double val;
|
|
if (!pkValidateSlotNumber(vm, 1, &val)) return;
|
|
pkSetSlotNumber(vm, 0, sinh(val));
|
|
}
|
|
|
|
DEF(stdMathCosh,
|
|
"cosh(val) -> val\n"
|
|
"Return the hyperbolic cosine value of the argument [val].") {
|
|
|
|
double val;
|
|
if (!pkValidateSlotNumber(vm, 1, &val)) return;
|
|
pkSetSlotNumber(vm, 0, cosh(val));
|
|
}
|
|
|
|
DEF(stdMathTanh,
|
|
"tanh(val) -> val\n"
|
|
"Return the hyperbolic tangent value of the argument [val].") {
|
|
|
|
double val;
|
|
if (!pkValidateSlotNumber(vm, 1, &val)) return;
|
|
pkSetSlotNumber(vm, 0, tanh(val));
|
|
}
|
|
|
|
DEF(stdMathArcSine,
|
|
"asin(num) -> num\n"
|
|
"Return the arcsine value of the argument [num] which is an angle "
|
|
"expressed in radians.") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
|
|
if (num < -1 || 1 < num) {
|
|
pkSetRuntimeError(vm, "Argument should be between -1 and +1");
|
|
}
|
|
|
|
pkSetSlotNumber(vm, 0, asin(num));
|
|
}
|
|
|
|
DEF(stdMathArcCosine,
|
|
"acos(num) -> num\n"
|
|
"Return the arc cosine value of the argument [num] which is "
|
|
"an angle expressed in radians.") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
|
|
if (num < -1 || 1 < num) {
|
|
pkSetRuntimeError(vm, "Argument should be between -1 and +1");
|
|
}
|
|
|
|
pkSetSlotNumber(vm, 0, acos(num));
|
|
}
|
|
|
|
DEF(stdMathArcTangent,
|
|
"atan(num) -> num\n"
|
|
"Return the arc tangent value of the argument [num] which is "
|
|
"an angle expressed in radians.") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
pkSetSlotNumber(vm, 0, atan(num));
|
|
}
|
|
|
|
DEF(stdMathLog10,
|
|
"log10(value:num) -> num\n"
|
|
"Return the logarithm to base 10 of argument [value]") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
pkSetSlotNumber(vm, 0, log10(num));
|
|
}
|
|
|
|
DEF(stdMathRound,
|
|
"round(value:num) -> num\n"
|
|
"Round to nearest integer, away from zero and return the number.") {
|
|
|
|
double num;
|
|
if (!pkValidateSlotNumber(vm, 1, &num)) return;
|
|
pkSetSlotNumber(vm, 0, round(num));
|
|
}
|
|
|
|
void registerModuleMath(PKVM* vm) {
|
|
|
|
PkHandle* math = pkNewModule(vm, "math");
|
|
|
|
pkModuleAddFunction(vm, math, "floor", stdMathFloor, 1);
|
|
pkModuleAddFunction(vm, math, "ceil", stdMathCeil, 1);
|
|
pkModuleAddFunction(vm, math, "pow", stdMathPow, 2);
|
|
pkModuleAddFunction(vm, math, "sqrt", stdMathSqrt, 1);
|
|
pkModuleAddFunction(vm, math, "abs", stdMathAbs, 1);
|
|
pkModuleAddFunction(vm, math, "sign", stdMathSign, 1);
|
|
pkModuleAddFunction(vm, math, "sin", stdMathSine, 1);
|
|
pkModuleAddFunction(vm, math, "cos", stdMathCosine, 1);
|
|
pkModuleAddFunction(vm, math, "tan", stdMathTangent, 1);
|
|
pkModuleAddFunction(vm, math, "sinh", stdMathSinh, 1);
|
|
pkModuleAddFunction(vm, math, "cosh", stdMathCosh, 1);
|
|
pkModuleAddFunction(vm, math, "tanh", stdMathTanh, 1);
|
|
pkModuleAddFunction(vm, math, "asin", stdMathArcSine, 1);
|
|
pkModuleAddFunction(vm, math, "acos", stdMathArcCosine, 1);
|
|
pkModuleAddFunction(vm, math, "atan", stdMathArcTangent, 1);
|
|
pkModuleAddFunction(vm, math, "log10", stdMathLog10, 1);
|
|
pkModuleAddFunction(vm, math, "round", stdMathRound, 1);
|
|
|
|
// FIXME:
|
|
// Refactor native type interface and add PI as a global to the module.
|
|
//
|
|
// Note that currently it's mutable (since it's a global variable, not
|
|
// constant and pocketlang doesn't support constant) so the user shouldn't
|
|
// modify the PI, like in python.
|
|
//pkModuleAddGlobal(vm, math, "PI", Handle-Of-PI);
|
|
|
|
pkRegisterModule(vm, math);
|
|
pkReleaseHandle(vm, math);
|
|
}
|