Branch: Tag:

2001-07-11

2001-07-11 04:25:07 by Martin Stjernholm <mast@lysator.liu.se>

Some work on breaking the evaluation of frames.

Rev: server/etc/modules/RXML.pmod/module.pmod:1.195

2:   //   // Created 1999-07-30 by Martin Stjernholm.   // - // $Id: module.pmod,v 1.194 2001/07/11 03:10:34 mast Exp $ + // $Id: module.pmod,v 1.195 2001/07/11 04:25:07 mast Exp $      // Kludge: Must use "RXML.refs" somewhere for the whole module to be   // loaded correctly.
1589:    //! evaluation. evaluator is the object that catched the error.    {    error_count++; -  if (objectp (err) && err->is_RXML_Backtrace) { +  +  if (objectp (err)) { +  if (err->is_RXML_break_eval) { +  if (err->action == "continue") return; +  Context ctx = RXML_CONTEXT; +  if (ctx->frame) { +  if (stringp (err->target) ? err->target == ctx->frame->scope_name : +  err->target == ctx->frame) +  err->action = "continue"; +  } +  else +  if (err->target) { +  ctx->frame = err->cur_frame; +  err = catch (parse_error ("There is no surround frame %s.\n", +  stringp (err->target) ? +  sprintf ("with scope %O", err->target) : +  sprintf ("%O", err->target))); +  ctx->frame = 0; +  handle_exception (err, evaluator, compile_error); +  } +  throw (err); +  } +  +  else if (err->is_RXML_Backtrace) {    if (evaluator->report_error && evaluator->recover_errors &&    evaluator->type->free_text) {    string msg;
1614:    }    throw (err);    } -  else throw_fatal (err); +     }    -  +  throw_fatal (err); +  } +     final array(mixed|PCode) eval_and_compile (Type type, string to_parse)    //! Parses and evaluates @[to_parse] with @[type] in this context.    //! At the same time, p-code is collected to reevaluate it later. An
1822:    }   }    + static class BreakEval (Frame|string target) + // Used in frame break exceptions. + { +  constant is_RXML_BreakEval = 1; +  string action = "break"; +  Frame cur_frame = RXML_CONTEXT->frame; + } +    class Backtrace   //! The object used to throw RXML errors.   {
2254:    //! A p-code object to evaluate. It's not necessary that the    //! type it evaluates to is the same as @[result_type]; it will    //! be converted if it isn't. -  //! @item mapping(string:mixed) -  //! A response mapping which will be returned instead of the -  //! evaluated page. The evaluation is stopped immediately after -  //! this. FIXME: Not yet implemented. +     //! @item function(RequestID:mixed)    //! Run the function and add its return value to the result.    //! It's assumed to be a valid value of @[result_type].
2410:    if (flags & FLAG_DEBUG) report_debug (msg, @args);    }    -  void terminate() -  //! Makes the parser abort. The data parsed so far will be returned. -  //! Does not return; throws a special exception instead. +  void break_frame (void|Frame|string frame_or_scope) +  //! Makes the parser break the evaluation up to the specified frame, +  //! or to the top level if no frame is given. If @[frame_or_scope] +  //! is a frame object higher up in the stack then the evaluation up +  //! to and including that frame will be broken, and then continue. +  //! If @[frame_or_scope] is a string then the closest frame higher +  //! up in the stack with a scope of that name will be broken. It's +  //! an error if @[frame_or_scope] is nonzero and doesn't match a +  //! frame in the stack. Does not return; throws a special exception +  //! instead. +  //! +  //! @note +  //! It's not well defined how much of the earlier evaluated data +  //! will be in the final result. Since none of the broken tags are +  //! executed on the partial data after the break, it won't be +  //! returned. This means that typically none of the earlier data is +  //! returned. However if streaming is in use then data in earlier +  //! returned pieces is not affected, of course.    { -  fatal_error ("FIXME\n"); +  throw (BreakEval (frame_or_scope));    }       void suspend()
4291:    {    mixed res = read();    if (!eval_piece) -  while (context->incomplete_eval()) +  while (context->incomplete_eval()) { +  write_end();    res = add_to_value (type, res, read()); -  +  }    return res;    }