Skip to content

Commit

Permalink
rollup and ts config improved; build for ES2017; factorial example im…
Browse files Browse the repository at this point in the history
…proved; allow to cancel input
  • Loading branch information
benchmarko committed Feb 9, 2025
1 parent bd21102 commit f14d339
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 110 deletions.
152 changes: 81 additions & 71 deletions dist/examples/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -1519,13 +1519,32 @@ PRINT
'
DEF FNnumStr$(x) = RIGHT$(STR$(x), LEN(STR$(x)) - 1)
'
PRINT "Properties of "; FNnumStr$(n); "!:"
GOSUB 400 ' number of digits of n!
GOSUB 500 ' trailing zeroes of n! (for checking the result)
PRINT
FRAME
GOSUB 1000 ' algorithm1
PRINT
FRAME
GOSUB 2000 ' algorithm2
END
'
REM Calculate number of digits
REM https://www.geeksforgeeks.org/count-digits-in-a-factorial-using-logarithm/
400 digits = 0
FOR i = 2 TO n
digits = digits + LOG10(i)
NEXT
digits = INT(digits) + 1
'or use Stirling's formula:
econst = 2.718281828459045
digits2 = n * LOG10(n / econst) + LOG10(2 * PI * n) / 2.0
digits2 = INT(digits2+1)
if digits<>digits2 THEN ?"digits calculation differs:"; digits; digits2
PRINT "Number of digits:"; digits
RETURN
'
REM Calculate number of trailing zeroes (to check the result)
REM https://www.geeksforgeeks.org/count-trailing-zeroes-factorial-number/
500 trailz = 0
Expand All @@ -1534,18 +1553,13 @@ WHILE INT(n / i) >= 1
trailz = trailz + INT(n / i)
i = i * 5
WEND
PRINT "Number of trailing zeroes for "; FNnumStr$(n); "!:"; trailz
PRINT "Number of trailing zeroes:"; trailz
RETURN
'
REM factorial 1
1000 t = TIME
REM Calculate number of 5-digit blocks
l = 1
FOR i = 2 TO n
l = l + LOG10(i)
NEXT
ri = INT(l / 5 + 1)
DIM r(ri)
ri = INT(digits / 5) - (digits mod 5 <> 0): 'number of 5-digit blocks
DIM r(ri + 1): 'one more to allow carry
r(1) = 1
'
REM Calculate factorial using sum of logarithms
Expand Down Expand Up @@ -1592,20 +1606,15 @@ RETURN
REM factorial2
REM based on: https://www.geeksforgeeks.org/factorial-large-number/
2000 t = TIME
l = 1
FOR i = 2 TO n
l = l + LOG10(i)
NEXT
ri2 = INT(l) + 1
DIM res(ri2)
DIM res(digits)
res(1) = 1
resSize = 1
FOR x = 2 TO n
carry = 0
FOR i = 1 TO resSize
prod = res(i) * x + carry
res(i) = prod MOD 10
carry = INT(prod / 10)
res(i) = prod - carry * 10
NEXT i
WHILE carry > 0
resSize = resSize + 1
Expand Down Expand Up @@ -2443,6 +2452,63 @@ END
'
`);

cpcBasic.addItem("", `
REM sierpin - Sierpinski triangle
REM see also: https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle
DEG
MODE 2
DIM cx(5),cy(5),r(5),lc(5),s$(80,25),smc(25)
cx(1)=320*80/640:cy(1)=140*25/400
r(1)=75:r(2)=40:r(3)=20:r(4)=12:r(5)=8
'
sa=120
st=1
GOSUB 800: 'init
GOSUB 1000: 'compute
GOSUB 2000: 'output
END
'
' Initialize output array
800 FOR r1=1 TO 25
FOR c1=1 TO 79
s$(c1,r1)=" "
NEXT
NEXT
RETURN
'
' Compute
1000 cx1=ROUND(cx(st))
cy1=ROUND((25-cy(st)))
'lc(st)=0
s$(cx1,cy1)=chr$(48+st)
IF cx1>smc(cy1) THEN smc(cy1)=cx1 'update max column
IF st<5 THEN GOSUB 2000:FRAME: 'intermediate output
IF st=5 THEN RETURN
lc(st)=0
start=1
WHILE (lc(st) MOD 360)<>0 OR start=1
start=0
cx(st+1)=cx(st)+1.7*80/640*r(st)*SIN(sa+lc(st))
cy(st+1)=cy(st)+1.7*25/400*r(st)*COS(sa+lc(st))
st=st+1
GOSUB 1000 'recursive call
st=st-1
lc(st)=lc(st)+2*sa
WEND
RETURN
'
' Output
2000 CLS
FOR r1=1 TO 25
FOR c1=1 TO smc(r1)
PRINT s$(c1,r1);
NEXT
PRINT
NEXT
RETURN
'
`);

cpcBasic.addItem("", `
REM sievebe - Sieve Benchmark
MODE 2
Expand Down Expand Up @@ -2540,62 +2606,6 @@ DATA -1,-1,-1: '"end"
'
`);

cpcBasic.addItem("", `
REM test1 - Test 1
DEG
MODE 2
DIM cx(5),cy(5),r(5),lc(5),s$(80,25),smc(25)
cx(1)=320*80/640:cy(1)=140*25/400
r(1)=75:r(2)=40:r(3)=20:r(4)=12:r(5)=8
'
sa=120
st=1
GOSUB 800: 'init
GOSUB 1000: 'compute
GOSUB 2000: 'output
END
'
' Initialize output array
800 FOR r1=1 TO 25
FOR c1=1 TO 79
s$(c1,r1)=" "
NEXT
NEXT
RETURN
'
' Compute
1000 cx1=ROUND(cx(st))
cy1=ROUND((25-cy(st)))
'lc(st)=0
s$(cx1,cy1)=chr$(48+st)
IF cx1>smc(cy1) THEN smc(cy1)=cx1 'update max column
IF st<5 THEN GOSUB 2000:FRAME: 'intermediate output
IF st=5 THEN RETURN
lc(st)=0
start=1
WHILE (lc(st) MOD 360)<>0 OR start=1
start=0
cx(st+1)=cx(st)+1.7*80/640*r(st)*SIN(sa+lc(st))
cy(st+1)=cy(st)+1.7*25/400*r(st)*COS(sa+lc(st))
st=st+1
GOSUB 1000 'recursive call
st=st-1
lc(st)=lc(st)+2*sa
WEND
RETURN
'
' Output
2000 CLS
FOR r1=1 TO 25
FOR c1=1 TO smc(r1)
PRINT s$(c1,r1);
NEXT
PRINT
NEXT
RETURN
'
`);

cpcBasic.addItem("", `
10 REM testinpu - Test Input
20 CLS
Expand Down
2 changes: 1 addition & 1 deletion dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="locobasic.css">
<title>LocoBasic v0.1.35</title>
<title>LocoBasic v0.1.36</title>
</head>

