about summary refs log blame commit diff stats
path: root/040---tests.cc
blob: 0586249b2748b10282274cbb700ad621a2a2ccf9 (plain) (tree)
pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# include this file in your ~/.nanorc

syntax "subx" "\.subx$"
# function definitions
color yellow "^[a-z][^ ]*:"
# global variables
color red "^[A-Z][^ ]*:"
# tests
color green "^test-[^ ]*:"
# strings literals
color cyan ""([^"\]|\\.)+""
# comments
comment "#"
color brightblue "# - .*"
color blue "#.*$"
color brightblack "# \. .*"
?h=hlt&id=0828df68de1defe68d63fd19cd3ed76be09918c8'>^
83c67014 ^
c442a5ad ^
caaeccd6 ^





03d50cc8 ^
caaeccd6 ^




03d50cc8 ^
caaeccd6 ^
















caaeccd6 ^



























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95







                                                                              
 

                                                                              
                           
                                          
 
       
                      

                                                              
      
                                      












                                                                     

                                       
                                   
                                                            





                                                               
                                                     




                                                   
                                           
















                                                                          



























                                                   
//: Automatically aggregate functions starting with 'test-' into a test suite
//: called 'run-tests'. Running this function will run all tests.
//:
//: This is actually SubX's first (trivial) compiler. We generate all the code
//: needed for the 'run-tests' function.
//:
//: By convention, temporary functions needed by tests will start with
//: '_test-'.

//: We don't rely on any transforms running in previous layers, but this layer
//: knows about labels and will emit labels for previous layers to transform.
:(after "Begin Transforms")
Transform.push_back(create_test_function);

:(code)
void test_run_test() {
  Mem.push_back(vma(0xbd000000));  // manually allocate memory
  Reg[ESP].u = 0xbd000100;
  run(
      "== code 0x1\n"  // code segment
      "main:\n"
      "  e8/call run-tests/disp32\n"  // 5 bytes
      "  f4/halt\n"                   // 1 byte
      "test-foo:\n"  // offset 7
      "  01 d8\n"  // just some unique instruction: add EBX to EAX
      "  c3/return\n"
  );
  // check that code in test-foo ran (implicitly called by run-tests)
  CHECK_TRACE_CONTENTS(
      "run: 0x00000007 opcode: 01\n"
  );
}

void create_test_function(program& p) {
  if (p.segments.empty()) return;
  segment& code = *find(p, "code");
  trace(3, "transform") << "-- create 'run-tests'" << end();
  vector<line> new_insts;
  for (int i = 0;  i < SIZE(code.lines);  ++i) {
    line& inst = code.lines.at(i);
    for (int j = 0;  j < SIZE(inst.words);  ++j) {
      const word& curr = inst.words.at(j);
      if (*curr.data.rbegin() != ':') continue;  // not a label
      if (!starts_with(curr.data, "test-")) continue;
      string fn = drop_last(curr.data);
      new_insts.push_back(call(fn));
    }
  }
  if (new_insts.empty()) return;  // no tests found
  code.lines.push_back(label("run-tests"));
  code.lines.insert(code.lines.end(), new_insts.begin(), new_insts.end());
  code.lines.push_back(ret());
}

string to_string(const segment& s) {
  ostringstream out;
  for (int i = 0;  i < SIZE(s.lines);  ++i) {
    const line& l = s.lines.at(i);
    for (int j = 0;  j < SIZE(l.words);  ++j) {
      if (j > 0) out << ' ';
      out << to_string(l.words.at(j));
    }
    out << '\n';
  }
  return out.str();
}

line call(string s) {
  line result;
  result.words.push_back(call());
  result.words.push_back(disp32(s));
  return result;
}

word call() {
  word result;
  result.data = "e8";
  result.metadata.push_back("call");
  return result;
}

word disp32(string s) {
  word result;
  result.data = s;
  result.metadata.push_back("disp32");
  return result;
}

line ret() {
  line result;
  result.words.push_back(word());
  result.words.back().data = "c3";
  result.words.back().metadata.push_back("return");
  return result;
}