Skip to content

Commit 00cb242

Browse files
committed
add function pointers
1 parent 7d6275b commit 00cb242

File tree

11 files changed

+134
-26
lines changed

11 files changed

+134
-26
lines changed

examples/funcPointers.cal

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
include "cores/select.cal"
2+
include "std/io.cal"
3+
4+
func sayHello begin
5+
"Hello!\n" printstr
6+
end
7+
8+
&sayHello call

source/app.d

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import std.process;
88
import std.algorithm;
99
import callisto.compiler;
1010
import callisto.language;
11-
import callisto.optimiser;
11+
import callisto.codeRemover;
1212
import callisto.preprocessor;
1313
import callisto.backends.uxn;
1414
import callisto.backends.y32;
@@ -270,11 +270,9 @@ int main(string[] args) {
270270
return 1;
271271
}
272272

273-
if (optimise) {
274-
auto optimiser = new Optimiser();
275-
optimiser.Run(nodes);
276-
nodes = optimiser.res;
277-
}
273+
/*auto codeRemover = new CodeRemover();
274+
codeRemover.Run(nodes);
275+
nodes = codeRemover.res;*/
278276

279277
compiler.versions = preproc.versions;
280278

source/backends/linux86.d

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,4 +743,20 @@ class BackendLinux86 : CompilerBackend {
743743
output ~= format("extern %s\n", node.func);
744744
}
745745
}
746+
747+
override void CompileCall(WordNode node) {
748+
output ~= "sub r15, 8\n";
749+
output ~= "mov rax, [r15]\n";
750+
output ~= "call rax\n";
751+
}
752+
753+
override void CompileFuncAddr(FuncAddrNode node) {
754+
if (node.func !in words) {
755+
Error(node.error, "Function '%s' doesn't exist");
756+
}
757+
758+
output ~= format("mov rax, __func__%s\n", node.func.Sanitise());
759+
output ~= "mov [r15], rax\n";
760+
output ~= "add r15, 8\n";
761+
}
746762
}

