Allow infix () and {} to call "call" on the left-hand side.

- Allow this for both argument lists and block arguments.

- Tweak precedence to make "." higher than infix "{}" to avoid a
  class body being parsed as the superclass clause's block argument.

- Convert all uses of ".call" to use this. (There was not a single
  case in the repo that ran into the getter ambiguity.)
This commit is contained in:
Bob Nystrom
2015-12-01 07:49:04 -08:00
parent 9df6aa2f8a
commit c3e2f17758
99 changed files with 376 additions and 284 deletions

View File

@ -83,4 +83,4 @@ var root = Question.new("Does it live in the water?",
// Play games until the user quits. // Play games until the user quits.
Fiber.new { Fiber.new {
while (true) root.ask() while (true) root.ask()
}.call() }()

View File

@ -11,7 +11,7 @@ foreign class File {
static open(path, fn) { static open(path, fn) {
var file = @open(path) var file = @open(path)
var fiber = Fiber.new { fn.call(file) } var fiber = Fiber.new { fn(file) }
// Poor man's finally. Can we make this more elegant? // Poor man's finally. Can we make this more elegant?
var result = fiber.try() var result = fiber.try()

View File

@ -13,7 +13,7 @@ static const char* ioModuleSource =
"\n" "\n"
" static open(path, fn) {\n" " static open(path, fn) {\n"
" var file = @open(path)\n" " var file = @open(path)\n"
" var fiber = Fiber.new { fn.call(file) }\n" " var fiber = Fiber.new { fn(file) }\n"
"\n" "\n"
" // Poor man's finally. Can we make this more elegant?\n" " // Poor man's finally. Can we make this more elegant?\n"
" var result = fiber.try()\n" " var result = fiber.try()\n"

View File

@ -3,7 +3,7 @@ class Scheduler {
if (__scheduled == null) __scheduled = [] if (__scheduled == null) __scheduled = []
__scheduled.add(Fiber.new { __scheduled.add(Fiber.new {
callable.call() callable()
@runNextScheduled_() @runNextScheduled_()
}) })
} }

View File

@ -5,7 +5,7 @@ static const char* schedulerModuleSource =
" if (__scheduled == null) __scheduled = []\n" " if (__scheduled == null) __scheduled = []\n"
"\n" "\n"
" __scheduled.add(Fiber.new {\n" " __scheduled.add(Fiber.new {\n"
" callable.call()\n" " callable()\n"
" @runNextScheduled_()\n" " @runNextScheduled_()\n"
" })\n" " })\n"
" }\n" " }\n"

View File

@ -6,7 +6,7 @@ class Meta {
// TODO: Include compile errors. // TODO: Include compile errors.
if (fn == null) Fiber.abort("Could not compile source code.") if (fn == null) Fiber.abort("Could not compile source code.")
Fiber.new(fn).call() Fiber.new(fn)()
} }
foreign static compile_(source) foreign static compile_(source)

View File

@ -8,7 +8,7 @@ static const char* metaModuleSource =
" // TODO: Include compile errors.\n" " // TODO: Include compile errors.\n"
" if (fn == null) Fiber.abort(\"Could not compile source code.\")\n" " if (fn == null) Fiber.abort(\"Could not compile source code.\")\n"
"\n" "\n"
" Fiber.new(fn).call()\n" " Fiber.new(fn)()\n"
" }\n" " }\n"
"\n" "\n"
" foreign static compile_(source)\n" " foreign static compile_(source)\n"

View File

@ -1494,7 +1494,8 @@ typedef enum
PREC_TERM, // + - PREC_TERM, // + -
PREC_FACTOR, // * / % PREC_FACTOR, // * / %
PREC_UNARY, // unary - ! ~ PREC_UNARY, // unary - ! ~
PREC_CALL, // . () [] PREC_CALL, // () [] {}
PREC_METHOD, // .
PREC_PRIMARY PREC_PRIMARY
} Precedence; } Precedence;
@ -1739,6 +1740,39 @@ static void finishArgumentList(Compiler* compiler, Signature* signature)
ignoreNewlines(compiler); ignoreNewlines(compiler);
} }
// Parses the rest of a block argument after the "{".
static void finishBlockArgument(Compiler* compiler, Signature* signature)
{
// Include the block argument in the arity.
signature->type = SIG_METHOD;
signature->arity++;
Compiler fnCompiler;
initCompiler(&fnCompiler, compiler->parser, compiler, true);
// Make a dummy signature to track the arity.
Signature fnSignature = { "", 0, SIG_METHOD, 0 };
// Parse the parameter list, if any.
if (match(compiler, TOKEN_PIPE))
{
finishParameterList(&fnCompiler, &fnSignature);
consume(compiler, TOKEN_PIPE, "Expect '|' after function parameters.");
}
fnCompiler.numParams = fnSignature.arity;
finishBody(&fnCompiler, false);
// Name the function based on the method its passed to.
char blockName[MAX_METHOD_SIGNATURE + 15];
int blockLength;
signatureToString(signature, blockName, &blockLength);
memmove(blockName + blockLength, " block argument", 16);
endCompiler(&fnCompiler, blockName, blockLength + 15);
}
// Compiles a method call with [signature] using [instruction]. // Compiles a method call with [signature] using [instruction].
static void callSignature(Compiler* compiler, Code instruction, static void callSignature(Compiler* compiler, Code instruction,
Signature* signature) Signature* signature)
@ -1790,37 +1824,10 @@ static void methodCall(Compiler* compiler, Code instruction,
consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after arguments."); consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after arguments.");
} }
// Parse the block argument, if any. // Parse an optional block argument.
if (match(compiler, TOKEN_LEFT_BRACE)) if (match(compiler, TOKEN_LEFT_BRACE))
{ {
// Include the block argument in the arity. finishBlockArgument(compiler, &called);
called.type = SIG_METHOD;
called.arity++;
Compiler fnCompiler;
initCompiler(&fnCompiler, compiler->parser, compiler, true);
// Make a dummy signature to track the arity.
Signature fnSignature = { "", 0, SIG_METHOD, 0 };
// Parse the parameter list, if any.
if (match(compiler, TOKEN_PIPE))
{
finishParameterList(&fnCompiler, &fnSignature);
consume(compiler, TOKEN_PIPE, "Expect '|' after function parameters.");
}
fnCompiler.numParams = fnSignature.arity;
finishBody(&fnCompiler, false);
// Name the function based on the method its passed to.
char blockName[MAX_METHOD_SIGNATURE + 15];
int blockLength;
signatureToString(&called, blockName, &blockLength);
memmove(blockName + blockLength, " block argument", 16);
endCompiler(&fnCompiler, blockName, blockLength + 15);
} }
// TODO: Allow Grace-style mixfix methods? // TODO: Allow Grace-style mixfix methods?
@ -1900,6 +1907,30 @@ static void grouping(Compiler* compiler, bool allowAssignment)
consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after expression."); consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
} }
static void call(Compiler* compiler, bool allowAssignment)
{
// An infix parenthesized call is syntax sugar for invoking the "call" method
// on the left-hand side.
Signature signature = { "call", 4, SIG_METHOD, 0 };
// Allow empty an argument list.
if (peek(compiler) != TOKEN_RIGHT_PAREN)
{
// Parse the argument list.
finishArgumentList(compiler, &signature);
}
consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after arguments.");
// Parse an optional block argument.
if (match(compiler, TOKEN_LEFT_BRACE))
{
finishBlockArgument(compiler, &signature);
}
callSignature(compiler, CODE_CALL_0, &signature);
}
// A list literal. // A list literal.
static void list(Compiler* compiler, bool allowAssignment) static void list(Compiler* compiler, bool allowAssignment)
{ {
@ -1956,6 +1987,16 @@ static void map(Compiler* compiler, bool allowAssignment)
consume(compiler, TOKEN_RIGHT_BRACE, "Expect '}' after map entries."); consume(compiler, TOKEN_RIGHT_BRACE, "Expect '}' after map entries.");
} }
// A block argument call on an expression receiver like `fn { block }`.
static void blockArgument(Compiler* compiler, bool allowAssignment)
{
// An infix block argument call is syntax sugar for invoking the "call"
// method on the left-hand side.
Signature signature = { "call", 4, SIG_METHOD, 0 };
finishBlockArgument(compiler, &signature);
callSignature(compiler, CODE_CALL_0, &signature);
}
// Unary operators like `-foo`. // Unary operators like `-foo`.
static void unaryOp(Compiler* compiler, bool allowAssignment) static void unaryOp(Compiler* compiler, bool allowAssignment)
{ {
@ -2266,7 +2307,7 @@ static void subscript(Compiler* compiler, bool allowAssignment)
callSignature(compiler, CODE_CALL_0, &signature); callSignature(compiler, CODE_CALL_0, &signature);
} }
static void call(Compiler* compiler, bool allowAssignment) static void dot(Compiler* compiler, bool allowAssignment)
{ {
ignoreNewlines(compiler); ignoreNewlines(compiler);
consume(compiler, TOKEN_NAME, "Expect method name after '.'."); consume(compiler, TOKEN_NAME, "Expect method name after '.'.");
@ -2497,14 +2538,14 @@ void constructorSignature(Compiler* compiler, Signature* signature)
GrammarRule rules[] = GrammarRule rules[] =
{ {
/* TOKEN_LEFT_PAREN */ PREFIX(grouping), /* TOKEN_LEFT_PAREN */ { grouping, call, NULL, PREC_CALL, NULL },
/* TOKEN_RIGHT_PAREN */ UNUSED, /* TOKEN_RIGHT_PAREN */ UNUSED,
/* TOKEN_LEFT_BRACKET */ { list, subscript, subscriptSignature, PREC_CALL, NULL }, /* TOKEN_LEFT_BRACKET */ { list, subscript, subscriptSignature, PREC_CALL, NULL },
/* TOKEN_RIGHT_BRACKET */ UNUSED, /* TOKEN_RIGHT_BRACKET */ UNUSED,
/* TOKEN_LEFT_BRACE */ PREFIX(map), /* TOKEN_LEFT_BRACE */ { map, blockArgument, NULL, PREC_CALL, NULL },
/* TOKEN_RIGHT_BRACE */ UNUSED, /* TOKEN_RIGHT_BRACE */ UNUSED,
/* TOKEN_COLON */ UNUSED, /* TOKEN_COLON */ UNUSED,
/* TOKEN_DOT */ INFIX(PREC_CALL, call), /* TOKEN_DOT */ INFIX(PREC_METHOD, dot),
/* TOKEN_DOTDOT */ INFIX_OPERATOR(PREC_RANGE, ".."), /* TOKEN_DOTDOT */ INFIX_OPERATOR(PREC_RANGE, ".."),
/* TOKEN_DOTDOTDOT */ INFIX_OPERATOR(PREC_RANGE, "..."), /* TOKEN_DOTDOTDOT */ INFIX_OPERATOR(PREC_RANGE, "..."),
/* TOKEN_COMMA */ UNUSED, /* TOKEN_COMMA */ UNUSED,
@ -3131,7 +3172,7 @@ static void classDefinition(Compiler* compiler, bool isForeign)
// Load the superclass (if there is one). // Load the superclass (if there is one).
if (match(compiler, TOKEN_IS)) if (match(compiler, TOKEN_IS))
{ {
parsePrecedence(compiler, false, PREC_CALL); parsePrecedence(compiler, false, PREC_METHOD);
} }
else else
{ {

View File

@ -5,19 +5,19 @@ class Null {}
class Num {} class Num {}
class Sequence { class Sequence {
all(f) { all(fn) {
var result = true var result = true
for (element in this) { for (element in this) {
result = f.call(element) result = fn(element)
if (!result) return result if (!result) return result
} }
return result return result
} }
any(f) { any(fn) {
var result = false var result = false
for (element in this) { for (element in this) {
result = f.call(element) result = fn(element)
if (result) return result if (result) return result
} }
return result return result
@ -38,17 +38,17 @@ class Sequence {
return result return result
} }
count(f) { count(fn) {
var result = 0 var result = 0
for (element in this) { for (element in this) {
if (f.call(element)) result = result + 1 if (fn(element)) result = result + 1
} }
return result return result
} }
each(f) { each(fn) {
for (element in this) { for (element in this) {
f.call(element) fn(element)
} }
} }
@ -58,21 +58,21 @@ class Sequence {
where(predicate) { WhereSequence.new(this, predicate) } where(predicate) { WhereSequence.new(this, predicate) }
reduce(accumulator, f) { reduce(accumulator, fn) {
for (element in this) { for (element in this) {
accumulator = f.call(accumulator, element) accumulator = fn(accumulator, element)
} }
return accumulator return accumulator
} }
reduce(f) { reduce(fn) {
var iterator = @iterate(null) var iterator = @iterate(null)
if (!iterator) Fiber.abort("Can't reduce an empty sequence.") if (!iterator) Fiber.abort("Can't reduce an empty sequence.")
// Seed with the first element. // Seed with the first element.
var result = @iteratorValue(iterator) var result = @iteratorValue(iterator)
while (iterator = @iterate(iterator)) { while (iterator = @iterate(iterator)) {
result = f.call(result, @iteratorValue(iterator)) result = fn(result, @iteratorValue(iterator))
} }
return result return result
@ -109,7 +109,7 @@ class MapSequence is Sequence {
} }
iterate(iterator) { _sequence.iterate(iterator) } iterate(iterator) { _sequence.iterate(iterator) }
iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) } iteratorValue(iterator) { _fn(_sequence.iteratorValue(iterator)) }
} }
class WhereSequence is Sequence { class WhereSequence is Sequence {
@ -120,7 +120,7 @@ class WhereSequence is Sequence {
iterate(iterator) { iterate(iterator) {
while (iterator = _sequence.iterate(iterator)) { while (iterator = _sequence.iterate(iterator)) {
if (_fn.call(_sequence.iteratorValue(iterator))) break if (_fn(_sequence.iteratorValue(iterator))) break
} }
return iterator return iterator
} }

View File

@ -7,19 +7,19 @@ static const char* coreModuleSource =
"class Num {}\n" "class Num {}\n"
"\n" "\n"
"class Sequence {\n" "class Sequence {\n"
" all(f) {\n" " all(fn) {\n"
" var result = true\n" " var result = true\n"
" for (element in this) {\n" " for (element in this) {\n"
" result = f.call(element)\n" " result = fn(element)\n"
" if (!result) return result\n" " if (!result) return result\n"
" }\n" " }\n"
" return result\n" " return result\n"
" }\n" " }\n"
"\n" "\n"
" any(f) {\n" " any(fn) {\n"
" var result = false\n" " var result = false\n"
" for (element in this) {\n" " for (element in this) {\n"
" result = f.call(element)\n" " result = fn(element)\n"
" if (result) return result\n" " if (result) return result\n"
" }\n" " }\n"
" return result\n" " return result\n"
@ -40,17 +40,17 @@ static const char* coreModuleSource =
" return result\n" " return result\n"
" }\n" " }\n"
"\n" "\n"
" count(f) {\n" " count(fn) {\n"
" var result = 0\n" " var result = 0\n"
" for (element in this) {\n" " for (element in this) {\n"
" if (f.call(element)) result = result + 1\n" " if (fn(element)) result = result + 1\n"
" }\n" " }\n"
" return result\n" " return result\n"
" }\n" " }\n"
"\n" "\n"
" each(f) {\n" " each(fn) {\n"
" for (element in this) {\n" " for (element in this) {\n"
" f.call(element)\n" " fn(element)\n"
" }\n" " }\n"
" }\n" " }\n"
"\n" "\n"
@ -60,21 +60,21 @@ static const char* coreModuleSource =
"\n" "\n"
" where(predicate) { WhereSequence.new(this, predicate) }\n" " where(predicate) { WhereSequence.new(this, predicate) }\n"
"\n" "\n"
" reduce(accumulator, f) {\n" " reduce(accumulator, fn) {\n"
" for (element in this) {\n" " for (element in this) {\n"
" accumulator = f.call(accumulator, element)\n" " accumulator = fn(accumulator, element)\n"
" }\n" " }\n"
" return accumulator\n" " return accumulator\n"
" }\n" " }\n"
"\n" "\n"
" reduce(f) {\n" " reduce(fn) {\n"
" var iterator = @iterate(null)\n" " var iterator = @iterate(null)\n"
" if (!iterator) Fiber.abort(\"Can't reduce an empty sequence.\")\n" " if (!iterator) Fiber.abort(\"Can't reduce an empty sequence.\")\n"
"\n" "\n"
" // Seed with the first element.\n" " // Seed with the first element.\n"
" var result = @iteratorValue(iterator)\n" " var result = @iteratorValue(iterator)\n"
" while (iterator = @iterate(iterator)) {\n" " while (iterator = @iterate(iterator)) {\n"
" result = f.call(result, @iteratorValue(iterator))\n" " result = fn(result, @iteratorValue(iterator))\n"
" }\n" " }\n"
"\n" "\n"
" return result\n" " return result\n"
@ -111,7 +111,7 @@ static const char* coreModuleSource =
" }\n" " }\n"
"\n" "\n"
" iterate(iterator) { _sequence.iterate(iterator) }\n" " iterate(iterator) { _sequence.iterate(iterator) }\n"
" iteratorValue(iterator) { _fn.call(_sequence.iteratorValue(iterator)) }\n" " iteratorValue(iterator) { _fn(_sequence.iteratorValue(iterator)) }\n"
"}\n" "}\n"
"\n" "\n"
"class WhereSequence is Sequence {\n" "class WhereSequence is Sequence {\n"
@ -122,7 +122,7 @@ static const char* coreModuleSource =
"\n" "\n"
" iterate(iterator) {\n" " iterate(iterator) {\n"
" while (iterator = _sequence.iterate(iterator)) {\n" " while (iterator = _sequence.iterate(iterator)) {\n"
" if (_fn.call(_sequence.iteratorValue(iterator))) break\n" " if (_fn(_sequence.iteratorValue(iterator))) break\n"
" }\n" " }\n"
" return iterator\n" " return iterator\n"
" }\n" " }\n"

View File

@ -658,22 +658,22 @@ var projectionTest = Fn.new {|n|
ScaleConstraint.new(src, scale, offset, dst, REQUIRED) ScaleConstraint.new(src, scale, offset, dst, REQUIRED)
} }
change.call(src, 17) change(src, 17)
total = total + dst.value total = total + dst.value
if (dst.value != 1170) System.print("Projection 1 failed") if (dst.value != 1170) System.print("Projection 1 failed")
change.call(dst, 1050) change(dst, 1050)
total = total + src.value total = total + src.value
if (src.value != 5) System.print("Projection 2 failed") if (src.value != 5) System.print("Projection 2 failed")
change.call(scale, 5) change(scale, 5)
for (i in 0...n - 1) { for (i in 0...n - 1) {
total = total + dests[i].value total = total + dests[i].value
if (dests[i].value != i * 5 + 1000) System.print("Projection 3 failed") if (dests[i].value != i * 5 + 1000) System.print("Projection 3 failed")
} }
change.call(offset, 2000) change(offset, 2000)
for (i in 0...n - 1) { for (i in 0...n - 1) {
total = total + dests[i].value total = total + dests[i].value
if (dests[i].value != i * 5 + 2000) System.print("Projection 4 failed") if (dests[i].value != i * 5 + 2000) System.print("Projection 4 failed")
@ -682,8 +682,8 @@ var projectionTest = Fn.new {|n|
var start = System.clock var start = System.clock
for (i in 0...40) { for (i in 0...40) {
chainTest.call(100) chainTest(100)
projectionTest.call(100) projectionTest(100)
} }
System.print(total) System.print(total)

View File

@ -7,10 +7,10 @@ var start = System.clock
for (i in 0...100000) { for (i in 0...100000) {
fibers.add(Fiber.new { fibers.add(Fiber.new {
sum = sum + i sum = sum + i
if (i < 99999) fibers[i + 1].call() if (i < 99999) fibers[i + 1]()
}) })
} }
fibers[0].call() fibers[0]()
System.print(sum) System.print(sum)
System.print("elapsed: %(System.clock - start)") System.print("elapsed: %(System.clock - start)")

View File

@ -3,5 +3,5 @@ var fiber = Fiber.new {
} }
System.print("before") // expect: before System.print("before") // expect: before
fiber.call() // expect: fiber fiber() // expect: fiber
System.print("after") // expect: after System.print("after") // expect: after

View File

@ -1,7 +1,7 @@
var fiber var fiber
fiber = Fiber.new { fiber = Fiber.new {
fiber.call() // expect runtime error: Fiber has already been called. fiber() // expect runtime error: Fiber has already been called.
} }
fiber.call() fiber()

View File

@ -2,5 +2,5 @@ var fiber = Fiber.new {
System.print("call") System.print("call")
} }
fiber.call() // expect: call fiber() // expect: call
fiber.call() // expect runtime error: Cannot call a finished fiber. fiber() // expect runtime error: Cannot call a finished fiber.

View File

@ -4,4 +4,4 @@ var fiber = Fiber.new {
} }
fiber.try() fiber.try()
fiber.call() // expect runtime error: Cannot call an aborted fiber. fiber() // expect runtime error: Cannot call an aborted fiber.

View File

@ -2,11 +2,11 @@ var a
var b var b
a = Fiber.new { a = Fiber.new {
b.call() // expect runtime error: Fiber has already been called. b() // expect runtime error: Fiber has already been called.
} }
b = Fiber.new { b = Fiber.new {
a.call() a()
} }
b.call() b()

View File

@ -2,4 +2,4 @@ var fiber = Fiber.new {
System.print("fiber") // expect: fiber System.print("fiber") // expect: fiber
} }
System.print(fiber.call()) // expect: null System.print(fiber()) // expect: null

View File

@ -3,4 +3,4 @@ var fiber = Fiber.new {
return "result" // expect: fiber return "result" // expect: fiber
} }
System.print(fiber.call()) // expect: result System.print(fiber()) // expect: result

View File

@ -6,7 +6,7 @@ var fiber = Fiber.new {
System.print("called") System.print("called")
} }
fiber.transfer() // expect: transferred fiber.transfer() // expect: transferred
System.print("main") // expect: main System.print("main") // expect: main
fiber.call() // expect: null fiber() // expect: null
// expect: called // expect: called

View File

@ -4,6 +4,6 @@ var fiber = Fiber.new {
// The first value passed to the fiber is ignored, since there's no yield call // The first value passed to the fiber is ignored, since there's no yield call
// to return it. // to return it.
System.print("before") // expect: before System.print("before") // expect: before
fiber.call("ignored") // expect: fiber fiber("ignored") // expect: fiber
System.print("after") // expect: after System.print("after") // expect: after

View File

@ -1,7 +1,7 @@
var fiber var fiber
fiber = Fiber.new { fiber = Fiber.new {
fiber.call(2) // expect runtime error: Fiber has already been called. fiber(2) // expect runtime error: Fiber has already been called.
} }
fiber.call(1) fiber(1)

View File

@ -2,5 +2,5 @@ var fiber = Fiber.new {
System.print("call") System.print("call")
} }
fiber.call(1) // expect: call fiber(1) // expect: call
fiber.call(2) // expect runtime error: Cannot call a finished fiber. fiber(2) // expect runtime error: Cannot call a finished fiber.

View File

@ -4,4 +4,4 @@ var fiber = Fiber.new {
} }
fiber.try() fiber.try()
fiber.call("value") // expect runtime error: Cannot call an aborted fiber. fiber("value") // expect runtime error: Cannot call an aborted fiber.

View File

@ -1,9 +1,9 @@
var A = Fiber.new { var a = Fiber.new {
B.call(3) // expect runtime error: Fiber has already been called. b(3) // expect runtime error: Fiber has already been called.
} }
var B = Fiber.new { var b = Fiber.new {
A.call(2) a(2)
} }
B.call(1) b(1)

View File

@ -6,7 +6,7 @@ var fiber = Fiber.new {
System.print("called") System.print("called")
} }
fiber.transfer() // expect: transferred fiber.transfer() // expect: transferred
System.print("main") // expect: main System.print("main") // expect: main
fiber.call("value") // expect: value fiber("value") // expect: value
// expect: called // expect: called

View File

@ -5,7 +5,7 @@ var fiber = Fiber.new {
} }
System.print(fiber.isDone) // expect: false System.print(fiber.isDone) // expect: false
fiber.call() // expect: 1 fiber() // expect: 1
System.print(fiber.isDone) // expect: false System.print(fiber.isDone) // expect: false
fiber.call() // expect: 2 fiber() // expect: 2
System.print(fiber.isDone) // expect: true System.print(fiber.isDone) // expect: true

View File

@ -4,12 +4,12 @@ var b = Fiber.new {
var a = Fiber.new { var a = Fiber.new {
System.print("begin fiber a") System.print("begin fiber a")
b.call() b()
System.print("end fiber a") System.print("end fiber a")
} }
System.print("begin main") System.print("begin main")
a.call() a()
System.print("end main") System.print("end main")
// expect: begin main // expect: begin main

View File

@ -1,9 +1,9 @@
var F = Fiber.new { var f = Fiber.new {
System.print(1) // expect: 1 System.print(1) // expect: 1
System.print(F.transfer()) // expect: null System.print(f.transfer()) // expect: null
System.print(2) // expect: 2 System.print(2) // expect: 2
} }
F.call() f()
// F remembers its original caller so transfers back to main. // f remembers its original caller so transfers back to main.
System.print(3) // expect: 3 System.print(3) // expect: 3

View File

@ -1,18 +1,18 @@
var A = Fiber.new { var a = Fiber.new {
System.print(2) System.print(2)
B.transfer() b.transfer()
System.print("nope") System.print("nope")
} }
var B = Fiber.new { var b = Fiber.new {
System.print(1) System.print(1)
A.transfer() a.transfer()
System.print(3) System.print(3)
} }
B.call() b()
// expect: 1 // expect: 1
// expect: 2 // expect: 2
// expect: 3 // expect: 3
// B remembers its original caller so returns to main. // b remembers its original caller so returns to main.
System.print(4) // expect: 4 System.print(4) // expect: 4

View File

@ -13,11 +13,11 @@ var fiber = Fiber.new {
fiber.transfer() // expect: fiber 1 fiber.transfer() // expect: fiber 1
System.print("main 1") // expect: main 1 System.print("main 1") // expect: main 1
fiber.call("call 1") // expect: call 1 fiber("call 1") // expect: call 1
System.print("main 2") // expect: main 2 System.print("main 2") // expect: main 2
// Transfer back into the fiber so it has a NULL caller. // Transfer back into the fiber so it has a NULL caller.
fiber.transfer() fiber.transfer()
fiber.call() // expect: null fiber() // expect: null
System.print("main 3") // expect: main 3 System.print("main 3") // expect: main 3

View File

@ -2,5 +2,5 @@ var a = Fiber.new {
System.print("run") System.print("run")
} }
a.call() // expect: run a() // expect: run
a.transfer() // expect runtime error: Cannot transfer to a finished fiber. a.transfer() // expect runtime error: Cannot transfer to a finished fiber.

View File

@ -4,6 +4,6 @@ var fiber = Fiber.new {
System.print("transferred") System.print("transferred")
} }
fiber.call() // expect: called fiber() // expect: called
fiber.transfer() // expect: null fiber.transfer() // expect: null
// expect: transferred // expect: transferred

View File

@ -1,8 +1,8 @@
var F = Fiber.new { var f = Fiber.new {
System.print(1) // expect: 1 System.print(1) // expect: 1
System.print(F.transfer("value")) // expect: value System.print(f.transfer("value")) // expect: value
System.print(2) // expect: 2 System.print(2) // expect: 2
} }
F.call() f()
System.print(3) // expect: 3 System.print(3) // expect: 3

View File

@ -1,16 +1,16 @@
var A = Fiber.new { var a = Fiber.new {
System.print(2) System.print(2)
B.transfer("ignored") b.transfer("ignored")
System.print("nope") System.print("nope")
} }
var B = Fiber.new { var b = Fiber.new {
System.print(1) System.print(1)
A.transfer("ignored") a.transfer("ignored")
System.print(3) System.print(3)
} }
B.call() b()
// expect: 1 // expect: 1
// expect: 2 // expect: 2
// expect: 3 // expect: 3

View File

@ -2,5 +2,5 @@ var a = Fiber.new {
System.print("run") System.print("run")
} }
a.call() // expect: run a() // expect: run
a.transfer("blah") // expect runtime error: Cannot transfer to a finished fiber. a.transfer("blah") // expect runtime error: Cannot transfer to a finished fiber.

View File

@ -4,6 +4,6 @@ var fiber = Fiber.new {
System.print("transferred") System.print("transferred")
} }
fiber.call() // expect: called fiber() // expect: called
fiber.transfer("value") // expect: value fiber.transfer("value") // expect: value
// expect: transferred // expect: transferred

View File

@ -4,4 +4,4 @@ fiber = Fiber.new {
fiber.try() // expect runtime error: Fiber has already been called. fiber.try() // expect runtime error: Fiber has already been called.
} }
fiber.call() fiber()

