Skip to content

Commit 7dcf816

Browse files
committed
WIP YETI-16 backend
1 parent 670efac commit 7dcf816

File tree

6 files changed

+282
-9
lines changed

6 files changed

+282
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ cac-test-*
1616
*.lst
1717
out.asm
1818
out.com
19+
out.bin
1920
test.cal

examples/literals.cal

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
include "cores/select.cal"
2+
include "std/io.cal"
3+
4+
func new_line begin
5+
13 printch 10 printch
6+
end
7+
8+
# Hexadecimal - prints 16
9+
0x10 printdec new_line
10+
11+
# Binary - prints 16
12+
0b00010000 printdec new_line
13+
14+
# Octal - prints 16
15+
0o20 printdec new_line

source/app.d

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import callisto.compiler;
88
import callisto.language;
99
import callisto.optimiser;
1010
import callisto.preprocessor;
11+
import callisto.backends.y16;
1112
import callisto.backends.rm86;
1213

1314
const static string usage = "
@@ -19,6 +20,11 @@ Flags:
1920
-i PATH - Adds PATH to the list of include directories
2021
-O - Enables optimisation (only works properly with programs without errors)
2122
-v VER - Enables VER as a version
23+
-b BACKEND - Uses the given backend (backends listed below)
24+
25+
Backends:
26+
rm86 - Real mode x86
27+
y16 - YETI-16 (work in progress)
2228
";
2329

