Commit 7ce753a16b

Andrew Kelley <superjoe30@gmail.com>
2017-03-26 11:21:28
replace "&&" and "||" with "and" and "or"
closes #272
1 parent 451ce09
doc/vim/syntax/zig.vim
@@ -11,7 +11,7 @@ let b:current_syntax = "zig"
 syn keyword zigStorage const var extern packed export pub noalias inline comptime nakedcc coldcc volatile
 syn keyword zigStructure struct enum union
 syn keyword zigStatement goto break return continue asm defer unreachable
-syn keyword zigConditional if else switch try
+syn keyword zigConditional if else switch try and or
 syn keyword zigRepeat while for
 
 syn keyword zigConstant null undefined this
@@ -22,7 +22,7 @@ syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ul
 
 syn keyword zigBoolean true false
 
-syn match zigOperator display "\%(+%\?\|-%\?\|/\|*%\?\|=\|\^\|&\|?\||\|!\|>\|<\|%\|<<%\?\|>>\|&&\|||\)=\?"
+syn match zigOperator display "\%(+%\?\|-%\?\|/\|*%\?\|=\|\^\|&\|?\||\|!\|>\|<\|%\|<<%\?\|>>\)=\?"
 syn match zigArrowCharacter display "->"
 
 syn match zigDecNumber display "\<[0-9]*\%(.[0-9]\+\)\=\%([eE][+-]\?[0-9]\+\)\="
doc/langref.md
@@ -69,7 +69,7 @@ UnwrapError = "%%" option("|" Symbol "|") Expression
 
 AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
 
-AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
+AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "*%=" | "+%=" | "-%=" | "<<%="
 
 BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression
 
@@ -85,7 +85,7 @@ WhileExpression = option("inline") "while" "(" Expression option(";" Expression)
 
 ForExpression = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") Expression
 
-BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
+BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
 
 ReturnExpression = option("%" | "?") "return" option(Expression)
 
@@ -101,7 +101,7 @@ IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeE
 
 Else = "else" Expression
 
-BoolAndExpression = ComparisonExpression "&&" BoolAndExpression | ComparisonExpression
+BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
 
 ComparisonExpression = BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression
 
src/parser.cpp
@@ -1007,7 +1007,6 @@ static PrefixOp tok_to_prefix_op(Token *token) {
         case TokenIdPercent: return PrefixOpError;
         case TokenIdPercentPercent: return PrefixOpUnwrapError;
         case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
-        case TokenIdBoolAnd: return PrefixOpAddressOf;
         case TokenIdStarStar: return PrefixOpDereference;
         default: return PrefixOpInvalid;
     }
@@ -1036,15 +1035,7 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
 
     AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
     AstNode *parent_node = node;