View File

@ -6,7 +6,7 @@ a = Fiber.new {
} }
b = Fiber.new { b = Fiber.new {
a.call() a()
} }
b.call() b()

View File

@ -6,9 +6,9 @@ var fiber = Fiber.new {
System.print("fiber 3") System.print("fiber 3")
} }
fiber.call() // expect: fiber 1 fiber() // expect: fiber 1
System.print("main 1") // expect: main 1 System.print("main 1") // expect: main 1
fiber.call() // expect: fiber 2 fiber() // expect: fiber 2
System.print("main 2") // expect: main 2 System.print("main 2") // expect: main 2
fiber.call() // expect: fiber 3 fiber() // expect: fiber 3
System.print("main 3") // expect: main 3 System.print("main 3") // expect: main 3

View File

@ -4,9 +4,9 @@ var fiber = Fiber.new {
System.print(Fiber.yield()) System.print(Fiber.yield())
} }
fiber.call() // expect: fiber 1 fiber() // expect: fiber 1
System.print("main 1") // expect: main 1 System.print("main 1") // expect: main 1
fiber.call("call 1") // expect: call 1 fiber("call 1") // expect: call 1
System.print("main 2") // expect: main 2 System.print("main 2") // expect: main 2
fiber.call() // expect: null fiber() // expect: null
System.print("main 3") // expect: main 3 System.print("main 3") // expect: main 3

