diff --git a/examples/hello.v b/examples/hello.v index 5167113..377d337 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -53,4 +53,4 @@ fn main(a int) int { v()()() } -fn voidfunc() {} +fn (v Typ) voidfunc() {} diff --git a/src/ast.zig b/src/ast.zig index 0ac53d6..91a045d 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -22,11 +22,18 @@ pub const ParamDecl = struct { typ: Token, }; +pub const MethodData = struct { + variable: Token, + typ: Token, + mutable: bool, +}; + pub const FnDecl = struct { func_name: Token, params: ParamList, return_type: Token, body: StmtList, + method: ?*MethodData, }; pub const SingleConst = struct { diff --git a/src/ast_printer.zig b/src/ast_printer.zig index b386b32..1b278dc 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -37,14 +37,31 @@ fn printBlock(ident: usize, block: var, endNewline: bool) void { pub fn printNode(node: *Node, ident: usize) void { switch (node.*) { .FnDecl => |decl| { - print(ident, "(fn {} (", decl.func_name.lexeme); + const name = decl.func_name.lexeme; + + printIdent(ident); + + // TODO print return types + + if (decl.method) |method| { + const vari = method.variable.lexeme; + const typ = method.typ.lexeme; + + if (method.mutable) { + warn("(method mut {} {} {} ", vari, typ, name); + } else { + warn("(method {} {} {} ", vari, typ, name); + } + } else { + warn("(fn {} (", name); + } for (decl.params.toSlice()) |param| { - std.debug.warn("({} {}) ", param.name.lexeme, param.typ.lexeme); + warn("({} {}) ", param.name.lexeme, param.typ.lexeme); } printBlock(ident + 1, decl.body, false); - std.debug.warn(")\n"); + warn(")\n"); }, .ConstDecl => |consts| { diff --git a/src/parser.zig b/src/parser.zig index e03a93d..02e9d22 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -139,6 +139,7 @@ pub const Parser = struct { params: ast.ParamList, return_type: Token, block: ast.StmtList, + method: ?*ast.MethodData, ) !*ast.Node { var node = try self.allocator.create(Node); node.* = Node{ @@ -147,6 +148,7 @@ pub const Parser = struct { .params = params, .return_type = return_type, .body = block, + .method = method, }, }; return node; @@ -389,22 +391,12 @@ pub const Parser = struct { var param_list = ast.ParamList.init(self.allocator); errdefer param_list.deinit(); + var method: ?*ast.MethodData = null; + _ = try self.consumeSingle(.Fn); if (self.check(.LeftParen)) { - _ = try self.consume(.LeftParen); - - var mutable_ref: bool = false; - const method_var = try self.consume(.Identifier); - - if (self.check(.Mut)) { - _ = try self.consume(.Mut); - mutable_ref = true; - } - - const method_typ = try self.consume(.Identifier); - - _ = try self.consume(.RightParen); + method = try self.parsePreMethod(); } const name = try self.consumeSingle(.Identifier); @@ -435,7 +427,35 @@ pub const Parser = struct { } var block_node = try self.parseBlock(); - return try self.mkFnDecl(name, param_list, return_type, block_node.Block); + return try self.mkFnDecl(name, param_list, return_type, block_node.Block, method); + } + + /// parse the (v [mut] T) part of the method (defined here + /// as a premethod) + fn parsePreMethod(self: *@This()) !?*ast.MethodData { + _ = try self.consumeSingle(.LeftParen); + + var mutable_ref: bool = false; + const variable = try self.consumeSingle(.Identifier); + + if (self.check(.Mut)) { + _ = try self.consumeSingle(.Mut); + mutable_ref = true; + } + + const typ = try self.consumeSingle(.Identifier); + + _ = try self.consumeSingle(.RightParen); + + // create method data and assign the values we got into it + var method = try self.allocator.create(ast.MethodData); + method.* = ast.MethodData{ + .variable = variable, + .typ = typ, + .mutable = mutable_ref, + }; + + return method; } fn parseConstDecl(self: *@This()) !*Node {