aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Lockwood2021-07-18 10:52:58 -0600
committerAlexis Lockwood2021-07-18 10:52:58 -0600
commitad318f0e62e15ec6e488c4594a22cee96ab154ba (patch)
treec3a3f5629875ab9a7b65172a40584aebfdff0c83
parentda12c0d48a33d46d0a9ea648d21c526953bf2da8 (diff)
Trig functions
-rw-r--r--Makefile2
-rwxr-xr-xgen_kws.py14
-rw-r--r--lib/ls_expr.c59
-rw-r--r--lib/ls_types.h8
-rw-r--r--ls_minify.c1
5 files changed, 77 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index 8c9664d..6b5c0bd 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ LIBS_ARGS := ${LIBEXPLAIN_ARGS}
TESTS := test/test_internal.test
CFLAGS := \
- -O0 -ggdb \
+ -O0 -ggdb -lm \
-std=c99 -D_DEFAULT_SOURCE \
-Wall -Wextra -Wpedantic -Wshadow -pedantic \
-Iinclude -Ilib \
diff --git a/gen_kws.py b/gen_kws.py
index 5d6c2ed..2d63d9c 100755
--- a/gen_kws.py
+++ b/gen_kws.py
@@ -52,12 +52,12 @@ KEYWORDS = [
Kw("AS", 0x82, noexec=True),
Kw("ASC", 0x83),
Kw("AT", 0x84, noexec=True),
- Kw("ATN", 0x85),
+ Kw("ATN", 0x85, op="LS_OP_ATN", noexec=True),
Kw("CALL", 0x86),
Kw("CAT", 0x87),
Kw("CHR", 0x88),
Kw("CLOSE", 0x89),
- Kw("COS", 0x8A),
+ Kw("COS", 0x8A, op="LS_OP_COS", noexec=True),
Kw("COUNT", 0x8B),
Kw("DATA", 0x8C),
Kw("DEC", 0x8D),
@@ -77,7 +77,7 @@ KEYWORDS = [
Kw("INPUT", 0x9B),
Kw("LEFT", 0x9C),
Kw("LET", 0x9D),
- Kw("LOG", 0x9E),
+ Kw("LOG", 0x9E, op="LS_OP_LOG", noexec=True),
Kw("MID", 0x9F),
Kw("NEXT", 0xA0, scanning=True),
Kw("NOT", 0xA1, op="LS_OP_NOT", noexec=True),
@@ -94,11 +94,11 @@ KEYWORDS = [
Kw("RETURN", 0xAC),
Kw("RIGHT", 0xAD),
Kw("RND", 0xAE),
- Kw("SIN", 0xAF),
- Kw("SQR", 0xB0),
+ Kw("SIN", 0xAF, op="LS_OP_SIN", noexec=True),
+ Kw("SQR", 0xB0, op="LS_OP_SQR", noexec=True),
Kw("STEP", 0xB1),
Kw("SWAP", 0xB2),
- Kw("TAN", 0xB3),
+ Kw("TAN", 0xB3, op="LS_OP_TAN", noexec=True),
Kw("THEN", 0xB4, noexec=True),
Kw("TO", 0xB5, noexec=True),
Kw("UNPACK", 0xB6),
@@ -110,6 +110,8 @@ KEYWORDS = [
Kw("XOR", 0xBC, op="LS_OP_XOR", noexec=True),
Kw("FLOAT", 0xBD, op="LS_OP_FLOAT", noexec=True),
Kw("INT", 0xBE, op="LS_OP_INT", noexec=True),
+ Kw("EXP", 0xBF, op="LS_OP_EXP", noexec=True),
+ Kw("SGN", 0xC0, op="LS_OP_SGN", noexec=True),
]
if len(sys.argv) == 2 and sys.argv[1] == "source":
diff --git a/lib/ls_expr.c b/lib/ls_expr.c
index 1a7b22b..d17453b 100644
--- a/lib/ls_expr.c
+++ b/lib/ls_expr.c
@@ -105,6 +105,9 @@ static ls_error_t _relop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op);
/// Casts
static ls_error_t _castop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op);
+/// Trig, logs, etc
+static ls_error_t _trigetcop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op);
+
// --- PUBLIC VARIABLES --------------------------------------------------------
// --- PRIVATE VARIABLES -------------------------------------------------------
@@ -114,6 +117,14 @@ static const ls_opdef_t _ops[] = {
[LS_OP_NEG] = { 13, true, true, &_arithop },
[LS_OP_FLOAT] = { 13, true, true, &_castop },
[LS_OP_INT] = { 13, true, true, &_castop },
+ [LS_OP_SGN] = { 13, true, true, &_arithop },
+ [LS_OP_ATN] = { 13, true, true, &_trigetcop },
+ [LS_OP_COS] = { 13, true, true, &_trigetcop },
+ [LS_OP_LOG] = { 13, true, true, &_trigetcop },
+ [LS_OP_SIN] = { 13, true, true, &_trigetcop },
+ [LS_OP_SQR] = { 13, true, true, &_trigetcop },
+ [LS_OP_TAN] = { 13, true, true, &_trigetcop },
+ [LS_OP_EXP] = { 13, true, true, &_trigetcop },
[LS_OP_MUL] = { 12, false, false, &_arithop },
[LS_OP_DIV] = { 12, false, false, &_arithop },
@@ -448,6 +459,8 @@ _arithop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op)
{
case LS_OP_ABS: *rhsi = (*rhsi < 0) ? -*rhsi : *rhsi; break;
case LS_OP_NEG: *rhsi = -*rhsi; break;
+ case LS_OP_SGN: *rhsi = (*rhsi < 0) ? -1 : (*rhsi > 0) ? 1 : 0;
+ break;
case LS_OP_MUL: *rhsi = *lhsi * *rhsi; break;
case LS_OP_DIV: *rhsi = *lhsi / *rhsi; break;
case LS_OP_MOD: *rhsi = *lhsi % *rhsi; break;
@@ -469,6 +482,8 @@ _arithop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op)
case LS_OP_ABS: *rhsi = fabsf(*rhsi); break;
#endif
case LS_OP_NEG: *rhsi = -*rhsi; break;
+ case LS_OP_SGN: *rhsi = (*rhsi < 0) ? -1 : (*rhsi > 0) ? 1 : 0;
+ break;
case LS_OP_MUL: *rhsi = *lhsi * *rhsi; break;
case LS_OP_DIV: *rhsi = *lhsi / *rhsi; break;
// TODO can we do better?
@@ -627,3 +642,47 @@ _castop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op)
return LS_OK;
}
+
+/// Trig, logs, etc
+static ls_error_t
+_trigetcop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op)
+{
+ (void) lhs;
+
+#ifdef LS_HAVE_FLOAT
+ switch (rhs->ty)
+ {
+ case LS_TY_INT:
+ rhs->body.float_.value = rhs->body.integer.value;
+ rhs->ty = LS_TY_FLOAT;
+ break;
+ case LS_TY_FLOAT:
+ break;
+ default:
+ return LS_TYPE_MISMATCH;
+ }
+
+ ls_float_t * v = &rhs->body.float_.value;
+
+ // TODO: use float or double functions depending on build settings
+ switch (op)
+ {
+ case LS_OP_ATN: *v = atan(*v); break;
+ case LS_OP_COS: *v = cos(*v); break;
+ case LS_OP_LOG: *v = log(*v); break;
+ case LS_OP_SIN: *v = sin(*v); break;
+ case LS_OP_SQR: *v = sqrt(*v); break;
+ case LS_OP_TAN: *v = tan(*v); break;
+ case LS_OP_EXP: *v = exp(*v); break;
+ default:
+ return LS_INTERNAL_ERROR;
+ }
+
+ return LS_OK;
+#else
+ (void) lhs;
+ (void) rhs;
+ (void) op;
+ return LS_TYPE_MISMATCH;
+#endif
+}
diff --git a/lib/ls_types.h b/lib/ls_types.h
index 4ee6b0e..caeded6 100644
--- a/lib/ls_types.h
+++ b/lib/ls_types.h
@@ -366,6 +366,14 @@ typedef enum {
LS_OP_XOR,
LS_OP_FLOAT,
LS_OP_INT,
+ LS_OP_ATN,
+ LS_OP_COS,
+ LS_OP_LOG,
+ LS_OP_SIN,
+ LS_OP_SQR,
+ LS_OP_TAN,
+ LS_OP_EXP,
+ LS_OP_SGN,
LS_NO_OP
} ls_op_t;
diff --git a/ls_minify.c b/ls_minify.c
index ff2ef6a..33e4307 100644
--- a/ls_minify.c
+++ b/ls_minify.c
@@ -310,6 +310,7 @@ static void _min_number_or_num_label(ls_token_t tok)
static void _min_float(ls_token_t tok)
{
+ (void) tok;
ls_float_t f = g_ls._token.float_;
ls_float_t g;
char buf[32];