View File

@ -9,11 +9,11 @@ var b = Fiber.new {
System.print("b") System.print("b")
System.print(Fiber.yield()) System.print(Fiber.yield())
a.call() a()
a.transfer("value") a.transfer("value")
} }
b.call() // expect: b b() // expect: b
b.transfer() b.transfer()
// expect: null // expect: null
// expect: a // expect: a

View File

@ -6,9 +6,9 @@ var fiber = Fiber.new {
System.print("fiber 3") System.print("fiber 3")
} }
System.print(fiber.call()) // expect: fiber 1 System.print(fiber()) // expect: fiber 1
// expect: yield 1 // expect: yield 1
System.print(fiber.call()) // expect: fiber 2 System.print(fiber()) // expect: fiber 2
// expect: yield 2 // expect: yield 2
System.print(fiber.call()) // expect: fiber 3 System.print(fiber()) // expect: fiber 3
// expect: null // expect: null

View File

@ -3,14 +3,14 @@ var f1 = Fn.new {|a| System.print("one %(a)") }
var f2 = Fn.new {|a, b| System.print("two %(a) %(b)") } var f2 = Fn.new {|a, b| System.print("two %(a) %(b)") }
var f3 = Fn.new {|a, b, c| System.print("three %(a) %(b) %(c)") } var f3 = Fn.new {|a, b, c| System.print("three %(a) %(b) %(c)") }
f0.call("a") // expect: zero f0("a") // expect: zero
f0.call("a", "b") // expect: zero f0("a", "b") // expect: zero
f1.call("a", "b") // expect: one a f1("a", "b") // expect: one a
f1.call("a", "b", "c") // expect: one a f1("a", "b", "c") // expect: one a
f2.call("a", "b", "c") // expect: two a b f2("a", "b", "c") // expect: two a b
f2.call("a", "b", "c", "d") // expect: two a b f2("a", "b", "c", "d") // expect: two a b
f3.call("a", "b", "c", "d") // expect: three a b c f3("a", "b", "c", "d") // expect: three a b c
f3.call("a", "b", "c", "d", "e") // expect: three a b c f3("a", "b", "c", "d", "e") // expect: three a b c

