Я пишу небольшой игрушечный язык / компилятор для (забавных и) научных 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
Однако этот дизайн пугает меня по нескольким причинам:
- Добавлена сложность, увеличено время компиляции?
- В C ++ компилятор может выполнять RVO и возвращать значение в стек напрямую. Я думаю, я мог бы сделать алгоритм более сложным для обнаружения таких случаев, но это сделает все это более сложным / ошибочным / медленным для компиляции.
- Небольшое изменение размера массива может привести к переключению из стека в кучу , Это может сбить с толку пользователя. Определение этого порога также потребует некоторой осторожности.
- Мне нужно проверить, что некоторая ссылка на этот массив также не возвращается (а также ссылки на ссылки и т. Д. c.). Я полагаю, что это может быть дорого отслеживать.
Обратите внимание, что я не хочу выставлять указатели или ссылки на моем языке. Массивы всегда будут передаваться по ссылке под капотом.
Есть ли в литературе изящный способ решения этой проблемы? Было ли это сделано раньше на существующем языке? Все языки, которые я знаю, требуют, чтобы пользователь указывал, где они хотят получить свои данные: у Fortran есть ::allocatable
, в C ++ - std::vector
и std::array
, et c. Я мог бы также сделать что-то вроде SmallVector
команды llvm и всегда выделять несколько элементов в стеке, прежде чем переходить в кучу. Мой подход вообще имеет какой-то смысл? Я использую этот проект, чтобы узнать больше о компиляторах и дизайне языка. Есть что-то, за чем я должен быть бдительным?