about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-06-30 22:46:32 -0700
committerKartik Agaram <vc@akkartik.com>2018-06-30 22:46:32 -0700
commitb20d9ad3030729c57da73ec2c321795907d11b7a (patch)
tree1154a1d9bcb23f697ebb1bd604e8ce6f625ca4a5 /subx
parent784bbd4a69d5381726f952c722dd9b3787e538ae (diff)
downloadmu-b20d9ad3030729c57da73ec2c321795907d11b7a.tar.gz
4298 - framework for translating SubX programs
Diffstat (limited to 'subx')
-rw-r--r--subx/010core.cc6
-rw-r--r--subx/021translate.cc49
2 files changed, 47 insertions, 8 deletions
diff --git a/subx/010core.cc b/subx/010core.cc
index 90359162..b21511d7 100644
--- a/subx/010core.cc
+++ b/subx/010core.cc
@@ -99,7 +99,7 @@ End_of_program = 0;
 // helper for tests: load a program into memory from a textual representation
 // of its bytes, and run it
 void run(const string& text_bytes) {
-  load_program(text_bytes);
+  load_program(text_bytes, 1);  // tests always assume a starting address of 1
   EIP = 1;  // preserve null pointer
   while (EIP < End_of_program)
     run_one_instruction();
@@ -151,9 +151,9 @@ void run_one_instruction() {
   }
 }
 
-void load_program(const string& text_bytes) {
+void load_program(const string& text_bytes, uint32_t addr) {
   istringstream in(text_bytes);
-  load_program(in, 1);
+  load_program(in, addr);
 }
 void load_program(istream& in, uint32_t addr) {
   in >> std::noskipws;
diff --git a/subx/021translate.cc b/subx/021translate.cc
index 94553ae9..f262bcd6 100644
--- a/subx/021translate.cc
+++ b/subx/021translate.cc
@@ -1,18 +1,45 @@
+//: Beginnings of a nicer way to build SubX programs.
+//: We're going to question every notion, including "Assembly language" and
+//: "compiler".
+//: Motto: Abstract nothing, check everything.
+//:
+//: Workflow: read 'source' file as a single string. Run a series of
+//: transforms on it, each converting to a new string. The final string should
+//: be just machine code and comments, suitable to pass to load_program().
+
+:(before "End Types")
+typedef void (*transform_fn)(const string& input, string& output);
+:(before "End Globals")
+vector<transform_fn> Transform;
+
 :(before "End Includes")
 const int START = 0x08048000;
 :(before "End Main")
 if (is_equal(argv[1], "translate")) {
   assert(argc > 3);
-  ifstream in(argv[2]);
-  Mem.resize(1024);
-  load_program(in, 1);  // since we're not going to run it right now, we can load it anywhere
-  dump_elf(argv[3]);
+  string program;
+  slurp(argv[2], program);
+  perform_all_transforms(program);
+  dump_elf(program, argv[3]);
 }
 
 :(code)
+void perform_all_transforms(string& program) {
+  string& in = program;
+  string out;
+  for (int t = 0;  t < SIZE(Transform);  ++t, in.swap(out), out.clear())
+    (*Transform.at(t))(in, out);
+}
+
 // write out the current Memory contents from address 1 to End_of_program to a
 // bare-bones ELF file with a single section/segment and a hard-coded origin address.
-void dump_elf(const char* filename) {
+void dump_elf(const string& program, const char* filename) {
+  Mem.resize(1024);
+  // load program into memory, filtering out comments
+  load_program(program, 1);  // Not where 'program' should be loaded for running.
+                             // But we're not going to run it right now, so we
+                             // can load it anywhere.
+  // dump contents of memory into ELF binary
   ofstream out(filename, ios::binary);
   dump_elf_header(out);
   for (size_t i = 1;  i < End_of_program;  ++i) {
@@ -93,5 +120,17 @@ void dump_elf_header(ostream& out) {
 #undef O
 }
 
+void slurp(const char* filename, string& out) {
+  ifstream fin(filename);
+  fin >> std::noskipws;
+  ostringstream fout;
+  char c = '\0';
+  while(has_data(fin)) {
+    fin >> c;
+    fout << c;
+  }
+  fout.str().swap(out);
+}
+
 :(before "End Includes")
 using std::ios;