wig compiler report - rjfwig › ~rshaik1 › papers › compiler.pdf · wig compiler report -...

29
McGill University School of Computer Science COMP 520 Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S´ ebastien L´ egar´ e elix Martineau Reehan Shaikh {jlegar, fmarti10, reehan.shaikh}@cs.mcgill.ca November 28, 2005 www.cs.mcgill.ca

Upload: others

Post on 07-Jul-2020

12 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

McGill University

School of Computer Science

COMP 520

Wig Compiler Report - RJFWig

Report No. 2005-01

Jean-Sebastien LegareFelix MartineauReehan Shaikh

{jlegar, fmarti10, reehan.shaikh}@cs.mcgill.ca

November 28, 2005

w w w . c s . m c g i l l . c a

Page 2: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

Contents

1 Introduction 2

1.1 Clarifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.2 Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3 Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.4 Implementation Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 Parsing and Abstract Syntax Trees 3

2.1 The Grammar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.2 Using the flex or SableCC Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.3 Using the bison or SableCC Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.4 Abstract Syntax Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.5 Desugaring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.6 Weeding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.7 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

3 Symbol Tables 13

3.1 Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.2 Scope Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3.3 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4 Type Checking 15

4.1 Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.2 Type Rules & Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.3 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

5 Tuples 15

5.1 Tuple Operations and Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

5.2 Type Checking Tuple Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

6 Resource Computation 16

7 Code Generation 16

7.1 Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

7.2 Code Templates & Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

7.3 Runtime System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

7.4 Sample Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

7.5 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

8 Availability and Group Dynamics 27

8.1 Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

8.2 Demo Site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

8.3 Division of Group Duties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

1

Page 3: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

1 Introduction

1.1 Clarifications

There wasn’t much that was unclear about the grammar, especially since we have all taken COMP-330 andhave expert background in reading regular expressions, grammar production and syntax. The few unclearpoints were porting the grammar so that it can be supported by SableCC version 3 and what the exactsyntax of converting a concrete syntax tree to an abstract syntax tree meant. A bit confusing was how toinclude new sets in the grammar, for example, a set of Helpers, Ignored Tokens, etc. . . . Nonetheless, wefigured out what needed to be done and have resolved these issues.

Another clarification to be addressed is that regarding plugs in an html document. We don’t enforce theuser to fill all the plugs in the document before showing it. The unplugged holes will just display as blankobjects in the html web-page. We leave this to the user to make sure he/she plugs in the desired holes.

1.2 Restrictions

These restrictions throw errors and compilation is stopped.

The first major restriction we came across was that concerning void types. Though methods can havevoid return types, a variable or schema field cannot be of type void. This facilitates comparing types, makingsure that when a variable is assigned to another, they are compatible. We pondered a while on what a voidvariable would be, if you can assign a void variable to another void variable, if all other types are subtypesof void (so that if you assign any variable to a void variable, it should work). This would be a good feature(as in Java, all objects extend Object), but it would be unconventional as all major programming languagesdon’t allow primitive void type variables.

Secondly, we do not allow a schema field to be of type tuple. In consequence, we cannot have nestedtuples. This significantly decreased the complexity of type checking tuple assignment and was purely done sothat we can focus our attention on much more needed aspects of the RJFWig compiler. Also, to recursivelycheck if a tuple assignment is valid when the tuple has a nested tuple that has a nested tuple that also hasa nested tuple. . . you get my point. Checking if each of the tuple’s fields has been initialized would also becumbersome. Moreover, suppose we have the following scenario,

schema s1 {tuple s2 t; int a; . . . }schema s2 {tuple s1 t; bool b; . . . }

This recursive definition would cause major problems. Finally, the cons of allowing this feature outweighthe pros.

Thirdly, we don’t allow WIG functions to have a SHOW call. We will show the motivation of thisdecision by example. Suppose we have functions A, B and C, where A and B both call C. Also, supposethat function C has a SHOW statement inside it. When this SHOW statement is reached, not only thecurrent state of the local variables of the callee (function C) would need to be saved, but the states of thelocal variables of all the functions on the call stack (function A or B) would need to be saved to a file as well.Once the user has submitted the form, the state is loaded back and execution resumes. We resume executionby jumping to the saved program counter label. When the Perl - our target language - return instructionwill be reached, we won’t have enough information to know if function C was called from A or B. To solvethis problem, we would need to implement our own return in Perl, which would be exciting but tedious.Furthermore the call stack could be extremely large and that would take a lot of time to save current states.

Fourth, we restrict the body of an html page to not have < or > symbols unless they are tags. Thisprovides a way to keep track of where a tag starts and where it closes as well as let us differentiate betweenactual Wig code and html page generation code. With our new whatever token, this is accomplished. Also,in an input tag of html code, the name text received must be a string type. So, if we are given an integer,an error is thrown.

Fifth, we don’t allow two variables with the same identifier to exist within a parent-child set of scopes.

2

Page 4: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

We do, however, allow sibling scopes to contain variables with the same identifier. We also allow a variableand a function to be declared with the same identifier within a set of scopes. This is due to the fact we havename spaces, one each for functions, variables, schemas, html holes and html constants (which we will referto as categories henceforth) within a set of scopes. Please refer to section 3 for more elaboration on scoping,name spaces and symbol declaration rules.

Sixth, we make sure functions with non-void return types have a return statement. Moreover, if a non-void function only returns in a conditional block, then an error is thrown reminding the user that the functionmay not return.

1.3 Extensions

Our WIG extensions include single and multi-line comments as well as all the required tasks for tuple types- such as keep and remove with the single and many variable variations and join. We have also extendedbinary operations such as addition to include strings. The following is a tabled view of all operation supportof the RJFWig compiler regarding strings.

operation left node right node result+ string string string+ string integer string+ integer string string

<,>,<=,>=,==,!= string string booleanTable 1: RJFWig support for string operations

Suppose we have variables string s1 = foo, string s2 = bar and int i = 3. The operations work as follows:s1 + s2 = foobar, s1 + i = foo3 and i + s2 = 3bar. Hence, any addition operation involving string operandsis basic string concatenation. If the addition involves a string and an integer (it must operate on at leastone string), the integer’s string representation is concatenated to the given string operand. For the booleanoperators on strings, we must clarify how our target language handles these operations. In Perl, strings arecompared lexicographically (dictionary ordering). For example, suppose we had two strings a and aa. Then,a is less than aa. But we must be careful here as A is less than a. Even more caution is required whendealing with number strings. Now, the string 4 is greater than 31. We trust that the user knows exactlywhat he/she is doing when comparing strings.

We have also allowed the user to declare empty tuples, i.e. tuple { }. Though there is no need for thissince the use of empty tuples is limited, we felt mathematically inclined to include the empty set (as tuplescan be regarded as sets). Moreover, we have allowed users to initialize multiple variables at the same time.For example, one can say int a = b = c = 3; or tuple d = e = f = g = {. . . };.

1.4 Implementation Status

We have implemented all of the features proposed in this report and they have been tested with variousexamples and benchmarks provided through the COMP-520 website. For thoroughness, we tested againstprevious compilers (specifically lkwig since the feature set supported by this compiler is very similar to ours).Thus far, all examples compile like a breeze.

2 Parsing and Abstract Syntax Trees

