static Value* parseToken(const char** expr, parser_cb* cb) { Value* ret; char* token = nextToken(expr); if(token == NULL) { return ValErr(badChar(**expr)); } trimSpaces(expr); if(**expr == '(') { (*expr)++; ArgList* arglist = ArgList_parse(expr, ',', ')', cb); if(arglist == NULL) { /* Parse error occurred and has already been raised */ free(token); return ValErr(ignoreError()); } ret = ValCall(FuncCall_create(token, arglist)); } else { ret = ValVar(token); } free(token); return ret; }
static Value* eval_map(Context* ctx, ArgList* arglist) { if(arglist->count != 2) { return ValErr(builtinArgs("map", 2, arglist->count)); } Value* func = Value_copy(arglist->args[0]); if(func->type != VAL_VAR) { Value* val = Value_eval(func, ctx); Value_free(func); if(val->type == VAL_ERR) return val; if(val->type != VAL_VAR) { Value_free(val); return ValErr(typeError("Builtin 'map' expects a callable as its first argument.")); } func = val; } Value* vec = Value_eval(arglist->args[1], ctx); if(vec->type == VAL_ERR) { Value_free(func); return vec; } if(func->type != VAL_VAR) { Value_free(func); Value_free(vec); return ValErr(typeError("Builtin 'map' expects a callable as its first argument.")); } if(vec->type != VAL_VEC) { Value_free(func); Value_free(vec); return ValErr(typeError("Builtin 'map' expects a vector as its second argument.")); } ArgList* mapping = ArgList_new(vec->vec->vals->count); /* Don't evaluate the call now. Let Builtin_eval do this for us */ unsigned i; for(i = 0; i < mapping->count; i++) { ArgList* arg = ArgList_create(1, Value_copy(vec->vec->vals->args[i])); Value* call = ValCall(FuncCall_new(func->name, arg)); mapping->args[i] = call; } Value_free(func); Value_free(vec); return ValVec(Vector_new(mapping)); }
Value* Value_copy(const Value* val) { Value* ret; switch(val->type) { case VAL_INT: ret = ValInt(val->ival); break; case VAL_REAL: ret = ValReal(val->rval); break; case VAL_FRAC: ret = ValFrac(Fraction_copy(val->frac)); break; case VAL_EXPR: ret = ValExpr(BinOp_copy(val->expr)); break; case VAL_CALL: ret = ValCall(FuncCall_copy(val->call)); break; case VAL_UNARY: ret = ValUnary(UnOp_copy(val->term)); break; case VAL_VAR: ret = ValVar(val->name); break; case VAL_VEC: ret = ValVec(Vector_copy(val->vec)); break; case VAL_NEG: /* Shouldn't be reached, but so easy to code */ ret = ValNeg(); break; case VAL_ERR: ret = ValErr(Error_copy(val->err)); break; default: typeError("Unknown value type: %d.", val->type); ret = NULL; break; } return ret; }
static Value* callFunc(Value* val, const char** expr, parser_cb* cb) { /* Ugly, but parses better. Only variables and the results of calls can be funcs */ if(val->type != VAL_VAR && val->type != VAL_CALL && val->type != VAL_PLACE) { return val; } /* Move past the opening parenthesis */ (*expr)++; ArgList* args = ArgList_parse(expr, ',', ')', cb); if(args == NULL) { Value_free(val); return ValErr(ignoreError()); } return ValCall(FuncCall_new(val, args)); }