Skip to content

Implemention of eval (by Andrey Shitov and Ruben Ayrapetyan) #174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 13, 2015
Merged
3 changes: 2 additions & 1 deletion jerry-core/ecma/base/ecma-gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */
case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */
case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */
case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */
case ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET: /* an integer */
case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
Expand Down
4 changes: 3 additions & 1 deletion jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,9 @@ typedef enum
ECMA_INTERNAL_PROPERTY_EXTENSIBLE, /**< [[Extensible]] */
ECMA_INTERNAL_PROPERTY_SCOPE, /**< [[Scope]] */
ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP, /**< [[ParametersMap]] */
ECMA_INTERNAL_PROPERTY_CODE, /**< [[Code]] */
ECMA_INTERNAL_PROPERTY_CODE_BYTECODE, /**< first part of [[Code]] - compressed pointer to bytecode array */
ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET, /**< second part of [[Code]] - offset in bytecode array and code flags
* (see also: ecma_pack_code_internal_property_value) */
ECMA_INTERNAL_PROPERTY_NATIVE_CODE, /**< native handler location descriptor */
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, /**< native handle associated with an object */
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, /**< object's native free callback */
Expand Down
3 changes: 2 additions & 1 deletion jerry-core/ecma/base/ecma-helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,8 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t */
case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t */
case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */
case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */
case ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET: /* an integer */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */
case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */
Expand Down
134 changes: 127 additions & 7 deletions jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,13 @@
*/

#include "ecma-alloc.h"
#include "ecma-builtins.h"
#include "ecma-conversion.h"
#include "ecma-exceptions.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-objects.h"
#include "ecma-function-object.h"
#include "ecma-lex-env.h"
#include "ecma-try-catch-macro.h"
#include "jrt.h"
#include "serializer.h"
#include "parser.h"

#define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h"
Expand Down Expand Up @@ -59,6 +56,9 @@ ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**<
/**
* Handle calling [[Construct]] of built-in Function object
*
* See also:
* ECMA-262 v5, 15.3.
*
* @return completion-value
*/
ecma_completion_value_t
Expand All @@ -67,7 +67,127 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
{
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);

ECMA_BUILTIN_CP_UNIMPLEMENTED (arguments_list_p, arguments_list_len);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

/* Last string, if any, is the function's body, and the rest, if any - are the function's parameter names */
MEM_DEFINE_LOCAL_ARRAY (string_params_p,
arguments_list_len == 0 ? 1 : arguments_list_len,
ecma_string_t*);
uint32_t params_count;

size_t zt_strings_buffer_size;

if (arguments_list_len == 0)
{
/* 3. */
string_params_p[0] = ecma_new_ecma_string_from_magic_string_id (ECMA_MAGIC_STRING__EMPTY);
zt_strings_buffer_size = sizeof (ecma_char_t);
params_count = 1;
}
else
{
/* 4., 5., 6. */
zt_strings_buffer_size = 0;

params_count = 0;
while (params_count < arguments_list_len
&& ecma_is_completion_value_empty (ret_value))
{
ECMA_TRY_CATCH (str_arg_value,
ecma_op_to_string (arguments_list_p[params_count]),
ret_value);

string_params_p[params_count] = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (str_arg_value));
zt_strings_buffer_size += ((size_t) ecma_string_get_length (string_params_p[params_count]) +
sizeof (ecma_char_t));
params_count++;

ECMA_FINALIZE (str_arg_value);
}
}

