From 183976b242dac0731caa7d925e88ad151a4dc8ee Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 26 Sep 2016 23:47:30 -0400 Subject: [PATCH] add this keyword refers to thing in immediate scope See #169 --- doc/langref.md | 2 +- doc/vim/syntax/zig.vim | 2 +- src/all_types.hpp | 12 ++++++-- src/analyze.cpp | 66 +++++++++++++++++++++++++++++++++++++----- src/ast_render.cpp | 4 +++ src/codegen.cpp | 10 +++++++ src/eval.cpp | 2 ++ src/parser.cpp | 12 +++++++- src/tokenizer.cpp | 2 ++ src/tokenizer.hpp | 1 + std/hash_map.zig | 2 +- std/list.zig | 2 +- std/rand.zig | 2 +- test/cases/this.zig | 47 ++++++++++++++++++++++++++++++ test/run_tests.cpp | 16 ++++++++++ test/self_hosted.zig | 1 + 16 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 test/cases/this.zig diff --git a/doc/langref.md b/doc/langref.md index b7023198e0a7c60f7bf661290ecdefdb49198e0a..b982ec0197213cd4abfb4bc999e5ff3a233146d6 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -151,7 +151,7 @@ GotoExpression = "goto" Symbol GroupedExpression = "(" Expression ")" -KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" +KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" ``` ## Operator Precedence diff --git a/doc/vim/syntax/zig.vim b/doc/vim/syntax/zig.vim index 32852f6a60f282ec1ae37bbc26bd0ad36ac9a3a7..02eacef28ce8bc1f08519108177b0ddeda80af3c 100644 --- a/doc/vim/syntax/zig.vim +++ b/doc/vim/syntax/zig.vim @@ -14,7 +14,7 @@ syn keyword zigStatement goto break return continue asm defer syn keyword zigConditional if else switch syn keyword zigRepeat while for -syn keyword zigConstant null undefined zeroes +syn keyword zigConstant null undefined zeroes this syn keyword zigKeyword fn use syn keyword zigType bool f32 f64 void unreachable type error syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize diff --git a/src/all_types.hpp b/src/all_types.hpp index 50a8c71a81d26214410af6775a4d76a5d977df87..d1826299e4ca12703642c540c3d59a84f2c7720c 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -85,6 +85,7 @@ struct ConstExprValue { ConstArrayValue x_array; ConstPtrValue x_ptr; ImportTableEntry *x_import; + BlockContext *x_block; } data; }; @@ -174,6 +175,7 @@ enum NodeType { NodeTypeNullLiteral, NodeTypeUndefinedLiteral, NodeTypeZeroesLiteral, + NodeTypeThisLiteral, NodeTypeIfBoolExpr, NodeTypeIfVarExpr, NodeTypeWhileExpr, @@ -719,6 +721,11 @@ struct AstNodeZeroesLiteral { Expr resolved_expr; }; +struct AstNodeThisLiteral { + // populated by semantic analyzer + Expr resolved_expr; +}; + struct AstNodeSymbolExpr { Buf *symbol; @@ -822,6 +829,7 @@ struct AstNode { AstNodeNullLiteral null_literal; AstNodeUndefinedLiteral undefined_literal; AstNodeZeroesLiteral zeroes_literal; + AstNodeThisLiteral this_literal; AstNodeSymbolExpr symbol_expr; AstNodeBoolLiteral bool_literal; AstNodeBreakExpr break_expr; @@ -1005,6 +1013,7 @@ enum TypeTableEntryId { TypeTableEntryIdFn, TypeTableEntryIdTypeDecl, TypeTableEntryIdNamespace, + TypeTableEntryIdBlock, TypeTableEntryIdGenericFn, }; @@ -1102,7 +1111,6 @@ struct FnTableEntry { AstNode *want_pure_return_type; bool safety_off; FnInline fn_inline; - BlockContext *parent_block_context; FnAnalState anal_state; ZigList cast_alloca_list; @@ -1209,6 +1217,7 @@ struct CodeGen { TypeTableEntry *entry_type; TypeTableEntry *entry_invalid; TypeTableEntry *entry_namespace; + TypeTableEntry *entry_block; TypeTableEntry *entry_num_lit_int; TypeTableEntry *entry_num_lit_float; TypeTableEntry *entry_undef; @@ -1340,7 +1349,6 @@ struct LabelTableEntry { }; struct BlockContext { - // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration AstNode *node; // any variables that are introduced by this scope diff --git a/src/analyze.cpp b/src/analyze.cpp index f529c572a40637b4f5e07658fbde9344ca182c64..93786ed15aec7b75abc55af8ac08c9436e4a5302 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -91,6 +91,7 @@ static AstNode *first_executing_node(AstNode *node) { case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: case NodeTypeZeroesLiteral: + case NodeTypeThisLiteral: case NodeTypeIfBoolExpr: case NodeTypeIfVarExpr: case NodeTypeLabel: @@ -246,6 +247,7 @@ static bool type_is_complete(TypeTableEntry *type_entry) { case TypeTableEntryIdFn: case TypeTableEntryIdTypeDecl: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: return true; } @@ -962,6 +964,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor case TypeTableEntryIdNullLit: case TypeTableEntryIdUnreachable: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: fn_proto->skip = true; add_node_error(g, child->data.param_decl.type, @@ -1012,6 +1015,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: case TypeTableEntryIdVar: fn_proto->skip = true; @@ -1896,6 +1900,7 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: case NodeTypeZeroesLiteral: + case NodeTypeThisLiteral: case NodeTypeSymbol: case NodeTypePrefixOpExpr: case NodeTypeIfBoolExpr: @@ -1960,6 +1965,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) { case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: return false; @@ -2745,6 +2751,7 @@ static bool is_container(TypeTableEntry *type_entry) { case TypeTableEntryIdFn: case TypeTableEntryIdTypeDecl: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: return false; } @@ -2791,6 +2798,7 @@ static void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { case TypeTableEntryIdFn: case TypeTableEntryIdTypeDecl: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: case TypeTableEntryIdInvalid: case TypeTableEntryIdVar: @@ -2965,7 +2973,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i } if (decl_node) { TopLevelDecl *tld = get_as_top_level_decl(decl_node); - if (tld->visib_mod == VisibModPrivate) { + if (tld->visib_mod == VisibModPrivate && decl_node->owner != import) { ErrorMsg *msg = add_node_error(g, node, buf_sprintf("'%s' is private", buf_ptr(field_name))); add_error_note(g, msg, decl_node, buf_sprintf("declared here")); @@ -3093,6 +3101,16 @@ static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, return g->builtin_types.entry_type; } +static TypeTableEntry *resolve_expr_const_val_as_block(CodeGen *g, AstNode *node, BlockContext *block_context, + bool depends_on_compile_var) +{ + Expr *expr = get_resolved_expr(node); + expr->const_val.ok = true; + expr->const_val.data.x_block = block_context; + expr->const_val.depends_on_compile_var = depends_on_compile_var; + return g->builtin_types.entry_block; +} + static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode *node, AstNode *other, bool depends_on_compile_var) { @@ -3221,6 +3239,13 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As return g->builtin_types.entry_num_lit_int; } +static TypeTableEntry *resolve_expr_const_val_as_import(CodeGen *g, AstNode *node, ImportTableEntry *import) { + Expr *expr = get_resolved_expr(node); + expr->const_val.ok = true; + expr->const_val.data.x_import = import; + return g->builtin_types.entry_namespace; +} + static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node, Buf *err_name) { @@ -3497,6 +3522,7 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im case TypeTableEntryIdFn: case TypeTableEntryIdTypeDecl: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: if (!is_equality_cmp) { add_node_error(g, node, @@ -4120,6 +4146,25 @@ static TypeTableEntry *analyze_zeroes_literal_expr(CodeGen *g, ImportTableEntry return expected_type ? expected_type : g->builtin_types.entry_undef; } +static TypeTableEntry *analyze_this_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, + TypeTableEntry *expected_type, AstNode *node) +{ + if (!context->parent) { + return resolve_expr_const_val_as_import(g, node, import); + } + if (context->fn_entry && (!context->parent->fn_entry || + (context->parent->parent && !context->parent->parent->fn_entry))) + { + return resolve_expr_const_val_as_fn(g, node, context->fn_entry, false); + } + if (context->node->type == NodeTypeContainerDecl) { + return resolve_expr_const_val_as_type(g, node, context->node->data.struct_decl.type_entry, false); + } + if (context->node->type == NodeTypeBlock) { + return resolve_expr_const_val_as_block(g, node, context, false); + } + zig_unreachable(); +} static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node) @@ -4793,13 +4838,6 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B return g->builtin_types.entry_invalid; } -static TypeTableEntry *resolve_expr_const_val_as_import(CodeGen *g, AstNode *node, ImportTableEntry *import) { - Expr *expr = get_resolved_expr(node); - expr->const_val.ok = true; - expr->const_val.data.x_import = import; - return g->builtin_types.entry_namespace; -} - static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) { @@ -5394,6 +5432,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: case TypeTableEntryIdVar: add_node_error(g, expr_node, @@ -6796,6 +6835,9 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn case NodeTypeZeroesLiteral: return_type = analyze_zeroes_literal_expr(g, import, context, expected_type, node); break; + case NodeTypeThisLiteral: + return_type = analyze_this_literal_expr(g, import, context, expected_type, node); + break; case NodeTypeSymbol: return_type = analyze_symbol_expr(g, import, context, expected_type, node, pointer_only); break; @@ -7085,6 +7127,7 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: case NodeTypeZeroesLiteral: + case NodeTypeThisLiteral: case NodeTypeSymbol: case NodeTypePrefixOpExpr: case NodeTypeIfBoolExpr: @@ -7347,6 +7390,8 @@ Expr *get_resolved_expr(AstNode *node) { return &node->data.undefined_literal.resolved_expr; case NodeTypeZeroesLiteral: return &node->data.zeroes_literal.resolved_expr; + case NodeTypeThisLiteral: + return &node->data.this_literal.resolved_expr; case NodeTypeGoto: return &node->data.goto_expr.resolved_expr; case NodeTypeBreak: @@ -7432,6 +7477,7 @@ static TopLevelDecl *get_as_top_level_decl(AstNode *node) { case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: case NodeTypeZeroesLiteral: + case NodeTypeThisLiteral: case NodeTypeLabel: case NodeTypeGoto: case NodeTypeBreak: @@ -7499,6 +7545,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { case TypeTableEntryIdUndefLit: case TypeTableEntryIdNullLit: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: case TypeTableEntryIdVar: zig_unreachable(); @@ -7640,6 +7687,8 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val) return hash_ptr(const_val->data.x_type); case TypeTableEntryIdNamespace: return hash_ptr(const_val->data.x_import); + case TypeTableEntryIdBlock: + return hash_ptr(const_val->data.x_block); case TypeTableEntryIdGenericFn: case TypeTableEntryIdInvalid: case TypeTableEntryIdUnreachable: @@ -7715,6 +7764,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry) case TypeTableEntryIdMetaType: case TypeTableEntryIdVoid: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: case TypeTableEntryIdVar: zig_unreachable(); diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 5857a88b08e6777fd01a156f613c6901ad47921d..81429586b5fe50d70c51b6687eaac376d7345c17 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -173,6 +173,8 @@ static const char *node_type_str(NodeType node_type) { return "UndefinedLiteral"; case NodeTypeZeroesLiteral: return "ZeroesLiteral"; + case NodeTypeThisLiteral: + return "ThisLiteral"; case NodeTypeIfBoolExpr: return "IfBoolExpr"; case NodeTypeIfVarExpr: @@ -597,6 +599,8 @@ static void render_node(AstRender *ar, AstNode *node) { zig_panic("TODO"); case NodeTypeZeroesLiteral: zig_panic("TODO"); + case NodeTypeThisLiteral: + zig_panic("TODO"); case NodeTypeIfBoolExpr: zig_panic("TODO"); case NodeTypeIfVarExpr: diff --git a/src/codegen.cpp b/src/codegen.cpp index 44e29702d2f45c49f914be73f31cb25ee31f0d34..956b5be0a6a9d33c13fdb419ba64f3659fe05a1b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3605,6 +3605,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: case NodeTypeZeroesLiteral: + case NodeTypeThisLiteral: case NodeTypeErrorType: case NodeTypeTypeLiteral: case NodeTypeArrayType: @@ -3826,6 +3827,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE case TypeTableEntryIdNullLit: case TypeTableEntryIdVoid: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdGenericFn: case TypeTableEntryIdVar: zig_unreachable(); @@ -4349,6 +4351,13 @@ static void define_builtin_types(CodeGen *g) { entry->deep_const = true; g->builtin_types.entry_namespace = entry; } + { + TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBlock); + buf_init_from_str(&entry->name, "(block)"); + entry->zero_bits = true; + entry->deep_const = true; + g->builtin_types.entry_block = entry; + } { TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat); buf_init_from_str(&entry->name, "(float literal)"); @@ -5145,6 +5154,7 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { case TypeTableEntryIdMetaType: case TypeTableEntryIdGenericFn: case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: case TypeTableEntryIdNumLitFloat: case TypeTableEntryIdNumLitInt: case TypeTableEntryIdUndefLit: diff --git a/src/eval.cpp b/src/eval.cpp index 8c619bb982562f06cb86e4dec7fce864b2a91e39..3677a14f6ab31cd85560ec432faec4c47b0e9136 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -83,6 +83,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty zig_panic("TODO"); case TypeTableEntryIdNamespace: zig_panic("TODO"); + case TypeTableEntryIdBlock: zig_panic("TODO"); case TypeTableEntryIdGenericFn: case TypeTableEntryIdInvalid: @@ -1373,6 +1374,7 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) { case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: case NodeTypeZeroesLiteral: + case NodeTypeThisLiteral: case NodeTypeIfVarExpr: case NodeTypeSwitchExpr: case NodeTypeSwitchProng: diff --git a/src/parser.cpp b/src/parser.cpp index e0423ae1e192191d529a6133cdf7b16593d6cfe0..52d3a855d0fd397d66c997d94af39fb5c741f6e3 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -620,7 +620,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m /* PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol") -KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" +KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" */ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -672,6 +672,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo AstNode *node = ast_create_node(pc, NodeTypeZeroesLiteral, token); *token_index += 1; return node; + } else if (token->id == TokenIdKeywordThis) { + AstNode *node = ast_create_node(pc, NodeTypeThisLiteral, token); + *token_index += 1; + return node; } else if (token->id == TokenIdKeywordType) { AstNode *node = ast_create_node(pc, NodeTypeTypeLiteral, token); *token_index += 1; @@ -2560,6 +2564,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeZeroesLiteral: // none break; + case NodeTypeThisLiteral: + // none + break; case NodeTypeIfBoolExpr: visit_field(&node->data.if_bool_expr.condition, visit, context); visit_field(&node->data.if_bool_expr.then_block, visit, context); @@ -2840,6 +2847,9 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index, case NodeTypeZeroesLiteral: // none break; + case NodeTypeThisLiteral: + // none + break; case NodeTypeIfBoolExpr: clone_subtree_field(&new_node->data.if_bool_expr.condition, old_node->data.if_bool_expr.condition, next_node_index); clone_subtree_field(&new_node->data.if_bool_expr.then_block, old_node->data.if_bool_expr.then_block, next_node_index); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 58aa2d261099129eced0268542f958d236eee7ea..62c4ea1f4c27225fc96e9bb24ab22334acd57ddb 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -129,6 +129,7 @@ static const struct ZigKeyword zig_keywords[] = { {"return", TokenIdKeywordReturn}, {"struct", TokenIdKeywordStruct}, {"switch", TokenIdKeywordSwitch}, + {"this", TokenIdKeywordThis}, {"true", TokenIdKeywordTrue}, {"type", TokenIdKeywordType}, {"undefined", TokenIdKeywordUndefined}, @@ -1470,6 +1471,7 @@ const char * token_name(TokenId id) { case TokenIdKeywordSwitch: return "switch"; case TokenIdKeywordUndefined: return "undefined"; case TokenIdKeywordZeroes: return "zeroes"; + case TokenIdKeywordThis: return "this"; case TokenIdKeywordError: return "error"; case TokenIdKeywordType: return "type"; case TokenIdKeywordInline: return "inline"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index f5d26c54042a25076b45999691403c4acd54946d..f67828b7cca9ffa83cb67b56dc5ded22588a1a2c 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -45,6 +45,7 @@ enum TokenId { TokenIdKeywordType, TokenIdKeywordInline, TokenIdKeywordDefer, + TokenIdKeywordThis, TokenIdLParen, TokenIdRParen, TokenIdComma, diff --git a/std/hash_map.zig b/std/hash_map.zig index 92c2742d0bff8a5019658cf4d733961ad9f9b987..c20d78c202ed40e9cc41c73266110f560aac57bb 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -24,7 +24,7 @@ pub struct SmallHashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b // this is used to detect bugs where a hashtable is edited while an iterator is running. modification_count: debug_u32, - const Self = SmallHashMap(K, V, hash, eql, static_size); + const Self = this; pub struct Entry { used: bool, diff --git a/std/list.zig b/std/list.zig index e4c8e9ac1e63303399e26ecc4ff0c09cd01b9efd..36c682cc1c44a6e2c23aa16c4a02d35103748cda 100644 --- a/std/list.zig +++ b/std/list.zig @@ -4,7 +4,7 @@ const mem = @import("mem.zig"); const Allocator = mem.Allocator; pub struct List(T: type) { - const Self = List(T); + const Self = this; items: []T, len: usize, diff --git a/std/rand.zig b/std/rand.zig index da8878f1b2131f377c0d67843f566314deeb1cbe..15cf9626b7e747213bbb995e63734296d73c906b 100644 --- a/std/rand.zig +++ b/std/rand.zig @@ -101,7 +101,7 @@ struct MersenneTwister( t: int, c: int, l: int, f: int) { - const Self = MersenneTwister(int, n, m, r, a, u, d, s, b, t, c, l, f); + const Self = this; array: [n]int, index: usize, diff --git a/test/cases/this.zig b/test/cases/this.zig new file mode 100644 index 0000000000000000000000000000000000000000..deac9c26e81a156ee77ff95ad20d20e0c0e9d1a2 --- /dev/null +++ b/test/cases/this.zig @@ -0,0 +1,47 @@ +const assert = @import("std").debug.assert; +const module = this; + +struct Point(inline T: type) { + const Self = this; + x: T, + y: T, + + fn addOne(self: &Self) { + self.x += 1; + self.y += 1; + } +} + +fn add(x: i32, y: i32) -> i32 { + x + y +} + +fn factorial(x: i32) -> i32 { + const selfFn = this; + if (x == 0) { + 1 + } else { + x * selfFn(x - 1) + } +} + +#attribute("test") +fn thisReferToModuleCallPrivateFn() { + assert(module.add(1, 2) == 3); +} + +#attribute("test") +fn thisReferToContainer() { + var pt = Point(i32) { + .x = 12, + .y = 34, + }; + pt.addOne(); + assert(pt.x == 13); + assert(pt.y == 35); +} + +#attribute("test") +fn thisReferToFn() { + assert(factorial(5) == 120); +} diff --git a/test/run_tests.cpp b/test/run_tests.cpp index aeab7566abd1ffa08bc6d735ec268f1b66f97a74..4b03efc7d6a59eb83fe9bfbdab6647e04b1b9dd3 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1597,6 +1597,22 @@ const TINY_QUANTUM_SIZE = 1 << TINY_QUANTUM_SHIFT; var block_aligned_stuff: usize = (4 + TINY_QUANTUM_SIZE) & ~(TINY_QUANTUM_SIZE - 1); )SOURCE", 1, ".tmp_source.zig:4:60: error: unable to perform binary not operation on type '(integer literal)'"); + { + TestCase *tc = add_compile_fail_case("multiple files with private function error", R"SOURCE( +const foo = @import("foo.zig"); + +fn callPrivFunction() { + foo.privateFunction(); +} + )SOURCE", 2, + ".tmp_source.zig:5:8: error: 'privateFunction' is private", + "foo.zig:2:1: note: declared here"); + + add_source_file(tc, "foo.zig", R"SOURCE( +fn privateFunction() { } + )SOURCE"); + } + } ////////////////////////////////////////////////////////////////////////////// diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 62be85c64ff84b0039895d5d06e35d8b1a7ee7d5..80fe018461673d9871b1ac11d52f1d660a52718f 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -15,6 +15,7 @@ const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cas const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig"); const test_enum_with_members = @import("cases/enum_with_members.zig"); const test_struct_contains_slice_of_itself = @import("cases/struct_contains_slice_of_itself.zig"); +const test_this = @import("cases/this.zig"); // normal comment /// this is a documentation comment -- 2.54.0