diff --git a/README.md b/README.md index 43dc024..4a17c57 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,10 @@ negatively charged towards ## wip - no `for` yet - - no arrays yet - no `map` yet - no `in` yet (probably will be dropped) - no `module`, `import` yet - no interfaces yet - - no enums yet - no generics yet - no attributes yet (`[live]`, `[skip]`) - no `defer` yet diff --git a/examples/hello.v b/examples/hello.v index 8b3f3bf..b0f03c1 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -61,6 +61,8 @@ fn main(a int) int { str.len -= 1 str.len *= 1 str.len /= 1 + + awoo := [1, 2, a(), b + 2, c(31) * d] } fn (v Typ) voidfunc() {} @@ -77,3 +79,9 @@ pub mut: pub mut mut: f int } + +enum Color { + red green blue + cyan + alpha +} diff --git a/src/ast.zig b/src/ast.zig index baa49eb..773d9c5 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -5,6 +5,7 @@ const Token = tokens.Token; pub const NodeList = std.ArrayList(*Node); pub const StmtList = std.ArrayList(*Stmt); pub const ExprList = std.ArrayList(*Expr); +pub const TokenList = std.ArrayList(Token); pub const ParamList = std.ArrayList(ParamDecl); pub const ConstList = std.ArrayList(SingleConst); @@ -13,6 +14,7 @@ pub const NodeType = enum { FnDecl, ConstDecl, Struct, + Enum, Block, Stmt, }; @@ -64,6 +66,7 @@ pub const LiteralExpr = union(enum) { Integer: []const u8, Float: []const u8, String: []const u8, + Array: ExprList, }; pub const AssignExpr = struct { @@ -238,11 +241,17 @@ pub const Struct = struct { fields: FieldList, }; +pub const Enum = struct { + name: Token, + fields: TokenList, +}; + pub const Node = union(NodeType) { Root: NodeList, FnDecl: FnDecl, ConstDecl: ConstList, Struct: Struct, + Enum: Enum, Block: StmtList, @@ -265,4 +274,16 @@ pub const Node = union(NodeType) { return node; } + + pub fn mkEnumDecl(allocator: *std.mem.Allocator, name: Token, fields: TokenList) !*Node { + var node = try allocator.create(Node); + node.* = Node{ + .Enum = Enum{ + .name = name, + .fields = fields, + }, + }; + + return node; + } }; diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 25f90b4..6360035 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -81,6 +81,20 @@ pub fn printNode(node: *Node, ident: usize) void { print(ident, "))\n"); }, + .Enum => |decl| { + print(ident, "(enum {} (\n", decl.name.lexeme); + + for (decl.fields.toSlice()) |field| { + print( + ident + 1, + "{}\n", + field.lexeme, + ); + } + + print(ident, "))\n"); + }, + .Root => { for (node.Root.toSlice()) |child| { printNode(child, ident + 1); @@ -146,6 +160,10 @@ pub fn printExpr(expr: *Expr) void { .Integer => |val| std.debug.warn("{}", val), .Float => |val| std.debug.warn("{}", val), .String => |val| std.debug.warn("'{}'", val), + .Array => |exprs| { + parenthetize("array", exprs.toSlice()); + }, + else => |typ| std.debug.warn("UnknownLiteral-{}", typ), } }, diff --git a/src/parser.zig b/src/parser.zig index 30c6c9c..197b69f 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -350,6 +350,17 @@ pub const Parser = struct { return expr; } + fn mkArray(self: *Parser, exprs: ast.ExprList) !*ast.Expr { + var expr = try self.allocator.create(Expr); + expr.* = Expr{ + .Literal = ast.LiteralExpr{ + .Array = exprs, + }, + }; + + return expr; + } + fn mkVariable(self: *Parser, variable: Token) !*ast.Expr { var expr = try self.allocator.create(Expr); expr.* = Expr{ .Variable = variable }; @@ -571,11 +582,31 @@ pub const Parser = struct { } } + fn parseEnumDecl(self: *@This()) !*Node { + _ = try self.consumeSingle(.Enum); + + var fields = ast.TokenList.init(self.allocator); + errdefer fields.deinit(); + + const name = try self.consumeSingle(.Identifier); + + _ = try self.consumeSingle(.LeftBrace); + + while (!self.check(.RightBrace)) { + try fields.append(try self.consumeSingle(.Identifier)); + } + + _ = try self.consumeSingle(.RightBrace); + + return try Node.mkEnumDecl(self.allocator, name, fields); + } + fn parseTopDecl(self: *@This()) !*Node { return switch (self.peek().ttype) { .Fn => try self.parseFnDecl(), .Const => try self.parseConstDecl(), .Struct => try self.parseStructDecl(), + .Enum => try self.parseEnumDecl(), else => |ttype| blk: { self.doError("expected Fn, Const, Struct, got {}\n", ttype); @@ -1000,7 +1031,23 @@ pub const Parser = struct { .String => try self.mkString(lexeme), .Identifier => try self.mkVariable(self.peek()), - .LeftParen => blk: { + // type checking for arrays happens at later stages + .LeftSquare => { + _ = try self.consumeSingle(.LeftSquare); + + var exprs = ast.ExprList.init(self.allocator); + errdefer exprs.deinit(); + + while (!self.check(.RightSquare)) { + try exprs.append(try self.parseExpr()); + if (self.check(.Comma)) _ = try self.consumeSingle(.Comma); + } + + _ = try self.consumeSingle(.RightSquare); + return try self.mkArray(exprs); + }, + + .LeftParen => { _ = try self.nextToken(); var expr = try self.parseExpr(); _ = try self.consume(.RightParen, "Expected ')' after expression");