From a706f077cbfc0f73e2a79ce03d5af5bce2bb3cd2 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 26 Aug 2019 21:31:01 -0300 Subject: [PATCH 1/4] add pub/mut modifiers to struct fields --- src/ast.zig | 6 ++++-- src/parser.zig | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/ast.zig b/src/ast.zig index 91a045d..baa49eb 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -227,8 +227,10 @@ pub const FieldList = std.ArrayList(StructField); pub const StructField = struct { name: Token, typ: Token, - mutable: bool = true, - public: bool = true, + + mutable: bool = false, + public: bool = false, + mutable_outside: bool = false, }; pub const Struct = struct { diff --git a/src/parser.zig b/src/parser.zig index 02e9d22..a9b63c3 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -18,6 +18,12 @@ const Stmt = ast.Stmt; const TokenList = std.ArrayList(Token); +const FieldState = struct { + public: bool = false, + mutable: bool = false, + mutable_outside: bool = false, +}; + pub const Parser = struct { allocator: *Allocator, scanner: *Scanner, @@ -405,8 +411,6 @@ pub const Parser = struct { while (self.peek().ttype != .RightParen) { const param_name = try self.consumeSingle(.Identifier); - - // TODO dedicated function to consume a type? const param_type = try self.consumeSingle(.Identifier); try param_list.append(ast.ParamDecl{ @@ -495,14 +499,37 @@ pub const Parser = struct { _ = try self.consumeSingle(.LeftBrace); + var field_state = FieldState{}; + while (!self.check(.RightBrace)) { - // TODO mut and pub + if (self.check(.Mut)) { + _ = try self.consumeSingle(.Mut); + _ = try self.consumeSingle(.Colon); + if (field_state.mutable) { + field_state.mutable_outside = true; + } else { + field_state.mutable = true; + } + } else if (self.check(.Pub)) { + _ = try self.consumeSingle(.Pub); + _ = try self.consumeSingle(.Colon); + field_state.public = true; + } + const field_name = try self.consumeSingle(.Identifier); const field_type = try self.consumeSingle(.Identifier); + // we could create a FieldState on the heap and copy our current + // field state into a StructField.state, but copying via this makes + // things so much nicer. + try fields.append(ast.StructField{ .name = field_name, .typ = field_type, + + .mutable = field_state.mutable, + .public = field_state.public, + .mutable_outside = field_state.mutable_outside, }); } From fc4b84b51ccf81769e999fedd5b53b4d3e82b6f5 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 26 Aug 2019 21:31:57 -0300 Subject: [PATCH 2/4] scanner: add pub keyword --- src/scanner.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/scanner.zig b/src/scanner.zig index 2ee42d1..76a9c7e 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -51,6 +51,7 @@ const keywords = [_][]const u8{ "None", "println", "loop", + "pub", }; const keyword_ttypes = [_]TokenType{ @@ -80,6 +81,7 @@ const keyword_ttypes = [_]TokenType{ .None, .Println, .Loop, + .Pub, }; fn getKeyword(keyword: []const u8) ?TokenType { From 96d48f87624ca25fcebf92883cb8f143b31cbb69 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 26 Aug 2019 21:32:10 -0300 Subject: [PATCH 3/4] tokens: add pub TokenType --- src/tokens.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tokens.zig b/src/tokens.zig index 360c6b6..1a79a13 100644 --- a/src/tokens.zig +++ b/src/tokens.zig @@ -75,6 +75,7 @@ pub const TokenType = enum { None, Println, + Pub, EOF, }; From ac5d29819c238eefc45d8b43cd40eda6ad5ae4de Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 26 Aug 2019 21:43:58 -0300 Subject: [PATCH 4/4] split access modifier parsing into own func - revamp parsing of access modifiers so it is correct --- examples/hello.v | 13 ++++++++++ src/ast_printer.zig | 4 +++ src/parser.zig | 59 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/examples/hello.v b/examples/hello.v index 377d337..3d16d61 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -54,3 +54,16 @@ fn main(a int) int { } fn (v Typ) voidfunc() {} + +struct Foo { + a int +mut: + b int + c int +pub: + d int +pub mut: + e int +pub mut mut: + f int +} diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 3a0ed4f..25f90b4 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -107,6 +107,10 @@ pub fn printNode(node: *Node, ident: usize) void { std.debug.warn("pub "); } + if (field.mutable_outside) { + std.debug.warn("MUT_OUT "); + } + std.debug.warn("{} {})\n", field.name.lexeme, field.typ.lexeme); } print(ident, "))\n"); diff --git a/src/parser.zig b/src/parser.zig index a9b63c3..9c0d436 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -502,19 +502,7 @@ pub const Parser = struct { var field_state = FieldState{}; while (!self.check(.RightBrace)) { - if (self.check(.Mut)) { - _ = try self.consumeSingle(.Mut); - _ = try self.consumeSingle(.Colon); - if (field_state.mutable) { - field_state.mutable_outside = true; - } else { - field_state.mutable = true; - } - } else if (self.check(.Pub)) { - _ = try self.consumeSingle(.Pub); - _ = try self.consumeSingle(.Colon); - field_state.public = true; - } + try self.parseFieldModifiers(&field_state); const field_name = try self.consumeSingle(.Identifier); const field_type = try self.consumeSingle(.Identifier); @@ -538,6 +526,51 @@ pub const Parser = struct { return Node.mkStructDecl(self.allocator, name, fields); } + fn parseFieldModifiers(self: *@This(), field_state: *FieldState) !void { + + // there are five access modifiers: + // - none (private immutable) + // - mut (private mutable) + // - pub (public immutable) + // - pub mut (public mutable only in module) + // - pub mut mut (public mutable everywhere) + + // this function takes care of that by changing the current FieldState + // to what the modifiers dictate. + switch (self.peek().ttype) { + .Mut => { + // There are no oher modifiers that start with mut, so we + // can just go the way of marking it as mutable + _ = try self.consumeSingle(.Mut); + _ = try self.consumeSingle(.Colon); + + field_state.mutable = true; + }, + + // 'pub', 'pub mut', and 'pub mut mut' are all handled here + .Pub => { + _ = try self.consumeSingle(.Pub); + field_state.public = true; + + if (self.check(.Mut)) { + _ = try self.consumeSingle(.Mut); + + field_state.mutable = true; + if (self.check(.Mut)) { + _ = try self.consumeSingle(.Mut); + field_state.mutable_outside = true; + } + } + + _ = try self.consumeSingle(.Colon); + }, + + // if it isn't mut or pub we're likely in an identifier, just + // ignore it. + else => return, + } + } + fn parseTopDecl(self: *@This()) !*Node { return switch (self.peek().ttype) { .Fn => try self.parseFnDecl(),