source/backends/rm86.d

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class BackendRM86 : CompilerBackend {
156156
output ~= "ret\n";
157157

158158
foreach (name, var ; globals) {
159-
output ~= format("__global_%s: times %d db 0\n", name, var.Size());
159+
output ~= format("__global_%s: times %d db 0\n", name.Sanitise(), var.Size());
160160
}
161161

162162
foreach (i, ref array ; arrays) {
@@ -652,4 +652,20 @@ class BackendRM86 : CompilerBackend {
652652
word.raw = node.raw;
653653
words[node.func] = word;
654654
}
655+
656+
override void CompileCall(WordNode node) {
657+
output ~= "sub si, 2\n";
658+
output ~= "mov ax, [si]\n";
659+
output ~= "call ax\n";
660+
}
661+
662+
override void CompileFuncAddr(FuncAddrNode node) {
663+
if (node.func !in words) {
664+
Error(node.error, "Function '%s' doesn't exist");
665+
}
666+
667+
output ~= format("mov ax, __func__%s\n", node.func.Sanitise());
668+
output ~= "mov [si], ax\n";
669+
output ~= "add si, 2\n";
670+
}
655671
}

source/backends/uxn.d

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ class BackendUXN : CompilerBackend {
160160
output ~= "JMP2r\n";
161161

162162
foreach (name, var ; globals) {
163-
output ~= format("@global_%s", name);
163+
output ~= format("@global_%s", name.Sanitise());
164164

165165
foreach (i ; 0 .. var.Size()) {
166166
output ~= " #00";
@@ -226,6 +226,10 @@ class BackendUXN : CompilerBackend {
226226
}
227227

228228
override void CompileInteger(IntegerNode node) {
229+
if (node.value > 0xFFFF) {
230+
Error(node.error, "Value is too big for 16-bit target");
231+
}
232+
229233
output ~= format("#%.4x\n", node.value);
230234
}
231235

@@ -637,4 +641,16 @@ class BackendUXN : CompilerBackend {
637641
word.raw = node.raw;
638642
words[node.func] = word;
639643
}
644+
645+
override void CompileCall(WordNode node) {
646+
output ~= "JSR2\n";
647+
}
648+
649+
override void CompileFuncAddr(FuncAddrNode node) {
650+
if (node.func !in words) {
651+
Error(node.error, "Function '%s' doesn't exist");
652+
}
653+
654+
output ~= format(";func__%s\n", node.func.Sanitise());
655+
}
640656
}

source/backends/y32.d

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,12 @@ class BackendY32 : CompilerBackend {
272272
override void CompileExtern(ExternNode node) {
273273
assert(0);
274274
}
275+
276+
override void CompileCall(WordNode node) {
277+
assert(0);
278+
}
279+
280+
override void CompileFuncAddr(FuncAddrNode node) {
281+
assert(0);
282+
}
275283
}

source/optimiser.d renamed to source/codeRemover.d

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
module callisto.optimiser;
1+
module callisto.codeRemover;
22

33
import std.stdio;
44
import std.format;
55
import std.algorithm;
66
import callisto.error;
77
import callisto.parser;
88

9-
class OptimiserError : Exception {
9+
class CodeRemoverError : Exception {
1010
this() {
1111
super("", "", 0);
1212
}
1313
}
1414

15-
class Optimiser {
15+
class CodeRemover {
1616
Node[] res;
1717
string[] usedFunctions;
1818
Node[][string] functions;
19+
string[] funcStack;
1920

2021
this() {
2122

@@ -24,7 +25,7 @@ class Optimiser {
2425
final void Error(Char, A...)(ErrorInfo error, in Char[] fmt, A args) {
2526
ErrorBegin(error);
2627
stderr.writeln(format(fmt, args));
27-
throw new OptimiserError();
28+
throw new CodeRemoverError();
2829
}
2930

3031
void FindFunctions(Node[] nodes) {
@@ -39,7 +40,13 @@ class Optimiser {
3940
continue;
4041
}
4142

43+
if (funcStack.canFind(node.name)) {
44+
return;
45+
}
46+
47+
funcStack ~= node.name;
4248
FindFunctions(functions[node.name]);
49+
funcStack = funcStack[0 .. $ - 1];
4350
break;
4451
}
4552
case NodeType.If: {

source/compiler.d

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class CompilerBackend {
4545
abstract void CompileUnion(UnionNode node);
4646
abstract void CompileAlias(AliasNode node);
4747
abstract void CompileExtern(ExternNode node);
48+
abstract void CompileCall(WordNode node);
49+
abstract void CompileFuncAddr(FuncAddrNode node);
4850

4951
final void Error(Char, A...)(ErrorInfo error, in Char[] fmt, A args) {
5052
ErrorBegin(error);
@@ -81,9 +83,10 @@ class Compiler {
8183
auto node = cast(WordNode) inode;
8284

8385
switch (node.name) {
84-
case "return": backend.CompileReturn(node); break;
86+
case "return": backend.CompileReturn(node); break;
8587
case "continue": backend.CompileContinue(node); break;
86-
case "break": backend.CompileBreak(node); break;
88+
case "break": backend.CompileBreak(node); break;
89+
case "call": backend.CompileCall(node); break;
8790
case "error": backend.Error(node.error, "Error thrown by code"); break;
8891
default: backend.CompileWord(node);
8992
}
@@ -159,14 +162,15 @@ class Compiler {
159162
}
160163
break;
161164
}
162-
case NodeType.Array: backend.CompileArray(cast(ArrayNode) inode); break;
163-
case NodeType.String: backend.CompileString(cast(StringNode) inode); break;
164-
case NodeType.Struct: backend.CompileStruct(cast(StructNode) inode); break;
165-
case NodeType.Const: backend.CompileConst(cast(ConstNode) inode); break;
166-
case NodeType.Enum: backend.CompileEnum(cast(EnumNode) inode); break;
167-
case NodeType.Union: backend.CompileUnion(cast(UnionNode) inode); break;
168-
case NodeType.Alias: backend.CompileAlias(cast(AliasNode) inode); break;
169-
case NodeType.Extern: backend.CompileExtern(cast(ExternNode) inode); break;
165+
case NodeType.Array: backend.CompileArray(cast(ArrayNode) inode); break;
166+
case NodeType.String: backend.CompileString(cast(StringNode) inode); break;
167+
case NodeType.Struct: backend.CompileStruct(cast(StructNode) inode); break;
168+
case NodeType.Const: backend.CompileConst(cast(ConstNode) inode); break;
169+
case NodeType.Enum: backend.CompileEnum(cast(EnumNode) inode); break;
170+
case NodeType.Union: backend.CompileUnion(cast(UnionNode) inode); break;
171+
case NodeType.Alias: backend.CompileAlias(cast(AliasNode) inode); break;
172+
case NodeType.Extern: backend.CompileExtern(cast(ExternNode) inode); break;
173+
case NodeType.FuncAddr: backend.CompileFuncAddr(cast(FuncAddrNode) inode); break;
170174
default: {
171175
backend.Error(inode.error, "Unimplemented node '%s'", inode.type);
172176
}

source/lexer.d

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ enum TokenType {
1414
String,
1515
Identifier,
1616
LSquare,
17-
RSquare
17+
RSquare,
18+
Ampersand
1819
}
1920

2021
struct Token {
@@ -202,6 +203,11 @@ class Lexer {
202203
col = 0;
203204
break;
204205
}
206+
case '&': {
207+
AddReading();
208+
AddToken(TokenType.Ampersand);
209+
break;
210+
}
205211
case '\'': {
206212
Next();
207213
char ch = code[i];

source/optimise.d

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module callisto.optimise;
2+
3+
class Optimiser {
4+
5+
}

source/parser.d

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ enum NodeType {
2929
Restrict,
3030
Union,
3131
Alias,
32-
Extern
32+
Extern,
33+
FuncAddr
3334
}
3435

3536
class Node {
@@ -410,6 +411,17 @@ class ExternNode : Node {
410411
override string toString() => format("extern %s%s", raw? "" : "raw ", func);
411412
}
412413

414+
class FuncAddrNode : Node {
415+
string func;
416+
417+
this(ErrorInfo perror) {
418+
type = NodeType.FuncAddr;
419+
error = perror;
420+
}
421+
422+
override string toString() => format("&%s", func);
423+
}
424+
413425
class ParserError : Exception {
414426
this() {
415427
super("", "", 0);
@@ -958,6 +970,17 @@ class Parser {
958970
return ret;
959971
}
960972

973+
Node ParseFuncAddr() {
974+
auto ret = new FuncAddrNode(GetError());
975+
parsing = NodeType.FuncAddr;
976+
977+
Next();
978+
Expect(TokenType.Identifier);
979+
ret.func = tokens[i].contents;
980+
981+
return ret;
982+
}
983+
961984
Node ParseStatement() {
962985
switch (tokens[i].type) {
963986
case TokenType.Integer: {
@@ -985,8 +1008,9 @@ class Parser {
9851008
default: return new WordNode(GetError(), tokens[i].contents);
9861009
}
9871010
}
988-
case TokenType.LSquare: return ParseArray();
989-
case TokenType.String: return ParseString();
1011+
case TokenType.LSquare: return ParseArray();
1012+
case TokenType.String: return ParseString();
1013+
case TokenType.Ampersand: return ParseFuncAddr();
9901014
default: {
9911015
Error("Unexpected %s", tokens[i].type);
9921016
}

0 commit comments

Comments
 (0)