General-purpose languages A general-purpose language is designed for a wide variety of programming problems Examples: C, C++, Fortran, Algol, Pascal, Java To meet conflicting demands, a general- purpose language must make many compromises
ASLs An Application-Specific Language (ASL) is designed for a particular class of problems –ZIL (Zork Implementation Language) –MOO (an O-O language for MUDs) –Bard (for manipulating Abstract Syntax Trees) –ML (originally designed for just one program-- Edinburgh LCF, Logic for Computable Functions)
Advantages of an ASL An ASL is not a "Jack of all trades, master of none" -- it's very focused An ASL can often avoid compromises, or at least bias them in favor of the application An ASL can use very high-level constructs An ASL can be simpler to learn and to use An ASL can boost productivity up to 10 x
Deciding to use an ASL Consider using an ASL if –The problem area has unique features –There are suitable high-level operations –The high-level operations are ubiquitous –There is a lot of very similar code to write –You can find a suitable existing ASL, or... –…you know how to write compilers
Sample ZIL Object -> tasty_food "tasty food" with description "Sure looks yummy!", article "some", initial "There is tasty food here.", name "food" "ration" "rations", after [; Eat: "Delicious!"; ], has edible;
More sample ZIL Object -> wicker_cage "wicker cage" with description "It's a small wicker cage.", initial "There is a small wicker cage discarded nearby.", name "cage" "small" "wicker", after [; Open: if (little_bird notin self) rfalse; print "(releasing the little bird)^"; <>; ], has container open openable transparent;
Khufu Mongo Telephone scenario ( MOO ) dial #350 The phone is ringing. The other phone is ringing. The other phone is ringing. The phone is ringing. answer phone It sounds like you have It sounds like you have a connection. a connection. say hello Mongo says, "hello" You say, "hello"
MOO Example 2 @program generic_telephone:answer this_phone = this; if (player != this_phone.location) player:tell("You must first take the phone."); else this_phone.off_hook = 1; other_phone = this_phone.connected_to; player.is_on_phone = this_phone; if (other_phone == 0) player:tell("You hear a dial tone."); endif.
How do you write an ASL? Compilers generally consist of three parts: –A lexical scanner, to turn an input stream of characters into tokens. –A parser, to construct an Abstract Syntax Tree (AST) from the token stream. –Either a code generator, to walk the AST and translate it into some other computer language, or –An interpreter, to walk the AST and perform the operations indicated therein
The lexical scanner Input to the ASL compiler is just a stream of characters The characters have to be grouped into tokens that are meaningful for the particular language Example: Input: i f ( m i n < 0 ) m i n + + ; Tokens: if ( min < 0 ) min ++ ;
The parser The parser constructs an Abstract Syntax Tree (AST) from the token stream The AST defines the operations to be performed and the order in which to perform them The AST is abstract because it leaves out information that may have been needed to construct the tree, but is no longer needed
Example Abstract Syntax Tree IF LESS_THANINCREMENT min 0 if (min < 0 ) min++ ;
Compilers and interpreters Once you have the AST, you have two choices: –Compile it: Generate code in some other computer language that does the same thing as the program in the ASL –Interpret it: Walk the tree and do what it says Compiling gives you faster code Interpreting is much easier and more flexible
lex and yacc One of the easiest and best ways to write a compiler or interpreter is to use a pair of UNIX programs called lex and yacc lex is an ASL for writing lexical scanners yacc is an ASL for writing code generators These ASLs have been ported to most platforms
Bard example idiom remove_null_statements; -- Remove null statements, except empty loop bodies. procedure remove_null_statements (1, Null_Statement); go to first child of parent; not match While_Op; not match Do_While; not match C_For_Loop; commit; go to @trigger; delete; end procedure; end idiom;
Summary I A programmer's goal should be to write the best code with the least time and effort. General-purpose languages provide tools to let you expand the program's "vocabulary": –functions (procedures, methods...) –structs, objects, tables and databases, etc. Much of the work is customizing the language...so why not start with a better language?
Summary II Application-specific languages are most useful if: –You can find suitable high-level operations. –The high-level operations are unusual. –The high-level operations are ubiquitous. –There is a lot of very similar code to write. Laymen need to be able to do the programming. –You know how to write compilers.