aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Lockwood2021-07-18 11:10:16 -0600
committerAlexis Lockwood2021-07-18 11:10:16 -0600
commit160d7a9b74b31538634b8140dad8053422d26e29 (patch)
treeaa7aca7d3def5d7bf12ac5e484ca98db2b133ced
parentad318f0e62e15ec6e488c4594a22cee96ab154ba (diff)
Implement nullary ops, fix op flag field overflow
-rwxr-xr-xgen_kws.py2
-rw-r--r--lib/ls_expr.c116
-rw-r--r--lib/ls_internal.h22
-rw-r--r--lib/ls_types.h1
4 files changed, 88 insertions, 53 deletions
diff --git a/gen_kws.py b/gen_kws.py
index 2d63d9c..8ca046d 100755
--- a/gen_kws.py
+++ b/gen_kws.py
@@ -93,7 +93,7 @@ KEYWORDS = [
Kw("RESTORE", 0xAB),
Kw("RETURN", 0xAC),
Kw("RIGHT", 0xAD),
- Kw("RND", 0xAE),
+ Kw("RND", 0xAE, op="LS_OP_RND", noexec=True),
Kw("SIN", 0xAF, op="LS_OP_SIN", noexec=True),
Kw("SQR", 0xB0, op="LS_OP_SQR", noexec=True),
Kw("STEP", 0xB1),
diff --git a/lib/ls_expr.c b/lib/ls_expr.c
index d17453b..b52a912 100644
--- a/lib/ls_expr.c
+++ b/lib/ls_expr.c
@@ -11,6 +11,7 @@
#include "ls_lex.h"
// Standard headers
+#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
@@ -27,8 +28,8 @@
/// Operator definition
typedef struct {
- uint8_t precedence : 6;
- bool unary : 1;
+ uint8_t precedence : 5;
+ uint8_t n_ops : 2;
bool right : 1; // associativity
ls_error_t (*fun)(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op);
@@ -108,47 +109,52 @@ 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);
+/// Nullary operators like RND. These return one value into *rhs
+static ls_error_t _nullaryop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op);
+
// --- PUBLIC VARIABLES --------------------------------------------------------
// --- PRIVATE VARIABLES -------------------------------------------------------
static const ls_opdef_t _ops[] = {
- [LS_OP_ABS] = { 13, true, true, &_arithop },
- [LS_OP_NOT] = { 13, true, true, &_logicop },
- [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 },
- [LS_OP_MOD] = { 12, false, false, &_arithop },
-
- [LS_OP_ADD] = { 11, false, false, &_arithop },
- [LS_OP_SUB] = { 11, false, false, &_arithop },
-
- [LS_OP_SHL] = { 10, false, false, &_logicop },
- [LS_OP_SHR] = { 10, false, false, &_logicop },
-
- [LS_OP_LT] = { 9, false, false, &_relop },
- [LS_OP_GT] = { 9, false, false, &_relop },
- [LS_OP_LEQ] = { 9, false, false, &_relop },
- [LS_OP_GEQ] = { 9, false, false, &_relop },
-
- [LS_OP_EQ] = { 8, false, false, &_relop },
- [LS_OP_NEQ] = { 8, false, false, &_relop },
-
- [LS_OP_AND] = { 7, false, false, &_logicop },
- [LS_OP_XOR] = { 7, false, false, &_logicop },
- [LS_OP_OR] = { 7, false, false, &_logicop },
- [LS_OP_EQV] = { 7, false, false, &_logicop },
- [LS_OP_IMP] = { 7, false, false, &_logicop },
+ [LS_OP_RND] = { 15, 0, true, &_nullaryop },
+
+ [LS_OP_ABS] = { 13, 1, true, &_arithop },
+ [LS_OP_NOT] = { 13, 1, true, &_logicop },
+ [LS_OP_NEG] = { 13, 1, true, &_arithop },
+ [LS_OP_FLOAT] = { 13, 1, true, &_castop },
+ [LS_OP_INT] = { 13, 1, true, &_castop },
+ [LS_OP_SGN] = { 13, 1, true, &_arithop },
+ [LS_OP_ATN] = { 13, 1, true, &_trigetcop },
+ [LS_OP_COS] = { 13, 1, true, &_trigetcop },
+ [LS_OP_LOG] = { 13, 1, true, &_trigetcop },
+ [LS_OP_SIN] = { 13, 1, true, &_trigetcop },
+ [LS_OP_SQR] = { 13, 1, true, &_trigetcop },
+ [LS_OP_TAN] = { 13, 1, true, &_trigetcop },
+ [LS_OP_EXP] = { 13, 1, true, &_trigetcop },
+
+ [LS_OP_MUL] = { 12, 2, false, &_arithop },
+ [LS_OP_DIV] = { 12, 2, false, &_arithop },
+ [LS_OP_MOD] = { 12, 2, false, &_arithop },
+
+ [LS_OP_ADD] = { 11, 2, false, &_arithop },
+ [LS_OP_SUB] = { 11, 2, false, &_arithop },
+
+ [LS_OP_SHL] = { 10, 2, false, &_logicop },
+ [LS_OP_SHR] = { 10, 2, false, &_logicop },
+
+ [LS_OP_LT] = { 9, 2, false, &_relop },
+ [LS_OP_GT] = { 9, 2, false, &_relop },
+ [LS_OP_LEQ] = { 9, 2, false, &_relop },
+ [LS_OP_GEQ] = { 9, 2, false, &_relop },
+
+ [LS_OP_EQ] = { 8, 2, false, &_relop },
+ [LS_OP_NEQ] = { 8, 2, false, &_relop },
+
+ [LS_OP_AND] = { 7, 2, false, &_logicop },
+ [LS_OP_XOR] = { 7, 2, false, &_logicop },
+ [LS_OP_OR] = { 7, 2, false, &_logicop },
+ [LS_OP_EQV] = { 7, 2, false, &_logicop },
+ [LS_OP_IMP] = { 7, 2, false, &_logicop },
};
// --- PUBLIC FUNCTIONS --------------------------------------------------------
@@ -278,12 +284,21 @@ _pop_oper_and_apply(ls_shuntingyard_t * yard)
if (op == LS_OP_LPAREN)
return;
+ if (p_op->n_ops == 0)
+ {
+ ls_value_t * out = ls_alloc(yard->self);
+ LS_TRY_THROW(yard->self, p_op->fun(NULL, out, op));
+ out->next = yard->outstack;
+ yard->outstack = out;
+ return;
+ }
+
ls_value_t * rhs = yard->outstack;
if (!rhs)
ls_throw_err(yard->self, LS_INVALID_EXPR);
ls_value_t * lhs = rhs->next;
- if (!p_op->unary)
+ if (p_op->n_ops == 2)
{
if (!lhs)
ls_throw_err(yard->self, LS_INVALID_EXPR);
@@ -293,7 +308,7 @@ _pop_oper_and_apply(ls_shuntingyard_t * yard)
LS_TRY_THROW(yard->self, p_op->fun(lhs, rhs, op));
- if (!p_op->unary)
+ if (p_op->n_ops == 2)
ls_free(yard->self, lhs);
}
@@ -686,3 +701,22 @@ _trigetcop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op)
return LS_TYPE_MISMATCH;
#endif
}
+
+static ls_error_t _nullaryop(ls_value_t * lhs, ls_value_t * rhs, ls_op_t op)
+{
+ (void) lhs;
+
+ switch (op)
+ {
+ case LS_OP_RND:
+ *rhs = (ls_value_t) {
+ .ty = LS_TY_INT,
+ .body.integer.value = rand() % 65536
+ };
+ break;
+ default:
+ return LS_INTERNAL_ERROR;
+ }
+
+ return LS_OK;
+}
diff --git a/lib/ls_internal.h b/lib/ls_internal.h
index a28ce59..ee24f54 100644
--- a/lib/ls_internal.h
+++ b/lib/ls_internal.h
@@ -86,22 +86,22 @@ typedef void (*ls_kw_fun_t)(ls_t * self);
typedef struct {
char const LS_PROGMEM * name;
ls_kw_fun_t fun;
- uint8_t flags; // 3..0 equivalent op, rel to LS_OP_FIRST_KW, or 0xF
- // 4 scanning keyword (see Scanning Keywords in help)
- // 5 not executable - does not have an implementation
+ uint8_t flags; // 4..0 equivalent op, rel to LS_OP_FIRST_KW, or 0xF
+ // 5 scanning keyword (see Scanning Keywords in help)
+ // 6 not executable - does not have an implementation
} ls_kwdef_t;
// Used to encode flags INTO the kwdefs
-#define KWDEF_FLAG_OP(op) (((op) - LS_OP_FIRST_KW) & 0xF)
-#define KWDEF_FLAG_NOT_OP 0x0F
-#define KWDEF_FLAG_SCANNING 0x10
-#define KWDEF_FLAG_NOEXEC 0x20
+#define KWDEF_FLAG_OP(op) (((op) - LS_OP_FIRST_KW) & 0x1F)
+#define KWDEF_FLAG_NOT_OP 0x1F
+#define KWDEF_FLAG_SCANNING 0x20
+#define KWDEF_FLAG_NOEXEC 0x40
// Used to decode flags FROM the kwdefs
-#define KWDEF_FLAG_HAS_OP(f) (((f) & 0x0F) != 0x0F)
-#define KWDEF_FLAG_GET_OP(f) ((ls_op_t)(((f) & 0x0F) + LS_OP_FIRST_KW))
-#define KWDEF_FLAG_IS_SCANNING(f) ((f) & 0x10)
-#define KWDEF_FLAG_IS_NOEXEC(f) ((f) & 0x20)
+#define KWDEF_FLAG_HAS_OP(f) (((f) & 0x1F) != 0x1F)
+#define KWDEF_FLAG_GET_OP(f) ((ls_op_t)(((f) & 0x1F) + LS_OP_FIRST_KW))
+#define KWDEF_FLAG_IS_SCANNING(f) ((f) & 0x20)
+#define KWDEF_FLAG_IS_NOEXEC(f) ((f) & 0x40)
// --- PUBLIC CONSTANTS --------------------------------------------------------
diff --git a/lib/ls_types.h b/lib/ls_types.h
index caeded6..928061a 100644
--- a/lib/ls_types.h
+++ b/lib/ls_types.h
@@ -374,6 +374,7 @@ typedef enum {
LS_OP_TAN,
LS_OP_EXP,
LS_OP_SGN,
+ LS_OP_RND,
LS_NO_OP
} ls_op_t;