Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closures: Added tests from the current closures PR #1393

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions tests/compiler/closure-common-js-patterns.json
@@ -0,0 +1,10 @@
{
"asc_flags": [
"--runtime full",
"--use ASC_RTRACE=1"
],
"stderr": [
"AS100: Not implemented: Closures",
"AS100: Not implemented: Closures"
]
}
183 changes: 183 additions & 0 deletions tests/compiler/closure-common-js-patterns.ts
@@ -0,0 +1,183 @@
// NOTE torch2424 6/15/20: This test has a lot of errors skipped. Closures is currently a WIP

// Common use cases / concepts for closures, as covered in articles like:
// https://medium.com/@dis_is_patrick/practical-uses-for-closures-c65640ae7304
// https://stackoverflow.com/questions/2728278/what-is-a-practical-use-for-a-closure-in-javascript
// https://softwareengineering.stackexchange.com/questions/285941/why-would-a-program-use-a-closure
// https://medium.com/@prashantramnyc/what-is-an-iife-in-javascript-24baf0febf08

// Currently, IIFEs and simple Function Factories work
// But my advanced Function Factory Pub Sub, and weird function namespacing does not
// Due to runtime and/or compilation errors :)

// IIFE (Immediately Invoked function expressions)
// Used for encapsulating data usually

// Simple IIFE
let myData = ((): boolean => {
return true;
})();

assert(myData == true);

// Constructor IIFE?
// Don't know why someone wouldn't just use their class, but yeah

class IIFEReturn {
myBool: boolean
myFunc: (x: i32) => i32
}

let myInstanceThing = ((): IIFEReturn => {
return {
myBool: true,
myFunc: (x: i32) => {
return x + 1;
}
};
})();

assert(myInstanceThing.myBool == true);
assert(myInstanceThing.myFunc(24) == 25);

// Function Factories
// Closures that create specific functions

// Simple function that will change depending on input
type generatedFunc = () => i32;
let myFactory = (x: i32): generatedFunc => {
let myFunc = (): i32 => {
return 24 + x;
};

return myFunc;
};

let generatedPlusOne: generatedFunc = myFactory(1);
let generatedPlusTwo: generatedFunc = myFactory(2);

// For some reason, couldn't do
// Cannot invoke an expression whose type lacks a call signature. Type 'closure-common-js-patterns/myFactory' has no compatible call signatures.
// assert(myFactory(1)() == 25);
assert(generatedPlusOne() == 25);
assert(generatedPlusTwo() == 26);

// I often will use this for like Pub/Sub stuff

type SubFunc = () => void;
type UnSubFunc = () => void;
let subscriptions = new Array<SubFunc>();
let globalSubVar: i32 = 0;

function subscribe(funcToCallOnPub: SubFunc): UnSubFunc {
subscriptions.push(funcToCallOnPub);
return (): void => {
let funcIndex = subscriptions.indexOf(funcToCallOnPub);
subscriptions.splice(funcIndex, 1);
};
}

function publish(): void {
for(let i = 0; i < subscriptions.length; i++) {
// Can't call directly? Get a Type error
// ERROR TS2757: Type '() => void' has no call signatures.
// Noticed some other weird type errors if I don't declare the function type
// But I also am meh at typescripte signatures haha!
// subscriptions[i]();

let subFunc = subscriptions[i];
subFunc();
}
}

let plusOne = (): void => {
globalSubVar += 1;
};

let plusTwo = (): void => {
globalSubVar += 1;
};


let unsubPlusOne: () => void = subscribe(plusOne);
let unsubPlusTwo: () => void = subscribe(plusTwo);

assert(globalSubVar == 0);
assert(subscriptions.length == 2);

publish();

assert(globalSubVar == 3);
assert(subscriptions.length == 2);

unsubPlusOne();

assert(globalSubVar == 3);
assert(subscriptions.length == 1);

publish();

assert(globalSubVar == 5);
assert(subscriptions.length == 1);

unsubPlusTwo();

assert(globalSubVar == 5);
assert(subscriptions.length == 0);

publish();

assert(globalSubVar == 5);
assert(subscriptions.length == 0);


// TODO (torch2424 6/15/20): Uncomment this test once closures is fully implemented
/*

// Namespacing private functions
// Again, kind of weird, they should probably just make a class, but it's another interesting test

class Chunk {
totalSize: i32;
usedSize: i32;
write: (size: i32) => void;
}

let getChunk = (): Chunk => {
let chunk: Chunk = {
totalSize: 1024,
usedSize: 0,
write: (x: i32): void => {}
};

let growChunk = (): void => {
chunk.totalSize += 1024;
}

let allocateForChunk = (amount: i32): void => {
if (chunk.usedSize + amount <= chunk.totalSize) {
chunk.usedSize += amount;
} else {
// growChunk(chunk);
// allocateForChunk(chunk, amount);
}
}

chunk.write = (x: i32) => {
allocateForChunk(x);
}

return chunk;

}

let myChunk: Chunk = getChunk();

assert(myChunk.totalSize == 1024);
assert(myChunk.usedSize == 0);

myChunk.write(1025);

assert(myChunk.totalSize == 2048);
assert(myChunk.usedSize == 1025);
*/
Empty file.
9 changes: 9 additions & 0 deletions tests/compiler/closure-limitations-runtime.json
@@ -0,0 +1,9 @@
{
"asc_flags": [
"--runtime full"
],
"stderr": [
"AS100: Not implemented: Closures"
],
"skipInstantiate": true
}
7 changes: 7 additions & 0 deletions tests/compiler/closure-limitations-runtime.ts
@@ -0,0 +1,7 @@
export function exportedClosureReturns(): (value: i32) => i32 {
var $local0 = 0;
return function inner(value: i32): i32 {
return $local0;
};
}
exportedClosureReturns();
Empty file.
11 changes: 11 additions & 0 deletions tests/compiler/closure-limitations.json
@@ -0,0 +1,11 @@
{
"asc_flags": [
"--runtime none"
],
"stderr": [
"AS100: Not implemented: Closures",
"AS100: Not implemented: Closures",
"AS100: Not implemented: Closures",
"EOF"
]
}
22 changes: 22 additions & 0 deletions tests/compiler/closure-limitations.ts
@@ -0,0 +1,22 @@
function closureWrites(): (value: i32) => i32 {
var $local0 = 0;
return function inner(value: i32) {
$local0 = $local0 + 1;
return $local0;
};
}
closureWrites();

function inScopeNestedCalls(): (value: i32) => i32 {
var x = 0;
var f = (): i32 => {
return x;
};
var p = (value: i32): i32 => {
return f();
};
return p;
}
inScopeNestedCalls();

ERROR("EOF");
6 changes: 6 additions & 0 deletions tests/compiler/closure-passing-functions.json
@@ -0,0 +1,6 @@
{
"asc_flags": [
"--runtime full",
"--use ASC_RTRACE=1"
]
}