STOID Mold_Object(REBVAL *value, REB_MOLD *mold) { REBSER *wser; REBVAL *words; REBVAL *vals; // first value is context REBCNT n; REBOOL indented = !GET_MOPT(mold, MOPT_INDENT); ASSERT(VAL_OBJ_FRAME(value), RP_NO_OBJECT_FRAME); wser = VAL_OBJ_WORDS(value); // if (wser < 1000) // Dump_Block_Raw(VAL_OBJ_FRAME(value), 0, 1); words = BLK_HEAD(wser); vals = VAL_OBJ_VALUES(value); // first value is context Pre_Mold(value, mold); Append_Byte(mold->series, '['); // Prevent infinite looping: if (Find_Same_Block(MOLD_LOOP, value) > 0) { Append_Bytes(mold->series, "...]"); return; } Append_Val(MOLD_LOOP, value); mold->indent++; for (n = 1; n < SERIES_TAIL(wser); n++) { if ( !VAL_GET_OPT(words+n, OPTS_HIDE) && ((VAL_TYPE(vals+n) > REB_NONE) || !GET_MOPT(mold, MOPT_NO_NONE)) ){ if(indented) New_Indented_Line(mold); else if (n > 1) Append_Byte(mold->series, ' '); Append_UTF8(mold->series, Get_Sym_Name(VAL_WORD_SYM(words+n)), -1); //Print("Slot: %s", Get_Sym_Name(VAL_WORD_SYM(words+n))); Append_Bytes(mold->series, ": "); if (IS_WORD(vals+n) && !GET_MOPT(mold, MOPT_MOLD_ALL)) Append_Byte(mold->series, '\''); Mold_Value(mold, vals+n, TRUE); } } mold->indent--; if (indented) New_Indented_Line(mold); Append_Byte(mold->series, ']'); End_Mold(mold); Remove_Last(MOLD_LOOP); }
STOID Form_Object(REBVAL *value, REB_MOLD *mold) { REBSER *wser = VAL_OBJ_WORDS(value); REBVAL *words = BLK_HEAD(wser); REBVAL *vals = VAL_OBJ_VALUES(value); // first value is context REBCNT n; // Prevent endless mold loop: if (Find_Same_Block(MOLD_LOOP, value) > 0) { Append_Bytes(mold->series, "...]"); return; } Append_Val(MOLD_LOOP, value); // Mold all words and their values: for (n = 1; n < SERIES_TAIL(wser); n++) { if (!VAL_GET_OPT(words+n, OPTS_HIDE)) Emit(mold, "N: V\n", VAL_WORD_SYM(words+n), vals+n); } Remove_Last(mold->series); Remove_Last(MOLD_LOOP); }
STOID Mold_Block_Series(REB_MOLD *mold, REBSER *series, REBCNT index, REBYTE *sep) { REBSER *out = mold->series; REBOOL line_flag = FALSE; // newline was part of block REBOOL had_lines = FALSE; REBVAL *value = BLK_SKIP(series, index); if (!sep) sep = "[]"; if (IS_END(value)) { Append_Bytes(out, sep); return; } // Recursion check: (variation of: Find_Same_Block(MOLD_LOOP, value)) for (value = BLK_HEAD(MOLD_LOOP); NOT_END(value); value++) { if (VAL_SERIES(value) == series) { Emit(mold, "C...C", sep[0], sep[1]); return; } } value = Append_Value(MOLD_LOOP); Set_Block(value, series); if (sep[1]) { Append_Byte(out, sep[0]); mold->indent++; } // else out->tail--; // why????? value = BLK_SKIP(series, index); while (NOT_END(value)) { if (VAL_GET_LINE(value)) { if (sep[1] || line_flag) New_Indented_Line(mold); had_lines = TRUE; } line_flag = TRUE; Mold_Value(mold, value, TRUE); value++; if (NOT_END(value)) Append_Byte(out, (sep[0] == '/') ? '/' : ' '); } if (sep[1]) { mold->indent--; if (VAL_GET_LINE(value) || had_lines) New_Indented_Line(mold); Append_Byte(out, sep[1]); } Remove_Last(MOLD_LOOP); }
STOID Mold_Map(REBVAL *value, REB_MOLD *mold, REBFLG molded) { REBSER *mapser = VAL_SERIES(value); REBVAL *val; // Prevent endless mold loop: if (Find_Same_Block(MOLD_LOOP, value) > 0) { Append_Bytes(mold->series, "...]"); return; } Append_Val(MOLD_LOOP, value); if (molded) { Pre_Mold(value, mold); Append_Byte(mold->series, '['); } // Mold all non-none entries mold->indent++; for (val = BLK_HEAD(mapser); NOT_END(val) && NOT_END(val+1); val += 2) { if (!IS_NONE(val+1)) { if (molded) New_Indented_Line(mold); Emit(mold, "V V", val, val+1); if (!molded) Append_Byte(mold->series, '\n'); } } mold->indent--; if (molded) { New_Indented_Line(mold); Append_Byte(mold->series, ']'); } End_Mold(mold); Remove_Last(MOLD_LOOP); }
*/ static REBINT Add_Arg(REBDIA *dia, REBVAL *value) /* ** Add an actual argument to the output block. ** ** Note that the argument may be out sequence with the formal ** arguments so we must scan for a slot that matches. ** ** Returns: ** 1: arg matches a formal arg and has been stored ** 0: no arg of that type was found ** -N: error (type block contains a bad value) ** ***********************************************************************/ { REBINT type = 0; REBINT accept = 0; REBVAL *fargs; REBINT fargi; REBVAL *outp; REBINT rept = 0; outp = BLK_SKIP(dia->out, dia->outi); // Scan all formal args, looking for one that matches given value: for (fargi = dia->fargi;; fargi++) { //Debug_Fmt("Add_Arg fargi: %d outi: %d", fargi, outi); if (IS_END(fargs = BLK_SKIP(dia->fargs, fargi))) return 0; again: // Formal arg can be a word (type or refinement), datatype, or * (repeater): if (IS_WORD(fargs)) { // If word is a datatype name: type = VAL_WORD_CANON(fargs); if (type < REB_MAX) { type--; // the type id } else if (type == SYM__P) { // repeat: * integer! rept = 1; fargs++; goto again; } else { // typeset or refinement REBVAL *temp; type = -1; // Is it a refinement word? if (IS_WORD(value) && VAL_WORD_CANON(fargs) == VAL_WORD_CANON(value)) { accept = 4; } // Is it a typeset? else if (NZ(temp = Get_Var_No_Trap(fargs)) && IS_TYPESET(temp)) { if (TYPE_CHECK(temp, VAL_TYPE(value))) accept = 1; } else if (!IS_WORD(value)) return 0; // do not search past a refinement //else return -REB_DIALECT_BAD_SPEC; } } // It's been reduced and is an actual datatype or typeset: else if (IS_DATATYPE(fargs)) { type = VAL_DATATYPE(fargs); } else if (IS_TYPESET(fargs)) { if (TYPE_CHECK(fargs, VAL_TYPE(value))) accept = 1; } else return -REB_DIALECT_BAD_SPEC; // Make room for it in the output block: if (IS_END(outp)) outp = Append_Value(dia->out); else if (!IS_NONE(outp)) { // There's already an arg in this slot, so skip it... if (dia->cmd > 1) outp++; if (!rept) continue; // see if there's another farg that will work for it // Look for first empty slot: while (NOT_END(outp) && !IS_NONE(outp)) outp++; if (IS_END(outp)) outp = Append_Value(dia->out); } // The datatype was correct from above! if (accept) break; //Debug_Fmt("want: %d got: %d rept: %d", type, VAL_TYPE(value), rept); // Direct match to datatype or to integer/decimal coersions: if (type == (REBINT)VAL_TYPE(value)) { accept = 1; break; } else if (type == REB_INTEGER && IS_DECIMAL(value)) { accept = 2; break; } else if (type == REB_DECIMAL && IS_INTEGER(value)) { accept = 3; break; } dia->missed++; // for debugging // Repeat did not match, so stop repeating and remove unused output slot: if (rept) { Remove_Last(dia->out); outp--; rept = 0; continue; } if (dia->cmd > 1) outp++; // skip output slot (for non-default values) } // Process the result: switch (accept) { case 1: *outp = *value; break; case 2: SET_INTEGER(outp, (REBI64)VAL_DECIMAL(value)); break; case 3: SET_DECIMAL(outp, (REBDEC)VAL_INT64(value)); break; case 4: // refinement: dia->fargi = fargs - BLK_HEAD(dia->fargs) + 1; dia->outi = outp - BLK_HEAD(dia->out) + 1; *outp = *value; return 1; case 0: return 0; } // Optimization: arg was in correct order: if (!rept && fargi == (signed)(dia->fargi)) { dia->fargi++; dia->outi++; } return 1; }