[njs] Math object.
Igor Sysoev
igor at sysoev.ru
Thu Mar 24 15:16:58 UTC 2016
details: http://hg.nginx.org/njs/rev/e3bc4f6f3480
branches:
changeset: 86:e3bc4f6f3480
user: Igor Sysoev <igor at sysoev.ru>
date: Wed Mar 23 15:27:14 2016 +0300
description:
Math object.
diffstat:
Makefile | 14 +
njs/njs_array.c | 1 +
njs/njs_builtin.c | 22 +-
njs/njs_disassembler.c | 4 +-
njs/njs_function.c | 15 +-
njs/njs_generator.c | 42 +++-
njs/njs_lexer_keyword.c | 1 +
njs/njs_math.c | 554 +++++++++++++++++++++++++++++++++++++++++++++++
njs/njs_math.h | 17 +
njs/njs_object.c | 28 ++-
njs/njs_object.h | 2 +
njs/njs_parser.c | 37 +++-
njs/njs_parser.h | 4 +
njs/njs_regexp.c | 1 +
njs/njs_vm.c | 64 +++--
njs/njs_vm.h | 26 +-
njs/test/njs_unit_test.c | 62 +++++
17 files changed, 841 insertions(+), 53 deletions(-)
diffs (truncated from 1256 to 1000 lines):
diff -r 5995bd7637ff -r e3bc4f6f3480 Makefile
--- a/Makefile Wed Mar 23 15:27:10 2016 +0300
+++ b/Makefile Wed Mar 23 15:27:14 2016 +0300
@@ -18,6 +18,7 @@ NXT_BUILDDIR = build
$(NXT_BUILDDIR)/njs_array.o \
$(NXT_BUILDDIR)/njs_function.o \
$(NXT_BUILDDIR)/njs_regexp.o \
+ $(NXT_BUILDDIR)/njs_math.o \
$(NXT_BUILDDIR)/njs_extern.o \
$(NXT_BUILDDIR)/njs_variable.o \
$(NXT_BUILDDIR)/njs_builtin.o \
@@ -46,6 +47,7 @@ NXT_BUILDDIR = build
$(NXT_BUILDDIR)/njs_array.o \
$(NXT_BUILDDIR)/njs_function.o \
$(NXT_BUILDDIR)/njs_regexp.o \
+ $(NXT_BUILDDIR)/njs_math.o \
$(NXT_BUILDDIR)/njs_extern.o \
$(NXT_BUILDDIR)/njs_variable.o \
$(NXT_BUILDDIR)/njs_builtin.o \
@@ -220,6 +222,18 @@ tarball:
-I$(NXT_LIB) -Injs $(NXT_PCRE_CFLAGS) \
njs/njs_regexp.c
+$(NXT_BUILDDIR)/njs_math.o: \
+ $(NXT_BUILDDIR)/libnxt.a \
+ njs/njscript.h \
+ njs/njs_vm.h \
+ njs/njs_object.h \
+ njs/njs_math.h \
+ njs/njs_math.c \
+
+ $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_math.o $(NXT_CFLAGS) \
+ -I$(NXT_LIB) -Injs \
+ njs/njs_math.c
+
$(NXT_BUILDDIR)/njs_extern.o: \
$(NXT_BUILDDIR)/libnxt.a \
njs/njscript.h \
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_array.c
--- a/njs/njs_array.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_array.c Wed Mar 23 15:27:14 2016 +0300
@@ -129,6 +129,7 @@ njs_array_alloc(njs_vm_t *vm, uint32_t l
nxt_lvlhsh_init(&array->object.hash);
nxt_lvlhsh_init(&array->object.shared_hash);
array->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_ARRAY];
+ array->object.shared = 0;
array->size = size;
array->length = length;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_builtin.c
--- a/njs/njs_builtin.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_builtin.c Wed Mar 23 15:27:14 2016 +0300
@@ -19,6 +19,7 @@
#include <njs_array.h>
#include <njs_function.h>
#include <njs_regexp.h>
+#include <njs_math.h>
#include <string.h>
@@ -33,7 +34,7 @@ njs_builtin_objects_create(njs_vm_t *vm)
{
nxt_int_t ret;
nxt_uint_t i;
- njs_object_t *prototypes;
+ njs_object_t *objects, *prototypes;
njs_function_t *functions;
static const njs_object_init_t *prototype_init[] = {
@@ -71,6 +72,10 @@ njs_builtin_objects_create(njs_vm_t *vm)
{ njs_eval_function, { 0 } },
};
+ static const njs_object_init_t *objects_init[] = {
+ &njs_math_object_init,
+ };
+
static const njs_object_prop_t null_proto_property = {
.type = NJS_WHITEOUT,
.name = njs_string("__proto__"),
@@ -83,6 +88,19 @@ njs_builtin_objects_create(njs_vm_t *vm)
return NXT_ERROR;
}
+ objects = vm->shared->objects;
+
+ for (i = NJS_OBJECT_MATH; i < NJS_OBJECT_MAX; i++) {
+ ret = njs_object_hash_create(vm, &objects[i].shared_hash,
+ objects_init[i]->properties,
+ objects_init[i]->items);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+
+ objects[i].shared = 1;
+ }
+
prototypes = vm->shared->prototypes;
for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
@@ -99,9 +117,9 @@ njs_builtin_objects_create(njs_vm_t *vm)
functions = vm->shared->functions;
for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
+ functions[i].object.shared = 0;
functions[i].native = 1;
functions[i].args_offset = 1;
- functions[i].shared = 0;
functions[i].u.native = native_functions[i].native;
functions[i].args_types[0] = native_functions[i].args_types[0];
functions[i].args_types[1] = native_functions[i].args_types[1];
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_disassembler.c
--- a/njs/njs_disassembler.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_disassembler.c Wed Mar 23 15:27:14 2016 +0300
@@ -35,10 +35,10 @@ static njs_code_name_t code_names[] = {
nxt_string("OBJECT ") },
{ njs_vmcode_function, sizeof(njs_vmcode_function_t),
nxt_string("FUNCTION ") },
- { njs_vmcode_function_copy, sizeof(njs_vmcode_function_copy_t),
- nxt_string("FUNCTION COPY ") },
{ njs_vmcode_regexp, sizeof(njs_vmcode_regexp_t),
nxt_string("REGEXP ") },
+ { njs_vmcode_object_copy, sizeof(njs_vmcode_object_copy_t),
+ nxt_string("OBJECT COPY ") },
{ njs_vmcode_property_get, sizeof(njs_vmcode_prop_get_t),
nxt_string("PROPERTY GET ") },
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_function.c
--- a/njs/njs_function.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_function.c Wed Mar 23 15:27:14 2016 +0300
@@ -31,8 +31,15 @@ njs_function_alloc(njs_vm_t *vm)
function = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t));
if (nxt_fast_path(function != NULL)) {
+ /*
+ * nxt_mem_cache_zalloc() does also:
+ * nxt_lvlhsh_init(&function->object.hash);
+ * nxt_lvlhsh_init(&function->object.shared_hash);
+ * function->object.__proto__ = NULL;
+ */
+
+ function->object.shared = 1;
function->args_offset = 1;
- function->shared = 1;
function->u.lambda = nxt_mem_cache_zalloc(vm->mem_cache_pool,
sizeof(njs_function_lambda_t));
@@ -52,7 +59,7 @@ njs_function_value_copy(njs_vm_t *vm, nj
function = value->data.u.function;
- if (!function->shared) {
+ if (!function->object.shared) {
return function;
}
@@ -61,7 +68,7 @@ njs_function_value_copy(njs_vm_t *vm, nj
if (nxt_fast_path(function != NULL)) {
*function = *value->data.u.function;
function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
- function->shared = 0;
+ function->object.shared = 0;
value->data.u.function = function;
}
@@ -458,7 +465,7 @@ njs_function_prototype_bind(njs_vm_t *vm
*function = *args[0].data.u.function;
function->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
- function->shared = 0;
+ function->object.shared = 0;
if (nargs == 1) {
args = (njs_value_t *) &njs_value_void;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_generator.c
--- a/njs/njs_generator.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_generator.c Wed Mar 23 15:27:14 2016 +0300
@@ -25,6 +25,8 @@ static nxt_int_t njs_generator(njs_vm_t
njs_parser_node_t *node);
static nxt_int_t njs_generate_name(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *node);
+static nxt_int_t njs_generate_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node);
static nxt_int_t njs_generate_variable(njs_parser_t *parser,
njs_parser_node_t *node);
static nxt_int_t njs_generate_if_statement(njs_vm_t *vm, njs_parser_t *parser,
@@ -289,6 +291,9 @@ njs_generator(njs_vm_t *vm, njs_parser_t
case NJS_TOKEN_NAME:
return njs_generate_name(vm, parser, node);
+ case NJS_TOKEN_MATH:
+ return njs_generate_builtin_object(vm, parser, node);
+
case NJS_TOKEN_FUNCTION:
return njs_generate_function_declaration(vm, parser, node);
@@ -319,9 +324,9 @@ njs_generator(njs_vm_t *vm, njs_parser_t
static nxt_int_t
njs_generate_name(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
{
- njs_index_t index;
- njs_value_t *value;
- njs_vmcode_function_copy_t *copy;
+ njs_index_t index;
+ njs_value_t *value;
+ njs_vmcode_object_copy_t *copy;
index = node->u.variable->index;
value = njs_variable_value(parser, index);
@@ -333,12 +338,12 @@ njs_generate_name(njs_vm_t *vm, njs_pars
return node->index;
}
- njs_generate_code(parser, njs_vmcode_function_copy_t, copy);
- copy->code.operation = njs_vmcode_function_copy;
+ njs_generate_code(parser, njs_vmcode_object_copy_t, copy);
+ copy->code.operation = njs_vmcode_object_copy;
copy->code.operands = NJS_VMCODE_2OPERANDS;
copy->code.retval = NJS_VMCODE_RETVAL;
copy->retval = node->index;
- copy->function = index;
+ copy->object = index;
return NXT_OK;
}
@@ -348,6 +353,31 @@ njs_generate_name(njs_vm_t *vm, njs_pars
static nxt_int_t
+njs_generate_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node)
+{
+ njs_index_t index;
+ njs_vmcode_object_copy_t *copy;
+
+ index = node->index;
+
+ node->index = njs_generator_dest_index(vm, parser, node);
+ if (nxt_slow_path(node->index == NJS_INDEX_ERROR)) {
+ return node->index;
+ }
+
+ njs_generate_code(parser, njs_vmcode_object_copy_t, copy);
+ copy->code.operation = njs_vmcode_object_copy;
+ copy->code.operands = NJS_VMCODE_2OPERANDS;
+ copy->code.retval = NJS_VMCODE_RETVAL;
+ copy->retval = node->index;
+ copy->object = index;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
njs_generate_variable(njs_parser_t *parser, njs_parser_node_t *node)
{
njs_value_t *value;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_lexer_keyword.c Wed Mar 23 15:27:14 2016 +0300
@@ -73,6 +73,7 @@ static const njs_keyword_t njs_keywords
/* Builtin objects. */
{ nxt_string("this"), NJS_TOKEN_THIS, 0 },
+ { nxt_string("Math"), NJS_TOKEN_MATH, 0 },
/* Builtin functions. */
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_math.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/njs/njs_math.c Wed Mar 23 15:27:14 2016 +0300
@@ -0,0 +1,554 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_stub.h>
+#include <nxt_array.h>
+#include <nxt_lvlhsh.h>
+#include <nxt_mem_cache_pool.h>
+#include <njscript.h>
+#include <njs_vm.h>
+#include <njs_number.h>
+#include <njs_object.h>
+#include <njs_function.h>
+#include <math.h>
+
+
+static njs_ret_t
+njs_object_math_abs(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, fabs(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_acos(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, acos(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_asin(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, asin(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_atan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, atan(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_atan2(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double y, x;
+
+ y = NJS_NAN;
+ x = NJS_NAN;
+
+ if (nargs > 1) {
+ y = args[1].data.u.number;
+ }
+
+ if (nargs > 2) {
+ x = args[2].data.u.number;
+ }
+
+ njs_number_set(&vm->retval, atan2(y, x));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_ceil(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, ceil(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_cos(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, cos(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_exp(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, exp(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_floor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, floor(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_log(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, log(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_max(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+ nxt_uint_t i;
+
+ if (nargs > 1) {
+ for (i = 1; i < nargs; i++) {
+ if (!njs_is_numeric(&args[i])) {
+ vm->frame->trap_scratch.data.u.value = &args[i];
+ return NJS_TRAP_NUMBER_ARG;
+ }
+ }
+
+ num = args[1].data.u.number;
+
+ for (i = 2; i < nargs; i++) {
+ num = fmax(num, args[i].data.u.number);
+ }
+
+ } else {
+ num = -NJS_INFINITY;
+ }
+
+ njs_number_set(&vm->retval, num);
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_min(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+ nxt_uint_t i;
+
+ if (nargs > 1) {
+ for (i = 1; i < nargs; i++) {
+ if (!njs_is_numeric(&args[i])) {
+ vm->frame->trap_scratch.data.u.value = &args[i];
+ return NJS_TRAP_NUMBER_ARG;
+ }
+ }
+
+ num = args[1].data.u.number;
+
+ for (i = 2; i < nargs; i++) {
+ num = fmin(num, args[i].data.u.number);
+ }
+
+ } else {
+ num = NJS_INFINITY;
+ }
+
+ njs_number_set(&vm->retval, num);
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_pow(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double base, exponent;
+
+ base = NJS_NAN;
+ exponent = NJS_NAN;
+
+ if (nargs > 1) {
+ base = args[1].data.u.number;
+ }
+
+ if (nargs > 2) {
+ exponent = args[2].data.u.number;
+ }
+
+ njs_number_set(&vm->retval, pow(base, exponent));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_round(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, round(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_sin(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, sin(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_sqrt(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, sqrt(num));
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_object_math_tan(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ if (nargs > 1) {
+ num = args[1].data.u.number;
+
+ } else {
+ num = NJS_NAN;
+ }
+
+ njs_number_set(&vm->retval, tan(num));
+
+ return NXT_OK;
+}
+
+
+static const njs_object_prop_t njs_math_object_properties[] =
+{
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("E"),
+ .value = njs_value(NJS_NUMBER, 1, 2.718281828459045),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LN10"),
+ .value = njs_value(NJS_NUMBER, 1, 2.302585092994046),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LN2"),
+ .value = njs_value(NJS_NUMBER, 1, 0.6931471805599453),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LOG10E"),
+ .value = njs_value(NJS_NUMBER, 1, 0.4342944819032518),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("LOG2E"),
+ .value = njs_value(NJS_NUMBER, 1, 1.4426950408889634),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("PI"),
+ .value = njs_value(NJS_NUMBER, 1, 3.141592653589793),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("SQRT1_2"),
+ .value = njs_value(NJS_NUMBER, 1, 0.7071067811865476),
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("SQRT2"),
+ .value = njs_value(NJS_NUMBER, 1, 1.4142135623730951),
+ },
+
+ {
+ .type = NJS_NATIVE_GETTER,
+ .name = njs_string("__proto__"),
+ .value = njs_native_getter(njs_object_prototype_get_proto),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("abs"),
+ .value = njs_native_function(njs_object_math_abs, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("acos"),
+ .value = njs_native_function(njs_object_math_acos, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("asin"),
+ .value = njs_native_function(njs_object_math_asin, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("atan"),
+ .value = njs_native_function(njs_object_math_atan, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("atan2"),
+ .value = njs_native_function(njs_object_math_atan2, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("ceil"),
+ .value = njs_native_function(njs_object_math_ceil, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("cos"),
+ .value = njs_native_function(njs_object_math_cos, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("exp"),
+ .value = njs_native_function(njs_object_math_exp, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("floor"),
+ .value = njs_native_function(njs_object_math_floor, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("log"),
+ .value = njs_native_function(njs_object_math_log, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("max"),
+ .value = njs_native_function(njs_object_math_max, 0, 0),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("min"),
+ .value = njs_native_function(njs_object_math_min, 0, 0),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("pow"),
+ .value = njs_native_function(njs_object_math_pow, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("round"),
+ .value = njs_native_function(njs_object_math_round, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("sin"),
+ .value = njs_native_function(njs_object_math_sin, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("sqrt"),
+ .value = njs_native_function(njs_object_math_sqrt, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+
+ {
+ .type = NJS_METHOD,
+ .name = njs_string("tan"),
+ .value = njs_native_function(njs_object_math_tan, 0,
+ NJS_SKIP_ARG, NJS_NUMBER_ARG),
+ },
+};
+
+
+const njs_object_init_t njs_math_object_init = {
+ njs_math_object_properties,
+ nxt_nitems(njs_math_object_properties),
+};
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_math.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/njs/njs_math.h Wed Mar 23 15:27:14 2016 +0300
@@ -0,0 +1,17 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NJS_MATH_H_INCLUDED_
+#define _NJS_MATH_H_INCLUDED_
+
+
+#include <math.h>
+
+
+extern const njs_object_init_t njs_math_object_init;
+
+
+#endif /* _NJS_MATH_H_INCLUDED_ */
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_object.c
--- a/njs/njs_object.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_object.c Wed Mar 23 15:27:14 2016 +0300
@@ -34,6 +34,31 @@ njs_object_alloc(njs_vm_t *vm)
nxt_lvlhsh_init(&object->hash);
nxt_lvlhsh_init(&object->shared_hash);
object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ object->shared = 0;
+ }
+
+ return object;
+}
+
+
+njs_object_t *
+njs_object_value_copy(njs_vm_t *vm, njs_value_t *value)
+{
+ njs_object_t *object;
+
+ object = value->data.u.object;
+
+ if (!object->shared) {
+ return object;
+ }
+
+ object = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_t));
+
+ if (nxt_fast_path(object != NULL)) {
+ *object = *value->data.u.object;
+ object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ object->shared = 0;
+ value->data.u.object = object;
}
return object;
@@ -51,6 +76,7 @@ njs_object_value_alloc(njs_vm_t *vm, con
if (nxt_fast_path(ov != NULL)) {
nxt_lvlhsh_init(&ov->object.hash);
nxt_lvlhsh_init(&ov->object.shared_hash);
+ ov->object.shared = 0;
index = njs_primitive_prototype_index(type);
ov->object.__proto__ = &vm->prototypes[index];
@@ -413,7 +439,7 @@ const njs_object_init_t njs_object_cons
};
-static njs_ret_t
+njs_ret_t
njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
{
njs_object_t *proto;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_object.h
--- a/njs/njs_object.h Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_object.h Wed Mar 23 15:27:14 2016 +0300
@@ -44,6 +44,7 @@ struct njs_object_init_s {
njs_object_t *njs_object_alloc(njs_vm_t *vm);
+njs_object_t *njs_object_value_copy(njs_vm_t *vm, njs_value_t *value);
njs_object_t *njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value,
nxt_uint_t type);
njs_object_prop_t *njs_object_property(njs_vm_t *vm, njs_object_t *obj,
@@ -55,6 +56,7 @@ njs_ret_t njs_object_constructor(njs_vm_
njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name);
njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value);
+njs_ret_t njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_parser.c
--- a/njs/njs_parser.c Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_parser.c Wed Mar 23 15:27:14 2016 +0300
@@ -68,6 +68,8 @@ static njs_token_t njs_parser_throw_stat
njs_parser_t *parser);
static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm,
njs_parser_t *parser);
+static njs_token_t njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node);
static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *obj);
static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser,
@@ -1470,7 +1472,7 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
break;
}
- parser->code_size += sizeof(njs_vmcode_function_copy_t);
+ parser->code_size += sizeof(njs_vmcode_object_copy_t);
node->lvalue = NJS_LVALUE_ENABLED;
node->u.variable = var;
break;
@@ -1588,6 +1590,9 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
node->index = NJS_INDEX_THIS;
break;
+ case NJS_TOKEN_MATH:
+ return njs_parser_builtin_object(vm, parser, node);
+
case NJS_TOKEN_OBJECT_CONSTRUCTOR:
node->index = NJS_INDEX_OBJECT;
break;
@@ -1632,6 +1637,36 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
static njs_token_t
+njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node)
+{
+ nxt_uint_t index, level;
+ njs_value_t *value;
+ njs_variable_t *var;
+
+ var = njs_parser_variable(vm, parser, &level);
+ if (nxt_slow_path(var == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ var->state = NJS_VARIABLE_DECLARED;
+ node->index = var->index;
+
+ value = njs_variable_value(parser, node->index);
+
+ index = node->token - NJS_TOKEN_FIRST_OBJECT;
+ value->data.u.object = &vm->shared->objects[index];
+ value->type = NJS_OBJECT;
+ value->data.truth = 1;
+
+ parser->node = node;
+ parser->code_size += sizeof(njs_vmcode_object_copy_t);
+
+ return njs_lexer_token(parser->lexer);
+}
+
+
+static njs_token_t
njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj)
{
njs_token_t token;
diff -r 5995bd7637ff -r e3bc4f6f3480 njs/njs_parser.h
--- a/njs/njs_parser.h Wed Mar 23 15:27:10 2016 +0300
+++ b/njs/njs_parser.h Wed Mar 23 15:27:14 2016 +0300
@@ -159,6 +159,10 @@ typedef enum {
NJS_TOKEN_THIS,
+#define NJS_TOKEN_FIRST_OBJECT NJS_TOKEN_MATH
+
+ NJS_TOKEN_MATH,
+
NJS_TOKEN_OBJECT_CONSTRUCTOR,
NJS_TOKEN_ARRAY_CONSTRUCTOR,
NJS_TOKEN_FUNCTION_CONSTRUCTOR,
More information about the nginx-devel
mailing list