From 0c05fc14327631b0fa70eadf60426d507812c4d5 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 12 Jun 2017 12:56:47 +0100 Subject: [PATCH] Prefix `type` and `let` to replace `immutable` --- core/_preload.odin | 28 ++++++------- core/decimal.odin | 2 +- core/fmt.odin | 8 ++-- core/math.odin | 14 +++---- core/mem.odin | 6 +-- core/os_linux.odin | 12 +++--- core/os_windows.odin | 8 ++-- core/os_x.odin | 12 +++--- core/raw.odin | 12 +++--- core/strconv.odin | 8 ++-- core/sync_linux.odin | 4 +- core/sync_windows.odin | 4 +- core/sys/wgl.odin | 18 ++++---- core/sys/windows.odin | 70 +++++++++++++++---------------- core/utf8.odin | 6 +-- src/check_decl.cpp | 2 + src/check_stmt.cpp | 2 +- src/checker.cpp | 65 +++++++++++++++++++---------- src/ir.cpp | 48 ++++++++++----------- src/parser.cpp | 95 +++++++++++++++++++++++++++++------------- src/ssa.cpp | 2 +- src/tokenizer.cpp | 2 +- 22 files changed, 244 insertions(+), 184 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index e67060ec3..c37601bb7 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -24,19 +24,19 @@ // IMPORTANT NOTE(bill): Do not change the order of any of this data // The compiler relies upon this _exact_ order -const TypeInfoEnumValue = raw_union { +type TypeInfoEnumValue raw_union { f: f64, i: i128, } // NOTE(bill): This must match the compiler's -const CallingConvention = enum { +type CallingConvention enum { Odin = 0, C = 1, Std = 2, Fast = 3, } -const TypeInfoRecord = struct #ordered { +type TypeInfoRecord struct #ordered { types: []^TypeInfo, names: []string, offsets: []int, // offsets may not be used in tuples @@ -46,7 +46,7 @@ const TypeInfoRecord = struct #ordered { custom_align: bool, } -const TypeInfo = union { +type TypeInfo union { size: int, align: int, @@ -151,22 +151,22 @@ proc read_cycle_counter() -> u64 #foreign __llvm_core "llvm.readcyclecounter"; // IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it) -const AllocatorMode = enum u8 { +type AllocatorMode enum u8 { Alloc, Free, FreeAll, Resize, } -const AllocatorProc = type proc(allocator_data: rawptr, mode: AllocatorMode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64) -> rawptr; -const Allocator = struct #ordered { +type AllocatorProc proc(allocator_data: rawptr, mode: AllocatorMode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64) -> rawptr; +type Allocator struct #ordered { procedure: AllocatorProc, data: rawptr, } -const Context = struct #ordered { +type Context struct #ordered { thread_id: int, allocator: Allocator, @@ -553,18 +553,18 @@ proc __default_hash_string(s: string) -> u128 { const __INITIAL_MAP_CAP = 16; -const __MapKey = struct #ordered { +type __MapKey struct #ordered { hash: u128, str: string, } -const __MapFindResult = struct #ordered { +type __MapFindResult struct #ordered { hash_index: int, entry_prev: int, entry_index: int, } -const __MapEntryHeader = struct #ordered { +type __MapEntryHeader struct #ordered { key: __MapKey, next: int, /* @@ -572,7 +572,7 @@ const __MapEntryHeader = struct #ordered { */ } -const __MapHeader = struct #ordered { +type __MapHeader struct #ordered { m: ^raw.DynamicMap, is_key_string: bool, entry_size: int, diff --git a/core/decimal.odin b/core/decimal.odin index 31014529b..4fbaec4ec 100644 --- a/core/decimal.odin +++ b/core/decimal.odin @@ -2,7 +2,7 @@ // Multiple precision decimal numbers // NOTE: This is only for floating point printing and nothing else -const Decimal = struct { +type Decimal struct { digits: [384]u8, // big-endian digits count: int, decimal_point: int, diff --git a/core/fmt.odin b/core/fmt.odin index 75ba990db..ce56ec0f5 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -8,12 +8,12 @@ const _BUFFER_SIZE = 1<<12; -const StringBuffer = union { +type StringBuffer union { Static {buf: []u8}, Dynamic{buf: [dynamic]u8}, } -const FmtInfo = struct { +type FmtInfo struct { minus: bool, plus: bool, space: bool, @@ -582,8 +582,8 @@ proc _fmt_int(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: int, _pad(fi, s); } -immutable var __DIGITS_LOWER = "0123456789abcdefx"; -immutable var __DIGITS_UPPER = "0123456789ABCDEFX"; +let __DIGITS_LOWER = "0123456789abcdefx"; +let __DIGITS_UPPER = "0123456789ABCDEFX"; proc fmt_rune(fi: ^FmtInfo, r: rune, verb: rune) { match verb { diff --git a/core/math.odin b/core/math.odin index c8617ef98..6cd4556c1 100644 --- a/core/math.odin +++ b/core/math.odin @@ -16,16 +16,16 @@ const EPSILON = 1.19209290e-7; const τ = TAU; const π = PI; -const Vec2 = [vector 2]f32; -const Vec3 = [vector 3]f32; -const Vec4 = [vector 4]f32; +type Vec2 [vector 2]f32; +type Vec3 [vector 3]f32; +type Vec4 [vector 4]f32; // Column major -const Mat2 = [2][2]f32; -const Mat3 = [3][3]f32; -const Mat4 = [4][4]f32; +type Mat2 [2][2]f32; +type Mat3 [3][3]f32; +type Mat4 [4][4]f32; -const Complex = complex64; +type Complex complex64; proc sqrt(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32"; proc sqrt(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64"; diff --git a/core/mem.odin b/core/mem.odin index e1e22c0b2..90b9a26e5 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -50,7 +50,7 @@ proc align_forward(ptr: rawptr, align: int) -> rawptr { -const AllocationHeader = struct { +type AllocationHeader struct { size: int, } @@ -78,14 +78,14 @@ proc allocation_header(data: rawptr) -> ^AllocationHeader { // Custom allocators -const Arena = struct { +type Arena struct { backing: Allocator, offset: int, memory: []u8, temp_count: int, } -const ArenaTempMemory = struct { +type ArenaTempMemory struct { arena: ^Arena, original_count: int, } diff --git a/core/os_linux.odin b/core/os_linux.odin index 97f41e611..8d9405ecd 100644 --- a/core/os_linux.odin +++ b/core/os_linux.odin @@ -1,9 +1,9 @@ // #import "fmt.odin"; #import "strings.odin"; -const Handle = i32; -const FileTime = u64; -const Errno = i32; +type Handle i32; +type FileTime u64; +type Errno i32; // INVALID_HANDLE: Handle : -1; @@ -34,9 +34,9 @@ const RTLD_BINDING_MASK = 0x3; const RTLD_GLOBAL = 0x100; // "Argv" arguments converted to Odin strings -immutable var args = _alloc_command_line_arguments(); +let args = _alloc_command_line_arguments(); -const _FileTime = struct #ordered { +type _FileTime struct #ordered { seconds: i64, nanoseconds: i32, reserved: i32, @@ -46,7 +46,7 @@ const _FileTime = struct #ordered { // https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6/+/jb-dev/sysroot/usr/include/bits/stat.h // Validity is not guaranteed. -const Stat = struct #ordered { +type Stat struct #ordered { device_id: u64, // ID of device containing file serial: u64, // File serial number nlink: u32, // Number of hard links diff --git a/core/os_windows.odin b/core/os_windows.odin index 473690661..c1a31ff50 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -1,8 +1,8 @@ #import win32 "sys/windows.odin"; -const Handle = int; -const FileTime = u64; -const Errno = int; +type Handle int; +type FileTime u64; +type Errno int; const INVALID_HANDLE: Handle = -1; @@ -49,7 +49,7 @@ const ERROR_FILE_IS_PIPE: Errno = 1<<29 + 0; // "Argv" arguments converted to Odin strings -immutable var args = _alloc_command_line_arguments(); +let args = _alloc_command_line_arguments(); proc open(path: string, mode: int, perm: u32) -> (Handle, Errno) { diff --git a/core/os_x.odin b/core/os_x.odin index 4135e2574..3b591e19c 100644 --- a/core/os_x.odin +++ b/core/os_x.odin @@ -1,12 +1,12 @@ #import "fmt.odin"; #import "strings.odin"; -const Handle = i32; -const FileTime = u64; -const Errno = int; +type Handle i32; +type FileTime u64; +type Errno int; // TODO(zangent): Find out how to make this work on x64 and x32. -const AddressSize = i64; +type AddressSize i64; // INVALID_HANDLE: Handle : -1; @@ -41,12 +41,12 @@ const RTLD_FIRST = 0x100; var args: [dynamic]string; -const _FileTime = struct #ordered { +type _FileTime struct #ordered { seconds: i64, nanoseconds: i64 } -const Stat = struct #ordered { +type Stat struct #ordered { device_id : i32, // ID of device containing file mode : u16, // Mode of the file nlink : u16, // Number of hard links diff --git a/core/raw.odin b/core/raw.odin index 5c8c79dff..3a9048bb4 100644 --- a/core/raw.odin +++ b/core/raw.odin @@ -1,27 +1,27 @@ -const Any = struct #ordered { +type Any struct #ordered { data: rawptr, type_info: ^TypeInfo, -} +}; -const String = struct #ordered { +type String struct #ordered { data: ^u8, len: int, }; -const Slice = struct #ordered { +type Slice struct #ordered { data: rawptr, len: int, cap: int, }; -const DynamicArray = struct #ordered { +type DynamicArray struct #ordered { data: rawptr, len: int, cap: int, allocator: Allocator, }; -const DynamicMap = struct #ordered { +type DynamicMap struct #ordered { hashes: [dynamic]int, entries: DynamicArray, }; diff --git a/core/strconv.odin b/core/strconv.odin index db5493fc5..e129241a3 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -1,6 +1,6 @@ #import . "decimal.odin"; -const IntFlag = enum { +type IntFlag enum { Prefix = 1<<0, Plus = 1<<1, Space = 1<<2, @@ -210,14 +210,14 @@ proc append_float(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string { -const DecimalSlice = struct { +type DecimalSlice struct { digits: []u8, count: int, decimal_point: int, neg: bool, } -const Float_Info = struct { +type Float_Info struct { mantbits: uint, expbits: uint, bias: int, @@ -415,7 +415,7 @@ proc round_shortest(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) { } const MAX_BASE = 32; -immutable var digits = "0123456789abcdefghijklmnopqrstuvwxyz"; +let digits = "0123456789abcdefghijklmnopqrstuvwxyz"; proc is_integer_negative(u: u128, is_signed: bool, bit_size: int) -> (unsigned: u128, neg: bool) { diff --git a/core/sync_linux.odin b/core/sync_linux.odin index f7a62adcf..228fb16b3 100644 --- a/core/sync_linux.odin +++ b/core/sync_linux.odin @@ -1,11 +1,11 @@ #import "atomics.odin"; #import "os.odin"; -const Semaphore = struct { +type Semaphore struct { // _handle: win32.Handle, } -const Mutex = struct { +type Mutex struct { _semaphore: Semaphore, _counter: i32, _owner: i32, diff --git a/core/sync_windows.odin b/core/sync_windows.odin index ca4d88000..e0ede4943 100644 --- a/core/sync_windows.odin +++ b/core/sync_windows.odin @@ -1,11 +1,11 @@ #import win32 "sys/windows.odin" when ODIN_OS == "windows"; #import "atomics.odin"; -const Semaphore = struct { +type Semaphore struct { _handle: win32.Handle, } -const Mutex = struct { +type Mutex struct { _semaphore: Semaphore, _counter: i32, _owner: i32, diff --git a/core/sys/wgl.odin b/core/sys/wgl.odin index 19d8e0cfd..5d373578a 100644 --- a/core/sys/wgl.odin +++ b/core/sys/wgl.odin @@ -9,10 +9,10 @@ const CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002; const CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001; const CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002; -const Hglrc = Handle; -const ColorRef = u32; +type Hglrc Handle; +type ColorRef u32; -const LayerPlaneDescriptor = struct { +type LayerPlaneDescriptor struct { size: u16, version: u16, flags: u32, @@ -39,11 +39,11 @@ const LayerPlaneDescriptor = struct { transparent: ColorRef, } -const PointFloat = struct { +type PointFloat struct { x, y: f32, } -const Glyph_MetricsFloat = struct { +type Glyph_MetricsFloat struct { black_box_x: f32, black_box_y: f32, glyph_origin: PointFloat, @@ -51,10 +51,10 @@ const Glyph_MetricsFloat = struct { cell_inc_y: f32, } -const CreateContextAttribsARBType = type proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc; -const ChoosePixelFormatARBType = type proc(hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool #cc_c; -const SwapIntervalEXTType = type proc(interval: i32) -> bool #cc_c; -const GetExtensionsStringARBType = type proc(Hdc) -> ^u8 #cc_c; +type CreateContextAttribsARBType proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc; +type ChoosePixelFormatARBType proc(hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool #cc_c; +type SwapIntervalEXTType proc(interval: i32) -> bool #cc_c; +type GetExtensionsStringARBType proc(Hdc) -> ^u8 #cc_c; var create_context_attribs_arb: CreateContextAttribsARBType; diff --git a/core/sys/windows.odin b/core/sys/windows.odin index c3c3b8b38..e4e4a4a32 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -4,21 +4,21 @@ #foreign_system_library "winmm.lib" when ODIN_OS == "windows"; #foreign_system_library "shell32.lib" when ODIN_OS == "windows"; -const Handle = rawptr; -const Hwnd = Handle; -const Hdc = Handle; -const Hinstance = Handle; -const Hicon = Handle; -const Hcursor = Handle; -const Hmenu = Handle; -const Hbrush = Handle; -const Hgdiobj = Handle; -const Hmodule = Handle; -const Wparam = uint; -const Lparam = int; -const Lresult = int; -const Bool = i32; -const WndProc = type proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c; +type Handle rawptr; +type Hwnd Handle; +type Hdc Handle; +type Hinstance Handle; +type Hicon Handle; +type Hcursor Handle; +type Hmenu Handle; +type Hbrush Handle; +type Hgdiobj Handle; +type Hmodule Handle; +type Wparam uint; +type Lparam int; +type Lresult int; +type Bool i32; +type WndProc proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c; const INVALID_HANDLE = Handle(~int(0)); @@ -86,11 +86,11 @@ const SM_CYSCREEN = 1; const SW_SHOW = 5; -const Point = struct #ordered { +type Point struct #ordered { x, y: i32, } -const WndClassExA = struct #ordered { +type WndClassExA struct #ordered { size, style: u32, wnd_proc: WndProc, cls_extra, wnd_extra: i32, @@ -102,7 +102,7 @@ const WndClassExA = struct #ordered { sm: Hicon, } -const Msg = struct #ordered { +type Msg struct #ordered { hwnd: Hwnd, message: u32, wparam: Wparam, @@ -111,24 +111,24 @@ const Msg = struct #ordered { pt: Point, } -const Rect = struct #ordered { +type Rect struct #ordered { left: i32, top: i32, right: i32, bottom: i32, } -const Filetime = struct #ordered { +type Filetime struct #ordered { lo, hi: u32, } -const Systemtime = struct #ordered { +type Systemtime struct #ordered { year, month: u16, day_of_week, day: u16, hour, minute, second, millisecond: u16, } -const ByHandleFileInformation = struct #ordered { +type ByHandleFileInformation struct #ordered { file_attributes: u32, creation_time, last_access_time, @@ -141,7 +141,7 @@ const ByHandleFileInformation = struct #ordered { file_index_low: u32, } -const FileAttributeData = struct #ordered { +type FileAttributeData struct #ordered { file_attributes: u32, creation_time, last_access_time, @@ -150,7 +150,7 @@ const FileAttributeData = struct #ordered { file_size_low: u32, } -const FindData = struct #ordered { +type FindData struct #ordered { file_attributes : u32, creation_time : Filetime, last_access_time : Filetime, @@ -164,7 +164,7 @@ const FindData = struct #ordered { } -const GET_FILEEX_INFO_LEVELS = i32; +type GET_FILEEX_INFO_LEVELS i32; const GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS = 0; const GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS = 1; @@ -323,7 +323,7 @@ const HEAP_ZERO_MEMORY = 0x00000008; // Synchronization -const Security_Attributes = struct #ordered { +type Security_Attributes struct #ordered { length: u32, security_descriptor: rawptr, inherit_handle: Bool, @@ -357,7 +357,7 @@ proc read_barrier () #foreign kernel32 "ReadBarrier"; -const Hmonitor = Handle; +type Hmonitor Handle; const GWL_STYLE = -16; @@ -374,14 +374,14 @@ const SWP_NOSIZE = 0x0001; const SWP_NOMOVE = 0x0002; -const MonitorInfo = struct #ordered { +type MonitorInfo struct #ordered { size: u32, monitor: Rect, work: Rect, flags: u32, } -const WindowPlacement = struct #ordered { +type WindowPlacement struct #ordered { length: u32, flags: u32, show_cmd: u32, @@ -418,7 +418,7 @@ proc LOWORD(lParam: Lparam) -> u16 { return u16(lParam); } -const BitmapInfoHeader = struct #ordered { +type BitmapInfoHeader struct #ordered { size: u32, width, height: i32, planes, bit_count: i16, @@ -429,13 +429,13 @@ const BitmapInfoHeader = struct #ordered { clr_used: u32, clr_important: u32, } -const BitmapInfo = struct #ordered { +type BitmapInfo struct #ordered { using header: BitmapInfoHeader, colors: [1]RgbQuad, } -const RgbQuad = struct #ordered { blue, green, red, reserved: u8 } +type RgbQuad struct #ordered { blue, green, red, reserved: u8 } const BI_RGB = 0; const DIB_RGB_COLORS = 0x00; @@ -481,7 +481,7 @@ const PFD_DOUBLEBUFFER_DONTCARE = 0x40000000; const PFD_STEREO_DONTCARE = 0x80000000; -const PixelFormatDescriptor = struct #ordered { +type PixelFormatDescriptor struct #ordered { size, version, flags: u32, @@ -519,7 +519,7 @@ proc swap_buffers (hdc: Hdc) -> Bool proc release_dc (wnd: Hwnd, hdc: Hdc) -> i32 #foreign user32 "ReleaseDC"; -const Proc = type proc() #cc_c; +type Proc proc() #cc_c; const MAPVK_VK_TO_CHAR = 2; const MAPVK_VK_TO_VSC = 0; @@ -533,7 +533,7 @@ proc get_async_key_state(v_key: i32) -> i16 #foreign user32 "GetAsyncKeyState"; proc is_key_down(key: KeyCode) -> bool #inline { return get_async_key_state(i32(key)) < 0; } -const KeyCode = enum i32 { +type KeyCode enum i32 { Lbutton = 0x01, Rbutton = 0x02, Cancel = 0x03, diff --git a/core/utf8.odin b/core/utf8.odin index 8b227c42e..a100423a2 100644 --- a/core/utf8.odin +++ b/core/utf8.odin @@ -28,9 +28,9 @@ const RUNE3_MAX = 1<<16 - 1; const LOCB = 0b1000_0000; const HICB = 0b1011_1111; -const AcceptRange = struct { lo, hi: u8 } +type AcceptRange struct { lo, hi: u8 } -immutable var accept_ranges = [5]AcceptRange{ +let accept_ranges = [5]AcceptRange{ {0x80, 0xbf}, {0xa0, 0xbf}, {0x80, 0x9f}, @@ -38,7 +38,7 @@ immutable var accept_ranges = [5]AcceptRange{ {0x80, 0x8f}, }; -immutable var accept_sizes = [256]u8{ +let accept_sizes = [256]u8{ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f diff --git a/src/check_decl.cpp b/src/check_decl.cpp index a4562404e..c4927bdd6 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -178,6 +178,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, if (init != NULL) { check_expr_or_type(c, &operand, init); } +#if 0 if (operand.mode == Addressing_Type) { e->kind = Entity_TypeName; @@ -186,6 +187,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, check_type_decl(c, e, d->type_expr, named_type); return; } +#endif check_init_constant(c, e, &operand); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 9aa5fd211..65a6387f8 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1538,7 +1538,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { case_ast_node(vd, ValueDecl, node); GB_ASSERT(!c->context.scope->is_file); - if (vd->token.kind != Token_var) { + if (vd->token.kind == Token_const) { // NOTE(bill): Handled elsewhere } else { Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count); diff --git a/src/checker.cpp b/src/checker.cpp index cded54d7f..26ef9992f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1451,7 +1451,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco case_end; case_ast_node(vd, ValueDecl, decl); - if (vd->token.kind == Token_var) { + if (vd->token.kind != Token_const) { if (!c->context.scope->is_file) { // NOTE(bill): local scope -> handle later and in order break; @@ -1527,30 +1527,30 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco Entity *e = NULL; AstNode *up_init = unparen_expr(init); - if (up_init != NULL && is_ast_node_type(up_init)) { - AstNode *type = up_init; - e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL); - // TODO(bill): What if vd->type != NULL??? How to handle this case? - d->type_expr = type; - d->init_expr = type; - } else if (up_init != NULL && up_init->kind == AstNode_Alias) { - #if 1 - error_node(up_init, "#alias declarations are not yet supported"); - continue; - #else - e = make_entity_alias(c->allocator, d->scope, name->Ident, NULL, EntityAlias_Invalid, NULL); - d->type_expr = vd->type; - d->init_expr = up_init->Alias.expr; - #endif - // } else if (init != NULL && up_init->kind == AstNode_ProcLit) { - // e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags); - // d->proc_lit = up_init; - // d->type_expr = vd->type; - } else { + // if (up_init != NULL && is_ast_node_type(up_init)) { + // AstNode *type = up_init; + // e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL); + // // TODO(bill): What if vd->type != NULL??? How to handle this case? + // d->type_expr = type; + // d->init_expr = type; + // } else if (up_init != NULL && up_init->kind == AstNode_Alias) { + // #if 1 + // error_node(up_init, "#alias declarations are not yet supported"); + // continue; + // #else + // e = make_entity_alias(c->allocator, d->scope, name->Ident, NULL, EntityAlias_Invalid, NULL); + // d->type_expr = vd->type; + // d->init_expr = up_init->Alias.expr; + // #endif + // // } else if (init != NULL && up_init->kind == AstNode_ProcLit) { + // // e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags); + // // d->proc_lit = up_init; + // // d->type_expr = vd->type; + // } else { e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, empty_exact_value); d->type_expr = vd->type; d->init_expr = init; - } + // } GB_ASSERT(e != NULL); e->identifier = name; @@ -1579,6 +1579,27 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco add_entity_and_decl_info(c, name, e, d); case_end; + case_ast_node(td, TypeDecl, decl); + AstNode *name = td->name; + if (name->kind != AstNode_Ident) { + error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); + break; + } + + + DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl); + Entity *e = NULL; + + AstNode *type = unparen_expr(td->type); + e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL); + // TODO(bill): What if vd->type != NULL??? How to handle this case? + d->type_expr = type; + d->init_expr = type; + + e->identifier = name; + add_entity_and_decl_info(c, name, e, d); + case_end; + case_ast_node(id, ImportDecl, decl); if (!c->context.scope->is_file) { if (id->is_import) { diff --git a/src/ir.cpp b/src/ir.cpp index 8acc7d3bf..abf2d80be 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5813,7 +5813,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { case_end; case_ast_node(vd, ValueDecl, node); - if (vd->token.kind == Token_var) { + if (vd->token.kind != Token_const) { irModule *m = proc->module; gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); @@ -5862,30 +5862,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { } gb_temp_arena_memory_end(tmp); - } else { - for_array(i, vd->names) { - AstNode *ident = vd->names[i]; - GB_ASSERT(ident->kind == AstNode_Ident); - Entity *e = entity_of_ident(proc->module->info, ident); - GB_ASSERT(e != NULL); - switch (e->kind) { - case Entity_TypeName: { - // NOTE(bill): Generate a new name - // parent_proc.name-guid - String ts_name = e->token.string; - isize name_len = proc->name.len + 1 + ts_name.len + 1 + 10 + 1; - u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len); - i32 guid = cast(i32)proc->module->members.entries.count; - name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(ts_name), guid); - String name = make_string(name_text, name_len-1); - - irValue *value = ir_value_type_name(proc->module->allocator, - name, e->type); - map_set(&proc->module->entity_names, hash_pointer(e), name); - ir_gen_global_type_name(proc->module, e, name); - } break; - } - } } case_end; @@ -5960,6 +5936,28 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { } case_end; + case_ast_node(td, TypeDecl, node); + AstNode *ident = td->name; + GB_ASSERT(ident->kind == AstNode_Ident); + Entity *e = entity_of_ident(proc->module->info, ident); + GB_ASSERT(e != NULL); + if (e->kind == Entity_TypeName) { + // NOTE(bill): Generate a new name + // parent_proc.name-guid + String ts_name = e->token.string; + isize name_len = proc->name.len + 1 + ts_name.len + 1 + 10 + 1; + u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len); + i32 guid = cast(i32)proc->module->members.entries.count; + name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(ts_name), guid); + String name = make_string(name_text, name_len-1); + + irValue *value = ir_value_type_name(proc->module->allocator, + name, e->type); + map_set(&proc->module->entity_names, hash_pointer(e), name); + ir_gen_global_type_name(proc->module, e, name); + } + case_end; + case_ast_node(as, AssignStmt, node); ir_emit_comment(proc, str_lit("AssignStmt")); diff --git a/src/parser.cpp b/src/parser.cpp index 4f63d17f6..09dbc77d7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -314,6 +314,11 @@ AST_NODE_KIND(_DeclBegin, "", i32) \ String foreign_name; \ String link_name; \ }) \ + AST_NODE_KIND(TypeDecl, "type declaration", struct { \ + Token token; \ + AstNode *name; \ + AstNode *type; \ + }) \ AST_NODE_KIND(ImportDecl, "import declaration", struct { \ Token token; \ bool is_import; \ @@ -1446,6 +1451,14 @@ AstNode *ast_proc_decl(AstFile *f, Token token, AstNode *name, AstNode *type, As return result; } +AstNode *ast_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) { + AstNode *result = make_ast_node(f, AstNode_TypeDecl); + result->TypeDecl.token = token; + result->TypeDecl.name = name; + result->TypeDecl.type = type; + return result; +} + AstNode *ast_import_decl(AstFile *f, Token token, bool is_import, Token relpath, Token import_name, AstNode *cond) { AstNode *result = make_ast_node(f, AstNode_ImportDecl); @@ -1590,6 +1603,11 @@ void fix_advance_to_next_stmt(AstFile *f) { case Token_Semicolon: return; + case Token_var: + case Token_const: + case Token_let: + case Token_type: + case Token_if: case Token_when: case Token_return: @@ -1597,7 +1615,6 @@ void fix_advance_to_next_stmt(AstFile *f) { case Token_defer: case Token_asm: case Token_using: - case Token_immutable: // case Token_thread_local: // case Token_no_alias: @@ -1671,9 +1688,12 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) { return s->ProcLit.body != NULL; case AstNode_ProcDecl: return s->ProcDecl.body != NULL; + case AstNode_TypeDecl: + return is_semicolon_optional_for_node(f, s->TypeDecl.type); + case AstNode_ValueDecl: - if (s->ValueDecl.token.kind != Token_var) { + if (s->ValueDecl.token.kind != Token_const) { if (s->ValueDecl.values.count > 0) { AstNode *last = s->ValueDecl.values[s->ValueDecl.values.count-1]; return is_semicolon_optional_for_node(f, last); @@ -2511,7 +2531,7 @@ AstNode *parse_value_decl(AstFile *f, Token token) { Array lhs = parse_lhs_expr_list(f); AstNode *type = NULL; Array values = {}; - bool is_mutable = token.kind == Token_var; + bool is_mutable = token.kind != Token_const; if (allow_token(f, Token_Colon)) { type = parse_type(f); @@ -2551,12 +2571,14 @@ AstNode *parse_value_decl(AstFile *f, Token token) { values = make_ast_node_array(f); } + Array specs = {}; array_init(&specs, heap_allocator(), 1); - // Token token = ast_node_token(lhs[0]); - // token.kind = is_mutable ? Token_var : Token_const; - // token.string = is_mutable ? str_lit("var") : str_lit("const"); - return ast_value_decl(f, token, lhs, type, values); + AstNode *decl = ast_value_decl(f, token, lhs, type, values); + if (token.kind == Token_let) { + decl->ValueDecl.flags |= VarDeclFlag_immutable; + } + return decl; } AstNode *parse_proc_decl(AstFile *f) { @@ -2583,6 +2605,13 @@ AstNode *parse_proc_decl(AstFile *f) { return ast_proc_decl(f, token, name, type, body, tags, foreign_library, foreign_name, link_name); } +AstNode *parse_type_decl(AstFile *f) { + Token token = expect_token(f, Token_type); + AstNode *name = parse_ident(f); + AstNode *type = parse_type(f); + return ast_type_decl(f, token, name, type); +} + AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { @@ -2590,6 +2619,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { switch (f->curr_token.kind) { case Token_var: case Token_const: + case Token_let: next_token(f); return parse_value_decl(f, token); } @@ -2783,7 +2813,7 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) { case Token_using: return FieldPrefix_Using; - case Token_immutable: + case Token_let: return FieldPrefix_Immutable; case Token_Hash: { @@ -3686,6 +3716,7 @@ AstNode *parse_stmt(AstFile *f) { case Token_var: case Token_const: + case Token_let: s = parse_simple_stmt(f, StmtAllowFlag_None); expect_semicolon(f, s); return s; @@ -3695,6 +3726,11 @@ AstNode *parse_stmt(AstFile *f) { expect_semicolon(f, s); return s; + case Token_type: + s = parse_type_decl(f); + expect_semicolon(f, s); + return s; + case Token_if: return parse_if_stmt(f); case Token_when: return parse_when_stmt(f); @@ -3722,27 +3758,30 @@ AstNode *parse_stmt(AstFile *f) { case Token_using: { // TODO(bill): Make using statements better Token token = expect_token(f, Token_using); - Array list = parse_lhs_expr_list(f); - if (list.count == 0) { - syntax_error(token, "Illegal use of `using` statement"); - expect_semicolon(f, NULL); - return ast_bad_stmt(f, token, f->curr_token); + AstNode *decl = NULL; + if (f->curr_token.kind == Token_var || + f->curr_token.kind == Token_let) { + Token var = f->curr_token; next_token(f); + decl = parse_value_decl(f, var); + expect_semicolon(f, decl); + } else { + Array list = parse_lhs_expr_list(f); + if (list.count == 0) { + syntax_error(token, "Illegal use of `using` statement"); + expect_semicolon(f, NULL); + return ast_bad_stmt(f, token, f->curr_token); + } + + if (f->curr_token.kind != Token_Colon) { + expect_semicolon(f, list[list.count-1]); + return ast_using_stmt(f, token, list); + } } - if (f->curr_token.kind != Token_Colon) { - expect_semicolon(f, list[list.count-1]); - return ast_using_stmt(f, token, list); - } - Token var = ast_node_token(list[0]); - var.kind = Token_var; - var.string = str_lit("var"); - AstNode *decl = parse_value_decl(f, var); - expect_semicolon(f, decl); - - if (decl->kind == AstNode_ValueDecl) { + if (decl != NULL && decl->kind == AstNode_ValueDecl) { #if 1 - if (decl->ValueDecl.token.kind != Token_var) { + if (decl->ValueDecl.token.kind == Token_const) { syntax_error(token, "`using` may not be applied to constant declarations"); return decl; } @@ -3761,13 +3800,13 @@ AstNode *parse_stmt(AstFile *f) { return ast_bad_stmt(f, token, f->curr_token); } break; -#if 1 +#if 0 case Token_immutable: { Token token = expect_token(f, Token_immutable); AstNode *node = parse_stmt(f); if (node->kind == AstNode_ValueDecl) { - if (node->ValueDecl.token.kind != Token_var) { + if (node->ValueDecl.token.kind == Token_const) { syntax_error(token, "`immutable` may not be applied to constant declarations"); } else { node->ValueDecl.flags |= VarDeclFlag_immutable; @@ -3939,7 +3978,7 @@ AstNode *parse_stmt(AstFile *f) { AstNode *s = parse_stmt(f); if (s->kind == AstNode_ValueDecl) { - if (s->ValueDecl.token.kind != Token_var) { + if (s->ValueDecl.token.kind == Token_const) { syntax_error(token, "`thread_local` may not be applied to constant declarations"); } if (f->curr_proc != NULL) { diff --git a/src/ssa.cpp b/src/ssa.cpp index c048c298b..18de4d767 100644 --- a/src/ssa.cpp +++ b/src/ssa.cpp @@ -1969,7 +1969,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) { case_end; case_ast_node(vd, ValueDecl, node); - if (vd->token.kind == Token_var) { + if (vd->token.kind != Token_const) { ssaModule *m = p->module; gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); if (vd->values.count == 0) { diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 425cd6a1d..d1ea26da7 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -83,6 +83,7 @@ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \ \ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_var, "var"), \ + TOKEN_KIND(Token_let, "let"), \ TOKEN_KIND(Token_const, "const"), \ TOKEN_KIND(Token_type, "type"), \ TOKEN_KIND(Token_when, "when"), \ @@ -109,7 +110,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_dynamic, "dynamic"), \ TOKEN_KIND(Token_map, "map"), \ TOKEN_KIND(Token_using, "using"), \ - TOKEN_KIND(Token_immutable, "immutable"), \ TOKEN_KIND(Token_context, "context"), \ TOKEN_KIND(Token_push_context, "push_context"), \ TOKEN_KIND(Token_push_allocator, "push_allocator"), \