if (ecma_is_completion_value_empty (ret_value))
{
JERRY_ASSERT (params_count >= 1);

MEM_DEFINE_LOCAL_ARRAY (zt_string_params_p,
params_count,
ecma_char_t*);
MEM_DEFINE_LOCAL_ARRAY (zt_string_buffer_p,
zt_strings_buffer_size,
ecma_char_t);

ssize_t zt_string_buffer_pos = 0;
for (uint32_t i = 0; i < params_count; i++)
{
ssize_t sz = ecma_string_to_zt_string (string_params_p[i],
&zt_string_buffer_p[zt_string_buffer_pos],
(ssize_t) zt_strings_buffer_size - zt_string_buffer_pos);
JERRY_ASSERT (sz > 0);

zt_string_params_p[i] = zt_string_buffer_p + zt_string_buffer_pos;

zt_string_buffer_pos += sz;
}

parser_init ();

/*
* FIXME:
* Handle syntax errors
*/
parser_parse_new_function ((const char **) zt_string_params_p, params_count);
const opcode_t* opcodes_p = (const opcode_t*) serializer_get_bytecode ();
serializer_print_opcodes ();
parser_free ();

bool is_strict = false;
bool do_instantiate_arguments_object = true;

opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (opcodes_p,
0);

if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT)
{
is_strict = true;
}

if ((scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing empty line.

&& (scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER))
{
/* the code doesn't use 'arguments' identifier
* and doesn't perform direct call to eval,
* so Arguments object can't be referenced */
do_instantiate_arguments_object = false;
}

/* 11. */
ecma_object_t *glob_lex_env_p = ecma_get_global_environment ();

ecma_object_t *func_obj_p = ecma_op_create_function_object (params_count > 1u ? string_params_p : NULL,
(ecma_length_t) (params_count - 1u),
glob_lex_env_p,
is_strict,
do_instantiate_arguments_object,
opcodes_p,
1);

ecma_deref_object (glob_lex_env_p);

ret_value = ecma_make_normal_completion_value (ecma_make_object_value (func_obj_p));

MEM_FINALIZE_LOCAL_ARRAY (zt_string_buffer_p);
MEM_FINALIZE_LOCAL_ARRAY (zt_string_params_p);
}

for (uint32_t i = 0; i < params_count; i++)
{
ecma_deref_ecma_string (string_params_p[i]);
}

MEM_FINALIZE_LOCAL_ARRAY (string_params_p);

return ret_value;
} /* ecma_builtin_function_dispatch_construct */

/**
Expand Down
34 changes: 33 additions & 1 deletion jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
#include "ecma-alloc.h"
#include "ecma-builtins.h"
#include "ecma-conversion.h"
#include "ecma-eval.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-try-catch-macro.h"
#include "jrt.h"
#include "vm.h"

#define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h"
Expand Down Expand Up @@ -52,7 +54,37 @@ static ecma_completion_value_t
ecma_builtin_global_object_eval (ecma_value_t this_arg, /**< this argument */
ecma_value_t x) /**< routine's first argument */
{
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, x);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

bool is_direct_eval = vm_is_direct_eval_form_call ();
JERRY_ASSERT (!(is_direct_eval
&& !ecma_is_value_undefined (this_arg)));

/* See also: ECMA-262 v5, 10.1.1 */
bool is_called_from_strict_mode_code;
if (is_direct_eval)
{
is_called_from_strict_mode_code = vm_is_strict_mode ();
}
else
{
is_called_from_strict_mode_code = false;
}

if (!ecma_is_value_string (x))
{
/* step 1 */
ret_value = ecma_make_normal_completion_value (ecma_copy_value (x, true));
}
else
{
/* steps 2 to 8 */
ret_value = ecma_op_eval (ecma_get_string_from_value (x),
is_direct_eval,
is_called_from_strict_mode_code);
}

return ret_value;
} /* ecma_builtin_global_object_eval */

/**
Expand Down
76 changes: 57 additions & 19 deletions jerry-core/ecma/operations/ecma-eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-lex-env.h"
#include "parser.h"
#include "serializer.h"
#include "vm.h"

/** \addtogroup ecma ECMA
Expand All @@ -29,10 +31,11 @@
*/

