| author | |
| committer | |
| log | 798dbe487b678a85c7e10b78c2424c4b3508475b |
| tree | dd2a88feaef08d5f6da545dceb724f0cd1eb9b44 |
| parent | 31d9dc35395d495fa896532bdffb4529c136ce41 |
2 files changed, 152 insertions(+), 22 deletions(-)
src-self-hosted/main.zig+127-2| ... | ... | @@ -3,18 +3,134 @@ const io = @import("std").io; |
| 3 | 3 | const os = @import("std").os; |
| 4 | 4 | const heap = @import("std").heap; |
| 5 | 5 | const warn = @import("std").debug.warn; |
| 6 | ||
| 6 | const assert = @import("std").debug.assert; | |
| 7 | const mem = @import("std").mem; | |
| 7 | 8 | |
| 8 | 9 | const Token = struct { |
| 10 | id: Id, | |
| 11 | start: usize, | |
| 12 | end: usize, | |
| 13 | ||
| 14 | const Keyword = enum { | |
| 15 | @"align", | |
| 16 | @"and", | |
| 17 | @"asm", | |
| 18 | @"break", | |
| 19 | @"coldcc", | |
| 20 | @"comptime", | |
| 21 | @"const", | |
| 22 | @"continue", | |
| 23 | @"defer", | |
| 24 | @"else", | |
| 25 | @"enum", | |
| 26 | @"error", | |
| 27 | @"export", | |
| 28 | @"extern", | |
| 29 | @"false", | |
| 30 | @"fn", | |
| 31 | @"for", | |
| 32 | @"goto", | |
| 33 | @"if", | |
| 34 | @"inline", | |
| 35 | @"nakedcc", | |
| 36 | @"noalias", | |
| 37 | @"null", | |
| 38 | @"or", | |
| 39 | @"packed", | |
| 40 | @"pub", | |
| 41 | @"return", | |
| 42 | @"stdcallcc", | |
| 43 | @"struct", | |
| 44 | @"switch", | |
| 45 | @"test", | |
| 46 | @"this", | |
| 47 | @"true", | |
| 48 | @"undefined", | |
| 49 | @"union", | |
| 50 | @"unreachable", | |
| 51 | @"use", | |
| 52 | @"var", | |
| 53 | @"volatile", | |
| 54 | @"while", | |
| 55 | }; | |
| 9 | 56 | |
| 57 | fn getKeyword(bytes: []const u8) -> ?Keyword { | |
| 58 | comptime var i = 0; | |
| 59 | inline while (i < @memberCount(Keyword)) : (i += 1) { | |
| 60 | if (mem.eql(u8, @memberName(Keyword, i), bytes)) { | |
| 61 | return Keyword(i); | |
| 62 | } | |
| 63 | } | |
| 64 | return null; | |
| 65 | } | |
| 66 | ||
| 67 | ||
| 68 | const Id = union(enum) { | |
| 69 | Invalid, | |
| 70 | Identifier, | |
| 71 | Keyword: Keyword, | |
| 72 | Eof, | |
| 73 | }; | |
| 10 | 74 | }; |
| 11 | 75 | |
| 12 | 76 | const Tokenizer = struct { |
| 77 | buffer: []const u8, | |
| 78 | index: usize, | |
| 13 | 79 | |
| 14 | pub fn next() -> Token { | |
| 80 | pub fn dump(self: &Tokenizer, token: &const Token) { | |
| 81 | warn("{} \"{}\"\n", @tagName(token.id), self.buffer[token.start..token.end]); | |
| 82 | } | |
| 15 | 83 | |
| 84 | pub fn init(buffer: []const u8) -> Tokenizer { | |
| 85 | return Tokenizer { | |
| 86 | .buffer = buffer, | |
| 87 | .index = 0, | |
| 88 | }; | |
| 16 | 89 | } |
| 17 | 90 | |
| 91 | const State = enum { | |
| 92 | Start, | |
| 93 | Identifier, | |
| 94 | }; | |
| 95 | ||
| 96 | pub fn next(self: &Tokenizer) -> Token { | |
| 97 | var state = State.Start; | |
| 98 | var result = Token { | |
| 99 | .id = Token.Id { .Eof = {} }, | |
| 100 | .start = self.index, | |
| 101 | .end = undefined, | |
| 102 | }; | |
| 103 | while (self.index < self.buffer.len) : (self.index += 1) { | |
| 104 | const c = self.buffer[self.index]; | |
| 105 | switch (state) { | |
| 106 | State.Start => switch (c) { | |
| 107 | ' ', '\n' => { | |
| 108 | result.start = self.index + 1; | |
| 109 | }, | |
| 110 | 'a'...'z', 'A'...'Z', '_' => { | |
| 111 | state = State.Identifier; | |
| 112 | result.id = Token.Id { .Identifier = {} }; | |
| 113 | }, | |
| 114 | else => { | |
| 115 | result.id = Token.Id { .Invalid = {} }; | |
| 116 | self.index += 1; | |
| 117 | break; | |
| 118 | }, | |
| 119 | }, | |
| 120 | State.Identifier => switch (c) { | |
| 121 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, | |
| 122 | else => { | |
| 123 | if (Token.getKeyword(self.buffer[result.start..self.index])) |keyword_id| { | |
| 124 | result.id = Token.Id { .Keyword = keyword_id }; | |
| 125 | } | |
| 126 | break; | |
| 127 | }, | |
| 128 | }, | |
| 129 | } | |
| 130 | } | |
| 131 | result.end = self.index; | |
| 132 | return result; | |
| 133 | } | |
| 18 | 134 | }; |
| 19 | 135 | |
| 20 | 136 | |
| ... | ... | @@ -36,4 +152,13 @@ pub fn main2() -> %void { |
| 36 | 152 | const target_file_buf = %return io.readFileAlloc(target_file, allocator); |
| 37 | 153 | |
| 38 | 154 | warn("{}", target_file_buf); |
| 155 | ||
| 156 | var tokenizer = Tokenizer.init(target_file_buf); | |
| 157 | while (true) { | |
| 158 | const token = tokenizer.next(); | |
| 159 | tokenizer.dump(token); | |
| 160 | if (@TagType(Token.Id)(token.id) == Token.Id.Eof) { | |
| 161 | break; | |
| 162 | } | |
| 163 | } | |
| 39 | 164 | } |
src/ir.cpp+25-20| ... | ... | @@ -8422,16 +8422,6 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 8422 | 8422 | if (type_is_invalid(wanted_type)) |
| 8423 | 8423 | return ira->codegen->invalid_instruction; |
| 8424 | 8424 | |
| 8425 | if (actual_type != wanted_type->data.enumeration.tag_int_type) { | |
| 8426 | ir_add_error(ira, source_instr, | |
| 8427 | buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'", | |
| 8428 | buf_ptr(&actual_type->name), | |
| 8429 | buf_ptr(&wanted_type->data.enumeration.tag_int_type->name))); | |
| 8430 | return ira->codegen->invalid_instruction; | |
| 8431 | } | |
| 8432 | ||
| 8433 | assert(actual_type->id == TypeTableEntryIdInt); | |
| 8434 | ||
| 8435 | 8425 | if (instr_is_comptime(target)) { |
| 8436 | 8426 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 8437 | 8427 | if (!val) |
| ... | ... | @@ -8453,6 +8443,17 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 8453 | 8443 | return result; |
| 8454 | 8444 | } |
| 8455 | 8445 | |
| 8446 | if (actual_type != wanted_type->data.enumeration.tag_int_type) { | |
| 8447 | ir_add_error(ira, source_instr, | |
| 8448 | buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'", | |
| 8449 | buf_ptr(&actual_type->name), | |
| 8450 | buf_ptr(&wanted_type->data.enumeration.tag_int_type->name))); | |
| 8451 | return ira->codegen->invalid_instruction; | |
| 8452 | } | |
| 8453 | ||
| 8454 | assert(actual_type->id == TypeTableEntryIdInt); | |
| 8455 | ||
| 8456 | ||
| 8456 | 8457 | IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope, |
| 8457 | 8458 | source_instr->source_node, target); |
| 8458 | 8459 | result->value.type = wanted_type; |
| ... | ... | @@ -8822,6 +8823,20 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8822 | 8823 | } |
| 8823 | 8824 | } |
| 8824 | 8825 | |
| 8826 | // explicit cast from integer to enum type with no payload | |
| 8827 | if ((actual_type->id == TypeTableEntryIdInt || actual_type->id == TypeTableEntryIdNumLitInt) && | |
| 8828 | wanted_type->id == TypeTableEntryIdEnum) | |
| 8829 | { | |
| 8830 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); | |
| 8831 | } | |
| 8832 | ||
| 8833 | // explicit cast from enum type with no payload to integer | |
| 8834 | if ((wanted_type->id == TypeTableEntryIdInt || wanted_type->id == TypeTableEntryIdNumLitInt) && | |
| 8835 | actual_type->id == TypeTableEntryIdEnum) | |
| 8836 | { | |
| 8837 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); | |
| 8838 | } | |
| 8839 | ||
| 8825 | 8840 | // explicit cast from number literal to another type |
| 8826 | 8841 | // explicit cast from number literal to &const integer |
| 8827 | 8842 | if (actual_type->id == TypeTableEntryIdNumLitFloat || |
| ... | ... | @@ -8886,16 +8901,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8886 | 8901 | return ir_analyze_int_to_err(ira, source_instr, value); |
| 8887 | 8902 | } |
| 8888 | 8903 | |
| 8889 | // explicit cast from integer to enum type with no payload | |
| 8890 | if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) { | |
| 8891 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); | |
| 8892 | } | |
| 8893 | ||
| 8894 | // explicit cast from enum type with no payload to integer | |
| 8895 | if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) { | |
| 8896 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); | |
| 8897 | } | |
| 8898 | ||
| 8899 | 8904 | // explicit cast from union to the enum type of the union |
| 8900 | 8905 | if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) { |
| 8901 | 8906 | type_ensure_zero_bits_known(ira->codegen, actual_type); |