mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Functions take a set number of arguments
This commit is contained in:
@@ -19,13 +19,12 @@ DONE: functions are invoked by calling their names
|
|||||||
DONE: function arguments can have specified types
|
DONE: function arguments can have specified types
|
||||||
DONE: function returns can have specified types
|
DONE: function returns can have specified types
|
||||||
DONE: closures are explicitly supported
|
DONE: closures are explicitly supported
|
||||||
|
DONE: functions are first-class citizens
|
||||||
|
DONE: functions take a set number of parameters
|
||||||
|
|
||||||
|
|
||||||
TODO: functions take a set number of parameters
|
TODO: functions return a set number of values
|
||||||
TODO: functions can return a set number of values
|
|
||||||
TODO: functions are first-class citizens
|
|
||||||
TODO: functions last argument can be a rest parameter
|
TODO: functions last argument can be a rest parameter
|
||||||
TODO: check for wrong number of function parameters
|
|
||||||
|
|
||||||
TODO: Nullish types
|
TODO: Nullish types
|
||||||
TODO: A way to check the type of a variable (typeOf keyword)
|
TODO: A way to check the type of a variable (typeOf keyword)
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ fn doSomething() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Functions can take a number of parameters within the parenthesis following their names, and can return a number of values to the calling context using the return keyword.
|
Functions can take a set number of parameters within the parenthesis following their names, and can return a number of values to the calling context using the return keyword.
|
||||||
|
|
||||||
```
|
```
|
||||||
fn reverseOrder(a, b, c) { //return type isn't required by default
|
fn reverseOrder(a, b, c) { //return type isn't required by default
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
fn name(param1: string, param2: string, param3): string {
|
|
||||||
print "foobar";
|
|
||||||
print param1;
|
|
||||||
return param2;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = name("hello world", "goodnight world");
|
|
||||||
|
|
||||||
print "fizz";
|
|
||||||
print result;
|
|
||||||
print "buzz";
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
fn outer() {
|
|
||||||
fn inner() {
|
|
||||||
print "foo";
|
|
||||||
}
|
|
||||||
|
|
||||||
inner();
|
|
||||||
|
|
||||||
return inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
var handle = outer();
|
|
||||||
|
|
||||||
handle(); //breaks
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
fn make() {
|
|
||||||
var counter = 0;
|
|
||||||
|
|
||||||
fn count() {
|
|
||||||
return counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tally = make();
|
|
||||||
|
|
||||||
print tally();
|
|
||||||
print tally();
|
|
||||||
print tally();
|
|
||||||
print tally();
|
|
||||||
print tally();
|
|
||||||
|
|
||||||
@@ -426,6 +426,25 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//push the argument COUNT to the top of the stack
|
||||||
|
int argumentsCount = findLiteralIndex(&compiler->literalCache, TO_INTEGER_LITERAL(node->fnCall.arguments->fnCollection.count));
|
||||||
|
if (argumentsCount < 0) {
|
||||||
|
argumentsCount = pushLiteralArray(&compiler->literalCache, TO_INTEGER_LITERAL(node->fnCall.arguments->fnCollection.count));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argumentsCount >= 256) {
|
||||||
|
//push a "long" index
|
||||||
|
compiler->bytecode[compiler->count++] = OP_LITERAL_LONG; //1 byte
|
||||||
|
|
||||||
|
*((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)argumentsCount; //2 bytes
|
||||||
|
compiler->count += sizeof(unsigned short);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//push the index
|
||||||
|
compiler->bytecode[compiler->count++] = OP_LITERAL; //1 byte
|
||||||
|
compiler->bytecode[compiler->count++] = (unsigned char)argumentsCount; //1 byte
|
||||||
|
}
|
||||||
|
|
||||||
//call the function
|
//call the function
|
||||||
//DO NOT call the collection, this is done in binary
|
//DO NOT call the collection, this is done in binary
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -750,8 +750,10 @@ static bool execFnCall(Interpreter* interpreter) {
|
|||||||
LiteralArray arguments;
|
LiteralArray arguments;
|
||||||
initLiteralArray(&arguments);
|
initLiteralArray(&arguments);
|
||||||
|
|
||||||
//unpack the arguments
|
Literal stackSize = popLiteralArray(&interpreter->stack);
|
||||||
while (interpreter->stack.count > 1) {
|
|
||||||
|
//unpack the stack of arguments
|
||||||
|
for (int i = 0; i < AS_INTEGER(stackSize); i++) {
|
||||||
pushLiteralArray(&arguments, popLiteralArray(&interpreter->stack)); //NOTE: also reverses the order
|
pushLiteralArray(&arguments, popLiteralArray(&interpreter->stack)); //NOTE: also reverses the order
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,6 +782,19 @@ static bool execFnCall(Interpreter* interpreter) {
|
|||||||
LiteralArray* paramArray = AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
LiteralArray* paramArray = AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
||||||
LiteralArray* returnArray = AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
LiteralArray* returnArray = AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]);
|
||||||
|
|
||||||
|
//check the param total is correct
|
||||||
|
if (paramArray->count != arguments.count * 2) {
|
||||||
|
printf(ERROR "ERROR: Incorrect number of arguments passed to function \"\n");
|
||||||
|
printLiteral(identifier);
|
||||||
|
printf("\"\n" RESET);
|
||||||
|
|
||||||
|
//free, and skip out
|
||||||
|
freeLiteralArray(&arguments);
|
||||||
|
freeInterpreter(&inner);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < paramArray->count; i += 2) { //contents is the indexes of identifier & type
|
for (int i = 0; i < paramArray->count; i += 2) { //contents is the indexes of identifier & type
|
||||||
//declare and define each entry in the scope
|
//declare and define each entry in the scope
|
||||||
if (!declareScopeVariable(inner.scope, paramArray->literals[i], paramArray->literals[i + 1])) {
|
if (!declareScopeVariable(inner.scope, paramArray->literals[i], paramArray->literals[i + 1])) {
|
||||||
|
|||||||
32
test/functions.toy
Normal file
32
test/functions.toy
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//test function return
|
||||||
|
fn testFourtyTwo() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert testFourtyTwo() == 42, "function returns failed";
|
||||||
|
|
||||||
|
|
||||||
|
//test function parameters
|
||||||
|
fn identity(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert identity("hello world") == "hello world", "identity function failed";
|
||||||
|
|
||||||
|
|
||||||
|
//test closures
|
||||||
|
fn make() {
|
||||||
|
var counter = 0;
|
||||||
|
|
||||||
|
fn count() {
|
||||||
|
return ++counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tally = make();
|
||||||
|
|
||||||
|
assert tally() == 1 && tally() == 2, "Closures failed";
|
||||||
|
|
||||||
|
print "All good";
|
||||||
Reference in New Issue
Block a user