use typename
[prop.git] / prop-src / compiler.pcc
blob94814f86850341fd123ac832767967f38d055da7
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 //  The file implements the class Compiler and this is the main entry
4 //  point of the Prop -> C++ translator.
5 //
6 ///////////////////////////////////////////////////////////////////////////////
7 #include <iostream>
8 #include "ir.ph"
9 #include "ast.ph"
10 #include "type.h"
11 #include "compiler.h"
12 #include "options.h"
14 ///////////////////////////////////////////////////////////////////////////////
16 //  Constructor and destructor
18 ///////////////////////////////////////////////////////////////////////////////
19 Compiler:: Compiler(TyOpt opt, int embedded_tags) 
20    : DatatypeCompiler (opt,embedded_tags) {}
21 Compiler::~Compiler() {}
23 ///////////////////////////////////////////////////////////////////////////////
25 //  Emit header info
27 ///////////////////////////////////////////////////////////////////////////////
28 void Compiler::emit_header(const char * text, int n) { header.emit(text,n); }
29 void Compiler::emit_header_text() 
30 {  const char * header_text = header.text();
31    if (header_text) pr("%s",header_text); 
34 ///////////////////////////////////////////////////////////////////////////////
36 //  Additional printing method
38 ///////////////////////////////////////////////////////////////////////////////
39 va_list Compiler::printer(char fmt, va_list arg) 
40 {  match (fmt) 
41    {  'm': { MatchCompiler::gen(va_arg(arg,Match)); }
42    |  '&': { gen(va_arg(arg,Decls)); }
43    |  'D': { gen(va_arg(arg,Decl)); }
44    |   _ : { bug("undefined print format '%%%c'\n", (int)fmt); }
45    }
46    return arg;
49 ///////////////////////////////////////////////////////////////////////////////
51 //  Top level code generation method
53 ///////////////////////////////////////////////////////////////////////////////
54 void Compiler::generate(Decls ds)
55 {  
56    // generate the quark literals
57    if (quark_map.size() > 0)
58    {  pr ("%^%/"
59           "%^//  Quark literals"
60           "%^%/");
61       foreach_entry (e, quark_map)
62       {  Id name  = (Id)quark_map.key(e);
63          Id quark = (Id)quark_map.value(e);
64          pr ("%^static const Quark %s(%s);\n", quark, name);
65       }
66    }
68    // now generate the main program.
69    gen(ds);
71    // finally, generate any outstanding rewriters
72    gen_rewriters();
74    // if the visualization is on then print GDL
75    if (options.visualization) print_definitions_as_GDL();
78 ///////////////////////////////////////////////////////////////////////////////
80 //  Method to generate a list of declarations.
82 ///////////////////////////////////////////////////////////////////////////////
83 void Compiler::gen(Decls ds) 
84 {  Bool line_prefix = true;
85    Bool line_suffix = true;
86    match while (ds)
87    {  #[one ... rest]:  
88       {  match (one)
89          {  TYPEEXPdecl _: { line_suffix = line_prefix; line_prefix = false; }
90          |  _:             { line_suffix = line_prefix; line_prefix = true; }
91          }
92          gen(one,line_prefix,line_suffix);
93          ds = rest;
94       }
95    }
98 ///////////////////////////////////////////////////////////////////////////////
100 //  Method to generate one declaration.
102 ///////////////////////////////////////////////////////////////////////////////
103 void Compiler::gen(Decl d, Bool line_prefix, Bool line_suffix)
104 {  match (d) of
105       NOdecl:                           { /* skip */ }
106    |  OPAQUEdecl d:                     { pr ("%C",d); }
107    |  DATATYPEdecl(d,v,l,t):            { gen_datatype(d,v,l,t); }
108    |  INSTANTIATEdecl(e,t):             { instantiate_datatypes(e,t);}
109    |  REWRITEdecl (id,indices,rules):   { gen_rewrite(id, indices, rules); }
110    |  REWRITINGdecl (a,b,c,d,e,f):      { gen_rewriting(a,b,c,d,e,f); }
111    |  FUNdecl (fundefs):                { gen_fun_def(fundefs); }
112    |  MATCHdecl (exps, rules, opt, ty): { gen_match_stmt(exps,rules,opt,ty); }
113    |  SYNTAXdecl(id, gram_exp):         { gen_parser(id,gram_exp); }
114    |  ATTRIBUTEGRAMMARdecl(id, e):      { gen_attribute_grammar(id,e); }
115    |  INFERENCEdecl (id, rules):        { gen_inference_rules(id, rules); }
116    |  SETLSTMTdecl stmt:                { gen_setl(stmt); }
117    |  SETLDEFdecl def:                  { gen_setl(def); }
118 // |  CONSTRAINTdecl(id,rules):         { compile_ruleset(id,rules); }
119    |  REPLACEMENTdecl(exp,mode):        { gen_replacement(exp,mode); }
120    |  CUTREWRITEdecl(exp,mode):         { gen_cutreplacement(exp,mode); }
121    |  FAILREWRITEdecl(mode):            { gen_failrewrite(mode); }
122    |  CLASSDEFdecl(a_class):
123       {  a_class->gen_class_definition(*this); }
124    |  CLASSOFdecl id:
125       {  match (lookup_ty(id))
126          {  TYCONty(DATATYPEtycon { id ... }, _):
127             {  pr ("a_%s", id); }
128          |  NOty:
129             {  match (find_cons(id))
130                {  ONEcons { ty = NOty ... }:
131                   {  error ("%Lconstructor %s is not a class\n", id); }
132                |  ONEcons { opt ... } | opt & OPTunboxed:
133                   {  error ("%Lthe class representation of constructor %s has been elided\n", id); }
134                |  ONEcons 
135                   { name, 
136                     alg_ty = 
137                       TYCONty(DATATYPEtycon{ id, opt ... },_) 
138                     ... }:
139                   {  if (opt & OPTsubclassless) pr ("a_%s", id); 
140                      else                       pr ("%s_%S", id, name); 
141                   }
142                |  _:  
143                   {  error ("%Ltype or constructor %s is undefined\n", id); }
144                }
145             }
146          |  ty: 
147             {  error ("%Ltype %s has unknown class: %T\n",id, ty); }
148          }
149       }
150    |  TYPEEXPdecl ty:               { pr ("%t", ty,""); }
151    |  GOTOdecl  label:              { pr ("%^goto %s;\n", label); }
152    |  SETSTATEdecl state:           { pr ("s__ = %i;", state); }
153    |  INJECTdecl { node_number, direction = RIGHTdirection }:
154       {  pr (" if (i__) insert_alpha(%i,fact__); else remove_alpha(%i,fact__); ",
155              node_number, node_number); }
156    |  INJECTdecl { node_number, direction = LEFTdirection }:
157       {  pr (" if (i__) insert_beta(%i,f__); else remove_beta(%i,f__); ", 
158              node_number, node_number); }
159 //   |  BITFIELDdecl { name, width, field_names, laws }:
160 //      {  define_bitfield(name, width, field_names, laws); 
161 //         gen_bitfield(name, width, field_names, laws);
162 //      }
163    |  EXPdecl { exp = e as (SYNexp _ || THISSYNexp _) ... }:  
164                                     { pr ("%e", e); }
165    |  EXPdecl { prefix, exp, suffix}: 
166       { pr ("%^%s%e%s", (prefix ? prefix : ""),exp, (suffix ? suffix : "")); }
167    |  MARKEDdecl (loc,d):          
168       {  line = loc.begin_line; 
169          file = loc.file_name;
170          if (line_prefix) pr ("%#",line,file);
171          gen(d);         
172          line = loc.end_line; 
173          if (line_suffix) pr ("%#",line,file);
174       }
175    |  d:  { bug("Unimplemented feature"); }
176    end match;
179 ///////////////////////////////////////////////////////////////////////////////
181 //  Method to generate a report.
183 ///////////////////////////////////////////////////////////////////////////////
184 ostream& Compiler::print_report(ostream& f)
185 {  f << 
186    "------------------------------- Statistics -------------------------------"
187 << "\nMerge matching rules         = " << (options.merge_match ?  "yes" : "no")
188 << "\nNumber of DFA nodes merged   = " << merges 
189 << "\nNumber of ifs generated      = " << ifs
190 << "\nNumber of switches generated = " << switches
191 << "\nNumber of labels             = " << goto_labels
192 << "\nNumber of gotos              = " << gotos
193 << "\nAdaptive matching            = " << (options.adaptive_matching ? "enabled" : "disabled")
194 << "\nFast string matching         = " << (options.fast_string_match ? "enabled" : "disabled")
195 << "\nInline downcasts             = " << (options.inline_casts ? "enabled" : "disabled")
196 << "\n"
197    "--------------------------------------------------------------------------"
198    "\n"
199    ;
200    return f;