static int exec_minus(node_ctx* ctx, int argc, strm_value* args, strm_value* ret) { if (argc == 1) { if (strm_int_p(args[0])) { *ret = strm_int_value(-strm_value_int(args[0])); return 0; } if (strm_flt_p(args[0])) { *ret = strm_flt_value(-strm_value_flt(args[0])); return 0; } return 1; } assert(argc == 2); if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])-strm_value_int(args[1])); return 0; } else if (strm_num_p(args[0])) { *ret = strm_flt_value(strm_value_flt(args[0])-strm_value_flt(args[1])); return 0; } return 1; }
static int exec_minus(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { if (argc == 1) { if (strm_int_p(args[0])) { *ret = strm_int_value(-strm_value_int(args[0])); return STRM_OK; } if (strm_flt_p(args[0])) { *ret = strm_flt_value(-strm_value_flt(args[0])); return STRM_OK; } return STRM_NG; } assert(argc == 2); if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])-strm_value_int(args[1])); return STRM_OK; } if (strm_num_p(args[0])) { *ret = strm_flt_value(strm_value_flt(args[0])-strm_value_flt(args[1])); return STRM_OK; } return STRM_NG; }
static int exec_plus(strm_state* state, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); if (strm_str_p(*args)) { strm_string *str1 = strm_value_str(args[0]); strm_string *str2 = strm_value_str(args[1]); strm_string *str3 = strm_str_new(NULL, str1->len + str2->len); char *p; p = (char*)str3->ptr; memcpy(p, str1->ptr, str1->len); memcpy(p+str1->len, str2->ptr, str2->len); p[str3->len] = '\0'; *ret = strm_ptr_value(str3); return STRM_OK; } if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])+strm_value_int(args[1])); return STRM_OK; } if (strm_num_p(args[0])) { *ret = strm_flt_value(strm_value_flt(args[0])+strm_value_flt(args[1])); return STRM_OK; } return STRM_NG; }
static int ary_correl(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { strm_value* v; int i, len; double sx, sy, sxx, syy, sxy; strm_get_args(strm, argc, args, "a", &v, &len); sx = sy = sxx = syy = sxy = 0; for (i=0; i<len; i++) { strm_value data = v[i]; strm_value* dv; double dx, dy; if (!strm_array_p(data) || strm_ary_len(data) != 2) { /* skip invalid data */ continue; } dv = strm_ary_ptr(data); dx = strm_value_flt(dv[0]) - sx; sx += dx / (i+1); dy = strm_value_flt(dv[1]) - sy; sy += dy / (i+1); sxx += i * dx * dx / (i+1); syy += i * dy * dy / (i+1); sxy += i * dx * dy / (i+1); } sxx = sqrt(sxx / (len-1)); syy = sqrt(syy / (len-1)); sxy /= (len-1) * sxx * syy; *ret = strm_flt_value(sxy); return STRM_OK; }
static int exec_plus(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); if (strm_string_p(*args)) { strm_string str1 = strm_value_str(args[0]); strm_string str2 = strm_value_str(args[1]); strm_string str3 = strm_str_new(NULL, strm_str_len(str1) + strm_str_len(str2)); char *p; p = (char*)strm_str_ptr(str3); memcpy(p, strm_str_ptr(str1), strm_str_len(str1)); memcpy(p+strm_str_len(str1), strm_str_ptr(str2), strm_str_len(str2)); p[strm_str_len(str3)] = '\0'; *ret = strm_str_value(str3); return STRM_OK; } if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])+strm_value_int(args[1])); return STRM_OK; } if (strm_num_p(args[0])) { *ret = strm_flt_value(strm_value_flt(args[0])+strm_value_flt(args[1])); return STRM_OK; } return STRM_NG; }
static int exec_div(node_ctx* ctx, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); *ret = strm_flt_value(strm_value_flt(args[0])/strm_value_flt(args[1])); return 0; }
static int exec_div(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); *ret = strm_flt_value(strm_value_flt(args[0])/strm_value_flt(args[1])); return STRM_OK; }
static int avg_finish(strm_stream* strm, strm_value data) { struct sum_data* d = strm->data; strm_emit(strm, strm_flt_value(d->sum/d->num), NULL); return STRM_OK; }
static int var_finish(strm_stream* strm, strm_value data) { struct stdev_data* d = strm->data; double s = d->s2 / (d->num-1); strm_emit(strm, strm_flt_value(s), NULL); return STRM_OK; }
static strm_value csv_value(const char* p, strm_int len, enum csv_type ftype) { const char *s = p; const char *send = s+len; long i=0; double f, pow = 1; enum csv_type type = TYPE_STR; switch (ftype) { case TYPE_UNSPC: case TYPE_NUM: /* skip preceding white spaces */ while (isspace((int)*s)) s++; /* check if numbers */ while (s<send) { switch (*s) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (type == TYPE_STR) type = TYPE_INT; i = i*10 + (*s - '0'); pow *= 10; break; case '.': if (type == TYPE_FLT) { /* second dot */ type = TYPE_TIME; break; } type = TYPE_FLT; f = i; i = 0; pow = 1; break; default: type = TYPE_UNSPC; break; } s++; } default: break; } switch (type) { case TYPE_INT: return strm_int_value(i); case TYPE_FLT: f += i / pow; return strm_flt_value(f); default: return csv_string(p, len, ftype); } /* not reached */ }
static int correl_finish(strm_stream* strm, strm_value data) { struct correl_data* d = strm->data; d->n--; double sxx = sqrt(d->sxx / d->n); double syy = sqrt(d->syy / d->n); double sxy = d->sxy / (d->n * sxx * syy); strm_emit(strm, strm_flt_value(sxy), NULL); return STRM_OK; }
static int ary_sum_avg(strm_stream* strm, int argc, strm_value* args, strm_value* ret, int avg) { int i, len; strm_value* v; double sum = 0; double c = 0; strm_value func; strm_get_args(strm, argc, args, "a|v", &v, &len, &func); if (argc == 0) { for (i=0; i<len; i++) { double y = strm_value_flt(v[i]) - c; double t = sum + y; c = (t - sum) - y; sum = t; } } else { for (i=0; i<len; i++) { strm_value val; double f, y, t; val = convert_number(strm, v[i], func); f = strm_value_flt(val); y = f - c; t = sum + y; c = (t - sum) - y; sum = t; } } if (avg) { *ret = strm_flt_value(sum/len); } else { *ret = strm_flt_value(sum); } return STRM_OK; }
static int exec_mult(strm_state* state, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])*strm_value_int(args[1])); return STRM_OK; } if (strm_num_p(args[0])) { *ret = strm_flt_value(strm_value_flt(args[0])*strm_value_flt(args[1])); return STRM_OK; } return STRM_NG; }
static int exec_mod(strm_stream* strm, int argc, strm_value* args, strm_value* ret) { assert(argc == 2); if (strm_int_p(args[0]) && strm_int_p(args[1])) { *ret = strm_int_value(strm_value_int(args[0])%strm_value_int(args[1])); return STRM_OK; } if (strm_num_p(args[0])) { *ret = strm_flt_value((int)strm_value_flt(args[0])%(int)strm_value_flt(args[1])); return STRM_OK; } return STRM_NG; }
static strm_value csv_value(const char* p, size_t len) { const char *s = p; const char *send = s+len; long i=0; double f, pow = 1; int type = 0; /* 0: string, 1: int, 2: float */ /* skip preceding white spaces */ while (isspace((int)*s)) s++; /* check if numbers */ while (s<send) { switch (*s) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (type == STRING_TYPE) type = 1; i = i*10 + (*s - '0'); pow *= 10; break; case '.': type = 2; f = i; i = 0; pow = 1; break; default: return strm_str_value(p, len); } s++; } switch (type) { case 1: /* int */ return strm_int_value(i); case 2: /* float */ f += i / pow; return strm_flt_value(f); default: return strm_str_value(p, len); } /* not reached */ }
static int ary_var_stdev(strm_stream* strm, int argc, strm_value* args, strm_value* ret, int stdev) { strm_value func; strm_value* v; int i, len; double s1, s2; strm_get_args(strm, argc, args, "a|v", &v, &len, &func); s1 = s2 = 0.0; if (argc == 0) { for (i=0; i<len; i++) { double x = strm_value_flt(v[i]); x -= s1; s1 += x/(i+1); s2 += i * x * x / (i+1); } } else { for (i=0; i<len; i++) { strm_value val; double x; val = convert_number(strm, v[i], func); x = strm_value_flt(val); x -= s1; s1 += x/(i+1); s2 += i * x * x / (i+1); } } s2 = s2 / (i-1); if (stdev) { s2 = sqrt(s2); } *ret = strm_flt_value(s2); return STRM_OK; }
static int exec_expr(node_ctx* ctx, node* np, strm_value* val) { int n; if (np == NULL) { return 1; } switch (np->type) { /* case NODE_ARGS: break; case NODE_EMIT: break; */ case NODE_IDENT: *val = strm_var_get(np->value.v.s); return 0; case NODE_IF: { strm_value v; node_if* nif = (node_if*)np; n = exec_expr(ctx, nif->cond, &v); if (n) return n; if (strm_value_bool(v)) { return exec_expr(ctx, nif->then, val); } else if (nif->opt_else != NULL) { return exec_expr(ctx, nif->opt_else, val); } else { *val = strm_nil_value(); return 0; } } break; case NODE_OP: { node_op* nop = (node_op*)np; strm_value args[2]; int i=0; if (nop->lhs) { n = exec_expr(ctx, nop->lhs, &args[i++]); if (n) return n; } if (nop->rhs) { n = exec_expr(ctx, nop->rhs, &args[i++]); if (n) return n; } return exec_call(ctx, nop->op, i, args, val); } break; case NODE_CALL: { /* TODO: wip code of ident */ node_call* ncall = (node_call*)np; if (ncall->ident != NULL) { int i; node_values* v0 = (node_values*)ncall->args; strm_value *args = malloc(sizeof(strm_value)*v0->len); for (i = 0; i < v0->len; i++) { n = exec_expr(ctx, v0->data[i], &args[i]); if (n) return n; } return exec_call(ctx, ncall->ident->value.v.s, i, args, val); } else { node_block* nblk = (node_block*)ncall; strm_value v; int n; n = exec_expr(ctx, nblk->compstmt, &v); if (n && ctx->exc->type == NODE_ERROR_RETURN) { *val = ctx->exc->arg; free(ctx->exc); return 0; } } } break; case NODE_RETURN: { node_return* nreturn = (node_return*)np; ctx->exc = malloc(sizeof(node_error)); ctx->exc->type = NODE_ERROR_RETURN; n = exec_expr(ctx, nreturn->rv, &ctx->exc->arg); return n; } break; case NODE_STMTS: { int i, n; node_values* v = (node_values*)np; for (i = 0; i < v->len; i++) { n = exec_expr(ctx, v->data[i], val); if (n) return n; } return 0; } break; case NODE_VALUE: switch (np->value.t) { case NODE_VALUE_BOOL: *val = strm_bool_value(np->value.v.b); return 0; case NODE_VALUE_NIL: *val = strm_nil_value(); return 0; case NODE_VALUE_STRING: case NODE_VALUE_IDENT: *val = strm_ptr_value(np->value.v.s); return 0; case NODE_VALUE_DOUBLE: *val = strm_flt_value(np->value.v.d); return 0; case NODE_VALUE_INT: *val = strm_int_value(np->value.v.i); return 0; /* following type should not be evaluated */ case NODE_VALUE_ERROR: case NODE_VALUE_USER: default: return 1; } default: break; } return 1; }
static int exec_expr(strm_state* state, node* np, strm_value* val) { int n; if (np == NULL) { return STRM_NG; } switch (np->type) { /* case NODE_ARGS: break; */ case NODE_SKIP: { state->exc = malloc(sizeof(node_error)); state->exc->type = NODE_ERROR_SKIP; state->exc->arg = strm_nil_value(); return STRM_OK; } case NODE_EMIT: { int i, n; node_values* v0; if (!state->task) { node_raise(state, "failed to emit"); } v0 = (node_values*)np->value.v.p; for (i = 0; i < v0->len; i++) { n = exec_expr(state, v0->data[i], val); if (n) return n; strm_emit(state->task, *val, NULL); } return STRM_OK; } break; case NODE_LET: { node_let *nlet = (node_let*)np; n = exec_expr(state, nlet->rhs, val); if (n) { node_raise(state, "failed to assign"); return n; } return strm_var_set(state, nlet->lhs, *val); } case NODE_ARRAY: { node_values* v0 = (node_values*)np; strm_array *arr = strm_ary_new(NULL, v0->len); strm_value *ptr = (strm_value*)arr->ptr; int i=0; for (i = 0; i < v0->len; i++, ptr++) { n = exec_expr(state, v0->data[i], ptr); if (n) return n; } *val = strm_ptr_value(arr); return STRM_OK; } case NODE_MAP: { node_map* v0 = (node_map*)np; strm_value nmap; strm_array* ary; n = exec_expr(state, v0->values, &nmap); if (n) return n; ary = strm_value_ary(nmap); ary->headers = v0->headers; *val = nmap; return STRM_OK; } case NODE_IDENT: n = strm_var_get(state, np->value.v.s, val); if (n) { node_raise(state, "failed to reference variable"); } return n; case NODE_IF: { strm_value v; node_if* nif = (node_if*)np; n = exec_expr(state, nif->cond, &v); if (n) return n; if (strm_value_bool(v) && v.val.i) { return exec_expr(state, nif->then, val); } else if (nif->opt_else != NULL) { return exec_expr(state, nif->opt_else, val); } else { *val = strm_nil_value(); return STRM_OK; } } break; case NODE_OP: { node_op* nop = (node_op*)np; strm_value args[2]; int i=0; if (nop->lhs) { n = exec_expr(state, nop->lhs, &args[i++]); if (n) return n; } if (nop->rhs) { n = exec_expr(state, nop->rhs, &args[i++]); if (n) return n; } return exec_call(state, nop->op, i, args, val); } break; case NODE_LAMBDA: { struct strm_lambda* lambda = malloc(sizeof(strm_lambda)); if (!lambda) return STRM_NG; lambda->type = STRM_OBJ_LAMBDA; lambda->body = (node_lambda*)np; lambda->state = state; *val = strm_ptr_value(lambda); return STRM_OK; } break; case NODE_CALL: { /* TODO: wip code of ident */ node_call* ncall = (node_call*)np; int i; node_values* v0 = (node_values*)ncall->args; strm_value *args = malloc(sizeof(strm_value)*v0->len); for (i = 0; i < v0->len; i++) { n = exec_expr(state, v0->data[i], &args[i]); if (n) return n; } return exec_call(state, ncall->ident, i, args, val); } break; case NODE_RETURN: { node_return* nreturn = (node_return*)np; node_values* args = (node_values*)nreturn->rv; state->exc = malloc(sizeof(node_error)); state->exc->type = NODE_ERROR_RETURN; switch (args->len) { case 0: state->exc->arg = strm_nil_value(); break; case 1: n = exec_expr(state, args->data[0], &state->exc->arg); if (n) return n; break; default: { strm_array* ary = strm_ary_new(NULL, args->len); size_t i; for (i=0; i<args->len; i++) { n = exec_expr(state, args->data[i], (strm_value*)&ary->ptr[i]); if (n) return n; } } break; } return STRM_NG; } break; case NODE_STMTS: { int i; node_values* v = (node_values*)np; for (i = 0; i < v->len; i++) { n = exec_expr(state, v->data[i], val); if (state->exc != NULL) return STRM_NG; if (n) return n; } } return STRM_OK; case NODE_VALUE: switch (np->value.t) { case NODE_VALUE_BOOL: *val = strm_bool_value(np->value.v.b); return STRM_OK; case NODE_VALUE_NIL: *val = strm_nil_value(); return STRM_OK; case NODE_VALUE_STRING: case NODE_VALUE_IDENT: *val = strm_ptr_value(np->value.v.s); return STRM_OK; case NODE_VALUE_DOUBLE: *val = strm_flt_value(np->value.v.d); return STRM_OK; case NODE_VALUE_INT: *val = strm_int_value(np->value.v.i); return STRM_OK; /* following type should not be evaluated */ case NODE_VALUE_ERROR: case NODE_VALUE_USER: default: return STRM_NG; } default: break; } return STRM_NG; }