作为编译原理课程的一部分,我正在大学学习,我们正在编写一个在OCaml中实现的编译器,它将Scheme代码编译成类似CISC的程序集(只是C宏)。 编译器的基本操作是这样的:
string
文件并将其转换为OCaml *.c
。if
文件。嗯,一切都很好,除了这个:我正在尝试读取一个大约4000行的输入文件,基本上是一个巨大的表达式,它是Scheme and
& utop
。
我正在通过{{1}}执行编译器。当我尝试读取输入文件时,我立即收到堆栈溢出错误消息。我初步猜测该文件对于OCaml来说只是很大,但是我找不到任何支持这种理论的文档。
有什么建议吗?
答案 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
。这可以防止堆栈溢出,但由于某种原因进入无限循环。哦,好吧......