Commit 3049410260

Andrew Kelley <superjoe30@gmail.com>
2015-12-15 02:51:07
`const` and `var` instead of `let` and `let mut`
closes #34
1 parent 8b72755
Changed files (9)
doc/langref.md
@@ -70,7 +70,7 @@ Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression to
 
 Label: token(Symbol) token(Colon)
 
-VariableDeclaration : token(Let) option(token(Mut)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
+VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
 
 Expression : BlockExpression | NonBlockExpression
 
example/arrays/arrays.zig
@@ -3,9 +3,9 @@ export executable "arrays";
 use "std.zig";
 
 export fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
-    let mut array : [i32; 5];
+    var array : [i32; 5];
 
-    let mut i : i32 = 0;
+    var i : i32 = 0;
 loop_start:
     if i == 5 {
         goto loop_end;
@@ -17,7 +17,7 @@ loop_start:
 loop_end:
 
     i = 0;
-    let mut accumulator : i32 = 0;
+    var accumulator : i32 = 0;
 loop_2_start:
     if i == 5 {
         goto loop_2_end;
example/expressions/expressions.zig
@@ -13,17 +13,17 @@ fn other_exit() -> unreachable {
 }
 
 export fn _start() -> unreachable {
-    let a : i32 = 1;
-    let b = 2 as i32;
-    // let c : i32; // not yet support for const variables
-    // let d; // parse error
+    const a : i32 = 1;
+    const b = 2 as i32;
+    // const c : i32; // not yet support for const variables
+    // const d; // parse error
     if (a + b == 3) {
-        let no_conflict : i32 = 5;
+        const no_conflict : i32 = 5;
         if (no_conflict == 5) { puts(c"OK 1"); }
     }
 
-    let c = {
-        let no_conflict : i32 = 10;
+    const c = {
+        const no_conflict : i32 = 10;
         no_conflict
     };
     if (c == 10) { puts(c"OK 2"); }
@@ -36,15 +36,15 @@ export fn _start() -> unreachable {
 }
 
 fn void_fun(a : i32, b : void, c : i32) -> void {
-    let x = a + 1;    // i32
-    let y = c + 1;    // i32
-    let z = b;        // void
-    let w : void = z; // void
+    const x = a + 1;    // i32
+    const y = c + 1;    // i32
+    const z = b;        // void
+    const w : void = z; // void
     if (x + y == 4) { return w; }
 }
 
 fn test_mutable_vars() {
-    let mut i : i32 = 0;
+    var i : i32 = 0;
 loop_start:
     if i == 3 {
         goto done;
example/structs/structs.zig
@@ -3,7 +3,7 @@ export executable "structs";
 use "std.zig";
 
 export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
-    let mut foo : Foo;
+    var foo : Foo;
 
     foo.a = foo.a + 1;
 
src/parser.cpp
@@ -1561,53 +1561,47 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
 }
 
 /*
-VariableDeclaration : token(Let) option(token(Mut)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
+VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
 */
 static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {
-    Token *let_tok = &pc->tokens->at(*token_index);
-    if (let_tok->id == TokenIdKeywordLet) {
-        *token_index += 1;
-        AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, let_tok);
+    Token *var_or_const_tok = &pc->tokens->at(*token_index);
 
-        Token *name_token;
-        Token *token = &pc->tokens->at(*token_index);
-        if (token->id == TokenIdKeywordMut) {
-            node->data.variable_declaration.is_const = false;
-            *token_index += 1;
-            name_token = &pc->tokens->at(*token_index);
-            ast_expect_token(pc, name_token, TokenIdSymbol);
-        } else if (token->id == TokenIdSymbol) {
-            node->data.variable_declaration.is_const = true;
-            name_token = token;
-        } else {
-            ast_invalid_token_error(pc, token);
-        }
+    bool is_const;
+    if (var_or_const_tok->id == TokenIdKeywordVar) {
+        is_const = false;
+    } else if (var_or_const_tok->id == TokenIdKeywordConst) {
+        is_const = true;
+    } else if (mandatory) {
+        ast_invalid_token_error(pc, var_or_const_tok);
+    } else {
+        return nullptr;
+    }
 
-        *token_index += 1;
-        ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);
+    *token_index += 1;
+    AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_or_const_tok);
 
-        Token *eq_or_colon = &pc->tokens->at(*token_index);
-        *token_index += 1;
-        if (eq_or_colon->id == TokenIdEq) {
-            node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
-            return node;
-        } else if (eq_or_colon->id == TokenIdColon) {
-            node->data.variable_declaration.type = ast_parse_type(pc, token_index);
+    node->data.variable_declaration.is_const = is_const;
 
-            Token *eq_token = &pc->tokens->at(*token_index);
-            if (eq_token->id == TokenIdEq) {
-                *token_index += 1;
+    Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
+    ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);
 
-                node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
-            }
-            return node;
-        } else {
-            ast_invalid_token_error(pc, eq_or_colon);
+    Token *eq_or_colon = &pc->tokens->at(*token_index);
+    *token_index += 1;
+    if (eq_or_colon->id == TokenIdEq) {
+        node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
+        return node;
+    } else if (eq_or_colon->id == TokenIdColon) {
+        node->data.variable_declaration.type = ast_parse_type(pc, token_index);
+
+        Token *eq_token = &pc->tokens->at(*token_index);
+        if (eq_token->id == TokenIdEq) {
+            *token_index += 1;
+
+            node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
         }
-    } else if (mandatory) {
-        ast_invalid_token_error(pc, let_tok);
+        return node;
     } else {
-        return nullptr;
+        ast_invalid_token_error(pc, eq_or_colon);
     }
 }
 
src/tokenizer.cpp
@@ -179,10 +179,8 @@ static void end_token(Tokenize *t) {
         t->cur_tok->id = TokenIdKeywordFn;
     } else if (mem_eql_str(token_mem, token_len, "return")) {
         t->cur_tok->id = TokenIdKeywordReturn;
-    } else if (mem_eql_str(token_mem, token_len, "let")) {
-        t->cur_tok->id = TokenIdKeywordLet;
-    } else if (mem_eql_str(token_mem, token_len, "mut")) {
-        t->cur_tok->id = TokenIdKeywordMut;
+    } else if (mem_eql_str(token_mem, token_len, "var")) {
+        t->cur_tok->id = TokenIdKeywordVar;
     } else if (mem_eql_str(token_mem, token_len, "const")) {
         t->cur_tok->id = TokenIdKeywordConst;
     } else if (mem_eql_str(token_mem, token_len, "extern")) {
@@ -797,9 +795,8 @@ static const char * token_name(Token *token) {
         case TokenIdSymbol: return "Symbol";
         case TokenIdKeywordFn: return "Fn";
         case TokenIdKeywordConst: return "Const";
-        case TokenIdKeywordMut: return "Mut";
+        case TokenIdKeywordVar: return "Var";
         case TokenIdKeywordReturn: return "Return";
-        case TokenIdKeywordLet: return "Let";
         case TokenIdKeywordExtern: return "Extern";
         case TokenIdKeywordUnreachable: return "Unreachable";
         case TokenIdKeywordPub: return "Pub";
src/tokenizer.hpp
@@ -15,8 +15,7 @@ enum TokenId {
     TokenIdSymbol,
     TokenIdKeywordFn,
     TokenIdKeywordReturn,
-    TokenIdKeywordLet,
-    TokenIdKeywordMut,
+    TokenIdKeywordVar,
     TokenIdKeywordConst,
     TokenIdKeywordExtern,
     TokenIdKeywordUnreachable,
std/std.zig
@@ -1,5 +1,5 @@
 fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize {
-    let mut result : isize;
+    var result : isize;
     asm volatile ("
         mov %[number], %%rax
         mov %[arg1], %%rdi
@@ -15,13 +15,13 @@ fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize {
 
 // TODO constants for SYS_write and stdout_fileno
 pub fn write(fd: isize, buf: &const u8, count: usize) -> isize {
-    let SYS_write : isize = 1;
+    const SYS_write : isize = 1;
     return syscall3(SYS_write, fd, buf as isize, count as isize);
 }
 
 // TODO error handling
 // TODO handle buffering and flushing
 pub fn print_str(str : string) -> isize {
-    let stdout_fileno : isize = 1;
+    const stdout_fileno : isize = 1;
     return write(stdout_fileno, str.ptr, str.len);
 }
test/run_tests.cpp
@@ -265,8 +265,8 @@ extern {
 }
 
 export fn _start() -> unreachable {
-    let a : i32 = 1;
-    let b = 2 as i32;
+    const a : i32 = 1;
+    const b = 2 as i32;
     if (a + b == 3) {
         puts(c"OK");
     }
@@ -299,12 +299,12 @@ extern {
 
 export fn _start() -> unreachable {
     if (true) {
-        let no_conflict : i32 = 5;
+        const no_conflict : i32 = 5;
         if (no_conflict == 5) { puts(c"OK 1"); }
     }
 
-    let c = {
-        let no_conflict = 10 as i32;
+    const c = {
+        const no_conflict = 10 as i32;
         no_conflict
     };
     if (c == 10) { puts(c"OK 2"); }
@@ -325,8 +325,8 @@ export fn _start() -> unreachable {
 }
 
 fn void_fun(a : i32, b : void, c : i32) {
-    let v = b;
-    let vv : void = if (a == 1) {v} else {};
+    const v = b;
+    const vv : void = if (a == 1) {v} else {};
     if (a + c == 3) { puts(c"OK"); }
     return vv;
 }
@@ -340,10 +340,10 @@ extern {
 }
 
 export fn _start() -> unreachable {
-    let mut zero : i32;
+    var zero : i32;
     if (zero == 0) { puts(c"zero"); }
 
-    let mut i = 0 as i32;
+    var i = 0 as i32;
 loop_start:
     if i == 3 {
         goto done;
@@ -364,9 +364,9 @@ extern {
 }
 
 export fn _start() -> unreachable {
-    let mut array : [i32; 5];
+    var array : [i32; 5];
 
-    let mut i : i32 = 0;
+    var i : i32 = 0;
 loop_start:
     if i == 5 {
         goto loop_end;
@@ -378,7 +378,7 @@ loop_start:
 loop_end:
 
     i = 0;
-    let mut accumulator = 0 as i32;
+    var accumulator = 0 as i32;
 loop_2_start:
     if i == 5 {
         goto loop_2_end;
@@ -458,7 +458,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
 use "std.zig";
 
 export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
-    let mut i : i32 = 0;
+    var i : i32 = 0;
     i += 5;  if i != 5  { print_str("BAD +=\n" as string); }
     i -= 2;  if i != 3  { print_str("BAD -=\n" as string); }
     i *= 20; if i != 60 { print_str("BAD *=\n" as string); }
@@ -481,7 +481,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
 use "std.zig";
 
 export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
-    let mut foo : Foo;
+    var foo : Foo;
     foo.a = foo.a + 1;
     foo.b = foo.a == 1;
     test_foo(foo);
@@ -589,20 +589,20 @@ fn f(a : i32, a : i32) {
 
     add_compile_fail_case("local variable redeclaration", R"SOURCE(
 fn f() {
-    let a : i32 = 0;
-    let a = 0;
+    const a : i32 = 0;
+    const a = 0;
 }
     )SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'");
 
     add_compile_fail_case("local variable redeclares parameter", R"SOURCE(
 fn f(a : i32) {
-    let a = 0;
+    const a = 0;
 }
     )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'");
 
     add_compile_fail_case("variable has wrong type", R"SOURCE(
 fn f() -> i32 {
-    let a = c"a";
+    const a = c"a";
     a
 }
     )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got '&const u8'");
@@ -615,15 +615,15 @@ fn f() {
 
     add_compile_fail_case("assign unreachable", R"SOURCE(
 fn f() {
-    let a = return;
+    const a = return;
 }
     )SOURCE", 1, ".tmp_source.zig:3:5: error: variable initialization is unreachable");
 
     add_compile_fail_case("unreachable variable", R"SOURCE(
 fn f() {
-    let a : unreachable = return;
+    const a : unreachable = return;
 }
-    )SOURCE", 1, ".tmp_source.zig:3:13: error: variable of type 'unreachable' not allowed");
+    )SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed");
 
     add_compile_fail_case("unreachable parameter", R"SOURCE(
 fn f(a : unreachable) {}
@@ -647,7 +647,7 @@ fn f() {
 
     add_compile_fail_case("assign to constant variable", R"SOURCE(
 fn f() {
-    let a = 3;
+    const a = 3;
     a = 4;
 }
     )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant variable");
@@ -658,15 +658,15 @@ fn f() {
 }
     )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
 
-    add_compile_fail_case("let is a statement, not an expression", R"SOURCE(
+    add_compile_fail_case("const is a statement, not an expression", R"SOURCE(
 fn f() {
-    (let a = 0);
+    (const a = 0);
 }
-    )SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'let'");
+    )SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'");
 
     add_compile_fail_case("array access errors", R"SOURCE(
 fn f() {
-    let mut bad : bool;
+    var bad : bool;
     i[i] = i[i];
     bad[bad] = bad[bad];
 }