예제 #1
0
bool compiler::compile_assign_stmt(codegen & cg, assign_stmt * as)
{
	FKLOG("[compiler] compile_assign_stmt %p", as);

	command var = 0;
	command value = 0;

	if (!compile_node(cg, as->value))
	{
		FKERR("[compiler] compile_assign_stmt value fail");
		return false;
	}
	value = m_cur_addr;
	FKLOG("[compiler] compile_assign_stmt value = %d", m_cur_addr);

	m_new_var = as->isnew;
	if (!compile_node(cg, as->var))
	{
		FKERR("[compiler] compile_assign_stmt var fail");
		return false;
	}
	m_new_var = false;
	var = m_cur_addr;
	FKLOG("[compiler] compile_assign_stmt var = %d", m_cur_addr);
	
	cg.push(MAKE_OPCODE(OPCODE_ASSIGN), as->lineno());
	cg.push(var, as->lineno());
	cg.push(value, as->lineno());
	FKLOG("[compiler] compile_assign_stmt %p OK", as);
	
	return true;
}
예제 #2
0
파일: compile.c 프로젝트: tinkertim/slash
NODE(sl_node_def_t, def)
{
    sl_vm_insn_t insn;
    sl_compile_state_t sub_cs;
    size_t i, on_reg;
    init_compile_state(&sub_cs, cs->vm, cs, node->req_arg_count + node->opt_arg_count + 1);
    for(i = 0; i < node->req_arg_count; i++) {
        st_insert(sub_cs.vars, (st_data_t)node->req_args[i], (st_data_t)(i + 1));
    }
    for(i = 0; i < node->opt_arg_count; i++) {
        st_insert(sub_cs.vars, (st_data_t)node->opt_args[i].name, (st_data_t)(node->req_arg_count + i + 1));
    }
    sub_cs.section->name = node->name;
    sub_cs.section->req_registers = node->req_arg_count;
    sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count;
    sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1));
    
    for(i = 0; i < node->opt_arg_count; i++) {
        sub_cs.section->opt_skip[i] = sub_cs.section->insns_count;
        compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1);
    }
    sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count;
    
    compile_node(&sub_cs, node->body, 0);
    insn.opcode = SL_OP_RETURN;
    emit(&sub_cs, insn);
    insn.uint = 0;
    emit(&sub_cs, insn);
    
    if(node->on) {
        on_reg = reg_alloc(cs);
        compile_node(cs, node->on, on_reg);
        insn.opcode = SL_OP_DEFINE_ON;
        emit(cs, insn);
        insn.uint = on_reg;
        emit(cs, insn);
        reg_free(cs, on_reg);
    } else {
        insn.opcode = SL_OP_DEFINE;
        emit(cs, insn);
    }
    insn.imm = node->name;
    emit(cs, insn);
    insn.section = sub_cs.section;
    emit(cs, insn);
    insn.uint = dest;
    emit(cs, insn);
}
예제 #3
0
bool compiler::compile_return_stmt(codegen & cg, return_stmt * rs)
{
	FKLOG("[compiler] compile_return_stmt %p", rs);

	if (rs->returnlist)
	{
		if (!compile_node(cg, rs->returnlist))
		{
			FKERR("[compiler] compile_return_stmt ret fail");
			return false;
		}

		cg.push(MAKE_OPCODE(OPCODE_RETURN), rs->lineno());
		cg.push(MAKE_POS(rs->returnlist->returnlist.size()), rs->lineno());
		for (int i = 0; i < (int)rs->returnlist->returnlist.size(); i++)
		{
			cg.push(m_cur_addrs[i], rs->lineno());
		}
	}
	else
	{
		cg.push(MAKE_OPCODE(OPCODE_RETURN), rs->lineno());
		cg.push(MAKE_POS(0), rs->lineno());
	}

	FKLOG("[compiler] compile_return_stmt %p OK", rs);
	
	return true;
}
예제 #4
0
bool compiler::compile_return_value_list(codegen & cg, return_value_list_node * rn)
{
	FKLOG("[compiler] compile_return_value_list %p", rn);

	if (rn->returnlist.size() > MAX_FAKE_RETURN_NUM)
	{
		FKERR("[compiler] compile_return_value_list return too much");
		compile_seterror(rn, m_fk, efk_compile_variable_not_found, "return too much");
		return false;
	}
	
	command tmp[MAX_FAKE_RETURN_NUM];
	for (int i = 0; i < (int)rn->returnlist.size(); i++)
	{
		if (!compile_node(cg, rn->returnlist[i]))
		{
			FKERR("[compiler] compile_return_value_list value fail");
			return false;
		}
		tmp[i] = m_cur_addr;
	}
	memcpy(m_cur_addrs, tmp, sizeof(command) * MAX_FAKE_RETURN_NUM);
	m_cur_addr = m_cur_addrs[0];

	FKLOG("[compiler] compile_return_value_list %p OK", rn);

	return true;
}
예제 #5
0
파일: compile.c 프로젝트: tinkertim/slash
NODE(sl_node_lambda_t, lambda)
{
    sl_vm_insn_t insn;
    sl_compile_state_t sub_cs;
    size_t i;
    init_compile_state(&sub_cs, cs->vm, cs, node->arg_count + 1);
    for(i = 0; i < node->arg_count; i++) {
        st_insert(sub_cs.vars, (st_data_t)node->args[i], (st_data_t)(i + 1));
    }
    sub_cs.section->req_registers = node->arg_count;
    sub_cs.section->arg_registers = node->arg_count;
    sub_cs.section->name = sl_make_cstring(cs->vm, "<lambda>");
    compile_node(&sub_cs, node->body, 0);
    insn.opcode = SL_OP_RETURN;
    emit(&sub_cs, insn);
    insn.uint = 0;
    emit(&sub_cs, insn);
    
    insn.opcode = SL_OP_LAMBDA;
    emit(cs, insn);
    insn.section = sub_cs.section;
    emit(cs, insn);
    insn.uint = dest;
    emit(cs, insn);
}
예제 #6
0
파일: compile.c 프로젝트: Hmaal/slash
static void
emit_assignment(sl_compile_state_t* cs, sl_node_base_t* lval, size_t reg)
{
    sl_node_assign_var_t a_var;
    sl_node_send_t send;

    size_t dest_reg = reg_alloc(cs);

    sl_node__register_t node;
    node.base.type = SL_NODE__REGISTER;
    node.base.line = 0;
    node.reg = reg;

    switch(lval->type) {
        case SL_NODE_VAR:    a_var.base.type = SL_NODE_ASSIGN_VAR;    break;
        case SL_NODE_IVAR:   a_var.base.type = SL_NODE_ASSIGN_IVAR;   break;
        case SL_NODE_CVAR:   a_var.base.type = SL_NODE_ASSIGN_CVAR;   break;
        case SL_NODE_CONST:  a_var.base.type = SL_NODE_ASSIGN_CONST;  break;
        case SL_NODE_ARRAY:  a_var.base.type = SL_NODE_ASSIGN_ARRAY;  break;
        case SL_NODE_SEND:
            /* special case that turns a.b = 1 into a.send("b=", 1) */
            /* this is separate to the other method of handling send assignments
               which also handles compound assignments. */
            memcpy(&send, lval, sizeof(sl_node_send_t));
            send.id = sl_id_make_setter(cs->vm, send.id);
            sl_node_base_t** args = sl_alloc(cs->vm->arena, sizeof(sl_node_base_t*) * (send.arg_count + 1));
            memcpy(args, send.args, sizeof(sl_node_base_t*) * send.arg_count);
            args[send.arg_count++] = (sl_node_base_t*)&node;
            send.args = args;
            compile_node(cs, (sl_node_base_t*)&send, dest_reg);
            reg_free(cs, dest_reg);
            return;
        default: {
            SLVAL err = sl_make_cstring(cs->vm, "Invalid lval in assignment");
            err = sl_make_error2(cs->vm, cs->vm->lib.SyntaxError, err);
            sl_error_add_frame(cs->vm, err, sl_make_cstring(cs->vm, "<compiler>"), sl_make_cstring(cs->vm, (char*)cs->section->filename), sl_make_int(cs->vm, lval->line));
            sl_throw(cs->vm, err);
        }
    }

    a_var.base.line = 0;
    a_var.lval = (void*)lval;
    a_var.rval = (sl_node_base_t*)&node;
    compile_node(cs, (sl_node_base_t*)&a_var, dest_reg);

    reg_free(cs, dest_reg);
}
예제 #7
0
bool compiler::compile_multi_assign_stmt(codegen & cg, multi_assign_stmt * as)
{
	FKLOG("[compiler] compile_multi_assign_stmt %p", as);

	// 目前多重赋值只支持a,b,c = myfunc1(),需要告诉func1多返回几个值
	m_func_ret_num = as->varlist->varlist.size();

	// 编译value
	if (!compile_node(cg, as->value))
	{
		FKERR("[compiler] compile_multi_assign_stmt value fail");
		return false;
	}

	// 挨个编译var
	std::vector<command> varlist;
	for (int i = 0; i < (int)as->varlist->varlist.size(); i++)
	{
		m_new_var = as->isnew;
		if (!compile_node(cg, as->varlist->varlist[i]))
		{
			FKERR("[compiler] compile_multi_assign_stmt var fail");
			return false;
		}
		m_new_var = false;
		varlist.push_back(m_cur_addr);
	}

	// 挨个赋值
	for (int i = 0; i < (int)as->varlist->varlist.size(); i++)
	{
		command var = 0;
		command value = 0;

		var = varlist[i];
		value = m_cur_addrs[i];

		cg.push(MAKE_OPCODE(OPCODE_ASSIGN), as->lineno());
		cg.push(var, as->lineno());
		cg.push(value, as->lineno());
	}

	FKLOG("[compiler] compile_multi_assign_stmt %p OK", as);

	return true;
}
예제 #8
0
파일: compile.c 프로젝트: Hmaal/slash
NODE(sl_node_interp_string_t, interp_string)
{
    size_t base_reg = reg_alloc_block(cs, node->components_count);
    for(size_t i = 0; i < node->components_count; i++) {
        compile_node(cs, node->components[i], base_reg + i);
    }
    op_build_string(cs, base_reg, node->components_count, dest);
    reg_free_block(cs, base_reg, node->components_count);
}
예제 #9
0
파일: compile.c 프로젝트: tinkertim/slash
NODE(sl_node_echo_t, echo_raw)
{
    sl_vm_insn_t insn;
    compile_node(cs, node->expr, dest);
    insn.opcode = SL_OP_ECHO_RAW;
    emit(cs, insn);
    insn.uint = dest;
    emit(cs, insn);
}
예제 #10
0
파일: compile.c 프로젝트: Hmaal/slash
NODE(sl_node_def_t, def)
{
    sl_compile_state_t sub_cs;
    size_t i, on_reg;
    size_t init_regs = 1 + node->req_arg_count + node->opt_arg_count;
    if(node->rest_arg) {
        init_regs++;
    }
    init_compile_state(&sub_cs, cs->vm, cs, init_regs);
    for(i = 0; i < node->req_arg_count; i++) {
        sl_st_insert(sub_cs.vars, (sl_st_data_t)node->req_args[i], (sl_st_data_t)(i + 1));
    }
    for(i = 0; i < node->opt_arg_count; i++) {
        sl_st_insert(sub_cs.vars, (sl_st_data_t)node->opt_args[i].name, (sl_st_data_t)(node->req_arg_count + i + 1));
    }
    if(node->rest_arg) {
        sl_st_insert(sub_cs.vars, (sl_st_data_t)node->rest_arg, (sl_st_data_t)(node->req_arg_count + node->opt_arg_count + 1));
        sub_cs.section->has_extra_rest_arg = 1;
    }
    sub_cs.section->name = node->name;
    sub_cs.section->req_registers = node->req_arg_count;
    sub_cs.section->arg_registers = node->req_arg_count + node->opt_arg_count;
    sub_cs.section->opt_skip = sl_alloc(cs->vm->arena, sizeof(size_t) * (node->opt_arg_count + 1));

    for(i = 0; i < node->opt_arg_count; i++) {
        sub_cs.section->opt_skip[i] = sub_cs.section->insns_count;
        compile_node(&sub_cs, node->opt_args[i].default_value, node->req_arg_count + i + 1);
    }
    sub_cs.section->opt_skip[node->opt_arg_count] = sub_cs.section->insns_count;

    compile_node(&sub_cs, node->body, 0);
    op_return(&sub_cs, 0);

    if(node->on) {
        on_reg = reg_alloc(cs);
        compile_node(cs, node->on, on_reg);
        op_define_on(cs, on_reg, node->name, node->doc, sub_cs.section, dest);
        reg_free(cs, on_reg);
    } else {
        op_define(cs, node->name, node->doc, sub_cs.section, dest);
    }
}
예제 #11
0
파일: compile.c 프로젝트: Hmaal/slash
NODE(sl_node_seq_t, seq)
{
    size_t i;
    for(i = 0; i < node->node_count; i++) {
        /*  we only care about the result of the last node so we'll write all
            results to the same output register we were given */
        compile_node(cs, node->nodes[i], dest);
    }
    if(node->node_count == 0) {
        op_immediate(cs, cs->vm->lib.nil, dest);
    }
}
예제 #12
0
파일: compile.c 프로젝트: Hmaal/slash
NODE(sl_node_lambda_t, lambda)
{
    sl_compile_state_t sub_cs;
    size_t i;
    init_compile_state(&sub_cs, cs->vm, cs, node->arg_count + 1);
    for(i = 0; i < node->arg_count; i++) {
        sl_st_insert(sub_cs.vars, (sl_st_data_t)node->args[i], (sl_st_data_t)(i + 1));
    }
    sub_cs.section->req_registers = node->arg_count;
    sub_cs.section->arg_registers = node->arg_count;
    sub_cs.section->name = sl_intern(cs->vm, "<lambda>");
    compile_node(&sub_cs, node->body, 0);
    op_return(&sub_cs, 0);
    op_lambda(cs, sub_cs.section, dest);
}
예제 #13
0
bool compiler::compile_block(codegen & cg, block_node * blocknode)
{
	FKLOG("[compiler] compile_block block_node %p", blocknode);

	for (int i = 0; i < (int)blocknode->stmtlist.size(); i++)
	{
		syntree_node * stmt = blocknode->stmtlist[i];
		if (!compile_node(cg, stmt))
		{
			FKERR("[compiler] compile_block compile_node %p fail %s", blocknode, stmt->gettypename());
			return false;
		}
	}
	
	FKLOG("[compiler] compile_block block_node %p OK", blocknode);
	
	return true;
}
예제 #14
0
bool compiler::compile_container_get(codegen & cg, container_get_node * cn)
{
	FKLOG("[compiler] compile_container_get %p", cn);

	// 编译con
	command con = 0;

	// 看看是否是全局常量定义
	variant * gcv = m_fk->pa.get_const_define(cn->container.c_str());
	if (gcv)
	{
		int pos = cg.getconst(*gcv);
		con = MAKE_ADDR(ADDR_CONST, pos);
	}
	else
	{
		int pos = cg.getvariable(cn->container);
		if (pos == -1)
		{
			FKERR("[compiler] compile_container_get variable not found %s", cn->container.c_str());
			compile_seterror(cn, m_fk, efk_compile_variable_not_found, "variable %s not found", cn->container.c_str());
			return false;
		}
		con = MAKE_ADDR(ADDR_STACK, pos);
	}

	// 编译key
	command key = 0;
	if (!compile_node(cg, cn->key))
	{
		FKERR("[compiler] compile_container_get key fail");
		return false;
	}
	key = m_cur_addr;

	// 返回
	int addrpos = cg.getcontaineraddr(con, key);
	m_cur_addr = MAKE_ADDR(ADDR_CONTAINER, addrpos);
	
	FKLOG("[compiler] compile_container_get %p OK", cn);

	return true;
}
예제 #15
0
bool compiler::compile_yield_stmt(codegen & cg, yield_stmt * ys)
{
	FKLOG("[compiler] compile_yield_stmt %p", ys);

	// 编译time
	command time = 0;
	if (!compile_node(cg, ys->time))
	{
		FKERR("[compiler] compile_sleep_stmt time fail");
		return false;
	}
	time = m_cur_addr;

	cg.push(MAKE_OPCODE(OPCODE_YIELD), ys->lineno());
	cg.push(time, ys->lineno());
	
	FKLOG("[compiler] compile_yield_stmt %p OK", ys);

	return true;
}
예제 #16
0
bool compiler::compile_while_stmt(codegen & cg, while_stmt * ws)
{
	FKLOG("[compiler] compile_while_stmt %p", ws);

	int startpos = 0;
	int jnepos = 0;

	m_loop_break_pos_stack.push_back(beak_pos_list());

	startpos = cg.byte_code_size();

	m_loop_continue_pos_stack.push_back(startpos);

	// 条件
	cg.push_stack_identifiers();
	if (!compile_node(cg, ws->cmp))
	{
		FKERR("[compiler] compile_while_stmt cmp fail");
		return false;
	}
	cg.pop_stack_identifiers();

	// cmp与jne结合
	if (m_cmp_jne)
	{
		cg.push(EMPTY_CMD, ws->cmp->lineno()); // 先塞个位置
		jnepos = cg.byte_code_size() - 1;
	}
	else
	{
		cg.push(MAKE_OPCODE(OPCODE_JNE), ws->lineno());
		cg.push(m_cur_addr, ws->lineno());
		cg.push(EMPTY_CMD, ws->lineno()); // 先塞个位置
		jnepos = cg.byte_code_size() - 1;
	}
	m_cmp_deps = 0;
	m_cmp_jne = false;
	
	// block块
	if (ws->block)
	{
		cg.push_stack_identifiers();
		if (!compile_node(cg, ws->block))
		{
			FKERR("[compiler] compile_while_stmt block fail");
			return false;
		}
		cg.pop_stack_identifiers();
	}

	// 跳回判断地方
	cg.push(MAKE_OPCODE(OPCODE_JMP), ws->lineno());
	cg.push(MAKE_POS(startpos), ws->lineno());

	// 跳转出block块
	cg.set(jnepos, MAKE_POS(cg.byte_code_size()));

	// 替换掉break
	beak_pos_list & bplist = m_loop_break_pos_stack[m_loop_break_pos_stack.size() - 1];
	for (int i = 0; i < (int)bplist.size(); i++)
	{
		cg.set(bplist[i], MAKE_POS(cg.byte_code_size()));
	}
	m_loop_break_pos_stack.pop_back();

	m_loop_continue_pos_stack.pop_back();
	
	FKLOG("[compiler] compile_while_stmt %p OK", ws);
	
	return true;
}
예제 #17
0
bool compiler::compile_function_call_node(codegen & cg, function_call_node * fn)
{
	FKLOG("[compiler] compile_function_call_node %p", fn);

	fake * fk = m_fk;
	myflexer * mf = m_mf;

	int ret_num = m_func_ret_num;
	m_func_ret_num = 1;

	// 参数
	std::vector<command> arglist;
	if (fn->arglist)
	{
		for (int i = 0; i < (int)fn->arglist->arglist.size(); i++)
		{
			syntree_node* sn = fn->arglist->arglist[i];
			if (!compile_node(cg, sn))
			{
				FKERR("[compiler] compile_function_call_node arg fail");
				return false;
			}
			arglist.push_back(m_cur_addr);
		}
	}

	// 调用位置
	command callpos;
	if (!fn->prefunc)
	{
		String func = fn->fuc;
		// 1 检查变量
		int pos = cg.getvariable(func);
		if (pos != -1)
		{
			// 是用变量来调用函数
			callpos = MAKE_ADDR(ADDR_STACK, pos);
		}
		// 2 检查struct
		else if (mf->is_have_struct(func))
		{
			// 直接替换成map
			variant v;
			v = fk->sh.allocsysstr(MAP_FUNC_NAME);
			pos = cg.getconst(v);
			callpos = MAKE_ADDR(ADDR_CONST, pos);
		}
		// 3 检查本地函数
		else if (mf->is_have_func(func))
		{
			// 申请字符串变量
			variant v;
			// 拼上包名
			String pname = fkgen_package_name(mf->get_package(), func);
			v = fk->sh.allocsysstr(pname.c_str());
			pos = cg.getconst(v);
			callpos = MAKE_ADDR(ADDR_CONST, pos);
		}
		// 4 直接字符串使用
		else
		{
			// 申请字符串变量
			variant v;
			v = fk->sh.allocsysstr(func.c_str());
			pos = cg.getconst(v);
			callpos = MAKE_ADDR(ADDR_CONST, pos);
		}
	}
	else
	{
		if (!compile_node(cg, fn->prefunc))
		{
			FKERR("[compiler] compile_function_call_node arg fail");
			return false;
		}

		callpos = m_cur_addr;
	}

	// oper
	command oper;
	oper = MAKE_OPCODE(OPCODE_CALL);

	// 调用类型
	command calltype;
	if (fn->fakecall)
	{
		calltype = MAKE_POS(CALL_FAKE);
	}
	else if (fn->classmem_call)
	{
		calltype = MAKE_POS(CALL_CLASSMEM);
	}
	else
	{
		calltype = MAKE_POS(CALL_NORMAL);
	}
	
	// 参数个数
	command argnum;
	argnum = MAKE_POS(arglist.size());
	if (arglist.size() > MAX_FAKE_PARAM_NUM)
	{
		FKERR("[compiler] compile_function_call_node arg too much");
		compile_seterror(fn, m_fk, efk_compile_variable_not_found, "arg too much");
		return false;
	}

	// 返回值个数
	command retnum;
	retnum = MAKE_POS(ret_num);
   
	// 返回值
	std::vector<command> ret;
	for (int i = 0; i < ret_num; i++)
	{
		int retpos = cg.alloc_stack_identifier();
		ret.push_back(MAKE_ADDR(ADDR_STACK, retpos));
		m_cur_addrs[i] = ret[i];
	}
	m_cur_addr = ret[0];
	
	cg.push(oper, fn->lineno());
	cg.push(calltype, fn->lineno());
	cg.push(callpos, fn->lineno());
	cg.push(retnum, fn->lineno());
	for (int i = 0; i < ret_num; i++)
	{
		cg.push(ret[i], fn->lineno());
	}
	cg.push(argnum, fn->lineno());
	for (int i = 0; i < (int)arglist.size(); i++)
	{
		cg.push(arglist[i], fn->lineno());
	}
	
	FKLOG("[compiler] compile_function_call_node %p OK", fn);
	
	return true;
}
예제 #18
0
bool compiler::compile_math_expr_node(codegen & cg, math_expr_node * mn)
{
	FKLOG("[compiler] compile_math_expr_node %p", mn);

	command oper = 0;
	command left = 0;
	command right = 0;
	command dest = 0;
	
	if (mn->oper == "+")
	{
		oper = MAKE_OPCODE(OPCODE_PLUS);
	}
	else if (mn->oper == "-")
	{
		oper = MAKE_OPCODE(OPCODE_MINUS);
	}
	else if (mn->oper == "*")
	{
		oper = MAKE_OPCODE(OPCODE_MULTIPLY);
	}
	else if (mn->oper == "/")
	{
		oper = MAKE_OPCODE(OPCODE_DIVIDE);
	}
	else if (mn->oper == "%")
	{
		oper = MAKE_OPCODE(OPCODE_DIVIDE_MOD);
	}
	else if (mn->oper == "..")
	{
		oper = MAKE_OPCODE(OPCODE_STRING_CAT);
	}
	else
	{
		FKERR("[compiler] compile_math_expr_node error oper type fail");
		compile_seterror(mn, m_fk, efk_compile_math_type_error, "compile math oper type %s error", mn->oper.c_str());
		return false;
	}

	// left
	if (!compile_node(cg, mn->left))
	{
		FKERR("[compiler] compile_math_expr_node left fail");
		return false;
	}
	left = m_cur_addr;

	// right
	if (!compile_node(cg, mn->right))
	{
		FKERR("[compiler] compile_math_expr_node left fail");
		return false;
	}
	right = m_cur_addr;

	// result
	int despos = cg.alloc_stack_identifier();
	dest = MAKE_ADDR(ADDR_STACK, despos);
	m_cur_addr = dest;
	
	cg.push(oper, mn->lineno());
	cg.push(left, mn->lineno());
	cg.push(right, mn->lineno());
	cg.push(dest, mn->lineno());

	FKLOG("[compiler] compile_math_expr_node %p OK", mn);
	
	return true;
}
예제 #19
0
파일: compile.c 프로젝트: Hmaal/slash
NODE(sl_node_echo_t, echo_raw)
{
    compile_node(cs, node->expr, dest);
    op_echo_raw(cs, dest);
}
예제 #20
0
bool compiler::compile_cmp_stmt(codegen & cg, cmp_stmt * cs)
{
	FKLOG("[compiler] compile_cmp_stmt %p", cs);

	int deps = m_cmp_deps;
	m_cmp_deps++;

	command oper = 0;
	command left = 0;
	command right = 0;
	command dest = 0;   

	if (cs->cmp != "not")
	{
		// oper
		if (cs->cmp == "&&")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_AND_JNE) : MAKE_OPCODE(OPCODE_AND);
		}
		else if (cs->cmp == "||")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_OR_JNE) : MAKE_OPCODE(OPCODE_OR);
		}
		else if (cs->cmp == "<")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_LESS_JNE) : MAKE_OPCODE(OPCODE_LESS);
		}
		else if (cs->cmp == ">")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_MORE_JNE) : MAKE_OPCODE(OPCODE_MORE);
		}
		else if (cs->cmp == "==")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_EQUAL_JNE) : MAKE_OPCODE(OPCODE_EQUAL);
		}
		else if (cs->cmp == ">=")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_MOREEQUAL_JNE) : MAKE_OPCODE(OPCODE_MOREEQUAL);
		}
		else if (cs->cmp == "<=")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_LESSEQUAL_JNE) : MAKE_OPCODE(OPCODE_LESSEQUAL);
		}
		else if (cs->cmp == "!=")
		{
			oper = !deps ? MAKE_OPCODE(OPCODE_NOTEQUAL_JNE) : MAKE_OPCODE(OPCODE_NOTEQUAL);
		}
		else if (cs->cmp == "true")
		{
			variant v;
			V_SET_REAL((&v), 1);
			int pos = cg.getconst(v);
			m_cur_addr = MAKE_ADDR(ADDR_CONST, pos);
			
			m_cmp_deps--;
			m_cmp_jne = false;
			
			return true;
		}
		else if (cs->cmp == "false")
		{
			variant v;
			V_SET_REAL((&v), 0);
			int pos = cg.getconst(v);
			m_cur_addr = MAKE_ADDR(ADDR_CONST, pos);
			
			m_cmp_deps--;
			m_cmp_jne = false;
			
			return true;
		}
		else if (cs->cmp == "is")
		{
			// left
			if (!compile_node(cg, cs->left))
			{
				FKERR("[compiler] compile_cmp_stmt left fail");
				return false;
			}
			
			m_cmp_deps--;
			m_cmp_jne = false;
			
			return true;
		}
		else
		{
			FKERR("[compiler] compile_cmp_stmt cmp error %s", cs->cmp.c_str());
			compile_seterror(cs, m_fk, efk_compile_cmp_error, "cmp error %s", cs->cmp.c_str());
			return false;
		}
		
		// left
		if (!compile_node(cg, cs->left))
		{
			FKERR("[compiler] compile_cmp_stmt left fail");
			return false;
		}
		left = m_cur_addr;

		// right
		if (!compile_node(cg, cs->right))
		{
			FKERR("[compiler] compile_cmp_stmt right fail");
			return false;
		}
		right = m_cur_addr;

		// result
		int despos = cg.alloc_stack_identifier();
		dest = MAKE_ADDR(ADDR_STACK, despos);
		m_cur_addr = dest;
		
		cg.push(oper, cs->lineno());
		cg.push(left, cs->lineno());
		cg.push(right, cs->lineno());
		cg.push(dest, cs->lineno());
	}
	/* "not" */
	else
	{
		oper = !deps ? MAKE_OPCODE(OPCODE_NOT_JNE) : MAKE_OPCODE(OPCODE_NOT);
		
		// left
		if (!compile_node(cg, cs->left))
		{
			FKERR("[compiler] compile_cmp_stmt left fail");
			return false;
		}
		left = m_cur_addr;
	
		int despos = cg.alloc_stack_identifier();
		dest = MAKE_ADDR(ADDR_STACK, despos);
		m_cur_addr = dest;
	
		cg.push(oper, cs->lineno());
		cg.push(left, cs->lineno());
		cg.push(dest, cs->lineno());
	}
	
	m_cmp_deps--;
	if (!deps)
	{
		m_cmp_jne = true;
	}
	
	FKLOG("[compiler] compile_cmp_stmt %p OK", cs);
	
	return true;
}
예제 #21
0
bool compiler::compile_math_assign_stmt(codegen & cg, math_assign_stmt * ms)
{
	FKLOG("[compiler] compile_math_assign_stmt %p", ms);

	command oper = 0;
	command var = 0;
	command value = 0;
	
	if (ms->oper == "+=")
	{
		oper = MAKE_OPCODE(OPCODE_PLUS_ASSIGN);
	}
	else if (ms->oper == "-=")
	{
		oper = MAKE_OPCODE(OPCODE_MINUS_ASSIGN);
	}
	else if (ms->oper == "*=")
	{
		oper = MAKE_OPCODE(OPCODE_MULTIPLY_ASSIGN);
	}
	else if (ms->oper == "/=")
	{
		oper = MAKE_OPCODE(OPCODE_DIVIDE_ASSIGN);
	}
	else if (ms->oper == "%=")
	{
		oper = MAKE_OPCODE(OPCODE_DIVIDE_MOD_ASSIGN);
	}
	else
	{
		FKERR("[compiler] compile_math_assign_stmt error oper type fail");
		compile_seterror(ms, m_fk, efk_compile_math_type_error, "compile math assign oper type %s error", ms->oper.c_str());
		return false;
	}

	// value
	if (!compile_node(cg, ms->value))
	{
		FKERR("[compiler] compile_math_assign_stmt value fail");
		return false;
	}
	value = m_cur_addr;
	FKLOG("[compiler] compile_math_assign_stmt value = %d", m_cur_addr);

	// var
	if (!compile_node(cg, ms->var))
	{
		FKERR("[compiler] compile_math_assign_stmt var fail");
		return false;
	}
	var = m_cur_addr;
	FKLOG("[compiler] compile_math_assign_stmt var = %d", m_cur_addr);

	cg.push(oper, ms->lineno());
	cg.push(var, ms->lineno());
	cg.push(value, ms->lineno());

	FKLOG("[compiler] compile_math_assign_stmt %p OK", ms);
	
	return true;
}
예제 #22
0
bool compiler::compile_switch_stmt(codegen & cg, switch_stmt * ss)
{
	FKLOG("[compiler] compile_switch_stmt %p", ss);

	command caseleft;
	command caseresult;

	cg.push_stack_identifiers();
	
	// caseleft
	if (!compile_node(cg, ss->cmp))
	{
		FKERR("[compiler] compile_switch_stmt cmp fail");
		return false;
	}
	caseleft = m_cur_addr;

	// caseresult
	int despos = cg.alloc_stack_identifier();
	caseresult = MAKE_ADDR(ADDR_STACK, despos);

	switch_caselist_node * scln = dynamic_cast<switch_caselist_node *>(ss->caselist);

	std::vector<int> jmpswitchposlist;
	
	// 挨个和case的比较
	for (int i = 0; i < (int)scln->list.size(); i++)
	{
		command oper = MAKE_OPCODE(OPCODE_EQUAL);
		command left = caseleft;
		command right = 0;
		command dest = caseresult;

		switch_case_node * scn = dynamic_cast<switch_case_node *>(scln->list[i]);
	
		// right
		if (!compile_node(cg, scn->cmp))
		{
			FKERR("[compiler] compile_switch_stmt case cmp fail");
			return false;
		}
		right = m_cur_addr;

		// push case
		cg.push(oper, scn->lineno());
		cg.push(left, scn->lineno());
		cg.push(right, scn->lineno());
		cg.push(dest, scn->lineno());

		// push jmp
		cg.push(MAKE_OPCODE(OPCODE_JNE), scn->lineno());
		cg.push(dest, scn->lineno());
		cg.push(EMPTY_CMD, scn->lineno()); // 先塞个位置
		int jnepos = cg.byte_code_size() - 1;

		// build block
		if (scn->block)
		{
			cg.push_stack_identifiers();
			if (!compile_node(cg, scn->block))
			{
				FKERR("[compiler] compile_switch_stmt block fail");
				return false;
			}
			cg.pop_stack_identifiers();
		}
		
		// 跳出switch块
		cg.push(MAKE_OPCODE(OPCODE_JMP), scn->lineno());
		cg.push(EMPTY_CMD, scn->lineno()); // 先塞个位置
		int jmpswitchpos = cg.byte_code_size() - 1;
		jmpswitchposlist.push_back(jmpswitchpos);
		
		// 跳转出case块
		cg.set(jnepos, MAKE_POS(cg.byte_code_size()));
		
	}

	// default
	if (ss->def)
	{
		cg.push_stack_identifiers();
		if (!compile_node(cg, ss->def))
		{
			FKERR("[compiler] compile_switch_stmt default fail");
			return false;
		}
		cg.pop_stack_identifiers();
	}
	
	cg.pop_stack_identifiers();

	// 塞跳出的
	for (int i = 0; i < (int)jmpswitchposlist.size(); i++)
	{
		cg.set(jmpswitchposlist[i], MAKE_POS(cg.byte_code_size()));
	}
	
	FKLOG("[compiler] compile_switch_stmt %p OK", ss);

	return true;
}
예제 #23
0
bool compiler::compile_if_stmt(codegen & cg, if_stmt * is)
{
	FKLOG("[compiler] compile_if_stmt %p", is);

	int jnepos = 0;
	std::vector<int> jmpifpos;

	// 条件
	cg.push_stack_identifiers();
	if (!compile_node(cg, is->cmp))
	{
		FKERR("[compiler] compile_if_stmt cmp fail");
		return false;
	}
	cg.pop_stack_identifiers();

	// cmp与jne结合
	if (m_cmp_jne)
	{
		cg.push(EMPTY_CMD, is->cmp->lineno()); // 先塞个位置
		jnepos = cg.byte_code_size() - 1;
	}
	else
	{
		cg.push(MAKE_OPCODE(OPCODE_JNE), is->lineno());
		cg.push(m_cur_addr, is->lineno());
		cg.push(EMPTY_CMD, is->lineno()); // 先塞个位置
		jnepos = cg.byte_code_size() - 1;
	}
	m_cmp_deps = 0;
	m_cmp_jne = false;
	
	// if块
	if (is->block)
	{
		cg.push_stack_identifiers();
		if (!compile_node(cg, is->block))
		{
			FKERR("[compiler] compile_if_stmt block fail");
			return false;
		}
		cg.pop_stack_identifiers();
	}
	
	// 跳出if块
	if (is->elseifs || (is->elses && is->elses->block))
	{
		cg.push(MAKE_OPCODE(OPCODE_JMP), is->lineno());
		cg.push(EMPTY_CMD, is->lineno()); // 先塞个位置
		jmpifpos.push_back(cg.byte_code_size() - 1);
	}
	
	// 开始处理elseif的
	if (is->elseifs)
	{
		stmt_node_list & list = is->elseifs->stmtlist;
		for (int i = 0; i < (int)list.size(); i++)
		{
			elseif_stmt * eis = dynamic_cast<elseif_stmt *>(list[i]);
			
			// 跳转到else if
			cg.set(jnepos, MAKE_POS(cg.byte_code_size()));
			
			// 条件
			cg.push_stack_identifiers();
			if (!compile_node(cg, eis->cmp))
			{
				FKERR("[compiler] compile_if_stmt cmp fail");
				return false;
			}
			cg.pop_stack_identifiers();

			// cmp与jne结合
			if (m_cmp_jne)
			{
				cg.push(EMPTY_CMD, eis->cmp->lineno()); // 先塞个位置
				jnepos = cg.byte_code_size() - 1;
			}
			else
			{
				cg.push(MAKE_OPCODE(OPCODE_JNE), eis->lineno());
				cg.push(m_cur_addr, eis->lineno());
				cg.push(EMPTY_CMD, eis->lineno()); // 先塞个位置
				jnepos = cg.byte_code_size() - 1;
			}
			m_cmp_deps = 0;
			m_cmp_jne = false;
			
			// else if块
			if (eis->block)
			{
				cg.push_stack_identifiers();
				if (!compile_node(cg, eis->block))
				{
					FKERR("[compiler] compile_if_stmt block fail");
					return false;
				}
				cg.pop_stack_identifiers();
			}
			
			// 跳出if块
			cg.push(MAKE_OPCODE(OPCODE_JMP), eis->lineno());
			cg.push(EMPTY_CMD, eis->lineno()); // 先塞个位置
			jmpifpos.push_back(cg.byte_code_size() - 1);
		}
	}
		
	// 跳转到else
	cg.set(jnepos, MAKE_POS(cg.byte_code_size()));
	
	// else块
	if (is->elses && is->elses->block)
	{
		cg.push_stack_identifiers();
		if (!compile_node(cg, is->elses->block))
		{
			FKERR("[compiler] compile_if_stmt else block fail");
			return false;
		}
		cg.pop_stack_identifiers();
	}
	
	// 跳转到结束
	for (int i = 0; i < (int)jmpifpos.size(); i++)
	{
		cg.set(jmpifpos[i], MAKE_POS(cg.byte_code_size()));
	}
	
	FKLOG("[compiler] compile_if_stmt %p OK", is);
	
	return true;
}
예제 #24
0
bool compiler::compile_for_loop_stmt(codegen & cg, for_loop_stmt * fs)
{
	FKLOG("[compiler] compile_for_loop_stmt %p", fs);

	int startpos = 0;
	int jnepos = 0;
	int continuepos = 0;

	m_loop_break_pos_stack.push_back(beak_pos_list());
	m_continue_end_pos_stack.push_back(continue_end_pos_list());

	// 初始值
	if (!compile_node(cg, fs->begin))
	{
		FKERR("[compiler] compile_for_loop_stmt begin fail");
		return false;
	}
	command begin = m_cur_addr;

	// 循环变量,这个作用域是全for都有效的
	cg.push_stack_identifiers();
	if (!compile_node(cg, fs->var))
	{
		FKERR("[compiler] compile_for_loop_stmt var fail");
		return false;
	}
	command var = m_cur_addr;

	// 最大值
	if (!compile_node(cg, fs->end))
	{
		FKERR("[compiler] compile_for_loop_stmt end fail");
		return false;
	}
	command end = m_cur_addr;

	// 变化值
	if (!compile_node(cg, fs->add))
	{
		FKERR("[compiler] compile_for_loop_stmt add fail");
		return false;
	}
	command add = m_cur_addr;

	// 塞for头
	cg.push(MAKE_OPCODE(OPCODE_FORBEGIN), fs->lineno());
	cg.push(var, fs->lineno());
	cg.push(begin, fs->lineno());
	cg.push(end, fs->lineno());
	cg.push(add, fs->lineno());
	cg.push(EMPTY_CMD, fs->lineno()); // 先塞个位置
	jnepos = cg.byte_code_size() - 1;

	// 需要continue end
	m_loop_continue_pos_stack.push_back(-1);

	startpos = cg.byte_code_size();

	// block块
	if (fs->block)
	{
		cg.push_stack_identifiers();
		if (!compile_node(cg, fs->block))
		{
			FKERR("[compiler] compile_for_loop_stmt block fail");
			return false;
		}
		cg.pop_stack_identifiers();
	}

	continuepos = cg.byte_code_size();

	// 最大值
	if (!compile_node(cg, fs->end))
	{
		FKERR("[compiler] compile_for_loop_stmt end fail");
		return false;
	}
	end = m_cur_addr;

	// 变化值
	if (!compile_node(cg, fs->add))
	{
		FKERR("[compiler] compile_for_loop_stmt add fail");
		return false;
	}
	add = m_cur_addr;

	// 塞for loop
	cg.push(MAKE_OPCODE(OPCODE_FORLOOP), fs->lineno());
	cg.push(var, fs->lineno());
	cg.push(end, fs->lineno());
	cg.push(add, fs->lineno());
	cg.push(MAKE_POS(startpos), fs->lineno());

	// 跳转出block块
	cg.set(jnepos, MAKE_POS(cg.byte_code_size()));

	// 替换掉break
	beak_pos_list & bplist = m_loop_break_pos_stack[m_loop_break_pos_stack.size() - 1];
	for (int i = 0; i < (int)bplist.size(); i++)
	{
		cg.set(bplist[i], MAKE_POS(cg.byte_code_size()));
	}
	m_loop_break_pos_stack.pop_back();
	
	// 替换掉continue
	continue_end_pos_list & cplist = m_continue_end_pos_stack[m_continue_end_pos_stack.size() - 1];
	for (int i = 0; i < (int)cplist.size(); i++)
	{
		cg.set(cplist[i], MAKE_POS(continuepos));
	}
	m_continue_end_pos_stack.pop_back();
	
	m_loop_continue_pos_stack.pop_back();
	
	// 离开作用域
	cg.pop_stack_identifiers();

	FKLOG("[compiler] compile_for_loop_stmt %p OK", fs);

	return true;
}