예제 #1
0
파일: t-pair.c 프로젝트: Oldes/r3
*/	REBINT PD_Pair(REBPVS *pvs)
/*
***********************************************************************/
{
	REBVAL *sel;
	REBVAL *val;
	REBINT n = 0;
	REBD32 dec;

	if (IS_WORD(sel = pvs->select)) {
		if (VAL_WORD_CANON(sel) == SYM_X) n = 1;
		else if (VAL_WORD_CANON(sel) == SYM_Y) n = 2;
		else return PE_BAD_SELECT;
	}
	else if (IS_INTEGER(sel)) {
		n = Int32(sel);
		if (n != 1 && n !=2) return PE_BAD_SELECT;
	}
	else
		return PE_BAD_SELECT;

	if (NZ(val = pvs->setval)) {
		if (IS_INTEGER(val)) dec = (REBD32)VAL_INT64(val);
		else if (IS_DECIMAL(val)) dec = (REBD32)VAL_DECIMAL(val);
		else return PE_BAD_SET;
		if (n == 1) VAL_PAIR_X(pvs->value) = dec;
		else VAL_PAIR_Y(pvs->value) = dec;
	} else {
		dec = (n == 1 ? VAL_PAIR_X(pvs->value) : VAL_PAIR_Y(pvs->value));
		SET_DECIMAL(pvs->store, dec);
		return PE_USE;
	}

	return PE_OK;
}
예제 #2
0
//
//  Find_Key: C
// 
// Returns hash index (either the match or the new one).
// A return of zero is valid (as a hash index);
// 
// Wide: width of record (normally 2, a key and a value).
// 
// Modes:
//     0 - search, return hash if found or not
//     1 - search, return hash, else return -1 if not
//     2 - search, return hash, else append value and return -1
//
REBINT Find_Key(REBSER *series, REBSER *hser, const REBVAL *key, REBINT wide, REBCNT cased, REBYTE mode)
{
    REBCNT *hashes;
    REBCNT skip;
    REBCNT hash;
    REBCNT len;
    REBCNT n;
    REBVAL *val;

    // Compute hash for value:
    len = hser->tail;
    hash = Hash_Value(key, len);
    if (!hash) fail (Error_Has_Bad_Type(key));

    // Determine skip and first index:
    skip  = (len == 0) ? 0 : (hash & 0x0000FFFF) % len;
    if (skip == 0) skip = 1;
    hash = (len == 0) ? 0 : (hash & 0x00FFFF00) % len;

    // Scan hash table for match:
    hashes = (REBCNT*)hser->data;
    if (ANY_WORD(key)) {
        while ((n = hashes[hash])) {
            val = BLK_SKIP(series, (n-1) * wide);
            if (
                ANY_WORD(val) &&
                (VAL_WORD_SYM(key) == VAL_WORD_SYM(val) ||
                (!cased && VAL_WORD_CANON(key) == VAL_WORD_CANON(val)))
            ) return hash;
            hash += skip;
            if (hash >= len) hash -= len;
        }
    }
    else if (ANY_BINSTR(key)) {
        while ((n = hashes[hash])) {
            val = BLK_SKIP(series, (n-1) * wide);
            if (
                VAL_TYPE(val) == VAL_TYPE(key)
                && 0 == Compare_String_Vals(key, val, (REBOOL)(!IS_BINARY(key) && !cased))
            ) return hash;
            hash += skip;
            if (hash >= len) hash -= len;
        }
    } else {
        while ((n = hashes[hash])) {
            val = BLK_SKIP(series, (n-1) * wide);
            if (VAL_TYPE(val) == VAL_TYPE(key) && 0 == Cmp_Value(key, val, !cased)) return hash;
            hash += skip;
            if (hash >= len) hash -= len;
        }
    }

    // Append new value the target series:
    if (mode > 1) {
        hashes[hash] = SERIES_TAIL(series) + 1;
        Append_Values_Len(series, key, wide);
    }

    return (mode > 0) ? NOT_FOUND : hash;
}
예제 #3
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/  static void Bind_Block_Words(REBSER *frame, REBVAL *value, REBCNT mode)
/*
**      Inner loop of bind block. Modes are:
**
**          BIND_ONLY    Only bind the words found in the frame.
**          BIND_SET     Add set-words to the frame during the bind.
**          BIND_ALL     Add words to the frame during the bind.
**          BIND_DEEP    Recurse into sub-blocks.
**
**      NOTE: BIND_SET must be used carefully, because it does not
**      bind prior instances of the word before the set-word. That is
**      forward references are not allowed.
**
***********************************************************************/
{
	REBINT *binds = WORDS_HEAD(Bind_Table); // GC safe to do here
	REBCNT n;
	REBFLG selfish = !IS_SELFLESS(frame);

	for (; NOT_END(value); value++) {
		if (ANY_WORD(value)) {
			//Print("Word: %s", Get_Sym_Name(VAL_WORD_CANON(value)));
			// Is the word found in this frame?
			if (NZ(n = binds[VAL_WORD_CANON(value)])) {
				if (n == NO_RESULT) n = 0; // SELF word
				ASSERT1(n < SERIES_TAIL(frame), RP_BIND_BOUNDS);
				// Word is in frame, bind it:
				VAL_WORD_INDEX(value) = n;
				VAL_WORD_FRAME(value) = frame;
			}
			else if (selfish && VAL_WORD_CANON(value) == SYM_SELF) {
				VAL_WORD_INDEX(value) = 0;
				VAL_WORD_FRAME(value) = frame;
			}
			else {
				// Word is not in frame. Add it if option is specified:
				if ((mode & BIND_ALL) || ((mode & BIND_SET) && (IS_SET_WORD(value)))) {
					Append_Frame(frame, value, 0);
					binds[VAL_WORD_CANON(value)] = VAL_WORD_INDEX(value);
				}
			}
		}
		else if (ANY_BLOCK(value) && (mode & BIND_DEEP))
			Bind_Block_Words(frame, VAL_BLK_DATA(value), mode);
		else if ((IS_FUNCTION(value) || IS_CLOSURE(value)) && (mode & BIND_FUNC))
			Bind_Block_Words(frame, BLK_HEAD(VAL_FUNC_BODY(value)), mode);
	}
}
예제 #4
0
파일: c-frame.c 프로젝트: kealist/ren-c
*/  REBSER *Collect_Words(REBVAL value[], REBVAL prior_value[], REBCNT modes)
/*
**		Collect words from a prior block and new block.
**
***********************************************************************/
{
	REBSER *series;
	REBCNT start;
	REBINT *binds = WORDS_HEAD(Bind_Table); // GC safe to do here
	CHECK_BIND_TABLE;

	if (SERIES_TAIL(BUF_WORDS)) panic Error_0(RE_WORD_LIST); // still in use

	if (prior_value)
		Collect_Words_Inner_Loop(binds, &prior_value[0], BIND_ALL);

	start = SERIES_TAIL(BUF_WORDS);
	Collect_Words_Inner_Loop(binds, &value[0], modes);

	// Reset word markers:
	for (value = BLK_HEAD(BUF_WORDS); NOT_END(value); value++)
		binds[VAL_WORD_CANON(value)] = 0;

	series = Copy_Array_At_Max_Shallow(
		BUF_WORDS, start, SERIES_TAIL(BUF_WORDS) - start
	);
	RESET_TAIL(BUF_WORDS);  // allow reuse

	CHECK_BIND_TABLE;
	return series;
}
예제 #5
0
파일: t-block.c 프로젝트: 51weekend/r3
*/	REBINT PD_Block(REBPVS *pvs)
/*
***********************************************************************/
{
	REBINT n = 0;

	/* Issues!!!
		a/1.3
		a/not-found: 10 error or append?
		a/not-followed: 10 error or append?
	*/

	if (IS_INTEGER(pvs->select)) {
		n = Int32(pvs->select) + VAL_INDEX(pvs->value) - 1;
	}
	else if (IS_WORD(pvs->select)) {
		n = Find_Word(VAL_SERIES(pvs->value), VAL_INDEX(pvs->value), VAL_WORD_CANON(pvs->select));
		if (n != NOT_FOUND) n++;
	}
	else {
		// other values:
		n = Find_Block_Simple(VAL_SERIES(pvs->value), VAL_INDEX(pvs->value), pvs->select) + 1;
	}

	if (n < 0 || (REBCNT)n >= VAL_TAIL(pvs->value)) {
		if (pvs->setval) return PE_BAD_SELECT;
		return PE_NONE;
	}

	if (pvs->setval) TRAP_PROTECT(VAL_SERIES(pvs->value));
	pvs->value = VAL_BLK_SKIP(pvs->value, n);
	// if valset - check PROTECT on block
	//if (NOT_END(pvs->path+1)) Next_Path(pvs); return PE_OK;
	return PE_SET;
}
예제 #6
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/  static void Bind_Relative_Words(REBSER *frame, REBSER *block)
/*
**      Recursive function for relative function word binding.
**
**      Note: frame arg points to an identifying series of the function,
**      not a normal frame. This will be used to verify the word fetch.
**
***********************************************************************/
{
	REBVAL *value = BLK_HEAD(block);
	REBINT n;

	for (; NOT_END(value); value++) {
		if (ANY_WORD(value)) {
			// Is the word (canon sym) found in this frame?
			if (NZ(n = WORDS_HEAD(Bind_Table)[VAL_WORD_CANON(value)])) {
				// Word is in frame, bind it:
				VAL_WORD_INDEX(value) = n;
				VAL_WORD_FRAME(value) = frame; // func body
			}
		}
		else if (ANY_BLOCK(value))
			Bind_Relative_Words(frame, VAL_SERIES(value));
	}
}
예제 #7
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/  REBSER *Collect_End(REBSER *prior)
/*
**		Finish collecting words, and free the Bind_Table for reuse.
**
***********************************************************************/
{
	REBVAL *words;
	REBINT *binds = WORDS_HEAD(Bind_Table); // GC safe to do here

	// Reset binding table (note BUF_WORDS may have expanded):
	for (words = BLK_HEAD(BUF_WORDS); NOT_END(words); words++)
		binds[VAL_WORD_CANON(words)] = 0;

	// If no new words, prior frame:
	if (prior && SERIES_TAIL(BUF_WORDS) == SERIES_TAIL(prior)) {
		RESET_TAIL(BUF_WORDS);  // allow reuse
		return FRM_WORD_SERIES(prior);
	}

	prior = Copy_Series(BUF_WORDS);
	RESET_TAIL(BUF_WORDS);  // allow reuse
	BARE_SERIES(prior); // No GC ever needed for word list

	CHECK_BIND_TABLE;

	return prior;
}
예제 #8
0
파일: c-value.c 프로젝트: rhencke/rebol
//
//  INIT_WORD_INDEX_Debug: C
//
void INIT_WORD_INDEX_Debug(RELVAL *v, REBCNT i)
{
    assert(ANY_WORD(v));
    assert(GET_VAL_FLAG((v), WORD_FLAG_BOUND));
    if (IS_RELATIVE(v))
        assert(
            VAL_WORD_CANON(v)
            == VAL_PARAM_CANON(FUNC_PARAM(VAL_WORD_FUNC(v), i))
        );
    else
        assert(
            VAL_WORD_CANON(v)
            == CTX_KEY_CANON(VAL_WORD_CONTEXT(KNOWN(v)), i)
        );
    v->payload.any_word.index = i;
}
예제 #9
0
파일: a-lib.c 프로젝트: asampal/ren-c
*/ RL_API u32 *RL_Map_Words(REBSER *series)
/*
**	Given a block of word values, return an array of word ids.
**
**	Returns:
**		An array of global word identifiers (integers). The [0] value is the size.
**	Arguments:
**		series - block of words as values (from REBOL blocks, not strings.)
**	Notes:
**		Word identifiers are persistent, and you can use them anytime.
**		The block can include any kind of word, including set-words, lit-words, etc.
**		If the input block contains non-words, they will be skipped.
**		The array is allocated with OS_ALLOC and you can OS_FREE it any time.
**
***********************************************************************/
{
	REBCNT i = 1;
	u32 *words;
	REBVAL *val = BLK_HEAD(series);

	words = OS_ALLOC_ARRAY(u32, series->tail + 2);

	for (; NOT_END(val); val++) {
		if (ANY_WORD(val)) words[i++] = VAL_WORD_CANON(val);
	}

	words[0] = i;
	words[i] = 0;

	return words;
}
예제 #10
0
파일: t-gob.c 프로젝트: ectsoft/saphir
*/	static void Set_Gob_Flag(REBGOB *gob, REBVAL *word)
/*
***********************************************************************/
{
	REBINT i;

	for (i = 0; Gob_Flag_Words[i]; i += 2) {
		if (VAL_WORD_CANON(word) == Gob_Flag_Words[i]) {
			REBCNT flag = Gob_Flag_Words[i+1];
			SET_GOB_FLAG(gob, flag);
			//handle mutual exclusive states
			switch (flag) {
				case GOBF_RESTORE:
					CLR_GOB_FLAGS(gob, GOBF_MINIMIZE, GOBF_MAXIMIZE);
					break;
				case GOBF_MINIMIZE:
					CLR_GOB_FLAGS(gob, GOBF_MAXIMIZE, GOBF_RESTORE);
					break;
				case GOBF_MAXIMIZE:
					CLR_GOB_FLAGS(gob, GOBF_MINIMIZE, GOBF_RESTORE);
					break;
			}
			break;
		}
	}
}
예제 #11
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/  REBSER *Collect_Block_Words(REBVAL *block, REBVAL *prior, REBCNT modes)
/*
**		Collect words from a prior block and new block.
**
***********************************************************************/
{
	REBSER *series;
	REBCNT start;
	REBINT *binds = WORDS_HEAD(Bind_Table); // GC safe to do here
	CHECK_BIND_TABLE;

	if (SERIES_TAIL(BUF_WORDS)) Crash(RP_WORD_LIST); // still in use

	if (prior)
		Collect_Simple_Words(prior, BIND_ALL);

	start = SERIES_TAIL(BUF_WORDS);
	Collect_Simple_Words(block, modes);

	// Reset word markers:
	for (block = BLK_HEAD(BUF_WORDS); NOT_END(block); block++)
		binds[VAL_WORD_CANON(block)] = 0;

	series = Copy_Series_Part(BUF_WORDS, start, SERIES_TAIL(BUF_WORDS)-start);
	RESET_TAIL(BUF_WORDS);  // allow reuse

	CHECK_BIND_TABLE;
	return series;
}
예제 #12
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/  REBSER *Merge_Frames(REBSER *parent1, REBSER *parent2)
/*
**      Create a child frame from two parent frames. Merge common fields.
**      Values from the second parent take precedence.
**
**		Deep copy and rebind the child.
**
***********************************************************************/
{
	REBSER *wrds;
	REBSER *child;
	REBVAL *words;
	REBVAL *value;
	REBCNT n;
	REBINT *binds = WORDS_HEAD(Bind_Table);

	// Merge parent1 and parent2 words.
	// Keep the binding table.
	Collect_Start(BIND_ALL);
	// Setup binding table and BUF_WORDS with parent1 words:
	if (parent1) Collect_Object(parent1);
	// Add parent2 words to binding table and BUF_WORDS:
	Collect_Words(BLK_SKIP(FRM_WORD_SERIES(parent2), 1), BIND_ALL);

	// Allocate child (now that we know the correct size):
	wrds = Copy_Series(BUF_WORDS);
	child = Make_Block(SERIES_TAIL(wrds));
	value = Append_Value(child);
	VAL_SET(value, REB_FRAME);
	VAL_FRM_WORDS(value) = wrds;
	VAL_FRM_SPEC(value) = 0;

	// Copy parent1 values:
	COPY_VALUES(FRM_VALUES(parent1)+1, FRM_VALUES(child)+1, SERIES_TAIL(parent1)-1);

	// Copy parent2 values:
	words = FRM_WORDS(parent2)+1;
	value = FRM_VALUES(parent2)+1;
	for (; NOT_END(words); words++, value++) {
		// no need to search when the binding table is available
		n = binds[VAL_WORD_CANON(words)];
		BLK_HEAD(child)[n] = *value;
	}

	// Terminate the child frame:
	SERIES_TAIL(child) = SERIES_TAIL(wrds);
	BLK_TERM(child);

	// Deep copy the child
	Copy_Deep_Values(child, 1, SERIES_TAIL(child), TS_CLONE);

	// Rebind the child
	Rebind_Block(parent1, child, BLK_SKIP(child, 1), REBIND_FUNC);
	Rebind_Block(parent2, child, BLK_SKIP(child, 1), REBIND_FUNC | REBIND_TABLE);

	// release the bind table 
	Collect_End(wrds);

	return child;
}
예제 #13
0
파일: t-struct.c 프로젝트: asampal/ren-c
*/	static REBFLG Get_Struct_Var(REBSTU *stu, REBVAL *word, REBVAL *val)
/*
***********************************************************************/
{
	struct Struct_Field *field = NULL;
	REBCNT i = 0;
	field = (struct Struct_Field *)SERIES_DATA(stu->fields);
	for (i = 0; i < SERIES_TAIL(stu->fields); i ++, field ++) {
		if (VAL_WORD_CANON(word) == VAL_SYM_CANON(BLK_SKIP(PG_Word_Table.series, field->sym))) {
			if (field->array) {
				REBSER *ser = Make_Array(field->dimension);
				REBCNT n = 0;
				for (n = 0; n < field->dimension; n ++) {
					REBVAL elem;
					get_scalar(stu, field, n, &elem);
					Append_Value(ser, &elem);
				}
				Val_Init_Block(val, ser);
			} else {
				get_scalar(stu, field, 0, val);
			}
			return TRUE;
		}
	}
	return FALSE;
}
예제 #14
0
파일: c-path.c 프로젝트: rgchris/ren-c
//
//  Resolve_Path: C
//
// Given a path, determine if it is ultimately specifying a selection out
// of a context...and if it is, return that context.  So `a/obj/key` would
// return the object assocated with obj, while `a/str/1` would return
// NULL if `str` were a string as it's not an object selection.
//
// !!! This routine overlaps the logic of Do_Path, and should potentially
// be a mode of that instead.  It is not very complete, considering that it
// does not execute GROUP! (and perhaps shouldn't?) and only supports a
// path that picks contexts out of other contexts, via word selection.
//
REBCTX *Resolve_Path(const REBVAL *path, REBCNT *index_out)
{
    RELVAL *selector;
    const REBVAL *var;
    REBARR *array;
    REBCNT i;

    array = VAL_ARRAY(path);
    selector = ARR_HEAD(array);

    if (IS_END(selector) || !ANY_WORD(selector))
        return NULL; // !!! only handles heads of paths that are ANY-WORD!

    var = GET_OPT_VAR_MAY_FAIL(selector, VAL_SPECIFIER(path));

    ++selector;
    if (IS_END(selector))
        return NULL; // !!! does not handle single-element paths

    while (ANY_CONTEXT(var) && IS_WORD(selector)) {
        i = Find_Canon_In_Context(
            VAL_CONTEXT(var), VAL_WORD_CANON(selector), FALSE
        );
        ++selector;
        if (IS_END(selector)) {
            *index_out = i;
            return VAL_CONTEXT(var);
        }

        var = CTX_VAR(VAL_CONTEXT(var), i);
    }

    DEAD_END;
}
예제 #15
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/ void Collect_Words(REBVAL *block, REBFLG modes)
/*
**		The inner recursive loop used for Collect_Words function below.
**
***********************************************************************/
{
	REBINT *binds = WORDS_HEAD(Bind_Table);
	REBVAL *word;
	REBVAL *value;

	for (; NOT_END(block); block++) {
		value = block;
		//if (modes & BIND_GET && IS_GET_WORD(block)) value = Get_Var(block);
		if (ANY_WORD(value)) {
			if (!binds[VAL_WORD_CANON(value)]) {  // only once per word
				if (IS_SET_WORD(value) || modes & BIND_ALL) {
					binds[VAL_WORD_CANON(value)] = SERIES_TAIL(BUF_WORDS);
					EXPAND_SERIES_TAIL(BUF_WORDS, 1);
					word = BLK_LAST(BUF_WORDS);
					VAL_SET(word, VAL_TYPE(value));
					VAL_SET_OPT(word, OPTS_UNWORD);
					VAL_BIND_SYM(word) = VAL_WORD_SYM(value);
					// Allow all datatypes (to start):
					VAL_BIND_TYPESET(word) = ~((TYPESET(REB_END) | TYPESET(REB_UNSET))); // not END or UNSET
				}
			} else {
				// If word duplicated:
				if (modes & BIND_NO_DUP) {
					// Reset binding table (note BUF_WORDS may have expanded):
					for (word = BLK_HEAD(BUF_WORDS); NOT_END(word); word++)
						binds[VAL_WORD_CANON(word)] = 0;
					RESET_TAIL(BUF_WORDS);  // allow reuse
					Trap1(RE_DUP_VARS, value);
				}
			}
			continue;
		}
		// Recurse into sub-blocks:
		if (ANY_EVAL_BLOCK(value) && (modes & BIND_DEEP))
			Collect_Words(VAL_BLK_DATA(value), modes);
		// In this mode (foreach native), do not allow non-words:
		//else if (modes & BIND_GET) Trap_Arg(value);
	}
	BLK_TERM(BUF_WORDS);
}
예제 #16
0
파일: c-frame.c 프로젝트: kealist/ren-c
*/  static void Bind_Values_Inner_Loop(REBINT *binds, REBVAL value[], REBSER *frame, REBCNT mode)
/*
**		Bind_Values_Core() sets up the binding table and then calls
**		this recursive routine to do the actual binding.
**
***********************************************************************/
{
	REBFLG selfish = !IS_SELFLESS(frame);

	for (; NOT_END(value); value++) {
		if (ANY_WORD(value)) {
			//Print("Word: %s", Get_Sym_Name(VAL_WORD_CANON(value)));
			// Is the word found in this frame?
			REBCNT n = binds[VAL_WORD_CANON(value)];
			if (n != 0) {
				if (n == NO_RESULT) n = 0; // SELF word
				assert(n < SERIES_TAIL(frame));
				// Word is in frame, bind it:
				VAL_WORD_INDEX(value) = n;
				VAL_WORD_FRAME(value) = frame;
			}
			else if (selfish && VAL_WORD_CANON(value) == SYM_SELF) {
				VAL_WORD_INDEX(value) = 0;
				VAL_WORD_FRAME(value) = frame;
			}
			else {
				// Word is not in frame. Add it if option is specified:
				if ((mode & BIND_ALL) || ((mode & BIND_SET) && (IS_SET_WORD(value)))) {
					Expand_Frame(frame, 1, 1);
					Append_Frame(frame, value, 0);
					binds[VAL_WORD_CANON(value)] = VAL_WORD_INDEX(value);
				}
			}
		}
		else if (ANY_BLOCK(value) && (mode & BIND_DEEP))
			Bind_Values_Inner_Loop(
				binds, VAL_BLK_DATA(value), frame, mode
			);
		else if ((IS_FUNCTION(value) || IS_CLOSURE(value)) && (mode & BIND_FUNC))
			Bind_Values_Inner_Loop(
				binds, BLK_HEAD(VAL_FUNC_BODY(value)), frame, mode
			);
	}
}
예제 #17
0
파일: c-frame.c 프로젝트: kealist/ren-c
*/ static void Collect_Frame_Inner_Loop(REBINT *binds, REBVAL value[], REBCNT modes)
/*
**		The inner recursive loop used for Collect_Frame function below.
**
***********************************************************************/
{
	for (; NOT_END(value); value++) {
		if (ANY_WORD(value)) {
			if (!binds[VAL_WORD_CANON(value)]) {  // only once per word
				if (IS_SET_WORD(value) || modes & BIND_ALL) {
					REBVAL *word;
					binds[VAL_WORD_CANON(value)] = SERIES_TAIL(BUF_WORDS);
					EXPAND_SERIES_TAIL(BUF_WORDS, 1);
					word = BLK_LAST(BUF_WORDS);
					Val_Init_Word_Typed(
						word,
						VAL_TYPE(value),
						VAL_WORD_SYM(value),
						// Allow all datatypes but END or UNSET (initially):
						~((TYPESET(REB_END) | TYPESET(REB_UNSET)))
					);
				}
			} else {
				// If word duplicated:
				if (modes & BIND_NO_DUP) {
					// Reset binding table (note BUF_WORDS may have expanded):
					REBVAL *word;
					for (word = BLK_HEAD(BUF_WORDS); NOT_END(word); word++)
						binds[VAL_WORD_CANON(word)] = 0;
					RESET_TAIL(BUF_WORDS);  // allow reuse
					raise Error_1(RE_DUP_VARS, value);
				}
			}
			continue;
		}
		// Recurse into sub-blocks:
		if (ANY_EVAL_BLOCK(value) && (modes & BIND_DEEP))
			Collect_Frame_Inner_Loop(binds, VAL_BLK_DATA(value), modes);
		// In this mode (foreach native), do not allow non-words:
		//else if (modes & BIND_GET) raise Error_Invalid_Arg(value);
	}
	BLK_TERM(BUF_WORDS);
}
예제 #18
0
*/	REBINT Compare_Word(REBVAL *s, REBVAL *t, REBFLG is_case)
/*
**		Compare the names of two words and return the difference.
**		Note that words are kept UTF8 encoded.
**		Positive result if s > t and negative if s < t.
**
***********************************************************************/
{
	REBYTE *sp = VAL_WORD_NAME(s);
	REBYTE *tp = VAL_WORD_NAME(t);

	// Use a more strict comparison than normal:
	if (is_case) return CMP_BYTES(sp, tp);

	// They are the equivalent words:
	if (VAL_WORD_CANON(s) == VAL_WORD_CANON(t)) return 0;

	// They must be differ by case:
	return Compare_UTF8(sp, tp, LEN_BYTES(tp)) + 2;
}
예제 #19
0
파일: p-file.c 프로젝트: mbk/ren-c
*/	static REBCNT Get_Mode_Id(REBVAL *word)
/*
***********************************************************************/
{
	REBCNT id = 0;
	if (IS_WORD(word)) {
		id = Find_Int(&Mode_Syms[0], VAL_WORD_CANON(word));
		if (id == NOT_FOUND) Trap_Arg_DEAD_END(word);
	}
	return id;
}
예제 #20
0
//
//  CT_Word: C
//
REBINT CT_Word(REBVAL *a, REBVAL *b, REBINT mode)
{
    REBINT e;
    REBINT diff;
    if (mode >= 0) {
        e = VAL_WORD_CANON(a) == VAL_WORD_CANON(b);
        if (mode == 1) e &= VAL_WORD_INDEX(a) == VAL_WORD_INDEX(b)
            && VAL_WORD_FRAME(a) == VAL_WORD_FRAME(b);
        else if (mode >= 2) {
            e = (VAL_WORD_SYM(a) == VAL_WORD_SYM(b) &&
                VAL_WORD_INDEX(a) == VAL_WORD_INDEX(b) &&
                VAL_WORD_FRAME(a) == VAL_WORD_FRAME(b));
        }
    } else {
        diff = Compare_Word(a, b, FALSE);
        if (mode == -1) e = diff >= 0;
        else e = diff > 0;
    }
    return e;
}
예제 #21
0
파일: t-datatype.c 프로젝트: 51weekend/r3
*/	REBFLG MT_Datatype(REBVAL *out, REBVAL *data, REBCNT type)
/*
***********************************************************************/
{
	if (!IS_WORD(data)) return FALSE;
	type = VAL_WORD_CANON(data);
	if (type > REB_MAX) return FALSE;
	VAL_SET(out, REB_DATATYPE);
	VAL_DATATYPE(out) = type-1;
	VAL_TYPE_SPEC(out) = 0;
	return TRUE;
}
예제 #22
0
파일: c-frame.c 프로젝트: kealist/ren-c
*/  static void Collect_Words_Inner_Loop(REBINT *binds, REBVAL value[], REBCNT modes)
/*
**		Used for Collect_Words() after the binds table has
**		been set up.
**
***********************************************************************/
{
	for (; NOT_END(value); value++) {
		if (ANY_WORD(value)
			&& !binds[VAL_WORD_CANON(value)]
			&& (modes & BIND_ALL || IS_SET_WORD(value))
		) {
			REBVAL *word;
			binds[VAL_WORD_CANON(value)] = 1;
			word = Alloc_Tail_Array(BUF_WORDS);
			Val_Init_Word_Unbound(word, REB_WORD, VAL_WORD_SYM(value));
		}
		else if (ANY_EVAL_BLOCK(value) && (modes & BIND_DEEP))
			Collect_Words_Inner_Loop(binds, VAL_BLK_DATA(value), modes);
	}
}
예제 #23
0
파일: c-bind.c 프로젝트: rgchris/ren-c
//
//  Bind_Relative_Inner_Loop: C
//
// Recursive function for relative function word binding.  Returns TRUE if
// any relative bindings were made.
//
static void Bind_Relative_Inner_Loop(
    struct Reb_Binder *binder,
    RELVAL *head,
    REBARR *paramlist,
    REBU64 bind_types
) {
    RELVAL *value = head;

    for (; NOT_END(value); value++) {
        REBU64 type_bit = FLAGIT_KIND(VAL_TYPE(value));

        // The two-pass copy-and-then-bind should have gotten rid of all the
        // relative values to other functions during the copy.
        //
        // !!! Long term, in a single pass copy, this would have to deal
        // with relative values and run them through the specification
        // process if they were not just getting overwritten.
        //
        assert(!IS_RELATIVE(value));

        if (type_bit & bind_types) {
            REBINT n = Try_Get_Binder_Index(binder, VAL_WORD_CANON(value));
            if (n != 0) {
                //
                // Word's canon symbol is in frame.  Relatively bind it.
                // (clear out existing binding flags first).
                //
                UNBIND_WORD(value);
                SET_VAL_FLAGS(value, WORD_FLAG_BOUND | VALUE_FLAG_RELATIVE);
                INIT_WORD_FUNC(value, AS_FUNC(paramlist)); // incomplete func
                INIT_WORD_INDEX(value, n);
            }
        }
        else if (ANY_ARRAY(value)) {
            Bind_Relative_Inner_Loop(
                binder, VAL_ARRAY_AT(value), paramlist, bind_types
            );

            // Set the bits in the ANY-ARRAY! REBVAL to indicate that it is
            // relative to the function.
            //
            // !!! Technically speaking it is not necessary for an array to
            // be marked relative if it doesn't contain any relative words
            // under it.  However, for uniformity in the near term, it's
            // easiest to debug if there is a clear mark on arrays that are
            // part of a deep copy of a function body either way.
            //
            SET_VAL_FLAG(value, VALUE_FLAG_RELATIVE);
            INIT_RELATIVE(value, AS_FUNC(paramlist)); // incomplete func
        }
    }
}
예제 #24
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/  void Collect_Simple_Words(REBVAL *block, REBCNT modes)
/*
**		Used for Collect_Block_Words().
**
***********************************************************************/
{
	REBINT *binds = WORDS_HEAD(Bind_Table); // GC safe to do here
	REBVAL *val;

	for (; NOT_END(block); block++) {
		if (ANY_WORD(block)
			&& !binds[VAL_WORD_CANON(block)]
			&& (modes & BIND_ALL || IS_SET_WORD(block))
		) {
			binds[VAL_WORD_CANON(block)] = 1;
			val = Append_Value(BUF_WORDS);
			Init_Word(val, VAL_WORD_SYM(block));
		}
		else if (ANY_EVAL_BLOCK(block) && (modes & BIND_DEEP))
			Collect_Simple_Words(VAL_BLK_DATA(block), modes);
	}
}
예제 #25
0
파일: t-gob.c 프로젝트: xqlab/r3
*/	static void Set_Gob_Flag(REBGOB *gob, REBVAL *word)
/*
***********************************************************************/
{
    REBINT i;

    for (i = 0; Gob_Flag_Words[i]; i += 2) {
        if (VAL_WORD_CANON(word) == Gob_Flag_Words[i]) {
            SET_GOB_FLAG(gob, Gob_Flag_Words[i+1]);
            break;
        }
    }
}
예제 #26
0
파일: c-bind.c 프로젝트: rgchris/ren-c
//
//  Try_Bind_Word: C
//
// Binds a word to a context. If word is not part of the context.
//
REBCNT Try_Bind_Word(REBCTX *context, REBVAL *word)
{
    REBCNT n = Find_Canon_In_Context(context, VAL_WORD_CANON(word), FALSE);
    if (n != 0) {
        //
        // Previously may have been bound relative, remove flag.
        //
        CLEAR_VAL_FLAG(word, VALUE_FLAG_RELATIVE);

        SET_VAL_FLAG(word, WORD_FLAG_BOUND);
        INIT_WORD_CONTEXT(word, context);
        INIT_WORD_INDEX(word, n);
    }
    return n;
}
예제 #27
0
파일: c-frame.c 프로젝트: MannyZhong/r3
*/  void Collect_Object(REBSER *prior)
/*
**		Collect words from a prior object.
**
***********************************************************************/
{
	REBVAL *words;
	REBINT *binds = WORDS_HEAD(Bind_Table); // GC safe to do here
	REBINT n;

	words = FRM_WORDS(prior);
	COPY_VALUES(words, BLK_HEAD(BUF_WORDS), SERIES_TAIL(prior));
	SERIES_TAIL(BUF_WORDS) = SERIES_TAIL(prior);
	for (n = 1, words++; NOT_END(words); words++) // skips first = SELF
		binds[VAL_WORD_CANON(words)] = n++;
}
예제 #28
0
파일: c-frame.c 프로젝트: dailybarid/rebol
*/	REBCNT Find_Word(REBSER *series, REBCNT index, REBCNT sym)
/*
**		Find word (of any type) in a block... quickly.
**
***********************************************************************/
{
	REBVAL *value;

	for (; index < SERIES_TAIL(series); index++) {
		value = BLK_SKIP(series, index);
		if (ANY_WORD(value) && sym == VAL_WORD_CANON(value))
			return index;
	}

	return NOT_FOUND;
}
예제 #29
0
파일: u-dialect.c 프로젝트: 51weekend/r3
*/	static REBVAL *Eval_Arg(REBDIA *dia)
/*
**		Handle all values passed in a dialect.
**
**		Contexts can be used for finding a word in a block of
**		contexts without using a path.
**
**		Returns zero on error.
**		Note: stack used to hold temp values
**
***********************************************************************/
{
	REBVAL *value = BLK_SKIP(dia->args, dia->argi);

	switch (VAL_TYPE(value)) {

	case REB_WORD:
		// Only look it up if not part of dialect:
		if (Find_Command(dia->dialect, value) == 0) {
			REBVAL *val = value; // save
			if (dia->contexts) {
				value = Find_In_Contexts(VAL_WORD_CANON(value), dia->contexts);
				if (value) break;
			}
			value = Get_Var_No_Trap(val); // may return zero
		}
		break;

	case REB_PATH:
		if (Do_Path(&value, 0)) return 0;
		value = DS_TOP;
		break;

	case REB_LIT_WORD:
		DS_PUSH(value);
		value = DS_TOP;
		VAL_SET(value, REB_WORD);
		break;

	case REB_PAREN:
		value = DO_BLK(value);
		DS_SKIP; // do not overwrite TOS
		break;
	}
	
	return value;
}
예제 #30
0
파일: a-lib.c 프로젝트: kjanz1899/ren-c
//
//  RL_Map_Words: C
// 
// Given a block of word values, return an array of word ids.
// 
// Returns:
//     An array of global word identifiers (integers). The [0] value is the size.
// Arguments:
//     series - block of words as values (from REBOL blocks, not strings.)
// Notes:
//     Word identifiers are persistent, and you can use them anytime.
//     The block can include any kind of word, including set-words, lit-words, etc.
//     If the input block contains non-words, they will be skipped.
//     The array is allocated with OS_ALLOC and you can OS_FREE it any time.
//
RL_API u32 *RL_Map_Words(REBARR *array)
{
    REBCNT i = 1;
    u32 *words;
    REBVAL *val = ARR_HEAD(array);

    words = OS_ALLOC_N(u32, ARR_LEN(array) + 2);

    for (; NOT_END(val); val++) {
        if (ANY_WORD(val)) words[i++] = VAL_WORD_CANON(val);
    }

    words[0] = i;
    words[i] = 0;

    return words;
}