From 304941026013e6310c9362849610c32d98d1332a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 14 Dec 2015 18:51:07 -0700 Subject: [PATCH] `const` and `var` instead of `let` and `let mut` closes #34 --- doc/langref.md | 2 +- example/arrays/arrays.zig | 6 +-- example/expressions/expressions.zig | 24 ++++----- example/structs/structs.zig | 2 +- src/parser.cpp | 76 +++++++++++++---------------- src/tokenizer.cpp | 9 ++-- src/tokenizer.hpp | 3 +- std/std.zig | 6 +-- test/run_tests.cpp | 52 ++++++++++---------- 9 files changed, 85 insertions(+), 95 deletions(-) diff --git a/doc/langref.md b/doc/langref.md index 79bbd67fc5..af2d9feed9 100644 --- a/doc/langref.md +++ b/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 diff --git a/example/arrays/arrays.zig b/example/arrays/arrays.zig index 26d4331153..237db8c157 100644 --- a/example/arrays/arrays.zig +++ b/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; diff --git a/example/expressions/expressions.zig b/example/expressions/expressions.zig index 5cf01d77d9..cab306c466 100644 --- a/example/expressions/expressions.zig +++ b/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; diff --git a/example/structs/structs.zig b/example/structs/structs.zig index 562df40996..53a7cad1d1 100644 --- a/example/structs/structs.zig +++ b/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; diff --git a/src/parser.cpp b/src/parser.cpp index 12d0a2d719..bb75a0da6e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1561,54 +1561,48 @@ 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); - } - - *token_index += 1; - ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol); - - 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); - } - return node; - } else { - ast_invalid_token_error(pc, eq_or_colon); - } + 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, let_tok); + ast_invalid_token_error(pc, var_or_const_tok); } else { return nullptr; } + + *token_index += 1; + AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_or_const_tok); + + node->data.variable_declaration.is_const = is_const; + + Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol); + ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol); + + 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); + } + return node; + } else { + ast_invalid_token_error(pc, eq_or_colon); + } } /* diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index acee0e04d8..b75ac0721d 100644 --- a/src/tokenizer.cpp +++ b/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"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index 240a9b7eba..fa79450e24 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -15,8 +15,7 @@ enum TokenId { TokenIdSymbol, TokenIdKeywordFn, TokenIdKeywordReturn, - TokenIdKeywordLet, - TokenIdKeywordMut, + TokenIdKeywordVar, TokenIdKeywordConst, TokenIdKeywordExtern, TokenIdKeywordUnreachable, diff --git a/std/std.zig b/std/std.zig index b4244b6346..375eddc920 100644 --- a/std/std.zig +++ b/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); } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index d9afc4ac4b..91d00d3373 100644 --- a/test/run_tests.cpp +++ b/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]; }