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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
import std.stdio;
import std.string;
import chunk;
import parser;
//import parser;
//import dbg;
//import value;
void printForm(Form f, string prefix = "") {
switch (f.type) {
case FormType.EOF:
writeln("eof");
return;
case FormType.ATOM:
writefln("%s atom: %s", prefix, atomAsString(cast(Atom)f));
break;
case FormType.CONS:
Cons c = cast(Cons)f;
writef("%s cons <", prefix);
if (c.evaluate) {
writeln("true>");
} else {
writeln("false>");
}
printForm(c.head, format("%s>", prefix));
foreach (Form i ; c.tail) {
printForm(i, format("%s>", prefix));
}
break;
case FormType.NIL:
writefln("%s NIL", prefix);
break;
case FormType.PARSE_ERROR:
ParseError pe = cast(ParseError)f;
writefln("ERROR: %s", pe.message);
break;
case FormType.SYMBOL:
Symbol s = cast(Symbol)f;
writefln("%s sym: %s", prefix, s.name);
break;
case FormType.FUNC:
Func func = cast(Func)f;
writefln("%s <fn %s>", prefix, func.name.name);
printForm(func.args, format("%s -", prefix));
writefln("%s with %d body lines", prefix, func.funcBody.length);
writefln("%s <end fn %s>", prefix, func.name.name);
break;
case FormType.DEF:
Def def = cast(Def)f;
writefln("%s var: %s", prefix, def.name.name);
break;
default:
writeln("printFormDefault");
break;
}
}
string printableValue(Value val) {
switch (val.type) {
case ValueType.STRING:
return val.as.str;
case ValueType.NUMBER:
return format("%g", val.as.number);
case ValueType.BOOLEAN:
if (val.as.boolean) {
return "true";
} else {
return "false";
}
default:
return "! unknown value type !";
}
}
string atomAsString(Atom a) {
return printableValue(a.value);
}
int constantInstruction(string message, Chunk chunk, int offset) {
ubyte idx = chunk.code[offset + 1];
//writeln("dunno how to write a constant");
writefln("%-16s %4d '%s'", message, idx, printableValue(chunk.constants[idx]));
//writefln("%-16s %4d '%s'", message, idx, atomAsString(chunk.constants[idx]));
return offset + 2;
}
int simpleInstruction(string message, int offset) {
writeln(message);
return offset + 1;
}
int disassemble(Chunk chunk, int offset) {
writef("%04d %4d ", offset, chunk.lines[offset]);
ubyte inst = chunk.code[offset];
switch (inst) {
case OpCode.OP_ADD:
return simpleInstruction("OP_ADD", offset);
case OpCode.OP_LESS:
return simpleInstruction("OP_LESS", offset);
case OpCode.OP_SUBTRACT:
return simpleInstruction("OP_SUBTRACT", offset);
case OpCode.OP_CONSTANT:
return constantInstruction("OP_CONSTANT", chunk, offset);
case OpCode.OP_DEFINE_GLOBAL:
return constantInstruction("OP_DEFINE_GLOBAL", chunk, offset);
case OpCode.OP_NEGATE:
return simpleInstruction("OP_NEGATE", offset);
case OpCode.OP_POP:
return simpleInstruction("OP_POP", offset);
case OpCode.OP_RETURN:
return simpleInstruction("OP_RETURN", offset);
case OpCode.OP_NIL:
return simpleInstruction("OP_NIL", offset);
default:
writeln("unknown opcode?");
return offset + 1;
}
return 0;
}
|