Язык с умным распределением массива (куча или стек) - PullRequest
0 голосов
/ 12 апреля 2020

Я пишу небольшой игрушечный язык / компилятор для (забавных и) научных c приложений. Основными принципами проектирования являются простота и эффективность (своего рода «современный» Фортран, если хотите). В языке были бы встроенные массивы, которые выглядели бы примерно так:

let x: Real[5] = {1.0, 2.0, 3.0, 4.0, 5.0}

let n = get_runtime_value()
let y: Integer[100,n] = ...

В вышеприведенном выражении пользователь явно не указывает, должен ли массив размещаться в стеке или в куче. Если это вообще возможно, я бы предпочел не раскрывать это пользователям (я полагаю, что большинство инженеров не знают о разнице и не должны об этом беспокоиться. У них есть другие проблемы, о которых нужно беспокоиться).

Технически, я мог бы написать что-то вроде:

if (some input parameter cannot be known at compile time)
  allocate on the heap
else  # candidate for the stack
  if (the array is not returned by the function && the allocated size is smaller than some threshold)
     allocate on the stack
  else
     allocate on the heap

Однако этот дизайн пугает меня по нескольким причинам:

  1. Добавлена ​​сложность, увеличено время компиляции?
  2. В C ++ компилятор может выполнять RVO и возвращать значение в стек напрямую. Я думаю, я мог бы сделать алгоритм более сложным для обнаружения таких случаев, но это сделает все это более сложным / ошибочным / медленным для компиляции.
  3. Небольшое изменение размера массива может привести к переключению из стека в кучу , Это может сбить с толку пользователя. Определение этого порога также потребует некоторой осторожности.
  4. Мне нужно проверить, что некоторая ссылка на этот массив также не возвращается (а также ссылки на ссылки и т. Д. c.). Я полагаю, что это может быть дорого отслеживать.

Обратите внимание, что я не хочу выставлять указатели или ссылки на моем языке. Массивы всегда будут передаваться по ссылке под капотом.

Есть ли в литературе изящный способ решения этой проблемы? Было ли это сделано раньше на существующем языке? Все языки, которые я знаю, требуют, чтобы пользователь указывал, где они хотят получить свои данные: у Fortran есть ::allocatable, в C ++ - std::vector и std::array, et c. Я мог бы также сделать что-то вроде SmallVector команды llvm и всегда выделять несколько элементов в стеке, прежде чем переходить в кучу. Мой подход вообще имеет какой-то смысл? Я использую этот проект, чтобы узнать больше о компиляторах и дизайне языка. Есть что-то, за чем я должен быть бдительным?

1 Ответ

0 голосов
/ 27 апреля 2020

Вариант действительно зависит от вас, но на вашем месте я бы позволил пользователю выбрать, размещать ли его в куче или стеке. Если нет, то это, скорее всего, станет очень запутанным для вас и пользователя. Если вы все еще хотите реализовать эту функцию, у меня есть несколько советов.

  • Вместо того, чтобы проверять, нельзя ли узнать что-либо во время компиляции, проверьте то, что можно узнать во время компиляции - это упростит вещи.
  • Сделайте все, что определено в куче или стеке по умолчанию - это облегчит работу с ситуациями, когда вам нужно переключиться из стека в кучу (или наоборот) (это проще, потому что предположим, когда append называется, вы можете переключиться в кучу).

В заключение, я рекомендую вам дать пользователю возможность явно объявить массив в стеке или куче.

...