-    if (token->id == TokenIdBoolAnd) {
-        // pretend that we got 2 ampersand tokens
-
-        parent_node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
-        parent_node->data.prefix_op_expr.primary_expr = node;
-        parent_node->data.prefix_op_expr.prefix_op = PrefixOpAddressOf;
-
-        node->column += 1;
-    } else if (token->id == TokenIdStarStar) {
+    if (token->id == TokenIdStarStar) {
         // pretend that we got 2 star tokens
 
         parent_node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
@@ -1362,7 +1353,7 @@ static AstNode *ast_parse_comparison_expr(ParseContext *pc, size_t *token_index,
 }
 
 /*
-BoolAndExpression : ComparisonExpression token(BoolAnd) BoolAndExpression | ComparisonExpression
+BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
  */
 static AstNode *ast_parse_bool_and_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
     AstNode *operand_1 = ast_parse_comparison_expr(pc, token_index, mandatory);
@@ -1371,7 +1362,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, size_t *token_index, b
 
     while (true) {
         Token *token = &pc->tokens->at(*token_index);
-        if (token->id != TokenIdBoolAnd)
+        if (token->id != TokenIdKeywordAnd)
             return operand_1;
         *token_index += 1;
 
@@ -1629,7 +1620,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
 }
 
 /*
-BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
+BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
 */
 static AstNode *ast_parse_bool_or_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
     AstNode *operand_1 = ast_parse_bool_and_expr(pc, token_index, mandatory);
@@ -1638,7 +1629,7 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, size_t *token_index, bo
 
     while (true) {
         Token *token = &pc->tokens->at(*token_index);
-        if (token->id != TokenIdBoolOr)
+        if (token->id != TokenIdKeywordOr)
             return operand_1;
         *token_index += 1;
 
@@ -1924,14 +1915,12 @@ static BinOpType tok_to_ass_op(Token *token) {
         case TokenIdBitAndEq: return BinOpTypeAssignBitAnd;
         case TokenIdBitXorEq: return BinOpTypeAssignBitXor;
         case TokenIdBitOrEq: return BinOpTypeAssignBitOr;
-        case TokenIdBoolAndEq: return BinOpTypeAssignBoolAnd;
-        case TokenIdBoolOrEq: return BinOpTypeAssignBoolOr;
         default: return BinOpTypeInvalid;
     }
 }
 
 /*
-AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
+AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "*%=" | "+%=" | "-%=" | "<<%="
 */
 static BinOpType ast_parse_ass_op(ParseContext *pc, size_t *token_index, bool mandatory) {
     Token *token = &pc->tokens->at(*token_index);
src/tokenizer.cpp
@@ -107,6 +107,7 @@ struct ZigKeyword {
 };
 
 static const struct ZigKeyword zig_keywords[] = {
+    {"and", TokenIdKeywordAnd},
     {"asm", TokenIdKeywordAsm},
     {"break", TokenIdKeywordBreak},
     {"coldcc", TokenIdKeywordColdCC},
@@ -128,6 +129,7 @@ static const struct ZigKeyword zig_keywords[] = {
     {"nakedcc", TokenIdKeywordNakedCC},
     {"noalias", TokenIdKeywordNoAlias},
     {"null", TokenIdKeywordNull},
+    {"or", TokenIdKeywordOr},
     {"packed", TokenIdKeywordPacked},
     {"pub", TokenIdKeywordPub},
     {"return", TokenIdKeywordReturn},
@@ -189,10 +191,8 @@ enum TokenizeState {
     TokenizeStateSawDash,
     TokenizeStateSawMinusPercent,
     TokenizeStateSawAmpersand,
-    TokenizeStateSawAmpersandAmpersand,
     TokenizeStateSawCaret,
     TokenizeStateSawPipe,
-    TokenizeStateSawPipePipe,
     TokenizeStateLineComment,
     TokenizeStateLineString,
     TokenizeStateLineStringEnd,
@@ -824,10 +824,6 @@ void tokenize(Buf *buf, Tokenization *out) {
                 break;
             case TokenizeStateSawAmpersand:
                 switch (c) {
-                    case '&':
-                        set_token_id(&t, t.cur_tok, TokenIdBoolAnd);
-                        t.state = TokenizeStateSawAmpersandAmpersand;
-                        break;
                     case '=':
                         set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
                         end_token(&t);
@@ -840,20 +836,6 @@ void tokenize(Buf *buf, Tokenization *out) {
                         continue;
                 }
                 break;
-            case TokenizeStateSawAmpersandAmpersand:
-                switch (c) {
-                    case '=':
-                        set_token_id(&t, t.cur_tok, TokenIdBoolAndEq);
-                        end_token(&t);
-                        t.state = TokenizeStateStart;
-                        break;
-                    default:
-                        t.pos -= 1;
-                        end_token(&t);
-                        t.state = TokenizeStateStart;
-                        continue;
-                }
-                break;
             case TokenizeStateSawCaret:
                 switch (c) {
                     case '=':
@@ -870,10 +852,6 @@ void tokenize(Buf *buf, Tokenization *out) {
                 break;
             case TokenizeStateSawPipe:
                 switch (c) {
-                    case '|':
-                        set_token_id(&t, t.cur_tok, TokenIdBoolOr);
-                        t.state = TokenizeStateSawPipePipe;
-                        break;
                     case '=':
                         set_token_id(&t, t.cur_tok, TokenIdBitOrEq);
                         end_token(&t);
@@ -886,20 +864,6 @@ void tokenize(Buf *buf, Tokenization *out) {
                         continue;
                 }
                 break;
-            case TokenizeStateSawPipePipe:
-                switch (c) {
-                    case '=':
-                        set_token_id(&t, t.cur_tok, TokenIdBoolOrEq);
-                        end_token(&t);
-                        t.state = TokenizeStateStart;
-                        break;
-                    default:
-                        t.pos -= 1;
-                        end_token(&t);
-                        t.state = TokenizeStateStart;
-                        continue;
-                }
-                break;
             case TokenizeStateSawSlash:
                 switch (c) {
                     case '/':
@@ -1401,10 +1365,8 @@ void tokenize(Buf *buf, Tokenization *out) {
         case TokenizeStateSawPlus:
         case TokenizeStateSawDash:
         case TokenizeStateSawAmpersand:
-        case TokenizeStateSawAmpersandAmpersand:
         case TokenizeStateSawCaret:
         case TokenizeStateSawPipe:
-        case TokenizeStateSawPipePipe:
         case TokenizeStateSawEq:
         case TokenizeStateSawBang:
         case TokenizeStateSawLessThan:
@@ -1463,10 +1425,6 @@ const char * token_name(TokenId id) {
         case TokenIdBitShiftRight: return ">>";
         case TokenIdBitShiftRightEq: return ">>=";
         case TokenIdBitXorEq: return "^=";
-        case TokenIdBoolAnd: return "&&";
-        case TokenIdBoolAndEq: return "&&=";
-        case TokenIdBoolOr: return "||";
-        case TokenIdBoolOrEq: return "||=";
         case TokenIdCharLiteral: return "CharLiteral";
         case TokenIdCmpEq: return "==";
         case TokenIdCmpGreaterOrEq: return ">=";
@@ -1484,6 +1442,7 @@ const char * token_name(TokenId id) {
         case TokenIdEof: return "EOF";
         case TokenIdEq: return "=";
         case TokenIdFatArrow: return "=>";
+        case TokenIdKeywordAnd: return "and";
         case TokenIdKeywordAsm: return "asm";
         case TokenIdKeywordBreak: return "break";
         case TokenIdKeywordColdCC: return "coldcc";
@@ -1505,6 +1464,7 @@ const char * token_name(TokenId id) {
         case TokenIdKeywordNakedCC: return "nakedcc";
         case TokenIdKeywordNoAlias: return "noalias";
         case TokenIdKeywordNull: return "null";
+        case TokenIdKeywordOr: return "or";
         case TokenIdKeywordPacked: return "packed";
         case TokenIdKeywordPub: return "pub";
         case TokenIdKeywordReturn: return "return";
src/tokenizer.hpp
@@ -27,10 +27,6 @@ enum TokenId {
     TokenIdBitShiftRight,
     TokenIdBitShiftRightEq,
     TokenIdBitXorEq,
-    TokenIdBoolAnd,
-    TokenIdBoolAndEq,
-    TokenIdBoolOr,
-    TokenIdBoolOrEq,
     TokenIdCharLiteral,
     TokenIdCmpEq,
     TokenIdCmpGreaterOrEq,
@@ -48,6 +44,7 @@ enum TokenId {
     TokenIdEof,
     TokenIdEq,
     TokenIdFatArrow,
+    TokenIdKeywordAnd,
     TokenIdKeywordAsm,
     TokenIdKeywordBreak,
     TokenIdKeywordColdCC,
@@ -69,6 +66,7 @@ enum TokenId {
     TokenIdKeywordNakedCC,
     TokenIdKeywordNoAlias,
     TokenIdKeywordNull,
+    TokenIdKeywordOr,
     TokenIdKeywordPacked,
     TokenIdKeywordPub,
     TokenIdKeywordReturn,
std/cstr.zig
@@ -14,7 +14,7 @@ pub fn len(ptr: &const u8) -> usize {
 
 pub fn cmp(a: &const u8, b: &const u8) -> i8 {
     var index: usize = 0;
-    while (a[index] == b[index] && a[index] != 0; index += 1) {}
+    while (a[index] == b[index] and a[index] != 0; index += 1) {}
     if (a[index] > b[index]) {
         return 1;
     } else if (a[index] < b[index]) {
std/darwin.zig
@@ -56,7 +56,7 @@ pub fn exit(status: usize) -> noreturn {
 /// Get the errno from a syscall return value, or 0 for no error.
 pub fn getErrno(r: usize) -> usize {
     const signed_r = *(&isize)(&r);
-    if (signed_r > -4096 && signed_r < 0) usize(-signed_r) else 0
+    if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0
 }
 
 pub fn write(fd: i32, buf: &const u8, count: usize) -> usize {
std/debug.zig
@@ -335,7 +335,7 @@ fn parseAbbrevTable(in_stream: &io.InStream) -> %AbbrevTable {
         while (true) {
             const attr_id = %return readULeb128(in_stream);
             const form_id = %return readULeb128(in_stream);
-            if (attr_id == 0 && form_id == 0)
+            if (attr_id == 0 and form_id == 0)
                 break;
             %return attrs.append(AbbrevAttr {
                 .attr_id = attr_id,
@@ -447,7 +447,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
 
 fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> ?&const CompileUnit {
     for (st.compile_unit_list.toSlice()) |*compile_unit| {
-        if (target_address >= compile_unit.pc_start && target_address < compile_unit.pc_end)
+        if (target_address >= compile_unit.pc_start and target_address < compile_unit.pc_end)
             return compile_unit;
     }
     return null;
@@ -499,7 +499,7 @@ fn readILeb128(in_stream: &io.InStream) -> %i64 {
         shift += 7;
 
         if ((byte & 0b10000000) == 0) {
-            if (shift < @sizeOf(i64) * 8 && (byte & 0b01000000) != 0)
+            if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0)
                 result |= -(i64(1) << shift);
 
             return result;
std/elf.zig
@@ -152,8 +152,8 @@ pub const Elf = struct {
         %return elf.in_stream.seekForward(4);
 
         const header_size = %return elf.in_stream.readInt(elf.is_big_endian, u16);
-        if ((elf.is_64 && header_size != 64) ||
-            (!elf.is_64 && header_size != 52))
+        if ((elf.is_64 and header_size != 64) or
+            (!elf.is_64 and header_size != 52))
         {
             return error.InvalidFormat;
         }
@@ -172,7 +172,7 @@ pub const Elf = struct {
         const end_ph = %return math.addOverflow(u64, elf.program_header_offset, ph_byte_count);
 
         const stream_end = %return elf.in_stream.getEndPos();
-        if (stream_end < end_sh || stream_end < end_ph) {
+        if (stream_end < end_sh or stream_end < end_ph) {
             return error.InvalidFormat;
         }
 
@@ -245,7 +245,7 @@ pub const Elf = struct {
 
             for (name) |expected_c| {
                 const target_c = %return elf.in_stream.readByte();
-                if (target_c == 0 || expected_c != target_c) goto next_section;
+                if (target_c == 0 or expected_c != target_c) goto next_section;
             }
 
             {
std/fmt.zig
@@ -33,7 +33,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->bool,
         switch (state) {
             State.Start => switch (c) {
                 '{' => {
-                    // TODO if you make this an if statement with && then it breaks
+                    // TODO if you make this an if statement with `and` then it breaks
                     if (start_index < i) {
                         if (!output(context, fmt[start_index...i]))
                             return false;
std/hash_map.zig
@@ -116,7 +116,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
                 while (roll_over < hm.entries.len; roll_over += 1) {
                     const next_index = (start_index + roll_over + 1) % hm.entries.len;
                     const next_entry = &hm.entries[next_index];
-                    if (!next_entry.used || next_entry.distance_from_start_index == 0) {
+                    if (!next_entry.used or next_entry.distance_from_start_index == 0) {
                         entry.used = false;
                         hm.size -= 1;
                         return;
@@ -164,7 +164,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
                 const index = (start_index + roll_over) % hm.entries.len;
                 const entry = &hm.entries[index];
 
-                if (entry.used && !eql(entry.key, key)) {
+                if (entry.used and !eql(entry.key, key)) {
                     if (entry.distance_from_start_index < distance_from_start_index) {
                         // robin hood to the rescue
                         const tmp = *entry;
std/io.zig
@@ -148,7 +148,7 @@ pub const OutStream = struct {
         while (true) {
             const close_ret = system.close(self.fd);
             const close_err = system.getErrno(close_ret);
-            if (close_err > 0 && close_err == errno.EINTR)
+            if (close_err > 0 and close_err == errno.EINTR)
                 continue;
             return;
         }
std/linux.zig
@@ -227,7 +227,7 @@ pub const AF_MAX = PF_MAX;
 /// Get the errno from a syscall return value, or 0 for no error.
 pub fn getErrno(r: usize) -> usize {
     const signed_r = *(&isize)(&r);
-    if (signed_r > -4096 && signed_r < 0) usize(-signed_r) else 0
+    if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0
 }
 
 pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: usize)
std/math.zig
@@ -49,7 +49,7 @@ pub fn log(comptime base: usize, value: var) -> @typeOf(value) {
 
 /// x must be an integer or a float
 /// Note that this causes undefined behavior if
-/// @typeOf(x).is_signed && x == @minValue(@typeOf(x)).
+/// @typeOf(x).is_signed and x == @minValue(@typeOf(x)).
 pub fn abs(x: var) -> @typeOf(x) {
     const T = @typeOf(x);
     if (@isInteger(T)) {
std/net.zig
@@ -166,11 +166,11 @@ pub fn parseIpLiteral(buf: []const u8) -> %Address {
 
 fn hexDigit(c: u8) -> u8 {
     // TODO use switch with range
-    if ('0' <= c && c <= '9') {
+    if ('0' <= c and c <= '9') {
         c - '0'
-    } else if ('A' <= c && c <= 'Z') {
+    } else if ('A' <= c and c <= 'Z') {
         c - 'A' + 10
-    } else if ('a' <= c && c <= 'z') {
+    } else if ('a' <= c and c <= 'z') {
         c - 'a' + 10
     } else {
         @maxValue(u8)
@@ -194,7 +194,7 @@ fn parseIp6(buf: []const u8) -> %Address {
     var scope_id = false;
     for (buf) |c| {
         if (scope_id) {
-            if (c >= '0' && c <= '9') {
+            if (c >= '0' and c <= '9') {
                 const digit = c - '0';
                 if (@mulWithOverflow(u32, result.scope_id, 10, &result.scope_id)) {
                     return error.Overflow;
@@ -255,7 +255,7 @@ fn parseIp6(buf: []const u8) -> %Address {
 //		if (isdigit(*++p)) scopeid = strtoull(p, &z, 10);
 //		else z = p-1;
 //		if (*z) {
-//			if (!IN6_IS_ADDR_LINKLOCAL(&a6) &&
+//			if (!IN6_IS_ADDR_LINKLOCAL(&a6) and
 //			    !IN6_IS_ADDR_MC_LINKLOCAL(&a6))
 //				return EAI_NONAME;
 //			scopeid = if_nametoindex(p);
@@ -297,7 +297,7 @@ fn parseIp4(buf: []const u8) -> %u32 {
             index += 1;
             x = 0;
             saw_any_digits = false;
-        } else if (c >= '0' && c <= '9') {
+        } else if (c >= '0' and c <= '9') {
             saw_any_digits = true;
             const digit = c - '0';
             if (@mulWithOverflow(u8, x, 10, &x)) {
@@ -310,7 +310,7 @@ fn parseIp4(buf: []const u8) -> %u32 {
             return error.InvalidChar;
         } 
     }
-    if (index == 3 && saw_any_digits) {
+    if (index == 3 and saw_any_digits) {
         out_ptr[index] = x;
         return result;
     }
test/cases/bool.zig
@@ -25,18 +25,6 @@ fn testBoolCmp(a: bool, b: bool) -> bool {
     a == b
 }
 
-test "shortCircuitAndOr" {
-    var a = true;
-    a &&= false;
-    assert(!a);
-    a &&= true;
-    assert(!a);
-    a ||= false;
-    assert(!a);
-    a ||= true;
-    assert(a);
-}
-
 const global_f = false;
 const global_t = true;
 const not_global_f = !global_f;
test/cases/eval.zig
@@ -167,7 +167,7 @@ fn testTryToTrickEvalWithRuntimeIf(b: bool) -> usize {
 
 fn max(comptime T: type, a: T, b: T) -> T {
     if (T == bool) {
-        return a || b;
+        return a or b;
     } else if (a > b) {
         return a;
     } else {
test/cases/math.zig
@@ -59,8 +59,8 @@ test "modifyOperators" {
 test "threeExprInARow" {
 }
 fn testThreeExprInARow(f: bool, t: bool) {
-    assertFalse(f || f || f);
-    assertFalse(t && t && f);
+    assertFalse(f or f or f);
+    assertFalse(t and t and f);
     assertFalse(1 | 2 | 4 != 7);
     assertFalse(3 ^ 6 ^ 8 != 13);
     assertFalse(7 & 14 & 28 != 4);
test/cases/misc.zig
@@ -100,17 +100,17 @@ fn testShortCircuit(f: bool, t: bool) {
     var hit_3 = f;
     var hit_4 = f;
 
-    if (t || {assert(f); f}) {
+    if (t or {assert(f); f}) {
         hit_1 = t;
     }
-    if (f || { hit_2 = t; f }) {
+    if (f or { hit_2 = t; f }) {
         assert(f);
     }
 
-    if (t && { hit_3 = t; f }) {
+    if (t and { hit_3 = t; f }) {
         assert(f);
     }
-    if (f && {assert(f); f}) {
+    if (f and {assert(f); f}) {
         assert(f);
     } else {
         hit_4 = t;