View File

@ -1,2 +1,2 @@
var f2 = Fn.new {|a, b| System.print(a + b) } var f2 = Fn.new {|a, b| System.print(a + b) }
f2.call("a") // expect runtime error: Function expects more arguments. f2("a") // expect runtime error: Function expects more arguments.

View File

@ -7,4 +7,4 @@ Fn.new {
System.print(a = "arg") // expect: arg System.print(a = "arg") // expect: arg
System.print(a) // expect: arg System.print(a) // expect: arg
}.call() }()

View File

@ -5,5 +5,5 @@ for (i in [1, 2, 3]) {
break break
} }
f.call() f()
// expect: 5 // expect: 5

View File

@ -5,5 +5,5 @@ while (true) {
break break
} }
f.call() f()
// expect: i // expect: i

View File

@ -16,10 +16,10 @@ var g = null
} }
} }
f.call() f()
// expect: local // expect: local
// expect: after f // expect: after f
g.call() g()
// expect: after f // expect: after f
// expect: after g // expect: after g

View File

@ -4,6 +4,6 @@ Fn.new {|param|
f = Fn.new { f = Fn.new {
System.print(param) System.print(param)
} }
}.call("param") }("param")
f.call() // expect: param f() // expect: param

View File

@ -9,5 +9,5 @@ Fn.new {
Fn.new { Fn.new {
System.print(b) // expect: b System.print(b) // expect: b
System.print(a) // expect: a System.print(a) // expect: a
}.call() }()
}.call() }()