2.1 The Grammar

Here is the exact wiggrammar.scc file that is used as input to SableCC. Keep in mind that we are usingversion 3.

Package wig;

3

Page 5: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

Helpers

letter = [[’a’ .. ’z’]+[’A’ .. ’Z’]];

digit = [’0’ .. ’9’];

any = [0x0 .. 0xfffff];

linechar = [0x0 .. 0x09]|[0x0b .. 0x0c]|[0x0e .. 0xffff];

lf = 0x0a;

cr = 0x0d;

line_terminator = lf | cr | cr lf;

nocomp = [[any - ’<’] - ’>’];

not_star = [any - ’*’];

not_star_slash = [not_star - ’/’];

States

wig_s,

html_s,

tag_s;

Tokens

{wig_s} service = ’service’;

{wig_s} const = ’const’;

{wig_s} html = ’html’;

{wig_s->html_s} html_tag_start = ’<html>’;

{html_s->wig_s} html_tag_end = ’</html>’;

{tag_s} input = ’input’;

{tag_s} select = ’select’;

{tag_s} type = ’type’;

{tag_s} name = ’name’;

{tag_s} text = ’"text"’;

{tag_s} radio = ’"radio"’;

{wig_s} schema = ’schema’;

{wig_s} session = ’session’;

{wig_s} show = ’show’;

{wig_s} exit = ’exit’;

{wig_s} return = ’return’;

{wig_s} if = ’if’;

{wig_s} else = ’else’;

{wig_s} while = ’while’;

{wig_s} plug = ’plug’;

{wig_s} receive = ’receive’;

{wig_s} int = ’int’;

{wig_s} bool = ’bool’;

{wig_s} string = ’string’;

{wig_s} void = ’void’;

{wig_s} tuple = ’tuple’;

{wig_s} true = ’true’;

{wig_s} false = ’false’;

{wig_s} l_brace = ’{’;

{wig_s} r_brace = ’}’;

{wig_s,tag_s} assign = ’=’;

{wig_s} semicolon = ’;’;

{wig_s,html_s->tag_s} lt = ’<’;

{wig_s,tag_s->html_s} gt = ’>’;

4

Page 6: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

{wig_s,html_s->tag_s} lt_slash = ’</’;

{html_s->wig_s} lt_bracket = ’<[’;

{wig_s->html_s} gt_bracket = ’]>’;

{wig_s} l_par = ’(’;

{wig_s} r_par = ’)’;

{wig_s} l_bracket = ’[’;

{wig_s} r_bracket = ’]’;

{wig_s} comma = ’,’;

{wig_s} keep = ’\+’;

{wig_s} remove = ’\-’;

{wig_s} join = ’<<’;

{wig_s} eq = ’==’;

{wig_s} neq = ’!=’;

{wig_s} lteq = ’<=’;

{wig_s} gteq = ’>=’;

{wig_s} not = ’!’;

{wig_s} minus = ’-’;

{wig_s} plus = ’+’;

{wig_s} mult = ’*’;

{wig_s} div = ’/’;

{wig_s} mod = ’%’;

{wig_s} and = ’&&’;

{wig_s} or = ’||’;

{wig_s} dot = ’.’;

{wig_s, tag_s} newline = ’\n’;

{wig_s, tag_s} blank = 10 | 10 13 | 9 | ’ ’;

{wig_s} scomment = ’//’ ([[any - cr] - lf])* line_terminator;

