Skip to content

Commit

Permalink
feat!: Add support for bitwise operators (#425)
Browse files Browse the repository at this point in the history
* add bitwise operators to parser.dyp

* add tokens to lexer

* add operator sigils to pervasives

* add tests for bitwise operators

* fix: operator precedence levels
  • Loading branch information
bmakuh authored and ospencer committed Jan 16, 2021
1 parent 438e95a commit ddd398b
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 11 deletions.
3 changes: 3 additions & 0 deletions compiler/src/parsing/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ rule token = parse
| "}" { RBRACE }
| "[" { LBRACK }
| "]" { RBRACK }
| "^" { CARET }
| "<" { LCARET }
| ">" { RCARET }
| "^" { CARET }
Expand All @@ -202,7 +203,9 @@ rule token = parse
| "%" { PERCENT }
| "<=" { LESSEQ }
| ">=" { GREATEREQ }
| "&" { AMP }
| "&&" { AMPAMP }
| "|" { PIPE }
| "||" { PIPEPIPE }
| "!" { NOT }
| '"' { read_dquote_str (Buffer.create 16) lexbuf }
Expand Down
27 changes: 26 additions & 1 deletion compiler/src/parsing/parser.dyp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ include Parser_header
%token LBRACK RBRACK LPAREN LPARENNOSPACE RPAREN LBRACE RBRACE LCARET RCARET
%token CARET
%token COMMA SEMI AS
%token THICKARROW ARROW PIPE
%token THICKARROW ARROW
%token IS ISNT EQEQ LESSEQ GREATEREQ
%token EQUAL GETS
%token UNDERSCORE
Expand All @@ -35,6 +35,7 @@ include Parser_header

%token LET MUT REC IF WHEN ELSE MATCH WHILE
%token AMPAMP PIPEPIPE NOT
%token AMP PIPE

%token ENUM RECORD IMPORT EXPORT FOREIGN WASM PRIMITIVE
%token EXCEPT FROM
Expand Down Expand Up @@ -127,11 +128,17 @@ binop_expr :
| binop_expr(<=p80) isnt_op eols? binop_expr(<p80) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p80
| binop_expr(<=p80) eqeq_op eols? binop_expr(<p80) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p80
| binop_expr(<=p80) noteq_op eols? binop_expr(<p80) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p80
| binop_expr(<=p60) caret_op eols? binop_expr(<p60) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p60
| binop_expr(<=p90) lcaret_op eols? binop_expr(<p90) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p90
| binop_expr(<=p100) llcaret_op eols? binop_expr(<p100) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p100
| binop_expr(<=p90) rcaret_op eols? binop_expr(<p90) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p90
| binop_expr(<=p100) rrcaret_op eols? binop_expr(<p100) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p100
| binop_expr(<=p90) rrrcaret_op eols? binop_expr(<p100) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p100
| binop_expr(<=p90) lesseq_op eols? binop_expr(<p90) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p90
| binop_expr(<=p90) greatereq_op eols? binop_expr(<p90) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p90
| binop_expr(<=p70) amp_op eols? binop_expr(<p70) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p70
| binop_expr(<=p40) ampamp_op eols? binop_expr(<p40) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p40
| binop_expr(<=p50) pipe_op eols? binop_expr(<p50) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p50
| binop_expr(<=p30) pipepipe_op eols? binop_expr(<p30) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p30
| binop_expr(<=p110) plusplus_op eols? binop_expr(<p110) { Exp.apply ~loc:(symbol_rloc dyp) (mkid_expr dyp [$2]) [$1; $4] } p110
| binop_expr colon typ { Exp.constraint_ ~loc:(symbol_rloc dyp) $1 $3 } p140
Expand Down Expand Up @@ -278,16 +285,28 @@ eqeq_op :
| EQEQ { "==" }
noteq_op :
| NOT EQUAL { "!=" }
caret_op :
| CARET { "^" }
lcaret_op :
| LCARET { "<" }
llcaret_op :
| LCARET LCARET { "<<" }
rcaret_op :
| RCARET { ">" }
rrcaret_op :
| RCARET RCARET { ">>" }
rrrcaret_op :
| RCARET RCARET RCARET { ">>>" }
lesseq_op :
| LESSEQ { "<=" }
greatereq_op :
| GREATEREQ { ">=" }
amp_op :
| AMP { "&" }
ampamp_op :
| AMPAMP { "&&" }
pipe_op :
| PIPE { "|" }
pipepipe_op :
| PIPEPIPE { "||" }
pluseq_op :
Expand All @@ -312,11 +331,17 @@ infix_op :
| eqeq_op
| plusplus_op
| noteq_op
| caret_op
| lcaret_op
| llcaret_op
| rcaret_op
| rrcaret_op
| rrrcaret_op
| lesseq_op
| greatereq_op
| amp_op
| ampamp_op
| pipe_op
| pipepipe_op
| pluseq_op
| dasheq_op
Expand Down
18 changes: 18 additions & 0 deletions compiler/test/test_end_to_end.re
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,24 @@ let basic_functionality_tests = [
t("or2", "true || false", "true"),
t("or3", "false || true", "true"),
t("or4", "false || false", "false"),
t("land1", "1 & 1", "1"),
t("land2", "1 & 0", "0"),
t("land3", "0 & 1", "0"),
t("land4", "0 & 0", "0"),
t("lor1", "1 | 1", "1"),
t("lor2", "1 | 0", "1"),
t("lor3", "0 | 1", "1"),
t("lor4", "0 | 0", "0"),
t("lxor1", "1 ^ 1", "0"),
t("lxor2", "1 ^ 0", "1"),
t("lxor3", "0 ^ 1", "1"),
t("lxor4", "0 ^ 0", "0"),
t("lsl1", "7 << 1", "14"),
t("lsl2", "0 << 1", "0"),
t("lsr1", "7 >>> 1", "3"),
t("lsr2", "0 >>> 1", "0"),
t("asr1", "179 >> 1", "89"),
t("asr2", "0 >> 1", "0"),
t("comp1", "if (2 < 3) {true} else {false}", "true"),
te("comp1e", "if (2 < 3) {true} else {3}", "type"),
t("comp2", "if (2 <= 3) {true} else {false}", "true"),
Expand Down
8 changes: 4 additions & 4 deletions docs/contributor/operator_precedence.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ This table shows which operators take precedence over other operators, and can b
| 130 | Exponentiation | right-to-left | NYI |
| 120 | Multiplication<br>Division<br>Modulus | left-to-right | `… * …`<br>`… / …`<br>`… % …` |
| 110 | Addition<br>Subtraction<br>String Concatenation | left-to-right | `… + …`<br>`… - …`<br>`… ++ …` |
| 100 | Bitwise Shift Left<br>Bitwise Shift Right<br>Bitwise Arithmetic Shift Right | left-to-right | NYI |
| 100 | Bitwise Shift Left<br>Bitwise Shift Right<br>Bitwise Arithmetic Shift Right | left-to-right | `… << …` <br> `… >> …` <br> `… >>> …` |
| 90 | Less Than<br>Less Than or Equal To<br>Greater Than<br>Greater Than or Equal To | left-to-right | `… < …`<br>`… <= …`<br>`… > …`<br>`… >= …` |
| 80 | Structural Equality<br>Structural Inequality<br>Physical Equality<br>Physical Inequality | left-to-right | `… == …`<br>`… != …`<br>`… is …`<br>`… isnt …`(NYI) |
| 70 | Bitwise AND | left-to-right | NYI |
| 60 | Bitwise XOR | left-to-right | NYI |
| 50 | Bitwise OR | left-to-right | NYI |
| 70 | Bitwise AND | left-to-right | `… & …` |
| 60 | Bitwise XOR | left-to-right | `… ^ …` |
| 50 | Bitwise OR | left-to-right | `… | …` |
| 40 | Logical AND | left-to-right | `… && …` |
| 30 | Logical OR | left-to-right | `… \|\| …` |
| 20 | Ternary Conditional | right-to-left | NYI |
Expand Down
12 changes: 6 additions & 6 deletions stdlib/pervasives.gr
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ import foreign wasm numberGreaterEqual : (Number, Number) -> Bool as (>=) from '
// Number bit/logical operations
import foreign wasm numberLnot : Number -> Number as lnot from 'stdlib-external/runtime'

import foreign wasm numberLand : (Number, Number) -> Number as land from 'stdlib-external/runtime'
import foreign wasm numberLor : (Number, Number) -> Number as lor from 'stdlib-external/runtime'
import foreign wasm numberLxor : (Number, Number) -> Number as lxor from 'stdlib-external/runtime'
import foreign wasm numberLand : (Number, Number) -> Number as (&) from 'stdlib-external/runtime'
import foreign wasm numberLor : (Number, Number) -> Number as (|) from 'stdlib-external/runtime'
import foreign wasm numberLxor : (Number, Number) -> Number as (^) from 'stdlib-external/runtime'

import foreign wasm numberLsl : (Number, Number) -> Number as lsl from 'stdlib-external/runtime'
import foreign wasm numberLsr : (Number, Number) -> Number as lsr from 'stdlib-external/runtime'
import foreign wasm numberAsr : (Number, Number) -> Number as asr from 'stdlib-external/runtime'
import foreign wasm numberLsl : (Number, Number) -> Number as (<<) from 'stdlib-external/runtime'
import foreign wasm numberLsr : (Number, Number) -> Number as (>>>) from 'stdlib-external/runtime'
import foreign wasm numberAsr : (Number, Number) -> Number as (>>) from 'stdlib-external/runtime'


// Number coercions & conversions
Expand Down

0 comments on commit ddd398b

Please sign in to comment.