use comptime instead of inline for var and params

See #221
This commit is contained in:
Andrew Kelley 2017-01-22 19:51:37 -05:00
parent 6a5e61acd1
commit 47cf8520ad
22 changed files with 82 additions and 79 deletions

View File

@ -15,7 +15,7 @@ ErrorValueDecl = "error" Symbol ";"
GlobalVarDecl = VariableDeclaration ";"
VariableDeclaration = option("inline") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
StructMember = (StructField | FnDef | GlobalVarDecl)
@ -33,7 +33,7 @@ FnDef = option("inline" | "extern") FnProto Block
ParamDeclList = "(" list(ParamDecl, ",") ")"
ParamDecl = option("noalias" | "inline") option(Symbol ":") TypeExpr | "..."
ParamDecl = option("noalias" | "comptime") option(Symbol ":") TypeExpr | "..."
Block = "{" list(option(Statement), ";") "}"

View File

@ -8,7 +8,7 @@ if exists("b:current_syntax")
endif
let b:current_syntax = "zig"
syn keyword zigStorage const var extern export pub noalias inline nakedcc coldcc
syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc
syn keyword zigStructure struct enum union
syn keyword zigStatement goto break return continue asm defer
syn keyword zigConditional if else switch

View File

@ -979,7 +979,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
if (param_is_inline) {
if (fn_type_id.is_extern) {
add_node_error(g, param_node,
buf_sprintf("inline parameter not allowed in extern function"));
buf_sprintf("comptime parameter not allowed in extern function"));
return g->builtin_types.entry_invalid;
}
return get_generic_fn_type(g, &fn_type_id);

View File

