Skip to content

Commit a5028c0

Browse files
committed
More HOF support
1 parent 102e90b commit a5028c0

File tree

3 files changed

+74
-27
lines changed

3 files changed

+74
-27
lines changed

mbit/hello.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ export function main(): void {
2626
testReccoll();
2727
showDigit(5);
2828
inBg();
29-
/*
3029
testAction(1);
3130
showDigit(6);
3231
testAction(7);
33-
testActionSave();
32+
testIter();
33+
testActionSave();
34+
/*
3435
msg("start mem test");
3536
testMemoryFree();
3637
msg("start 2nd mem test");
@@ -266,18 +267,26 @@ function inBg() {
266267
assert(rec.str == "foo", "inbg1")
267268
}
268269

269-
/*
270-
271-
272-
function runTwice(fn:Action) : void
273-
{
270+
function runTwice(fn: Action): void {
274271
msg("r2 start");
275272
fn();
276273
fn();
277274
}
278275

279-
function testAction(p: number) : void
280-
{
276+
function iter(max: number, fn: (v: number) => void) {
277+
for (var i = 0; i < max; ++i)
278+
fn(i);
279+
}
280+
281+
function testIter() {
282+
x = 0
283+
iter(10, v => {
284+
x = x + (v + 1)
285+
})
286+
assert(x == 55, "55")
287+
}
288+
289+
function testAction(p: number): void {
281290
let s = "hello" + "1";
282291
let coll = (<number[]>[]);
283292
let p2 = p * 2;
@@ -291,22 +300,19 @@ function testAction(p: number) : void
291300
assert(coll.length == 2, "run2");
292301
}
293302

294-
function saveAction(fn:Action) : void
295-
{
303+
function saveAction(fn: Action): void {
296304
action = fn;
297305
}
298306

299-
function saveGlobalAction() : void
300-
{
307+
function saveGlobalAction(): void {
301308
let s = "foo" + "42";
302309
tot = "";
303310
saveAction(() => {
304311
tot = tot + s;
305312
});
306313
}
307314

308-
function testActionSave() : void
309-
{
315+
function testActionSave(): void {
310316
saveGlobalAction();
311317
runTwice(action);
312318
msg(tot);
@@ -315,6 +321,7 @@ function testActionSave() : void
315321
action = (<Action>null);
316322
}
317323

324+
/*
318325
319326
function testRefLocals() : void
320327
{

src/mbit/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# ARM Thumb emitter for TypeScript
2+
3+
## TODO
4+
5+
* class methods
6+
* optional arguments
7+
* default arguments
8+
* code in top-level scope
9+
* image literals
10+
* +=, -= etc
11+
* return values in lambdas

src/mbit/emitter.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ namespace ts {
4040
node = node.parent
4141
if (!node)
4242
userError(lf("cannot determine parent of {0}", stringKind(node0)))
43-
if (node.kind == SyntaxKind.FunctionDeclaration) return <FunctionDeclaration>node
43+
if (node.kind == SyntaxKind.FunctionDeclaration ||
44+
node.kind == SyntaxKind.ArrowFunction ||
45+
node.kind == SyntaxKind.FunctionExpression) return <FunctionLikeDeclaration>node
4446
if (node.kind == SyntaxKind.SourceFile) return null
4547
}
4648
}
@@ -197,6 +199,7 @@ namespace ts {
197199
if (outer == null || outer == proc.action) {
198200
// not captured
199201
} else {
202+
debugger;
200203
if (proc.info.capturedVars.indexOf(v) < 0)
201204
proc.info.capturedVars.push(v);
202205
info.captured = true;
@@ -479,10 +482,8 @@ namespace ts {
479482
proc.emit("add sp, #4*" + args.length)
480483
if (hasRet)
481484
proc.emit("push {r0}");
482-
483485
}
484486

485-
486487
if (decl && decl.kind == SyntaxKind.FunctionDeclaration) {
487488
if (attrs.shim) {
488489
emitShim(decl, node, args);
@@ -517,6 +518,23 @@ namespace ts {
517518
unhandled(node, "non-shim method call");
518519
}
519520

521+
if (decl && (decl.kind == SyntaxKind.VariableDeclaration || decl.kind == SyntaxKind.Parameter)) {
522+
if (args.length > 1)
523+
userError("lambda functions with more than 1 argument not supported")
524+
525+
if (hasRet)
526+
userError("lambda functions cannot yet return values")
527+
528+
let suff = args.length + ""
529+
if (suff == "0") suff = ""
530+
531+
args.unshift(node.expression)
532+
args.forEach(emit)
533+
534+
proc.emitCall("action::run" + suff, getMask(args));
535+
return
536+
}
537+
520538
unhandled(node, stringKind(decl))
521539
}
522540

@@ -572,7 +590,10 @@ namespace ts {
572590
proc.emitCall("action::mk", 0)
573591
caps.forEach((l, i) => {
574592
proc.emitInt(i)
575-
proc.localIndex(l).emitLoad(proc, true) // direct load
593+
let loc = proc.localIndex(l)
594+
if (!loc)
595+
userError("cannot find captured value: " + checker.symbolToString(l.symbol))
596+
loc.emitLoad(proc, true) // direct load
576597
proc.emitCall("bitvm::stclo", 0)
577598
// already done by emitCall
578599
// proc.emit("push {r0}");
@@ -597,6 +618,13 @@ namespace ts {
597618
proc.emit("@stackmark inlfunc");
598619
proc.emit("push {r5, lr}");
599620
proc.emit("mov r5, r1");
621+
622+
node.parameters.forEach((p, i) => {
623+
if (i >= 2)
624+
userError(lf("only up to two parameters supported in lambdas"))
625+
proc.emit(`push {r${i + 2}}`)
626+
})
627+
proc.emit("@stackmark args");
600628
} else {
601629
proc.emit("@stackmark func");
602630
proc.emit("@stackmark args");
@@ -618,20 +646,24 @@ namespace ts {
618646

619647
if (proc.hasReturn()) {
620648
proc.emit("push {r0}");
621-
proc.emitClrs(null, true);
649+
proc.emitClrs();
622650
proc.emit("pop {r0}");
623651
} else {
624-
proc.emitClrs(null, true);
652+
proc.emitClrs();
625653
}
626654

627655
proc.popLocals();
628656

629657
if (isLambda) {
658+
proc.emit("@stackempty args")
659+
if (node.parameters.length)
660+
proc.emit("add sp, #4*" + node.parameters.length + " ; pop args")
630661
proc.emit("pop {r5, pc}");
631662
proc.emit("@stackempty inlfunc");
632663
} else {
633664
proc.emit("pop {pc}");
634665
proc.emit("@stackempty func");
666+
proc.emit("@stackempty args")
635667
}
636668
})
637669
}
@@ -1559,13 +1591,10 @@ namespace ts {
15591591
(noargs ? null : this.args.filter(n => n.def == l)[0])
15601592
}
15611593

1562-
emitClrs(omit: Declaration, inclArgs = false) {
1563-
var lst = this.locals
1564-
if (inclArgs)
1565-
lst = lst.concat(this.args)
1594+
emitClrs() {
1595+
var lst = this.locals.concat(this.args)
15661596
lst.forEach(p => {
1567-
if (p.def != omit)
1568-
p.emitClrIfRef(this)
1597+
p.emitClrIfRef(this)
15691598
})
15701599
}
15711600

0 commit comments

Comments
 (0)