SIMCAR_Value * get_array_element_lvalue(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, Expression *expr) { SIMCAR_Value array; SIMCAR_Value index; eval_expression(inter, env, expr->u.index_expression.array); eval_expression(inter, env, expr->u.index_expression.index); index = pop_value(inter); array = pop_value(inter); if (array.type != SIMCAR_ARRAY_VALUE) { crb_runtime_error(expr->line_number, INDEX_OPERAND_NOT_ARRAY_ERR, MESSAGE_ARGUMENT_END); } if (index.type != SIMCAR_INT_VALUE) { crb_runtime_error(expr->line_number, INDEX_OPERAND_NOT_INT_ERR, MESSAGE_ARGUMENT_END); } if (index.u.int_value < 0 || index.u.int_value >= array.u.object->u.array.size) { crb_runtime_error(expr->line_number, ARRAY_INDEX_OUT_OF_BOUNDS_ERR, INT_MESSAGE_ARGUMENT, "size", array.u.object->u.array.size, INT_MESSAGE_ARGUMENT, "index", index.u.int_value, MESSAGE_ARGUMENT_END); } return &array.u.object->u.array.array[index.u.int_value]; }
SIMCAR_Value crb_eval_minus_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, Expression *operand) { eval_minus_expression(inter, env, operand); return pop_value(inter); }
SIMCAR_Value crb_eval_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, Expression *expr) { eval_expression(inter, env, expr); return pop_value(inter); }
SIMCAR_Value crb_eval_binary_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, ExpressionType operato, Expression *left, Expression *right) { eval_binary_expression(inter, env, operato, left, right); return pop_value(inter); }
static void eval_logical_and_or_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, ExpressionType operato, Expression *left, Expression *right) { SIMCAR_Value left_val; SIMCAR_Value right_val; SIMCAR_Value result; result.type = SIMCAR_BOOLEAN_VALUE; eval_expression(inter, env, left); left_val = pop_value(inter); if (left_val.type != SIMCAR_BOOLEAN_VALUE) { crb_runtime_error(left->line_number, NOT_BOOLEAN_TYPE_ERR, MESSAGE_ARGUMENT_END); } if (operato == LOGICAL_AND_EXPRESSION) { if (!left_val.u.boolean_value) { result.u.boolean_value = SIMCAR_FALSE; goto FUNC_END; } } else if (operato == LOGICAL_OR_EXPRESSION) { if (left_val.u.boolean_value) { result.u.boolean_value = SIMCAR_TRUE; goto FUNC_END; } } else { DBG_panic(("bad operator..%d\n", operato)); } eval_expression(inter, env, right); right_val = pop_value(inter); result.u.boolean_value = right_val.u.boolean_value; FUNC_END: push_value(inter, &result); }
static void call_crowbar_function(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, SIMCAR_LocalEnvironment *caller_env, Expression *expr, FunctionDefinition *func) { SIMCAR_Value value; StatementResult result; ArgumentList *arg_p; ParameterList *param_p; for (arg_p = expr->u.function_call_expression.argument, param_p = func->u.crowbar_f.parameter; arg_p; arg_p = arg_p->next, param_p = param_p->next) { Variable *new_var; SIMCAR_Value arg_val; if (param_p == NULL) { crb_runtime_error(expr->line_number, ARGUMENT_TOO_MANY_ERR, MESSAGE_ARGUMENT_END); } eval_expression(inter, caller_env, arg_p->expression); arg_val = pop_value(inter); new_var = crb_add_local_variable(env, param_p->name); new_var->value = arg_val; } if (param_p) { crb_runtime_error(expr->line_number, ARGUMENT_TOO_FEW_ERR, MESSAGE_ARGUMENT_END); } result = crb_execute_statement_list(inter, env, func->u.crowbar_f.block ->statement_list); if (result.type == RETURN_STATEMENT_RESULT) { value = result.u.return_value; } else { value.type = SIMCAR_NULL_VALUE; } push_value(inter, &value); }
static void eval_minus_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, Expression *operand) { SIMCAR_Value operand_val; SIMCAR_Value result; eval_expression(inter, env, operand); operand_val = pop_value(inter); if (operand_val.type == SIMCAR_INT_VALUE) { result.type = SIMCAR_INT_VALUE; result.u.int_value = -operand_val.u.int_value; } else if (operand_val.type == SIMCAR_DOUBLE_VALUE) { result.type = SIMCAR_DOUBLE_VALUE; result.u.double_value = -operand_val.u.double_value; } else { crb_runtime_error(operand->line_number, MINUS_OPERAND_TYPE_ERR, MESSAGE_ARGUMENT_END); } push_value(inter, &result); }
static void eval_array_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, ExpressionList *list) { SIMCAR_Value v; int size; ExpressionList *pos; int i; size = 0; for (pos = list; pos; pos = pos->next) { size++; } v.type = SIMCAR_ARRAY_VALUE; v.u.object = crb_create_array_i(inter, size); push_value(inter, &v); for (pos = list, i = 0; pos; pos = pos->next, i++) { eval_expression(inter, env, pos->expression); v.u.object->u.array.array[i] = pop_value(inter); } }
static void op_pop_value(int byte, struct thread *thread) { pop_value(thread, decode_arg(thread)); }
static void op_pop_value_immed(int byte, struct thread *thread) { pop_value(thread, byte & 0xf); }
static void eval_method_call_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, Expression *expr) { SIMCAR_Value *left; SIMCAR_Value result; SIMCAR_Boolean error_flag = SIMCAR_FALSE; eval_expression(inter, env, expr->u.method_call_expression.expression); left = peek_stack(inter, 0); if (left->type == SIMCAR_ARRAY_VALUE) { if (!strcmp(expr->u.method_call_expression.identifier, "add")) { SIMCAR_Value *add; check_method_argument_count(expr->line_number, expr->u.method_call_expression .argument, 1); eval_expression(inter, env, expr->u.method_call_expression.argument ->expression); add = peek_stack(inter, 0); crb_array_add(inter, left->u.object, *add); pop_value(inter); result.type = SIMCAR_NULL_VALUE; } else if (!strcmp(expr->u.method_call_expression.identifier, "size")) { check_method_argument_count(expr->line_number, expr->u.method_call_expression .argument, 0); result.type = SIMCAR_INT_VALUE; result.u.int_value = left->u.object->u.array.size; } else if (!strcmp(expr->u.method_call_expression.identifier, "resize")) { SIMCAR_Value new_size; check_method_argument_count(expr->line_number, expr->u.method_call_expression .argument, 1); eval_expression(inter, env, expr->u.method_call_expression.argument ->expression); new_size = pop_value(inter); if (new_size.type != SIMCAR_INT_VALUE) { crb_runtime_error(expr->line_number, ARRAY_RESIZE_ARGUMENT_ERR, MESSAGE_ARGUMENT_END); } crb_array_resize(inter, left->u.object, new_size.u.int_value); result.type = SIMCAR_NULL_VALUE; } else { error_flag = SIMCAR_TRUE; } } else if (left->type == SIMCAR_STRING_VALUE) { if (!strcmp(expr->u.method_call_expression.identifier, "length")) { check_method_argument_count(expr->line_number, expr->u.method_call_expression .argument, 0); result.type = SIMCAR_INT_VALUE; result.u.int_value = strlen(left->u.object->u.string.string); } else { error_flag = SIMCAR_TRUE; } } else { error_flag = SIMCAR_TRUE; } if (error_flag) { crb_runtime_error(expr->line_number, NO_SUCH_METHOD_ERR, STRING_MESSAGE_ARGUMENT, "method_name", expr->u.method_call_expression.identifier, MESSAGE_ARGUMENT_END); } pop_value(inter); push_value(inter, &result); }
static void eval_binary_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, ExpressionType operato, Expression *left, Expression *right) { SIMCAR_Value *left_val; SIMCAR_Value *right_val; SIMCAR_Value result; eval_expression(inter, env, left); eval_expression(inter, env, right); left_val = peek_stack(inter, 1); right_val = peek_stack(inter, 0); if (left_val->type == SIMCAR_INT_VALUE && right_val->type == SIMCAR_INT_VALUE) { eval_binary_int(inter, operato, left_val->u.int_value, right_val->u.int_value, &result, left->line_number); } else if (left_val->type == SIMCAR_DOUBLE_VALUE && right_val->type == SIMCAR_DOUBLE_VALUE) { eval_binary_double(inter, operato, left_val->u.double_value, right_val->u.double_value, &result, left->line_number); } else if (left_val->type == SIMCAR_INT_VALUE && right_val->type == SIMCAR_DOUBLE_VALUE) { eval_binary_double(inter, operato, (double)left_val->u.int_value, right_val->u.double_value, &result, left->line_number); } else if (left_val->type == SIMCAR_DOUBLE_VALUE && right_val->type == SIMCAR_INT_VALUE) { eval_binary_double(inter, operato, left_val->u.double_value, (double)right_val->u.int_value, &result, left->line_number); } else if (left_val->type == SIMCAR_BOOLEAN_VALUE && right_val->type == SIMCAR_BOOLEAN_VALUE) { result.type = SIMCAR_BOOLEAN_VALUE; result.u.boolean_value = eval_binary_boolean(inter, operato, left_val->u.boolean_value, right_val->u.boolean_value, left->line_number); } else if (left_val->type == SIMCAR_STRING_VALUE && operato == ADD_EXPRESSION) { chain_string(inter, left_val, right_val, &result); } else if (left_val->type == SIMCAR_STRING_VALUE && right_val->type == SIMCAR_STRING_VALUE) { result.type = SIMCAR_BOOLEAN_VALUE; result.u.boolean_value = eval_compare_string(operato, left_val, right_val, left->line_number); } else if (left_val->type == SIMCAR_NULL_VALUE || right_val->type == SIMCAR_NULL_VALUE) { result.type = SIMCAR_BOOLEAN_VALUE; result.u.boolean_value = eval_binary_null(inter, operato, left_val, right_val, left->line_number); } else { char *op_str = crb_get_operator_string(operato); crb_runtime_error(left->line_number, BAD_OPERAND_TYPE_ERR, STRING_MESSAGE_ARGUMENT, "operator", op_str, MESSAGE_ARGUMENT_END); } pop_value(inter); pop_value(inter); push_value(inter, &result); }