11module callisto.backends.y16 ;
22
3+ import std.range ;
34import std.format ;
5+ import std.algorithm ;
46import callisto.util;
57import callisto.error;
68import callisto.parser;
79import callisto.compiler;
10+ import callisto.language;
811
912private struct Word {
1013 bool inline;
@@ -19,12 +22,32 @@ private struct Constant {
1922 Node value;
2023}
2124
25+ private struct Variable {
26+ string name;
27+ Type type;
28+ uint offset; // SP + offset to access
29+ bool array;
30+ ulong arraySize;
31+
32+ size_t Size () => array? arraySize * type.size : type.size;
33+ }
34+
35+ private struct Global {
36+ Type type;
37+ bool array;
38+ ulong arraySize;
39+
40+ size_t Size () => array? arraySize * type.size : type.size;
41+ }
42+
2243class BackendY16 : CompilerBackend {
2344 Word[string ] words;
2445 Type[string ] types;
2546 bool inScope;
2647 Constant[string ] consts;
2748 uint blockCounter;
49+ Variable[] variables;
50+ Global[string ] globals;
2851
2952 override string [] GetVersions () => [" Y16" ];
3053
@@ -33,11 +56,11 @@ class BackendY16 : CompilerBackend {
3356 types[" i8" ] = Type(1 );
3457 types[" u16" ] = Type(2 );
3558 types[" i16" ] = Type(2 );
36- types[" addr" ] = Type(2 );
59+ types[" addr" ] = Type(3 );
3760 types[" size" ] = Type(2 );
3861 types[" usize" ] = Type(2 );
3962 types[" cell" ] = Type(2 );
40- types[" Array" ] = Type(6 );
63+ types[" Array" ] = Type(7 );
4164
4265 foreach (name, ref type ; types) {
4366 NewConst(format(" %s.sizeof" , name), cast (long ) type.size);
@@ -56,6 +79,22 @@ class BackendY16 : CompilerBackend {
5679 void NewConst (string name, long value, ErrorInfo error = ErrorInfo.init) {
5780 consts[name] = Constant(new IntegerNode(error, value));
5881 }
82+
83+ bool VariableExists (string name) => variables.any! (v => v.name == name);
84+
85+ Variable GetVariable (string name) {
86+ foreach (ref var ; variables) {
87+ if (var.name == name) {
88+ return var;
89+ }
90+ }
91+
92+ assert (0 );
93+ }
94+
95+ size_t GetStackSize () {
96+ return variables.empty()? 0 : variables[0 ].offset + variables[0 ].type.size;
97+ }
5998
6099 override void Init () {
61100 output ~= " cpp sr bs\n " ;
@@ -65,6 +104,11 @@ class BackendY16 : CompilerBackend {
65104
66105 override void End () {
67106 output ~= " hlt\n " ;
107+
108+ foreach (name, var ; globals) {
109+ output ~= format(" __global_%s: fill %d 0\n " , name, var.Size());
110+ }
111+
68112 output ~= " __stack: fill 1024 0\n " ; // 512 cell stack
69113 }
70114
@@ -81,6 +125,29 @@ class BackendY16 : CompilerBackend {
81125 output ~= format(" callb __func__%s\n " , node.name.Sanitise());
82126 }
83127 }
128+ else if (VariableExists(node.name)) {
129+ auto var = GetVariable(node.name);
130+
131+ output ~= " cpp gh sp\n " ;
132+ output ~= format(" ldi a %d\n " , var.offset);
133+ output ~= " wrw sr g\n " ;
134+ output ~= " ldsi b 2\n " ;
135+ output ~= " addp sr b\n " ;
136+ output ~= " wrw sr h\n " ;
137+ output ~= " addp sr b\n " ;
138+ }
139+ else if (node.name in globals) {
140+ auto var = globals[node.name];
141+
142+ output ~= " cpp gh bs\n " ;
143+ output ~= format(" ldi a __global_%s\n " , node.name.Sanitise());
144+ output ~= " addp gh a\n " ;
145+ output ~= " wrw sr g\n " ;
146+ output ~= " ldsi b 2\n " ;
147+ output ~= " addp sr b\n " ;
148+ output ~= " wrw sr h\n " ;
149+ output ~= " addp sr b\n " ;
150+ }
84151 else if (node.name in consts) {
85152 compiler.CompileNode(consts[node.name].value);
86153 }
@@ -184,7 +251,47 @@ class BackendY16 : CompilerBackend {
184251 }
185252
186253 override void CompileLet (LetNode node) {
187- assert (0 );
254+ if (node.varType ! in types) {
255+ Error(node.error, " Undefined type '%s'" , node.varType);
256+ }
257+ if (VariableExists(node.name) || (node.name in words)) {
258+ Error(node.error, " Variable name '%s' already used" , node.name);
259+ }
260+ if (Language.bannedNames.canFind(node.name)) {
261+ Error(node.error, " Name '%s' can't be used" , node.name);
262+ }
263+
264+ if (inScope) {
265+ foreach (ref var ; variables) {
266+ var.offset += types[node.varType].size;
267+ // idk but RM86 had a comment here saying TODO: fix this
268+ // i have no memory of what needs to be fixed
269+ // but RM86 works fine so i guess its ok
270+ }
271+
272+ Variable var;
273+ var.name = node.name;
274+ var.type = types[node.varType];
275+ var.offset = 0 ;
276+ var.array = node.array;
277+ var.arraySize = node.arraySize;
278+
279+ variables ~= var;
280+
281+ if (var.Size() == 2 ) {
282+ output ~= " ldsi a 0\n " ;
283+ output ~= " push a\n " ;
284+ }
285+ else {
286+ output ~= format(" ldi a %d\n " , var.Size());
287+ output ~= " subp sp a\n " ;
288+ }
289+ }
290+ else {
291+ Global global;
292+ global.type = types[node.varType];
293+ globals[node.name] = global;
294+ }
188295 }
189296
190297 override void CompileArray (ArrayNode node) {
0 commit comments