Esempio n. 1
0
Block* find_first_common_block(Term* left, Term* right)
{
    Block* leftParent = left->owningBlock;
    Block* rightParent = right->owningBlock;

    if (leftParent == NULL) return NULL;
    if (rightParent == NULL) return NULL;

    // Walk upwards from left term.
    while (leftParent != NULL) {

        // Walk upwards from right term.
        while (rightParent != NULL) {
            if (leftParent == rightParent)
                return leftParent;

            rightParent = get_parent_block(rightParent);
        }

        leftParent = get_parent_block(leftParent);
        rightParent = right->owningBlock;
    }

    return NULL;
}
Esempio n. 2
0
Block* find_block_that_exit_point_will_reach(Term* term)
{
    ca_assert(is_exit_point(term));

    Block* block = term->owningBlock;

    // 'return' exits to nearest major block.
    if (term->function == FUNCS.return_func) {
        while (is_minor_block(block)) {
            Block* parent = get_parent_block(block);
            if (parent == NULL)
                return block;

            block = parent;
        }
        return block;
    }

    // 'case_condition_bool' exits the current if-block.
    if (term->function == FUNCS.case_condition_bool)
        return get_parent_block(term->owningBlock);

    // Otherwise, exit to nearest for-loop.
    while (!is_for_loop(block) && !is_while_loop(block)) {
        Block* parent = get_parent_block(block);
        if (parent == NULL)
            return block;

        block = parent;
    }
    return block;
}
Esempio n. 3
0
Block* get_parent_block_stackwise(Block* block)
{
    block = get_parent_block(block);

    if (block != NULL && is_switch_block(block))
        block = get_parent_block(block);

    return block;
}
Esempio n. 4
0
void UpwardIterator2::advanceWhileInvalid()
{
possibly_invalid:
    if (finished())
        return;

    if (index < 0) {
        // Stop if we've finished the lastBlock.
        if (block == lastBlock) {
            block = NULL;
            return;
        }

        Block* previousBlock = block;
        block = get_parent_block(block);
        Term* parentTerm = parent_term(previousBlock);

        if (block == NULL || parentTerm == NULL) {
            block = NULL;
            return;
        }

        index = parentTerm->index - 1;

        goto possibly_invalid;
    }
}
Esempio n. 5
0
void create_output_from_minor_block(Block* block, Value* description)
{
    if (is_case_block(block)) {
        Block* ifBlock = get_parent_block(block);
        if_block_append_output(ifBlock, description);
    } else if (is_minor_block(block)) {
        append_output_placeholder_with_description(block, description);
    }
}
Esempio n. 6
0
Block* find_enclosing_module(Block* block)
{
    while (true) {
        if (block == NULL)
            return NULL;
        if (is_module(block))
            return block;
        block = get_parent_block(block);
    }
}
Esempio n. 7
0
Block* find_common_parent(Block* a, Block* b)
{
    Block* parent = a;
    Block* searchBlock = b;

    while (parent != NULL) {

        searchBlock = b;
        while (searchBlock != NULL) {
            if (parent == searchBlock)
                return parent;

            searchBlock = get_parent_block(searchBlock);
        }

        parent = get_parent_block(parent);
    }
    return NULL;
}
Esempio n. 8
0
void Block__parent(VM* vm)
{
    Block* block = as_block(vm->input(0));
    if (block == NULL) {
        set_block(vm->output(), NULL);
        return;
    }

    set_block(vm->output(), get_parent_block(block));
}
Esempio n. 9
0
bool block_is_child_of(Block* possibleChild, Block* possibleParent)
{
    while (true) {
        possibleChild = get_parent_block(possibleChild);

        if (possibleChild == NULL)
            return false;
        if (possibleChild == possibleParent)
            return true;
    }
}
Esempio n. 10
0
bool name_is_reachable_from(Term* term, Block* block)
{
    if (term->owningBlock == block)
        return true;

    Block* parent = get_parent_block(block);

    if (parent == NULL)
        return false;

    return name_is_reachable_from(term, parent);
}
Esempio n. 11
0
void Block__source_filename(VM* vm)
{
    Block* block = as_block(vm->input(0));
    while (block != NULL) {
        Value* filename = block_get_source_filename(block);

        if (filename != NULL) {
            copy(filename, vm->output());
            return;
        }

        block = get_parent_block(block);
    }
    set_string(vm->output(), "");
}
Esempio n. 12
0
Block* find_enclosing_loop(Block* block)
{
    while (true) {
        if (block == NULL)
            return NULL;

        if (is_while_loop(block) || is_for_loop(block))
            return block;

        if (is_major_block(block))
            return NULL;

        block = get_parent_block(block);
    }
    return NULL;
}
Esempio n. 13
0
void get_source_file_location(Block* block, Value* out)
{
    // Search upwards until we find a block that has source-file defined.
    while (block != NULL && block_get_source_filename(block) == NULL)
        block = get_parent_block(block);

    if (block == NULL)
        return set_string(out, "");

    Value* sourceFilename = block_get_source_filename(block);

    if (sourceFilename == NULL)
        return set_string(out, "");

    get_directory_for_filename(sourceFilename, out);
}
Esempio n. 14
0
void controlFlow_postCompile(Term* term)
{
    // Mark the owning block, and all parent minor blocks, as hasControlFlow.
    Block* block = term->owningBlock;

    while (true) {
        set_bool(block_insert_property(block, s_HasControlFlow), true);

        if (!is_minor_block(block))
            break;

        block = get_parent_block(block);

        if (block == NULL)
            break;
    }
}
Esempio n. 15
0
Term* run_name_search(NameSearch* params)
{
    stat_increment(NameSearch);

    if (is_null(&params->name) || string_equals(&params->name, ""))
        return NULL;

    Block* block = params->block;

    if (block == NULL)
        return NULL;

    int position = 0;
    
    if (is_symbol(&params->position) && as_symbol(&params->position) == s_last)
        position = block->length();
    else
        position = as_int(&params->position);

    if (position > block->length())
        position = block->length();

    // Look for an exact match.
    for (int i = position - 1; i >= 0; i--) {

        stat_increment(NameSearchStep);

        Term* term = block->get(i);
        if (term == NULL)
            continue;

        if (equals(&term->nameValue, &params->name)
                && fits_lookup_type(term, params->lookupType)
                && (params->ordinal == -1 || term->uniqueOrdinal == params->ordinal))
            return term;

        // If this term exposes its names, then search inside the nested block.
        // (Deprecated, I think).
        if (term->nestedContents != NULL && exposes_nested_names(term)) {
            NameSearch nestedSearch;
            nestedSearch.block = term->nestedContents;
            set_value(&nestedSearch.name, &params->name);
            set_symbol(&nestedSearch.position, s_last);
            nestedSearch.ordinal = -1;
            nestedSearch.lookupType = params->lookupType;
            nestedSearch.searchParent = false;
            Term* found = run_name_search(&nestedSearch);
            if (found != NULL)
                return found;
        }

        #if 0
        // Check for an 'import' statement. If found, continue this search in the designated module.
        if (term->function == FUNCS.require && term->boolProp(s_Syntax_Import, false)) {
            Block* module = find_module_for_require_statement(term);
            if (module != NULL) {
                NameSearch moduleSearch;
                moduleSearch.block = module;
                set_value(&moduleSearch.name, &params->name);
                set_symbol(&moduleSearch.position, s_last);
                moduleSearch.ordinal = -1;
                moduleSearch.lookupType = params->lookupType;
                moduleSearch.searchParent = false;
                Term* found = run_name_search(&moduleSearch);
                if (found != NULL)
                    return found;
            }
        }
        #endif
    }

    // Did not find in the local block. Possibly continue this search upwards.
    
    if (!params->searchParent)
        return NULL;

    // Possibly take this search to the builtins block.
    if ((get_parent_block(block) == NULL) || is_module(block)) {
        NameSearch builtinsSearch;
        builtinsSearch.block = find_builtins_block(block);
        set_value(&builtinsSearch.name, &params->name);
        set_symbol(&builtinsSearch.position, s_last);
        builtinsSearch.lookupType = params->lookupType;
        builtinsSearch.ordinal = -1;
        builtinsSearch.searchParent = false;
        return run_name_search(&builtinsSearch);
    }

    // Search parent

    // The choice of position is a little weird. For regular name searches,
    // we start at the parent term's position (ie, search all the terms that
    // came before the parent).
    //
    // For a LookupFunction search, start at the bottom of the branch. It's okay
    // for a term to use a function that occurs after the term.
    
    NameSearch parentSearch;

    Term* parentTerm = block->owningTerm;
    if (parentTerm == NULL)
        return NULL;

    parentSearch.block = parentTerm->owningBlock;
    if (params->lookupType == s_LookupFunction)
        set_symbol(&parentSearch.position, s_last);
    else
        set_int(&parentSearch.position, parentTerm->index + 1);

    set_value(&parentSearch.name, &params->name);
    parentSearch.lookupType = params->lookupType;
    parentSearch.ordinal = -1;
    parentSearch.searchParent = true;
    return run_name_search(&parentSearch);
}