aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Lockwood2021-07-08 19:55:56 -0600
committerAlexis Lockwood2021-07-08 19:55:56 -0600
commit50651dae90976f223dfe58dc941c188f684cd40e (patch)
treedff2ae65a9514fe0158539fb391afeabe4503150
parent6952ba1cc69282636c3b5f372aa62d2fc6375163 (diff)
Add bitshift operators
-rw-r--r--README.md32
-rw-r--r--lib/ls_expr.c27
-rw-r--r--lib/ls_lex.c4
-rw-r--r--lib/ls_types.h2
4 files changed, 63 insertions, 2 deletions
diff --git a/README.md b/README.md
index 6de0103..2e48017 100644
--- a/README.md
+++ b/README.md
@@ -107,7 +107,6 @@ The following things use pool entries:
- All keywords (except block definers like loops) should cleanly stop parsing
at the first keyword they don't recognize. This will enable things like
IF...THEN...ELSE
-- Add leftshift, rightshift operators
- It'd be cool if `ls_minify` could access full idents beyond `LS_IDENT_LEN`;
the number of possible minified six-letter idents is enormous (about 52
billion if I did the math right) so if you're always going to minify idents
@@ -254,6 +253,37 @@ COMn [speed] [parity] [data]
FILE device /path/to/file
```
+## Operators
+
+The following operators are supported, with higher precedence values binding
+more tightly:
+
+| **OPER** | **PREC** | **OPERATION ** |
+|:---------:|---------:|----------------|
+| `ABS n` | 13 | Absolute value of n |
+| `NOT n` | 13 | Bitwise inverse of n |
+| `-n` | 13 | Negation of n |
+| `x * y` | 12 | Multiplication of x by y |
+| `x / y` | 12 | Division of x by y |
+| `x % y` | 12 | Remainder of x divided by y |
+| `x + y` | 11 | Addition of x and y |
+| `x - y` | 11 | Subtraction from x of y |
+| `x << y` | 10 | Shift of x left by y bits. If y < 0, shift right. |
+| `x >> y` | 10 | Shift of x right by y bits. If y < 0, shift left. |
+| `x < y` | 9 | Comparison of x < y |
+| `x > y` | 9 | Comparison of x > y |
+| `x <= y` | 9 | Comparison of x ≤ y |
+| `x >= y` | 9 | Comparison of x ≥ y |
+| `x = y` | 8 | Comparison of x = y |
+| `x <> y` | 8 | Comparison of x ≠ y |
+| `x and y` | 7 | Bitwise AND of x with y |
+| `x xor y` | 7 | Bitwise XOR of x with y |
+| `x or y` | 7 | Bitwise OR of x with y |
+| `x eqv y` | 7 | Bitwise equivalency of x and y (`not (x xor y)`) |
+| `x imp y` | 7 | Bitwise implication of x and y (`not (x and not y`) |
+
+The operator precedence is based on that of C.
+
## Statements
(More verbose documentation is provided below, when useful)
diff --git a/lib/ls_expr.c b/lib/ls_expr.c
index f2e4bfc..3c5581b 100644
--- a/lib/ls_expr.c
+++ b/lib/ls_expr.c
@@ -90,6 +90,8 @@ static ls_int_t _sub_int_int(ls_int_t lhs, ls_int_t rhs);
static ls_int_t _mul_int_int(ls_int_t lhs, ls_int_t rhs);
static ls_int_t _div_int_int(ls_int_t lhs, ls_int_t rhs);
static ls_int_t _mod_int_int(ls_int_t lhs, ls_int_t rhs);
+static ls_int_t _shl_int_int(ls_int_t lhs, ls_int_t rhs);
+static ls_int_t _shr_int_int(ls_int_t lhs, ls_int_t rhs);
static ls_int_t _abs_int(ls_int_t lhs, ls_int_t rhs);
static ls_int_t _neg_int(ls_int_t lhs, ls_int_t rhs);
@@ -124,6 +126,9 @@ static const ls_opdef_t _ops[] = {
[LS_OP_ADD] = { 11, false, false, &_add_int_int },
[LS_OP_SUB] = { 11, false, false, &_sub_int_int },
+ [LS_OP_SHL] = { 10, false, false, &_shl_int_int },
+ [LS_OP_SHR] = { 10, false, false, &_shr_int_int },
+
[LS_OP_LT] = { 9, false, false, &_lt_int_int },
[LS_OP_GT] = { 9, false, false, &_gt_int_int },
[LS_OP_LEQ] = { 9, false, false, &_leq_int_int },
@@ -425,6 +430,28 @@ _mod_int_int(ls_int_t lhs, ls_int_t rhs)
}
static ls_int_t
+_shl_int_int(ls_int_t lhs, ls_int_t rhs)
+{
+ if (rhs < 0)
+ return _shr_int_int(lhs, -rhs);
+ else if (rhs > 32)
+ return 0;
+ else
+ return lhs << rhs;
+}
+
+static ls_int_t
+_shr_int_int(ls_int_t lhs, ls_int_t rhs)
+{
+ if (rhs < 0)
+ return _shl_int_int(lhs, -rhs);
+ else if (rhs > 32)
+ return 0;
+ else
+ return lhs >> rhs;
+}
+
+static ls_int_t
_abs_int(ls_int_t lhs, ls_int_t rhs)
{
(void) lhs;
diff --git a/lib/ls_lex.c b/lib/ls_lex.c
index a5908dd..4de0318 100644
--- a/lib/ls_lex.c
+++ b/lib/ls_lex.c
@@ -64,7 +64,7 @@ typedef enum {
static const uint8_t _ch_kind_lut[32] = {
K(CH_KIND_SPACE, CH_KIND_OPER), // space !
K(CH_KIND_STR, CH_KIND_SIGIL), // " #
- K(CH_KIND_SIGIL, CH_KIND_SIGIL), // $ %
+ K(CH_KIND_SIGIL, CH_KIND_OPER), // $ %
K(CH_KIND_DIGIT, CH_KIND_REM), // & '
K(CH_KIND_OPER, CH_KIND_OPER), // ( )
K(CH_KIND_OPER, CH_KIND_OPER), // * +
@@ -102,6 +102,8 @@ static const ls_uchar _ops[][2] = {
[LS_OP_LEQ] = "<=",
[LS_OP_GEQ] = ">=",
[LS_OP_NEQ] = "<>",
+ [LS_OP_SHL] = "<<",
+ [LS_OP_SHR] = ">>",
[LS_OP_LPAREN] = "(",
[LS_OP_RPAREN] = ")",
[LS_OP_MOD] = "%",
diff --git a/lib/ls_types.h b/lib/ls_types.h
index 7b8d218..15ef207 100644
--- a/lib/ls_types.h
+++ b/lib/ls_types.h
@@ -300,6 +300,8 @@ typedef enum {
LS_OP_LEQ,
LS_OP_GEQ,
LS_OP_NEQ,
+ LS_OP_SHL,
+ LS_OP_SHR,
// Single char
LS_OP_LPAREN,