View File

@ -1,14 +1,14 @@
var F = null var f
class Foo { class Foo {
construct new() {} construct new() {}
method(param) { method(param) {
F = Fn.new { f = Fn.new {
System.print(param) System.print(param)
} }
} }
} }
Foo.new().method("param") Foo.new().method("param")
F.call() // expect: param f() // expect: param

View File

@ -7,4 +7,4 @@ var f = null
} }
} }
f.call() // expect: local f() // expect: local

View File

@ -11,11 +11,11 @@ Fn.new {
System.print(b) System.print(b)
System.print(c) System.print(c)
} }
}.call() }()
}.call() }()
}.call() }()
f.call() f()
// expect: a // expect: a
// expect: b // expect: b
// expect: c // expect: c

View File

@ -2,5 +2,5 @@
var local = "local" var local = "local"
Fn.new { Fn.new {
System.print(local) // expect: local System.print(local) // expect: local
}.call() }()
} }

View File

@ -8,6 +8,6 @@ var f = null
} }
} }
f.call() f()
// expect: a // expect: a
// expect: a // expect: a

View File

@ -10,7 +10,7 @@
// Since a is out of scope, the local slot will be reused by b. Make sure // Since a is out of scope, the local slot will be reused by b. Make sure
// that f still closes over a. // that f still closes over a.
var b = "b" var b = "b"
f.call() // expect: a f() // expect: a
} }
} }

