Clean up behavior and syntax for unsigned bit shifts (<<<, >>>)
This commit is contained in:
parent
3743913ce2
commit
39a58bc129
4
ast.c
4
ast.c
@ -15,8 +15,8 @@ static const char *OP_NAMES[] = {
|
||||
[BINOP_UNKNOWN]="unknown",
|
||||
[BINOP_POWER]="^", [BINOP_MULT]="*", [BINOP_DIVIDE]="/",
|
||||
[BINOP_MOD]="mod", [BINOP_MOD1]="mod1", [BINOP_PLUS]="+", [BINOP_MINUS]="minus",
|
||||
[BINOP_CONCAT]="++", [BINOP_LSHIFT]="<<", [BINOP_ULSHIFT]="<<[u]",
|
||||
[BINOP_RSHIFT]=">>", [BINOP_URSHIFT]=">>[u]", [BINOP_MIN]="min",
|
||||
[BINOP_CONCAT]="++", [BINOP_LSHIFT]="<<", [BINOP_ULSHIFT]="<<<",
|
||||
[BINOP_RSHIFT]=">>", [BINOP_URSHIFT]=">>>", [BINOP_MIN]="min",
|
||||
[BINOP_MAX]="max", [BINOP_EQ]="==", [BINOP_NE]="!=", [BINOP_LT]="<",
|
||||
[BINOP_LE]="<=", [BINOP_GT]=">", [BINOP_GE]=">=", [BINOP_CMP]="<>",
|
||||
[BINOP_AND]="and", [BINOP_OR]="or", [BINOP_XOR]="xor",
|
||||
|
@ -725,6 +725,14 @@ CORD compile_statement(env_t *env, ast_t *ast)
|
||||
if (lhs_t->tag != IntType && lhs_t->tag != ByteType)
|
||||
code_err(ast, "I can't do a shift assignment with this operator between %T and %T", lhs_t, rhs_t);
|
||||
return CORD_all(lhs, " >>= ", rhs, ";");
|
||||
case BINOP_ULSHIFT:
|
||||
if (lhs_t->tag != IntType && lhs_t->tag != ByteType)
|
||||
code_err(ast, "I can't do a shift assignment with this operator between %T and %T", lhs_t, rhs_t);
|
||||
return CORD_all("{ ", compile_unsigned_type(lhs_t), " *dest = (void*)&(", lhs, "); *dest <<= ", rhs, "; }");
|
||||
case BINOP_URSHIFT:
|
||||
if (lhs_t->tag != IntType && lhs_t->tag != ByteType)
|
||||
code_err(ast, "I can't do a shift assignment with this operator between %T and %T", lhs_t, rhs_t);
|
||||
return CORD_all("{ ", compile_unsigned_type(lhs_t), " *dest = (void*)&(", lhs, "); *dest >>= ", rhs, "; }");
|
||||
case BINOP_AND: {
|
||||
if (lhs_t->tag == BoolType)
|
||||
return CORD_all("if (", lhs, ") ", lhs, " = ", rhs, ";");
|
||||
|
@ -21,8 +21,9 @@ truncated form of the input value.
|
||||
|
||||
Integers support the standard math operations (`x+y`, `x-y`, `x*y`, `x/y`) as
|
||||
well as powers/exponentiation (`x^y`), modulus (`x mod y` and `x mod1 y`), and
|
||||
bitwise operations: `x and y`, `x or y`, `x xor y`, `x << y`, and `x >> y`. The
|
||||
operators `and`, `or`, and `xor` are _bitwise_, not logical operators.
|
||||
bitwise operations: `x and y`, `x or y`, `x xor y`, `x << y`, `x >> y`, `x >>>
|
||||
y` (unsigned right shift), and `x <<< y` (unsighted left shift). The operators
|
||||
`and`, `or`, and `xor` are _bitwise_, not logical operators.
|
||||
|
||||
# Integer Functions
|
||||
|
||||
|
@ -10,6 +10,7 @@ Tomo supports a number of operators, both infix and prefix:
|
||||
is particularly useful for doing wraparound behavior on 1-indexed arrays.
|
||||
- `++`: concatenation (for text and arrays)
|
||||
- `<<`, `>>`: bitwise left shift and right shift for integers
|
||||
- `<<<`, `>>>`: unsigned bitwise left shift and right shift for integers
|
||||
- `_min_`/`_max_`: minimum and maximum (see below)
|
||||
- `<`, `<=`, `>`, `>=`, `==`, `!=`: comparisons
|
||||
- `<>`: the signed comparison operator (see below)
|
||||
@ -283,8 +284,10 @@ and will return a value of the same type.
|
||||
#### Bit Operations
|
||||
|
||||
```
|
||||
func left_shift(T, Int)->T
|
||||
func right_shift(T, Int)->T
|
||||
func left_shifted(T, Int)->T
|
||||
func right_shifted(T, Int)->T
|
||||
func unsigned_left_shifted(T, Int)->T
|
||||
func unsigned_right_shifted(T, Int)->T
|
||||
func bit_and(T, T)->T
|
||||
func bit_or(T, T)->T
|
||||
func bit_xor(T, T)->T
|
||||
@ -292,7 +295,8 @@ func bit_xor(T, T)->T
|
||||
|
||||
In a bit shifting expression, `a >> b` or `a << b`, if `a` has type `T` and `b`
|
||||
is an `Int`, then the method `left_shift()` or `right_shift()` will be invoked.
|
||||
A value of type `T` will be returned.
|
||||
A value of type `T` will be returned. The same is true for `>>>`
|
||||
(`unsigned_right_shift()`) and `<<<` (`unsigned_left_shift`).
|
||||
|
||||
In a bitwise binary operation `a and b`, `a or b`, or `a xor b`, then the
|
||||
method `bit_and()`, `bit_or()`, or `bit_xor()` will be invoked, assuming that
|
||||
|
@ -138,8 +138,8 @@ env_t *new_compilation_unit(CORD libname)
|
||||
{"modulo1", "Int64$modulo1", "func(x,y:Int64 -> Int64)"},
|
||||
{"octal", "Int64$octal", "func(i:Int64, digits=0, prefix=yes -> Text)"},
|
||||
{"to", "Int64$to", "func(from:Int64,to:Int64 -> Range)"},
|
||||
{"unsigned_left_shift", "Int64$unsigned_left_shift", "func(x:Int64,y:Int64 -> Int64)"},
|
||||
{"unsigned_right_shift", "Int64$unsigned_right_shift", "func(x:Int64,y:Int64 -> Int64)"},
|
||||
{"unsigned_left_shifted", "Int64$unsigned_left_shifted", "func(x:Int64,y:Int64 -> Int64)"},
|
||||
{"unsigned_right_shifted", "Int64$unsigned_right_shifted", "func(x:Int64,y:Int64 -> Int64)"},
|
||||
{"wrapping_minus", "Int64$wrapping_minus", "func(x:Int64,y:Int64 -> Int64)"},
|
||||
{"wrapping_plus", "Int64$wrapping_plus", "func(x:Int64,y:Int64 -> Int64)"},
|
||||
// Must be defined after min/max:
|
||||
@ -159,8 +159,8 @@ env_t *new_compilation_unit(CORD libname)
|
||||
{"modulo1", "Int32$modulo1", "func(x,y:Int32 -> Int32)"},
|
||||
{"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes -> Text)"},
|
||||
{"to", "Int32$to", "func(from:Int32,to:Int32 -> Range)"},
|
||||
{"unsigned_left_shift", "Int32$unsigned_left_shift", "func(x:Int32,y:Int32 -> Int32)"},
|
||||
{"unsigned_right_shift", "Int32$unsigned_right_shift", "func(x:Int32,y:Int32 -> Int32)"},
|
||||
{"unsigned_left_shifted", "Int32$unsigned_left_shifted", "func(x:Int32,y:Int32 -> Int32)"},
|
||||
{"unsigned_right_shifted", "Int32$unsigned_right_shifted", "func(x:Int32,y:Int32 -> Int32)"},
|
||||
{"wrapping_minus", "Int32$wrapping_minus", "func(x:Int32,y:Int32 -> Int32)"},
|
||||
{"wrapping_plus", "Int32$wrapping_plus", "func(x:Int32,y:Int32 -> Int32)"},
|
||||
// Must be defined after min/max:
|
||||
@ -180,8 +180,8 @@ env_t *new_compilation_unit(CORD libname)
|
||||
{"modulo1", "Int16$modulo1", "func(x,y:Int16 -> Int16)"},
|
||||
{"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes -> Text)"},
|
||||
{"to", "Int16$to", "func(from:Int16,to:Int16 -> Range)"},
|
||||
{"unsigned_left_shift", "Int16$unsigned_left_shift", "func(x:Int16,y:Int16 -> Int16)"},
|
||||
{"unsigned_right_shift", "Int16$unsigned_right_shift", "func(x:Int16,y:Int16 -> Int16)"},
|
||||
{"unsigned_left_shifted", "Int16$unsigned_left_shifted", "func(x:Int16,y:Int16 -> Int16)"},
|
||||
{"unsigned_right_shifted", "Int16$unsigned_right_shifted", "func(x:Int16,y:Int16 -> Int16)"},
|
||||
{"wrapping_minus", "Int16$wrapping_minus", "func(x:Int16,y:Int16 -> Int16)"},
|
||||
{"wrapping_plus", "Int16$wrapping_plus", "func(x:Int16,y:Int16 -> Int16)"},
|
||||
// Must be defined after min/max:
|
||||
@ -201,8 +201,8 @@ env_t *new_compilation_unit(CORD libname)
|
||||
{"modulo1", "Int8$modulo1", "func(x,y:Int8 -> Int8)"},
|
||||
{"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes -> Text)"},
|
||||
{"to", "Int8$to", "func(from:Int8,to:Int8 -> Range)"},
|
||||
{"unsigned_left_shift", "Int8$unsigned_left_shift", "func(x:Int8,y:Int8 -> Int8)"},
|
||||
{"unsigned_right_shift", "Int8$unsigned_right_shift", "func(x:Int8,y:Int8 -> Int8)"},
|
||||
{"unsigned_left_shifted", "Int8$unsigned_left_shifted", "func(x:Int8,y:Int8 -> Int8)"},
|
||||
{"unsigned_right_shifted", "Int8$unsigned_right_shifted", "func(x:Int8,y:Int8 -> Int8)"},
|
||||
{"wrapping_minus", "Int8$wrapping_minus", "func(x:Int8,y:Int8 -> Int8)"},
|
||||
{"wrapping_plus", "Int8$wrapping_plus", "func(x:Int8,y:Int8 -> Int8)"},
|
||||
// Must be defined after min/max:
|
||||
|
22
parse.c
22
parse.c
@ -1706,21 +1706,21 @@ binop_e match_binary_operator(const char **pos)
|
||||
case '^': *pos += 1; return BINOP_POWER;
|
||||
case '<': {
|
||||
*pos += 1;
|
||||
if (match(pos, "=")) return BINOP_LE;
|
||||
else if (match(pos, ">")) return BINOP_CMP;
|
||||
if (match(pos, "=")) return BINOP_LE; // "<="
|
||||
else if (match(pos, ">")) return BINOP_CMP; // "<>"
|
||||
else if (match(pos, "<")) {
|
||||
if (match(pos, "[u]"))
|
||||
return BINOP_ULSHIFT;
|
||||
return BINOP_LSHIFT;
|
||||
if (match(pos, "<"))
|
||||
return BINOP_ULSHIFT; // "<<<"
|
||||
return BINOP_LSHIFT; // "<<"
|
||||
} else return BINOP_LT;
|
||||
}
|
||||
case '>': {
|
||||
*pos += 1;
|
||||
if (match(pos, "=")) return BINOP_GE;
|
||||
if (match(pos, "=")) return BINOP_GE; // ">="
|
||||
if (match(pos, ">")) {
|
||||
if (match(pos, "[u]"))
|
||||
return BINOP_URSHIFT;
|
||||
return BINOP_RSHIFT;
|
||||
if (match(pos, ">"))
|
||||
return BINOP_URSHIFT; // ">>>"
|
||||
return BINOP_RSHIFT; // ">>"
|
||||
}
|
||||
return BINOP_GT;
|
||||
}
|
||||
@ -1814,6 +1814,10 @@ PARSER(parse_update) {
|
||||
else if (match(&pos, "*=")) op = BINOP_MULT;
|
||||
else if (match(&pos, "/=")) op = BINOP_DIVIDE;
|
||||
else if (match(&pos, "^=")) op = BINOP_POWER;
|
||||
else if (match(&pos, "<<=")) op = BINOP_LSHIFT;
|
||||
else if (match(&pos, "<<<=")) op = BINOP_ULSHIFT;
|
||||
else if (match(&pos, ">>=")) op = BINOP_RSHIFT;
|
||||
else if (match(&pos, ">>>=")) op = BINOP_URSHIFT;
|
||||
else if (match(&pos, "and=")) op = BINOP_AND;
|
||||
else if (match(&pos, "or=")) op = BINOP_OR;
|
||||
else if (match(&pos, "xor=")) op = BINOP_XOR;
|
||||
|
@ -67,10 +67,10 @@
|
||||
MACROLIKE PUREFUNC c_type type_name ## $wrapping_minus(c_type x, c_type y) { \
|
||||
return (c_type)((u##c_type)x + (u##c_type)y); \
|
||||
} \
|
||||
MACROLIKE PUREFUNC c_type type_name ## $unsigned_left_shift(c_type x, c_type y) { \
|
||||
MACROLIKE PUREFUNC c_type type_name ## $unsigned_left_shifted(c_type x, c_type y) { \
|
||||
return (c_type)((u##c_type)x << y); \
|
||||
} \
|
||||
MACROLIKE PUREFUNC c_type type_name ## $unsigned_right_shift(c_type x, c_type y) { \
|
||||
MACROLIKE PUREFUNC c_type type_name ## $unsigned_right_shifted(c_type x, c_type y) { \
|
||||
return (c_type)((u##c_type)x >> y); \
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,11 @@ func main():
|
||||
!! Signed and unsigned bit shifting:
|
||||
>> -2[64] << 1
|
||||
= -4[64]
|
||||
>> -2[64] <<[u] 1
|
||||
>> -2[64] <<< 1
|
||||
= -4[64]
|
||||
>> -2[64] >> 1
|
||||
= -1[64]
|
||||
>> -2[64] >>[u] 1
|
||||
>> -2[64] >>> 1
|
||||
= 9223372036854775807[64]
|
||||
|
||||
>> 3 and 2
|
||||
|
Loading…
Reference in New Issue
Block a user