mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
Update playground to use generators
This commit is contained in:
@@ -365,9 +365,17 @@ impl ModuleCompiler {
|
||||
use swc_ecma_ast::ExportSpecifier::*;
|
||||
use swc_ecma_ast::ModuleExportName;
|
||||
|
||||
if en.type_only {
|
||||
return;
|
||||
}
|
||||
|
||||
for specifier in &en.specifiers {
|
||||
match specifier {
|
||||
Named(named) => {
|
||||
if named.is_type_only {
|
||||
continue;
|
||||
}
|
||||
|
||||
let orig_name = match &named.orig {
|
||||
ModuleExportName::Ident(ident) => ident,
|
||||
ModuleExportName::Str(_) => {
|
||||
|
||||
@@ -1,38 +1,9 @@
|
||||
export default function main() {
|
||||
return [...new Range(0, 10)];
|
||||
return [...range(0, 10)];
|
||||
}
|
||||
|
||||
class Range {
|
||||
start: number;
|
||||
end: number;
|
||||
|
||||
constructor(start: number, end: number) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return new RangeIterator(this.start, this.end);
|
||||
}
|
||||
}
|
||||
|
||||
class RangeIterator {
|
||||
value: number;
|
||||
end: number;
|
||||
|
||||
constructor(value: number, end: number) {
|
||||
this.value = value;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
next() {
|
||||
const done = this.value >= this.end;
|
||||
const res = { value: this.value, done };
|
||||
|
||||
if (!done) {
|
||||
this.value++;
|
||||
}
|
||||
|
||||
return res;
|
||||
function* range(start: number, end: number) {
|
||||
for (let i = start; i < end; i++) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { NotNullish } from "../lib/util.ts";
|
||||
import type { NotNullish } from "../lib/mod.ts";
|
||||
|
||||
export default function main() {
|
||||
let a = new SmallQueue(["item1"]);
|
||||
|
||||
@@ -20,21 +20,21 @@ export default class BinaryTree<T extends NotNullish> {
|
||||
}
|
||||
}
|
||||
|
||||
toArray() {
|
||||
let res: T[] = [];
|
||||
|
||||
*[Symbol.iterator](): Generator<T> {
|
||||
if (this.left) {
|
||||
res.push(...this.left.toArray());
|
||||
for (const value of this.left) {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.value !== undefined) {
|
||||
res.push(this.value);
|
||||
if (this.value) {
|
||||
yield this.value;
|
||||
}
|
||||
|
||||
if (this.right) {
|
||||
res.push(...this.right.toArray());
|
||||
for (const value of this.right) {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
5
website/src/playground/files/root/lib/mod.ts
Normal file
5
website/src/playground/files/root/lib/mod.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export { default as BinaryTree } from "./BinaryTree.ts";
|
||||
export { type NotNullish } from "./util.ts";
|
||||
export { factorize, factorizeAsPowers, primes, isPrime } from "./primes.ts";
|
||||
|
||||
// Note: `export *` would be used here, but it isn't implemented yet.
|
||||
@@ -1,159 +1,85 @@
|
||||
export function factorize(n: number): number[] {
|
||||
let factors: number[] = [];
|
||||
let p = 2;
|
||||
export function* factorize(n: number) {
|
||||
for (const p of primes()) {
|
||||
if (p * p > n) {
|
||||
yield n;
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
while (n % p === 0) {
|
||||
factors.push(p);
|
||||
yield p;
|
||||
n /= p;
|
||||
}
|
||||
|
||||
if (n === 1) {
|
||||
return factors;
|
||||
}
|
||||
|
||||
p = nextOddPrime(p);
|
||||
|
||||
if (p * p > n) {
|
||||
factors.push(n);
|
||||
return factors;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function factorizeAsPowers(n: number): [number, number][] {
|
||||
export function* factorizeAsPowers(n: number) {
|
||||
const factors = factorize(n);
|
||||
|
||||
if (factors.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result: [number, number][] = [];
|
||||
let currentFactor = factors[0];
|
||||
let currentFactor: number | undefined;
|
||||
let currentPower = 1;
|
||||
|
||||
for (let i = 1; i < factors.length; i++) {
|
||||
const factor = factors[i];
|
||||
for (const factor of factors) {
|
||||
currentFactor = factor;
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentFactor === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const factor of factors) {
|
||||
if (factor === currentFactor) {
|
||||
currentPower += 1;
|
||||
} else {
|
||||
result.push([currentFactor, currentPower]);
|
||||
yield [currentFactor, currentPower];
|
||||
currentFactor = factor;
|
||||
currentPower = 1;
|
||||
}
|
||||
}
|
||||
|
||||
result.push([currentFactor, currentPower]);
|
||||
|
||||
return result;
|
||||
yield [currentFactor, currentPower];
|
||||
}
|
||||
|
||||
export function nextOddPrime(n: number): number {
|
||||
n += 1 + (n % 2); // Next odd number
|
||||
export function* primes() {
|
||||
yield 2;
|
||||
yield 3;
|
||||
yield 5;
|
||||
yield 7;
|
||||
yield 11;
|
||||
yield 13;
|
||||
yield 17;
|
||||
yield 19;
|
||||
yield 23;
|
||||
yield 29;
|
||||
|
||||
while (!isOddPrime(n)) {
|
||||
n += 2;
|
||||
}
|
||||
let base = 30;
|
||||
let offsets = [1, 7, 11, 13, 17, 19, 23, 29];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
export function isOddPrime(n: number): boolean {
|
||||
let i = 3;
|
||||
|
||||
while (i * i <= n) {
|
||||
if (n % i === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i += 2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export class PrimeGenerator {
|
||||
pcg: PrimeCandidatesGenerator;
|
||||
|
||||
constructor() {
|
||||
this.pcg = new PrimeCandidatesGenerator();
|
||||
}
|
||||
|
||||
next() {
|
||||
while (true) {
|
||||
const candidate = this.pcg.next();
|
||||
while (true) {
|
||||
for (const offset of offsets) {
|
||||
let candidate = base + offset;
|
||||
|
||||
if (isPrime(candidate)) {
|
||||
return candidate;
|
||||
yield candidate;
|
||||
}
|
||||
}
|
||||
|
||||
base += 30;
|
||||
}
|
||||
}
|
||||
|
||||
export function isPrime(n: number) {
|
||||
let pcg = new PrimeCandidatesGenerator();
|
||||
|
||||
while (true) {
|
||||
const pc = pcg.next();
|
||||
|
||||
if (pc * pc > n) {
|
||||
for (const p of primes()) {
|
||||
if (p * p > n) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (n % pc === 0) {
|
||||
if (n % p === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class PrimeCandidatesGenerator {
|
||||
gen: Gen235 | GenMod30;
|
||||
|
||||
constructor() {
|
||||
this.gen = new Gen235();
|
||||
}
|
||||
|
||||
next() {
|
||||
let c = this.gen.next();
|
||||
|
||||
if (c !== undefined) {
|
||||
return c;
|
||||
}
|
||||
|
||||
this.gen = new GenMod30();
|
||||
return this.gen.next();
|
||||
}
|
||||
}
|
||||
|
||||
class Gen235 {
|
||||
nums: number[];
|
||||
i: number;
|
||||
|
||||
constructor() {
|
||||
this.nums = [2, 3, 5];
|
||||
this.i = 0;
|
||||
}
|
||||
|
||||
next() {
|
||||
return this.nums[this.i++];
|
||||
}
|
||||
}
|
||||
|
||||
class GenMod30 {
|
||||
nums: number[];
|
||||
i: number;
|
||||
|
||||
constructor() {
|
||||
this.nums = [1, 7, 11, 13, 17, 19, 23, 29];
|
||||
this.i = 1;
|
||||
}
|
||||
|
||||
next() {
|
||||
const rem = this.i % 8;
|
||||
const rounds = (this.i - rem) / 8;
|
||||
this.i++;
|
||||
|
||||
return 30 * rounds + this.nums[rem];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// language itself. In JavaScript you'd need to carefully follow the functional
|
||||
// rules, but in ValueScript it's free.
|
||||
|
||||
import BinaryTree from "../lib/BinaryTree.ts";
|
||||
import { BinaryTree } from "../lib/mod.ts";
|
||||
|
||||
export default function main() {
|
||||
let tree = new BinaryTree<number>();
|
||||
@@ -21,7 +21,7 @@ export default function main() {
|
||||
tree.insert(3);
|
||||
tree.insert(4);
|
||||
|
||||
return [treeSnapshot.toArray(), tree.toArray()];
|
||||
return [[...treeSnapshot], [...tree]];
|
||||
// JavaScript: [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
|
||||
// ValueScript: [[1, 2, 5], [1, 2, 3, 4, 5]]
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function () {
|
||||
nums.sort(), // [1, 10, 3]
|
||||
"b" + "a" + +"a" + "a", // "baNaNa"
|
||||
];
|
||||
// JavaScript and ValueScript agree on these.
|
||||
// JavaScript and ValueScript agree on these.
|
||||
}
|
||||
|
||||
// We're not sure yet where exactly to draw this line. Another notable example
|
||||
|
||||
@@ -2,28 +2,24 @@
|
||||
//
|
||||
// In this example, we import `factorize` from the primes module. In the
|
||||
// assembly, you can see `factorize` has been included, as well as the
|
||||
// `nextOddPrime` and `isOddPrime` functions it depends on.
|
||||
// `primes` and `isPrime` functions it depends on.
|
||||
//
|
||||
// However, the primes module also defines:
|
||||
// - `factorizeAsPowers`
|
||||
// - `PrimeGenerator`
|
||||
// - `PrimeCandidatesGenerator`
|
||||
// - `Gen235`
|
||||
// - `GenMod30`
|
||||
//
|
||||
// These definitions are not included, because the definitions exported by this
|
||||
// module do not need them. Omitting those unused definitions reduces the
|
||||
// bytecode for this module from 1,091 to 295 bytes.
|
||||
// bytecode for this module from 1,071 to 413 bytes.
|
||||
|
||||
import { factorize } from "../lib/primes.ts";
|
||||
import { factorize } from "../lib/mod.ts";
|
||||
|
||||
// It's not just the default export that matters. If you uncomment this line,
|
||||
// the assembly will also include `PrimeCandidatesGenerator`, even though it's
|
||||
// not used anywhere else.
|
||||
// export { PrimeCandidatesGenerator } from "../lib/primes";
|
||||
// the assembly will also include `BinaryTree`, even though it's not used
|
||||
// anywhere else.
|
||||
// export { BinaryTree } from "../lib/mod.ts";
|
||||
|
||||
export default function main() {
|
||||
return factorize(18); // [2, 3, 3], because 2 * 3 * 3 = 18
|
||||
return [...factorize(18)]; // [2, 3, 3], because 2 * 3 * 3 = 18
|
||||
}
|
||||
|
||||
// These functions are also not in the assembly, because none of our exports use
|
||||
|
||||
Reference in New Issue
Block a user