added ability to output a tag file
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 3 Sep 2020 15:38:12 +0000 (10:38 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 3 Sep 2020 15:38:12 +0000 (10:38 -0500)
12 files changed:
core/js/webgl.js
core/js/webgl.onyx
core/stdio.onyx
core/string.onyx
docs/cli [new file with mode: 0644]
docs/plan
include/onyxdoc.h
onyx
progs/poly_test.onyx
src/onyx.c
src/onyxdoc.c
src/onyxerrors.c

index 16b971e2d917493b8ecae2955a42e3c8554cb121..1199e8969f6625fe7027fe7d1cf61b1bbcf325f6 100644 (file)
@@ -11,6 +11,7 @@ WebGl_Wasm = {
         this.renderbuffers = [];
         this.textures = [];
         this.uniformlocs = [];
+        this.vertexArrays = [];
 
         this.canvas = document.getElementById(canvasname);
         if (this.canvas == null) return 0;
@@ -34,6 +35,8 @@ WebGl_Wasm = {
     bindFramebuffer(target, framebuffer) { this.gl.bindFramebuffer(target, this.framebuffers[framebuffer]); },
     bindRenderbuffer(target, renderbuffer) { this.gl.bindRenderbuffer(target, this.renderbuffers[renderbuffer]); },
     bindTexture(target, texture) { this.gl.bindTexture(target, this.textures[texture]); },
+    bindVertexArray(vertexArray) { this.gl.bindVertexArray(this.vertexArrays[vertexArray]); },
+
     blendColor(red, green, blue, alpha) { this.gl.blendColor(red, green, blue, alpha); },
     blendEquation(mode) { this.gl.blendEquation(mode); },
     blendEquationSeparate(modeRGB, modeAlpha) { this.gl.blendEquationSeparate(modeRGB, modeAlpha); },
@@ -118,6 +121,13 @@ WebGl_Wasm = {
         this.textures.push(texture);
         return this.textures.length - 1;
     },
+    createVertexArray() {
+        const vao = this.gl.createVertexArray();
+        if (vao == null) return -1;
+
+        this.vertexArrays.push(vao);
+        return this.vertexArrays.length - 1;
+    },
     cullFace(mode) { this.gl.cullFace(mode); },
     deleteBuffer(buffer) { this.gl.deleteBuffer(this.buffers[buffer]); },
     deleteFramebuffer(framebuffer) { this.gl.deleteFramebuffer(this.framebuffers[framebuffer]); },
@@ -125,6 +135,7 @@ WebGl_Wasm = {
     deleteRenderbuffer(renderbuffer) { this.gl.deleteRenderbuffer(this.renderbuffers[renderbuffer]); },
     deleteShader(shader) { this.gl.deleteShader(this.shaders[shader]); },
     deleteTexture(texture) { this.gl.deleteTexture(this.textures[texture]); },
+    deleteVertexArray(vertexArray) { this.gl.deleteVertexArray(this.vertexArrays[vertexArray]); },
     depthFunc(func) { this.gl.depthFunc(func); },
     depthMask(flag) { this.gl.depthMask(flag); },
     depthRange(znear, zfar) { this.gl.depthRange(znear, zfar); },
@@ -132,7 +143,9 @@ WebGl_Wasm = {
     disable(cap) { this.gl.disable(cap); },
     disableVertexAttribArray(index) { this.gl.disableVertexAttribArray(index); },
     drawArrays(mode, first, count) { this.gl.drawArrays(mode, first, count); },
+    drawArraysInstanced(mode, first, count, instanceCount) { this.gl.drawArraysInstanced(mode, first, count, instanceCount); },
     drawElements(mode, count, type, offset) { this.gl.drawElements(mode, count, type, offset); },
+    drawElementsInstanced(mode, count, type, offset, instanceCount) { this.gl.drawElementsInstanced(mode, count, type, offset, instanceCount); },
     enable(cap) { this.gl.enable(cap); },
     enableVertexAttribArray(index) { this.gl.enableVertexAttribArray(index); },
     finish() { this.gl.finish(); },
@@ -261,6 +274,7 @@ WebGl_Wasm = {
     vertexAttrib3f(idx, x, y, z) { this.gl.vertexAttrib3f(idx, x, y, z); },
     vertexAttrib4f(idx, x, y, z, w) { this.gl.vertexAttrib4f(idx, x, y, z, w); },
     vertexAttribPointer(idx, size, type, normalized, stride, offset) { this.gl.vertexAttribPointer(idx, size, type, normalized, stride, offset); },
+    vertexAttribDivisor(idx, divisor) { this.gl.vertexAttribDivisor(idx, divisor); },
     viewport(x, y, width, height) { this.gl.viewport(x, y, width, height); },
 
 };
index d738253c6d6c8e1d57a3c9195b81e8f9bf6769b8..a4d2afea05961f699df163269a515cb8df000f4b 100644 (file)
@@ -1,6 +1,6 @@
 package gl
 // To be used with the corresponding gl.js
-
+// There are many things that are missing but this suffices for me.
 
 
 // ClearBufferMask 
@@ -708,6 +708,7 @@ GLRenderbuffer :: #type i32
 GLTexture :: #type i32
 GLBuffer :: #type i32
 GLUniformLocation :: #type i32
+GLVertexArrayObject :: #type i32
 
 GLActiveInfo :: struct {
     size     : GLint;
@@ -728,6 +729,7 @@ bindBuffer                     :: proc (target: GLenum, buffer: GLBuffer) #forei
 bindFramebuffer                :: proc (target: GLenum, framebuffer: GLFramebuffer) #foreign "gl" "bindFramebuffer" ---
 bindRenderbuffer               :: proc (target: GLenum, renderbuffer: GLRenderbuffer) #foreign "gl" "bindRenderbuffer" ---
 bindTexture                    :: proc (target: GLenum, texture: GLTexture) #foreign "gl" "bindTexture" ---
+bindVertexArray                :: proc (vertexArray: GLVertexArrayObject) #foreign "gl" "bindVertexArray" ---
 blendColor                     :: proc (red: GLclampf, green: GLclampf, blue: GLclampf, alpha: GLclampf) #foreign "gl" "blendColor" ---
 blendEquation                  :: proc (mode: GLenum) #foreign "gl" "blendEquation" ---
 blendEquationSeparate          :: proc (modeRGB: GLenum, modeAlpha: GLenum) #foreign "gl" "blendEquationSeparate" ---
@@ -737,7 +739,7 @@ blitFramebuffer                :: proc (sx0: GLint, sy0: GLint, sx1: GLint, sy1:
 bufferDataWithData             :: proc (target: GLenum, buffer: Buffer, usage: GLenum) #foreign "gl" "bufferDataWithData" ---
 bufferDataNoData               :: proc (target: GLenum, size: GLsizeiptr, usage: GLenum) #foreign "gl" "bufferDataNoData" ---
 bufferData                     :: proc #overloaded { bufferDataWithData, bufferDataNoData }
-bufferSubData                  :: proc (target: GLenum, offset: GLintptr, data: string) #foreign "gl" "bufferSubData" ---
+bufferSubData                  :: proc (target: GLenum, offset: GLsizei, data: Buffer) #foreign "gl" "bufferSubData" ---
 checkFrameBufferStatus         :: proc (target: GLenum) -> GLenum #foreign "gl" "checkFrameBufferStatus" ---
 clear                          :: proc (mask: GLbitfield) #foreign "gl" "clear" ---
 clearColor                     :: proc (red: GLclampf, green: GLclampf, blue: GLclampf, alpha: GLclampf) #foreign "gl" "clearColor" ---
@@ -756,6 +758,7 @@ createProgram                  :: proc -> GLProgram #foreign "gl" "createProgram
 createRenderbuffer             :: proc -> GLRenderbuffer #foreign "gl" "createRenderbuffer" ---
 createShader                   :: proc (type: GLenum) -> GLShader #foreign "gl" "createShader" ---
 createTexture                  :: proc -> GLTexture #foreign "gl" "createTexture" ---
+createVertexArray              :: proc -> GLVertexArrayObject #foreign "gl" "createVertexArray" ---
 cullFace                       :: proc (mode: GLenum) #foreign "gl" "cullFace" ---
 deleteBuffer                   :: proc (buffer: GLBuffer) #foreign "gl" "deleteBuffer" ---
 deleteFramebuffer              :: proc (framebuffer: GLFramebuffer) #foreign "gl" "deleteFramebuffer" ---
@@ -763,6 +766,7 @@ deleteProgram                  :: proc (program: GLProgram) #foreign "gl" "delet
 deleteRenderbuffer             :: proc (renderbuffer: GLRenderbuffer) #foreign "gl" "deleteRenderbuffer" ---
 deleteShader                   :: proc (shader: GLShader) #foreign "gl" "deleteShader" ---
 deleteTexture                  :: proc (texture: GLTexture) #foreign "gl" "deleteTexture" ---
+deleteVertexArray              :: proc (vertexArray: GLVertexArrayObject) #foreign "gl" "deleteVertexArray" ---
 depthFunc                      :: proc (func: GLenum) #foreign "gl" "depthFunc" ---
 depthMask                      :: proc (flag: GLboolean) #foreign "gl" "depthMask" ---
 depthRange                     :: proc (zNear: GLclampf, zFar: GLclampf) #foreign "gl" "depthRange" ---
@@ -770,7 +774,9 @@ detachShader                   :: proc (program: GLProgram, shader: GLShader) #f
 disable                        :: proc (cap: GLenum) #foreign "gl" "disable" ---
 disableVertexAttribArray       :: proc (index: GLuint) #foreign "gl" "disableVertexAttribArray" ---
 drawArrays                     :: proc (mode: GLenum, first: GLint, count: GLsizei) #foreign "gl" "drawArrays" ---
+drawArraysInstanced            :: proc (mode: GLenum, first: GLint, count: GLsizei, instanceCount: GLsizei) #foreign "gl" "drawArraysInstanced" ---
 drawElements                   :: proc (mode: GLenum, count: GLsizei, type: GLenum, offset: GLint) #foreign "gl" "drawElements" ---
+drawElementsInstanced          :: proc (mode: GLenum, count: GLsizei, type: GLenum, offset: GLint, instanceCount: GLsizei) #foreign "gl" "drawElementsInstanced" ---
 enable                         :: proc (cap: GLenum) #foreign "gl" "enable" ---
 enableVertexAttribArray        :: proc (index: GLuint) #foreign "gl" "enableVertexAttribArray" ---
 finish                         :: proc #foreign "gl" "finish" ---
@@ -838,4 +844,5 @@ vertexAttrib2f                 :: proc (idx: GLuint, x: GLfloat, y: GLfloat) #fo
 vertexAttrib3f                 :: proc (idx: GLuint, x: GLfloat, y: GLfloat, z: GLfloat) #foreign "gl" "vertexAttrib3f" ---
 vertexAttrib4f                 :: proc (idx: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) #foreign "gl" "vertexAttrib4f" ---
 vertexAttribPointer            :: proc (idx: GLuint, size: GLint, type: GLenum, normalized: GLboolean, stride: GLsizei, offset: GLint) #foreign "gl" "vertexAttribPointer" ---
+vertexAttribDivisor            :: proc (idx: GLuint, divisor: GLuint) #foreign "gl" "vertexAttribDivisor" ---
 viewport                       :: proc (x: GLint, y: GLint, width: GLsizei, height: GLsizei) #foreign "gl" "viewport" ---      
index a0f0794b65eba56e846a255f735d32a7f5b6bc97..3d2fc0f57f32179492e4bb3e2cc6a90e2036ce26 100644 (file)
@@ -39,6 +39,8 @@ print_array :: proc (arr: $T, sep := " ") {
 }
 
 print_buffer_flush :: proc {
+    if print_buffer.len == 0 do return;
+
        ^print_buffer
                |> string_builder_to_string()
                |> system.output_string();
index 3804ea356408552946123e318dad1eef90a44e5f..9dac85d455b970b28307c30c65463a8f934a5795 100644 (file)
@@ -26,9 +26,6 @@ string_length :: proc #overloaded {
     },
 }
 
-#private
-string_length_string :: proc (s: string) -> u32 do return s.count;
-
 string_concat :: proc (s1: string, s2: string) -> string {
     len1 :: string_length(s1);
     len2 :: string_length(s2);
diff --git a/docs/cli b/docs/cli
new file mode 100644 (file)
index 0000000..e372cc0
--- /dev/null
+++ b/docs/cli
@@ -0,0 +1,21 @@
+Thoughts about the CLI for Onyx
+-------------------------------
+
+Right now, unless a specific argument is recognized, it is treated as a file to add to the compilation.
+This has worked well, but as the amount of functionality that is being added to the compiler is increasing,
+the need for a better CLI system is imminent.
+
+Here are all the things the compiler should be able to do:
+    * Compile a file or a set of files
+    * Validate a file or set of files
+        - Everything done in compilations
+        - No outputting to final WASM file
+    * Generate documentation for a compilation
+        - In Human, Tags, or Html format
+    * Print a help menu
+
+
+
+  $ onyx compile progs/poly_test.onyx -I other_folder
+
+  $ onyx doc progs/poly_test.onyx --format tag
index 60b058bfb482a246144ede4f1cf5cc9b16c5b7f3..ba6b114e0dca38813fd8660da0c4fdd7a04ba166 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -174,7 +174,7 @@ HOW:
             X All members specified means names not required
             X Named member initialization
             X Default values on structs so they don't have to be named
-            
+
         [X] #union on structs
 
         [X] #align on structs
@@ -201,7 +201,7 @@ HOW:
 
         [X] Add slices
             - Arrays without a size
-            - Converted to a struct that looks like:    
+            - Converted to a struct that looks like:
                 []T :: struct {
                     data  : ^T;
                     count : u32;
@@ -226,8 +226,17 @@ HOW:
         [X] #file and #line directives
             - string and u32 respectively that represent the current file and line number where the directive is
 
+        [X] Generate a tags file
+            - This looks very simple
+            - I think all the infrastructure is there for this
+
         [ ] data structure based iteration
 
+        [ ] baked parameters
+            - Compile time known parameters
+            - Removes the argument from the list and replaces the function with the
+                baked function
+
         [ ] Put type info in data section so it is runtime accessible
             - type name
             - size
index b3b3ba73064e08ee52ce53194f0061bb514e124f..b5ec16d7dbe0dd7e3d22af364cb5ab26e7a0d1c1 100644 (file)
@@ -4,8 +4,15 @@
 #include "bh.h"
 #include "onyxastnodes.h"
 
+typedef enum DocFormat {
+    Doc_Format_Human,
+    Doc_Format_Tags,
+    Doc_Format_Html,
+} DocFormat;
+
 typedef struct DocEntry {
        OnyxFilePos pos;
+    char* sym; // Unused by doc generator
        char* def;
        char* additional;
 } DocEntry;
@@ -20,10 +27,12 @@ typedef struct DocPackage {
 typedef struct OnyxDocumentation {
        bh_arena doc_arena;
 
+    DocFormat format;
+
        bh_arr(DocPackage) package_docs;
 } OnyxDocumentation;
 
 OnyxDocumentation onyx_docs_generate(ProgramInfo* prog);
-void onyx_docs_write(OnyxDocumentation* doc);
+void onyx_docs_emit(OnyxDocumentation* doc);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/onyx b/onyx
index a21c505676db1d50d980aa85b2ca603188a64485..bfe7d9cd83347f794ed6ceb65a69c35f3a4e880d 100755 (executable)
Binary files a/onyx and b/onyx differ
index 69f6548875cb68bdc150ae63d574d54a8ccc897e..b4a68d62ef84bd6565caef43001c058f7bb5cd33 100644 (file)
@@ -119,7 +119,7 @@ main :: proc (args: [] cstring) {
     print(ptrmap_has(^map, ^s.a[20]));
     print("\n");
 }
-    
+
 main2 :: proc (args: [] cstring) {
     print(cast(u32) __heap_start, 16);
 
@@ -223,4 +223,4 @@ cmp_vec3 :: proc (v1: Vec3, v2: Vec3) -> i32 {
     if v1.x != v2.x do return v1.x - v2.x;
     if v1.y != v2.y do return v1.y - v2.y;
     return v1.z - v2.z;
-}
\ No newline at end of file
+}
index b1628aa62c316dd36e63b2a98f0d26941e1c464a..59b6acf36ce9cdc98dce2540872486e9eb1f4638 100644 (file)
@@ -334,6 +334,16 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
     bh_file_contents fc = bh_file_read_contents(compiler_state->token_alloc, &file);
     bh_file_close(&file);
 
+    // POTENTIAL BUG: If there are too many files and too many collisions in the table,
+    // there is a chance that the inner arrays of the table will be repositioned. That
+    // would completely break the pointer taken here, which would break all references
+    // to file contents anywhere else in the program.
+    //
+    // A good solution would be to not use a table and just use a array of char* and
+    // ensure that the filename is not in that list.
+    //                                                      - brendanfh 2020/09/03
+
+
     // NOTE: Need to reget the value out of the table so token references work
     bh_table_put(bh_file_contents, compiler_state->loaded_files, (char *) filename, fc);
     fc = bh_table_get(bh_file_contents, compiler_state->loaded_files, (char *) filename);
@@ -394,7 +404,8 @@ static i32 onyx_compile(CompilerState* compiler_state) {
 
     if (compiler_state->options->action == ONYX_COMPILE_ACTION_DOCUMENT) {
         OnyxDocumentation docs = onyx_docs_generate(&compiler_state->prog_info);
-        onyx_docs_write(&docs);
+        docs.format = Doc_Format_Tags;
+        onyx_docs_emit(&docs);
 
         return ONYX_COMPILER_PROGRESS_SUCCESS;
     }
index 918f6e8cf3d55ced4a08273c6b00018dc99e8618..fbe7515dc97f78652c8fa411488cba331bd282f9 100644 (file)
@@ -12,7 +12,7 @@ static i32 cmp_doc_entry(const void * a, const void * b) {
 static i32 cmp_doc_package(const void * a, const void * b) {
     DocPackage* d1 = (DocPackage *) a;
     DocPackage* d2 = (DocPackage *) b;
-    
+
     return strncmp(d1->name, d2->name, 1024);
 }
 
@@ -79,7 +79,8 @@ static char* node_to_doc_def(const char* sym, AstNode *node, bh_allocator a) {
         case Ast_Kind_Basic_Type:
         case Ast_Kind_Array_Type:
         case Ast_Kind_Type_Alias:
-        case Ast_Kind_Slice_Type: {
+        case Ast_Kind_Slice_Type:
+        case Ast_Kind_DynArr_Type: {
             strncat(buf, type_get_name(type_build_from_ast(global_heap_allocator, (AstType *) node)), 1023);
             break;
         }
@@ -105,6 +106,7 @@ static DocPackage doc_package_create(Package* p, bh_allocator a) {
         DocEntry de;
         de.pos = value->token->pos;
         de.def = node_to_doc_def(key, value, a);
+        de.sym = (char *) key;
         de.additional = NULL;
 
         bh_arr_push(dp.public_entries, de);
@@ -114,6 +116,7 @@ static DocPackage doc_package_create(Package* p, bh_allocator a) {
         DocEntry de;
         de.pos = value->token->pos;
         de.def = node_to_doc_def(key, value, a);
+        de.sym = (char *) key;
         de.additional = NULL;
 
         bh_arr_push(dp.private_entries, de);
@@ -144,7 +147,7 @@ OnyxDocumentation onyx_docs_generate(ProgramInfo* prog) {
     return doc;
 }
 
-void onyx_docs_write(OnyxDocumentation* doc) {
+static void onyx_docs_emit_human(OnyxDocumentation* doc) {
     // NOTE: Disabling fancy line printing until I can make it better
     #if 0
     bh_arr_each(DocPackage, dp, doc->package_docs) {
@@ -214,3 +217,66 @@ void onyx_docs_write(OnyxDocumentation* doc) {
     }
     #endif
 }
+
+
+static i32 sort_tags(const void* a, const void* b) {
+    DocEntry *da = *((DocEntry **) a);
+    DocEntry *db = *((DocEntry **) b);
+
+    return strcmp(da->sym, db->sym);
+}
+
+static void onyx_docs_emit_tags(OnyxDocumentation* doc) {
+    bh_file tags_file;
+    if (bh_file_create(&tags_file, "./tags") != BH_FILE_ERROR_NONE) {
+        bh_printf("Cannot create 'tags'.\n");
+        return;
+    }
+
+    bh_fprintf(&tags_file, "!_TAG_FILE_FORMAT\t2\n");
+    bh_fprintf(&tags_file, "!_TAG_FILE_SORTED\t1\n");
+    bh_fprintf(&tags_file, "!_TAG_OUTPUT_FILESEP\tslash\n");
+    bh_fprintf(&tags_file, "!_TAG_OUTPUT_MODE\tu-ctags\n");
+    bh_fprintf(&tags_file, "!_TAG_PROGRAM_AUTHOR\tOnyx Compiler\n");
+    bh_fprintf(&tags_file, "!_TAG_PROGRAM_NAME\tOnyx Compiler\n");
+    bh_fprintf(&tags_file, "!_TAG_PROGRAM_URL\thttps://github.com/brendanfh/onyx\n");
+    bh_fprintf(&tags_file, "!_TAG_PROGRAM_VERSION\t0.0.1\n");
+
+    bh_arr(DocEntry *) tags = NULL;
+    bh_arr_new(global_heap_allocator, tags, 256);
+
+    bh_arr_each(DocPackage, dp, doc->package_docs) {
+        bh_arr_each(DocEntry, de, dp->public_entries) bh_arr_push(tags, de);
+        bh_arr_each(DocEntry, de, dp->private_entries) bh_arr_push(tags, de);
+    }
+
+    qsort(tags, bh_arr_length(tags), sizeof(DocEntry *), sort_tags);
+
+    bh_arr_each(DocEntry *, tag, tags) {
+        if ((*tag)->pos.filename == NULL) continue;
+
+        i32 line_len = 0;
+        char *c = (*tag)->pos.line_start;
+        while (*c++ != '\n') line_len++;
+
+        bh_fprintf(&tags_file, "%s\t%s\t/^%b$/\n",
+                (*tag)->sym, (*tag)->pos.filename,
+                (*tag)->pos.line_start, line_len);
+    }
+
+    bh_file_close(&tags_file);
+}
+
+static void onyx_docs_emit_html(OnyxDocumentation* doc) {
+    bh_printf("HTML documentation output not supported yet.\n");
+    return;
+}
+
+void onyx_docs_emit(OnyxDocumentation* doc) {
+    switch (doc->format) {
+        case Doc_Format_Human: onyx_docs_emit_human(doc); break;
+        case Doc_Format_Tags: onyx_docs_emit_tags(doc); break;
+        case Doc_Format_Html: onyx_docs_emit_html(doc); break;
+    }
+}
+
index 5e9879d08cb02cb4e42ce629678b7f2ac180e296..ed8bc702fdf7dd0f857d90f29f4bf92bec21fe75 100644 (file)
@@ -50,6 +50,13 @@ static void print_detailed_message(OnyxError* err, bh_file_contents* fc) {
 }
 
 void onyx_errors_print() {
+    // NOTE: If the format of the error messages is ever changed,
+    // update onyx_compile.vim and onyx.sublime-build to match
+    // the new format. This was editor error highlighting is still
+    // supported.
+    //
+    //                                      - brendanfh   2020/09/03
+
     bh_arr_each(OnyxError, err, errors.errors) {
         if (err->pos.filename) {
             bh_file_contents* fc = &bh_table_get(bh_file_contents, *errors.file_contents, (char *) err->pos.filename);