{wig_s} mcomment = ’/*’ not_star* (’*’)+ (not_star_slash not_star* (’*’)+)* ’/’;

{wig_s, tag_s} identifier = letter(letter|digit|’_’)*;// usual identifiers

{wig_s, tag_s} intconst = ’0’ |[’1’ .. ’9’](digit)*;

{wig_s,tag_s} stringconst = ’"’ ([any - ’"’]|’\"’)* ’"’; // usual string constants

{wig_s,html_s} meta = ’<!--’ linechar* ’-->’; // any string of the form <!-- ... -->

{html_s} whatever = nocomp(nocomp)*;

Ignored Tokens

blank,newline,scomment,mcomment;

Productions

service =

T.service l_brace P.html+ P.schema* variable* function* P.session+ r_brace

{-> New service([P.html],[P.schema],[variable],[function],[P.session])};

html =

const T.html identifier assign html_tag_start htmlbody* html_tag_end semicolon

{-> New html(identifier,[htmlbody])};

htmlbody =

{tag_start} lt identifier attribute* gt {-> New htmlbody.tag_start(identifier,

[attribute.attr])} |

{tag_end} lt_slash identifier gt {-> New htmlbody.tag_end(identifier)}|

{hole} lt_bracket identifier gt_bracket {-> New htmlbody.hole(identifier)} |

{whatever} whatever {-> New htmlbody.whatever(whatever)} |

{meta} meta {-> New htmlbody.meta(meta)} |

5

Page 7: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

{input} lt T.input inputattr+ gt {-> New htmlbody.input([inputattr])} |

{select} lt [select_tag]:select inputattr+ [first_gt]:gt htmlbody* lt_slash select

[second_gt]:gt {-> New htmlbody.select([inputattr],[htmlbody])};

inputattr =

{name} T.name T.assign attr {-> New inputattr.name(attr)} |

{type} T.type T.assign inputtype {-> New inputattr.type(inputtype)} |

{attribute} attribute {-> New inputattr.attribute(attribute.attr)};

inputtype =

{text} text |

{radio} radio;

attribute {-> attr} =

{attr} [attrib]:attr {-> attrib.attr} |

{assign} [left_attr]:attr assign [right_attr]:attr

{-> New attr.assign(left_attr.attr,right_attr.attr)};

attr =

{id} identifier |

{str} stringconst |

{int} intconst;

schema =

T.schema identifier l_brace [flds]:field* r_brace

{-> New schema(identifier, [flds.field]) };

field =

simpletype identifier semicolon {-> New field(simpletype.type,identifier) };

variable {-> variable} =

P.type identifiers semicolon

{-> New variable(P.type.type,[identifiers.identifier])};

identifiers {-> identifier*}=

{one} identifier {-> [identifier]} |

{many} identifiers comma identifier {-> [identifiers.identifier,identifier] };

simpletype {-> P.type} =

{int} int {-> New type.int(int)}|

{bool} bool {-> New type.bool(bool)}|

{string} string {-> New type.string(string)}|

{void} void {-> New type.void(void)};

type {-> P.type} =

{simple} simpletype {-> simpletype.type}|

{tuple} tuple identifier {-> New type.tuple(identifier)};

function =

P.type identifier l_par arguments? r_par compoundstm

{-> New function(P.type.type, identifier,[arguments.argument],compoundstm)};

arguments {-> argument*} =

6

Page 8: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

{one} argument {-> [argument]} |

{many} [list]:arguments comma argument {-> [list.argument, argument] };

argument =

P.type identifier;

session =

T.session identifier l_par r_par compoundstm

{-> New session(identifier, compoundstm)} ;

stm {-> stm}=

{no} semicolon {-> New stm.nostm() } |

{show} show document P.receive? semicolon {-> New stm.show(document,P.receive)}|

{exit} exit document semicolon {-> New stm.exit(document)} |

{return} return semicolon {-> New stm.returnvoid()} |

{retexp} return exp semicolon {-> New stm.returnexp(exp)} |

{if} if l_par exp r_par stm {-> New stm.if(exp,stm)} |

{ifelse} if l_par exp r_par [then_stm]:stm_no_short_if else [else_stm]:stm

{-> New stm.ifelse(exp,then_stm.stm,else_stm.stm)} |

{while} while l_par [condition]:exp r_par [actions]:stm

{-> New stm.while(condition,actions)} |

{comp} compoundstm {-> New stm.comp(compoundstm)} |

{exp} exp semicolon {-> New stm.exp(exp)};

stm_no_short_if {-> stm}=

{no} semicolon {-> New stm.nostm() } |

{show} show document P.receive? semicolon {-> New stm.show(document,P.receive)} |

{exit} exit document semicolon {-> New stm.exit(document)} |

{return} return semicolon {-> New stm.returnvoid()} |

{retexp} return exp semicolon {-> New stm.returnexp(exp)} |

{ifelse} if l_par exp r_par [then_stm]:stm_no_short_if else [else_stm]:stm_no_short_if

{-> New stm.ifelse(exp,then_stm.stm,else_stm.stm)} |

{while} while l_par [condition]:exp r_par [actions]:stm_no_short_if

{-> New stm.while(condition,actions.stm)} |

{comp} compoundstm {-> New stm.comp(compoundstm)} |

{exp} exp semicolon {-> New stm.exp(exp)};

document =

{id} identifier {-> New document(identifier, [] )} |

{plug} T.plug identifier l_bracket plugs r_bracket

{-> New document(identifier,[plugs.plug])};

receive =

T.receive l_bracket inputs r_bracket {-> New receive([inputs.input])};

compoundstm =

l_brace variable* stm* r_brace {-> New compoundstm(l_brace,[variable],[stm],r_brace)};

plugs {-> P.plug*} =

{one} P.plug {-> [P.plug]} |

{many} [first]:P.plugs comma [last]:P.plug {-> [first.plug,last.plug]};

plug {-> P.plug} =

7

Page 9: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

identifier assign exp {-> New plug(identifier,exp)};

inputs {-> P.input*} =

{one} P.input {-> [P.input]}|

{many} [first]:P.inputs comma [last]:P.input {-> [first.input,last.input]};

input {-> P.input} =

lvalue assign identifier {-> New input(lvalue.exp,identifier)};

exp {-> exp} =

{assign} lvalue assign or_exp {-> New exp.assign(lvalue.exp,or_exp.exp)} |

{default} or_exp {-> or_exp.exp} ;

or_exp {-> exp} =

{or} [left]:or_exp or [right]:and_exp {-> New exp.or(left.exp,right.exp)} |

{default} and_exp {-> and_exp.exp};

and_exp {-> exp} =

{and} [left]:and_exp and [right]:cmp_exp {-> New exp.and(left.exp, right.exp) } |

{default} cmp_exp {-> cmp_exp.exp};

cmp_exp {-> exp} =

{comparison} [left]:add_exp [op]:cmp_op [right]:add_exp

{-> New exp.comparison(left.exp,op.cmp_op,right.exp)} |

{default} add_exp {-> add_exp.exp};

cmp_op {-> P.cmp_op} =

{eq} eq {-> New cmp_op.eq(eq)} |

{neq} neq {-> New cmp_op.neq(neq)} |

{lt} lt {-> New cmp_op.lt(lt)} |

{gt} gt {-> New cmp_op.gt(gt)} |

{gteq} gteq {-> New cmp_op.gteq(gteq)} |

{lteq} lteq {-> New cmp_op.lteq(lteq)};

add_exp {-> exp} =

{plus} [left]:add_exp plus [right]:mult_exp {-> New exp.plus(left.exp,right.exp)} |

{minus} [left]:add_exp minus [right]:mult_exp {-> New exp.minus(left.exp,right.exp)} |

{default} mult_exp {-> mult_exp.exp};

mult_exp {-> exp} =

{mult} [left]:mult_exp mult [right]:join_exp {-> New exp.mult(left.exp,right.exp)} |

{div} [left]:mult_exp div [right]:join_exp {-> New exp.div(left.exp,right.exp)} |

{mod} [left]:mult_exp mod [right]:join_exp {-> New exp.plus(left.exp,right.exp)} |

{default} join_exp {-> join_exp.exp};

join_exp {-> exp} =

{join} [left]:tuple_exp join [right]:join_exp {-> New exp.join(left.exp,right.exp)} |

{default} tuple_exp {-> tuple_exp.exp };

tuple_exp {-> exp} =

{keep} tuple_exp keep identifier

{-> New exp.keep(tuple_exp.exp, [identifier])} |

8

Page 10: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

{remove} tuple_exp remove identifier

{-> New exp.remove(tuple_exp.exp, [identifier])} |

{keep_many} tuple_exp keep l_par identifiers r_par

{-> New exp.keep(tuple_exp.exp, [identifiers.identifier])} |

{remove_many} tuple_exp remove l_par identifiers r_par

{-> New exp.remove(tuple_exp.exp, [identifiers.identifier])} |

{default} unary_exp {-> unary_exp.exp};

unary_exp {-> exp} =

{not} not base_exp {-> New exp.not(base_exp.exp)} |

{neg} minus base_exp {-> New exp.neg(base_exp.exp)} |

{default} base_exp {-> base_exp.exp};

base_exp {-> exp} =

{lvalue} lvalue {-> lvalue.exp} |

{call} identifier l_par exps? r_par {-> New exp.call(identifier, [exps.exp])} |

{int} intconst {-> New exp.int(intconst)} |

{true} true {-> New exp.true(true) }|

{false} false {-> New exp.false(false)} |

{string} stringconst {-> New exp.string(stringconst) } |

{tuple} tuple l_brace fieldvalues? r_brace {-> New exp.tuple([fieldvalues.exp])}|

{paren} l_par exp r_par {-> New exp.paren(exp.exp) };

exps {-> exp*} =

{one} [arg]:exp {-> [arg.exp]} |

{many} exps comma [last]:exp {-> [exps.exp,last.exp]};

lvalue {-> exp}=

{simple} identifier {-> New exp.lvalues(identifier) } |

{qualified} [left]:identifier dot [right]:identifier {-> New exp.lvalueq(left,right) };

fieldvalues {-> exp*} =

{one} [arg]:fieldvalue {-> [arg.exp]} |

{many} [arg]:fieldvalues comma [last]:fieldvalue {-> [arg.exp,last.exp] };

fieldvalue {-> exp} =

identifier assign [rvalue]:exp {-> New exp.fieldvalue(identifier, rvalue.exp)};

Abstract Syntax Tree

service =

[html]:P.html+ [schema]:P.schema* [vars]:variable* [funcs]:function* [sessions]:P.session*;

html =

[id]:identifier [html]:htmlbody*;

htmlbody =

{tag_start} [id]:identifier [attribute]:attr* |

{tag_end} [id]:identifier |

{hole} [id]:identifier |

9

Page 11: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

{whatever} whatever |

{meta} meta |

{input} inputattr+ |

{select} [attribute]:inputattr+ [html]:htmlbody*;

inputattr =

{name} [attribute]:attr |

{type} [type]:inputtype |

{attribute} attr;

inputtype =

{text} text |

{radio} radio;

schema =

[id]:identifier [fields]:field*;

attr =

{id} [id]:identifier |

{str} [string]:stringconst |

{int} [int]:intconst |

{assign} [l]:attr [r]:attr;

field =

[type]:P.type [id]:identifier;

function =

[type]:P.type [id]:identifier [args]:argument* [statements]:compoundstm;

argument =

[type]:P.type [id]:identifier;

session =

[id]:identifier [statements]:compoundstm;

compoundstm =

[lbrace]:l_brace [l]:variable* [r]:stm* [rbrace]:r_brace;

variable =

[type]:P.type [id]:identifier*;

document =

[l]:identifier [r]:P.plug*;

receive =

P.input*;

type =

{int} int |

{bool} bool |

{string} string |

{void} void |

10

Page 12: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

{tuple} [schemaname]:identifier;

plug =

[l]:identifier [r]:exp;

input =

[l]:exp [r]:identifier;

stm =

{nostm} |

{show} [l]:document [r]:P.receive? |

{exit} document |

{returnvoid} |

{returnexp} exp |

{if} [eval]:exp [then_stm]:stm |

{ifelse} [eval]:exp [then_stm]:stm [else_stm]:stm |

{while} [eval]:exp [stm]:stm |

{comp} compoundstm |

{exp} exp;

cmp_op =

{eq} [op]:eq |

{neq} [op]:neq |

{lt} [op]:lt |

{gt} [op]:gt |

{lteq} [op]:lteq |

{gteq} [op]:gteq ;

exp =

{assign} [l]:exp [r]:exp |

{or} [l]:exp [r]:exp |

{and} [l]:exp [r]:exp |

{plus} [l]:exp [r]:exp |

{minus} [l]:exp [r]:exp |

{mult} [l]:exp [r]:exp |

{div} [l]:exp [r]:exp |

{mod} [l]:exp [r]:exp |

{comparison} [l]:exp [op]:P.cmp_op [r]:exp |

{keep} [l]:exp [r]:identifier* |

{remove} [l]:exp [r]:identifier* |

{not} [l]:exp |

{neg} [l]:exp |

{call} [funcname]:identifier [args]:exp* |

{int} intconst |

{true} [l]:true |

{false} [l]:false |

{string} stringconst |

{tuple} [list]:exp* |

{paren} [l]:exp |

{fieldvalue} [l]:identifier [r]:exp |

{lvalues} identifier |

{lvalueq} [l]:identifier [r]:identifier |

{join} [l]:exp [r]:exp ;

11

Page 13: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

2.2 Using the flex or SableCC Tool

We used the SableCC tool so there was not much that needed to be done on our part. However, we weregrateful for SableCC keeping track of the line and position of tokens as it greatly eased the reporting oferrors, warnings and code-related output.

From the grammar output above, one of the most drastic changes was that of states. We do this so thatwe can keep track of commands that alter the state. The three states include an html state, the portionwhere all the html pages are declared; a tag state (which is a subset of the html state), the portion of theinput between html tags; and finally a wig state, the actual Wig code of sessions, functions, services, etc...A problem arose when we added the whatever token. Since there is a longest common match rule used whenmatching input to a particular token, the entire input was being tokenized as whatever. Once we added thestates, however, all was resolved and certain input was mapped to certain tokens.

2.3 Using the bison or SableCC Tool

We used the SableCC tool so there was not much that needed to be done on our part. The most importantparsing implementation included the generation of a proper abstract syntax tree, so that the generated parserwould accept the grammar. This is discussed in great detail in the following section.

2.4 Abstract Syntax Trees

Our abstract syntax tree was constructed directly from the grammar file using the -> New command given bySableCC version 3. The concrete syntax tree has many unuseful nodes that need not be there. For example,if we were given the expression a + (b * c), the concrete syntax tree would include many parentheses. Forthe above expression, it would look like (a + (b * c)). This adds extra space for storing the tree as well asa lot of extra time for traversing it. Moreover, if we know that an add node (or a multiply node) has a leftchild and a right child with the plus (or star) operator in the middle, we can just store these values. For theabove example, this would be a + b * c for the above expression. So, this is exactly what is modified in ourconcrete syntax tree.

2.5 Desugaring

Most of our syntactic sugaring has already been discussed. Our ease of string concatenation with the additionoperation, the fact that short statements are allowed yet changed at compile time, the allowance of emptytuples and multiple assignment gives the user a bit more freedom than if these features weren’t allowed.

2.6 Weeding

Our weeding stage detects all of our restrictions listed in section 1.2. Though we don’t actually weed outthese restrictions, the detection will throw errors, which in turn stops compilation.

Actual weeding, also done in the weeding stage, includes throwing away unreachable code (for example,after a return or exit instruction). Since Perl doesn’t support short if, else and while statements, if we aregiven a short statement, we transform it into a compound statement block. This is much more desired thanrestricting the user to no short statements. For example, the following would be a scenario of this situationwhere the left-hand side would be weeded out and replaced by the right-hand side.

if (true) x = 1; -> if (true) {x = 1};

2.7 Testing

This phase is tested and does work. We built random Wig files and purposely put code that would beweeded out. We have tried code after return and exit statements, short if statements, empty tuples, multiple

12

Page 14: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

assignments, the whole bit. With our very Pretty Printer, we analyzed the output (which was the resultabstract syntax tree) to see that all that was desired was actually output. There were no operations afterreturn and exit statements in our target code, short if statements were converted to compound statementblocks and no errors were thrown when coming across an empty tuple or multiple assignment. The followingis a snippet of the resulting code of this phase, the output from the pretty printer.

show plug TupResult [result = "&lt" + t1.s + "&gt" ];

count = 0 ;

while (true)

{

show Prompt receive [infromuser= tbox];

if (infromuser == 0 )

{

if (globalinc < count)

{

globalinc = count;

exit plug ExitRecord [record = count];

}

exit Exit ;

}

else

{

count = increment (count, infromuser);

}

}

3 Symbol Tables

3.1 Algorithm

We first describe the algorithm so that scoping rules can be easily shown. Since we are using SableCC,we are blessed with Java objects. We have one main object, the Symbol object. Then there are the twomost important objects, the SymbolVariable and SymbolTable objects, both of which extend Symbol. Wekeep track of scopes via symbol tables i.e. every scope is given a symbol table object, implying there isa one-to-one relation between scopes and symbol tables. Every variable is given a symbol object. Hence,symbol tables store symbols (of the current scope) as well as other symbol tables depicting children scope.Thus, every symbol table has at least two hash maps (some tables may have more for convenience). So, webuild our symbol table as follows.

We start with the parent scope, the service scope. This is the base case so it doesn’t matter if this scopehas no identifier (which it never does, based on the WIG language). We construct a new symbol table andassign it to service. Now, we go through the code and every time we encounter a compound statement,function, html tag, schema declaration or session, we construct a new symbol table, store it into the currentscope’s symbol table, set the parent scope of the new symbol table to the current scope, step into the newscope and set the new scope as the current scope. Every time we leave a scope, we roll back to the currentscope’s parent scope.

Every time we encounter a symbol, for example an int, string, boolean or tuple, we first verify that theidentifier for the symbol is not already used in the current symbol table or any of the parent symbol tables.If there is already an occurrence of this identifier, an error is thrown. If not, we construct a new symbolobject, assign the name, type and if the variable has been initialized yet and store this in the current scope’ssymbol table. To determine if the variable is initialized, we first check if the variable is on the left-handside of an assignment, if so, then it is currently being initialized. If not, then it is just a declaration. Ifwe encounter a variable on the right-hand side of an assignment and it has not been initialized, an error is

13

Page 15: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

thrown.

We did encounter problems when dealing with scopes of compound statements since these entities don’thave explicit identifiers. Hence, we give them ordered numerical identifiers for the sheer purpose of identifyingtheir symbol tables.

3.2 Scope Rules

The first thing to note is that we only go up the parent scopes to verify if an identifier has already beenused. In consequence, any sibling scope of the current scope may declare a variable with the same identifieras the current one in question. For example, if there is a global variable int g declared in the service, onecannot declare a local variable with the same name in any of the sessions (since the parent scope of a givensession is the service scope). Moreover, if there is some session with a local variable string l, then any othersession (or even all the other sessions) may declare a variable named string l.

Finally, we allow different categories that require an identifier to have the same identifier name. This isdue to the fact that we have declared name spaces for these categories. Within a parent-child set of scopes,there is a name space for functions, variables, schemas, html holes and html constants. Within a namespace, the same identifier may not exist whereas across name spaces, it might. For example, if there is afunction identifier id used, users may not declare another function with the same identifier. However, theymay declare a variable, schema, html hole and/or html constant with the same identifier id.

3.3 Testing

This aspect of the RJFWig compiler has been fully and thoroughly tested. This was verified by printing outstatements every time we step into or rollback from a scope, when a new symbol is encountered as well asconcrete error checking when identifiers with the same name were declared. Here is some example outputfor this phase.

( SymbolSession ) [66,9] start {

[66,17] {

( SymbolVariableTuple ) [69,15] str s2 {

( SymbolVariableInt ) [67,13] infromuser

( SymbolVariableTuple ) [70,11] bi bitup {

( SymbolVariableTuple ) [68,17] Scm1shot t12 {

( SymbolVariableTuple ) [69,12] str s1 {

( SymbolVariableInt ) [67,6] count

[80,14] {

[83,24] {

[85,27] {} [88,4]

} [90,3]

[91,8] {} [93,3]

} [94,2]

} [96,1]

}

14

Page 16: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

4 Type Checking

4.1 Types

Our WIG specifications support the four primitive types of variables: bool, int, string and tuple. Forfunctions, we support the above as well as void types. Within tuples, we may include fields of any typeexcept void and tuple.

4.2 Type Rules & Algorithm

Type rules kick in when we encounter an assignment, comparison, function call or when we receive or pluginput or output from or to the user, respectively (damn that was good). So, once we reach an assignmentor comparison of equality (i.e. == or !=), we obtain the types for both the left- and right-hand sides. Thetypes are stored in the symbols respective object. If these types are the same, we allow the assignmentor comparison, otherwise we throw an error. The allowed types don’t include void. Any other type ofcomparison (i.e. <, >, <= or >=) is allowed only on string and int types. So, we make sure that both sidesof the comparison are the same and that they are of type string or int. When a function call is encountered,two checks are done. First we verify that the function actually returns the same type as it is declared to andwe also allow void types for this check. Second, we verify if all the function arguments are the correct type,where void types aren’t allowed. If a receive or plug is reached, we just call the assignment type checkingrule on each assignment of the receive or plug block.

4.3 Testing

This phase has been tested and is working. Once again, we use informative print statements when a typechecking rule is invoked. Here is a snippet of the output from the type checker.

Type Checking (increment<--->int) [58,9] ...OK

Type Checking (boolinput<--->void) [58,9] ...OK

Type Checking (tuple) [72,2] t12...OK

Type Checking (tuple) [73,2] t1...OK

Type Checking (tuple) [74,2] t1...OK

Type Checking (int) [79,2] count...OK

Type Checking (while<--->bool) [79,2] ...OK

Checking comparison at [83,7]...OK

Checking comparison at [85,8]...OK

Type Checking (if<--->bool) [85,8] ...OK

Type Checking (int) [86,5] globalinc...OK

Type Checking (int) [92,4] count...OK

5 Tuples

5.1 Tuple Operations and Rules

Tuple operations include keep, remove and join where the first two operations take a tuple and either a fieldor a set of fields and the third operation takes two tuples. For the first two operations, we verify if the givenfield(s) exist within the given tuple. If not, an error is thrown. If so, a tuple with (keep) or without (remove)the given fields is returned. For the third operation, our convention is from right to left. We will show thiswith an example. Suppose we two tuples t1 and t2 and the instruction t1 join t2. There are two possibilitieshere. If t1 and t2 have a field with the same name, the value of the field with the same name in the resultingtuple will be the value of the field from the tuple on the right side of the operation (tuple t2 in this example).If t1 and t2 do not have any fields with the same name, then the resulting tuple will have all the fields from

15

Page 17: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

both the tuples. The following is a table with example operations on tuples and their results. All variablesbeginning with a b, i or s are bools, ints or strings respectively.

left node operation right node result{b=true, i=5} keep b {b=true}

{b=true, i=5, s=abab} keep {b, s} {b=true, s=abab}{b=true, i=5, s=abab} remove i {b=true, s=abab}{b=true, i=5, s=abab} remove {b, i} {s=abab}{b=true, i=5, s=abab} join {s=xyxy} {b=true, i=5, s=xyxy}{b=true, i=5, s=abab} join {s1=xyxy} {b=true, i=5, s=abab, s1=xyxy}

Table 2: RJFWig operations on tuples

5.2 Type Checking Tuple Operations

Type checking tuples was a considerably harder task and required a lot of design decisions. First, let usdiscuss tuple assignment. Suppose we have the tuples defined in the previous section. For the instruction t1= t2 to be valid, the types of both tuples must be the same. As a design decision, we can only assign tuplesto each other if their fields have the same type and are in the same order, regardless of the field names.Thus, the type of a tuple is a list of the types of its fields. For example, if t1 = tuple{bool b, int i}, thenthe type of t1 is {bool, int}. This is what we mean by type when referring to tuples. Now, once the rulesfor keep, remove and join have been applied, the resulting intermediate tuple is assigned to a declared tuple,where the assignment rules are applied. For example, the instruction for a join would look like

t3 = t1 << t2

Joining t1 and t2 would use the rule concerning names discussed in the previous section. Once the result iscomputed, it is assigned to t3 where we would use the rule concerning types discussed in this section.

6 Resource Computation

Due to the nature of our target language, we didn’t need to worry about resource computation. Perl’sinterpreter is dynamic and allocates resources on-the-fly as they are needed.

7 Code Generation

7.1 Strategy

Generating code for a service is very similar to running the very Pretty Printer, but instead of outputtingWig specific code, we output code following the format of our target language, Perl. One of the mainchallenges was persisting the values of global variables across different clients using the same service. Also,when a show statement is used, we need to store the current context, that is, the program counter and alllocal variables found in the session, in order to resume execution when the user has submitted the form.To correctly support these features, we needed to implement a file locking mechanism to prevent concurrentaccess to globals. Also, a session key must be attributed for each local context being saved. This allows usto make sure that local context is unique to a particular session. There are generic helper functions thatare created for every outputted Perl script that allow us to seamlessly implement these features. These arealways generated at the beginning of a file. Please look at the generated sample code in this section.

7.2 Code Templates & Algorithm

Our code template recursively traverses the abstract syntax tree and produces valid output adhering to thePerl syntax. When dealing with variables, we check whether the variable is a global, a tuple or both. In

16

Page 18: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

turn, we call a helper function that appropriately deals with the variable. For example, when we encounter aglobal variable on the left-hand side of an assignment statement, we call a helper function named WriteGlobalthat writes the value to an external file. There are such code templates for assigning tuples, getting a valueof a tuple’s field, etc. . .

7.3 Runtime System

We issue a menu for the lazy user who didn’t want to specify a specific session. This menu lists all thesession names that are available in the current service. Moreover, the runtime system will create files ondemand when local contexts and global variables need to be stored. This system also assigns unique sessionkeys when saving to file, provided that a key has not been assigned to the current session. As a convenience,the runtime system provides a Go! button which allows the user to navigate easily through each session.

7.4 Sample Code

Here is the complete code for our hangman01.wig example, written as Perl output in a file called hang-man01.pl.

#!/usr/bin/perl

#Compiled by RJFWig

use strict ’refs’,’subs’;

no strict ’vars’;

use CGI qw(:standard);

use CGI::Carp qw(warningsToBrowser fatalsToBrowser);

use DB_File;

use integer;

use Data::Dumper;

use File::Basename;

use Fcntl qw(:flock);

#The following hash will contain all the global variables that

#will be accessed during the session.

%WIG_GLOBALHASH;

#HTML header tag output at every page

$starthtml = qq{<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US=" xml:lang="en-US">\n};

#SESSIONS IN CURRENT WIG DOCUMENT

%WIG_SESSIONS = (

Play => 1

);

# Sets up some global variables, parses session

# and key from query_string and calls the session

# if the sessionid is valid

$WIG_CGI = CGI::new();

$WIG_QS = $ENV{’QUERY_STRING’};

17

Page 19: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

($WIG_SESSID, $WIG_KEY) = $WIG_QS =~ /([A-Za-z_]\w*)\$?(\w*)/;

$WIG_REFERER = referer;

$WIG_SCRIPTNAME = script_name;

$WIG_LOCKTIMEOUT = 20;

$WIG_GLOBALFILE = basename($WIG_SCRIPTNAME) . ’.globals.db’;

if (!$WIG_SESSID || !exists($WIG_SESSIONS{$WIG_SESSID})) {

if (!exists($WIG_SESSIONS{$WIG_SESSID})) {

print header;

print start_html(’BAD SESSION NAME’);

print ’You did not enter a valid session name.<br>’;

print ’Try one of these:<br>’;

WIG_list_sessions();

print end_html;

exit(0);

}

}

$WIG_ACTION = ’http://’ . $ENV{HTTP_HOST} . $WIG_SCRIPTNAME . ’?’ . $WIG_SESSID .

’$’ . $WIG_KEY;

eval(’SESSION_’ . $WIG_SESSID . ’()’);

#WIG FUNCTIONS

sub mylock {

for(my $i=0; $i<$WIG_LOCKTIMEOUT; $i++) {

if (-e "$WIG_GLOBALFILE.lock") {

sleep 0.5;

} else {

last;

}

}

if (-e "$WIG_GLOBALFILE.lock") {

unlink ("$WIG_GLOBALFILE.lock")

or confess "couldn’t remove $WIG_GLOBALFILE.lock";

}

open GLOBALSLOCK, ">$WIG_GLOBALFILE.lock"

or confess "couldn’t open $WIG_GLOBALFILE.lock";

tie %WIG_GLOBALHASH, ’DB_File’, $WIG_GLOBALFILE, O_CREAT | O_RDWR, 0644;

}

sub myunlock {

untie %WIG_GLOBALHASH;

close GLOBALSLOCK or confess "couldn’t close $WIG_GLOBALFILE.lock\n";

unlink ("$WIG_GLOBALFILE.lock") or confess "couldn’t delete $WIG_GLOBALFILE.lock\n";

}

# tuple-specific functions

sub WIG_writeglobalTUP {

my ($tupname, $tup) = @_;

my %tuple = %$tup;

my $d = Data::Dumper->new([\%tuple]);

my $str = $d->Dumpxs();

mylock();

$WIG_GLOBALHASH{$tupname} = $str;

18

Page 20: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

myunlock();

return \%tuple;

}

sub WIG_writeglobalTUPFIELD {

my ($tupname, $fieldname, $newvalue) = @_;

mylock();

eval $WIG_GLOBALHASH{$tupname};

$$VAR1{$fieldname} = $newvalue;

my $d = Data::Dumper->new([$VAR1]);

my $str = $d->Dumpxs();

$WIG_GLOBALHASH{$tupname} = $str;

myunlock();

$newvalue;

}

sub WIG_readglobalTUPFIELD {

my ($tupname, $fieldname) = @_;

mylock();

$tupstring = $WIG_GLOBALHASH{$tupname};

if (! $tupstring) {

$tupstring = ’$VAR1 = { };’;

}

myunlock();

eval($tupstring);

return $$VAR1{$fieldname};

}

sub WIG_readglobalTUP {

my $tupname = shift;

my $tupstring;

mylock();

$tupstring = $WIG_GLOBALHASH{$tupname};

if (! $tupstring) {

$tupstring = ’$VAR1 = { };’;

}

myunlock();

eval($tupstring);

return $VAR1;

}

sub WIG_tupcp {

my $tocopy = shift;

my %copy = %$tocopy;

return \%copy;

}

sub WIG_keep (%@) {

($tuple, $idents) = @_;

%tup = %$tuple;

foreach $key (keys %tup) {

delete $tup{$key} if !(grep /$key/, @$idents);

}

return \%tup;

19

Page 21: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

}

sub WIG_throw (%@) {

($tuple, $idlist) = @_;

%tup = %$tuple;

delete @tup{@$idlist} and \%tup;

return \%tup;

}

sub WIG_combine (%%) {

($tuple1, $tuple2) = @_;

(%tup1, %tup2) = (%$tuple1, %$tuple2);

foreach (keys %tup2) {

$tup1{$_} = $tup2{$_};

}

return \%tup1;

}

sub WIG_tuple_eq {

($tuple1, $tuple2) = @_;

foreach (keys %$tuple1, keys %$tuple2) {

if($$tuple1{$_} ne $$tuple2{$_}){

return 0;

}

}

return 1;

}

#Creates a copy of the tuple passed with

#renamed keys. The keys are renamed according

#to the 2nd arg.

sub WIG_tuple_rename (% %)

{

(my $tupref, $map) = @_;

my %tup = %$tupref;

foreach (keys %$map) {

$dest = $$map{$_};

$tup{$dest} = $tup{$_};

if ($_ ne $dest) {

delete $tup{$_};

}

}

return \%tup;

}

sub WIG_stringify {

my $bool = shift;

if($bool){

return ’true’;

}else{

return ’false’;

}

}

20

Page 22: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

sub WIG_writeglobalVAR {

my ($varname, $value) = @_;

mylock();

$WIG_GLOBALHASH{$varname} = $value;

myunlock();

$value;

}

sub WIG_readglobalVAR {

$varname = shift;

mylock();

my $value = $WIG_GLOBALHASH{$varname};

myunlock();

return $value;

}

sub WIG_dump_locals {

my $localdumper = shift;

open LOCALSFILE, qq{+>$localsfile} ||

die qq{Saving session: failed to open $localsfile};

print LOCALSFILE $localdumper->Dumpxs();

close LOCALSFILE;

unlink qq{$localsfile.lock};

}

sub WIG_list_sessions {

print ’<ul>’;

foreach $sess (sort keys(%WIG_SESSIONS)) {

print "<li><a href=\"http://",$ENV{HTTP_HOST},

$ENV{SCRIPT_NAME},’?’,"$sess\">",$sess,"</a></li>\n";

}

print ’</ul>’;

}

#Error Message for invalid Key

sub WIG_invalid_key {

print header;

print start_html(’INVALID KEY’);

print ’Your session key is not valid<br>’;

print ’Try one of the sessions below for a new key<br>’;

WIG_list_sessions();

print end_html;

exit(0);

}

#GENERATES "UNIQUE" SESSION KEY

sub WIG_keygenerator {

my @choosefrom = (’0’..’9’,’a’..’z’,’A’..’Z’);

for (my $i=0; $i<32; $i++) {

$WIG_KEY .= $choosefrom[int(rand(scalar(@choosefrom)))];

}

}

21

Page 23: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

sub WIG_validatesession {

$localsfile = basename($WIG_SCRIPTNAME) . ’?’ . $WIG_SESSID .

’$’ . $WIG_KEY;

if(!$WIG_KEY) {

do {

#The user doesn’t have a key yet, so we generate one for him

WIG_keygenerator();

#Allocates a filename for the locals. If that file is locked or

#already exists, a different key will be generated.

$localsfile = basename($WIG_SCRIPTNAME) . ’?’ . $WIG_SESSID .

’$’ . $WIG_KEY;

} while(-e qq{$localsfile.lock} or -e $localsfile);

$WIG_ACTION = ’http://’ . $ENV{HTTP_HOST} . $WIG_SCRIPTNAME . ’?’ . $WIG_SESSID .

’$’ . $WIG_KEY;

open LOCALSLOCK, qq{+>$localsfile.lock}

|| die qq{failed to open $localsfile.lock};

#Grab an exclusive lock on the file. The call LOCK_NB makes it

#nonblocking. If the locking fails then it means 2 new users

#grabbed the same generated key -- which is very unlikely.

flock LOCALSLOCK, LOCK_EX || die qq{failed to lock $localsfile.lock};

#Check if we can write to the locals file. Maybe the guy

#reached his quota. Or maybe the directory’s not writable.

open LOCALSFILE, qq{+>$localsfile} ||

die qq{Starting new session: failed to open $localsfile};

close LOCALSFILE;

} elsif(-e $localsfile) {

do {

#Give enough time for the nfs to update/refresh.

sleep 1;

} while(-e qq{$localsfile.lock});

open LOCALSLOCK, qq{+<$localsfile.lock} ||

die qq{failed to open $localsfile.lock};

flock LOCALSLOCK, LOCK_EX ||

die qq{failed to lock $localsfile.lock};

open LOCALSFILE, qq{+<$localsfile} ||

die qq{failed to open $localsfile};

@locals = <LOCALSFILE>;

close LOCALSFILE;

my $pc_str = shift @locals;

eval($pc_str);

eval qq{goto show_$pc;};

exit(-1);

} else {

#The user has a key but there’s no corresponding locals file.

goto &WIG_invalid_key;

}

}

22

Page 24: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

#########################

#INTERESTING CODE BEGINS#

#########################

sub HTML_game {

%plugs = @_;

my $body = ’

<body><form method="POST" action="~~FORM~~">

<h1>Hangman</h1>

The word is: <[g1]>-<[g2]>-<[g3]>-<[g4]>-<[g5]>-<[g6]>-<[g7]>-<[g8]>

<br>

Number of BAD guesses: <[numTries]> out of <[maxTries]>

<img src="http://www.cs.mcgill.ca/~rshaik1/hangman/<[numTries]>.JPG" >

<br>

Enter a lower-case letter for your guess:

<input name="letter" type="text" maxlength=1size=1/>

<~~GOBUTTON~~></form></body>

’;

foreach $hole (keys %plugs){

$body =~ s/<\[$hole\]>/$plugs{$hole}/g;

}

$body =~ s/<\[[\w]+\]>//g;

$body =~ s/<~~GOBUTTON~~>/$gobutton/g;

$gobutton = "";

$body =~ s/~~FORM~~/$WIG_ACTION/;

return header() . $starthtml . $body . end_html();

}

sub HTML_gameWon {

%plugs = @_;

my $body = ’

<body><form method="POST" action="~~FORM~~">

<h1>Hangman</h1>

The answer was: <[word]>

<br>

You won !!! Way to go playa!!!

<br>

<img src="http://www.cs.mcgill.ca/~rshaik1/hangman/<[numTries]>.JPG" >

<[numTries]>

<~~GOBUTTON~~></form></body>

’;

foreach $hole (keys %plugs){

$body =~ s/<\[$hole\]>/$plugs{$hole}/g;

}

$body =~ s/<\[[\w]+\]>//g;

$body =~ s/<~~GOBUTTON~~>/$gobutton/g;

$gobutton = "";

$body =~ s/~~FORM~~/$WIG_ACTION/;

return header() . $starthtml . $body . end_html();

}

sub HTML_gameLost {

23

Page 25: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

%plugs = @_;

my $body = ’

<body><form method="POST" action="~~FORM~~">

<h1>Hangman</h1>

The answer was: <[word]>

<br>

You lost !!! What up?!!!

<br>

<img src="http://www.cs.mcgill.ca/~rshaik1/hangman/<[numTries]>.JPG" >

<[numTries]>

<~~GOBUTTON~~></form></body>

’;

foreach $hole (keys %plugs){

$body =~ s/<\[$hole\]>/$plugs{$hole}/g;

}

$body =~ s/<\[[\w]+\]>//g;

$body =~ s/<~~GOBUTTON~~>/$gobutton/g;

$gobutton = "";

$body =~ s/~~FORM~~/$WIG_ACTION/;

return header() . $starthtml . $body . end_html();

}

sub SESSION_Play {

WIG_validatesession();

{

my $VAR_answer;

my $VAR_letter;

my $VAR_l1;

my $VAR_l2;

my $VAR_l3;

my $VAR_l4;

my $VAR_l5;

my $VAR_l6;

my $VAR_l7;

my $VAR_l8;

my $VAR_g1;

my $VAR_g2;

my $VAR_g3;

my $VAR_g4;

my $VAR_g5;

my $VAR_g6;

my $VAR_g7;

my $VAR_g8;

my $VAR_numTries;

my $VAR_maxTries;

my $VAR_gameOver;

my $VAR_goodGuess;

$VAR_answer = "compiler";

$VAR_l1 = "c";

$VAR_l2 = "o";

$VAR_l3 = "m";

$VAR_l4 = "p";

$VAR_l5 = "i";

24

Page 26: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

$VAR_l6 = "l";

$VAR_l7 = "e";

$VAR_l8 = "r";

$VAR_g1 = "_";

$VAR_g2 = "_";

$VAR_g3 = "_";

$VAR_g4 = "_";

$VAR_g5 = "_";

$VAR_g6 = "_";

$VAR_g7 = "_";

$VAR_g8 = "_";

$VAR_numTries = 0;

$VAR_maxTries = 6;

$VAR_gameOver = 0;

$VAR_goodGuess = 0;

while (!$VAR_gameOver)

{

$pc = 0;

local $gobutton = ’<br /><input type="submit" value="go" />’;

my $frozenbody = HTML_game(’g1’ => $VAR_g1, ’g2’ => $VAR_g2, ’g3’ =>

$VAR_g3, ’g4’ => $VAR_g4, ’g5’ => $VAR_g5, ’g6’ => $VAR_g6, ’g7’ =>

$VAR_g7, ’g8’ => $VAR_g8, ’numTries’ => $VAR_numTries, ’maxTries’ =>

$VAR_maxTries);

my $localdump = Data::Dumper->new([

$pc,

$frozenbody,

$VAR_g4,

$VAR_g3,

$VAR_l4,

$VAR_l5,

$VAR_l2,

$VAR_g5,

$VAR_answer,

$VAR_maxTries,

$VAR_l8,

$VAR_letter,

$VAR_g6,

$VAR_g1,

$VAR_l7,

$VAR_goodGuess,

$VAR_gameOver,

$VAR_numTries,

$VAR_g2,

$VAR_g7,

$VAR_g8,

$VAR_l6,

$VAR_l1,

$VAR_l3

],[’pc’,’frozenbody’, ’VAR_g4’, ’VAR_g3’, ’VAR_l4’, ’VAR_l5’,

’VAR_l2’, ’VAR_g5’, ’VAR_answer’, ’VAR_maxTries’, ’VAR_l8’,

’VAR_letter’, ’VAR_g6’, ’VAR_g1’, ’VAR_l7’, ’VAR_goodGuess’,

’VAR_gameOver’, ’VAR_numTries’, ’VAR_g2’, ’VAR_g7’, ’VAR_g8’,

’VAR_l6’, ’VAR_l1’, ’VAR_l3’]);

25

Page 27: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

WIG_dump_locals($localdump);

print $frozenbody;

return; #We will return

show_0:

foreach (@locals){

$mylocals .= $_;

}

eval($mylocals);

if(request_method() ne ’POST’) {

print $frozenbody;

exit(0); # terminated!

} else {

$VAR_letter = $WIG_CGI->param(’letter’);

}

if ($VAR_letter eq $VAR_l1)

{

$VAR_g1 = $VAR_l1;

$VAR_goodGuess = 1;

}

if ($VAR_letter eq $VAR_l2)

{

$VAR_g2 = $VAR_l2;

$VAR_goodGuess = 1;

}

if ($VAR_letter eq $VAR_l3)

{

$VAR_g3 = $VAR_l3;

$VAR_goodGuess = 1;

}

if ($VAR_letter eq $VAR_l4)

{

$VAR_g4 = $VAR_l4;

$VAR_goodGuess = 1;

}

if ($VAR_letter eq $VAR_l5)

{

$VAR_g5 = $VAR_l5;

$VAR_goodGuess = 1;

}

if ($VAR_letter eq $VAR_l6)

{

$VAR_g6 = $VAR_l6;

$VAR_goodGuess = 1;

}

if ($VAR_letter eq $VAR_l7)

{

$VAR_g7 = $VAR_l7;

$VAR_goodGuess = 1;

}

if ($VAR_letter eq $VAR_l8)

{

$VAR_g8 = $VAR_l8;

$VAR_goodGuess = 1;

26

Page 28: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

}

if ($VAR_goodGuess)

{

$VAR_goodGuess = 0;

}

else

{

$VAR_numTries = $VAR_numTries + 1;

}

if ($VAR_numTries == $VAR_maxTries)

{

local $gobutton = ’’;

print HTML_gameLost(’word’ => $VAR_answer, ’numTries’ => $VAR_numTries);

unlink $localsfile;

unlink qq{$localsfile.lock};

exit(0); #originates from an exit

}

if ($VAR_g1 eq $VAR_l1 and $VAR_g2 eq $VAR_l2 and $VAR_g3 eq $VAR_l3 and

$VAR_g4 eq $VAR_l4 and $VAR_g5 eq $VAR_l5 and $VAR_g6 eq $VAR_l6 and

$VAR_g7 eq $VAR_l7 and $VAR_g8 eq $VAR_l8)

{

local $gobutton = ’’;

print HTML_gameWon(’word’ => $VAR_answer, ’numTries’ => $VAR_numTries);

unlink $localsfile;

unlink qq{$localsfile.lock};

exit(0); #originates from an exit

}

}

local $gobutton = ’’;

print HTML_gameWon(’word’ => $VAR_answer);

unlink $localsfile;

unlink qq{$localsfile.lock};

exit(0); #originates from an exit

}

}

7.5 Testing

The above output is direct evidence that this compiler has been tested. Moreover, we have compiled andran almost all the available Wig programs, most of which are available at the demo site listed below.

8 Availability and Group Dynamics

8.1 Manual

Given a file written in the WIG language, just go to the parent directory of Main.class. The main class willmost likely be in a folder called wig/ (since wig is the package name). Now, you execute the command javawig.Main. Without any arguments, you will get the following usage output.

java wig.Main [flags] file

Will compile wig input file ’file’ to ’file.pl’.

27

Page 29: Wig Compiler Report - RJFWig › ~rshaik1 › papers › Compiler.pdf · Wig Compiler Report - RJFWig Report No. 2005-01 Jean-S ebastien L egar e F elix Martineau Reehan Shaikh fjlegar,

Possible flags are :

-t......................Show Timing Info.

-p filename.............Pretty prints the wig file to the

filename passed (’-’ for stdout).

-S......................Output Symbol Table.

-l......................Output Lexer tokens only. Do not generate parse tree.

-o filename.............Output generated code to the other file instead.

(put filename ’-’ to output to stdout)

-pwd absolutepath.......Set the current working directory.

-s......................Show lexer state changes (enables -l automatically).

-fc.....................Pop up a File chooser to select the file to compile.

If you press cancel, the file passed on the command line

will be taken instead.

Follow the instructions and get the desired result. Once you have compiled and generated a Perl scriptof your Wig program, just copy the script to your cgi-bin directory of your ∼/public html directory and goto your script web-page via Internet and have fun with your service.

8.2 Demo Site

The following URL has many examples of generated Perl scripts:

http://www.cs.mcgill.ca/∼jlegar/wig

8.3 Division of Group Duties

Every member worked on every part of the compiler, especially Felix, Jean-Sebastien and Reehan. In theend, we all went out for coffee and couldn’t stop talking about the PEEPHOLE contest. Cheers!!!

28