97 lines
3.2 KiB
C++
97 lines
3.2 KiB
C++
|
|
// Step 1948: CompilerPhaseSpec + CompilerPhaseRegistry
|
||
|
|
//
|
||
|
|
// t1: registerPhase and phaseCount
|
||
|
|
// t2: getPhase returns correct spec; throws on missing
|
||
|
|
// t3: hasPhase correct
|
||
|
|
// t4: phaseIdsSorted returns ids in order field order
|
||
|
|
// t5: phasesForLanguage filters correctly
|
||
|
|
|
||
|
|
#include "CompilerPhaseSpec.h"
|
||
|
|
#include <iostream>
|
||
|
|
|
||
|
|
namespace ws = whetstone;
|
||
|
|
static int p=0,f=0;
|
||
|
|
#define T(n) { std::cout<<" "<<#n<<"... "; }
|
||
|
|
#define P() { std::cout<<"PASS\n"; ++p; }
|
||
|
|
#define F(m) { std::cout<<"FAIL: "<<m<<"\n"; ++f; }
|
||
|
|
#define C(c,m) if(!(c)){F(m);return;}
|
||
|
|
|
||
|
|
static void populate(ws::CompilerPhaseRegistry& r) {
|
||
|
|
r.registerPhase({"lex", "C++", "Lexing", 1, "Source", "Token"});
|
||
|
|
r.registerPhase({"parse", "Haskell", "Parsing", 2, "Token", "AST"});
|
||
|
|
r.registerPhase({"typecheck","Rust", "Type checking",3, "AST", "TypedAST"});
|
||
|
|
r.registerPhase({"optimize", "Lisp", "Optimization", 4, "TypedAST","OptimizedAST"});
|
||
|
|
r.registerPhase({"emit", "Go", "Code emit", 5, "OptimizedAST","Bytecode"});
|
||
|
|
}
|
||
|
|
|
||
|
|
void t1(){
|
||
|
|
T(registerPhase_and_phaseCount);
|
||
|
|
ws::CompilerPhaseRegistry r;
|
||
|
|
C(r.phaseCount() == 0, "empty initially");
|
||
|
|
populate(r);
|
||
|
|
C(r.phaseCount() == 5, "five phases");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t2(){
|
||
|
|
T(getPhase_returns_correct_spec);
|
||
|
|
ws::CompilerPhaseRegistry r;
|
||
|
|
populate(r);
|
||
|
|
auto spec = r.getPhase("lex");
|
||
|
|
C(spec.phaseId == "lex", "phaseId");
|
||
|
|
C(spec.language == "C++", "language");
|
||
|
|
C(spec.order == 1, "order");
|
||
|
|
C(spec.inputKind == "Source", "inputKind");
|
||
|
|
bool threw = false;
|
||
|
|
try { r.getPhase("nonexistent"); } catch (const std::out_of_range&) { threw = true; }
|
||
|
|
C(threw, "throws on missing");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t3(){
|
||
|
|
T(hasPhase_correct);
|
||
|
|
ws::CompilerPhaseRegistry r;
|
||
|
|
populate(r);
|
||
|
|
C( r.hasPhase("emit"), "emit present");
|
||
|
|
C(!r.hasPhase("nonexistent"), "nonexistent absent");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t4(){
|
||
|
|
T(phaseIdsSorted_by_order);
|
||
|
|
ws::CompilerPhaseRegistry r;
|
||
|
|
// Register out of order
|
||
|
|
r.registerPhase({"emit", "Go", "emit", 5, "", ""});
|
||
|
|
r.registerPhase({"lex", "C++", "lex", 1, "", ""});
|
||
|
|
r.registerPhase({"typecheck","Rust", "tc", 3, "", ""});
|
||
|
|
r.registerPhase({"parse", "Haskell", "parse", 2, "", ""});
|
||
|
|
r.registerPhase({"optimize", "Lisp", "opt", 4, "", ""});
|
||
|
|
auto ids = r.phaseIdsSorted();
|
||
|
|
C(ids.size() == 5, "five ids");
|
||
|
|
C(ids[0] == "lex", "lex first");
|
||
|
|
C(ids[1] == "parse", "parse second");
|
||
|
|
C(ids[2] == "typecheck", "typecheck third");
|
||
|
|
C(ids[3] == "optimize", "optimize fourth");
|
||
|
|
C(ids[4] == "emit", "emit fifth");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
void t5(){
|
||
|
|
T(phasesForLanguage_filters_correctly);
|
||
|
|
ws::CompilerPhaseRegistry r;
|
||
|
|
populate(r);
|
||
|
|
auto ids = r.phasesForLanguage("Rust");
|
||
|
|
C(ids.size() == 1, "one Rust phase");
|
||
|
|
C(ids[0] == "typecheck", "typecheck");
|
||
|
|
auto none = r.phasesForLanguage("Java");
|
||
|
|
C(none.empty(), "no Java phases");
|
||
|
|
P();
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(){
|
||
|
|
std::cout << "Step 1948: CompilerPhaseSpec + CompilerPhaseRegistry\n";
|
||
|
|
t1(); t2(); t3(); t4(); t5();
|
||
|
|
std::cout << "\n" << p << "/" << (p+f) << " passed\n";
|
||
|
|
return f > 0 ? 1 : 0;
|
||
|
|
}
|