从stdin \ file读取时的OCaml字符串长度限制

时间:2016-01-24 08:10:27

标签: ocaml utop

作为编译原理课程的一部分,我正在大学学习,我们正在编写一个在OCaml中实现的编译器,它将Scheme代码编译成类似CISC的程序集(只是C宏)。 编译器的基本操作是这样的:

  1. 阅读string文件并将其转换为OCaml *.c
  2. 解析字符串并执行各种分析。
  3. 在语义分析器的AST输出上运行代码生成器,将文本输出到if文件。
  4. 使用GCC编译该文件并在终端中运行。
  5. 嗯,一切都很好,除了这个:我正在尝试读取一个大约4000行的输入文件,基本上是一个巨大的表达式,它是Scheme and& utop。 我正在通过{{1}}执行编译器。当我尝试读取输入文件时,我立即收到堆栈溢出错误消息。我初步猜测该文件对于OCaml来说只是很大,但是我找不到任何支持这种理论的文档。

    有什么建议吗?

2 个答案:

答案 0 :(得分:1)

最大字符串长度由Sys.max_string_length给出。对于32位系统,它很短:16777211。对于64位系统,它是144115188075855863。

除非您使用的是32位系统,并且您的4000行文件超过16MB,否则我认为您没有达到字符串长度限制。

当字符串太长时,堆栈溢出不是您期望看到的。

您更有可能拥有无限递归,或者可能只是一个非常深层次的嵌套计算。

答案 1 :(得分:0)

嗯,事实证明,限制是OCaml配置使用的最大ram数量。

我在终端中运行了以下命令以增加配额:

export OCAMLRUNPARAM="l=5555555555"

这就像一个魅力 - 我设法几乎立即读取和编译输入文件。

供参考,这是读取文件的代码:

let file_to_string input_file =
  let in_channel = open_in input_file in
  let rec run () =
    try
      let ch = input_char in_channel in ch :: (run ())
    with End_of_file ->
      ( close_in in_channel;
       [] )
  in list_to_string (run ());;

其中list_to_string是:

let list_to_string s =
  let rec loop s n =
    match s with
    | [] -> String.make n '?'
    | car :: cdr ->
       let result = loop cdr (n + 1) in
       String.set result n car;
       result
  in
  loop s 0;;

有趣的是 - 我在尾递归中写了file_to_string。这可以防止堆栈溢出,但由于某种原因进入无限循环。哦,好吧......