Skip to content

Commit

Permalink
Ограниченная поддержка копилки (только функции Br и Dg) (#37, #33)
Browse files Browse the repository at this point in the history
Функции реализованы в рантайме, поэтому рантайм может распечатывать
содержимое копилки в отладочном дампе (или при завершении программы
при наличии макроса R05_DUMP_BURIED).

Уточнена документация на эти функции.

Остальные функции копилки добавить сравнительно несложно, добавлю
их по потребности.
  • Loading branch information
Mazdaywik committed Apr 2, 2019
1 parent 26a630f commit 552154c
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
компиляции программ требуется компилятор языка Си.
* Размер символов-чисел равен размеру `unsigned long int` для используемого
компилятора.
* Поддерживается 25 встроенных функций Рефала-5:
* Поддерживается 27 встроенных функций Рефала-5:
* арифметика: `Add`, `Compare`, `Div`, `Mod`, `Mul`, `Sub` — как уже
сказано, беззнаковая и без контроля переполнения,
* работа с типами символов: `Chr`, `Explode`, `Numb`, `Ord`, `Symb`,
Expand All @@ -81,6 +81,7 @@
`ExistFile`,
* операционная система: `Arg`, `GetEnv`, `Exit`, `System`,
* метафункция `Mu` — просто вызывает функцию по указателю,
* копилка: `Br`, `Dg`,
* функция `ListOfBuiltin`, возвращающая список встроенных функций (она есть
и в Рефале-5 тоже).

Expand Down
27 changes: 27 additions & 0 deletions autotests/br-dg.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
$ENTRY Go {
= <Eq () <Dg 'Foo'>>
<Eq () <Br 'Foo=' 1 2>>
<Eq () <Br 'Bar=' 3 4>>
<Eq () <Br 'Foo=' 5 6>>
<Eq (3 4) <Dg 'Bar'>>
<Eq () <Dg 'Bar'>>
<Eq () <Br '=' 10 11>>
<Eq () <Br 'Zz='>>
<Eq (10 11) <Dg>>
<Eq () <Dg 'Zz'>>
<Eq (5 6) <Dg 'Foo'>>
<Eq (1 2) <Dg 'Foo'>>
<Eq () <Dg 'Foo'>>

<Test_Refal-5_bug>;
}

Eq { (e.Eq) e.Eq = }

* Тест на совместимость с багом Рефала-5

Test_Refal-5_bug {
= <Br 'A=B=C'> <C <Dg 'A=B'>>
}

C { 'C' = }
2 changes: 1 addition & 1 deletion autotests/run.bat
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ setlocal
exit /b 1
)

%CLINE% -I../lib %CFILE% ../lib/refal05rts.c
%CLINE% -I../lib %CFILE% ../lib/Library.c ../lib/refal05rts.c
if errorlevel 1 (
echo COMPILATION FAILED
exit /b 1
Expand Down
2 changes: 1 addition & 1 deletion autotests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ run_test_aux() {
exit
fi

$CLINE -I../lib -o$EXE $CFILE ../lib/refal05rts.c
$CLINE -I../lib -o$EXE $CFILE ../lib/Library.c ../lib/refal05rts.c
if [ $? -gt 0 ]; then
echo COMPILATION FAILED
exit
Expand Down
2 changes: 2 additions & 0 deletions docs/1-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,8 @@ _Примечание._ Такой вариант рассматривался,
но и на уровне дизайна самого языка — в нём нет ни статических ящиков,
ни копилки.

**Обновление 2019-04-02:** копилка всё же добавлена.

Код в некоторых местах можно было бы _сократить,_ используя глобальное
хранилище, но, по мнению автора, это _ухудшило бы читаемость и понимаемость._
Минимализм — это цель, а прозрачность исходников — граничное условие.
Expand Down
26 changes: 26 additions & 0 deletions docs/2-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,16 @@ N — число двоичных разрядов типа `unsigned long` и
начинающиеся на знак минус, поэтому в переносимых программах не рекомендуется
использовать ключи командной строки, начинающиеся на минус.

### 4. Br

<Br e.Key '=' e.Value> == пусто

e.Key, e.Value ::= e.AnyExpr

**Семантика:** Сохраняет в копилке соответствующую пару «ключ-значение».

**Совместимость с Рефалом-5:** полная.

### 5. Card

<Card> == s.CHAR* 0?
Expand All @@ -814,6 +824,22 @@ N — число двоичных разрядов типа `unsigned long` и

**Совместимость с Рефалом-5:** полностью совместима.

### 8. Dg

<Dg e.Key> == e.Value

**Семантика:** Извлекает из копилки последнее сохранённое значение с заданным
ключом. Если с заданным ключом ничего не сохранялось, возвращается пустое
выражение.

**Совместимость с Рефалом-5:** полная. Включая следующую ошибку:

$ENTRY Go {
= <Br 'A=B=C'> <Prout <Dg 'A=B'>>
}

И Рефал-5, и Рефал-05 распечатают `C`.

### 10. Div

<Div s.NUMBER s.NUMBER> == s.NUMBER
Expand Down
5 changes: 5 additions & 0 deletions docs/3-install-and-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ _библиотеку поддержки времени выполнения_ (r
полезен для программ, которые почему-то требуют много памяти и вылетают от её
недостатка.

#### Макрос `R05_DUMP_BURIED`

Если этот макрос установлен, то программа при завершении выводит содержимое
копилки.

#### Макрос `R05_MEMORY_LIMIT=n`

Макрос должен принимать целочисленное значение. Если макрос установлен, то при
Expand Down
4 changes: 2 additions & 2 deletions lib/Library.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ R05_DEFINE_ENTRY_FUNCTION(Add) {
/**
4. <Br e.Key '=' e.Value> == empty
*/
R05_DEFINE_ENTRY_ENUM(Br);
struct r05_function r05f_Br = { r05_br, "Br" };


/**
Expand Down Expand Up @@ -157,7 +157,7 @@ R05_DEFINE_ENTRY_FUNCTION(Chr) {
/**
8. <Dg e.Key> == e.Value
*/
R05_DEFINE_ENTRY_ENUM(Dg);
struct r05_function r05f_Dg = { r05_dg, "Dg" };


/**
Expand Down
90 changes: 90 additions & 0 deletions lib/refal05rts.c
Original file line number Diff line number Diff line change
Expand Up @@ -1335,13 +1335,17 @@ static void print_seq(struct r05_node *begin, struct r05_node *end) {
}


static void dump_buried(void);

static void make_dump(void) {
fprintf(stderr, "\nSTEP NUMBER %lu\n", s_step_counter);
fprintf(stderr, "\nPRIMARY ACTIVE EXPRESSION:\n");
print_seq(s_arg_begin, s_arg_end);
fprintf(stderr, "\nVIEW FIELD:\n");
print_seq(&s_begin_view_field, &s_end_view_field);

dump_buried();

#ifdef R05_DUMP_FREE_LIST
fprintf(stderr, "\nFREE LIST:\n");
print_seq(&s_begin_free_list, &s_end_free_list);
Expand All @@ -1353,6 +1357,7 @@ static void make_dump(void) {


R05_NORETURN void r05_exit(int retcode) {
dump_buried();
fflush(stderr);
fflush(stdout);
end_profiler();
Expand Down Expand Up @@ -1413,6 +1418,91 @@ R05_NORETURN void r05_switch_default_violation_impl(
}


/*==============================================================================
Копилка
==============================================================================*/


static struct r05_node s_end_buried;

static struct r05_node s_begin_buried = {
0, &s_end_buried, R05_DATATAG_ILLEGAL, { '\0' }
};
static struct r05_node s_end_buried = {
&s_begin_buried, 0, R05_DATATAG_ILLEGAL, { '\0' }
};


void r05_br(struct r05_node *arg_begin, struct r05_node *arg_end) {
struct r05_node *callee = arg_begin->next;
struct r05_node *p, *left_bracket, *right_bracket;

p = callee->next;
while (
p != arg_end && ! (p->tag == R05_DATATAG_CHAR && p->info.char_ == '=')
) {
p = p->next;
}

if (p == arg_end) {
r05_recognition_impossible();
}

left_bracket = callee;
right_bracket = arg_end;
left_bracket->tag = R05_DATATAG_OPEN_BRACKET;
right_bracket->tag = R05_DATATAG_CLOSE_BRACKET;
r05_link_brackets(left_bracket, right_bracket);
list_splice(s_begin_buried.next, left_bracket, right_bracket);

r05_splice_to_freelist(arg_begin, arg_begin);
}


void r05_dg(struct r05_node *arg_begin, struct r05_node *arg_end) {
struct r05_node *buried_begin = s_begin_buried.next;
struct r05_node *key_begin, *key_end;

r05_prepare_argument(&key_begin, &key_end, arg_begin, arg_end);

while (buried_begin != &s_end_buried) {
struct r05_node *left_bracket = buried_begin;
struct r05_node *right_bracket = left_bracket->info.link;

struct r05_node *in_brackets_b = left_bracket->next;
struct r05_node *in_brackets_e = right_bracket->prev;
struct r05_node *rep_key_b, *rep_key_e;

int found =
r05_repeated_evar_left(
&rep_key_b, &rep_key_e,
key_begin, key_end,
&in_brackets_b, &in_brackets_e
)
&& r05_char_left('=', &in_brackets_b, &in_brackets_e);

if (found) {
r05_splice_evar(arg_begin, in_brackets_b, in_brackets_e);
r05_splice_to_freelist(left_bracket, right_bracket);
break;
}

buried_begin = right_bracket->next;
}

r05_splice_to_freelist(arg_begin, arg_end);
return;
}


static void dump_buried(void) {
#ifdef R05_DUMP_BURIED
fprintf(stderr, "\nBURIED:\n");
print_seq(&s_begin_buried, &s_end_buried);
#endif /* ifdef R05_DUMP_BURIED */
}


int main(int argc, char **argv) {
s_argc = argc;
s_argv = argv;
Expand Down
4 changes: 4 additions & 0 deletions lib/refal05rts.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ R05_NORETURN void r05_switch_default_violation_impl(
)


void r05_br(struct r05_node *arg_begin, struct r05_node *arg_end);
void r05_dg(struct r05_node *arg_begin, struct r05_node *arg_end);


#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
Expand Down

0 comments on commit 552154c

Please sign in to comment.