@ -250,7 +250,7 @@ static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool
}
/*
ParamDecl = option("noalias" | "inline") option("Symbol" ":") TypeExpr | "..."
ParamDecl = option("noalias" | "comptime") option(Symbol ":") TypeExpr | "..."
*/
static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) {
Token *token = &pc->tokens->at(*token_index);
@ -266,7 +266,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) {
node->data.param_decl.is_noalias = true;
*token_index += 1;
token = &pc->tokens->at(*token_index);
} else if (token->id == TokenIdKeywordInline) {
} else if (token->id == TokenIdKeywordCompTime) {
node->data.param_decl.is_inline = true;
*token_index += 1;
token = &pc->tokens->at(*token_index);
@ -1492,7 +1492,7 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
}
/*
VariableDeclaration = option("inline") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
*/
static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,
VisibMod visib_mod)
@ -1501,9 +1501,9 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
Token *var_token;
bool is_const;
bool is_inline;
if (first_token->id == TokenIdKeywordInline) {
is_inline = true;
bool is_comptime;
if (first_token->id == TokenIdKeywordCompTime) {
is_comptime = true;
var_token = &pc->tokens->at(*token_index + 1);
if (var_token->id == TokenIdKeywordVar) {
@ -1518,12 +1518,12 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
*token_index += 2;
} else if (first_token->id == TokenIdKeywordVar) {
is_inline = false;
is_comptime = false;
is_const = false;
var_token = first_token;
*token_index += 1;
} else if (first_token->id == TokenIdKeywordConst) {
is_inline = false;
is_comptime = false;
is_const = true;
var_token = first_token;
*token_index += 1;
@ -1535,7 +1535,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token);
node->data.variable_declaration.is_inline = is_inline;
node->data.variable_declaration.is_inline = is_comptime;
node->data.variable_declaration.is_const = is_const;
node->data.variable_declaration.visib_mod = visib_mod;

View File

@ -110,6 +110,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"asm", TokenIdKeywordAsm},
{"break", TokenIdKeywordBreak},
{"coldcc", TokenIdKeywordColdCC},
{"comptime", TokenIdKeywordCompTime},
{"const", TokenIdKeywordConst},
{"continue", TokenIdKeywordContinue},
{"defer", TokenIdKeywordDefer},
@ -1475,6 +1476,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordError: return "error";
case TokenIdKeywordType: return "type";
case TokenIdKeywordInline: return "inline";
case TokenIdKeywordCompTime: return "comptime";
case TokenIdKeywordDefer: return "defer";
case TokenIdKeywordColdCC: return "coldcc";
case TokenIdKeywordNakedCC: return "nakedcc";

View File

@ -43,6 +43,7 @@ enum TokenId {
TokenIdKeywordError,
TokenIdKeywordType,
TokenIdKeywordInline,
TokenIdKeywordCompTime,
TokenIdKeywordDefer,
TokenIdKeywordThis,
TokenIdKeywordColdCC,

View File

@ -16,7 +16,7 @@ var argv: &&u8 = undefined;
export nakedcc fn _start() -> unreachable {
@setFnVisible(this, want_start_symbol);
inline switch (@compileVar("arch")) {
switch (@compileVar("arch")) {
Arch.x86_64 => {
argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> usize));
argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8));

View File

@ -241,7 +241,7 @@ fn parseFormValueRefLen(in_stream: &io.InStream, size: usize) -> %FormValue {
return FormValue.Ref { buf };
}
fn parseFormValueRef(in_stream: &io.InStream, inline T: type) -> %FormValue {
fn parseFormValueRef(in_stream: &io.InStream, comptime T: type) -> %FormValue {
const block_len = %return in_stream.readIntLe(T);
return parseFormValueRefLen(in_stream, block_len);
}

View File

@ -1,16 +1,16 @@
pub inline fn swapIfLe(inline T: type, x: T) -> T {
pub inline fn swapIfLe(comptime T: type, x: T) -> T {
swapIf(false, T, x)
}
pub inline fn swapIfBe(inline T: type, x: T) -> T {
pub inline fn swapIfBe(comptime T: type, x: T) -> T {
swapIf(true, T, x)
}
pub inline fn swapIf(is_be: bool, inline T: type, x: T) -> T {
pub inline fn swapIf(is_be: bool, comptime T: type, x: T) -> T {
if (@compileVar("is_big_endian") == is_be) swap(T, x) else x
}
pub fn swap(inline T: type, x: T) -> T {
pub fn swap(comptime T: type, x: T) -> T {
const x_slice = ([]u8)((&const x)[0...1]);
var result: T = undefined;
const result_slice = ([]u8)((&result)[0...1]);

View File

@ -7,8 +7,8 @@ const Allocator = mem.Allocator;
const want_modification_safety = !@compileVar("is_release");
const debug_u32 = if (want_modification_safety) u32 else void;
pub fn HashMap(inline K: type, inline V: type, inline hash: fn(key: K)->u32,
inline eql: fn(a: K, b: K)->bool) -> type
pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K)->u32,
comptime eql: fn(a: K, b: K)->bool) -> type
{
struct {
entries: []Entry,

View File

@ -105,7 +105,7 @@ pub const OutStream = struct {
return byte_count;
}
pub fn printInt(self: &OutStream, inline T: type, x: T) -> %usize {
pub fn printInt(self: &OutStream, comptime T: type, x: T) -> %usize {
// TODO replace max_u64_base10_digits with math.log10(math.pow(2, @sizeOf(T)))
if (self.index + max_u64_base10_digits >= self.buffer.len) {
%return self.flush();
@ -255,22 +255,22 @@ pub const InStream = struct {
return result[0];
}
pub fn readIntLe(is: &InStream, inline T: type) -> %T {
pub fn readIntLe(is: &InStream, comptime T: type) -> %T {
is.readInt(false, T)
}
pub fn readIntBe(is: &InStream, inline T: type) -> %T {
pub fn readIntBe(is: &InStream, comptime T: type) -> %T {
is.readInt(true, T)
}
pub fn readInt(is: &InStream, is_be: bool, inline T: type) -> %T {
pub fn readInt(is: &InStream, is_be: bool, comptime T: type) -> %T {
var result: T = undefined;
const result_slice = ([]u8)((&result)[0...1]);
%return is.readNoEof(result_slice);
return endian.swapIf(!is_be, T, result);
}
pub fn readVarInt(is: &InStream, is_be: bool, inline T: type, size: usize) -> %T {
pub fn readVarInt(is: &InStream, is_be: bool, comptime T: type, size: usize) -> %T {
assert(size <= @sizeOf(T));
assert(size <= 8);
var input_buf: [8]u8 = undefined;
@ -355,7 +355,7 @@ pub const InStream = struct {
}
};
pub fn parseUnsigned(inline T: type, buf: []u8, radix: u8) -> %T {
pub fn parseUnsigned(comptime T: type, buf: []u8, radix: u8) -> %T {
var x: T = 0;
for (buf) |c| {
@ -381,11 +381,11 @@ fn charToDigit(c: u8, radix: u8) -> %u8 {
return if (value >= radix) error.InvalidChar else value;
}
pub fn bufPrintInt(inline T: type, out_buf: []u8, x: T) -> usize {
pub fn bufPrintInt(comptime T: type, out_buf: []u8, x: T) -> usize {
if (T.is_signed) bufPrintSigned(T, out_buf, x) else bufPrintUnsigned(T, out_buf, x)
}
fn bufPrintSigned(inline T: type, out_buf: []u8, x: T) -> usize {
fn bufPrintSigned(comptime T: type, out_buf: []u8, x: T) -> usize {
const uint = @intType(false, T.bit_count);
if (x < 0) {
out_buf[0] = '-';
@ -395,7 +395,7 @@ fn bufPrintSigned(inline T: type, out_buf: []u8, x: T) -> usize {
}
}
fn bufPrintUnsigned(inline T: type, out_buf: []u8, x: T) -> usize {
fn bufPrintUnsigned(comptime T: type, out_buf: []u8, x: T) -> usize {
var buf: [max_u64_base10_digits]u8 = undefined;
var a = x;
var index: usize = buf.len;

View File

@ -3,7 +3,7 @@ const assert = debug.assert;
const mem = @import("mem.zig");
const Allocator = mem.Allocator;
pub fn List(inline T: type) -> type{
pub fn List(comptime T: type) -> type{
struct {
const Self = this;

View File

@ -13,19 +13,19 @@ pub fn max(x: var, y: var) -> @typeOf(x + y) {
}
error Overflow;
pub fn mulOverflow(inline T: type, a: T, b: T) -> %T {
pub fn mulOverflow(comptime T: type, a: T, b: T) -> %T {
var answer: T = undefined;
if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer
}
pub fn addOverflow(inline T: type, a: T, b: T) -> %T {
pub fn addOverflow(comptime T: type, a: T, b: T) -> %T {
var answer: T = undefined;
if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer
}
pub fn subOverflow(inline T: type, a: T, b: T) -> %T {
pub fn subOverflow(comptime T: type, a: T, b: T) -> %T {
var answer: T = undefined;
if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer
}
pub fn shlOverflow(inline T: type, a: T, b: T) -> %T {
pub fn shlOverflow(comptime T: type, a: T, b: T) -> %T {
var answer: T = undefined;
if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer
}

View File

@ -15,7 +15,7 @@ pub const Allocator = struct {
context: ?&Context,
/// Aborts the program if an allocation fails.
fn checkedAlloc(self: &Allocator, inline T: type, n: usize) -> []T {
fn checkedAlloc(self: &Allocator, comptime T: type, n: usize) -> []T {
alloc(self, T, n) %% |err| {
// TODO var args printf
%%io.stderr.write("allocation failure: ");
@ -25,37 +25,37 @@ pub const Allocator = struct {
}
}
fn alloc(self: &Allocator, inline T: type, n: usize) -> %[]T {
fn alloc(self: &Allocator, comptime T: type, n: usize) -> %[]T {
const byte_count = %return math.mulOverflow(usize, @sizeOf(T), n);
([]T)(%return self.allocFn(self, byte_count))
}
fn realloc(self: &Allocator, inline T: type, old_mem: []T, n: usize) -> %[]T {
fn realloc(self: &Allocator, comptime T: type, old_mem: []T, n: usize) -> %[]T {
const byte_count = %return math.mulOverflow(usize, @sizeOf(T), n);
([]T)(%return self.reallocFn(self, ([]u8)(old_mem), byte_count))
}
// TODO mem: []var and get rid of 2nd param
fn free(self: &Allocator, inline T: type, mem: []T) {
fn free(self: &Allocator, comptime T: type, mem: []T) {
self.freeFn(self, ([]u8)(mem));
}
};
/// Copy all of source into dest at position 0.
/// dest.len must be >= source.len.
pub fn copy(inline T: type, dest: []T, source: []const T) {
pub fn copy(comptime T: type, dest: []T, source: []const T) {
@setDebugSafety(this, false);
assert(dest.len >= source.len);
for (source) |s, i| dest[i] = s;
}
pub fn set(inline T: type, dest: []T, value: T) {
pub fn set(comptime T: type, dest: []T, value: T) {
for (dest) |*d| *d = value;
}
/// Return < 0, == 0, or > 0 if memory a is less than, equal to, or greater than,
/// memory b, respectively.
pub fn cmp(inline T: type, a: []const T, b: []const T) -> Cmp {
pub fn cmp(comptime T: type, a: []const T, b: []const T) -> Cmp {
const n = math.min(a.len, b.len);
var i: usize = 0;
while (i < n; i += 1) {
@ -66,7 +66,7 @@ pub fn cmp(inline T: type, a: []const T, b: []const T) -> Cmp {
return if (a.len > b.len) Cmp.Greater else if (a.len < b.len) Cmp.Less else Cmp.Equal;
}
pub fn sliceAsInt(buf: []u8, is_be: bool, inline T: type) -> T {
pub fn sliceAsInt(buf: []u8, is_be: bool, comptime T: type) -> T {
var result: T = undefined;
const result_slice = ([]u8)((&result)[0...1]);
set(u8, result_slice, 0);

View File

@ -29,7 +29,7 @@ pub const Rand = struct {
}
/// Get an integer with random bits.
pub fn scalar(r: &Rand, inline T: type) -> T {
pub fn scalar(r: &Rand, comptime T: type) -> T {
if (T == usize) {
return r.rng.get();
} else {
@ -59,7 +59,7 @@ pub const Rand = struct {
/// Get a random unsigned integer with even distribution between `start`
/// inclusive and `end` exclusive.
// TODO support signed integers and then rename to "range"
pub fn rangeUnsigned(r: &Rand, inline T: type, start: T, end: T) -> T {
pub fn rangeUnsigned(r: &Rand, comptime T: type, start: T, end: T) -> T {
const range = end - start;
const leftover = @maxValue(T) % range;
const upper_bound = @maxValue(T) - leftover;
@ -75,7 +75,7 @@ pub const Rand = struct {
}
/// Get a floating point value in the range 0.0..1.0.
pub fn float(r: &Rand, inline T: type) -> T {
pub fn float(r: &Rand, comptime T: type) -> T {
// TODO Implement this way instead:
// const int = @int_type(false, @sizeOf(T) * 8);
// const mask = ((1 << @float_mantissa_bit_count(T)) - 1);
@ -94,12 +94,12 @@ pub const Rand = struct {
};
fn MersenneTwister(
inline int: type, inline n: usize, inline m: usize, inline r: int,
inline a: int,
inline u: int, inline d: int,
inline s: int, inline b: int,
inline t: int, inline c: int,
inline l: int, inline f: int) -> type
comptime int: type, comptime n: usize, comptime m: usize, comptime r: int,
comptime a: int,
comptime u: int, comptime d: int,
comptime s: int, comptime b: int,
comptime t: int, comptime c: int,
comptime l: int, comptime f: int) -> type
{
struct {
const Self = this;

View File

@ -5,13 +5,13 @@ const math = @import("math.zig");
pub const Cmp = math.Cmp;
pub fn sort(inline T: type, array: []T, inline cmp: fn(a: &const T, b: &const T)->Cmp) {
pub fn sort(comptime T: type, array: []T, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {
if (array.len > 0) {
quicksort(T, array, 0, array.len - 1, cmp);
}
}
fn quicksort(inline T: type, array: []T, left: usize, right: usize, inline cmp: fn(a: &const T, b: &const T)->Cmp) {
fn quicksort(comptime T: type, array: []T, left: usize, right: usize, comptime cmp: fn(a: &const T, b: &const T)->Cmp) {
var i = left;
var j = right;
const p = (i + j) / 2;

View File

@ -4,7 +4,7 @@ pub fn eql(a: []const u8, b: []const u8) -> bool {
sliceEql(u8, a, b)
}
pub fn sliceEql(inline T: type, a: []const T, b: []const T) -> bool {
pub fn sliceEql(comptime T: type, a: []const T, b: []const T) -> bool {
if (a.len != b.len) return false;
for (a) |item, index| {
if (b[index] != item) return false;

View File

@ -25,17 +25,17 @@ fn testStaticAddOne() {
fn inlinedLoop() {
@setFnTest(this);
inline var i = 0;
inline var sum = 0;
comptime var i = 0;
comptime var sum = 0;
inline while (i <= 5; i += 1)
sum += i;
assert(sum == 15);
}
fn gimme1or2(inline a: bool) -> i32 {
fn gimme1or2(comptime a: bool) -> i32 {
const x: i32 = 1;
const y: i32 = 2;
inline var z: i32 = if (a) x else y;
comptime var z: i32 = if (a) x else y;
return z;
}
fn inlineVariableGetsResultOfConstIf() {

View File

@ -8,11 +8,11 @@ fn simpleGenericFn() {
assert(add(2, 3) == 5);
}
fn max(inline T: type, a: T, b: T) -> T {
fn max(comptime T: type, a: T, b: T) -> T {
return if (a > b) a else b;
}
fn add(inline a: i32, b: i32) -> i32 {
fn add(comptime a: i32, b: i32) -> i32 {
return @staticEval(a) + b;
}
@ -67,11 +67,11 @@ fn max_f64(a: f64, b: f64) -> f64 {
}
pub fn List(inline T: type) -> type {
pub fn List(comptime T: type) -> type {
SmallList(T, 8)
}
pub fn SmallList(inline T: type, inline STATIC_SIZE: usize) -> type {
pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type {
struct {
items: []T,
length: usize,
@ -100,7 +100,7 @@ fn genericStruct() {
assert(a1.value == a1.getVal());
assert(b1.getVal());
}
fn GenNode(inline T: type) -> type {
fn GenNode(comptime T: type) -> type {
struct {
value: T,
next: ?&GenNode(T),
@ -113,7 +113,7 @@ fn constDeclsInStruct() {
assert(GenericDataThing(3).count_plus_one == 4);
}
fn GenericDataThing(inline count: isize) -> type {
fn GenericDataThing(comptime count: isize) -> type {
struct {
const count_plus_one = count + 1;
}
@ -125,7 +125,7 @@ fn useGenericParamInGenericParam() {
assert(aGenericFn(i32, 3, 4) == 7);
}
fn aGenericFn(inline T: type, inline a: T, b: T) -> T {
fn aGenericFn(comptime T: type, comptime a: T, b: T) -> T {
return a + b;
}
@ -137,6 +137,6 @@ fn genericFnWithImplicitCast() {
assert(getFirstByte(u16, []u16 {0, 13}) == 0);
}
fn getByte(ptr: ?&u8) -> u8 {*??ptr}
fn getFirstByte(inline T: type, mem: []T) -> u8 {
fn getFirstByte(comptime T: type, mem: []T) -> u8 {
getByte((&u8)(&mem[0]))
}

View File

@ -292,10 +292,10 @@ fn genericMallocFree() {
memFree(u8, a);
}
const some_mem : [100]u8 = undefined;
fn memAlloc(inline T: type, n: usize) -> %[]T {
fn memAlloc(comptime T: type, n: usize) -> %[]T {
return (&T)(&some_mem[0])[0...n];
}
fn memFree(inline T: type, mem: []T) { }
fn memFree(comptime T: type, mem: []T) { }
fn castUndefined() {

View File

@ -2,7 +2,7 @@ const assert = @import("std").debug.assert;
const module = this;
fn Point(inline T: type) -> type {
fn Point(comptime T: type) -> type {
struct {
const Self = this;
x: T,

View File

@ -1195,7 +1195,7 @@ const invalid = foo > foo;
)SOURCE", 1, ".tmp_source.zig:3:21: error: operator not allowed for type 'fn()'");
add_compile_fail_case("generic function instance with non-constant expression", R"SOURCE(
fn foo(inline x: i32, y: i32) -> i32 { return x + y; }
fn foo(comptime x: i32, y: i32) -> i32 { return x + y; }
fn test1(a: i32, b: i32) -> i32 {
return foo(a, b);
}
@ -1407,18 +1407,18 @@ fn f() {
}
)SOURCE", 1, ".tmp_source.zig:3:13: error: unable to evaluate constant expression");
add_compile_fail_case("export function with inline parameter", R"SOURCE(
export fn foo(inline x: i32, y: i32) -> i32{
add_compile_fail_case("export function with comptime parameter", R"SOURCE(
export fn foo(comptime x: i32, y: i32) -> i32{
x + y
}
)SOURCE", 1, ".tmp_source.zig:2:15: error: inline parameter not allowed in extern function");
)SOURCE", 1, ".tmp_source.zig:2:15: error: comptime parameter not allowed in extern function");
add_compile_fail_case("extern function with inline parameter", R"SOURCE(
extern fn foo(inline x: i32, y: i32) -> i32;
add_compile_fail_case("extern function with comptime parameter", R"SOURCE(
extern fn foo(comptime x: i32, y: i32) -> i32;
fn f() -> i32 {
foo(1, 2)
}
)SOURCE", 1, ".tmp_source.zig:2:15: error: inline parameter not allowed in extern function");
)SOURCE", 1, ".tmp_source.zig:2:15: error: comptime parameter not allowed in extern function");
add_compile_fail_case("convert fixed size array to slice with invalid size", R"SOURCE(
fn f() {
@ -1429,12 +1429,12 @@ fn f() {
add_compile_fail_case("non-pure function returns type", R"SOURCE(
var a: u32 = 0;
pub fn List(inline T: type) -> type {
pub fn List(comptime T: type) -> type {
a += 1;
SmallList(T, 8)
}
pub fn SmallList(inline T: type, inline STATIC_SIZE: usize) -> type {
pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type {
struct {
items: []T,
length: usize,