View File

@ -7,5 +7,5 @@
System.print(foo) // expect: shadow System.print(foo) // expect: shadow
} }
System.print(foo) // expect: closure System.print(foo) // expect: closure
}.call() }()
} }

View File

@ -15,5 +15,5 @@ var closure
if (false) Fn.new { b } if (false) Fn.new { b }
} }
System.print(closure.call()) // expect: a System.print(closure()) // expect: a
} }

View File

@ -17,9 +17,9 @@ var closure
} }
} }
fiber.call() // expect: before fiber() // expect: before
closure.call() // expect: before closure() // expect: before
fiber.call() fiber()
closure.call() // expect: after closure() // expect: after
fiber.call() // expect: after fiber() // expect: after
closure.call() // expect: final closure() // expect: final

View File

@ -1,16 +1,16 @@
class Foo { class Foo {
construct new() { _field = "Foo field" } construct new() { _field = "Foo field" }
closeOverGet { closeOverGet() {
return Fn.new { _field } return Fn.new { _field }
} }
closeOverSet { closeOverSet() {
return Fn.new { _field = "new value" } return Fn.new { _field = "new value" }
} }
} }
var foo = Foo.new() var foo = Foo.new()
System.print(foo.closeOverGet.call()) // expect: Foo field System.print(foo.closeOverGet()()) // expect: Foo field
foo.closeOverSet.call() foo.closeOverSet()()
System.print(foo.closeOverGet.call()) // expect: new value System.print(foo.closeOverGet()()) // expect: new value

View File

@ -4,7 +4,7 @@ for (i in [1, 2, 3]) {
list.add(Fn.new { System.print(i) }) list.add(Fn.new { System.print(i) })
} }
for (f in list) f.call() for (f in list) f()
// expect: 1 // expect: 1
// expect: 2 // expect: 2
// expect: 3 // expect: 3

View File

@ -5,7 +5,7 @@ for (i in [1, 2, 3]) {
list.add(Fn.new { System.print(j) }) list.add(Fn.new { System.print(j) })
} }
for (f in list) f.call() for (f in list) f()
// expect: 2 // expect: 2
// expect: 3 // expect: 3
// expect: 4 // expect: 4

View File

@ -3,7 +3,7 @@ var f = Fn.new {
return [1, 2, 3] return [1, 2, 3]
} }
for (i in f.call()) System.print(i) for (i in f()) System.print(i)
// expect: evaluate sequence // expect: evaluate sequence
// expect: 1 // expect: 1
// expect: 2 // expect: 2

View File

@ -4,6 +4,6 @@ var f = Fn.new {
} }
} }
var g = f.call() var g = f()
g.call() g()
// expect: 1 // expect: 1

View File

@ -4,5 +4,5 @@ var f = Fn.new {
} }
} }
System.print(f.call()) System.print(f())
// expect: 1 // expect: 1

View File

@ -1,2 +1,2 @@
var f = Fn.new {} var f = Fn.new {}
System.print(f.call()) // expect: null System.print(f()) // expect: null

View File

@ -1,4 +1,4 @@
var f = Fn.new { var f = Fn.new {
// Hi. // Hi.
} }
System.print(f.call()) // expect: null System.print(f()) // expect: null

View File

@ -1,2 +1,2 @@
Fn.new { System.print("ok") // expect error Fn.new { System.print("ok") // expect error
}.call() }()

View File

