Compare commits
	
		
			No commits in common. "master" and "zig-bug-report" have entirely different histories.
		
	
	
		
			master
			...
			zig-bug-re
		
	
		
					 9 changed files with 144 additions and 219 deletions
				
			
		|  | @ -37,6 +37,7 @@ negatively charged towards | |||
| 
 | ||||
| ## wip | ||||
| 
 | ||||
|  - no `for` yet | ||||
|  - no `map` yet | ||||
|  - no `in` yet (probably will be dropped) | ||||
|  - no `module`, `import` yet | ||||
|  |  | |||
|  | @ -17,8 +17,6 @@ fn main(a int) int { | |||
| 	mut a := 1+2 | ||||
| 	a = 2 | ||||
| 
 | ||||
| 	a = 1 && 0 | ||||
| 
 | ||||
| 	if a { | ||||
| 		println(30) | ||||
| 	} else { | ||||
|  | @ -65,9 +63,6 @@ fn main(a int) int { | |||
| 	str.len /= 1 | ||||
| 
 | ||||
| 	awoo := [1, 2, a(), b + 2, c(31) * d] | ||||
| 
 | ||||
| 	for a in b {} | ||||
| 	for idx, a in b {} | ||||
| } | ||||
| 
 | ||||
| fn (v Typ) voidfunc() {} | ||||
|  |  | |||
							
								
								
									
										22
									
								
								src/ast.zig
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								src/ast.zig
									
										
									
									
									
								
							|  | @ -158,20 +158,12 @@ pub const LoopStmt = struct { | |||
|     then_branch: Block, | ||||
| }; | ||||
| 
 | ||||
| pub const ForStmt = struct { | ||||
|     index: ?Token, | ||||
|     value: Token, | ||||
|     array: Token, | ||||
|     block: Block, | ||||
| }; | ||||
| 
 | ||||
| pub const Stmt = union(enum) { | ||||
|     Expr: *Expr, | ||||
|     Println: *Expr, | ||||
| 
 | ||||
|     If: IfStmt, | ||||
|     Loop: LoopStmt, | ||||
|     For: ForStmt, | ||||
| 
 | ||||
|     Return: ReturnStmt, | ||||
| 
 | ||||
|  | @ -220,20 +212,6 @@ pub const Stmt = union(enum) { | |||
|         return stmt; | ||||
|     } | ||||
| 
 | ||||
|     pub fn mkFor(allocator: *std.mem.Allocator, index: ?Token, value: Token, array: Token, block: Block) !*Stmt { | ||||
|         var stmt = try allocator.create(Stmt); | ||||
|         stmt.* = Stmt{ | ||||
|             .For = ForStmt{ | ||||
|                 .index = index, | ||||
|                 .value = value, | ||||
|                 .array = array, | ||||
|                 .block = block, | ||||
|             }, | ||||
|         }; | ||||
| 
 | ||||
|         return stmt; | ||||
|     } | ||||
| 
 | ||||
|     pub fn mkReturn(allocator: *std.mem.Allocator, tok: Token, value: *Expr) !*Stmt { | ||||
|         var stmt = try allocator.create(Stmt); | ||||
|         stmt.* = Stmt{ | ||||
|  |  | |||
|  | @ -9,28 +9,28 @@ const warn = std.debug.warn; | |||
| fn printIdent(ident: usize) void { | ||||
|     var i: usize = 0; | ||||
|     while (i < ident) : (i += 1) { | ||||
|         std.debug.warn("\t", .{}); | ||||
|         std.debug.warn("\t"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn print(ident: usize, comptime fmt: []const u8, args: anytype) void { | ||||
| fn print(ident: usize, comptime fmt: []const u8, args: ...) void { | ||||
|     printIdent(ident); | ||||
|     std.debug.warn(fmt, args); | ||||
| } | ||||
| 
 | ||||
| fn printBlock(ident: usize, block: anytype, endNewline: bool) void { | ||||
|     std.debug.warn("(\n", .{}); | ||||
| fn printBlock(ident: usize, block: var, endNewline: bool) void { | ||||
|     std.debug.warn("(\n"); | ||||
| 
 | ||||
|     for (block.items) |stmt| { | ||||
|     for (block.toSlice()) |stmt| { | ||||
|         printIdent(ident); | ||||
|         printStmt(ident, stmt); | ||||
|         std.debug.warn("\n", .{}); | ||||
|         std.debug.warn("\n"); | ||||
|     } | ||||
| 
 | ||||
|     if (endNewline) { | ||||
|         print(ident - 1, ")\n", .{}); | ||||
|         print(ident - 1, ")\n"); | ||||
|     } else { | ||||
|         print(ident - 1, ")", .{}); | ||||
|         print(ident - 1, ")"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -48,51 +48,55 @@ pub fn printNode(node: *Node, ident: usize) void { | |||
|                 const typ = method.typ.lexeme; | ||||
| 
 | ||||
|                 if (method.mutable) { | ||||
|                     warn("(method mut {} {} {} {} ", .{ vari, typ, name, ret_type }); | ||||
|                     warn("(method mut {} {} {} {} ", vari, typ, name, ret_type); | ||||
|                 } else { | ||||
|                     warn("(method {} {} {} {} ", .{ vari, typ, name, ret_type }); | ||||
|                     warn("(method {} {} {} {} ", vari, typ, name, ret_type); | ||||
|                 } | ||||
|             } else { | ||||
|                 warn("(fn {} {} (", .{ name, ret_type }); | ||||
|                 warn("(fn {} {} (", name, ret_type); | ||||
|             } | ||||
| 
 | ||||
|             for (decl.params.items) |param| { | ||||
|                 warn("({} {}) ", .{ param.name.lexeme, param.typ.lexeme }); | ||||
|             for (decl.params.toSlice()) |param| { | ||||
|                 warn("({} {}) ", param.name.lexeme, param.typ.lexeme); | ||||
|             } | ||||
| 
 | ||||
|             printBlock(ident + 1, decl.body, false); | ||||
|             warn(")\n", .{}); | ||||
|             warn(")\n"); | ||||
|         }, | ||||
| 
 | ||||
|         .ConstDecl => |consts| { | ||||
|             print(ident, "(const (\n", .{}); | ||||
|             print(ident, "(const (\n"); | ||||
| 
 | ||||
|             for (consts.items) |const_decl| { | ||||
|                 print(ident + 1, "({} ", .{ | ||||
|             for (consts.toSlice()) |const_decl| { | ||||
|                 print( | ||||
|                     ident + 1, | ||||
|                     "({} ", | ||||
|                     const_decl.name.lexeme, | ||||
|                 }); | ||||
|                 ); | ||||
| 
 | ||||
|                 printExpr(const_decl.expr); | ||||
|                 std.debug.warn(")\n", .{}); | ||||
|                 std.debug.warn(")\n"); | ||||
|             } | ||||
| 
 | ||||
|             print(ident, "))\n", .{}); | ||||
|             print(ident, "))\n"); | ||||
|         }, | ||||
| 
 | ||||
|         .Enum => |decl| { | ||||
|             print(ident, "(enum {} (\n", .{decl.name.lexeme}); | ||||
|             print(ident, "(enum {} (\n", decl.name.lexeme); | ||||
| 
 | ||||
|             for (decl.fields.items) |field| { | ||||
|                 print(ident + 1, "{}\n", .{ | ||||
|             for (decl.fields.toSlice()) |field| { | ||||
|                 print( | ||||
|                     ident + 1, | ||||
|                     "{}\n", | ||||
|                     field.lexeme, | ||||
|                 }); | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
|             print(ident, "))\n", .{}); | ||||
|             print(ident, "))\n"); | ||||
|         }, | ||||
| 
 | ||||
|         .Root => { | ||||
|             for (node.Root.items) |child| { | ||||
|             for (node.Root.toSlice()) |child| { | ||||
|                 printNode(child, ident + 1); | ||||
|             } | ||||
|         }, | ||||
|  | @ -100,129 +104,129 @@ pub fn printNode(node: *Node, ident: usize) void { | |||
|         .Stmt => |stmt| { | ||||
|             printIdent(ident); | ||||
|             printStmt(ident, stmt); | ||||
|             std.debug.warn("\n", .{}); | ||||
|             std.debug.warn("\n"); | ||||
|         }, | ||||
| 
 | ||||
|         .Struct => |struc| { | ||||
|             print(ident, "(struct {} (\n", .{struc.name.lexeme}); | ||||
|             for (struc.fields.items) |field| { | ||||
|             print(ident, "(struct {} (\n", struc.name.lexeme); | ||||
|             for (struc.fields.toSlice()) |field| { | ||||
|                 printIdent(ident + 1); | ||||
|                 if (field.mutable) { | ||||
|                     std.debug.warn("(mut ", .{}); | ||||
|                     std.debug.warn("(mut "); | ||||
|                 } else { | ||||
|                     std.debug.warn("(", .{}); | ||||
|                     std.debug.warn("("); | ||||
|                 } | ||||
| 
 | ||||
|                 if (field.public) { | ||||
|                     std.debug.warn("pub ", .{}); | ||||
|                     std.debug.warn("pub "); | ||||
|                 } | ||||
| 
 | ||||
|                 if (field.mutable_outside) { | ||||
|                     std.debug.warn("MUT_OUT ", .{}); | ||||
|                     std.debug.warn("MUT_OUT "); | ||||
|                 } | ||||
| 
 | ||||
|                 std.debug.warn("{} {})\n", .{ field.name.lexeme, field.typ.lexeme }); | ||||
|                 std.debug.warn("{} {})\n", field.name.lexeme, field.typ.lexeme); | ||||
|             } | ||||
|             print(ident, "))\n", .{}); | ||||
|             print(ident, "))\n"); | ||||
|         }, | ||||
| 
 | ||||
|         else => { | ||||
|             print(ident, "unknown node: {}\n", .{node}); | ||||
|             print(ident, "unknown node: {}\n", node); | ||||
|         }, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn parenthetize(name: []const u8, exprs: []*const Expr) void { | ||||
|     std.debug.warn("({}", .{name}); | ||||
| fn parenthetize(name: []const u8, exprs: []*Expr) void { | ||||
|     std.debug.warn("({}", name); | ||||
| 
 | ||||
|     for (exprs) |expr| { | ||||
|         std.debug.warn(" ", .{}); | ||||
|         std.debug.warn(" "); | ||||
|         printExpr(expr); | ||||
|     } | ||||
| 
 | ||||
|     std.debug.warn(")", .{}); | ||||
|     std.debug.warn(")"); | ||||
| } | ||||
| 
 | ||||
| pub fn printExpr(expr: *const Expr) void { | ||||
| pub fn printExpr(expr: *Expr) void { | ||||
|     switch (expr.*) { | ||||
|         .Binary => |binary| parenthetize(binary.op.lexeme, &[_]*const Expr{ binary.left, binary.right }), | ||||
|         .Logical => |binary| parenthetize(binary.op.lexeme, &[_]*const Expr{ binary.left, binary.right }), | ||||
|         .Unary => |unary| parenthetize(unary.op.lexeme, &[_]*const Expr{unary.right}), | ||||
|         .Grouping => |expr_ptr| parenthetize("group", &[_]*const Expr{expr_ptr}), | ||||
|         .Binary => |binary| parenthetize(binary.op.lexeme, &[_]*Expr{ binary.left, binary.right }), | ||||
|         .Logical => |binary| parenthetize(binary.op.lexeme, &[_]*Expr{ binary.left, binary.right }), | ||||
|         .Unary => |unary| parenthetize(unary.op.lexeme, &[_]*Expr{unary.right}), | ||||
|         .Grouping => |expr_ptr| parenthetize("group", &[_]*Expr{expr_ptr}), | ||||
| 
 | ||||
|         .Literal => |literal| { | ||||
|             switch (literal) { | ||||
|                 .Bool => |val| std.debug.warn("{}", .{val}), | ||||
|                 .Integer => |val| std.debug.warn("{}", .{val}), | ||||
|                 .Float => |val| std.debug.warn("{}", .{val}), | ||||
|                 .String => |val| std.debug.warn("'{}'", .{val}), | ||||
|                 .Bool => |val| std.debug.warn("{}", val), | ||||
|                 .Integer => |val| std.debug.warn("{}", val), | ||||
|                 .Float => |val| std.debug.warn("{}", val), | ||||
|                 .String => |val| std.debug.warn("'{}'", val), | ||||
|                 .Array => |exprs| { | ||||
|                     parenthetize("array", exprs.items); | ||||
|                     parenthetize("array", exprs.toSlice()); | ||||
|                 }, | ||||
|                 else => |typ| std.debug.warn("UnknownLiteral-{}", .{typ}), | ||||
|                 else => |typ| std.debug.warn("UnknownLiteral-{}", typ), | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         .Variable => |token| std.debug.warn("{}", .{token.lexeme}), | ||||
|         .Variable => |token| std.debug.warn("{}", token.lexeme), | ||||
| 
 | ||||
|         .VarDecl => |decl| { | ||||
|             if (decl.mutable) { | ||||
|                 std.debug.warn("(mut ", .{}); | ||||
|                 std.debug.warn("(mut "); | ||||
|             } else { | ||||
|                 std.debug.warn("(", .{}); | ||||
|                 std.debug.warn("("); | ||||
|             } | ||||
| 
 | ||||
|             std.debug.warn("let {} ", .{decl.assign.name.lexeme}); | ||||
|             std.debug.warn("let {} ", decl.assign.name.lexeme); | ||||
|             printExpr(decl.assign.value); | ||||
|             std.debug.warn(")", .{}); | ||||
|             std.debug.warn(")"); | ||||
|         }, | ||||
| 
 | ||||
|         .Assign => |assign| { | ||||
|             std.debug.warn("(set ", .{}); | ||||
|             std.debug.warn("{} ", .{assign.name.lexeme}); | ||||
|             std.debug.warn("(set "); | ||||
|             std.debug.warn("{} ", assign.name.lexeme); | ||||
|             printExpr(assign.value); | ||||
|             std.debug.warn(")", .{}); | ||||
|             std.debug.warn(")"); | ||||
|         }, | ||||
| 
 | ||||
|         .Call => |call| { | ||||
|             std.debug.warn("(", .{}); | ||||
|             std.debug.warn("("); | ||||
|             printExpr(call.callee); | ||||
| 
 | ||||
|             for (call.arguments.items) |arg| { | ||||
|                 std.debug.warn(" ", .{}); | ||||
|             for (call.arguments.toSlice()) |arg| { | ||||
|                 std.debug.warn(" "); | ||||
|                 printExpr(arg); | ||||
|             } | ||||
| 
 | ||||
|             std.debug.warn(")", .{}); | ||||
|             std.debug.warn(")"); | ||||
|         }, | ||||
| 
 | ||||
|         .Struct => |val| { | ||||
|             std.debug.warn("({} (", .{val.name.lexeme}); | ||||
|             std.debug.warn("({} (", val.name.lexeme); | ||||
| 
 | ||||
|             for (val.inits.items) |init| { | ||||
|                 std.debug.warn(" ({} ", .{init.field.lexeme}); | ||||
|             for (val.inits.toSlice()) |init| { | ||||
|                 std.debug.warn(" ({} ", init.field.lexeme); | ||||
|                 printExpr(init.expr); | ||||
|                 std.debug.warn(")", .{}); | ||||
|                 std.debug.warn(")"); | ||||
|             } | ||||
| 
 | ||||
|             std.debug.warn("))", .{}); | ||||
|             std.debug.warn("))"); | ||||
|         }, | ||||
| 
 | ||||
|         .Get => |get| { | ||||
|             warn("(", .{}); | ||||
|             warn("("); | ||||
|             printExpr(get.struc); | ||||
|             warn("{}", .{get.name.lexeme}); | ||||
|             warn(".{})", get.name.lexeme); | ||||
|         }, | ||||
| 
 | ||||
|         .Set => |set| { | ||||
|             warn("(set ", .{}); | ||||
|             warn("(set "); | ||||
|             printExpr(set.struc); | ||||
|             warn(" {} ", .{set.field.lexeme}); | ||||
|             warn(" {} ", set.field.lexeme); | ||||
|             printExpr(set.value); | ||||
|             warn(")", .{}); | ||||
|             warn(")"); | ||||
|         }, | ||||
| 
 | ||||
|         else => std.debug.warn("UnknownExpr-{}", .{@tagName(expr.*)}), | ||||
|         else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -232,53 +236,38 @@ pub fn printStmt(ident: usize, stmt: *Stmt) void { | |||
|         .Expr => |expr| printExpr(expr), | ||||
| 
 | ||||
|         .If => |ifstmt| { | ||||
|             std.debug.warn("(if ", .{}); | ||||
|             std.debug.warn("(if "); | ||||
|             printExpr(ifstmt.condition); | ||||
|             std.debug.warn(" ", .{}); | ||||
|             std.debug.warn(" "); | ||||
| 
 | ||||
|             printBlock(ident + 1, ifstmt.then_branch, false); | ||||
|             if (ifstmt.else_branch) |else_branch| { | ||||
|                 std.debug.warn(" else ", .{}); | ||||
|                 std.debug.warn(" else "); | ||||
|                 printBlock(ident + 1, else_branch, false); | ||||
|             } | ||||
| 
 | ||||
|             std.debug.warn(")\n", .{}); | ||||
|             std.debug.warn(")\n"); | ||||
|         }, | ||||
| 
 | ||||
|         .Loop => |loop| { | ||||
|             std.debug.warn("(loop ", .{}); | ||||
|             std.debug.warn("(loop "); | ||||
|             if (loop.condition) |cond| { | ||||
|                 printExpr(cond); | ||||
|             } else { | ||||
|                 std.debug.warn("true", .{}); | ||||
|                 std.debug.warn("true"); | ||||
|             } | ||||
|             std.debug.warn(" ", .{}); | ||||
|             std.debug.warn(" "); | ||||
| 
 | ||||
|             printBlock(ident + 1, loop.then_branch, false); | ||||
|             std.debug.warn(")\n", .{}); | ||||
|         }, | ||||
| 
 | ||||
|         .For => |forstmt| { | ||||
|             std.debug.warn("(for ", .{}); | ||||
| 
 | ||||
|             if (forstmt.index) |index| { | ||||
|                 std.debug.warn("({} {}) ", .{ index.lexeme, forstmt.value.lexeme }); | ||||
|             } else { | ||||
|                 std.debug.warn("{} ", .{forstmt.value.lexeme}); | ||||
|             } | ||||
| 
 | ||||
|             std.debug.warn("{} ", .{forstmt.array.lexeme}); | ||||
| 
 | ||||
|             printBlock(ident + 1, forstmt.block, false); | ||||
|             std.debug.warn(")\n", .{}); | ||||
|             std.debug.warn(")\n"); | ||||
|         }, | ||||
| 
 | ||||
|         .Return => |ret| { | ||||
|             std.debug.warn("(return ", .{}); | ||||
|             std.debug.warn("(return "); | ||||
|             printExpr(ret.value); | ||||
|             std.debug.warn(")\n", .{}); | ||||
|             std.debug.warn(")\n"); | ||||
|         }, | ||||
| 
 | ||||
|         else => std.debug.warn("UnknownStmt-{}", .{@tagName(stmt.*)}), | ||||
|         else => std.debug.warn("UnknownStmt-{}", @tagName(stmt.*)), | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,14 +1,14 @@ | |||
| const std = @import("std"); | ||||
| pub fn report(line: usize, where: []const u8, message: []const u8) void { | ||||
|     std.debug.warn("[line {}] Error{}: {}", .{ line, where, message }); | ||||
|     std.debug.warn("[line {}] Error{}: {}", line, where, message); | ||||
| } | ||||
| 
 | ||||
| pub fn reportN(line: usize, message: []const u8) void { | ||||
|     report(line, "", message); | ||||
| } | ||||
| 
 | ||||
| pub fn reportFmt(line: usize, comptime fmt: []const u8, args: anytype) void { | ||||
|     std.debug.warn("[line {}] Error", .{line}); | ||||
| pub fn reportFmt(line: usize, comptime fmt: []const u8, args: ...) void { | ||||
|     std.debug.warn("[line {}] Error", line); | ||||
|     std.debug.warn(fmt, args); | ||||
|     std.debug.warn("\n", .{}); | ||||
|     std.debug.warn("\n"); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										42
									
								
								src/main.zig
									
										
									
									
									
								
							
							
						
						
									
										42
									
								
								src/main.zig
									
										
									
									
									
								
							|  | @ -10,16 +10,18 @@ pub const Result = error{ | |||
|     CompileError, | ||||
| }; | ||||
| 
 | ||||
| fn run(allocator: *Allocator, data: []const u8) !void { | ||||
|     var stdout_file = std.io.getStdOut(); | ||||
|     const stdout = stdout_file.outStream(); | ||||
| pub const StdOut = *std.io.OutStream(std.fs.File.WriteError); | ||||
| 
 | ||||
| fn run(allocator: *Allocator, data: []u8) !void { | ||||
|     var stdout_file = try std.io.getStdOut(); | ||||
|     const stdout = &stdout_file.outStream().stream; | ||||
| 
 | ||||
|     var runner = runners.Runner.init(allocator, stdout); | ||||
|     return runner.execute(data); | ||||
| } | ||||
| 
 | ||||
| fn runFile(allocator: *Allocator, path: []const u8) !void { | ||||
|     var file = try std.fs.cwd().openFile(path, .{}); | ||||
|     var file = try std.fs.File.openRead(path); | ||||
|     defer file.close(); | ||||
| 
 | ||||
|     const total_bytes = try file.getEndPos(); | ||||
|  | @ -37,32 +39,26 @@ fn runFile(allocator: *Allocator, path: []const u8) !void { | |||
| } | ||||
| 
 | ||||
| fn runPrompt(allocator: *Allocator) !void { | ||||
|     var stdout_file = std.io.getStdOut(); | ||||
|     const stdout = stdout_file.outStream(); | ||||
| 
 | ||||
|     var stdin_file = std.io.getStdIn(); | ||||
|     const stdin = stdin_file.inStream(); | ||||
| 
 | ||||
|     var line_buf: [1024]u8 = undefined; | ||||
|     var stdout_file = try std.io.getStdOut(); | ||||
|     const stdout = &stdout_file.outStream().stream; | ||||
| 
 | ||||
|     while (true) { | ||||
|         try stdout.print("> ", .{}); | ||||
|         try stdout.print("> "); | ||||
|         var buffer = try std.Buffer.init(allocator, ""[0..]); | ||||
| 
 | ||||
|         const amt = try stdin.read(&line_buf); | ||||
|         if (amt == line_buf.len) { | ||||
|             try stdout.print("Input too long.\n", .{}); | ||||
|             continue; | ||||
|         } | ||||
|         const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n"); | ||||
|         var line = std.io.readLine(&buffer) catch |err| { | ||||
|             if (err == error.EndOfStream) return; | ||||
|             return err; | ||||
|         }; | ||||
| 
 | ||||
|         run(allocator, line) catch |err| { | ||||
|             switch (err) { | ||||
|                 Result.Ok => {}, | ||||
|                 Result.ScannerError => blk: { | ||||
|                     try stdout.print("scanner error.\n", .{}); | ||||
|                     try stdout.print("scanner error.\n"); | ||||
|                 }, | ||||
|                 Result.CompileError => blk: { | ||||
|                     try stdout.print("compile error.\n", .{}); | ||||
|                     try stdout.print("compile error.\n"); | ||||
|                 }, | ||||
|                 else => return err, | ||||
|             } | ||||
|  | @ -71,12 +67,12 @@ fn runPrompt(allocator: *Allocator) !void { | |||
| } | ||||
| 
 | ||||
| pub fn main() anyerror!void { | ||||
|     var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); | ||||
|     var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator); | ||||
|     defer arena.deinit(); | ||||
|     var allocator = &arena.allocator; | ||||
| 
 | ||||
|     var stdout_file = std.io.getStdOut(); | ||||
|     var stdout = stdout_file.outStream(); | ||||
|     var stdout_file = try std.io.getStdOut(); | ||||
|     var stdout = &stdout_file.outStream().stream; | ||||
| 
 | ||||
|     var args_it = std.process.args(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -43,27 +43,27 @@ pub const Parser = struct { | |||
|         self.tokens.deinit(); | ||||
|     } | ||||
| 
 | ||||
|     fn doError(self: *Parser, comptime fmt: []const u8, args: anytype) void { | ||||
|     fn doError(self: *Parser, comptime fmt: []const u8, args: ...) void { | ||||
|         self.hadError = true; | ||||
| 
 | ||||
|         std.debug.warn("parser error at line {}\n\t", .{self.scanner.line}); | ||||
|         std.debug.warn("parser error at line {}\n\t", self.scanner.line); | ||||
|         std.debug.warn(fmt, args); | ||||
|         std.debug.warn("\n", .{}); | ||||
|         std.debug.warn("\n"); | ||||
|     } | ||||
| 
 | ||||
|     fn peek(self: *Parser) Token { | ||||
|         return self.tokens.items[self.tokens.items.len - 1]; | ||||
|         return self.tokens.at(self.tokens.len - 1); | ||||
|     } | ||||
| 
 | ||||
|     fn previous(self: *Parser) Token { | ||||
|         return self.tokens.items[self.tokens.items.len - 2]; | ||||
|         return self.tokens.at(self.tokens.len - 2); | ||||
|     } | ||||
| 
 | ||||
|     fn tokenError(self: *Parser, token: Token, msg: []const u8) Result!void { | ||||
|         if (token.ttype == .EOF) { | ||||
|             err.report(token.line, " at end", msg); | ||||
|         } else { | ||||
|             err.reportFmt(token.line, " at '{}': {}", .{ token.lexeme, msg }); | ||||
|             err.reportFmt(token.line, " at '{}': {}", token.lexeme, msg); | ||||
|         } | ||||
| 
 | ||||
|         return Result.CompileError; | ||||
|  | @ -90,7 +90,7 @@ pub const Parser = struct { | |||
|         } | ||||
| 
 | ||||
|         try self.tokens.append(token); | ||||
|         std.debug.warn("skip to {}\n", .{token}); | ||||
|         std.debug.warn("skip to {}\n", token); | ||||
|         return token; | ||||
|     } | ||||
| 
 | ||||
|  | @ -117,17 +117,19 @@ pub const Parser = struct { | |||
| 
 | ||||
|         // TODO maybe this could be entirely comptime? | ||||
|         var buf_main: [1000]u8 = undefined; | ||||
|         var buf = try std.fmt.bufPrint(buf_main[0..], "expected {}, got {}", .{ | ||||
|         var buf = try std.fmt.bufPrint( | ||||
|             buf_main[0..], | ||||
|             "expected {}, got {}", | ||||
|             ttype, | ||||
|             self.peek().ttype, | ||||
|         }); | ||||
|         ); | ||||
| 
 | ||||
|         try self.tokenError(self.peek(), buf); | ||||
|         return Result.CompileError; | ||||
|     } | ||||
| 
 | ||||
|     /// check() against multiple tokens | ||||
|     fn compareAnyOf(self: *@This(), ttypes: []const TokenType) bool { | ||||
|     fn compareAnyOf(self: *@This(), ttypes: []TokenType) bool { | ||||
|         for (ttypes) |ttype| { | ||||
|             if (self.check(ttype)) return true; | ||||
|         } | ||||
|  | @ -189,7 +191,7 @@ pub const Parser = struct { | |||
|     } | ||||
| 
 | ||||
|     fn mkUnary(self: *Parser, op: Token, right: *Expr) !*Expr { | ||||
|         std.debug.warn("Unary\n", .{}); | ||||
|         std.debug.warn("Unary\n"); | ||||
| 
 | ||||
|         var expr = try self.allocator.create(Expr); | ||||
|         expr.* = Expr{ | ||||
|  | @ -607,7 +609,7 @@ pub const Parser = struct { | |||
|             .Enum => try self.parseEnumDecl(), | ||||
| 
 | ||||
|             else => |ttype| blk: { | ||||
|                 self.doError("expected Fn, Const, Struct, got {}\n", .{ttype}); | ||||
|                 self.doError("expected Fn, Const, Struct, got {}\n", ttype); | ||||
|                 return Result.CompileError; | ||||
|             }, | ||||
|         }; | ||||
|  | @ -634,7 +636,6 @@ pub const Parser = struct { | |||
|         return switch (self.peek().ttype) { | ||||
|             .If => try self.parseIfStmt(), | ||||
|             .Loop => try self.parseLoop(), | ||||
|             .For => try self.parseForStmt(), | ||||
|             .Println => try self.parsePrintln(), | ||||
|             .Return => try self.parseReturn(), | ||||
|             else => try self.parseStmtExpr(), | ||||
|  | @ -674,42 +675,6 @@ pub const Parser = struct { | |||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     fn parseForStmt(self: *@This()) !*Stmt { | ||||
|         // There are two types of for in vig's V subset: | ||||
|         //  - for x in y | ||||
|         //  - for idx, x in y | ||||
|         _ = try self.consumeSingle(.For); | ||||
| 
 | ||||
|         var index_var: ?Token = null; | ||||
|         var value_var: Token = undefined; | ||||
| 
 | ||||
|         const subject_1 = try self.consumeSingle(.Identifier); | ||||
| 
 | ||||
|         if (self.check(.Comma)) { | ||||
|             _ = try self.consumeSingle(.Comma); | ||||
| 
 | ||||
|             const subject_2 = try self.consumeSingle(.Identifier); | ||||
|             index_var = subject_1; | ||||
|             value_var = subject_2; | ||||
|         } else { | ||||
|             value_var = subject_1; | ||||
|         } | ||||
| 
 | ||||
|         _ = try self.consumeSingle(.In); | ||||
| 
 | ||||
|         // MUST be identifier | ||||
|         var array = try self.consumeSingle(.Identifier); | ||||
|         var block = try self.parseStmtBlock(); | ||||
| 
 | ||||
|         return try Stmt.mkFor( | ||||
|             self.allocator, | ||||
|             index_var, | ||||
|             value_var, | ||||
|             array, | ||||
|             block, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     fn parseLoop(self: *@This()) !*Stmt { | ||||
|         _ = try self.consumeSingle(.Loop); | ||||
|         var expr: ?*Expr = null; | ||||
|  | @ -837,7 +802,7 @@ pub const Parser = struct { | |||
|             .Get => |get| { | ||||
|                 switch (op.ttype) { | ||||
|                     .ColonEqual => { | ||||
|                         self.doError("can not initialize struct field", .{}); | ||||
|                         self.doError("can not initialize struct field"); | ||||
|                         return Result.CompileError; | ||||
|                     }, | ||||
| 
 | ||||
|  | @ -857,7 +822,7 @@ pub const Parser = struct { | |||
|             }, | ||||
| 
 | ||||
|             else => |expr_typ| { | ||||
|                 self.doError("Invalid assignment target {}", .{expr_typ}); | ||||
|                 self.doError("Invalid assignment target {}", expr_typ); | ||||
|                 return Result.CompileError; | ||||
|             }, | ||||
|         } | ||||
|  | @ -1027,8 +992,8 @@ pub const Parser = struct { | |||
|     fn finishStructVal(self: *@This(), expr: *Expr) !*Expr { | ||||
|         // <expr>{a: 10 b: 10} | ||||
|         // for this to work properly, <expr> must be Variable, since its a type. | ||||
|         if (@as(ast.ExprType, expr.*) != .Variable) { | ||||
|             self.doError("Expected variable for struct type, got {}", .{@as(ast.ExprType, expr.*)}); | ||||
|         if (ast.ExprType(expr.*) != .Variable) { | ||||
|             self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*)); | ||||
|             return Result.CompileError; | ||||
|         } | ||||
| 
 | ||||
|  | @ -1093,7 +1058,7 @@ pub const Parser = struct { | |||
|             }, | ||||
| 
 | ||||
|             else => blk: { | ||||
|                 self.doError("expected literal, got {}", .{curtype}); | ||||
|                 self.doError("expected literal, got {}", curtype); | ||||
|                 return Result.CompileError; | ||||
|             }, | ||||
|         }; | ||||
|  |  | |||
|  | @ -13,31 +13,32 @@ const Parser = parsers.Parser; | |||
| 
 | ||||
| pub const Runner = struct { | ||||
|     allocator: *Allocator, | ||||
|     stdout: std.fs.File.OutStream, | ||||
|     stdout: main.StdOut, | ||||
| 
 | ||||
|     pub fn init(allocator: *Allocator, stdout: anytype) Runner { | ||||
|         return .{ .allocator = allocator, .stdout = stdout }; | ||||
|     pub fn init(allocator: *Allocator, stdout: main.StdOut) Runner { | ||||
|         return Runner{ .allocator = allocator, .stdout = stdout }; | ||||
|     } | ||||
| 
 | ||||
|     fn testScanner(self: *Runner, scanner: *scanners.Scanner) !void { | ||||
|         while (true) { | ||||
|             var tok_opt = scanner.nextToken() catch |err| { | ||||
|                 try self.stdout.print("error at '{}': {}\n", .{ | ||||
|                 try self.stdout.print( | ||||
|                     "error at '{}': {}\n", | ||||
|                     scanner.currentLexeme(), | ||||
|                     err, | ||||
|                 }); | ||||
|                 ); | ||||
| 
 | ||||
|                 return Result.ScannerError; | ||||
|             }; | ||||
| 
 | ||||
|             if (tok_opt) |tok| { | ||||
|                 if (tok.ttype == .EOF) break; | ||||
|                 try self.stdout.print("{x}\n", .{tok}); | ||||
|                 try self.stdout.print("{x}\n", tok); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn execute(self: *Runner, code: []const u8) !void { | ||||
|     pub fn execute(self: *Runner, code: []u8) !void { | ||||
|         var scanner = scanners.Scanner.init(self.allocator, code); | ||||
|         try self.testScanner(&scanner); | ||||
| 
 | ||||
|  | @ -45,9 +46,9 @@ pub const Runner = struct { | |||
|         var parser = Parser.init(self.allocator, &scanner); | ||||
|         var root = try parser.parse(); | ||||
| 
 | ||||
|         // var it = root.Root.iterator(); | ||||
|         var it = root.Root.iterator(); | ||||
| 
 | ||||
|         std.debug.warn("parse tree\n", .{}); | ||||
|         std.debug.warn("parse tree\n"); | ||||
|         printer.printNode(root, 0); | ||||
| 
 | ||||
|         return Result.Ok; | ||||
|  |  | |||
|  | @ -97,13 +97,13 @@ fn getKeyword(keyword: []const u8) ?TokenType { | |||
| /// Scanner for vlang tokens. | ||||
| pub const Scanner = struct { | ||||
|     allocator: *Allocator, | ||||
|     source: []const u8, | ||||
|     source: []u8, | ||||
| 
 | ||||
|     start: usize = 0, | ||||
|     current: usize = 0, | ||||
|     line: usize = 1, | ||||
| 
 | ||||
|     pub fn init(allocator: *Allocator, source: []const u8) Scanner { | ||||
|     pub fn init(allocator: *Allocator, source: []u8) Scanner { | ||||
|         return Scanner{ .allocator = allocator, .source = source }; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue