*/ static REBVAL *Do_Parse_Path(REBVAL *item, REBPARSE *parse, REBCNT *index) /* ** Handle a PATH, including get and set, that's found in a rule. ** ***********************************************************************/ { REBVAL *path = item; REBVAL tmp; if (IS_PATH(item)) { if (Do_Path(&path, 0)) return item; // found a function item = DS_TOP; } else if (IS_SET_PATH(item)) { Set_Series(parse->type, &tmp, parse->series); VAL_INDEX(&tmp) = *index; if (Do_Path(&path, &tmp)) return item; // found a function return 0; } else if (IS_GET_PATH(item)) { if (Do_Path(&path, 0)) return item; // found a function item = DS_TOP; // CureCode #1263 change // if (parse->type != VAL_TYPE(item) || VAL_SERIES(item) != parse->series) if (!ANY_SERIES(item)) Trap1(RE_PARSE_SERIES, path); *index = Set_Parse_Series(parse, item); return 0; } return item; }
// // Get_Simple_Value_Into: C // // Does easy lookup, else just returns the value as is. // void Get_Simple_Value_Into(REBVAL *out, const REBVAL *val) { if (IS_WORD(val) || IS_GET_WORD(val)) { *out = *GET_OPT_VAR_MAY_FAIL(val); } else if (IS_PATH(val) || IS_GET_PATH(val)) { if (Do_Path_Throws(out, NULL, val, NULL)) fail (Error_No_Catch_For_Throw(out)); } else { *out = *val; } }
// // Get_Simple_Value_Into: C // // Does easy lookup, else just returns the value as is. // void Get_Simple_Value_Into(REBVAL *out, const RELVAL *val, REBCTX *specifier) { if (IS_WORD(val) || IS_GET_WORD(val)) { *out = *GET_OPT_VAR_MAY_FAIL(val, specifier); } else if (IS_PATH(val) || IS_GET_PATH(val)) { if (Do_Path_Throws_Core(out, NULL, val, specifier, NULL)) fail (Error_No_Catch_For_Throw(out)); } else { COPY_VALUE(out, val, specifier); } }
*/ static REBCNT Do_Eval_Rule(REBPARSE *parse, REBCNT index, REBVAL **rule) /* ** Evaluate the input as a code block. Advance input if ** rule succeeds. Return new index or failure. ** ** Examples: ** do skip ** do end ** do "abc" ** do 'abc ** do [...] ** do variable ** do datatype! ** do quote 123 ** do into [...] ** ** Problem: cannot write: set var do datatype! ** ***********************************************************************/ { REBVAL value; REBVAL *item = *rule; REBCNT n; REBPARSE newparse; // First, check for end of input: if (index >= parse->series->tail) { if (IS_WORD(item) && VAL_CMD(item) == SYM_END) return index; else return NOT_FOUND; } // Evaluate next N input values: index = Do_Next(parse->series, index, FALSE); // Value is on top of stack (volatile!): value = *DS_POP; if (THROWN(&value)) Throw_Break(&value); // Get variable or command: if (IS_WORD(item)) { n = VAL_CMD(item); if (n == SYM_SKIP) return (IS_SET(&value)) ? index : NOT_FOUND; if (n == SYM_QUOTE) { item = item + 1; (*rule)++; if (IS_END(item)) Trap1(RE_PARSE_END, item-2); if (IS_PAREN(item)) { item = Do_Block_Value_Throw(item); // might GC } } else if (n == SYM_INTO) { item = item + 1; (*rule)++; if (IS_END(item)) Trap1(RE_PARSE_END, item-2); item = Get_Parse_Value(item); // sub-rules if (!IS_BLOCK(item)) Trap1(RE_PARSE_RULE, item-2); if (!ANY_BINSTR(&value) && !ANY_BLOCK(&value)) return NOT_FOUND; return (Parse_Series(&value, VAL_BLK_DATA(item), parse->flags, 0) == VAL_TAIL(&value)) ? index : NOT_FOUND; } else if (n > 0) Trap1(RE_PARSE_RULE, item); else item = Get_Parse_Value(item); // variable } else if (IS_PATH(item)) { item = Get_Parse_Value(item); // variable } else if (IS_SET_WORD(item) || IS_GET_WORD(item) || IS_SET_PATH(item) || IS_GET_PATH(item)) Trap1(RE_PARSE_RULE, item); if (IS_NONE(item)) { return (VAL_TYPE(&value) > REB_NONE) ? NOT_FOUND : index; } // Copy the value into its own block: newparse.series = Make_Block(1); SAVE_SERIES(newparse.series); Append_Val(newparse.series, &value); newparse.type = REB_BLOCK; newparse.flags = parse->flags; newparse.result = 0; n = (Parse_Next_Block(&newparse, 0, item, 0) != NOT_FOUND) ? index : NOT_FOUND; UNSAVE_SERIES(newparse.series); return n; }