static Value _evalTo (Procedure self, ExpType type, Exp a, Exp b, Exp c) { Value va = _EVAL(a), vb = _EVAL(b), vc = _EVAL(c); if (!vc) { vc = Value_number(1); } if (!(Value_is(va, at_Number) && Value_is(vb, at_Number) && Value_is(vc, at_Number))) { yyerror("wrong to expression with NAN."); return NULL; } Value result = Value_new(at_Array, NULL); int endIndex = 0; real i = va->u.number; for (;i < vb->u.number || i == vb->u.number && type == TO_EXP; i += vc->u.number) { Value_set(result, Value_number(endIndex++), Value_number(i)); } Value_set(result, at_TV_endIndex, Value_number(endIndex)); return result; }
// ================================================================================================ // _evalTrue, _evalWhile, _evalForeach, _evalBreak, _evalSwitch // ================================================================================================ static Value _evalTrue (Procedure self, Exp exp) { Value result = NULL, key = NULL, value = NULL; Exp iColon = NULL; real endIndex = 0; result = Value_new(at_True, NULL); while (exp) { TRAVERSEL_COMMA_EXP(exp, iColon); if (!iColon) continue; if (iColon->type == ASSIGN_EXP) { result->meta = at_Function; result->u.proc = Procedure_new(self, NULL, NULL, result, iColon->u.binary->b); } else { if (iColon->type != COLON_EXP && iColon->type != ACCESSOR_EXP) { key = Value_number(endIndex++); value = _EVAL(iColon); } else { key = _EVAL(iColon->u.binary->a); value = (iColon->type == ACCESSOR_EXP ? Value_functionAccessor(self, iColon->u.binary->b) : _EVAL(iColon->u.binary->b) ); if (Value_is(key, at_Number)) { endIndex = key->u.number + 1; } } Value_set(result, key, value); } } return result; }
int AST_walk_hash(tst_t *settings, Value *data, ast_hash_walk_cb cb) { struct ASTScanData scan = {.settings = settings, .cb = cb, .error = 0}; tst_traverse(data->as.hash, ast_hash_traverse_cb, &scan); return scan.error; } Value *AST_get(tst_t *settings, tst_t *fr, bstring name, ValueType type) { Pair *pair = tst_search(fr, bdata(name), blength(name)); check_debug(pair, "Couldn't find variable %s of type %s", bdata(name), Value_type_name(type)); Value *val = Pair_value(pair); if(Value_is(val, REF)) { val = Value_resolve(settings, val); check(val, "Couldn't find variable %s of type %s", bdata(name), Value_type_name(type)); } check(val->type == type, "Invalid type for %s, should be %s not %s", bdata(name), Value_type_name(type), Value_type_name(val->type)); return val; error: return NULL; }
static Value _evalRequire (Value name) { if (!(Value_is(name, at_String))) return NULL; Interpreter currentInterpreter = at_currentInterpreter; if (!LIB_getInitFunc(name->u.string)) { name = Interpreter_getFilePath(at_currentInterpreter, name); } Value result = Interpreter_eval(name); at_currentInterpreter = currentInterpreter; return result; }
Value Procedure_evalAccessor (Value at, Value me, Value arg) { if (!(me && Value_is(me, at_Accessor) && me->u.value)) { yyerror("wrong accessor call expression."); return NULL; } Value func = me->u.value; Exp tempExp = Exp_value(arg); Value result = Procedure_evalFunction(func->u.proc, at, func, tempExp); free(tempExp); return arg != func ? arg : result; }
Value *Value_resolve(tst_t *settings, Value *val) { if(Value_is(val, REF)) { Pair *pair = tst_search(settings, bdata(val->as.ref->data), blength(val->as.ref->data)); check(pair != NULL, "Couldn't find variable named: %s", bdata(val->as.ref->data)); return Pair_value(pair); } else { return val; } error: return NULL; }
static Value _evalMath (Procedure self, ExpType type, Exp a, Exp b) { Value va = NULL, vb = NULL; switch (type) { case AND_EXP:case OR_EXP: va = _EVAL(a); return (type == AND_EXP && va) || (type == OR_EXP && !va) ? _EVAL(b) : va; case EQ_EXP:case NE_EXP:case GT_EXP:case GE_EXP:case LT_EXP:case LE_EXP: va = _EVAL(a); if (type == NE_EXP) { vb = _EVAL(b); if (!va) return vb; if (!vb) return va; return va != vb ? vb : NULL; } else if (type == EQ_EXP) { vb = _EVAL(b); if (va == at_True) return vb; if (vb == at_True) return va; if (va == vb) return va ? vb : at_True; return NULL; } if (!va) return NULL; vb = _EVAL(b); if (!vb) return NULL; if (type == EQ_EXP) { return va == vb ? vb : NULL; } else if (Value_is(va, at_Number) && (Value_is(vb, at_Number) || Value_is(vb, at_String))) { vb = Value_toNumberValue(vb); return (type == GT_EXP && va->u.number > vb->u.number) || (type == GE_EXP && va->u.number >= vb->u.number) || (type == LT_EXP && va->u.number < vb->u.number) || (type == LE_EXP && va->u.number <- vb->u.number) ? vb : NULL; } else if (Value_is(va, at_String) && (Value_is(vb, at_Number) || Value_is(vb, at_String))) { vb = Value_toStringValue(vb); return (type == GT_EXP && strcmp(va->u.string, vb->u.string) > 0) || (type == GE_EXP && strcmp(va->u.string, vb->u.string) >= 0) || (type == LT_EXP && strcmp(va->u.string, vb->u.string) < 0) || (type == LE_EXP && strcmp(va->u.string, vb->u.string) <= 0) ? vb : NULL; } return NULL; case CAT_EXP: va = Value_toStringValue(_EVAL(a)); vb = Value_toStringValue(_EVAL(b)); if (!va) return vb; if (!vb) return va; return Value_string(String_cat(va->u.string, vb->u.string)); default: va = Value_toNumberValue(_EVAL(a)); vb = Value_toNumberValue(_EVAL(b)); if (!(va && vb)) return NULL; if (type == ADD_EXP) return Value_number(va->u.number + vb->u.number); if (type == SUB_EXP) return Value_number(va->u.number - vb->u.number); if (type == MUL_EXP) return Value_number(va->u.number * vb->u.number); if (type == DIV_EXP) return Value_number(va->u.number / vb->u.number); return NULL; } }
// ================================================================================================ // _evalAbs, _evalMath, _evalAssign, _evalTo, _evalComma // ================================================================================================ static Value _evalAbs (Procedure self, ExpType type, Exp exp) { Value value = _EVAL(exp); real number = 0; if (!(Value_is(value, at_Number))) { // 产生一个临时变量 value = Value_toNumberValue(value); if (!value) { yyerror("can't convert to number."); return NULL; } } number = value->u.number; return (type == ABS_EXP && number < 0) || (type == MINUS_EXP && number != 0) ? Value_number(-number) : value; }
// ================================================================================================ // _evalFunction, _evalAccessor, _evalMember, _evalCall // ================================================================================================ Value Procedure_evalFunction (Procedure self, Value at, Value me, Exp arg) { Value result = NULL; Procedure proc = NULL; Exp para = NULL, paraE = NULL, argE = NULL; if (!(Value_is(me, at_Function) && me->u.proc)) { yyerror("wrong call expression."); return NULL; } if (Value_is(me, at_Func)) { return me->u.func(self, at, arg); } proc = Procedure_new(me->u.proc, Assoc_new(), at, me, me->u.proc->exp); para = proc->exp->u.binary->a; while (para && arg) { TRAVERSEL_COMMA_EXP(para, paraE); TRAVERSEL_COMMA_EXP(arg, argE); _set(proc, paraE->u.value, _EVAL(argE)); } result = Procedure_eval(proc, proc->exp->u.binary->b); //Assoc_free(proc->assoc); //free(proc); return result; }
static Value _set (Procedure self, Value key, Value value) { if (!(self && key)) return NULL; Assoc assocNode = _has(self, key); Value me = NULL; if (assocNode && (me = assocNode->value) && Value_is(me, at_Accessor)) { Procedure_evalAccessor(NULL, me, value); } else { if (!self->assoc) { self->assoc = Assoc_new(); } Assoc_set(self->assoc, key, value); } return me; }
void ast_hash_traverse_cb(void *value, void *data) { // we want to *copy* this pair so that we can resolve it on the fly Pair pair = *((Pair *)value); struct ASTScanData *scan = data; // then we temporarily just swap it out for this callback if we resolve if(Value_is(pair.value, REF)) { pair.value = Value_resolve(scan->settings, pair.value); } int rc = scan->cb(scan->settings, &pair); scan->error = scan->error == 0 ? rc : scan->error; }
int Route_load(tst_t *settings, Pair *pair) { const char *name = bdata(Pair_key(pair)); char *sql = NULL; Value *val = Pair_value(pair); bstring type = NULL; int rc = 0; check(val, "Error loading route: %s", bdata(Pair_key(pair))); check(Value_is(val, CLASS), "Expected a Class but got a %s instead.", Value_type_name(val->type)); Class *cls = val->as.cls; type = bstrcpy(Class_ident(cls)); btolower(type); if(cls->id == -1) { if(biseqcstr(type, "dir")) { rc = Dir_load(settings, cls->params); } else if(biseqcstr(type, "proxy")) { rc = Proxy_load(settings, cls->params); } else if(biseqcstr(type, "handler")) { rc = Handler_load(settings, cls->params); } else { sentinel("Invalid type of route target: %s", bdata(Class_ident(cls))); } check(rc != -1, "Failed to create target for route %s", name); cls->id = rc; } sql = sqlite3_mprintf(bdata(&ROUTE_SQL), name, HOST_ID, cls->id, bdata(type)); rc = DB_exec(sql, NULL, NULL); check(rc == 0, "Failed to intialize route."); sqlite3_free(sql); bdestroy(type); return 0; error: if(sql) sqlite3_free(sql); bdestroy(type); return -1; }
static Value _get (Procedure self, Value key) { if (!(self && key)) return NULL; Assoc assocNode = _has(self, key); Value result = assocNode ? assocNode->value : NULL; return result && Value_is(result, at_Accessor) ? _evalAccessor(NULL, result, result->u.value) : result; }