@ -1,50 +1,50 @@
var f0 = Fn.new { 0 } var f0 = Fn.new { 0 }
System.print(f0.call()) // expect: 0 System.print(f0()) // expect: 0
var f1 = Fn.new {|a| a } var f1 = Fn.new {|a| a }
System.print(f1.call(1)) // expect: 1 System.print(f1(1)) // expect: 1
var f2 = Fn.new {|a, b| a + b } var f2 = Fn.new {|a, b| a + b }
System.print(f2.call(1, 2)) // expect: 3 System.print(f2(1, 2)) // expect: 3
var f3 = Fn.new {|a, b, c| a + b + c } var f3 = Fn.new {|a, b, c| a + b + c }
System.print(f3.call(1, 2, 3)) // expect: 6 System.print(f3(1, 2, 3)) // expect: 6
var f4 = Fn.new {|a, b, c, d| a + b + c + d } var f4 = Fn.new {|a, b, c, d| a + b + c + d }
System.print(f4.call(1, 2, 3, 4)) // expect: 10 System.print(f4(1, 2, 3, 4)) // expect: 10
var f5 = Fn.new {|a, b, c, d, e| a + b + c + d + e } var f5 = Fn.new {|a, b, c, d, e| a + b + c + d + e }
System.print(f5.call(1, 2, 3, 4, 5)) // expect: 15 System.print(f5(1, 2, 3, 4, 5)) // expect: 15
var f6 = Fn.new {|a, b, c, d, e, f| a + b + c + d + e + f } var f6 = Fn.new {|a, b, c, d, e, f| a + b + c + d + e + f }
System.print(f6.call(1, 2, 3, 4, 5, 6)) // expect: 21 System.print(f6(1, 2, 3, 4, 5, 6)) // expect: 21
var f7 = Fn.new {|a, b, c, d, e, f, g| a + b + c + d + e + f + g } var f7 = Fn.new {|a, b, c, d, e, f, g| a + b + c + d + e + f + g }
System.print(f7.call(1, 2, 3, 4, 5, 6, 7)) // expect: 28 System.print(f7(1, 2, 3, 4, 5, 6, 7)) // expect: 28
var f8 = Fn.new {|a, b, c, d, e, f, g, h| a + b + c + d + e + f + g + h } var f8 = Fn.new {|a, b, c, d, e, f, g, h| a + b + c + d + e + f + g + h }
System.print(f8.call(1, 2, 3, 4, 5, 6, 7, 8)) // expect: 36 System.print(f8(1, 2, 3, 4, 5, 6, 7, 8)) // expect: 36
var f9 = Fn.new {|a, b, c, d, e, f, g, h, i| a + b + c + d + e + f + g + h + i } var f9 = Fn.new {|a, b, c, d, e, f, g, h, i| a + b + c + d + e + f + g + h + i }
System.print(f9.call(1, 2, 3, 4, 5, 6, 7, 8, 9)) // expect: 45 System.print(f9(1, 2, 3, 4, 5, 6, 7, 8, 9)) // expect: 45
var f10 = Fn.new {|a, b, c, d, e, f, g, h, i, j| a + b + c + d + e + f + g + h + i + j } var f10 = Fn.new {|a, b, c, d, e, f, g, h, i, j| a + b + c + d + e + f + g + h + i + j }
System.print(f10.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // expect: 55 System.print(f10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // expect: 55
var f11 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k| a + b + c + d + e + f + g + h + i + j + k } var f11 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k| a + b + c + d + e + f + g + h + i + j + k }
System.print(f11.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)) // expect: 66 System.print(f11(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)) // expect: 66
var f12 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l| a + b + c + d + e + f + g + h + i + j + k + l } var f12 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l| a + b + c + d + e + f + g + h + i + j + k + l }
System.print(f12.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) // expect: 78 System.print(f12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) // expect: 78
var f13 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m| a + b + c + d + e + f + g + h + i + j + k + l + m } var f13 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m| a + b + c + d + e + f + g + h + i + j + k + l + m }
System.print(f13.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)) // expect: 91 System.print(f13(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)) // expect: 91
var f14 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n| a + b + c + d + e + f + g + h + i + j + k + l + m + n } var f14 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n| a + b + c + d + e + f + g + h + i + j + k + l + m + n }
System.print(f14.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)) // expect: 105 System.print(f14(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)) // expect: 105
var f15 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n, o| a + b + c + d + e + f + g + h + i + j + k + l + m + n + o } var f15 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n, o| a + b + c + d + e + f + g + h + i + j + k + l + m + n + o }
System.print(f15.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)) // expect: 120 System.print(f15(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)) // expect: 120
var f16 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p| a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p } var f16 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p| a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p }
System.print(f16.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) // expect: 136 System.print(f16(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) // expect: 136

View File

@ -1,16 +1,16 @@
// Single expression body. // Single expression body.
Fn.new { System.print("ok") }.call() // expect: ok Fn.new { System.print("ok") }() // expect: ok
// Curly body. // Curly body.
Fn.new { Fn.new {
System.print("ok") // expect: ok System.print("ok") // expect: ok
}.call() }()
// Multiple statements. // Multiple statements.
Fn.new { Fn.new {
System.print("1") // expect: 1 System.print("1") // expect: 1
System.print("2") // expect: 2 System.print("2") // expect: 2
}.call() }()
// Extra newlines. // Extra newlines.
Fn.new { Fn.new {
@ -22,4 +22,4 @@ Fn.new {
System.print("2") // expect: 2 System.print("2") // expect: 2
}.call() }()

View File

@ -0,0 +1,11 @@
Fn.new {
var fn = Fn.new {|arg| System.print(arg) }
fn("string") // expect: string
fn = Fn.new {|block| System.print(block()) }
fn { "block" } // expect: block
fn = Fn.new {|a, b, c| System.print("%(a) %(b) %(c())") }
fn(1, 2) { 3 } // expect: 1 2 3
}()

View File

@ -0,0 +1,9 @@
var fn = Fn.new {|arg| System.print(arg) }
fn("string") // expect: string
fn = Fn.new {|block| System.print(block()) }
fn { "block" } // expect: block
fn = Fn.new {|a, b, c| System.print("%(a) %(b) %(c())") }
fn(1, 2) { 3 } // expect: 1 2 3

View File

@ -0,0 +1,27 @@
class CallArg {
static test() {
this("string") // expect: string
}
static call(arg) { System.print(arg) }
}
class CallBlock {
static test() {
this { "block" } // expect: block
}
static call(block) { System.print(block()) }
}
class CallBoth {
static test() {
this(1, 2) { 3 } // expect: 1 2 3
}
static call(a, b, c) { System.print("%(a) %(b) %(c())") }
}
CallArg.test()
CallBlock.test()
CallBoth.test()

View File

@ -1,11 +1,11 @@
class Foo { class Foo {
construct new() { _field = "Foo field" } construct new() { _field = "Foo field" }
closeOverFooGet { closeOverFooGet() {
return Fn.new { Fn.new { _field } } return Fn.new { Fn.new { _field } }
} }
closeOverFooSet { closeOverFooSet() {
return Fn.new { Fn.new { _field = "new foo value" } } return Fn.new { Fn.new { _field = "new foo value" } }
} }
} }
@ -16,21 +16,21 @@ class Bar is Foo {
_field = "Bar field" _field = "Bar field"
} }
closeOverBarGet { closeOverBarGet() {
return Fn.new { Fn.new { _field } } return Fn.new { Fn.new { _field } }
} }
closeOverBarSet { closeOverBarSet() {
return Fn.new { Fn.new { _field = "new bar value" } } return Fn.new { Fn.new { _field = "new bar value" } }
} }
} }
var bar = Bar.new() var bar = Bar.new()
System.print(bar.closeOverFooGet.call().call()) // expect: Foo field System.print(bar.closeOverFooGet()()()) // expect: Foo field
System.print(bar.closeOverBarGet.call().call()) // expect: Bar field System.print(bar.closeOverBarGet()()()) // expect: Bar field
bar.closeOverFooSet.call().call() bar.closeOverFooSet()()()
System.print(bar.closeOverFooGet.call().call()) // expect: new foo value System.print(bar.closeOverFooGet()()()) // expect: new foo value
System.print(bar.closeOverBarGet.call().call()) // expect: Bar field System.print(bar.closeOverBarGet()()()) // expect: Bar field
bar.closeOverBarSet.call().call() bar.closeOverBarSet()()()
System.print(bar.closeOverFooGet.call().call()) // expect: new foo value System.print(bar.closeOverFooGet()()()) // expect: new foo value
System.print(bar.closeOverBarGet.call().call()) // expect: new bar value System.print(bar.closeOverBarGet()()()) // expect: new bar value