/**
* eval
* Perform 'eval' with code stored in ecma-string
*
* See also:
* ECMA-262 v5, 15.1.2.1
* ecma_op_eval_chars_buffer
* ECMA-262 v5, 15.1.2.1 (steps 2 to 8)
*
* @return completion value
*/
Expand All @@ -41,7 +44,7 @@ ecma_op_eval (ecma_string_t *code_p, /**< code string */
bool is_direct, /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */
bool is_called_from_strict_mode_code) /**< is eval is called from strict mode code */
{
ecma_completion_value_t completion;
ecma_completion_value_t ret_value;

int32_t chars_num = ecma_string_get_length (code_p);
MEM_DEFINE_LOCAL_ARRAY (code_zt_buffer_p,
Expand All @@ -54,15 +57,51 @@ ecma_op_eval (ecma_string_t *code_p, /**< code string */
buf_size);
JERRY_ASSERT (buffer_size_req == buf_size);

// FIXME: Get parser feedback about syntax correctness
bool is_syntax_correct = true;
bool is_strict_prologue;
ret_value = ecma_op_eval_chars_buffer (code_zt_buffer_p,
(size_t) buf_size,
is_direct,
is_called_from_strict_mode_code);

MEM_FINALIZE_LOCAL_ARRAY (code_zt_buffer_p);

return ret_value;
} /* ecma_op_eval */

/**
* Perform 'eval' with code stored in continuous character buffer
*
* See also:
* ecma_op_eval
* ECMA-262 v5, 15.1.2.1 (steps 2 to 8)
*
* @return completion value
*/
ecma_completion_value_t
ecma_op_eval_chars_buffer (const ecma_char_t *code_p, /**< code characters buffer */
size_t code_buffer_size, /**< size of the buffer */
bool is_direct, /**< is eval called directly (ECMA-262 v5, 15.1.2.1.1) */
bool is_called_from_strict_mode_code) /**< is eval is called from strict mode code */
{
JERRY_ASSERT (code_p != NULL);

ecma_completion_value_t completion;

// FIXME: Call parser
JERRY_UNIMPLEMENTED ("eval operation is not implemented");
parser_init ();
bool is_syntax_correct = parser_parse_eval ((const char *) code_p, code_buffer_size);
const opcode_t* opcodes_p = (const opcode_t*) serializer_get_bytecode ();
serializer_print_opcodes ();
parser_free ();

opcode_counter_t first_opcode_index = 0u;
bool is_strict_prologue = false;
opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (opcodes_p,
first_opcode_index++);
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT)
{
is_strict_prologue = true;
}

// FIXME:
is_strict_prologue = false;
bool is_strict = (is_strict_prologue || (is_direct && is_called_from_strict_mode_code));

if (!is_syntax_correct)
{
Expand All @@ -85,18 +124,20 @@ ecma_op_eval (ecma_string_t *code_p, /**< code string */
lex_env_p = ecma_get_global_environment ();
}

if (is_strict_prologue
|| (is_direct && is_called_from_strict_mode_code))
if (is_strict)
{
ecma_object_t *strict_lex_env_p = ecma_create_decl_lex_env (lex_env_p);
ecma_deref_object (lex_env_p);

lex_env_p = strict_lex_env_p;
}

// FIXME: Call interpreter
completion = ecma_make_return_completion_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED));
JERRY_UNIMPLEMENTED ("eval operation is not implemented");
completion = vm_run_from_pos (opcodes_p,
first_opcode_index,
this_binding,
lex_env_p,
is_strict,
true);

if (ecma_is_completion_value_return (completion))
{
Expand All @@ -112,11 +153,8 @@ ecma_op_eval (ecma_string_t *code_p, /**< code string */
ecma_free_value (this_binding, true);
}


MEM_FINALIZE_LOCAL_ARRAY (code_zt_buffer_p);

return completion;
} /* ecma_op_eval */
} /* ecma_op_eval_chars_buffer */

/**
* @}
Expand Down
6 changes: 6 additions & 0 deletions jerry-core/ecma/operations/ecma-eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ ecma_op_eval (ecma_string_t *code_p,
bool is_direct,
bool is_called_from_strict_mode_code);

extern ecma_completion_value_t
ecma_op_eval_chars_buffer (const ecma_char_t *code_p,
size_t code_buffer_size,
bool is_direct,
bool is_called_from_strict_mode_code);

/**
* @}
* @}
Expand Down
Loading