From afdff66710b20cb4eee974ab7a1c68eb708b09ff Mon Sep 17 00:00:00 2001 From: nakst <> Date: Wed, 9 Feb 2022 21:04:45 +0000 Subject: [PATCH] header generator: return type determination for scripting engine --- desktop/os.header | 6 +- util/header_generator.c | 156 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 156 insertions(+), 6 deletions(-) diff --git a/desktop/os.header b/desktop/os.header index 7297d90..cdeb5ff 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -2049,7 +2049,7 @@ function void *EsFileStoreReadAll(EsFileStore *file, size_t *fileSize) @heap_buf function bool EsFileStoreWriteAll(EsFileStore *file, const void *data, size_t dataBytes) @buffer_in(data, dataBytes); function bool EsFileStoreAppend(EsFileStore *file, const void *data, size_t dataBytes) @buffer_in(data, dataBytes); function EsFileOffsetDifference EsFileStoreGetSize(EsFileStore *file); // Returns -1 on error. -function void *EsFileStoreMap(EsFileStore *file, size_t *fileSize, uint32_t flags) @buffer_out(return, fileSize*) @out(fileSize); +function void *EsFileStoreMap(EsFileStore *file, size_t *fileSize, uint32_t flags) @native(); // These calls require permission_all_files. function bool EsMountPointGetVolumeInformation(STRING prefix, EsVolumeInformation *information) @out(information); // Returns false if the mount point does not exist. @@ -2362,7 +2362,7 @@ function int EsCRTvsnprintf(char *buffer, size_t bufferSize, EsCString format, v function EsError EsClipboardAddText(EsClipboard clipboard, STRING text = BLANK_STRING); function bool EsClipboardHasFormat(EsClipboard clipboard, EsClipboardFormat format); function bool EsClipboardHasData(EsClipboard clipboard); -function char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes, uint32_t *flags = ES_NULL) @out(flags) @buffer_out(return, bytes*) @out(bytes); // Free with EsHeapFree. +function char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes, uint32_t *flags = ES_NULL) @out(flags) @heap_buffer_out(return, bytes*) @out(bytes); // Free with EsHeapFree. function EsFileStore *EsClipboardOpen(EsClipboard clipboard); // Open the clipboard for writing. function EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format, EsFileStore *fileStore, uint32_t flags = ES_FLAGS_DEFAULT); @@ -2507,7 +2507,7 @@ function EsTextbox *EsTextboxCreate(EsElement *parent, uint64_t flags = ES_FLAGS function bool EsTextboxFind(EsTextbox *textbox, STRING string, int32_t *line, int32_t *byte, uint32_t flags) @out(line) @out(byte); function void EsTextboxInsert(EsTextbox *textbox, STRING string = BLANK_STRING, bool sendUpdatedMessage = true); // Deletes existing selection first. function void EsTextboxAppend(EsTextbox *textbox, STRING string = BLANK_STRING, bool sendUpdatedMessage = true); // Ignores the user's selection. -function char *EsTextboxGetContents(EsTextbox *textbox, size_t *bytes = ES_NULL, uint32_t flags = ES_FLAGS_DEFAULT) @buffer_out(return, bytes*) @out(bytes); // Result will be zero-terminated; free with EsHeapFree. +function char *EsTextboxGetContents(EsTextbox *textbox, size_t *bytes = ES_NULL, uint32_t flags = ES_FLAGS_DEFAULT) @heap_buffer_out(return, bytes*) @out(bytes); // Result will be zero-terminated; free with EsHeapFree. function double EsTextboxGetContentsAsDouble(EsTextbox *textbox, uint32_t flags = ES_FLAGS_DEFAULT); function size_t EsTextboxGetLineLength(EsTextbox *textbox, uintptr_t line = 0); function void EsTextboxGetSelection(EsTextbox *textbox, int32_t *fromLine, int32_t *fromByte, int32_t *toLine, int32_t *toByte) @out(fromLine) @out(fromByte) @out(toLine) @out(toByte); diff --git a/util/header_generator.c b/util/header_generator.c index 5499425..4a7c3c6 100644 --- a/util/header_generator.c +++ b/util/header_generator.c @@ -1291,7 +1291,158 @@ void OutputScript(Entry *root) { } } - FilePrintFormat(output, "void %s(", entry->children[0].name); + uintptr_t returnValueCount = 0; + + for (int pass = 0; pass < 2; pass++) { + if (pass == 1 && returnValueCount > 1) { + FilePrintFormat(output, "tuple["); + } + + returnValueCount = 0; + + for (int i = 0; i < arrlen(entry->children); i++) { + Entry argument = entry->children[i]; + assert(argument.type == ENTRY_VARIABLE); + bool isVoidReturn = 0 == strcmp(argument.variable.type, "void") && !argument.variable.pointer; + bool isOutput = i == 0 && !isVoidReturn; + + for (int i = 0; i < arrlen(entry->annotations); i++) { + if ((0 == strcmp(entry->annotations[i].name, "out") + || 0 == strcmp(entry->annotations[i].name, "buffer_out")) + && 0 == strcmp(entry->annotations[i].children[0].name, argument.name)) { + isOutput = true; + } + } + + char nameWithAsteriskSuffix[256]; + assert(strlen(argument.name) < sizeof(nameWithAsteriskSuffix) - 2); + strcpy(nameWithAsteriskSuffix, argument.name); + strcat(nameWithAsteriskSuffix, "*"); + + for (int i = 0; i < arrlen(entry->annotations); i++) { + if ((0 == strcmp(entry->annotations[i].name, "heap_array_out") + || 0 == strcmp(entry->annotations[i].name, "heap_buffer_out")) + && 0 == strcmp(entry->annotations[i].children[1].name, nameWithAsteriskSuffix)) { + assert(isOutput); + isOutput = false; + } + } + + if (!isOutput) { + continue; + } + + returnValueCount++; + + if (pass == 0) { + continue; + } + + if (returnValueCount > 1) { + FilePrintFormat(output, ", "); + } + + bool foundType = false; + int pointer = argument.variable.pointer; + + for (int i = 0; i < arrlen(entry->annotations); i++) { + if ((0 == strcmp(entry->annotations[i].name, "heap_array_out") + || 0 == strcmp(entry->annotations[i].name, "heap_buffer_out")) + && 0 == strcmp(entry->annotations[i].children[1].name, nameWithAsteriskSuffix)) { + assert(isOutput); + isOutput = false; + } + } + + for (int i = 0; i < arrlen(entry->annotations); i++) { + if ((0 == strcmp(entry->annotations[i].name, "out")) + && 0 == strcmp(entry->annotations[i].children[0].name, argument.name)) { + pointer--; + } + } + + bool isArray = false; + const char *argumentName = i ? argument.name : "return"; + + for (int i = 0; i < arrlen(entry->annotations); i++) { + if ((0 == strcmp(entry->annotations[i].name, "heap_array_out") + || 0 == strcmp(entry->annotations[i].name, "heap_matrix_out") + || 0 == strcmp(entry->annotations[i].name, "heap_buffer_out") + || 0 == strcmp(entry->annotations[i].name, "fixed_buffer_out") + || 0 == strcmp(entry->annotations[i].name, "buffer_out")) + && 0 == strcmp(entry->annotations[i].children[0].name, argumentName)) { + isArray = 0 == strcmp(entry->annotations[i].name, "heap_array_out"); + + if (isArray) { + pointer--; + } else { + foundType = true; + FilePrintFormat(output, "str"); + } + } + } + + if (foundType) { + } else if (pointer == 0) { + if (ScriptWriteBasicType(argument.variable.type)) { + foundType = true; + } else { + for (int k = 0; k < arrlen(root->children); k++) { + if (!root->children[k].name) continue; + if (strcmp(argument.variable.type, root->children[k].name)) continue; + + if (root->children[k].type == ENTRY_TYPE_NAME) { + if (ScriptWriteBasicType(root->children[k].variable.type)) { + foundType = true; + } + } else if (root->children[k].type == ENTRY_ENUM) { + FilePrintFormat(output, "%s", root->children[k].name); + foundType = true; + } else if (root->children[k].type == ENTRY_STRUCT) { + FilePrintFormat(output, "%s", root->children[k].name); + foundType = true; + } + } + } + } else if (pointer == 1) { + for (int k = 0; k < arrlen(root->children); k++) { + if (!root->children[k].name) continue; + if (strcmp(argument.variable.type, root->children[k].name)) continue; + + if (root->children[k].type == ENTRY_API_TYPE) { + FilePrintFormat(output, "%s", root->children[k].name); + foundType = true; + } else if (root->children[k].type == ENTRY_STRUCT) { + FilePrintFormat(output, "%s", root->children[k].name); + foundType = true; + } + } + + if (!foundType && 0 == strcmp(argument.variable.type, "ES_INSTANCE_TYPE")) { + FilePrintFormat(output, "EsInstance"); + foundType = true; + } + } + + if (isArray) { + FilePrintFormat(output, "[]"); + } + + if (!foundType) { + assert(false); + } + } + + if (pass == 1 && returnValueCount > 1) { + FilePrintFormat(output, "]"); + } + } + + if (returnValueCount == 0) { + FilePrintFormat(output, "void"); + } + + FilePrintFormat(output, " %s(", entry->children[0].name); bool firstArgument = true; @@ -1307,8 +1458,7 @@ void OutputScript(Entry *root) { && 0 == strcmp(entry->annotations[i].children[0].name, argument->name)) { goto skipArgument; } else if ((0 == strcmp(entry->annotations[i].name, "array_in") - || 0 == strcmp(entry->annotations[i].name, "buffer_in") - || 0 == strcmp(entry->annotations[i].name, "buffer_out")) + || 0 == strcmp(entry->annotations[i].name, "buffer_in")) && 0 == strcmp(entry->annotations[i].children[1].name, argument->name)) { goto skipArgument; } else if ((0 == strcmp(entry->annotations[i].name, "buffer_in")