Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!lll-winken!uunet!mcsun!ukc!edcastle!cs.ed.ac.uk!cs.edinburgh.ac.uk!nick From: nick@cs.edinburgh.ac.uk (Nick Rothwell) Newsgroups: comp.lang.functional Subject: Re: Intermediate Codes for Functional Languages Message-ID: <3054@skye.cs.ed.ac.uk> Date: 6 Dec 90 12:38:07 GMT References: <1316@ucl-cs.uucp> Sender: nnews@cs.ed.ac.uk Reply-To: nick@lfcs.ed.ac.uk Organization: Wavetables 'R' Us Lines: 66 In article <1316@ucl-cs.uucp>, D.Parrott@cs.ucl.ac.uk writes: > > FLIC is probably the most universal of the intermediate codes because > it was designed to be. > ... > %T DACTL: A computational model and compiler target > language based on graph reduction > %J ICL Technical Journal I would guess (although I don't know for sure) that these schemes are biased towards lazy, pure functional languages - the mention of graph reduction above implying this. Compilers for SML (which is neither lazy nor purely functional) have to use different intermediate languages. SML/New Jersey and the Edinburgh Kit Compiler use untyped lambda calculus as an intermediate language - all the language features in ML (including pattern matching and the modules system) can be compiled down to a pretty simple intermediate code. In fact, if I dig around, I can probably find the signature for the Kit Compiler's intermediate form... datatype 'a option = NONE | SOME of 'a datatype LambdaExp = VAR of lvar (* lambda variables. *) | INTEGER of int (* constants... *) | STRING of string | REAL of real | FN of lvar * LambdaExp (* function-terms. *) | FIX of lvar list * LambdaExp list * LambdaExp (* mutual recursive fns. *) | APP of LambdaExp * LambdaExp (* function application. *) | PRIM_APP of prim * LambdaExp (* primitive function application. *) | VECTOR of LambdaExp list (* records/tuples. *) | SELECT of int * lvar (* con/record indexing. *) | SWITCH_I of int Switch (* switch on integers. *) | SWITCH_S of string Switch (* ...strings *) | SWITCH_R of real Switch (* ...reals *) | RAISE of LambdaExp (* raise exception *) | HANDLE of LambdaExp * LambdaExp (* exception handling. *) | VOID (* nil, () etc. *) (* HANDLE(e1, e2) executes e1; if an exception packet results, e2 is applied to the packet. therefore, e2 must be a FN. *) and 'a Switch = SWITCH of {arg: lvar, selections: ('a, LambdaExp) map, wildcard: LambdaExp option (* mandatory for REAL or STRING switches. *) } There's no type information here at all; the compiler works on an abstract syntax tree which it assumes has typechecked. In fact, the typechecker has to provide a few hooks for datatype switches and the like. SML/New Jersey has a second intermediate form, which is essentially lambda calculus but without nested applications, which can be used to build continuation expressions (I'm a little fuzzy on the details). The are a lot of intermediate passes to do closure analysis, register allocation, and so on. -- Nick Rothwell, Laboratory for Foundations of Computer Science, Edinburgh. nick@lfcs.ed.ac.uk !mcsun!ukc!lfcs!nick ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "You ain't seen nothing yet. I can take this floor out too, no trouble." Brought to you by Super Global Mega Corp .com