The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

3.6 Динамическая компоновка

3.6 Динамическая компоновка

Предыдущая  Содержание  Следующая V*D*V

Распознаватель завершён. value.h полностью скрывает блок вычислений арифметических выражений и в то же время определяет, что мы должны реализовать. new() принимает описание, например, Add (сложение) и подходящие аргументы, например, указатели на операнды сложения и возвращает указатель, представляющий собой данную сумму:

 

struct Type {

    void * (* new) (va_list ap);

    double (* exec) (const void * tree);

    void (* delete) (void * tree);

};

 

void * new (const void * type, ...) {

    va_list ap;

    void * result;

 

    assert(type && ((struct Type *) type) -> new);

 

    va_start(ap, type);

    result = ((struct Type *) type) -> new(ap);

    * (const struct Type **) result = type;

    va_end(ap);

    return result;

}

 

Мы используем динамическую компоновку и передаём вызов в зависимую от узла подпрограмму, которая в случае Add должна создать узел и записать два указателя:

 

struct Bin {

    const void * type;

    void * left, * right;

};

 

static void * mkBin (va_list ap) {

    struct Bin * node = malloc(sizeof(struct Bin));

 

    assert(node);

    node -> left = va_arg(ap, void *);

    node -> right = va_arg(ap, void *);

    return node;

}

 

Обратите внимание, что только mkBin() знает, какой узел создаётся. Всё, что требуется, чтобы различные узлы начинались с указателя для динамической компоновки. Этот указатель вводится new() так, чтобы delete() могла добраться своей до зависимой от узла функции:

 

void delete (void * tree)

{

    assert(tree && * (struct Type **) tree

        && (* (struct Type **) tree) -> delete);

 

    (* (struct Type **) tree) -> delete(tree);

}

 

static void freeBin (void * tree)

{

    delete(((struct Bin *) tree) -> left);

    delete(((struct Bin *) tree) -> right);

    free(tree);

}

 

Динамическая компоновка элегантно избегает сложных узлов. .new() создаёт совершенно правильный узел для каждого описания типа: бинарные операторы имеют два потомка, унарные операторы имеют одного, а узел со значением содержит только это значение. delete() очень простая функция, потому что каждый узел обрабатывает свою собственное уничтожение: бинарные операторы удаляют два поддерева и очищают свой собственный узел, унарные операторы удаляют только одно поддерево, а узел со значением будет очищать только самого себя. Переменные или константы даже могут быть оставлены — они просто ничего не будут делать в ответ на delete().

 

Предыдущая  Содержание  Следующая