Remove the per-array type category so arrays can mix types like structs. Add 13 passing and 125 expected-failure duskscript test fixtures with a table-driven runner. Also includes the in-progress entity/physics and archive moves from the working tree. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
185 lines
3.8 KiB
Plaintext
185 lines
3.8 KiB
Plaintext
// Declaration, calling and returning
|
|
function add(a, b) {
|
|
return a + b;
|
|
}
|
|
assert(add(1, 2) == 3);
|
|
assert(add("a", "b") == "ab");
|
|
assert(add(add(1, 2), add(3, 4)) == 10);
|
|
|
|
// Functions are there from the start of their block
|
|
assert(later(2) == 4);
|
|
function later(n) {
|
|
return n * 2;
|
|
}
|
|
|
|
// No return, or a bare return, gives undefined
|
|
function nothing() {
|
|
}
|
|
function bare() {
|
|
return;
|
|
}
|
|
assert(isundefined(nothing()));
|
|
assert(isundefined(bare()));
|
|
function early(flag) {
|
|
if(flag) return "early";
|
|
return "late";
|
|
}
|
|
assert(early(true) == "early");
|
|
assert(early(false) == "late");
|
|
|
|
// Recursion
|
|
function factorial(n) {
|
|
if(n <= 1) return 1;
|
|
return n * factorial(n - 1);
|
|
}
|
|
assert(factorial(1) == 1);
|
|
assert(factorial(5) == 120);
|
|
function countdown(n) {
|
|
if(n == 0) return 0;
|
|
return 1 + countdown(n - 1);
|
|
}
|
|
assert(countdown(5) == 5);
|
|
|
|
// Default parameters
|
|
function greet(name, greeting = "Hello") {
|
|
return greeting + " " + name;
|
|
}
|
|
assert(greet("Ann") == "Hello Ann");
|
|
assert(greet("Ann", "Hi") == "Hi Ann");
|
|
function scale(value, factor = 2, offset = 1) {
|
|
return value * factor + offset;
|
|
}
|
|
assert(scale(3) == 7);
|
|
assert(scale(3, 3) == 10);
|
|
assert(scale(3, 3, 0) == 9);
|
|
function defaultsToArray(list = [1, 2]) {
|
|
return len(list);
|
|
}
|
|
assert(defaultsToArray() == 2);
|
|
assert(defaultsToArray([1]) == 1);
|
|
|
|
// Extra arguments are ignored
|
|
function one(a) {
|
|
return a;
|
|
}
|
|
assert(one(1, 2, 3) == 1);
|
|
|
|
// Undefined argument takes the default
|
|
assert(greet("Bo", undefined) == "Hello Bo");
|
|
|
|
// Functions are values
|
|
var fn = add;
|
|
assert(fn(2, 3) == 5);
|
|
assert(isfunction(fn));
|
|
assert(isfunction(add));
|
|
assert(!isfunction(1));
|
|
assert(!isfunction("add"));
|
|
assert(!isfunction(null));
|
|
var anon = function(x) { return x * x; };
|
|
assert(anon(4) == 16);
|
|
assert(isfunction(anon));
|
|
var list = [function() { return 1; }, function() { return 2; }];
|
|
assert(list[0]() == 1);
|
|
assert(list[1]() == 2);
|
|
var table = {double: function(x) { return x * 2; }, name: "t"};
|
|
assert(table.double(4) == 8);
|
|
assert(table["double"](5) == 10);
|
|
|
|
// Passing and returning functions
|
|
function apply(f, v) {
|
|
return f(v);
|
|
}
|
|
assert(apply(anon, 5) == 25);
|
|
assert(apply(function(v) { return v + 1; }, 1) == 2);
|
|
function pick(flag) {
|
|
if(flag) return add;
|
|
return anon;
|
|
}
|
|
assert(pick(true)(1, 1) == 2);
|
|
assert(pick(false)(3) == 9);
|
|
|
|
// A function sees and changes the variables of the script
|
|
var counter = 0;
|
|
function increment() {
|
|
counter++;
|
|
return counter;
|
|
}
|
|
increment();
|
|
increment();
|
|
assert(counter == 2);
|
|
assert(increment() == 3);
|
|
|
|
// Arguments are by value, but arrays and structs are shared
|
|
function reassign(v) {
|
|
v = 99;
|
|
return v;
|
|
}
|
|
var original = 1;
|
|
assert(reassign(original) == 99);
|
|
assert(original == 1);
|
|
function append(l) {
|
|
push(l, 4);
|
|
}
|
|
var shared = [1, 2, 3];
|
|
append(shared);
|
|
assert(len(shared) == 4);
|
|
function rename(s) {
|
|
s.name = "changed";
|
|
}
|
|
var record = {name: "start"};
|
|
rename(record);
|
|
assert(record.name == "changed");
|
|
function replace(l) {
|
|
l = [];
|
|
return len(l);
|
|
}
|
|
assert(replace(shared) == 0);
|
|
assert(len(shared) == 4);
|
|
|
|
// Locals are not shared between calls
|
|
function local() {
|
|
var inner = 0;
|
|
inner++;
|
|
return inner;
|
|
}
|
|
assert(local() == 1);
|
|
assert(local() == 1);
|
|
|
|
// Parameter named like an outer variable
|
|
var value = "outer";
|
|
function shadows(value) {
|
|
return value;
|
|
}
|
|
assert(shadows("inner") == "inner");
|
|
assert(value == "outer");
|
|
|
|
// Name of a function
|
|
function named() {}
|
|
assert(tostr(named) == "named");
|
|
|
|
// Mutual recursion
|
|
function isEven(n) {
|
|
if(n == 0) return true;
|
|
return isOdd(n - 1);
|
|
}
|
|
function isOdd(n) {
|
|
if(n == 0) return false;
|
|
return isEven(n - 1);
|
|
}
|
|
assert(isEven(4));
|
|
assert(isOdd(3));
|
|
assert(!isEven(3));
|
|
|
|
// inline and noinline
|
|
inline function twice(n) {
|
|
return n * 2;
|
|
}
|
|
noinline function thrice(n) {
|
|
return n * 3;
|
|
}
|
|
assert(twice(4) == 8);
|
|
assert(thrice(4) == 12);
|
|
var t = 0;
|
|
for(var i = 0; i < 3; i++) t += twice(i) + thrice(i);
|
|
assert(t == 0 + 5 + 10);
|