strm_state* strm_value_ns(strm_value val) { if (strm_array_p(val)) return strm_ary_ns(val); if (strm_value_tag(val) == STRM_TAG_PTR) { struct strm_misc* p = strm_ptr(val); if (strm_ptr_type(p) == STRM_PTR_MISC) { return p->ns; } } return NULL; }
strm_state* strm_value_ns(strm_value val) { if (strm_array_p(val)) { strm_state* ns = strm_ary_ns(val); if (ns) return ns; return strm_ns_array; } if (strm_string_p(val)) { return strm_ns_string; } if (strm_number_p(val)) { return strm_ns_number; } if (strm_value_tag(val) == STRM_TAG_PTR) { struct strm_misc* p = strm_ptr(val); if (!p) return NULL; if (strm_ptr_type(p) == STRM_PTR_AUX) { return p->ns; } } return NULL; }
static int exec_expr(strm_stream* strm, 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_NS: { node_ns* ns = (node_ns*)np; strm_state* s = strm_ns_find(state, node_to_sym(ns->name)); if (!s) { strm_raise(strm, "failed to create namespace"); return STRM_NG; } return exec_expr(strm, s, ns->body, val); } case NODE_IMPORT: { node_import *ns = (node_import*)np; strm_state* s = strm_ns_get(node_to_sym(ns->name)); if (!s) { strm_raise(strm, "no such namespace"); return STRM_NG; } n = strm_env_copy(state, s); if (n) { strm_raise(strm, "failed to import"); return n; } return STRM_OK; } break; case NODE_SKIP: strm_set_exc(strm, NODE_ERROR_SKIP, strm_nil_value()); return STRM_OK; case NODE_EMIT: { int i, n; node_array* v0; v0 = (node_array*)((node_emit*)np)->emit; if (!v0) { strm_emit(strm, strm_nil_value(), NULL); } else { for (i = 0; i < v0->len; i++) { n = exec_expr(strm, state, v0->data[i], val); if (n) return n; strm_emit(strm, *val, NULL); } } return STRM_OK; } break; case NODE_LET: { node_let *nlet = (node_let*)np; n = exec_expr(strm, state, nlet->rhs, val); if (n) { strm_raise(strm, "failed to assign"); return n; } return strm_var_set(state, node_to_sym(nlet->lhs), *val); } case NODE_ARRAY: { node_array* v0 = (node_array*)np; strm_array arr = strm_ary_new(NULL, v0->len); strm_value *ptr = (strm_value*)strm_ary_ptr(arr); int i=0; for (i = 0; i < v0->len; i++, ptr++) { n = exec_expr(strm, state, v0->data[i], ptr); if (n) return n; } if (v0->headers) { strm_ary_headers(arr) = ary_headers(v0->headers, v0->len); } if (v0->ns) { strm_ary_ns(arr) = strm_ns_get(node_to_sym(v0->ns)); } else { strm_ary_ns(arr) = strm_str_null; } *val = strm_ary_value(arr); return STRM_OK; } case NODE_IDENT: { node_ident* ni = (node_ident*)np; n = strm_var_get(state, node_to_sym(ni->name), val); if (n) { strm_raise(strm, "failed to reference variable"); } return n; } case NODE_IF: { strm_value v; node_if* nif = (node_if*)np; n = exec_expr(strm, state, nif->cond, &v); if (n) return n; if (strm_bool_p(v) && strm_value_bool(v)) { return exec_expr(strm, state, nif->then, val); } else if (nif->opt_else != NULL) { return exec_expr(strm, 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(strm, state, nop->lhs, &args[i++]); if (n) return n; } if (nop->rhs) { n = exec_expr(strm, state, nop->rhs, &args[i++]); if (n) return n; } return exec_call(strm, state, node_to_sym(nop->op), i, args, val); } break; case NODE_LAMBDA: { strm_lambda lambda = malloc(sizeof(struct strm_lambda)); if (!lambda) return STRM_NG; lambda->type = STRM_PTR_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_nodes* v0 = (node_nodes*)ncall->args; strm_value *args = malloc(sizeof(strm_value)*v0->len); for (i = 0; i < v0->len; i++) { n = exec_expr(strm, state, v0->data[i], &args[i]); if (n) return n; } return exec_call(strm, state, node_to_sym(ncall->ident), i, args, val); } break; case NODE_RETURN: { node_return* nreturn = (node_return*)np; node_nodes* args = (node_nodes*)nreturn->rv; strm_value arg; if (!args) { arg = strm_nil_value(); } else { switch (args->len) { case 0: arg = strm_nil_value(); break; case 1: n = exec_expr(strm, state, args->data[0], &arg); if (n) return n; break; default: { strm_array ary = strm_ary_new(NULL, args->len); strm_int i; for (i=0; i<args->len; i++) { n = exec_expr(strm, state, args->data[i], (strm_value*)&strm_ary_ptr(ary)[i]); if (n) return n; } } break; } } strm_set_exc(strm, NODE_ERROR_RETURN, arg); return STRM_OK; } break; case NODE_NODES: { int i; node_nodes* v = (node_nodes*)np; for (i = 0; i < v->len; i++) { n = exec_expr(strm, state, v->data[i], val); if (n) { if (strm) { node_error* exc = strm->exc; if (exc != NULL) { node* n = v->data[i]; exc->fname = n->fname; exc->lineno = n->lineno; } } return n; } } } return STRM_OK; case NODE_INT: *val = strm_int_value(((node_int*)np)->value); return STRM_OK; case NODE_FLOAT: *val = strm_int_value(((node_float*)np)->value); return STRM_OK; case NODE_BOOL: *val = strm_bool_value(((node_bool*)np)->value); return STRM_OK; case NODE_NIL: *val = strm_nil_value(); return STRM_OK; case NODE_STR: *val = strm_str_value(node_to_str(((node_str*)np)->value)); return STRM_OK; default: break; } return STRM_NG; }