2430
int main(string[] args) {
@@ -31,13 +37,14 @@ int main(string[] args) {
3137
return 0;
3238
}
3339

34-
string file;
35-
string outFile = "out.asm";
36-
ulong org;
37-
bool orgSet;
38-
string[] includeDirs;
39-
bool optimise;
40-
string[] versions;
40+
string file;
41+
string outFile = "out.asm";
42+
ulong org;
43+
bool orgSet;
44+
string[] includeDirs;
45+
bool optimise;
46+
string[] versions;
47+
CompilerBackend backend = new BackendRM86();
4148

4249
for (size_t i = 1; i < args.length; ++ i) {
4350
if (args[i][0] == '-') {
@@ -100,6 +107,28 @@ int main(string[] args) {
100107
versions ~= args[i];
101108
break;
102109
}
110+
case "-b": {
111+
++ i;
112+
if (i >= args.length) {
113+
stderr.writeln("-b requires BACKEND parameter");
114+
return 1;
115+
}
116+
117+
switch (args[i]) {
118+
case "rm86": {
119+
backend = new BackendRM86();
120+
break;
121+
}
122+
case "y16": {
123+
backend = new BackendY16();
124+
break;
125+
}
126+
default: {
127+
stderr.writefln("Unknown backend '%s'", args[i]);
128+
}
129+
}
130+
break;
131+
}
103132
default: {
104133
stderr.writefln("Unknown flag '%s'", args[i]);
105134
return 1;
@@ -125,7 +154,7 @@ int main(string[] args) {
125154
auto nodes = ParseFile(file);
126155

127156
auto compiler = new Compiler();
128-
compiler.backend = new BackendRM86();
157+
compiler.backend = backend;
129158
compiler.backend.org = org;
130159
compiler.backend.orgSet = orgSet;
131160

source/backends/y16.d

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
module callisto.backends.y16;
2+
3+
import std.format;
4+
import callisto.util;
5+
import callisto.error;
6+
import callisto.parser;
7+
import callisto.compiler;
8+
9+
private struct Word {
10+
bool inline;
11+
Node[] inlineNodes;
12+
}
13+
14+
private struct Type {
15+
ulong size;
16+
}
17+
18+
private struct Constant {
19+
Node value;
20+
}
21+
22+
class BackendY16 : CompilerBackend {
23+
Word[string] words;
24+
Type[string] types;
25+
bool inScope;
26+
Constant[string] consts;
27+
uint blockCounter;
28+
29+
override string[] GetVersions() => ["Y16"];
30+
31+
this() {
32+
types["u8"] = Type(1);
33+
types["i8"] = Type(1);
34+
types["u16"] = Type(2);
35+
types["i16"] = Type(2);
36+
types["addr"] = Type(2);
37+
types["size"] = Type(2);
38+
types["usize"] = Type(2);
39+
types["cell"] = Type(2);
40+
types["Array"] = Type(6);
41+
42+
foreach (name, ref type ; types) {
43+
NewConst(format("%s.sizeof", name), cast(long) type.size);
44+
}
45+
46+
// struct Array
47+
// usize length
48+
// usize memberSize
49+
// addr elements
50+
// end
51+
NewConst("Array.length", 0);
52+
NewConst("Array.memberSize", 2);
53+
NewConst("Array.elements", 4);
54+
}
55+
56+
void NewConst(string name, long value, ErrorInfo error = ErrorInfo.init) {
57+
consts[name] = Constant(new IntegerNode(error, value));
58+
}
59+
60+
override void Init() {
61+
output ~= "cpp sr bs\n";
62+
output ~= "ldi a __stack\n";
63+
output ~= "addp sr a\n";
64+
}
65+
66+
override void End() {
67+
output ~= "hlt\n";
68+
output ~= "__stack: fill 1024 0\n"; // 512 cell stack
69+
}
70+
71+
override void CompileWord(WordNode node) {
72+
if (node.name in words) {
73+
auto word = words[node.name];
74+
75+
if (word.inline) {
76+
foreach (inode ; word.inlineNodes) {
77+
compiler.CompileNode(inode);
78+
}
79+
}
80+
else {
81+
output ~= format("callb __func__%s\n", node.name.Sanitise());
82+
}
83+
}
84+
else if (node.name in consts) {
85+
compiler.CompileNode(consts[node.name].value);
86+
}
87+
else {
88+
Error(node.error, "Undefined identifier '%s'", node.name);
89+
}
90+
}
91+
92+
override void CompileInteger(IntegerNode node) {
93+
output ~= format("ldi a %d\n", node.value);
94+
output ~= "wrw sr a\n";
95+
output ~= "ldsi a 2\n";
96+
output ~= "addp sr a\n";
97+
}
98+
99+
override void CompileFuncDef(FuncDefNode node) {
100+
if (node.inline) {
101+
words[node.name] = Word(true, node.nodes);
102+
}
103+
else {
104+
assert(!inScope);
105+
inScope = true;
106+
107+
words[node.name] = Word(false, []);
108+
109+
output ~= format("jmpb __func_end__%s\n", node.name.Sanitise());
110+
output ~= format("__func__%s:\n", node.name.Sanitise());
111+
112+
foreach (ref inode ; node.nodes) {
113+
compiler.CompileNode(inode);
114+
}
115+
116+
output ~= format("__func_return__%s:\n", node.name.Sanitise());
117+
118+
output ~= "ret\n";
119+
output ~= format("__func_end__%s:\n", node.name.Sanitise());
120+
inScope = false;
121+
}
122+
}
123+
124+
override void CompileIf(IfNode node) {
125+
++ blockCounter;
126+
auto blockNum = blockCounter;
127+
uint condCounter;
128+
129+
foreach (i, ref condition ; node.condition) {
130+
foreach (ref inode ; condition) {
131+
compiler.CompileNode(inode);
132+
}
133+
134+
output ~= "ldsi b 2\n";
135+
output ~= "subp sr b\n";
136+
output ~= "rdw a sr\n";
137+
output ~= "ldsi b 0\n";
138+
output ~= "cmp a b\n";
139+
output ~= format("jzb __if_%d_%d\n", blockNum, condCounter + 1);
140+
141+
foreach (ref inode ; node.doIf[i]) {
142+
compiler.CompileNode(inode);
143+
}
144+
145+
output ~= format("jmpb __if_%d_end\n", blockNum);
146+
147+
++ condCounter;
148+
output ~= format("__if_%d_%d:\n", blockNum, condCounter);
149+
}
150+
151+
if (node.hasElse) {
152+
foreach (ref inode ; node.doElse) {
153+
compiler.CompileNode(inode);
154+
}
155+
}
156+
157+
output ~= format("__if_%d_end:\n", blockNum);
158+
}
159+
160+
override void CompileWhile(WhileNode node) {
161+
++ blockCounter;
162+
uint blockNum = blockCounter;
163+
164+
output ~= format("jmpb __while_%d_condition\n", blockNum);
165+
output ~= format("__while_%d:\n", blockNum);
166+
167+
foreach (ref inode ; node.doWhile) {
168+
compiler.CompileNode(inode);
169+
}
170+
171+
output ~= format("__while_%d_condition:\n", blockNum);
172+
173+
foreach (ref inode ; node.condition) {
174+
compiler.CompileNode(inode);
175+
}
176+
177+
output ~= "ldsi b 2\n";
178+
output ~= "subp sr b\n";
179+
output ~= "rdw a sr\n";
180+
output ~= "ldsi b 0\n";
181+
output ~= "cmp a b\n";
182+
output ~= format("jnzb __while_%d\n", blockNum);
183+
output ~= format("__while_%d_end:\n", blockNum);
184+
}
185+
186+
override void CompileLet(LetNode node) {
187+
assert(0);
188+
}
189+
190+
override void CompileArray(ArrayNode node) {
191+
assert(0);
192+
}
193+
194+
override void CompileString(StringNode node) {
195+
assert(0);
196+
}
197+
198+
override void CompileStruct(StructNode node) {
199+
assert(0);
200+
}
201+
}

source/lexer.d

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
module callisto.lexer;
22

3+
import std.conv;
34
import std.stdio;
45
import std.format;
56
import std.string;
7+
import std.algorithm;
8+
import callisto.util;
69
import callisto.error;
710

811
enum TokenType {
@@ -67,6 +70,30 @@ class Lexer {
6770
else if (reading.isNumeric()) {
6871
AddToken(TokenType.Integer);
6972
}
73+
else if (reading.startsWith("0x")) {
74+
if (!reading.OnlyContains("0123456789abcdefABCDEF")) {
75+
Error("Invalid literal");
76+
}
77+
78+
reading = format("%d", reading[2 .. $].to!long(16));
79+
AddToken(TokenType.Integer);
80+
}
81+
else if (reading.startsWith("0b")) {
82+
if (!reading.OnlyContains("01")) {
83+
Error("Invalid binary literal");
84+
}
85+
86+
reading = format("%d", reading[2 .. $].to!long(2));
87+
AddToken(TokenType.Integer);
88+
}
89+
else if (reading.startsWith("0o")) {
90+
if (!reading.OnlyContains("01234567")) {
91+
Error("Invalid octal literal");
92+
}
93+
94+
reading = format("%d", reading[2 .. $].to!long(8));
95+
AddToken(TokenType.Integer);
96+
}
7097
else {
7198
AddToken(TokenType.Identifier);
7299
}

std

Submodule std updated 1 file

0 commit comments

Comments
 (0)