<body>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "locobasic",
"version": "0.1.35",
"version": "0.1.36",
"description": "# LocoBasic - Loco BASIC",
"type": "commonjs",
"scripts": {
Expand Down
10 changes: 7 additions & 3 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default [
input: 'src/main.ts', // main entry
output: {
file: 'dist/locobasic.js',
format: 'umd', // "es" ECMAScript-Module
format: 'umd',
sourcemap: true,
name: 'locobasic',
globals: {
Expand All @@ -19,11 +19,15 @@ export default [
input: "./src/UI/UI.ts", // main entry
output: {
file: "dist/locobasicUI.js",
format: "umd", // "es" ECMAScript-Module
format: "umd",
sourcemap: true,
name: "locobasicUI"
},
plugins: [typescript()]
plugins: [
typescript({
tsconfig: "./src/UI/tsconfig.json"
})
]
}

];
6 changes: 3 additions & 3 deletions src/BasicVmBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ export class BasicVmBrowser extends BasicVmCore {
/**
* Prompts the user with a message and returns the input.
* @param msg - The message to prompt.
* @returns The user input.
* @returns A promise that resolves to the user input or null if canceled.
*/
public fnOnPrompt(msg: string): string | null {
public async fnOnPrompt(msg: string): Promise<string | null> {
const input = this.ui.prompt(msg);
return input;
return Promise.resolve(input);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/BasicVmCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class BasicVmCore implements IVmAdmin {
// override
}

protected fnOnPrompt(_msg: string): string | null { // eslint-disable-line @typescript-eslint/no-unused-vars
protected async fnOnPrompt(_msg: string): Promise<string | null> { // eslint-disable-line @typescript-eslint/no-unused-vars
// override
return "";
}
Expand Down Expand Up @@ -133,7 +133,7 @@ export class BasicVmCore implements IVmAdmin {
this.output += args.join('');
}

public prompt(msg: string): string | null {
public prompt(msg: string): Promise<string | null> {
this.flush();
return this.fnOnPrompt(msg);
};
Expand Down
4 changes: 2 additions & 2 deletions src/BasicVmNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ export class BasicVmNode extends BasicVmCore {
console.log(msg.replace(/\n$/, ""));
}

public fnOnPrompt(msg: string): string {
public async fnOnPrompt(msg: string): Promise<string> {
console.log(msg);
return "";
return Promise.resolve("");
}

public fnGetPenColor(num: number): string {
Expand Down
2 changes: 1 addition & 1 deletion src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface IVm {
paper(color: number): void;
pen(color: number): void;
print(_msg: string): void;
prompt(_msg: string): string | null;
prompt(_msg: string): Promise<string | null>;
}

export interface IVmAdmin extends IVm {
Expand Down
2 changes: 1 addition & 1 deletion src/NodeParts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const dummyVm: DummyVm = {
paper(num: number) { this.debug("paper:", num); },
pen(num: number) { this.debug("pen:", num); },
print(...args: (string | number)[]) { this._output += args.join(''); },
prompt(msg: string) { console.log(msg); return ""; }
async prompt(msg: string) { console.log(msg); return ""; }
};

export class NodeParts {
Expand Down
28 changes: 16 additions & 12 deletions src/Semantics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function getCodeSnippets() {
const _data: (string | number)[] = [];
let _dataPtr = 0;
const _restoreMap: Record<string, number> = {};
const frame = async () => {}; // dummy

const codeSnippets = {
bin$: function bin$(num: number, pad: number = 0): string {
Expand Down Expand Up @@ -42,7 +43,7 @@ function getCodeSnippets() {
_o.flush();
return "end";
},
frame: function frame() { // async
frame: async function frame() {
_o.flush();
return new Promise<void>(resolve => setTimeout(() => resolve(), Date.now() % 50));
},
Expand All @@ -52,13 +53,17 @@ function getCodeSnippets() {
hex$: function hex$(num: number, pad?: number) {
return num.toString(16).toUpperCase().padStart(pad || 0, "0");
},
input: function input(msg: string, isNum: boolean) { // async
_o.flush();
return new Promise(resolve => setTimeout(() => {
const input = _o.prompt(msg);
resolve(isNum ? Number(input) : input);
}, 5));
},
input: async function input(msg: string, isNum: boolean) {
await frame();
const input = await _o.prompt(msg);
if (input === null) {
throw new Error("Input canceled");
} else if (isNum && isNaN(Number(input))) {
throw new Error("Invalid number input");
} else {
return isNum ? Number(input) : input;
}
},
mid$Assign: function mid$Assign(s: string, start: number, newString: string, len?: number) {
start -= 1;
len = Math.min(len ?? newString.length, newString.length, s.length - start);
Expand Down Expand Up @@ -225,11 +230,9 @@ function getSemantics(semanticsHelper: ISemanticsHelper): ActionDict<string> {
if (instrMap[key]) {
const code = String((codeSnippets[key as keyof typeof codeSnippets]).toString());
const adaptedCode = trimIndent(code);
if (adaptedCode.includes("Promise") || adaptedCode.includes("await")) {
lineList.push("async " + adaptedCode);
lineList.push(adaptedCode);
if (adaptedCode.startsWith("async ")) {
needsAsync = true;
} else {
lineList.push(adaptedCode);
}
}
}
Expand Down Expand Up @@ -507,6 +510,7 @@ function getSemantics(semanticsHelper: ISemanticsHelper): ActionDict<string> {

Input(_inputLit: Node, message: Node, _semi: Node, e: Node) {
semanticsHelper.addInstr("input");
semanticsHelper.addInstr("frame");

const messageString = message.sourceString.replace(/\s*[;,]$/, "");
const identifier = e.eval();
Expand Down
2 changes: 1 addition & 1 deletion src/UI/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"compilerOptions": {
"outDir": "../../dist/UI",
"declarationDir": "../../dist/UI/types",
//"sourceRoot":"./src/UI",
"lib": [
"es2020",
"dom"
],
"rootDir": "../",
"composite": true,
},
"include": ["./*.ts"],
Expand Down
2 changes: 1 addition & 1 deletion src/tsconfig-base.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"module": "ESNext",
"target": "ES6",
"target": "ES2017",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
Expand Down
Loading

0 comments on commit f14d339

Please sign in to comment.