View File

@ -3,6 +3,6 @@ var fiber = Fiber.new {
Fiber.yield("result") Fiber.yield("result")
} }
System.print("outer %(fiber.call()) string") System.print("outer %(fiber()) string")
// expect: in fiber // expect: in fiber
// expect: outer result string // expect: outer result string

View File

@ -14,5 +14,5 @@ System.print(variable) // expect: method
Fn.new { Fn.new {
variable = "fn" variable = "fn"
}.call() }()
System.print(variable) // expect: fn System.print(variable) // expect: fn

View File

@ -2,4 +2,4 @@ var variable = "module"
Fn.new { Fn.new {
System.print(variable) // expect: module System.print(variable) // expect: module
}.call() }()

View File

@ -4,4 +4,4 @@ var f = Fn.new {
var variable = "module" var variable = "module"
f.call() // expect: module f() // expect: module

View File

@ -1,3 +1,7 @@
// () has higher precedence than unary.
var fn = Fn.new { 2 }
System.print(-fn()) // expect: -2
// * has higher precedence than +. // * has higher precedence than +.
System.print(2 + 3 * 4) // expect: 14 System.print(2 + 3 * 4) // expect: 14

View File

@ -1,3 +1,3 @@
System.print(Fn.new { System.print(Fn.new {
if (false) "no" else return "ok" if (false) "no" else return "ok"
}.call()) // expect: ok }()) // expect: ok

View File

@ -1,3 +1,3 @@
System.print(Fn.new { System.print(Fn.new {
if (true) return "ok" if (true) return "ok"
}.call()) // expect: ok }()) // expect: ok

View File

@ -1,3 +1,3 @@
System.print(Fn.new { System.print(Fn.new {
while (true) return "ok" while (true) return "ok"
}.call()) // expect: ok }()) // expect: ok

View File

@ -3,4 +3,4 @@ var f = Fn.new {
System.print("bad") System.print("bad")
} }
System.print(f.call()) // expect: ok System.print(f()) // expect: ok

View File

@ -3,4 +3,4 @@ var f = Fn.new {
System.print("bad") System.print("bad")
} }
System.print(f.call()) // expect: null System.print(f()) // expect: null

View File

@ -10,4 +10,4 @@ class Foo {
makeClosure() { Fn.new { @method() } } makeClosure() { Fn.new { @method() } }
} }
Foo.new("value").makeClosure().call() // expect: value Foo.new("value").makeClosure()() // expect: value

View File

@ -1,16 +1,16 @@
class Foo { class Foo {
static initialize { __field = "Foo field" } static initialize() { __field = "Foo field" }
static closeOverGet { static closeOverGet() {
return Fn.new { __field } return Fn.new { __field }
} }
static closeOverSet { static closeOverSet() {
return Fn.new { __field = "new value" } return Fn.new { __field = "new value" }
} }
} }
Foo.initialize Foo.initialize()
System.print(Foo.closeOverGet.call()) // expect: Foo field System.print(Foo.closeOverGet()()) // expect: Foo field
Foo.closeOverSet.call() Foo.closeOverSet()()
System.print(Foo.closeOverGet.call()) // expect: new value System.print(Foo.closeOverGet()()) // expect: new value

View File

@ -4,9 +4,9 @@ class Base {
class Derived is Base { class Derived is Base {
construct new() {} construct new() {}
getClosure { Fn.new { super.toString } } getClosure() { Fn.new { super.toString } }
toString { "Derived" } toString { "Derived" }
} }
var closure = Derived.new().getClosure var closure = Derived.new().getClosure()
System.print(closure.call()) // expect: Base System.print(closure()) // expect: Base

View File

@ -1,6 +1,6 @@
class A { class A {
callSuperToString { callSuperToString {
return Fn.new { super.toString }.call() return Fn.new { super.toString }()
} }
toString { "A.toString" } toString { "A.toString" }

View File

@ -5,4 +5,4 @@ class Foo {
} }
var closure = Foo.new().getClosure() var closure = Foo.new().getClosure()
System.print(closure.call()) // expect: Foo System.print(closure()) // expect: Foo

View File

@ -17,7 +17,7 @@ class Outer {
} }
Inner.new().method Inner.new().method
}.call() }()
} }
toString { "Outer" } toString { "Outer" }

View File

@ -5,4 +5,4 @@ class Foo {
} }
var closure = Foo.new().getClosure var closure = Foo.new().getClosure
System.print(closure.call().call().call()) // expect: Foo System.print(closure()()()) // expect: Foo

View File

@ -1,6 +1,6 @@
Fn.new { Fn.new {
System.print(notDefined) System.print(notDefined)
}.call() }()
// Error on last line because it assumes the variable gets declared later at // Error on last line because it assumes the variable gets declared later at
// the module level. // the module level.
// expect error // expect error

View File

@ -7,7 +7,7 @@ while (i < 4) {
i = i + 1 i = i + 1
} }
for (f in list) f.call() for (f in list) f()
// expect: 2 // expect: 2
// expect: 3 // expect: 3
// expect: 4 // expect: 4

View File

@ -5,6 +5,6 @@ var f = Fn.new {
} }
} }
var g = f.call() var g = f()
g.call() g()
// expect: i // expect: i

View File

@ -5,5 +5,5 @@ var f = Fn.new {
} }
} }
System.print(f.call()) System.print(f())
// expect: i // expect: i

View File

@ -1009,5 +1009,5 @@ Fn.new {
System.print(9) // expect: 9 System.print(9) // expect: 9
System.print(10) // expect: 10 System.print(10) // expect: 10
// 1000 // 1000
}.call() }()

View File

@ -65537,4 +65537,4 @@ var f = Fn.new {
System.print(65536) System.print(65536)
} }
f.call() // expect: 65536 f() // expect: 65536

View File

@ -8,14 +8,14 @@ var a = Fiber.new {
var b = Fiber.new { var b = Fiber.new {
System.print("b before") System.print("b before")
a.call() a()
System.print("b after") System.print("b after")
} }
// All fibers are suspended since they were directly called and not scheduled. // All fibers are suspended since they were directly called and not scheduled.
System.print("before") // expect: before System.print("before") // expect: before
b.call() // expect: b before b() // expect: b before
// expect: a before // expect: a before
// expect: a after // expect: a after
// expect: b after // expect: b after
System.print("done") // expect: done System.print("done") // expect: done