const and var instead of let and let mut

closes #34
This commit is contained in:
Andrew Kelley 2015-12-14 18:51:07 -07:00
parent 8b727557d3
commit 3049410260
9 changed files with 85 additions and 95 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}
/*

View file

@ -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";

View file

@ -15,8 +15,7 @@ enum TokenId {
TokenIdSymbol,
TokenIdKeywordFn,
TokenIdKeywordReturn,
TokenIdKeywordLet,
TokenIdKeywordMut,
TokenIdKeywordVar,
TokenIdKeywordConst,
TokenIdKeywordExtern,
TokenIdKeywordUnreachable,

View file

@ -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);
}

View file

@ -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];
}