From 70f02878ae0579bcfb616aa625ed05df3e5a95ba Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 5 Jul 2021 22:26:44 -0500 Subject: [PATCH] bugfix and added to immediate rendering capability --- bin/onyx | Bin 409256 -> 409256 bytes docs/plan | 2 +- docs/todo | 2 +- modules/immediate_mode/canvas.onyx | 39 +++++++ .../immediate_mode/immediate_renderer.onyx | 100 ++++++++++++++++-- modules/immediate_mode/module.onyx | 4 + modules/immediate_mode/texture.onyx | 49 +++++++++ modules/ui/ui.onyx | 16 +-- modules/webgl2/webgl2.js | 48 +++++++-- modules/webgl2/webgl2.onyx | 6 +- src/onyxutils.c | 28 ++--- 11 files changed, 246 insertions(+), 48 deletions(-) create mode 100644 modules/immediate_mode/canvas.onyx create mode 100644 modules/immediate_mode/texture.onyx diff --git a/bin/onyx b/bin/onyx index efef128ab1ec0ceca6109f640c765b04e2ded42f..4248b85a435d768c33cdd750450cbac28a68f8c7 100755 GIT binary patch delta 31191 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 diff --git a/docs/plan b/docs/plan index 081487fd..116ef9e7 100644 --- a/docs/plan +++ b/docs/plan @@ -34,7 +34,7 @@ HOW: I have a working compiler with many features, but here are some additional features I would like to consider adding in the future. - [ ] Put type info in data section so it is runtime accessible + [X] Put type info in data section so it is runtime accessible - type name - size - alignment diff --git a/docs/todo b/docs/todo index cdbeaf3b..f7eab465 100644 --- a/docs/todo +++ b/docs/todo @@ -11,7 +11,7 @@ Command Line Interface: [X] Remove old code from CLI logic [X] Add statistic printing - [ ] Fix documentation generation (broken since compiler architecture change) + [X] Fix documentation generation (broken since compiler architecture change) [ ] Add automated running component - Store to temporary file (OS independent) - Detect / choose WASM backend diff --git a/modules/immediate_mode/canvas.onyx b/modules/immediate_mode/canvas.onyx new file mode 100644 index 00000000..6e9d88af --- /dev/null +++ b/modules/immediate_mode/canvas.onyx @@ -0,0 +1,39 @@ +package immediate_mode + +use package core + +// A render target that can be used instead of the default +Canvas :: struct { + color_texture : Texture; + depth_stencil_buffer : gl.GLRenderbuffer; + framebuffer : gl.GLFramebuffer; + + width, height: i32; +} + +create_canvas :: (width: i32, height: i32) -> Canvas { + + color_texture := create_texture(width, height, gl.RGBA8); + + depth_stencil_buffer := gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, depth_stencil_buffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, width, height); + gl.bindRenderbuffer(gl.RENDERBUFFER, -1); + + framebuffer := gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, color_texture.texture, 0); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depth_stencil_buffer); + gl.bindFramebuffer(gl.FRAMEBUFFER, -1); + + assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE, "Framebuffer not complete!"); + + return .{ + color_texture = color_texture, + depth_stencil_buffer = depth_stencil_buffer, + framebuffer = framebuffer, + width = width, + height = height, + }; +} + diff --git a/modules/immediate_mode/immediate_renderer.onyx b/modules/immediate_mode/immediate_renderer.onyx index 302f6482..1f750c50 100644 --- a/modules/immediate_mode/immediate_renderer.onyx +++ b/modules/immediate_mode/immediate_renderer.onyx @@ -1,7 +1,7 @@ package immediate_mode use package core -#private_file gl :: package gl +use package core.intrinsics.onyx { __initialize } Vector2 :: struct { x, y: f32; @@ -12,6 +12,11 @@ Color4 :: struct { a: f32 = 1; } +Immediate_Mode :: enum { + Triangles; + Lines; +} + Immediate_Vertex :: struct { position : Vector2; color : Color4; @@ -19,7 +24,6 @@ Immediate_Vertex :: struct { } Immediate_Renderer :: struct { - // Will point to either the simple_shader or the textured_shader. active_shader : ^Shader; simple_shader, textured_shader : Shader; @@ -28,7 +32,8 @@ Immediate_Renderer :: struct { // 'verticies' contains the vertex data and the maximum number of verticies // that can be rendered at a given time. 'vertex_count' is used to store how // many verticies will be rendered in the next draw call. 'vertex_count' is - // expected to be a multiple of 3, given that triangles are being rendered. + // expected to be a multiple of 3 or 2, given that triangles or lines are + // being rendered. verticies : [] Immediate_Vertex; vertex_count : u32; @@ -37,11 +42,18 @@ Immediate_Renderer :: struct { vertex_array : gl.GLVertexArrayObject; vertex_buffer : gl.GLBuffer; - // Needs to be a multiple of 3!! - Default_Max_Verticies :: 1023; + // Needs to be a multiple of 6!! + Default_Max_Verticies :: 1020; + + mode := Immediate_Mode.Triangles; + + canvas: ^Canvas = null; + + window_width, window_height: i32; make :: (max_verticies := Default_Max_Verticies) -> Immediate_Renderer { ir : Immediate_Renderer; + __initialize(^ir); init(^ir, max_verticies); return ir; @@ -120,9 +132,15 @@ Immediate_Renderer :: struct { gl.bufferSubData(gl.ARRAY_BUFFER, 0, .{ count = vertex_count * sizeof Immediate_Vertex, data = ~~verticies.data }); gl.bindBuffer(gl.ARRAY_BUFFER, -1); + gl_mode : gl.GLenum; + switch mode { + case .Triangles do gl_mode = gl.TRIANGLES; + case .Lines do gl_mode = gl.LINES; + } + gl.useProgram(active_shader.program); gl.bindVertexArray(vertex_array); - gl.drawArrays(gl.TRIANGLES, 0, vertex_count); + gl.drawArrays(gl_mode, 0, vertex_count); gl.bindVertexArray(-1); vertex_count = 0; @@ -267,6 +285,45 @@ Immediate_Renderer :: struct { gl.disable(gl.SCISSOR_TEST); } } + + set_mode :: (use ir: ^Immediate_Renderer, new_mode: Immediate_Mode) { + if mode != new_mode { + ir->flush(); + mode = new_mode; + } + } + + use_canvas :: (use ir: ^Immediate_Renderer, new_canvas: ^Canvas) { + if canvas == new_canvas do return; + ir->flush(); + + canvas = new_canvas; + if canvas != null { + gl.bindFramebuffer(gl.FRAMEBUFFER, canvas.framebuffer); + gl.viewport(0, 0, canvas.width, canvas.height); + + @Note // This flips the projection because generally with using framebuffers as textures, + // the bottom left, (0, 0) in WebGL world, you want to be the top left when you render it. + ir->use_ortho_projection(0, ~~canvas.width, ~~canvas.height, 0); + + } else { + gl.bindFramebuffer(gl.FRAMEBUFFER, -1); + gl.viewport(0, 0, window_width, window_height); + ir->use_ortho_projection(0, ~~window_width, 0, ~~window_height); + } + } + + set_window_size :: (use ir: ^Immediate_Renderer, width: i32, height: i32) { + window_width = width; + window_height = height; + + // If there is no active canvas, immediately update the values. + // Maybe this should flush the current buffer first? + if canvas == null { + gl.viewport(0, 0, window_width, window_height); + ir->use_ortho_projection(0, ~~window_width, 0, ~~window_height); + } + } } @@ -280,7 +337,7 @@ Immediate_Renderer :: struct { immediate_renderer : Immediate_Renderer; immediate_renderer_init :: () { - Immediate_Renderer.init(^immediate_renderer); + immediate_renderer = Immediate_Renderer.make(); } immediate_renderer_free :: () { @@ -306,7 +363,20 @@ circle :: (center: Vector2, radius: f32, color: Color4 = .{1,1,1}, segments := 1 flush :: () do immediate_renderer->flush(); -set_texture :: (texture_id: i32 = -1) do immediate_renderer->set_texture(texture_id); +set_texture :: #match { + (texture_id: i32 = -1) { immediate_renderer->set_texture(texture_id); }, + (texture: ^Texture, texture_index := 0) { + immediate_renderer->set_texture(texture_index); + + if texture_index >= 0 { + gl.activeTexture(gl.TEXTURE0 + texture_index); + gl.bindTexture(gl.TEXTURE_2D, texture.texture); + + } else { + gl.bindTexture(gl.TEXTURE_2D, -1); + } + } +} use_ortho_projection :: (left: f32, right: f32, top: f32, bottom: f32) { immediate_renderer->use_ortho_projection(left, right, top, bottom); @@ -322,4 +392,16 @@ scissor :: (x: f32, y: f32, w: f32, h: f32) { scissor_disable :: () { immediate_renderer->scissor_disable(); -} \ No newline at end of file +} + +set_mode :: (mode: Immediate_Mode) { + immediate_renderer->set_mode(mode); +} + +use_canvas :: (canvas: ^Canvas) { + immediate_renderer->use_canvas(canvas); +} + +set_window_size :: (width: i32, height: i32) { + immediate_renderer->set_window_size(width, height); +} diff --git a/modules/immediate_mode/module.onyx b/modules/immediate_mode/module.onyx index fc992e23..3c72307f 100644 --- a/modules/immediate_mode/module.onyx +++ b/modules/immediate_mode/module.onyx @@ -3,3 +3,7 @@ package immediate_mode #load "./immediate_renderer" #load "./gl_utils" +#load "./canvas" +#load "./texture" + +#private gl :: package gl diff --git a/modules/immediate_mode/texture.onyx b/modules/immediate_mode/texture.onyx new file mode 100644 index 00000000..9982e134 --- /dev/null +++ b/modules/immediate_mode/texture.onyx @@ -0,0 +1,49 @@ +package immediate_mode + +use package core + +Texture :: struct { + texture : gl.GLTexture; + + width, height: i32; +} + +create_texture :: (width: i32, height: i32, format: gl.GLenum) -> Texture { + texture := gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texStorage2D(gl.TEXTURE_2D, 1, format, width, height); + + // Setting some reasonable defaults for the texture parameters + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + gl.bindTexture(gl.TEXTURE_2D, -1); + + return .{ + texture = texture, + width = width, + height = height, + }; +} + +load_texture :: (width: i32, height: i32, data: [] u8, format: gl.GLenum, internal_type := gl.UNSIGNED_BYTE) -> Texture { + texture := gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, internal_type, data); + + // Setting some reasonable defaults for the texture parameters + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + gl.bindTexture(gl.TEXTURE_2D, -1); + + return .{ + texture = texture, + width = width, + height = height, + }; +} diff --git a/modules/ui/ui.onyx b/modules/ui/ui.onyx index 39f67518..aef9b0fe 100644 --- a/modules/ui/ui.onyx +++ b/modules/ui/ui.onyx @@ -5,7 +5,7 @@ use package core @Cleanup // Move these to the theme? // Or create a cache of fonts and put pointers/string in the themes? #private font : bmfont.BMFont; -#private font_texture : gl.GLTexture; +#private font_texture : gfx.Texture; @Temporary DEFAULT_TEXT_SIZE :: 1.0f @@ -161,8 +161,7 @@ is_hot_item :: (id: UI_Id) -> bool { @FontSizing // Currently, `size` is just a multipler for the baked font size. This should be changed to be height in pixels, or 'em's. draw_text_raw :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) { - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, font_texture); + gfx.set_texture(^font_texture); gfx.use_alpha_shader(0); for glyph: bmfont.get_character_positions(^font, size, text, x, y) { @@ -173,7 +172,7 @@ draw_text_raw :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := } gfx.flush(); - gl.bindTexture(gl.TEXTURE_2D, -1); + gfx.set_texture(); } draw_rect :: #match { @@ -286,14 +285,7 @@ get_text_width :: (text: str, size := DEFAULT_TEXT_SIZE) -> f32 { tex_width, tex_height := font.common.scale_width, font.common.scale_height; - font_texture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, font_texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, tex_width, tex_height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, texture_data); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.bindTexture(gl.TEXTURE_2D, -1); + font_texture = gfx.load_texture(tex_width, tex_height, texture_data, gl.ALPHA); } diff --git a/modules/webgl2/webgl2.js b/modules/webgl2/webgl2.js index bd533993..df8936d2 100644 --- a/modules/webgl2/webgl2.js +++ b/modules/webgl2/webgl2.js @@ -38,10 +38,34 @@ window.ONYX_MODULES.push({ gl.bindBuffer(target, buffers[buffer]); } }, - bindFramebuffer(target, framebuffer) { gl.bindFramebuffer(target, framebuffers[framebuffer]); }, - bindRenderbuffer(target, renderbuffer) { gl.bindRenderbuffer(target, renderbuffers[renderbuffer]); }, - bindTexture(target, texture) { gl.bindTexture(target, textures[texture]); }, - bindVertexArray(vertexArray) { gl.bindVertexArray(vertexArrays[vertexArray]); }, + bindFramebuffer(target, framebuffer) { + if (framebuffer == -1) { + gl.bindFramebuffer(target, null); + } else { + gl.bindFramebuffer(target, framebuffers[framebuffer]); + } + }, + bindRenderbuffer(target, renderbuffer) { + if (renderbuffer == -1) { + gl.bindRenderbuffer(target, null); + } else { + gl.bindRenderbuffer(target, renderbuffers[renderbuffer]); + } + }, + bindTexture(target, texture) { + if (texture == -1) { + gl.bindTexture(target, null); + } else { + gl.bindTexture(target, textures[texture]); + } + }, + bindVertexArray(vertexArray) { + if (vertexArray == -1) { + gl.bindVertexArray(null); + } else { + gl.bindVertexArray(vertexArrays[vertexArray]); + } + }, blendColor(red, green, blue, alpha) { gl.blendColor(red, green, blue, alpha); }, blendEquation(mode) { gl.blendEquation(mode); }, @@ -67,7 +91,7 @@ window.ONYX_MODULES.push({ canvas.width = width; canvas.height = height; }, - checkFrameBufferStatus(target) { return gl.checkFrameBufferStatus(target); }, + checkFramebufferStatus(target) { return gl.checkFramebufferStatus(target); }, clear(bit) { gl.clear(bit); }, clearColor(r, g, b, a) { gl.clearColor(r, g, b, a); }, clearDepth(depth) { gl.clearDepth(depth); }, @@ -83,8 +107,8 @@ window.ONYX_MODULES.push({ gl.compressedSubTexImage2D(target, level, internalformat, xoff, yoff, width, height, format, pixels); }, copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size) { gl.copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); }, - copyTexImage2D(target, level, internalforamt, x, y, width, height, border) { - gl.copyTexImage2D(target, level, internalforamt, x, y, width, height, border); + copyTexImage2D(target, level, internalformat, x, y, width, height, border) { + gl.copyTexImage2D(target, level, internalformat, x, y, width, height, border); }, copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height) { gl.copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height); @@ -229,8 +253,9 @@ window.ONYX_MODULES.push({ gl.readPixels(x, y, width, height, format, type, pixeldata); }, readBuffer(src) { gl.readBuffer(src); }, - renderbufferStorageMultisample(target, samples, internalforamt, width, height) { - gl.renderbufferStorageMultisample(target, samples, internalforamt, width, height); + renderbufferStorage(target, internalformat, width, height) { gl.renderbufferStorage(target, internalformat, width, height); }, + renderbufferStorageMultisample(target, samples, internalformat, width, height) { + gl.renderbufferStorageMultisample(target, samples, internalformat, width, height); }, sampleCoverage(value, invert) { gl.sampleCoverage(value, invert); }, scissor(x, y, width, height) { gl.scissor(x, y, width, height); }, @@ -248,12 +273,13 @@ window.ONYX_MODULES.push({ stencilMaskSeparate(face, mask) { gl.stencilMaskSeparate(face, mask); }, stencilOp(fail, zfail, mask) { gl.stencilOp(fail, zfail, mask); }, stencilOpSeparate(face, fail, zfail, zpass) { gl.stencilOpSeparate(face, fail, zfail, zpass); }, - texImage2D(target, level, internalforamt, width, height, border, format, type, pixels, pixelslen) { + texImage2D(target, level, internalformat, width, height, border, format, type, pixels, pixelslen) { const data = new Uint8Array(window.ONYX_MEMORY.buffer, pixels, pixelslen); - gl.texImage2D(target, level, internalforamt, width, height, border, format, type, data); + gl.texImage2D(target, level, internalformat, width, height, border, format, type, data); }, texParameterf(target, pname, param) { gl.texParameterf(target, pname, param); }, texParameteri(target, pname, param) { gl.texParameteri(target, pname, param); }, + texStorage2D(target, levels, internalformat, width, height) { gl.texStorage2D(target, levels, internalformat, width, height); }, texSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels, pixelslen) { const data = new Uint8Array(window.ONYX_MEMORY.buffer, pixels, pixelslen); gl.texSubImage2D(target, level, xoff, yoff, width, height, format, type, data); diff --git a/modules/webgl2/webgl2.onyx b/modules/webgl2/webgl2.onyx index 0b20cfb2..24141a39 100644 --- a/modules/webgl2/webgl2.onyx +++ b/modules/webgl2/webgl2.onyx @@ -747,7 +747,7 @@ bufferDataNoData :: (target: GLenum, size: GLsizei, usage: GLenum) bufferData :: #match { bufferDataWithData, bufferDataNoData } bufferSubData :: (target: GLenum, offset: GLsizei, data: [] void) -> void #foreign "gl" "bufferSubData" --- canvasSize :: (width: GLsizei, height: GLsizei) -> void #foreign "gl" "canvasSize" --- -checkFrameBufferStatus :: (target: GLenum) -> GLenum #foreign "gl" "checkFrameBufferStatus" --- +checkFramebufferStatus :: (target: GLenum) -> GLenum #foreign "gl" "checkFramebufferStatus" --- clear :: (mask: GLbitfield) -> void #foreign "gl" "clear" --- clearColor :: (red: GLclampf, green: GLclampf, blue: GLclampf, alpha: GLclampf) -> void #foreign "gl" "clearColor" --- clearDepth :: (depth: GLclampf) -> void #foreign "gl" "clearDepth" --- @@ -819,7 +819,8 @@ printProgramInfoLog :: (program: GLProgram) -> void #foreign "gl" "pr printShaderInfoLog :: (shader: GLShader) -> void #foreign "gl" "printShaderInfoLog" --- readBuffer :: (src: GLenum) -> void #foreign "gl" "readBuffer" --- readPixels :: (x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, type: GLenum, pixels: str) -> void #foreign "gl" "readPixels" --- -renderbufferStorageMultisample :: (target: GLenum, samples: GLsizei, internalforamt: GLenum, width: GLsizei, height: GLsizei) -> void #foreign "gl" "renderbufferStorageMultisample" --- +renderbufferStorage :: (target: GLenum, internalformat: GLenum, width: GLsizei, height: GLsizei) -> void #foreign "gl" "renderbufferStorage" --- +renderbufferStorageMultisample :: (target: GLenum, samples: GLsizei, internalformat: GLenum, width: GLsizei, height: GLsizei) -> void #foreign "gl" "renderbufferStorageMultisample" --- sampleCoverage :: (value: GLclampf, invert: GLboolean) -> void #foreign "gl" "sampleCoverage" --- scissor :: (x: GLint, y: GLint, width: GLsizei, height: GLsizei) -> void #foreign "gl" "scissor" --- setSize :: (width: GLint, y: GLint) -> void #foreign "gl" "setSize" --- @@ -833,6 +834,7 @@ stencilOpSeparate :: (face: GLenum, fail: GLenum, zfail: GLenum, zp texImage2D :: (target: GLenum, level: GLint, internalFormat: GLenum, width: GLsizei, height: GLsizei, border: GLint, format: GLenum, type: GLenum, pixels: str) -> void #foreign "gl" "texImage2D" --- texParameterf :: (target: GLenum, pname: GLenum, param: GLfloat) -> void #foreign "gl" "texParameterf" --- texParameteri :: (target: GLenum, pname: GLenum, param: GLint) -> void #foreign "gl" "texParameteri" --- +texStorage2D :: (target: GLenum, levels: GLsizei, internalformat: GLenum, width: GLsizei, height: GLsizei) -> void #foreign "gl" "texStorage2D" --- texSubImage2D :: (target: GLenum, level: GLint, xoff: GLint, yoff: GLint, width: GLsizei, height: GLsizei, format: GLenum, type: GLenum, pixels: str) -> void #foreign "gl" "texSubImage2D" --- uniform1f :: (loc: GLUniformLocation, x: GLfloat) -> void #foreign "gl" "uniform1f" --- uniform1i :: (loc: GLUniformLocation, x: GLint) -> void #foreign "gl" "uniform1i" --- diff --git a/src/onyxutils.c b/src/onyxutils.c index 5864662f..c4a8ef56 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -154,23 +154,27 @@ AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) { } AstNode* try_symbol_raw_resolve_from_node(AstNode* node, char* symbol) { - // CLEANUP: So many checks for null.... - if (!node) return NULL; - - if (node->kind == Ast_Kind_Type_Raw_Alias) - node = (AstNode *) ((AstTypeRawAlias *) node)->to->ast_type; + b32 used_pointer = 0; - if (!node) return NULL; + while (1) { + if (!node) return NULL; - if (node->kind == Ast_Kind_Type_Alias) - node = (AstNode *) ((AstTypeAlias *) node)->to; + switch (node->kind) { + case Ast_Kind_Type_Raw_Alias: node = (AstNode *) ((AstTypeRawAlias *) node)->to->ast_type; break; + case Ast_Kind_Type_Alias: node = (AstNode *) ((AstTypeAlias *) node)->to; break; + case Ast_Kind_Pointer_Type: { + if (used_pointer) goto all_types_peeled_off; + used_pointer = 1; - if (!node) return NULL; + node = (AstNode *) ((AstPointerType *) node)->elem; + break; + } - // A single pointer can be dereferenced to lookup symbols in struct. - if (node->kind == Ast_Kind_Pointer_Type) - node = (AstNode *) ((AstPointerType *) node)->elem; + default: goto all_types_peeled_off; + } + } +all_types_peeled_off: if (!node) return NULL; switch (node->kind) { -- 2.25.1