Реализация интерпретатора с прямой резьбой на функциональном языке, таком как OCaml

В C / C ++ вы можете реализовать прямой потоковый интерпретатор с массив указателей на функции. Массив представляет вашу программу - массив операций. Каждая из функций операции должна заканчиваться вызовом следующей функции в массиве, например:

void op_plus(size_t pc, uint8_t* data) {
  *data += 1;
  BytecodeArray[pc+1](pc+1, data); //call the next operation in the array
}

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

Как можно реализовать что-то подобное в OCaml? Возможно, я пытаюсь перевести этот код слишком буквально: я использовал массив функций OCaml, как в C ++. Проблема в том, что я продолжаю получать что-то вроде:

let op_plus pc data = Printf.printf "pc: %d, data_i: %d \n" pc data;
                        let f = (op_array.(pc+1)) in         
                        f (pc+1) (data+1) ;;

где op_array - это массив, определенный в области выше, а затем переопределить его позже, чтобы он был заполнен кучей функций op_plus ... однако, функция op_plus использует предыдущее определение op_array. Это проблема курицы и яйца.

8
задан aneccodeal 31 August 2010 в 00:36
поделиться

2 ответа

Еще один вариант (если размер заранее известен) - изначально заполнить массив пустыми инструкциями:

let op_array = Array.create size (fun _ _ -> assert false)
let op_plus = ...
let () = op_array.(0) <- op_plus; ...
2
ответ дан 5 December 2019 в 15:16
поделиться

Вы не должны переопределять op_array, вы должны заполнить его инструкциями, изменив его на месте так, чтобы он был тем же op_array, который уже используется в ваших функциях. Ссылаться на. К сожалению, в OCaml нельзя динамически изменять размер массива.

Я вижу два решения:

1) если не нужно менять последовательность "инструкций", определить их во взаимной рекурсии с массивом op_array. OCaml позволяет определять взаимно рекурсивные функции и значения, которые начинаются с применения конструктора. Что-то вроде:

let rec op_plus pc data = ...
and op_array = [| ... |]

2) Или используйте дополнительную косвенность: сделайте op_array ссылкой на массив инструкций и обратитесь в функциях к (!op_array).(pc+1). Позже, после того как вы определили все инструкции, вы можете сделать так, чтобы op_array указывал на массив нужного размера, полный необходимых инструкций.

let op_array = ref [| |] ;;
let op_plus pc data = ... ;;
op_array := [| ... |] ;;
4
ответ дан 5 December 2019 в 15:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: