mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-15 17:02:53 +08:00
607 lines
22 KiB
C
607 lines
22 KiB
C
/*
|
|
* This file is part of the PikaScript project.
|
|
* http://github.com/pikastech/pikascript
|
|
*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2021 lyon 李昂 liang6516@outlook.com
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
#include "PikaCompiler.h"
|
|
#include "BaseObj.h"
|
|
#include "PikaObj.h"
|
|
#include "PikaParser.h"
|
|
#include "dataQueue.h"
|
|
#include "dataQueueObj.h"
|
|
#include "dataStack.h"
|
|
#include "dataStrs.h"
|
|
|
|
/* const Pool output redirect */
|
|
static void __handler_constPool_output_file(ConstPool* self, char* content) {
|
|
/* to ram */
|
|
uint16_t size = strGetSize(content) + 1;
|
|
self->arg_buff = arg_append(self->arg_buff, content, size);
|
|
/* to flash */
|
|
__platform_fwrite(content, 1, size, self->output_f);
|
|
}
|
|
|
|
/* instruct array output redirect */
|
|
static void __handler_instructArray_output_none(InstructArray* self,
|
|
InstructUnit* ins_unit) {
|
|
/* none */
|
|
}
|
|
|
|
static void __handler_instructArray_output_file(InstructArray* self,
|
|
InstructUnit* ins_unit) {
|
|
/* to flash */
|
|
__platform_fwrite(ins_unit, 1, instructUnit_getSize(), self->output_f);
|
|
}
|
|
|
|
/*
|
|
need implament :
|
|
__platform_fopen()
|
|
__platform_fwrite()
|
|
__platform_fclose()
|
|
*/
|
|
|
|
int pikaCompile(char* output_file_name, char* py_lines) {
|
|
ByteCodeFrame bytecode_frame = {0};
|
|
|
|
FILE* bytecode_f = __platform_fopen(output_file_name, "wb+");
|
|
/* main process */
|
|
|
|
/* step 1, get size of const pool and instruct array */
|
|
byteCodeFrame_init(&bytecode_frame);
|
|
bytecode_frame.const_pool.output_f = bytecode_f;
|
|
bytecode_frame.instruct_array.output_f = bytecode_f;
|
|
bytecode_frame.instruct_array.output_redirect_fun =
|
|
__handler_instructArray_output_none;
|
|
Parser_parsePyLines(NULL, &bytecode_frame, py_lines);
|
|
uint16_t const_pool_size = bytecode_frame.const_pool.size;
|
|
uint16_t instruct_array_size = bytecode_frame.instruct_array.size;
|
|
byteCodeFrame_deinit(&bytecode_frame);
|
|
|
|
/* step 2, write instruct array to file */
|
|
__platform_fwrite(&instruct_array_size, 1, 2, bytecode_f);
|
|
byteCodeFrame_init(&bytecode_frame);
|
|
bytecode_frame.const_pool.output_f = bytecode_f;
|
|
bytecode_frame.instruct_array.output_f = bytecode_f;
|
|
/* instruct array to file */
|
|
bytecode_frame.instruct_array.output_redirect_fun =
|
|
__handler_instructArray_output_file;
|
|
Parser_parsePyLines(NULL, &bytecode_frame, py_lines);
|
|
byteCodeFrame_deinit(&bytecode_frame);
|
|
|
|
/* step 3, write const pool to file */
|
|
__platform_fwrite(&const_pool_size, 1, 2, bytecode_f);
|
|
char void_ = 0;
|
|
/* add \0 at the start */
|
|
__platform_fwrite(&void_, 1, 1, bytecode_f);
|
|
byteCodeFrame_init(&bytecode_frame);
|
|
bytecode_frame.const_pool.output_f = bytecode_f;
|
|
bytecode_frame.instruct_array.output_f = bytecode_f;
|
|
/* const pool to file */
|
|
bytecode_frame.const_pool.output_redirect_fun =
|
|
__handler_constPool_output_file;
|
|
/* instruct array to none */
|
|
bytecode_frame.instruct_array.output_redirect_fun =
|
|
__handler_instructArray_output_none;
|
|
Parser_parsePyLines(NULL, &bytecode_frame, py_lines);
|
|
byteCodeFrame_deinit(&bytecode_frame);
|
|
|
|
/* deinit */
|
|
__platform_fclose(bytecode_f);
|
|
/* succeed */
|
|
return 0;
|
|
};
|
|
|
|
/*
|
|
need implament :
|
|
__platform_fopen()
|
|
__platform_fread()
|
|
__platform_fwrite()
|
|
__platform_fclose()
|
|
*/
|
|
int pikaCompileFileWithOutputName(char* output_file_name,
|
|
char* input_file_name) {
|
|
Args buffs = {0};
|
|
Arg* input_file_arg = arg_loadFile(NULL, input_file_name);
|
|
if (NULL == input_file_arg) {
|
|
return 1;
|
|
}
|
|
char* lines = (char*)arg_getBytes(input_file_arg);
|
|
/* replace the "\r\n" to "\n" */
|
|
lines = strsReplace(&buffs, lines, "\r\n", "\n");
|
|
/* clear the void line */
|
|
lines = strsReplace(&buffs, lines, "\n\n", "\n");
|
|
/* add '\n' at the end */
|
|
lines = strsAppend(&buffs, lines, "\n\n");
|
|
pikaCompile(output_file_name, lines);
|
|
arg_deinit(input_file_arg);
|
|
strsDeinit(&buffs);
|
|
return 0;
|
|
}
|
|
|
|
int pikaCompileFile(char* input_file_name) {
|
|
Args buffs = {0};
|
|
char* output_file_name = strsGetFirstToken(&buffs, input_file_name, '.');
|
|
output_file_name = strsAppend(&buffs, input_file_name, ".o");
|
|
pikaCompileFileWithOutputName(output_file_name, input_file_name);
|
|
strsDeinit(&buffs);
|
|
return 0;
|
|
}
|
|
|
|
LibObj* New_LibObj(Args* args) {
|
|
LibObj* self = New_TinyObj(NULL);
|
|
return self;
|
|
}
|
|
|
|
void LibObj_deinit(LibObj* self) {
|
|
obj_deinit(self);
|
|
}
|
|
|
|
/* add bytecode to lib, not copy the bytecode */
|
|
void LibObj_dynamicLink(LibObj* self, char* module_name, uint8_t* bytecode) {
|
|
if (!obj_isArgExist(self, module_name)) {
|
|
obj_newObj(self, module_name, "", New_TinyObj);
|
|
}
|
|
PikaObj* module_obj = obj_getObj(self, module_name);
|
|
obj_setStr(module_obj, "name", module_name);
|
|
obj_setPtr(module_obj, "bytecode", bytecode);
|
|
}
|
|
|
|
/* add bytecode to lib, and copy the bytecode to the buff in the lib */
|
|
int LibObj_staticLink(LibObj* self,
|
|
char* module_name,
|
|
uint8_t* bytecode,
|
|
size_t size) {
|
|
if (!obj_isArgExist(self, module_name)) {
|
|
obj_newObj(self, module_name, "", New_TinyObj);
|
|
}
|
|
PikaObj* module_obj = obj_getObj(self, module_name);
|
|
/* copy bytecode to buff */
|
|
obj_setBytes(module_obj, "buff", bytecode, size);
|
|
/* link to buff */
|
|
LibObj_dynamicLink(self, module_name, obj_getBytes(module_obj, "buff"));
|
|
return 0;
|
|
}
|
|
|
|
int LibObj_staticLinkFile(LibObj* self, char* input_file_name) {
|
|
Args buffs = {0};
|
|
/* read file */
|
|
Arg* input_file_arg = arg_loadFile(NULL, input_file_name);
|
|
char* module_name = strsGetLastToken(&buffs, input_file_name, '/');
|
|
|
|
/* cut off '.py.o' */
|
|
module_name[strlen(module_name) - (sizeof(".py.o") - 1)] = 0;
|
|
|
|
/* push bytecode */
|
|
LibObj_staticLink(self, module_name, arg_getBytes(input_file_arg),
|
|
arg_getBytesSize(input_file_arg));
|
|
|
|
/* deinit */
|
|
strsDeinit(&buffs);
|
|
arg_deinit(input_file_arg);
|
|
return 0;
|
|
}
|
|
|
|
static int32_t __foreach_handler_listModules(Arg* argEach, Args* context) {
|
|
if (argType_isObject(arg_getType(argEach))) {
|
|
PikaObj* module_obj = arg_getPtr(argEach);
|
|
__platform_printf("%s\r\n", obj_getStr(module_obj, "name"));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void LibObj_listModules(LibObj* self) {
|
|
args_foreach(self->list, __foreach_handler_listModules, NULL);
|
|
}
|
|
|
|
static int32_t __foreach_handler_writeBytecode(Arg* argEach, Args* context) {
|
|
FILE* out_file = args_getPtr(context, "out_file");
|
|
if (argType_isObject(arg_getType(argEach))) {
|
|
PikaObj* module_obj = arg_getPtr(argEach);
|
|
char* bytecode = obj_getPtr(module_obj, "bytecode");
|
|
size_t bytecode_size = obj_getBytesSize(module_obj, "buff");
|
|
size_t aline_size =
|
|
aline_by(bytecode_size, sizeof(uint32_t)) - bytecode_size;
|
|
char aline_buff[sizeof(uint32_t)] = {0};
|
|
__platform_fwrite(bytecode, 1, bytecode_size, out_file);
|
|
__platform_fwrite(aline_buff, 1, aline_size, out_file);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int32_t __foreach_handler_writeIndex(Arg* argEach, Args* context) {
|
|
FILE* out_file = args_getPtr(context, "out_file");
|
|
if (argType_isObject(arg_getType(argEach))) {
|
|
PikaObj* module_obj = arg_getPtr(argEach);
|
|
uint32_t bytecode_size = obj_getBytesSize(module_obj, "buff");
|
|
char buff[LIB_INFO_BLOCK_SIZE - sizeof(uint32_t)] = {0};
|
|
bytecode_size = aline_by(bytecode_size, sizeof(uint32_t));
|
|
char* module_name = obj_getStr(module_obj, "name");
|
|
__platform_memcpy(buff, module_name, strGetSize(module_name));
|
|
__platform_fwrite(buff, 1, LIB_INFO_BLOCK_SIZE - sizeof(bytecode_size),
|
|
out_file);
|
|
__platform_fwrite(&bytecode_size, 1, sizeof(bytecode_size), out_file);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int32_t __foreach_handler_getModuleNum(Arg* argEach, Args* context) {
|
|
if (argType_isObject(arg_getType(argEach))) {
|
|
args_setInt(context, "module_num",
|
|
args_getInt(context, "module_num") + 1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int LibObj_saveLibraryFile(LibObj* self, char* output_file_name) {
|
|
FILE* out_file = __platform_fopen(output_file_name, "wb+");
|
|
|
|
Args context = {0};
|
|
args_setPtr(&context, "out_file", out_file);
|
|
args_setInt(&context, "module_num", 0);
|
|
|
|
/* write meta information */
|
|
char buff[LIB_INFO_BLOCK_SIZE] = {0};
|
|
args_foreach(self->list, __foreach_handler_getModuleNum, &context);
|
|
|
|
/* meta info */
|
|
char magic_code[] = {0x7f, 'p', 'y', 'a'};
|
|
uint32_t version_num = 1;
|
|
uint32_t module_num = args_getInt(&context, "module_num");
|
|
|
|
/* write meta info */
|
|
const uint32_t magic_code_offset = sizeof(uint32_t) * 0;
|
|
const uint32_t version_offset = sizeof(uint32_t) * 1;
|
|
const uint32_t module_num_offset = sizeof(uint32_t) * 2;
|
|
|
|
__platform_memcpy(buff + magic_code_offset, &magic_code, sizeof(uint32_t));
|
|
__platform_memcpy(buff + version_offset, &version_num, sizeof(uint32_t));
|
|
/* write module_num to the file */
|
|
__platform_memcpy(buff + module_num_offset, &module_num, sizeof(uint32_t));
|
|
/* aline to 32 bytes */
|
|
__platform_fwrite(buff, 1, LIB_INFO_BLOCK_SIZE, out_file);
|
|
/* write module index to file */
|
|
args_foreach(self->list, __foreach_handler_writeIndex, &context);
|
|
/* write module bytecode to file */
|
|
args_foreach(self->list, __foreach_handler_writeBytecode, &context);
|
|
args_deinit_stack(&context);
|
|
/* main process */
|
|
/* deinit */
|
|
__platform_fclose(out_file);
|
|
return 0;
|
|
}
|
|
|
|
int LibObj_loadLibrary(LibObj* self, uint8_t* library_bytes) {
|
|
if (0 != ((intptr_t)library_bytes & 0x03)) {
|
|
return PIKA_RES_ERR_UNALIGNED_PTR;
|
|
}
|
|
|
|
char* magic_code = (char*)library_bytes;
|
|
|
|
uint32_t* library_info = (uint32_t*)library_bytes;
|
|
uint32_t version_num = library_info[1];
|
|
uint32_t module_num = library_info[2];
|
|
|
|
/* check magic_code */
|
|
if (!((magic_code[0] == 0x7f) && (magic_code[1] == 'p') &&
|
|
(magic_code[2] == 'y') && (magic_code[3] == 'a'))) {
|
|
__platform_printf("Error: invalid magic code.\r\n");
|
|
return PIKA_RES_ERR_ILLEGAL_MAGIC_CODE;
|
|
}
|
|
/* check version num */
|
|
if (version_num != LIB_VERSION_NUMBER) {
|
|
__platform_printf(
|
|
"Error: invalid version number. Expected %, got %\r\n",
|
|
LIB_VERSION_NUMBER, version_num);
|
|
return PIKA_RES_ERR_INVALID_VERSION_NUMBER;
|
|
}
|
|
uint8_t* bytecode_addr =
|
|
library_bytes + LIB_INFO_BLOCK_SIZE * (module_num + 1);
|
|
for (uint32_t i = 0; i < module_num; i++) {
|
|
char* module_name =
|
|
(char*)(library_bytes + LIB_INFO_BLOCK_SIZE * (i + 1));
|
|
LibObj_dynamicLink(self, module_name, bytecode_addr);
|
|
uint32_t module_size =
|
|
*(uint32_t*)(module_name + LIB_INFO_BLOCK_SIZE - sizeof(uint32_t));
|
|
bytecode_addr += module_size;
|
|
}
|
|
return PIKA_RES_OK;
|
|
}
|
|
|
|
int LibObj_loadLibraryFile(LibObj* self, char* lib_file_name) {
|
|
Arg* file_arg = arg_loadFile(NULL, lib_file_name);
|
|
if (NULL == file_arg) {
|
|
__platform_printf("Error: Could not load library file '%s'\n",
|
|
lib_file_name);
|
|
return PIKA_RES_ERR_IO_ERROR;
|
|
}
|
|
/* save file_arg as __lib_buf to libObj */
|
|
obj_setArg_noCopy(self, "__lib_buf", file_arg);
|
|
if (0 != LibObj_loadLibrary(self, arg_getBytes(file_arg))) {
|
|
__platform_printf("Error: Could not load library from '%s'\n",
|
|
lib_file_name);
|
|
return PIKA_RES_ERR_OPERATION_FAILED;
|
|
}
|
|
return PIKA_RES_OK;
|
|
}
|
|
|
|
size_t pika_fputs(char* str, FILE* fp) {
|
|
size_t size = strGetSize(str);
|
|
return __platform_fwrite(str, 1, size, fp);
|
|
}
|
|
|
|
int Lib_loadLibraryFileToArray(char* origin_file_name, char* out_folder) {
|
|
Args buffs = {0};
|
|
Arg* file_arg = arg_loadFile(NULL, origin_file_name);
|
|
int res = 0;
|
|
if (NULL == file_arg) {
|
|
__platform_printf("Error: Could not load file '%s'\n",
|
|
origin_file_name);
|
|
return 1;
|
|
}
|
|
char* output_file_name = NULL;
|
|
output_file_name = strsGetLastToken(&buffs, origin_file_name, '/');
|
|
output_file_name = strsAppend(&buffs, "__asset_", output_file_name);
|
|
output_file_name = strsReplace(&buffs, output_file_name, ".", "_");
|
|
output_file_name = strsAppend(&buffs, output_file_name, ".c");
|
|
|
|
char* output_file_path = strsAppend(&buffs, out_folder, "/");
|
|
output_file_path = strsAppend(&buffs, output_file_path, output_file_name);
|
|
|
|
FILE* fp = __platform_fopen(output_file_path, "wb+");
|
|
char* array_name = strsGetLastToken(&buffs, origin_file_name, '/');
|
|
array_name = strsReplace(&buffs, array_name, ".", "_");
|
|
__platform_printf(" loading %s[]...\n", array_name);
|
|
pika_fputs("#include \"PikaPlatform.h\"\n", fp);
|
|
pika_fputs("/* warning: auto generated file, please do not modify */\n",
|
|
fp);
|
|
pika_fputs("PIKA_BYTECODE_ALIGN const unsigned char ", fp);
|
|
pika_fputs(array_name, fp);
|
|
pika_fputs("[] = {", fp);
|
|
char byte_buff[32] = {0};
|
|
uint8_t* array = arg_getBytes(file_arg);
|
|
for (size_t i = 0; i < arg_getBytesSize(file_arg); i++) {
|
|
if (i % 12 == 0) {
|
|
pika_fputs("\n ", fp);
|
|
}
|
|
__platform_sprintf(byte_buff, "0x%02x, ", array[i]);
|
|
pika_fputs(byte_buff, fp);
|
|
}
|
|
|
|
pika_fputs("\n};\n", fp);
|
|
res = 0;
|
|
goto exit;
|
|
|
|
exit:
|
|
__platform_fclose(fp);
|
|
strsDeinit(&buffs);
|
|
arg_deinit(file_arg);
|
|
return res;
|
|
}
|
|
|
|
static void __Maker_compileModuleWithInfo(PikaMaker* self, char* module_name) {
|
|
Args buffs = {0};
|
|
char* input_file_name = strsAppend(&buffs, module_name, ".py");
|
|
char* input_file_path =
|
|
strsAppend(&buffs, obj_getStr(self, "pwd"), input_file_name);
|
|
__platform_printf(" compiling %s...\r\n", input_file_name);
|
|
char* output_file_name = strsAppend(&buffs, module_name, ".py.o");
|
|
char* output_file_path = NULL;
|
|
output_file_path =
|
|
strsAppend(&buffs, obj_getStr(self, "pwd"), "pikascript-api/");
|
|
output_file_path = strsAppend(&buffs, output_file_path, output_file_name);
|
|
pikaCompileFileWithOutputName(output_file_path, input_file_path);
|
|
strsDeinit(&buffs);
|
|
}
|
|
|
|
PikaMaker* New_PikaMaker(void) {
|
|
PikaMaker* self = New_TinyObj(NULL);
|
|
obj_setStr(self, "pwd", "");
|
|
return self;
|
|
}
|
|
|
|
void pikaMaker_setPWD(PikaMaker* self, char* pwd) {
|
|
obj_setStr(self, "pwd", pwd);
|
|
}
|
|
|
|
void pikaMaker_setState(PikaMaker* self, char* module_name, char* state) {
|
|
obj_newMetaObj(self, module_name, New_TinyObj);
|
|
PikaObj* module_obj = obj_getObj(self, module_name);
|
|
obj_setStr(module_obj, "name", module_name);
|
|
obj_setStr(module_obj, "state", state);
|
|
}
|
|
|
|
void pikaMaker_compileModule(PikaMaker* self, char* module_name) {
|
|
__Maker_compileModuleWithInfo(self, module_name);
|
|
/* update compile info */
|
|
pikaMaker_setState(self, module_name, "compiled");
|
|
}
|
|
|
|
int pikaMaker_getDependencies(PikaMaker* self, char* module_name) {
|
|
int res = 0;
|
|
ByteCodeFrame bf = {0};
|
|
Args buffs = {0};
|
|
byteCodeFrame_init(&bf);
|
|
ConstPool* const_pool = NULL;
|
|
InstructArray* ins_array = NULL;
|
|
char* module_path =
|
|
strsAppend(&buffs, obj_getStr(self, "pwd"), "pikascript-api/");
|
|
module_path = strsAppend(&buffs, module_path, module_name);
|
|
char* file_path = strsAppend(&buffs, module_path, ".py.o");
|
|
Arg* file_arg = arg_loadFile(NULL, file_path);
|
|
uint8_t offset_befor = 0;
|
|
if (NULL == file_arg) {
|
|
res = 1;
|
|
goto exit;
|
|
}
|
|
byteCodeFrame_loadByteCode(&bf, arg_getBytes(file_arg));
|
|
const_pool = &bf.const_pool;
|
|
ins_array = &bf.instruct_array;
|
|
|
|
offset_befor = ins_array->content_offset_now;
|
|
ins_array->content_offset_now = 0;
|
|
while (1) {
|
|
InstructUnit* ins_unit = instructArray_getNow(ins_array);
|
|
if (NULL == ins_unit) {
|
|
goto exit;
|
|
}
|
|
if (instructUnit_getInstruct(ins_unit) == IMP) {
|
|
char* imp_module_name =
|
|
constPool_getByOffset(const_pool, ins_unit->const_pool_index);
|
|
char* imp_module_path =
|
|
strsAppend(&buffs, obj_getStr(self, "pwd"), imp_module_name);
|
|
/* check if compiled the module */
|
|
if (obj_isArgExist(self, imp_module_name)) {
|
|
/* module info is exist, do nothing */
|
|
} else {
|
|
/* module info is not exist */
|
|
/* set module to be compile */
|
|
FILE* imp_file_py = __platform_fopen(
|
|
strsAppend(&buffs, imp_module_path, ".py"), "rb");
|
|
FILE* imp_file_pyi = __platform_fopen(
|
|
strsAppend(&buffs, imp_module_path, ".pyi"), "rb");
|
|
if (NULL != imp_file_py) {
|
|
/* found *.py, push to nocompiled list */
|
|
pikaMaker_setState(self, imp_module_name, "nocompiled");
|
|
__platform_fclose(imp_file_py);
|
|
} else if (NULL != imp_file_pyi) {
|
|
/* found *.py, push to nocompiled list */
|
|
pikaMaker_setState(self, imp_module_name, "cmodule");
|
|
__platform_fclose(imp_file_pyi);
|
|
} else {
|
|
__platform_printf(
|
|
" [warning]: file: '%s.pyi' or '%s.py' no found\n",
|
|
imp_module_name, imp_module_name);
|
|
}
|
|
}
|
|
}
|
|
instructArray_getNext(ins_array);
|
|
}
|
|
|
|
exit:
|
|
ins_array->content_offset_now = offset_befor;
|
|
if (NULL != file_arg) {
|
|
arg_deinit(file_arg);
|
|
}
|
|
strsDeinit(&buffs);
|
|
byteCodeFrame_deinit(&bf);
|
|
return res;
|
|
}
|
|
|
|
int32_t __foreach_handler_printStates(Arg* argEach, Args* context) {
|
|
if (argType_isObject(arg_getType(argEach))) {
|
|
PikaObj* module_obj = arg_getPtr(argEach);
|
|
__platform_printf("%s: %s\r\n", obj_getStr(module_obj, "name"),
|
|
obj_getStr(module_obj, "state"));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void pikaMaker_printStates(PikaMaker* self) {
|
|
args_foreach(self->list, __foreach_handler_printStates, NULL);
|
|
}
|
|
|
|
int32_t __foreach_handler_getFirstNocompiled(Arg* argEach, Args* context) {
|
|
if (argType_isObject(arg_getType(argEach))) {
|
|
PikaObj* module_obj = arg_getPtr(argEach);
|
|
char* state = obj_getStr(module_obj, "state");
|
|
if (args_isArgExist(context, "res")) {
|
|
/* already get method */
|
|
return 0;
|
|
}
|
|
if (strEqu("nocompiled", state)) {
|
|
/* push module */
|
|
args_setStr(context, "res", obj_getStr(module_obj, "name"));
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char* pikaMaker_getFirstNocompiled(PikaMaker* self) {
|
|
Args context = {0};
|
|
args_foreach(self->list, __foreach_handler_getFirstNocompiled, &context);
|
|
char* res = args_getStr(&context, "res");
|
|
if (NULL == res) {
|
|
/* remove res in maker */
|
|
obj_removeArg(self, "res");
|
|
} else {
|
|
obj_setStr(self, "res", res);
|
|
}
|
|
args_deinit_stack(&context);
|
|
return obj_getStr(self, "res");
|
|
}
|
|
|
|
void pikaMaker_compileModuleWithDepends(PikaMaker* self, char* module_name) {
|
|
pikaMaker_compileModule(self, module_name);
|
|
pikaMaker_getDependencies(self, module_name);
|
|
while (1) {
|
|
char* uncompiled = pikaMaker_getFirstNocompiled(self);
|
|
/* compiled all modules */
|
|
if (NULL == uncompiled) {
|
|
break;
|
|
}
|
|
pikaMaker_compileModule(self, uncompiled);
|
|
pikaMaker_getDependencies(self, uncompiled);
|
|
}
|
|
}
|
|
|
|
int32_t __foreach_handler_linkCompiledModules(Arg* argEach, Args* context) {
|
|
Args buffs = {0};
|
|
if (argType_isObject(arg_getType(argEach))) {
|
|
LibObj* lib = args_getPtr(context, "__lib");
|
|
PikaMaker* maker = args_getPtr(context, "__maker");
|
|
PikaObj* module_obj = arg_getPtr(argEach);
|
|
char* module_name = obj_getStr(module_obj, "name");
|
|
char* state = obj_getStr(module_obj, "state");
|
|
if (strEqu(state, "compiled")) {
|
|
char* pwd = obj_getStr(maker, "pwd");
|
|
char* folder_path = strsAppend(&buffs, pwd, "pikascript-api/");
|
|
char* module_file_name = strsAppend(&buffs, module_name, ".py.o");
|
|
char* module_file_path =
|
|
strsAppend(&buffs, folder_path, module_file_name);
|
|
LibObj_staticLinkFile(lib, module_file_path);
|
|
}
|
|
}
|
|
strsDeinit(&buffs);
|
|
return 0;
|
|
}
|
|
|
|
void pikaMaker_linkCompiledModules(PikaMaker* self, char* lib_name) {
|
|
Args context = {0};
|
|
LibObj* lib = New_LibObj(NULL);
|
|
Args buffs = {0};
|
|
__platform_printf(" linking %s...\n", lib_name);
|
|
args_setPtr(&context, "__lib", lib);
|
|
args_setPtr(&context, "__maker", self);
|
|
args_foreach(self->list, __foreach_handler_linkCompiledModules, &context);
|
|
args_deinit_stack(&context);
|
|
char* pwd = obj_getStr(self, "pwd");
|
|
char* folder_path = strsAppend(&buffs, pwd, "pikascript-api/");
|
|
char* lib_file_path = strsAppend(&buffs, folder_path, lib_name);
|
|
LibObj_saveLibraryFile(lib, lib_file_path);
|
|
Lib_loadLibraryFileToArray(lib_file_path, folder_path);
|
|
LibObj_deinit(lib);
|
|
strsDeinit(&buffs);
|
|
}
|