2332 lines
77 KiB
C
Raw Normal View History

2022-06-24 00:21:00 +08:00
/*
* 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 "PikaVM.h"
#include "BaseObj.h"
#include "PikaCompiler.h"
#include "PikaObj.h"
#include "PikaParser.h"
#include "PikaPlatform.h"
#include "dataStrs.h"
#if PIKA_MATH_ENABLE
#include <math.h>
#endif
2022-06-24 00:21:00 +08:00
/* head declear start */
static uint8_t VMState_getInputArgNum(VMState* vs);
static VMParameters* __pikaVM_runByteCodeFrameWithState(
PikaObj* self,
VMParameters* locals,
VMParameters* globals,
ByteCodeFrame* bytecode_frame,
uint16_t pc,
TryInfo* try_info);
2022-06-24 00:21:00 +08:00
/* head declear end */
static InstructUnit* VMState_getInstructNow(VMState* vs) {
return instructArray_getByOffset(&(vs->bytecode_frame->instruct_array),
vs->pc);
}
static void VMState_setErrorCode(VMState* vs, uint8_t error_code) {
vs->error_code = error_code;
}
static InstructUnit* VMState_getInstructWithOffset(VMState* vs,
int32_t offset) {
return instructArray_getByOffset(&(vs->bytecode_frame->instruct_array),
vs->pc + offset);
}
static int VMState_getBlockDeepthNow(VMState* vs) {
/* support run byteCode */
InstructUnit* ins_unit = VMState_getInstructNow(vs);
return instructUnit_getBlockDeepth(ins_unit);
}
static char* VMState_getConstWithInstructUnit(VMState* vs,
InstructUnit* ins_unit) {
return constPool_getByOffset(&(vs->bytecode_frame->const_pool),
instructUnit_getConstPoolIndex(ins_unit));
}
static int32_t VMState_getAddrOffsetOfJmpBack(VMState* vs) {
2022-06-24 00:21:00 +08:00
int offset = 0;
int loop_deepth = -1;
/* find loop deepth */
2022-06-24 00:21:00 +08:00
while (1) {
offset -= instructUnit_getSize(ins_unit_now);
InstructUnit* ins_unit_now = VMState_getInstructWithOffset(vs, offset);
2022-06-24 00:21:00 +08:00
uint16_t invoke_deepth = instructUnit_getInvokeDeepth(ins_unit_now);
enum Instruct ins = instructUnit_getInstruct(ins_unit_now);
char* data = VMState_getConstWithInstructUnit(vs, ins_unit_now);
if ((0 == invoke_deepth) && (JEZ == ins) && strEqu(data, "2")) {
loop_deepth = instructUnit_getBlockDeepth(ins_unit_now);
break;
}
}
offset = 0;
while (1) {
offset += instructUnit_getSize(ins_unit_now);
InstructUnit* ins_unit_now = VMState_getInstructWithOffset(vs, offset);
enum Instruct ins = instructUnit_getInstruct(ins_unit_now);
char* data = VMState_getConstWithInstructUnit(vs, ins_unit_now);
int block_deepth_now = instructUnit_getBlockDeepth(ins_unit_now);
if ((block_deepth_now == loop_deepth) && (JMP == ins) &&
strEqu(data, "-1")) {
2022-06-24 00:21:00 +08:00
return offset;
}
}
}
static size_t VMState_getInstructArraySize(VMState* vs) {
return instructArray_getSize(&(vs->bytecode_frame->instruct_array));
}
static int32_t VMState_getAddrOffsetFromJmp(VMState* vs) {
int offset = 0;
/* run byte Code */
InstructUnit* this_ins_unit = VMState_getInstructNow(vs);
int thisBlockDeepth = instructUnit_getBlockDeepth(this_ins_unit);
int8_t blockNum = 0;
if (vs->jmp > 0) {
offset = 0;
while (1) {
offset += instructUnit_getSize();
/* reach the end */
if (vs->pc + offset >= (int)VMState_getInstructArraySize(vs)) {
break;
}
this_ins_unit = VMState_getInstructWithOffset(vs, offset);
if (instructUnit_getIsNewLine(this_ins_unit)) {
uint8_t blockDeepth =
instructUnit_getBlockDeepth(this_ins_unit);
if (blockDeepth <= thisBlockDeepth) {
blockNum++;
}
}
if (blockNum >= vs->jmp) {
break;
}
}
}
if (vs->jmp < 0) {
while (1) {
offset -= instructUnit_getSize();
this_ins_unit = VMState_getInstructWithOffset(vs, offset);
if (instructUnit_getIsNewLine(this_ins_unit)) {
uint8_t blockDeepth =
instructUnit_getBlockDeepth(this_ins_unit);
if (blockDeepth == thisBlockDeepth) {
blockNum--;
}
}
if (blockNum <= vs->jmp) {
break;
}
}
}
return offset;
}
static int32_t VMState_getAddrOffsetOfBreak(VMState* vs) {
int32_t offset = VMState_getAddrOffsetOfJmpBack(vs);
2022-06-24 00:21:00 +08:00
/* byteCode */
offset += instructUnit_getSize();
return offset;
}
static int32_t VMState_getAddrOffsetOfRaise(VMState* vs) {
int offset = 0;
InstructUnit* ins_unit_now = VMState_getInstructNow(vs);
while (1) {
offset += instructUnit_getSize(ins_unit_now);
ins_unit_now = VMState_getInstructWithOffset(vs, offset);
enum Instruct ins = instructUnit_getInstruct(ins_unit_now);
if ((NTR == ins)) {
return offset;
}
}
}
2022-06-24 00:21:00 +08:00
static int32_t VMState_getAddrOffsetOfContinue(VMState* vs) {
int32_t offset = VMState_getAddrOffsetOfJmpBack(vs);
2022-06-24 00:21:00 +08:00
/* byteCode */
return offset;
}
static void VMState_delLReg(VMState* vs, uint8_t index) {
PikaObj* obj = vs->lreg[index];
if (NULL != obj) {
obj_refcntDec(obj);
vs->lreg[index] = NULL;
if (0 == obj_refcntNow(obj)) {
obj_deinit(obj);
}
}
}
static void VMState_initReg(VMState* vs) {
for (uint8_t i = 0; i < PIKA_REGIST_SIZE; i++) {
vs->lreg[i] = NULL;
vs->ireg[i] = 0;
}
}
2022-06-24 00:21:00 +08:00
static PIKA_BOOL _checkLReg(char* data) {
if ((data[0] == '_') && (data[1] == 'l') && (data[2] >= '0') &&
(data[2] <= '9')) {
return PIKA_TRUE;
}
return PIKA_FALSE;
}
static uint8_t _getLRegIndex(char* data) {
return data[2] - '0';
}
static void VMState_setLReg(VMState* vs, uint8_t index, PikaObj* obj) {
obj_refcntInc(obj);
vs->lreg[index] = obj;
}
typedef Arg* (*VM_instruct_handler)(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg);
static Arg* VM_instruction_handler_NON(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
return NULL;
}
Arg* __vm_get(PikaObj* self, Arg* key, Arg* obj) {
ArgType obj_type = arg_getType(obj);
int index = 0;
if (ARG_TYPE_INT == arg_getType(key)) {
index = arg_getInt(key);
}
if (ARG_TYPE_STRING == obj_type) {
char* str_pyload = arg_getStr(obj);
char char_buff[] = " ";
if (index < 0) {
index = strGetSize(str_pyload) + index;
}
char_buff[0] = str_pyload[index];
return arg_newStr(char_buff);
}
if (ARG_TYPE_BYTES == obj_type) {
uint8_t* bytes_pyload = arg_getBytes(obj);
uint8_t byte_buff[] = " ";
if (index < 0) {
index = arg_getBytesSize(obj) + index;
}
byte_buff[0] = bytes_pyload[index];
return arg_newBytes(byte_buff, 1);
}
if (argType_isObject(obj_type)) {
PikaObj* arg_obj = arg_getPtr(obj);
obj_setArg(arg_obj, "__key", key);
/* clang-format off */
PIKA_PYTHON(
__res = __getitem__(__key)
)
/* clang-format on */
const uint8_t bytes[] = {
0x0c, 0x00, /* instruct array size */
0x10, 0x81, 0x01, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x04, 0x13,
0x00,
/* instruct array */
0x19, 0x00, /* const pool size */
0x00, 0x5f, 0x5f, 0x6b, 0x65, 0x79, 0x00, 0x5f, 0x5f, 0x67, 0x65,
0x74, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x5f, 0x00, 0x5f, 0x5f, 0x72,
0x65, 0x73, 0x00,
/* const pool */
};
pikaVM_runByteCode(arg_obj, (uint8_t*)bytes);
return arg_copy(args_getArg(arg_obj->list, "__res"));
}
return arg_newNull();
}
Arg* __vm_slice(PikaObj* self, Arg* end, Arg* obj, Arg* start, int step) {
#if PIKA_SYNTAX_SLICE_ENABLE
/* No interger index only support __getitem__ */
if (!(arg_getType(start) == ARG_TYPE_INT &&
arg_getType(end) == ARG_TYPE_INT)) {
return __vm_get(self, start, obj);
}
int start_i = arg_getInt(start);
int end_i = arg_getInt(end);
/* __slice__ is equal to __getitem__ */
if (end_i - start_i == 1) {
return __vm_get(self, start, obj);
}
if (ARG_TYPE_STRING == arg_getType(obj)) {
size_t len = strGetSize(arg_getStr(obj));
if (start_i < 0) {
start_i += len;
}
if (end_i < 0) {
end_i += len + 1;
}
Arg* sliced_arg = arg_newStr("");
for (int i = start_i; i < end_i; i++) {
Arg* i_arg = arg_newInt(i);
Arg* item_arg = __vm_get(self, i_arg, obj);
sliced_arg = arg_strAppend(sliced_arg, arg_getStr(item_arg));
arg_deinit(item_arg);
arg_deinit(i_arg);
}
return sliced_arg;
}
if (ARG_TYPE_BYTES == arg_getType(obj)) {
size_t len = arg_getBytesSize(obj);
if (start_i < 0) {
start_i += len;
}
if (end_i < 0) {
end_i += len + 1;
}
Arg* sliced_arg = arg_newBytes(NULL, 0);
for (int i = start_i; i < end_i; i++) {
Arg* i_arg = arg_newInt(i);
Arg* item_arg = __vm_get(self, i_arg, obj);
uint8_t* bytes_origin = arg_getBytes(sliced_arg);
size_t size_origin = arg_getBytesSize(sliced_arg);
Arg* sliced_arg_new = arg_newBytes(NULL, size_origin + 1);
__platform_memcpy(arg_getBytes(sliced_arg_new), bytes_origin,
size_origin);
__platform_memcpy(arg_getBytes(sliced_arg_new) + size_origin,
arg_getBytes(item_arg), 1);
arg_deinit(sliced_arg);
sliced_arg = sliced_arg_new;
arg_deinit(item_arg);
arg_deinit(i_arg);
}
return sliced_arg;
}
return arg_newNull();
#else
return __vm_get(self, start, obj);
#endif
}
static Arg* VM_instruction_handler_SLC(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
#if PIKA_SYNTAX_SLICE_ENABLE
int arg_num_input = VMState_getInputArgNum(vs);
if (arg_num_input < 2) {
return arg_newNull();
}
if (arg_num_input == 2) {
Arg* key = stack_popArg_alloc(&vs->stack);
Arg* obj = stack_popArg_alloc(&vs->stack);
Arg* res = __vm_get(self, key, obj);
arg_deinit(key);
arg_deinit(obj);
return res;
}
if (arg_num_input == 3) {
Arg* end = stack_popArg_alloc(&vs->stack);
Arg* start = stack_popArg_alloc(&vs->stack);
Arg* obj = stack_popArg_alloc(&vs->stack);
Arg* res = __vm_slice(self, end, obj, start, 1);
arg_deinit(end);
arg_deinit(obj);
arg_deinit(start);
return res;
}
return arg_newNull();
#else
Arg* key = stack_popArg_alloc(&vs->stack);
Arg* obj = stack_popArg_alloc(&vs->stack);
Arg* res = __vm_get(self, key, obj);
arg_deinit(key);
arg_deinit(obj);
return res;
#endif
}
static Arg* VM_instruction_handler_TRY(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
pika_assert(NULL != vs->try_info);
vs->try_info->try_state = TRY_STATE_TOP;
return NULL;
}
static Arg* VM_instruction_handler_NTR(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
vs->try_info->try_state = TRY_STATE_NONE;
return NULL;
}
static Arg* VM_instruction_handler_NEW(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
Arg* origin_arg = obj_getArg(vs->locals, data);
Arg* new_arg = arg_copy(origin_arg);
origin_arg = arg_setType(origin_arg, ARG_TYPE_OBJECT);
arg_setType(new_arg, ARG_TYPE_OBJECT_NEW);
return new_arg;
}
static Arg* VM_instruction_handler_REF(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
if (strEqu(data, (char*)"True")) {
return arg_setInt(arg_ret_reg, "", 1);
2022-06-24 00:21:00 +08:00
}
if (strEqu(data, (char*)"False")) {
return arg_setInt(arg_ret_reg, "", 0);
2022-06-24 00:21:00 +08:00
}
if (strEqu(data, (char*)"None")) {
return arg_setNull(arg_ret_reg);
}
if (strEqu(data, (char*)"RuntimeError")) {
return arg_setInt(arg_ret_reg, "", PIKA_RES_ERR_RUNTIME_ERROR);
}
Arg* arg = NULL;
if (data[0] == '.') {
/* find host from stack */
Arg* host_obj = stack_popArg_alloc(&(vs->stack));
if (argType_isObject(arg_getType(host_obj))) {
arg = arg_copy_noalloc(obj_getArg(arg_getPtr(host_obj), data + 1),
arg_ret_reg);
}
arg_deinit(host_obj);
} else {
/* find in local list first */
arg = arg_copy_noalloc(obj_getArg(vs->locals, data), arg_ret_reg);
if (NULL == arg) {
/* find in global list second */
arg = arg_copy_noalloc(obj_getArg(vs->globals, data), arg_ret_reg);
}
2022-06-24 00:21:00 +08:00
}
2022-06-24 00:21:00 +08:00
if (NULL == arg) {
VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND);
2022-06-24 00:21:00 +08:00
__platform_printf("NameError: name '%s' is not defined\r\n", data);
}
return arg;
}
static Arg* VM_instruction_handler_GER(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
PIKA_RES err = (PIKA_RES)vs->try_error_code;
Arg* err_arg = arg_newInt(err);
return err_arg;
}
2022-06-24 00:21:00 +08:00
static int32_t __foreach_handler_deinitTuple(Arg* argEach, Args* context) {
if (arg_getType(argEach) == ARG_TYPE_TUPLE) {
PikaTuple* tuple = arg_getPtr(argEach);
tuple_deinit(tuple);
}
return PIKA_RES_OK;
}
Arg* _obj_runMethodArgWithState(PikaObj* self,
PikaObj* method_args_obj,
Arg* method_arg,
TryInfo* try_state,
Arg* ret_arg_reg) {
pika_assert(NULL != try_state);
2022-06-24 00:21:00 +08:00
Arg* return_arg = NULL;
/* get method Ptr */
Method method_ptr = methodArg_getPtr(method_arg);
/* get method type list */
ArgType method_type = arg_getType(method_arg);
/* error */
if (ARG_TYPE_NONE == method_type) {
2022-06-24 00:21:00 +08:00
return NULL;
}
ByteCodeFrame* method_bytecodeFrame =
methodArg_getBytecodeFrame(method_arg);
PikaObj* method_context = methodArg_getDefContext(method_arg);
if (NULL != method_context) {
self = method_context;
}
obj_setErrorCode(self, PIKA_RES_OK);
2022-06-24 00:21:00 +08:00
/* run method */
if (method_type == ARG_TYPE_METHOD_NATIVE) {
/* native method */
method_ptr(self, method_args_obj->list);
2022-06-24 00:21:00 +08:00
/* get method return */
return_arg = arg_copy_noalloc(
args_getArg(method_args_obj->list, (char*)"return"), ret_arg_reg);
2022-06-24 00:21:00 +08:00
} else if (method_type == ARG_TYPE_METHOD_NATIVE_CONSTRUCTOR) {
/* native method */
method_ptr(self, method_args_obj->list);
2022-06-24 00:21:00 +08:00
/* get method return */
return_arg = arg_copy_noalloc(
args_getArg(method_args_obj->list, (char*)"return"), ret_arg_reg);
2022-06-24 00:21:00 +08:00
} else {
/* static method and object method */
/* byteCode */
uintptr_t insturctArray_start = (uintptr_t)instructArray_getByOffset(
&(method_bytecodeFrame->instruct_array), 0);
uint16_t pc = (uintptr_t)method_ptr - insturctArray_start;
method_args_obj = __pikaVM_runByteCodeFrameWithState(
self, method_args_obj, self, method_bytecodeFrame, pc, try_state);
2022-06-24 00:21:00 +08:00
/* get method return */
return_arg = arg_copy_noalloc(
args_getArg(method_args_obj->list, (char*)"return"), ret_arg_reg);
2022-06-24 00:21:00 +08:00
}
args_foreach(method_args_obj->list, __foreach_handler_deinitTuple, NULL);
return return_arg;
}
Arg* obj_runMethodArgWithState(PikaObj* self,
PikaObj* method_args_obj,
Arg* method_arg,
TryInfo* try_state) {
return _obj_runMethodArgWithState(self, method_args_obj, method_arg,
try_state, NULL);
}
Arg* obj_runMethodArgWithState_noalloc(PikaObj* self,
PikaObj* method_args_obj,
Arg* method_arg,
TryInfo* try_state,
Arg* ret_arg_reg) {
return _obj_runMethodArgWithState(self, method_args_obj, method_arg,
try_state, ret_arg_reg);
}
Arg* obj_runMethodArg(PikaObj* self,
PikaObj* method_args_obj,
Arg* method_arg) {
TryInfo try_info = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE};
return obj_runMethodArgWithState(self, method_args_obj, method_arg,
&try_info);
}
2022-06-24 00:21:00 +08:00
static int VMState_loadArgsFromMethodArg(VMState* vs,
PikaObj* method_host_obj,
Args* args,
Arg* method_arg,
char* method_name,
int arg_num_used) {
char _buffs1[PIKA_LINE_BUFF_SIZE / 2] = {0};
char* buffs1 = (char*)_buffs1;
char _buffs2[PIKA_LINE_BUFF_SIZE / 2] = {0};
char* buffs2 = (char*)_buffs2;
2022-06-24 00:21:00 +08:00
uint8_t arg_num_dec = 0;
PIKA_BOOL is_variable = PIKA_FALSE;
PIKA_BOOL is_get_variable_arg = PIKA_FALSE;
uint8_t arg_num = 0;
ArgType method_type = ARG_TYPE_UNDEF;
uint8_t arg_num_input = 0;
PikaTuple* tuple = NULL;
char* variable_tuple_name = NULL;
char* type_list_buff = NULL;
int variable_arg_start = 0;
2022-06-24 00:21:00 +08:00
/* get method type list */
char* type_list =
methodArg_getTypeList(method_arg, buffs1, sizeof(_buffs1));
2022-06-24 00:21:00 +08:00
if (NULL == type_list) {
__platform_printf(
"OverflowError: type list is too long, please use bigger "
"PIKA_LINE_BUFF_SIZE\r\n");
while (1)
;
2022-06-24 00:21:00 +08:00
}
method_type = arg_getType(method_arg);
2022-06-24 00:21:00 +08:00
/* check variable */
if (strIsContain(type_list, '*')) {
is_variable = PIKA_TRUE;
}
/* get arg_num_dec */
if (strEqu("", type_list)) {
arg_num_dec = 0;
} else {
arg_num_dec = strCountSign(type_list, ',') + 1;
}
if (method_type == ARG_TYPE_METHOD_OBJECT) {
/* delete the 'self' */
arg_num_dec--;
}
arg_num_input = VMState_getInputArgNum(vs);
2022-06-24 00:21:00 +08:00
/* check arg num */
if (method_type == ARG_TYPE_METHOD_NATIVE_CONSTRUCTOR ||
method_type == ARG_TYPE_METHOD_CONSTRUCTOR ||
is_variable == PIKA_TRUE) {
/* skip for constrctor */
/* skip for variable args */
} else {
/* check arg num decleard and input */
if (arg_num_dec != arg_num_input - arg_num_used) {
VMState_setErrorCode(vs, PIKA_RES_ERR_INVALID_PARAM);
2022-06-24 00:21:00 +08:00
__platform_printf(
"TypeError: %s() takes %d positional argument but %d were "
"given\r\n",
method_name, arg_num_dec, arg_num_input);
goto exit;
}
}
if (PIKA_TRUE == is_variable) {
arg_num = arg_num_input;
} else {
arg_num = arg_num_dec;
}
if (strIsContain(type_list, '*')) {
/* get variable tuple name */
type_list_buff = strCopy(buffs2, type_list);
variable_arg_start = 0;
for (int i = 0; i < arg_num_dec; i++) {
char* arg_def = strPopLastToken(type_list_buff, ',');
if (strIsStartWith(arg_def, "*")) {
/* skip the '*' */
variable_tuple_name = arg_def + 1;
variable_arg_start = arg_num_dec - i - 1;
is_get_variable_arg = PIKA_TRUE;
break;
}
2022-06-24 00:21:00 +08:00
}
}
/* found variable arg */
if (PIKA_TRUE == is_get_variable_arg) {
tuple = New_tuple();
strPopLastToken(type_list, ',');
}
/* load pars */
for (int i = 0; i < arg_num; i++) {
char* arg_name = NULL;
if (arg_num - i <= variable_arg_start) {
is_get_variable_arg = PIKA_FALSE;
}
if (PIKA_FALSE == is_get_variable_arg) {
char* arg_def = strPopLastToken(type_list, ',');
strPopLastToken(arg_def, ':');
arg_name = arg_def;
} else {
/* clear the variable arg name */
arg_name = "";
2022-06-24 00:21:00 +08:00
}
Arg* call_arg = stack_popArg_alloc(&(vs->stack));
2022-06-24 00:21:00 +08:00
call_arg = arg_setName(call_arg, arg_name);
/* load the variable arg */
if (PIKA_TRUE == is_get_variable_arg) {
list_append(&tuple->super, call_arg);
/* the append would copy the arg */
arg_deinit(call_arg);
} else {
/* load normal arg */
args_setArg(args, call_arg);
}
}
if (PIKA_TRUE == is_variable) {
/* resort the tuple */
PikaTuple* tuple_sorted = New_tuple();
if (NULL != tuple) {
int tuple_size = tuple_getSize(tuple);
for (int i = 0; i < tuple_size; i++) {
Arg* arg = tuple_getArg(tuple, tuple_size - 1 - i);
list_append(&(tuple_sorted->super), arg);
}
tuple_deinit(tuple);
}
/* load variable tuple */
args_setPtrWithType(args, variable_tuple_name, ARG_TYPE_TUPLE,
tuple_sorted);
}
/* load 'self' as the first arg when call object method */
if (method_type == ARG_TYPE_METHOD_OBJECT) {
Arg* call_arg = arg_setRef(NULL, "self", method_host_obj);
args_setArg(args, call_arg);
}
exit:
return arg_num;
}
void __vm_List_append(PikaObj* self, Arg* arg) {
PikaList* list = obj_getPtr(self, "list");
list_append(list, arg);
}
void __vm_List___init__(PikaObj* self) {
if (!obj_isArgExist(self, "list")) {
PikaList* list = New_list();
obj_setPtr(self, "list", list);
}
}
#if PIKA_BUILTIN_STRUCT_ENABLE
2022-06-24 00:21:00 +08:00
PikaObj* New_PikaStdData_List(Args* args);
PikaObj* New_PikaStdData_Tuple(Args* args);
2022-06-24 00:21:00 +08:00
#endif
static Arg* _vm_create_list_or_tuple(PikaObj* self,
VMState* vs,
PIKA_BOOL is_list) {
#if PIKA_BUILTIN_STRUCT_ENABLE
NewFun constructor = is_list ? New_PikaStdData_List : New_PikaStdData_Tuple;
2022-06-24 00:21:00 +08:00
uint8_t arg_num = VMState_getInputArgNum(vs);
PikaObj* list = newNormalObj(constructor);
__vm_List___init__(list);
2022-06-24 00:21:00 +08:00
Stack stack = {0};
stack_init(&stack);
/* load to local stack to change sort */
for (int i = 0; i < arg_num; i++) {
Arg* arg = stack_popArg_alloc(&(vs->stack));
2022-06-24 00:21:00 +08:00
stack_pushArg(&stack, arg);
}
for (int i = 0; i < arg_num; i++) {
Arg* arg = stack_popArg_alloc(&stack);
__vm_List_append(list, arg);
2022-06-24 00:21:00 +08:00
arg_deinit(arg);
}
stack_deinit(&stack);
return arg_newPtr(ARG_TYPE_OBJECT, list);
2022-06-24 00:21:00 +08:00
#else
return VM_instruction_handler_NON(self, vs, "", NULL);
2022-06-24 00:21:00 +08:00
#endif
}
static Arg* VM_instruction_handler_LST(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
return _vm_create_list_or_tuple(self, vs, PIKA_TRUE);
}
void __vm_Dict___init__(PikaObj* self) {
PikaDict* dict = New_dict();
PikaDict* keys = New_dict();
obj_setPtr(self, "dict", dict);
obj_setPtr(self, "_keys", keys);
}
void __vm_Dict_set(PikaObj* self, Arg* arg, char* key) {
PikaDict* dict = obj_getPtr(self, "dict");
PikaDict* keys = obj_getPtr(self, "_keys");
Arg* arg_key = arg_setStr(NULL, key, key);
Arg* arg_new = arg_copy(arg);
arg_setName(arg_new, key);
dict_setArg(dict, arg_new);
dict_setArg(keys, arg_key);
}
#if PIKA_BUILTIN_STRUCT_ENABLE
PikaObj* New_PikaStdData_Dict(Args* args);
#endif
static Arg* VM_instruction_handler_DCT(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
#if PIKA_BUILTIN_STRUCT_ENABLE
uint8_t arg_num = VMState_getInputArgNum(vs);
PikaObj* dict = newNormalObj(New_PikaStdData_Dict);
__vm_Dict___init__(dict);
Stack stack = {0};
stack_init(&stack);
/* load to local stack to change sort */
for (int i = 0; i < arg_num; i++) {
Arg* arg = stack_popArg_alloc(&(vs->stack));
stack_pushArg(&stack, arg);
}
for (int i = 0; i < arg_num / 2; i++) {
Arg* key_arg = stack_popArg_alloc(&stack);
Arg* val_arg = stack_popArg_alloc(&stack);
__vm_Dict_set(dict, val_arg, arg_getStr(key_arg));
arg_deinit(key_arg);
arg_deinit(val_arg);
}
stack_deinit(&stack);
return arg_newPtr(ARG_TYPE_OBJECT, dict);
#else
return VM_instruction_handler_NON(self, vs, data, arg_ret_reg);
#endif
}
static Arg* VM_instruction_handler_RUN(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
Arg* return_arg = NULL;
VMParameters* sub_locals = NULL;
char* methodPath = data;
PikaObj* method_host_obj = NULL;
2022-06-24 00:21:00 +08:00
Arg* method_arg = NULL;
Arg* host_arg = NULL;
PIKA_BOOL isClass = PIKA_FALSE;
2022-06-24 00:21:00 +08:00
char* sys_out;
int arg_num_used = 0;
arg_newReg(arg_reg1, 64);
TryInfo sub_try_info = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE};
pika_assert(NULL != vs->try_info);
if (vs->try_info->try_state == TRY_STATE_TOP ||
vs->try_error_code == TRY_STATE_INNER) {
sub_try_info.try_state = TRY_STATE_INNER;
}
/* tuple or single arg */
if (data[0] == 0) {
if (VMState_getInputArgNum(vs) < 2) {
/* return arg directly */
Arg* arg1 = stack_popArg(&(vs->stack), &arg_reg1);
return_arg = arg_copy_noalloc(arg1, arg_ret_reg);
arg_deinit(arg1);
goto exit;
}
/* create a tuple */
return_arg = _vm_create_list_or_tuple(self, vs, PIKA_FALSE);
2022-06-24 00:21:00 +08:00
goto exit;
}
2022-06-24 00:21:00 +08:00
/* return tiny obj */
if (strEqu(data, "TinyObj")) {
return_arg = arg_newMetaObj(New_TinyObj);
goto exit;
}
/* get method host obj from reg */
if (NULL == method_host_obj && _checkLReg(data)) {
uint8_t reg_index = _getLRegIndex(data);
method_host_obj = vs->lreg[reg_index];
}
/* get method host obj from stack */
if (NULL == method_host_obj && methodPath[0] == '.') {
/* get method host obj from stack */
Arg* stack_tmp[PIKA_ARG_NUM_MAX] = {0};
int arg_num = VMState_getInputArgNum(vs);
if (arg_num > PIKA_ARG_NUM_MAX) {
__platform_printf(
"[ERROR] Too many args in RUN instruction, please use bigger "
"#define PIKA_ARG_NUM_MAX\n");
while (1) {
}
}
for (int i = 0; i < arg_num; i++) {
stack_tmp[i] = stack_popArg_alloc(&(vs->stack));
}
host_arg = stack_tmp[arg_num - 1];
if (argType_isObject(arg_getType(host_arg))) {
method_host_obj = arg_getPtr(host_arg);
arg_num_used++;
}
/* push back other args to stack */
for (int i = arg_num - 2; i >= 0; i--) {
stack_pushArg(&(vs->stack), stack_tmp[i]);
}
}
2022-06-24 00:21:00 +08:00
/* get method host obj from self */
if (NULL == method_host_obj) {
method_host_obj = obj_getHostObjWithIsClass(self, methodPath, &isClass);
}
2022-06-24 00:21:00 +08:00
/* get method host obj from local scope */
if (NULL == method_host_obj) {
method_host_obj =
obj_getHostObjWithIsClass(vs->locals, methodPath, &isClass);
2022-06-24 00:21:00 +08:00
}
/* method host obj is not found */
2022-06-24 00:21:00 +08:00
if (NULL == method_host_obj) {
/* error, not found object */
VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND);
2022-06-24 00:21:00 +08:00
__platform_printf("Error: method '%s' no found.\r\n", data);
goto exit;
}
2022-06-24 00:21:00 +08:00
/* get method in local */
method_arg =
obj_getMethodArg_noalloc(method_host_obj, methodPath, &arg_reg1);
2022-06-24 00:21:00 +08:00
if (NULL == method_arg) {
/* get method in global */
method_arg =
obj_getMethodArg_noalloc(vs->globals, methodPath, &arg_reg1);
2022-06-24 00:21:00 +08:00
}
/* assert method type */
if (NULL == method_arg || ARG_TYPE_NONE == arg_getType(method_arg)) {
2022-06-24 00:21:00 +08:00
/* error, method no found */
VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND);
2022-06-24 00:21:00 +08:00
__platform_printf("NameError: name '%s' is not defined\r\n", data);
goto exit;
}
2022-06-24 00:21:00 +08:00
/* create sub local scope */
sub_locals = New_PikaObj();
2022-06-24 00:21:00 +08:00
/* load args from vmState to sub_local->list */
arg_num_used += VMState_loadArgsFromMethodArg(
vs, method_host_obj, sub_locals->list, method_arg, data, arg_num_used);
2022-06-24 00:21:00 +08:00
/* load args faild */
if (vs->error_code != 0) {
goto exit;
}
/* run method arg */
return_arg = obj_runMethodArgWithState_noalloc(
method_host_obj, sub_locals, method_arg, &sub_try_info, arg_ret_reg);
2022-06-24 00:21:00 +08:00
/* __init__() */
if (ARG_TYPE_OBJECT_NEW == arg_getType(return_arg)) {
arg_setType(return_arg, ARG_TYPE_OBJECT);
/* init object */
PikaObj* new_obj = arg_getPtr(return_arg);
Arg* method_arg =
obj_getMethodArg_noalloc(new_obj, "__init__", &arg_reg1);
2022-06-24 00:21:00 +08:00
PikaObj* sub_locals = New_PikaObj();
Arg* return_arg_init = NULL;
if (NULL == method_arg) {
goto init_exit;
}
VMState_loadArgsFromMethodArg(vs, new_obj, sub_locals->list, method_arg,
"__init__", arg_num_used);
/* load args faild */
if (vs->error_code != 0) {
goto init_exit;
}
return_arg_init = obj_runMethodArgWithState(new_obj, sub_locals,
method_arg, &sub_try_info);
2022-06-24 00:21:00 +08:00
init_exit:
if (NULL != return_arg_init) {
arg_deinit(return_arg_init);
}
obj_deinit(sub_locals);
arg_deinit(method_arg);
}
/* transfer sysOut */
sys_out = obj_getSysOut(method_host_obj);
if (NULL != sys_out) {
args_setSysOut(vs->locals->list, sys_out);
}
2022-06-24 00:21:00 +08:00
/* transfer errCode */
if (0 != obj_getErrorCode(method_host_obj)) {
/* method error */
VMState_setErrorCode(vs, PIKA_RES_ERR_RUNTIME_ERROR);
}
/* check try result */
if (sub_try_info.try_result == TRY_RESULT_RAISE) {
/* try error */
VMState_setErrorCode(vs, PIKA_RES_ERR_RUNTIME_ERROR);
vs->jmp = VM_JMP_RAISE;
2022-06-24 00:21:00 +08:00
}
goto exit;
exit:
if (NULL != method_arg) {
arg_deinit(method_arg);
}
if (NULL != sub_locals) {
obj_deinit(sub_locals);
}
if (NULL != host_arg) {
arg_deinit(host_arg);
}
if (NULL != method_host_obj && isClass) {
/* class method */
obj_deinit(method_host_obj);
}
2022-06-24 00:21:00 +08:00
return return_arg;
}
static char* __get_transferd_str(Args* buffs, char* str, size_t* iout_p) {
char* str_rep = strsReplace(buffs, str, "\\n", "\n");
str_rep = strsReplace(buffs, str_rep, "\\r", "\r");
str_rep = strsReplace(buffs, str_rep, "\\t", "\t");
char* transfered_str = args_getBuff(buffs, strGetSize(str_rep));
size_t i_out = 0;
for (size_t i = 0; i < strGetSize(str_rep); i++) {
/* eg. replace '\x33' to '3' */
if ((str_rep[i] == '\\') && (str_rep[i + 1] == 'x')) {
char hex_str[] = "0x00";
hex_str[2] = str_rep[i + 2];
hex_str[3] = str_rep[i + 3];
char hex = (char)strtol(hex_str, NULL, 0);
transfered_str[i_out++] = hex;
i += 3;
continue;
}
/* normal char */
transfered_str[i_out++] = str_rep[i];
}
*iout_p = i_out;
return transfered_str;
}
static Arg* VM_instruction_handler_STR(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
if (strIsContain(data, '\\')) {
Args buffs = {0};
size_t i_out = 0;
char* transfered_str = __get_transferd_str(&buffs, data, &i_out);
Arg* return_arg = arg_ret_reg;
2022-06-24 00:21:00 +08:00
return_arg = arg_setStr(return_arg, "", transfered_str);
strsDeinit(&buffs);
return return_arg;
}
return arg_setStr(arg_ret_reg, "", data);
2022-06-24 00:21:00 +08:00
}
static Arg* VM_instruction_handler_BYT(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
if (strIsContain(data, '\\')) {
Args buffs = {0};
size_t i_out = 0;
char* transfered_str = __get_transferd_str(&buffs, data, &i_out);
Arg* return_arg = New_arg(NULL);
return_arg =
arg_setBytes(return_arg, "", (uint8_t*)transfered_str, i_out);
strsDeinit(&buffs);
return return_arg;
}
return arg_newBytes((uint8_t*)data, strGetSize(data));
2022-06-24 00:21:00 +08:00
}
static Arg* VM_instruction_handler_OUT(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
arg_newReg(outArg_reg, PIKA_ARG_BUFF_SIZE);
Arg* outArg = stack_popArg(&vs->stack, &outArg_reg);
// Arg* outArg = stack_popArg_alloc(&vs->stack);
2022-06-24 00:21:00 +08:00
ArgType outArg_type = arg_getType(outArg);
if (_checkLReg(data)) {
uint8_t index = _getLRegIndex(data);
if (argType_isObject(outArg_type)) {
PikaObj* obj = arg_getPtr(outArg);
VMState_setLReg(vs, index, obj);
arg_deinit(outArg);
}
return NULL;
}
2022-06-24 00:21:00 +08:00
PikaObj* hostObj = vs->locals;
/* match global_list */
if (args_isArgExist(vs->locals->list, "__gl")) {
char* global_list = args_getStr(vs->locals->list, "__gl");
/* use a arg as buff */
Arg* global_list_arg = arg_newStr(global_list);
2022-06-24 00:21:00 +08:00
char* global_list_buff = arg_getStr(global_list_arg);
/* for each arg arg in global_list */
char token_buff[32] = {0};
for (int i = 0; i < strCountSign(global_list, ',') + 1; i++) {
char* global_arg = strPopToken(token_buff, global_list_buff, ',');
/* matched global arg, hostObj set to global */
if (strEqu(global_arg, data)) {
hostObj = vs->globals;
}
}
arg_deinit(global_list_arg);
}
/* use RunAs object */
if (args_isArgExist(vs->locals->list, "__runAs")) {
hostObj = args_getPtr(vs->locals->list, "__runAs");
}
/* set free object to nomal object */
if (ARG_TYPE_OBJECT_NEW == outArg_type) {
arg_setType(outArg, ARG_TYPE_OBJECT);
}
/* ouput arg to locals */
obj_setArg_noCopy(hostObj, data, outArg);
return NULL;
}
/* run as */
static Arg* VM_instruction_handler_RAS(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
if (strEqu(data, "$origin")) {
/* use origin object to run */
obj_removeArg(vs->locals, "__runAs");
return NULL;
}
/* use "data" object to run */
PikaObj* runAs = obj_getObj(vs->locals, data);
args_setRef(vs->locals->list, "__runAs", runAs);
return NULL;
}
static Arg* VM_instruction_handler_NUM(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
Arg* numArg = arg_ret_reg;
2022-06-24 00:21:00 +08:00
/* hex */
if (data[1] == 'x' || data[1] == 'X') {
return arg_setInt(numArg, "", strtol(data, NULL, 0));
}
if (data[1] == 'o' || data[1] == 'O') {
char strtol_buff[10] = {0};
strtol_buff[0] = '0';
__platform_memcpy(strtol_buff + 1, data + 2, strGetSize(data) - 2);
return arg_setInt(numArg, "", strtol(strtol_buff, NULL, 0));
}
if (data[1] == 'b' || data[1] == 'B') {
char strtol_buff[10] = {0};
__platform_memcpy(strtol_buff, data + 2, strGetSize(data) - 2);
return arg_setInt(numArg, "", strtol(strtol_buff, NULL, 2));
}
2022-06-24 00:21:00 +08:00
/* float */
if (strIsContain(data, '.')) {
return arg_setFloat(numArg, "", atof(data));
}
/* int */
return arg_setInt(numArg, "", fast_atoi(data));
}
static Arg* VM_instruction_handler_JMP(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
vs->jmp = fast_atoi(data);
return NULL;
}
static Arg* VM_instruction_handler_SER(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
vs->try_error_code = fast_atoi(data);
return NULL;
}
static Arg* VM_instruction_handler_JEZ(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
int thisBlockDeepth;
thisBlockDeepth = VMState_getBlockDeepthNow(vs);
int jmp_expect = fast_atoi(data);
arg_newReg(pika_assertArg_reg, PIKA_ARG_BUFF_SIZE);
Arg* pika_assertArg = stack_popArg(&(vs->stack), &pika_assertArg_reg);
int pika_assert = 0;
if (NULL != pika_assertArg) {
pika_assert = arg_getInt(pika_assertArg);
}
arg_deinit(pika_assertArg);
vs->ireg[thisBlockDeepth] = !pika_assert;
if (0 == pika_assert) {
/* jump */
vs->jmp = jmp_expect;
}
/* restore loop deepth */
if (2 == jmp_expect && 0 == pika_assert) {
int block_deepth_now = VMState_getBlockDeepthNow(vs);
vs->loop_deepth = block_deepth_now;
2022-06-24 00:21:00 +08:00
}
2022-06-24 00:21:00 +08:00
return NULL;
}
static uint8_t VMState_getInputArgNum(VMState* vs) {
InstructUnit* ins_unit_now = VMState_getInstructNow(vs);
uint8_t invoke_deepth_this = instructUnit_getInvokeDeepth(ins_unit_now);
2022-06-24 00:21:00 +08:00
int32_t pc_this = vs->pc;
uint8_t num = 0;
while (1) {
ins_unit_now--;
pc_this -= instructUnit_getSize(ins_unit_now);
uint8_t invode_deepth = instructUnit_getInvokeDeepth(ins_unit_now);
if (pc_this < 0) {
break;
}
if (invode_deepth == invoke_deepth_this + 1) {
2022-06-24 00:21:00 +08:00
num++;
}
if (instructUnit_getIsNewLine(ins_unit_now)) {
break;
}
if (invode_deepth <= invoke_deepth_this) {
2022-06-24 00:21:00 +08:00
break;
}
}
return num;
}
static Arg* VM_instruction_handler_OPT(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
Arg* outArg = arg_ret_reg;
2022-06-24 00:21:00 +08:00
uint8_t input_arg_num = VMState_getInputArgNum(vs);
Arg* arg1 = NULL;
Arg* arg2 = NULL;
arg_newReg(arg_reg1, PIKA_ARG_BUFF_SIZE);
arg_newReg(arg_reg2, PIKA_ARG_BUFF_SIZE);
2022-06-24 00:21:00 +08:00
if (input_arg_num == 2) {
/* tow input */
arg2 = stack_popArg(&(vs->stack), &arg_reg2);
arg1 = stack_popArg(&(vs->stack), &arg_reg1);
2022-06-24 00:21:00 +08:00
} else if (input_arg_num == 1) {
/* only one input */
arg2 = stack_popArg(&(vs->stack), &arg_reg2);
arg1 = NULL;
2022-06-24 00:21:00 +08:00
}
ArgType type_arg1 = arg_getType(arg1);
ArgType type_arg2 = arg_getType(arg2);
int num1_i = 0;
int num2_i = 0;
float num1_f = 0.0;
float num2_f = 0.0;
/* get int and float num */
if (type_arg1 == ARG_TYPE_INT) {
num1_i = arg_getInt(arg1);
num1_f = (float)num1_i;
} else if (type_arg1 == ARG_TYPE_FLOAT) {
num1_f = arg_getFloat(arg1);
num1_i = (int)num1_f;
}
if (type_arg2 == ARG_TYPE_INT) {
num2_i = arg_getInt(arg2);
num2_f = (float)num2_i;
} else if (type_arg2 == ARG_TYPE_FLOAT) {
num2_f = arg_getFloat(arg2);
num2_i = (int)num2_f;
}
if (strEqu("+", data)) {
if ((type_arg1 == ARG_TYPE_STRING) && (type_arg2 == ARG_TYPE_STRING)) {
char* num1_s = NULL;
char* num2_s = NULL;
Args str_opt_buffs = {0};
num1_s = arg_getStr(arg1);
num2_s = arg_getStr(arg2);
char* opt_str_out = strsAppend(&str_opt_buffs, num1_s, num2_s);
outArg = arg_setStr(outArg, "", opt_str_out);
strsDeinit(&str_opt_buffs);
goto OPT_exit;
}
/* match float */
if ((type_arg1 == ARG_TYPE_FLOAT) || type_arg2 == ARG_TYPE_FLOAT) {
outArg = arg_setFloat(outArg, "", num1_f + num2_f);
goto OPT_exit;
}
/* int is default */
outArg = arg_setInt(outArg, "", num1_i + num2_i);
goto OPT_exit;
}
if (strEqu("-", data)) {
if (type_arg2 == ARG_TYPE_NONE) {
if (type_arg1 == ARG_TYPE_INT) {
outArg = arg_setInt(outArg, "", -num1_i);
goto OPT_exit;
}
if (type_arg1 == ARG_TYPE_FLOAT) {
outArg = arg_setFloat(outArg, "", -num1_f);
goto OPT_exit;
}
}
if ((type_arg1 == ARG_TYPE_FLOAT) || type_arg2 == ARG_TYPE_FLOAT) {
outArg = arg_setFloat(outArg, "", num1_f - num2_f);
goto OPT_exit;
}
outArg = arg_setInt(outArg, "", num1_i - num2_i);
goto OPT_exit;
}
if (strEqu("*", data)) {
if ((type_arg1 == ARG_TYPE_FLOAT) || type_arg2 == ARG_TYPE_FLOAT) {
outArg = arg_setFloat(outArg, "", num1_f * num2_f);
goto OPT_exit;
}
outArg = arg_setInt(outArg, "", num1_i * num2_i);
goto OPT_exit;
}
if (strEqu("/", data)) {
if (0 == num2_f) {
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
2022-06-24 00:21:00 +08:00
args_setSysOut(vs->locals->list,
"ZeroDivisionError: division by zero");
outArg = NULL;
goto OPT_exit;
}
outArg = arg_setFloat(outArg, "", num1_f / num2_f);
goto OPT_exit;
}
if (strEqu("<", data)) {
outArg = arg_setInt(outArg, "", num1_f < num2_f);
goto OPT_exit;
}
if (strEqu(">", data)) {
outArg = arg_setInt(outArg, "", num1_f > num2_f);
goto OPT_exit;
}
if (strEqu("%", data)) {
if ((type_arg1 == ARG_TYPE_INT) && (type_arg2 == ARG_TYPE_INT)) {
outArg = arg_setInt(outArg, "", num1_i % num2_i);
goto OPT_exit;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"TypeError: unsupported operand type(s) for %: 'float'\n");
outArg = NULL;
2022-06-24 00:21:00 +08:00
goto OPT_exit;
}
if (strEqu("**", data)) {
if (type_arg1 == ARG_TYPE_INT && type_arg2 == ARG_TYPE_INT) {
int res = 1;
for (int i = 0; i < num2_i; i++) {
res = res * num1_i;
}
outArg = arg_setInt(outArg, "", res);
goto OPT_exit;
} else if (type_arg1 == ARG_TYPE_FLOAT && type_arg2 == ARG_TYPE_INT) {
float res = 1;
for (int i = 0; i < num2_i; i++) {
res = res * num1_f;
}
outArg = arg_setFloat(outArg, "", res);
goto OPT_exit;
} else {
#if PIKA_MATH_ENABLE
float res = 1;
res = pow(num1_f, num2_f);
outArg = arg_setFloat(outArg, "", res);
goto OPT_exit;
#else
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"Operation float ** float is not enabled, please set "
"PIKA_MATH_ENABLE\n");
#endif
2022-06-24 00:21:00 +08:00
}
}
if (strEqu("//", data)) {
if ((type_arg1 == ARG_TYPE_INT) && (type_arg2 == ARG_TYPE_INT)) {
outArg = arg_setInt(outArg, "", num1_i / num2_i);
goto OPT_exit;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"TypeError: unsupported operand type(s) for //: 'float'\n");
outArg = NULL;
2022-06-24 00:21:00 +08:00
goto OPT_exit;
}
if (strEqu("==", data) || strEqu("!=", data)) {
int8_t is_equ = -1;
if (type_arg1 == ARG_TYPE_NONE && type_arg2 == ARG_TYPE_NONE) {
is_equ = 1;
goto EQU_exit;
}
2022-06-24 00:21:00 +08:00
/* type not equl, and type is not int or float */
if (type_arg1 != type_arg2) {
if ((type_arg1 != ARG_TYPE_FLOAT) && (type_arg1 != ARG_TYPE_INT)) {
is_equ = 0;
goto EQU_exit;
}
if ((type_arg2 != ARG_TYPE_FLOAT) && (type_arg2 != ARG_TYPE_INT)) {
is_equ = 0;
goto EQU_exit;
}
}
/* string compire */
if (type_arg1 == ARG_TYPE_STRING) {
is_equ = strEqu(arg_getStr(arg1), arg_getStr(arg2));
goto EQU_exit;
}
/* bytes compire */
if (type_arg1 == ARG_TYPE_BYTES) {
if (arg_getBytesSize(arg1) != arg_getBytesSize(arg2)) {
is_equ = 0;
goto EQU_exit;
}
is_equ = 1;
for (size_t i = 0; i < arg_getBytesSize(arg1); i++) {
if (arg_getBytes(arg1)[i] != arg_getBytes(arg2)[i]) {
is_equ = 0;
goto EQU_exit;
}
}
goto EQU_exit;
}
/* default: int and float */
is_equ = ((num1_f - num2_f) * (num1_f - num2_f) < (float)0.000001);
goto EQU_exit;
EQU_exit:
if (strEqu("==", data)) {
outArg = arg_setInt(outArg, "", is_equ);
} else {
outArg = arg_setInt(outArg, "", !is_equ);
}
goto OPT_exit;
}
if (strEqu(">=", data)) {
outArg = arg_setInt(
outArg, "",
(num1_f > num2_f) ||
((num1_f - num2_f) * (num1_f - num2_f) < (float)0.000001));
goto OPT_exit;
}
if (strEqu("<=", data)) {
outArg = arg_setInt(
outArg, "",
(num1_f < num2_f) ||
((num1_f - num2_f) * (num1_f - num2_f) < (float)0.000001));
goto OPT_exit;
}
if (strEqu("&", data)) {
if ((type_arg1 == ARG_TYPE_INT) && (type_arg2 == ARG_TYPE_INT)) {
outArg = arg_setInt(outArg, "", num1_i & num2_i);
goto OPT_exit;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"TypeError: unsupported operand type(s) for &: 'float'\n");
outArg = NULL;
2022-06-24 00:21:00 +08:00
goto OPT_exit;
}
if (strEqu("|", data)) {
if ((type_arg1 == ARG_TYPE_INT) && (type_arg2 == ARG_TYPE_INT)) {
outArg = arg_setInt(outArg, "", num1_i | num2_i);
goto OPT_exit;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"TypeError: unsupported operand type(s) for |: 'float'\n");
outArg = NULL;
2022-06-24 00:21:00 +08:00
goto OPT_exit;
}
if (strEqu("~", data)) {
if (type_arg2 == ARG_TYPE_INT) {
outArg = arg_setInt(outArg, "", ~num2_i);
goto OPT_exit;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"TypeError: unsupported operand type(s) for ~: 'float'\n");
outArg = NULL;
2022-06-24 00:21:00 +08:00
goto OPT_exit;
}
if (strEqu(">>", data)) {
if ((type_arg1 == ARG_TYPE_INT) && (type_arg2 == ARG_TYPE_INT)) {
outArg = arg_setInt(outArg, "", num1_i >> num2_i);
goto OPT_exit;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"TypeError: unsupported operand type(s) for >>: 'float'\n");
outArg = NULL;
2022-06-24 00:21:00 +08:00
goto OPT_exit;
}
if (strEqu("<<", data)) {
if ((type_arg1 == ARG_TYPE_INT) && (type_arg2 == ARG_TYPE_INT)) {
outArg = arg_setInt(outArg, "", num1_i << num2_i);
goto OPT_exit;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf(
"TypeError: unsupported operand type(s) for <<: 'float'\n");
outArg = NULL;
2022-06-24 00:21:00 +08:00
goto OPT_exit;
}
if (strEqu(" and ", data)) {
outArg = arg_setInt(outArg, "", num1_i && num2_i);
goto OPT_exit;
}
if (strEqu(" or ", data)) {
outArg = arg_setInt(outArg, "", num1_i || num2_i);
goto OPT_exit;
}
if (strEqu(" not ", data)) {
outArg = arg_setInt(outArg, "", !num2_i);
goto OPT_exit;
}
if (strEqu(" import ", data)) {
outArg = NULL;
goto OPT_exit;
}
OPT_exit:
arg_deinit(arg1);
arg_deinit(arg2);
if (NULL != outArg) {
return outArg;
}
return NULL;
}
static Arg* __VM_instruction_handler_DEF(PikaObj* self,
VMState* vs,
char* data,
uint8_t is_class) {
int thisBlockDeepth = VMState_getBlockDeepthNow(vs);
PikaObj* hostObj = vs->locals;
uint8_t is_in_class = 0;
/* use RunAs object */
if (args_isArgExist(vs->locals->list, "__runAs")) {
hostObj = args_getPtr(vs->locals->list, "__runAs");
is_in_class = 1;
}
int offset = 0;
/* byteCode */
while (1) {
InstructUnit* ins_unit_now = VMState_getInstructWithOffset(vs, offset);
if (!instructUnit_getIsNewLine(ins_unit_now)) {
offset += instructUnit_getSize();
continue;
}
if (instructUnit_getBlockDeepth(ins_unit_now) == thisBlockDeepth + 1) {
if (is_in_class) {
class_defineObjectMethod(hostObj, data, (Method)ins_unit_now,
self, vs->bytecode_frame);
2022-06-24 00:21:00 +08:00
} else {
if (is_class) {
class_defineRunTimeConstructor(hostObj, data,
(Method)ins_unit_now, self,
2022-06-24 00:21:00 +08:00
vs->bytecode_frame);
} else {
class_defineStaticMethod(hostObj, data,
(Method)ins_unit_now, self,
2022-06-24 00:21:00 +08:00
vs->bytecode_frame);
}
}
break;
}
offset += instructUnit_getSize();
}
return NULL;
}
static Arg* VM_instruction_handler_DEF(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
return __VM_instruction_handler_DEF(self, vs, data, 0);
}
static Arg* VM_instruction_handler_CLS(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
return __VM_instruction_handler_DEF(self, vs, data, 1);
}
static Arg* VM_instruction_handler_RET(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
/* exit jmp signal */
vs->jmp = VM_JMP_EXIT;
Arg* return_arg = stack_popArg_alloc(&(vs->stack));
2022-06-24 00:21:00 +08:00
method_returnArg(vs->locals->list, return_arg);
return NULL;
}
static Arg* VM_instruction_handler_RIS(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
Arg* err_arg = stack_popArg_alloc(&(vs->stack));
PIKA_RES err = (PIKA_RES)arg_getInt(err_arg);
VMState_setErrorCode(vs, err);
arg_deinit(err_arg);
/* raise jmp */
if (vs->try_info->try_state == TRY_STATE_TOP) {
vs->jmp = VM_JMP_RAISE;
} else if (vs->try_info->try_state == TRY_STATE_INNER) {
vs->try_info->try_result = TRY_RESULT_RAISE;
return VM_instruction_handler_RET(self, vs, data, arg_ret_reg);
}
return NULL;
}
static Arg* VM_instruction_handler_NEL(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
int thisBlockDeepth = VMState_getBlockDeepthNow(vs);
if (0 == vs->ireg[thisBlockDeepth]) {
2022-06-24 00:21:00 +08:00
/* set __else flag */
vs->jmp = fast_atoi(data);
}
return NULL;
}
static Arg* VM_instruction_handler_DEL(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
if (_checkLReg(data)) {
uint8_t reg_index = _getLRegIndex(data);
VMState_delLReg(vs, reg_index);
return NULL;
}
if (obj_isArgExist(vs->locals, data)) {
obj_removeArg(vs->locals, data);
return NULL;
}
if (obj_isArgExist(vs->globals, data)) {
obj_removeArg(vs->globals, data);
return NULL;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_OPERATION_FAILED);
__platform_printf("NameError: name '%s' is not defined\n", data);
2022-06-24 00:21:00 +08:00
return NULL;
}
static Arg* VM_instruction_handler_EST(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
Arg* arg = obj_getArg(vs->locals, data);
if (arg == NULL) {
return arg_setInt(arg_ret_reg, "", 0);
2022-06-24 00:21:00 +08:00
}
if (ARG_TYPE_NONE == arg_getType(arg)) {
return arg_setInt(arg_ret_reg, "", 0);
2022-06-24 00:21:00 +08:00
}
return arg_setInt(arg_ret_reg, "", 1);
2022-06-24 00:21:00 +08:00
}
static Arg* VM_instruction_handler_BRK(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
/* break jmp signal */
vs->jmp = VM_JMP_BREAK;
2022-06-24 00:21:00 +08:00
return NULL;
}
static Arg* VM_instruction_handler_CTN(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
/* continue jmp signal */
vs->jmp = VM_JMP_CONTINUE;
2022-06-24 00:21:00 +08:00
return NULL;
}
static Arg* VM_instruction_handler_GLB(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
Arg* global_list_buff = NULL;
char* global_list = args_getStr(vs->locals->list, "__gl");
/* create new global_list */
if (NULL == global_list) {
args_setStr(vs->locals->list, "__gl", data);
goto exit;
}
/* append to exist global_list */
global_list_buff = arg_newStr(global_list);
2022-06-24 00:21:00 +08:00
global_list_buff = arg_strAppend(global_list_buff, ",");
global_list_buff = arg_strAppend(global_list_buff, data);
args_setStr(vs->locals->list, "__gl", arg_getStr(global_list_buff));
goto exit;
exit:
if (NULL != global_list_buff) {
arg_deinit(global_list_buff);
}
return NULL;
}
static Arg* VM_instruction_handler_IMP(PikaObj* self,
VMState* vs,
char* data,
Arg* arg_ret_reg) {
2022-06-24 00:21:00 +08:00
/* the module is already imported, skip. */
if (obj_isArgExist(self, data)) {
return NULL;
}
/* find cmodule in root object */
extern PikaObj* __pikaMain;
if (obj_isArgExist(__pikaMain, data)) {
obj_setArg(self, data, obj_getArg(__pikaMain, data));
return NULL;
}
/* import module from '__lib' */
if (0 == obj_importModule(self, data)) {
return NULL;
}
VMState_setErrorCode(vs, PIKA_RES_ERR_ARG_NO_FOUND);
2022-06-24 00:21:00 +08:00
__platform_printf("ModuleNotFoundError: No module named '%s'\r\n", data);
return NULL;
}
const VM_instruct_handler VM_instruct_handler_table[__INSTRCUTION_CNT] = {
#define __INS_TABLE
#include "__instruction_table.cfg"
};
enum Instruct pikaVM_getInstructFromAsm(char* ins_str) {
2022-06-24 00:21:00 +08:00
#define __INS_COMPIRE
#include "__instruction_table.cfg"
return NON;
}
static int pikaVM_runInstructUnit(PikaObj* self,
VMState* vs,
InstructUnit* ins_unit) {
enum Instruct instruct = instructUnit_getInstruct(ins_unit);
arg_newReg(return_Arg_reg, PIKA_ARG_BUFF_SIZE);
Arg* return_arg = &return_Arg_reg;
2022-06-24 00:21:00 +08:00
// char invode_deepth1_str[2] = {0};
int32_t pc_next = vs->pc + instructUnit_getSize();
char* data = VMState_getConstWithInstructUnit(vs, ins_unit);
/* run instruct */
pika_assert(NULL != vs->try_info);
return_arg =
VM_instruct_handler_table[instruct](self, vs, data, &return_Arg_reg);
2022-06-24 00:21:00 +08:00
if (NULL != return_arg) {
stack_pushArg(&(vs->stack), return_arg);
}
goto nextLine;
nextLine:
/* exit */
if (VM_JMP_EXIT == vs->jmp) {
pc_next = VM_PC_EXIT;
2022-06-24 00:21:00 +08:00
goto exit;
}
/* break */
if (VM_JMP_BREAK == vs->jmp) {
2022-06-24 00:21:00 +08:00
pc_next = vs->pc + VMState_getAddrOffsetOfBreak(vs);
goto exit;
}
/* continue */
if (VM_JMP_CONTINUE == vs->jmp) {
2022-06-24 00:21:00 +08:00
pc_next = vs->pc + VMState_getAddrOffsetOfContinue(vs);
goto exit;
}
/* raise */
if (VM_JMP_RAISE == vs->jmp) {
pc_next = vs->pc + VMState_getAddrOffsetOfRaise(vs);
goto exit;
}
2022-06-24 00:21:00 +08:00
/* static jmp */
if (vs->jmp != 0) {
pc_next = vs->pc + VMState_getAddrOffsetFromJmp(vs);
goto exit;
}
/* not jmp */
pc_next = vs->pc + instructUnit_getSize();
goto exit;
exit:
vs->jmp = 0;
/* reach the end */
if (pc_next >= (int)VMState_getInstructArraySize(vs)) {
return VM_PC_EXIT;
2022-06-24 00:21:00 +08:00
}
return pc_next;
}
VMParameters* pikaVM_runAsm(PikaObj* self, char* pikaAsm) {
ByteCodeFrame bytecode_frame;
byteCodeFrame_init(&bytecode_frame);
byteCodeFrame_appendFromAsm(&bytecode_frame, pikaAsm);
VMParameters* res = pikaVM_runByteCodeFrame(self, &bytecode_frame);
byteCodeFrame_deinit(&bytecode_frame);
return res;
}
static VMParameters* __pikaVM_runPyLines_or_byteCode(PikaObj* self,
char* py_lines,
uint8_t* bytecode) {
uint8_t is_run_py;
if (NULL != py_lines) {
is_run_py = 1;
} else if (NULL != bytecode) {
is_run_py = 0;
} else {
return NULL;
}
Args buffs = {0};
VMParameters* globals = NULL;
ByteCodeFrame bytecode_frame_stack = {0};
ByteCodeFrame* bytecode_frame_p = NULL;
uint8_t is_use_heap_bytecode = 0;
/*
* the first obj_run, cache bytecode to heap, to support 'def' and 'class'
*/
if (!args_isArgExist(self->list, "__first_bytecode")) {
is_use_heap_bytecode = 1;
/* load bytecode to heap */
args_setHeapStruct(self->list, "__first_bytecode", bytecode_frame_stack,
byteCodeFrame_deinit);
/* get bytecode_ptr from heap */
bytecode_frame_p = args_getHeapStruct(self->list, "__first_bytecode");
} else {
/* not the first obj_run */
/* save 'def' and 'class' to heap */
if ((strIsStartWith(py_lines, "def ")) ||
(strIsStartWith(py_lines, "class "))) {
char* declear_name = strsGetFirstToken(&buffs, py_lines, ':');
/* load bytecode to heap */
args_setHeapStruct(self->list, declear_name, bytecode_frame_stack,
byteCodeFrame_deinit);
/* get bytecode_ptr from heap */
bytecode_frame_p = args_getHeapStruct(self->list, declear_name);
} else {
/* get bytecode_ptr from stack */
bytecode_frame_p = &bytecode_frame_stack;
}
}
/* load or generate byte code frame */
if (is_run_py) {
/* generate byte code */
byteCodeFrame_init(bytecode_frame_p);
if (1 == bytecodeFrame_fromMultiLine(bytecode_frame_p, py_lines)) {
__platform_printf("[error]: Syntax error.\r\n");
globals = NULL;
goto exit;
}
} else {
/* load bytecode */
byteCodeFrame_loadByteCode(bytecode_frame_p, bytecode);
}
/* run byteCode */
globals = pikaVM_runByteCodeFrame(self, bytecode_frame_p);
goto exit;
exit:
if (!is_use_heap_bytecode) {
byteCodeFrame_deinit(&bytecode_frame_stack);
}
strsDeinit(&buffs);
return globals;
}
VMParameters* pikaVM_runSingleFile(PikaObj* self, char* filename) {
Args buffs = {0};
2022-06-24 00:21:00 +08:00
Arg* file_arg = arg_loadFile(NULL, filename);
pika_assert(NULL != file_arg);
if (NULL == file_arg) {
return NULL;
}
2022-06-24 00:21:00 +08:00
char* lines = (char*)arg_getBytes(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");
VMParameters* res = pikaVM_run(self, lines);
arg_deinit(file_arg);
strsDeinit(&buffs);
return res;
}
VMParameters* pikaVM_run(PikaObj* self, char* py_lines) {
return __pikaVM_runPyLines_or_byteCode(self, py_lines, NULL);
}
VMParameters* pikaVM_runByteCode(PikaObj* self, uint8_t* bytecode) {
return __pikaVM_runPyLines_or_byteCode(self, NULL, bytecode);
}
void constPool_update(ConstPool* self) {
self->content_start = (void*)arg_getContent(self->arg_buff);
}
void constPool_init(ConstPool* self) {
self->arg_buff = arg_newStr("");
2022-06-24 00:21:00 +08:00
constPool_update(self);
self->content_offset_now = 0;
self->size = strGetSize(constPool_getStart(self)) + 1;
self->output_redirect_fun = NULL;
self->output_f = NULL;
}
void constPool_deinit(ConstPool* self) {
if (NULL != self->arg_buff) {
arg_deinit(self->arg_buff);
}
}
void constPool_append(ConstPool* self, char* content) {
uint16_t size = strGetSize(content) + 1;
if (NULL == self->output_redirect_fun) {
self->arg_buff = arg_append(self->arg_buff, content, size);
} else {
self->output_redirect_fun(self, content);
};
constPool_update(self);
self->size += size;
}
char* constPool_getNow(ConstPool* self) {
if (self->content_offset_now >= self->size) {
/* is the end */
return NULL;
}
return (char*)((uintptr_t)constPool_getStart(self) +
(uintptr_t)(self->content_offset_now));
}
uint16_t constPool_getOffsetByData(ConstPool* self, char* data) {
uint16_t ptr_befor = self->content_offset_now;
/* set ptr_now to begin */
self->content_offset_now = 0;
uint16_t offset_out = 65535;
while (1) {
if (NULL == constPool_getNext(self)) {
goto exit;
}
if (strEqu(data, constPool_getNow(self))) {
offset_out = self->content_offset_now;
goto exit;
}
}
exit:
/* retore ptr_now */
self->content_offset_now = ptr_befor;
return offset_out;
}
char* constPool_getNext(ConstPool* self) {
self->content_offset_now += strGetSize(constPool_getNow(self)) + 1;
return constPool_getNow(self);
}
char* constPool_getByIndex(ConstPool* self, uint16_t index) {
uint16_t ptr_befor = self->content_offset_now;
/* set ptr_now to begin */
self->content_offset_now = 0;
for (uint16_t i = 0; i < index; i++) {
constPool_getNext(self);
}
char* res = constPool_getNow(self);
/* retore ptr_now */
self->content_offset_now = ptr_befor;
return res;
}
void constPool_print(ConstPool* self) {
uint16_t ptr_befor = self->content_offset_now;
/* set ptr_now to begin */
self->content_offset_now = 0;
while (1) {
if (NULL == constPool_getNext(self)) {
goto exit;
}
uint16_t offset = self->content_offset_now;
__platform_printf("%d: %s\r\n", offset, constPool_getNow(self));
}
exit:
/* retore ptr_now */
self->content_offset_now = ptr_befor;
return;
}
void byteCodeFrame_init(ByteCodeFrame* self) {
/* init to support append,
if only load static bytecode,
can not init */
constPool_init(&(self->const_pool));
instructArray_init(&(self->instruct_array));
}
void byteCodeFrame_loadByteCode(ByteCodeFrame* self, uint8_t* bytes) {
uint16_t* ins_size_p = (uint16_t*)bytes;
void* ins_start_p = (uint16_t*)(bytes + 2);
uint16_t* const_size_p =
(uint16_t*)((uintptr_t)ins_start_p + (uintptr_t)(*ins_size_p));
self->instruct_array.size = *ins_size_p;
self->instruct_array.content_start = ins_start_p;
self->const_pool.size = *const_size_p;
self->const_pool.content_start = (char*)((uintptr_t)const_size_p + 2);
}
void byteCodeFrame_deinit(ByteCodeFrame* self) {
constPool_deinit(&(self->const_pool));
instructArray_deinit(&(self->instruct_array));
}
void instructArray_init(InstructArray* self) {
self->arg_buff = arg_newNull();
2022-06-24 00:21:00 +08:00
instructArray_update(self);
self->size = 0;
self->content_offset_now = 0;
self->output_redirect_fun = NULL;
self->output_f = NULL;
}
void instructArray_deinit(InstructArray* self) {
if (NULL != self->arg_buff) {
arg_deinit(self->arg_buff);
}
}
void instructArray_append(InstructArray* self, InstructUnit* ins_unit) {
if (NULL == self->output_redirect_fun) {
self->arg_buff =
arg_append(self->arg_buff, ins_unit, instructUnit_getSize());
} else {
self->output_redirect_fun(self, ins_unit);
};
instructArray_update(self);
self->size += instructUnit_getSize();
}
void instructUnit_init(InstructUnit* ins_unit) {
ins_unit->deepth = 0;
ins_unit->const_pool_index = 0;
ins_unit->isNewLine_instruct = 0;
}
void instructArray_update(InstructArray* self) {
self->content_start = (void*)arg_getContent(self->arg_buff);
}
InstructUnit* instructArray_getNow(InstructArray* self) {
if (self->content_offset_now >= self->size) {
/* is the end */
return NULL;
}
return (InstructUnit*)((uintptr_t)instructArray_getStart(self) +
(uintptr_t)(self->content_offset_now));
}
InstructUnit* instructArray_getNext(InstructArray* self) {
self->content_offset_now += instructUnit_getSize();
return instructArray_getNow(self);
}
static char* instructUnit_getInstructStr(InstructUnit* self) {
#define __INS_GET_INS_STR
#include "__instruction_table.cfg"
return "NON";
}
void instructUnit_print(InstructUnit* self) {
if (instructUnit_getIsNewLine(self)) {
__platform_printf("B%d\r\n", instructUnit_getBlockDeepth(self));
}
__platform_printf("%d %s #%d\r\n", instructUnit_getInvokeDeepth(self),
instructUnit_getInstructStr(self),
self->const_pool_index);
}
static void instructUnit_printWithConst(InstructUnit* self,
ConstPool* const_pool) {
// if (instructUnit_getIsNewLine(self)) {
// __platform_printf("B%d\r\n", instructUnit_getBlockDeepth(self));
// }
__platform_printf("%s %s \t\t(#%d)\r\n", instructUnit_getInstructStr(self),
constPool_getByOffset(const_pool, self->const_pool_index),
self->const_pool_index);
}
void instructArray_printWithConst(InstructArray* self, ConstPool* const_pool) {
uint16_t offset_befor = self->content_offset_now;
self->content_offset_now = 0;
while (1) {
InstructUnit* ins_unit = instructArray_getNow(self);
if (NULL == ins_unit) {
goto exit;
}
instructUnit_printWithConst(ins_unit, const_pool);
instructArray_getNext(self);
}
exit:
self->content_offset_now = offset_befor;
return;
}
void instructArray_print(InstructArray* self) {
uint16_t offset_befor = self->content_offset_now;
self->content_offset_now = 0;
while (1) {
InstructUnit* ins_unit = instructArray_getNow(self);
if (NULL == ins_unit) {
goto exit;
}
instructUnit_print(ins_unit);
instructArray_getNext(self);
}
exit:
self->content_offset_now = offset_befor;
return;
}
void instructArray_printAsArray(InstructArray* self) {
uint16_t offset_befor = self->content_offset_now;
self->content_offset_now = 0;
uint8_t line_num = 12;
uint16_t g_i = 0;
uint8_t* ins_size_p = (uint8_t*)&self->size;
__platform_printf("0x%02x, ", *(ins_size_p));
__platform_printf("0x%02x, ", *(ins_size_p + (uintptr_t)1));
__platform_printf("/* instruct array size */\n");
while (1) {
InstructUnit* ins_unit = instructArray_getNow(self);
if (NULL == ins_unit) {
goto exit;
}
for (int i = 0; i < (int)instructUnit_getSize(ins_unit); i++) {
g_i++;
__platform_printf("0x%02x, ", *((uint8_t*)ins_unit + (uintptr_t)i));
if (g_i % line_num == 0) {
__platform_printf("\n");
}
}
instructArray_getNext(self);
}
exit:
__platform_printf("/* instruct array */\n");
self->content_offset_now = offset_befor;
return;
}
size_t byteCodeFrame_getSize(ByteCodeFrame* bf) {
return bf->const_pool.size + bf->instruct_array.size;
}
void byteCodeFrame_print(ByteCodeFrame* self) {
constPool_print(&(self->const_pool));
instructArray_printWithConst(&(self->instruct_array), &(self->const_pool));
__platform_printf("---------------\r\n");
__platform_printf("byte code size: %d\r\n",
self->const_pool.size + self->instruct_array.size);
}
void VMState_solveUnusedStack(VMState* vs) {
uint8_t top = stack_getTop(&(vs->stack));
for (int i = 0; i < top; i++) {
Arg* arg = stack_popArg_alloc(&(vs->stack));
2022-06-24 00:21:00 +08:00
ArgType type = arg_getType(arg);
if (type == ARG_TYPE_NONE) {
2022-06-24 00:21:00 +08:00
arg_deinit(arg);
continue;
}
if (vs->line_error_code != 0) {
arg_deinit(arg);
continue;
}
if (argType_isObject(type)) {
char* res = obj_toStr(arg_getPtr(arg));
__platform_printf("%s\r\n", res);
} else if (type == ARG_TYPE_INT) {
2022-06-24 00:21:00 +08:00
__platform_printf("%d\r\n", (int)arg_getInt(arg));
} else if (type == ARG_TYPE_FLOAT) {
__platform_printf("%f\r\n", arg_getFloat(arg));
} else if (type == ARG_TYPE_STRING) {
__platform_printf("%s\r\n", arg_getStr(arg));
} else if (type == ARG_TYPE_BYTES) {
arg_printBytes(arg);
} else if (ARG_TYPE_POINTER == type ||
ARG_TYPE_METHOD_NATIVE_CONSTRUCTOR) {
__platform_printf("%p\r\n", arg_getPtr(arg));
2022-06-24 00:21:00 +08:00
}
arg_deinit(arg);
}
}
static VMParameters* __pikaVM_runByteCodeFrameWithState(
PikaObj* self,
VMParameters* locals,
VMParameters* globals,
ByteCodeFrame* bytecode_frame,
uint16_t pc,
TryInfo* try_info) {
pika_assert(NULL != try_info);
2022-06-24 00:21:00 +08:00
int size = bytecode_frame->instruct_array.size;
/* locals is the local scope */
VMState vs = {
.bytecode_frame = bytecode_frame,
.locals = locals,
.globals = globals,
.jmp = 0,
.pc = pc,
.loop_deepth = 0,
.error_code = PIKA_RES_OK,
.line_error_code = PIKA_RES_OK,
.try_error_code = PIKA_RES_OK,
.try_info = try_info,
2022-06-24 00:21:00 +08:00
};
stack_init(&(vs.stack));
VMState_initReg(&vs);
2022-06-24 00:21:00 +08:00
while (vs.pc < size) {
if (vs.pc == VM_PC_EXIT) {
2022-06-24 00:21:00 +08:00
break;
}
InstructUnit* this_ins_unit = VMState_getInstructNow(&vs);
if (instructUnit_getIsNewLine(this_ins_unit)) {
VMState_solveUnusedStack(&vs);
stack_reset(&(vs.stack));
vs.error_code = 0;
vs.line_error_code = 0;
}
vs.pc = pikaVM_runInstructUnit(self, &vs, this_ins_unit);
if (0 != vs.error_code) {
vs.line_error_code = vs.error_code;
InstructUnit* head_ins_unit = this_ins_unit;
/* get first ins of a line */
while (1) {
if (instructUnit_getIsNewLine(head_ins_unit)) {
break;
}
head_ins_unit--;
}
if (vs.try_info->try_state) {
vs.try_error_code = vs.error_code;
}
2022-06-24 00:21:00 +08:00
/* print inses of a line */
if (!vs.try_info->try_state) {
while (1) {
if (head_ins_unit != this_ins_unit) {
__platform_printf(" ");
} else {
__platform_printf(" -> ");
}
instructUnit_printWithConst(head_ins_unit,
&(bytecode_frame->const_pool));
head_ins_unit++;
if (head_ins_unit > this_ins_unit) {
break;
}
2022-06-24 00:21:00 +08:00
}
}
__platform_error_handle();
vs.error_code = 0;
}
}
VMState_solveUnusedStack(&vs);
stack_deinit(&(vs.stack));
return locals;
}
VMParameters* pikaVM_runByteCodeFrame(PikaObj* self,
ByteCodeFrame* byteCode_frame) {
TryInfo try_info = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE};
try_info.try_state = TRY_STATE_NONE;
2022-06-24 00:21:00 +08:00
return __pikaVM_runByteCodeFrameWithState(self, self, self, byteCode_frame,
0, &try_info);
2022-06-24 00:21:00 +08:00
}
InstructUnit* instructArray_getByOffset(InstructArray* self, int32_t offset) {
return (InstructUnit*)((uintptr_t)instructArray_getStart(self) +
(uintptr_t)offset);
}
void constPool_printAsArray(ConstPool* self) {
uint8_t* const_size_str = (uint8_t*)&(self->size);
__platform_printf("0x%02x, ", *(const_size_str));
__platform_printf("0x%02x, ", *(const_size_str + (uintptr_t)1));
__platform_printf("/* const pool size */\n");
uint16_t ptr_befor = self->content_offset_now;
uint8_t line_num = 12;
uint16_t g_i = 0;
/* set ptr_now to begin */
self->content_offset_now = 0;
__platform_printf("0x00, ");
while (1) {
if (NULL == constPool_getNext(self)) {
goto exit;
}
char* data_each = constPool_getNow(self);
/* todo start */
for (uint32_t i = 0; i < strGetSize(data_each) + 1; i++) {
__platform_printf("0x%02x, ", *(data_each + (uintptr_t)i));
g_i++;
if (g_i % line_num == 0) {
__platform_printf("\n");
}
}
/* todo end */
}
exit:
/* retore ptr_now */
__platform_printf("/* const pool */\n");
self->content_offset_now = ptr_befor;
return;
}
void byteCodeFrame_printAsArray(ByteCodeFrame* self) {
__platform_printf("const uint8_t bytes[] = {\n");
instructArray_printAsArray(&(self->instruct_array));
constPool_printAsArray(&(self->const_pool));
__platform_printf("};\n");
__platform_printf("pikaVM_runByteCode(self, (uint8_t*)bytes);\n");
}
PikaObj* pikaVM_runFile(PikaObj* self, char* file_name) {
Args buffs = {0};
char* module_name = strsCopy(&buffs, file_name);
strPopLastToken(module_name, '.');
__platform_printf("(pikascript) pika compiler:\r\n");
PikaMaker* maker = New_PikaMaker();
pikaMaker_compileModuleWithDepends(maker, module_name);
pikaMaker_linkCompiledModules(maker, "pikaModules_cache.py.a");
obj_deinit(maker);
__platform_printf("(pikascript) all succeed.\r\n\r\n");
pikaMemMaxReset();
Obj_linkLibraryFile(self, "pikascript-api/pikaModules_cache.py.a");
self = pikaVM_runSingleFile(self, file_name);
strsDeinit(&buffs);
return self;
}