{"title":"尾部递归语言的有效堆栈分配","authors":"C. Hanson","doi":"10.1145/91556.91603","DOIUrl":null,"url":null,"abstract":"The Scheme dialect of Lisp [9] is properly tail-recuraiwit relies entirely on procedure calls to express iteration. In Scheme, a tail-recursive procedure call (that is, a call in which the calling procedure does not do any further processing of the returned due) is essentially a goto that passes arguments, sa was first pointed out by Steele [13]. In a prop erly tail-recursive language, there is no need for any explicit iteration constructs such as do or vhile; these can all be defined in terms of ordinary procedure calls. As elegant as tail-recursion may be from the perspective of the programmer or the theoretician, it poses challenges for the compiler designer. One of the crucial decisions in the design of a compiler is the formation of a strategy for memory allocation and deallocation. An important aspect of this strategy is the treatment of memory locations used to hold the bindings of local variables. Because local variables play a significant role in most computer languages, their treatment can have a noticeable impact on a program’s execution speed and run-time space requirements. Compilers for many block-structured languages use a simple strategy when allocating local variables: stack allocation. This strategy is supported by hardware on many computers, and by software mechanisms such as the aceem link and the display. However, the standard methods for implementing stack allocation assume that the language is not tail-recursive, and a straightforward application of these methods to a tailrecursive language can result in non-tail-recursive compiled code.’ This paper describes stack-allocation techniques for compiling tail-recursive languages. We do not claim that these are the only techniquea that can be used to solve the prob lem, nor do we compare them to other techniques. Instead, we use our techniques as a concrete example to demonstrate that it is possible to implement stack allocation of local variables without sacrificing tail recursion, which to our knowledge has not previously been shown. We have implemented these techniques in the MIT","PeriodicalId":409945,"journal":{"name":"LISP and Functional Programming","volume":"1 1","pages":"0"},"PeriodicalIF":0.0000,"publicationDate":"1990-05-01","publicationTypes":"Journal Article","fieldsOfStudy":null,"isOpenAccess":false,"openAccessPdf":"","citationCount":"29","resultStr":"{\"title\":\"Efficient stack allocation for tail-recursive languages\",\"authors\":\"C. Hanson\",\"doi\":\"10.1145/91556.91603\",\"DOIUrl\":null,\"url\":null,\"abstract\":\"The Scheme dialect of Lisp [9] is properly tail-recuraiwit relies entirely on procedure calls to express iteration. In Scheme, a tail-recursive procedure call (that is, a call in which the calling procedure does not do any further processing of the returned due) is essentially a goto that passes arguments, sa was first pointed out by Steele [13]. In a prop erly tail-recursive language, there is no need for any explicit iteration constructs such as do or vhile; these can all be defined in terms of ordinary procedure calls. As elegant as tail-recursion may be from the perspective of the programmer or the theoretician, it poses challenges for the compiler designer. One of the crucial decisions in the design of a compiler is the formation of a strategy for memory allocation and deallocation. An important aspect of this strategy is the treatment of memory locations used to hold the bindings of local variables. Because local variables play a significant role in most computer languages, their treatment can have a noticeable impact on a program’s execution speed and run-time space requirements. Compilers for many block-structured languages use a simple strategy when allocating local variables: stack allocation. This strategy is supported by hardware on many computers, and by software mechanisms such as the aceem link and the display. However, the standard methods for implementing stack allocation assume that the language is not tail-recursive, and a straightforward application of these methods to a tailrecursive language can result in non-tail-recursive compiled code.’ This paper describes stack-allocation techniques for compiling tail-recursive languages. We do not claim that these are the only techniquea that can be used to solve the prob lem, nor do we compare them to other techniques. Instead, we use our techniques as a concrete example to demonstrate that it is possible to implement stack allocation of local variables without sacrificing tail recursion, which to our knowledge has not previously been shown. We have implemented these techniques in the MIT\",\"PeriodicalId\":409945,\"journal\":{\"name\":\"LISP and Functional Programming\",\"volume\":\"1 1\",\"pages\":\"0\"},\"PeriodicalIF\":0.0000,\"publicationDate\":\"1990-05-01\",\"publicationTypes\":\"Journal Article\",\"fieldsOfStudy\":null,\"isOpenAccess\":false,\"openAccessPdf\":\"\",\"citationCount\":\"29\",\"resultStr\":null,\"platform\":\"Semanticscholar\",\"paperid\":null,\"PeriodicalName\":\"LISP and Functional Programming\",\"FirstCategoryId\":\"1085\",\"ListUrlMain\":\"https://doi.org/10.1145/91556.91603\",\"RegionNum\":0,\"RegionCategory\":null,\"ArticlePicture\":[],\"TitleCN\":null,\"AbstractTextCN\":null,\"PMCID\":null,\"EPubDate\":\"\",\"PubModel\":\"\",\"JCR\":\"\",\"JCRName\":\"\",\"Score\":null,\"Total\":0}","platform":"Semanticscholar","paperid":null,"PeriodicalName":"LISP and Functional Programming","FirstCategoryId":"1085","ListUrlMain":"https://doi.org/10.1145/91556.91603","RegionNum":0,"RegionCategory":null,"ArticlePicture":[],"TitleCN":null,"AbstractTextCN":null,"PMCID":null,"EPubDate":"","PubModel":"","JCR":"","JCRName":"","Score":null,"Total":0}
Efficient stack allocation for tail-recursive languages
The Scheme dialect of Lisp [9] is properly tail-recuraiwit relies entirely on procedure calls to express iteration. In Scheme, a tail-recursive procedure call (that is, a call in which the calling procedure does not do any further processing of the returned due) is essentially a goto that passes arguments, sa was first pointed out by Steele [13]. In a prop erly tail-recursive language, there is no need for any explicit iteration constructs such as do or vhile; these can all be defined in terms of ordinary procedure calls. As elegant as tail-recursion may be from the perspective of the programmer or the theoretician, it poses challenges for the compiler designer. One of the crucial decisions in the design of a compiler is the formation of a strategy for memory allocation and deallocation. An important aspect of this strategy is the treatment of memory locations used to hold the bindings of local variables. Because local variables play a significant role in most computer languages, their treatment can have a noticeable impact on a program’s execution speed and run-time space requirements. Compilers for many block-structured languages use a simple strategy when allocating local variables: stack allocation. This strategy is supported by hardware on many computers, and by software mechanisms such as the aceem link and the display. However, the standard methods for implementing stack allocation assume that the language is not tail-recursive, and a straightforward application of these methods to a tailrecursive language can result in non-tail-recursive compiled code.’ This paper describes stack-allocation techniques for compiling tail-recursive languages. We do not claim that these are the only techniquea that can be used to solve the prob lem, nor do we compare them to other techniques. Instead, we use our techniques as a concrete example to demonstrate that it is possible to implement stack allocation of local variables without sacrificing tail recursion, which to our knowledge has not previously been shown. We have implemented these techniques in the MIT