diff options
author | Alexis Lockwood | 2021-07-18 11:10:16 -0600 |
---|---|---|
committer | Alexis Lockwood | 2021-07-18 11:10:16 -0600 |
commit | 160d7a9b74b31538634b8140dad8053422d26e29 (patch) | |
tree | aa7aca7d3def5d7bf12ac5e484ca98db2b133ced | |
parent | ad318f0e62e15ec6e488c4594a22cee96ab154ba (diff) |
Implement nullary ops, fix op flag field overflow
-rwxr-xr-x | gen_kws.py | 2 | ||||
-rw-r--r-- | lib/ls_expr.c | 116 | ||||
-rw-r--r-- | lib/ls_internal.h | 22 | ||||
-rw-r--r-- | lib/ls_types.h | 1 |
4 files changed, 88 insertions, 53 deletions
@@ -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; |