pure-dango 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/package.json +45 -0
- package/src/core/compiler.ts +1269 -0
- package/src/core/interpreter.ts +2042 -0
- package/src/core/parser/handlers.ts +1091 -0
- package/src/core/parser/helpers.ts +157 -0
- package/src/core/parser/main.ts +620 -0
- package/src/core/tokenizer/funnies.ts +43 -0
- package/src/core/tokenizer/tokenizer.ts +334 -0
- package/src/core/utils.ts +534 -0
- package/src/index.ts +190 -0
- package/src/runtime/errors.ts +239 -0
- package/src/runtime/globals.ts +11 -0
- package/src/runtime/libs/ai.pds +56 -0
- package/src/runtime/libs/errors.pds +74 -0
- package/src/runtime/libs/gambling.pds +93 -0
- package/src/runtime/libs/io.pds +371 -0
- package/src/runtime/libs/math.pds +86 -0
- package/src/runtime/libs/std.pds +2 -0
- package/src/runtime/libs/types.pds +1232 -0
- package/src/runtime/stdlib.ts +1483 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// pure-dango v0.9.1.
|
|
4
|
+
// a programming language made for precision and myself
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// TODO: Document
|
|
8
|
+
|
|
9
|
+
// note for myself:
|
|
10
|
+
// tokenizer: tokens
|
|
11
|
+
// parser: syntax errors
|
|
12
|
+
// compiler: bytecode converter interpreter:
|
|
13
|
+
// runtime errors
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
process.title = "pure-dango";
|
|
17
|
+
|
|
18
|
+
// imports
|
|
19
|
+
import fs from "fs";
|
|
20
|
+
import path from "path";
|
|
21
|
+
import readline from "readline";
|
|
22
|
+
import {execSync} from "child_process";
|
|
23
|
+
|
|
24
|
+
import {parser} from "./core/parser/main";
|
|
25
|
+
import {tokenizer} from "./core/tokenizer/tokenizer";
|
|
26
|
+
import {interpret, Scope, initGMP} from "./core/interpreter";
|
|
27
|
+
import {buildBytecode} from "./core/compiler";
|
|
28
|
+
|
|
29
|
+
import * as utils from "./core/utils";
|
|
30
|
+
const
|
|
31
|
+
{
|
|
32
|
+
run,
|
|
33
|
+
saveBytecode,
|
|
34
|
+
loadBytecode
|
|
35
|
+
} = utils;
|
|
36
|
+
|
|
37
|
+
// get all info
|
|
38
|
+
const packageJson =
|
|
39
|
+
{
|
|
40
|
+
name: typeof PACKAGE_NAME !== "undefined" ? PACKAGE_NAME : "pure-dango",
|
|
41
|
+
version: typeof PACKAGE_VERSION !== "undefined" ? PACKAGE_VERSION : "1.8.0",
|
|
42
|
+
description: typeof PACKAGE_DESCRIPTION !== "undefined" ? PACKAGE_DESCRIPTION : "A simple programming language built in JavaScript"
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
type ASTOutput =
|
|
46
|
+
{
|
|
47
|
+
scopes : Scope
|
|
48
|
+
stack : (number | bigint | string | null | undefined)[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function pause(code: number = 0)
|
|
52
|
+
{
|
|
53
|
+
// creates a way to question the user
|
|
54
|
+
const rl = readline.createInterface(
|
|
55
|
+
{
|
|
56
|
+
input : process.stdin,
|
|
57
|
+
output : process.stdout
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// questions the user
|
|
62
|
+
rl.question(
|
|
63
|
+
"\nPress enter to exit...", () =>
|
|
64
|
+
{
|
|
65
|
+
rl.close();
|
|
66
|
+
process.exit(code);
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
process.on(
|
|
72
|
+
"warning", (warning) =>
|
|
73
|
+
{
|
|
74
|
+
if (warning.name === 'ExperimentalWarning' && warning.message.includes('Fetch API'))
|
|
75
|
+
return;
|
|
76
|
+
console.warn(warning);
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
(async function main()
|
|
81
|
+
{
|
|
82
|
+
if (process.platform === "win32")
|
|
83
|
+
{
|
|
84
|
+
try
|
|
85
|
+
{
|
|
86
|
+
execSync("reg add HKCU\\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 /f", {stdio: "ignore"});
|
|
87
|
+
}
|
|
88
|
+
catch {}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
process.on(
|
|
92
|
+
"uncaughtException", () =>
|
|
93
|
+
{
|
|
94
|
+
process.stdout.write("\x1B[?25h");
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
process.on("exit", () => process.stdout.write("\x1B[?25h"));
|
|
99
|
+
process.on(
|
|
100
|
+
"SIGINT", () =>
|
|
101
|
+
{
|
|
102
|
+
process.stdout.write("\x1B[?25h");
|
|
103
|
+
process.exit();
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
let state : {time : number, position : number} =
|
|
108
|
+
{
|
|
109
|
+
time : 0,
|
|
110
|
+
position : 0
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const args = process.argv.slice(2);
|
|
114
|
+
|
|
115
|
+
let filename: string;
|
|
116
|
+
if (args[0] === "run")
|
|
117
|
+
filename = args[1];
|
|
118
|
+
else if (args[0])
|
|
119
|
+
filename = args[0];
|
|
120
|
+
else
|
|
121
|
+
{
|
|
122
|
+
console.error("please provide a file to run (.pds)");
|
|
123
|
+
pause(1);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!filename.endsWith(".pds"))
|
|
128
|
+
{
|
|
129
|
+
console.error(`file "${filename}" is not a (.pds) Pure Dango Script file`);
|
|
130
|
+
pause(1);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const filePath: string = path.resolve(process.cwd(), filename);
|
|
135
|
+
if (!fs.existsSync(filePath))
|
|
136
|
+
{
|
|
137
|
+
console.error(`file not found: ${filename}`);
|
|
138
|
+
pause(1);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// greeting (might change later)
|
|
143
|
+
console.log(`Welcome to ${packageJson.name} v${packageJson.version}`);
|
|
144
|
+
console.log(`${packageJson.description} \n`);
|
|
145
|
+
|
|
146
|
+
const cache = process.env.LOCALAPPDATA // Windows
|
|
147
|
+
|| process.env.XDG_CACHE_HOME // Linux (proper)
|
|
148
|
+
|| path.join(process.env.HOME || process.cwd(), ".cache"); // Linux fallback
|
|
149
|
+
|
|
150
|
+
const pureDangoDirectory : string = path.join(cache, "pure-dango"); // get the normal path
|
|
151
|
+
const cacheFolder : string = path.join(pureDangoDirectory, ".pdbccache"); // if the filepath is "C:/user/Documents/pure-dango" it will be: "C:/user/Documents/pure-dango/.pdbccache"
|
|
152
|
+
|
|
153
|
+
if (!fs.existsSync(cacheFolder))
|
|
154
|
+
fs.mkdirSync(cacheFolder, {recursive: true}); // makes a file with the path of cacheFolder
|
|
155
|
+
|
|
156
|
+
try
|
|
157
|
+
{
|
|
158
|
+
let FILE = fs.readFileSync(filePath, "utf-8"); // Read the file given by the user
|
|
159
|
+
if (FILE.charCodeAt(0) === 0xFFFE || FILE.charCodeAt(0) === 0xFEFF)
|
|
160
|
+
FILE = Buffer.from(FILE, "binary").toString("utf16le");
|
|
161
|
+
FILE = FILE.replace(/\u0000/g, "");
|
|
162
|
+
|
|
163
|
+
const srcMTime = fs.statSync(filePath).mtimeMs;
|
|
164
|
+
|
|
165
|
+
await initGMP();
|
|
166
|
+
|
|
167
|
+
let BYTECODE : Array<string | number> | null = loadBytecode(cacheFolder, filename);
|
|
168
|
+
|
|
169
|
+
if (!BYTECODE)
|
|
170
|
+
{
|
|
171
|
+
const TOKENS : BaseToken[] = await run(tokenizer, state, FILE);
|
|
172
|
+
const PARSED : AST = await run(parser, state, TOKENS);
|
|
173
|
+
BYTECODE = await run(buildBytecode, state, PARSED, filePath);
|
|
174
|
+
const OUTPUT : ASTOutput = await run(interpret, state, BYTECODE, path.dirname(path.resolve(filePath)), filePath);
|
|
175
|
+
|
|
176
|
+
saveBytecode(cacheFolder, BYTECODE as Array<string | number>, filename, srcMTime);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
else
|
|
180
|
+
await run(interpret, state, BYTECODE, path.dirname(path.resolve(filePath)), filePath);
|
|
181
|
+
|
|
182
|
+
console.log(`\nPure dango program exited after: ${state.time.toFixed(3)} milliseconds...`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
catch (error : unknown)
|
|
186
|
+
{
|
|
187
|
+
console.error(`\n${(error as Error).message}`);
|
|
188
|
+
console.log(`Pure dango program exited after: ${state.time.toFixed(3)} milliseconds...`);
|
|
189
|
+
}
|
|
190
|
+
})()
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
export class GeneralError extends Error
|
|
2
|
+
{
|
|
3
|
+
constructor(name : string, message : string)
|
|
4
|
+
{
|
|
5
|
+
super(`[ERROR] ${name}:\n${message}`);
|
|
6
|
+
this.name = "";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// singular tokenizer error
|
|
11
|
+
export class Tokenizer extends GeneralError
|
|
12
|
+
{
|
|
13
|
+
constructor(message : string, row : number, column : number)
|
|
14
|
+
{
|
|
15
|
+
super(`Tokenizer [${row}:${column}]`, message);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// runtime errors
|
|
20
|
+
class ConstantAssignmentOperator extends GeneralError
|
|
21
|
+
{
|
|
22
|
+
constructor(variableName : string)
|
|
23
|
+
{
|
|
24
|
+
super(`ConstantAssignmentOperator`, `assignment to a constant "${variableName}"`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class FunctionError extends GeneralError
|
|
29
|
+
{
|
|
30
|
+
constructor(functionName : string)
|
|
31
|
+
{
|
|
32
|
+
super("FunctionError", `function "${functionName}" does not exist`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class StackError extends GeneralError
|
|
37
|
+
{
|
|
38
|
+
constructor()
|
|
39
|
+
{
|
|
40
|
+
super("StackError", `pop on empty stack`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class MissingStackTokenError extends GeneralError
|
|
45
|
+
{
|
|
46
|
+
constructor(expected : string | number)
|
|
47
|
+
{
|
|
48
|
+
super("MissingTokenError", `expected a value after "${expected}"`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class BreakError extends GeneralError
|
|
53
|
+
{
|
|
54
|
+
constructor()
|
|
55
|
+
{
|
|
56
|
+
super("BreakError", `break statement outside of loop`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class ContinueError extends GeneralError
|
|
61
|
+
{
|
|
62
|
+
constructor()
|
|
63
|
+
{
|
|
64
|
+
super("ContinueError", `continue statement outside of loop`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
class DivisionByZero extends GeneralError
|
|
69
|
+
{
|
|
70
|
+
constructor(left : bigint | any, right : bigint | any)
|
|
71
|
+
{
|
|
72
|
+
super("DivisionByZero", `operands must not divide by 0, got "${left}/${right}"`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
class InternalError extends GeneralError
|
|
77
|
+
{
|
|
78
|
+
constructor(message: string)
|
|
79
|
+
{
|
|
80
|
+
super("InternalError", message);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
class MethodError extends GeneralError
|
|
85
|
+
{
|
|
86
|
+
constructor(methodName: string)
|
|
87
|
+
{
|
|
88
|
+
super("MethodError", `method "${methodName}" does not exist`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
class PropertyError extends GeneralError
|
|
93
|
+
{
|
|
94
|
+
constructor(methodName: string)
|
|
95
|
+
{
|
|
96
|
+
super("PropertyError", `property "${methodName}" does not exist`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class ClassError extends GeneralError
|
|
101
|
+
{
|
|
102
|
+
constructor(className: string)
|
|
103
|
+
{
|
|
104
|
+
super("ClassError", `"${className}" is not a class`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const runtimeErrors =
|
|
109
|
+
{
|
|
110
|
+
FunctionError,
|
|
111
|
+
ConstantAssignmentOperator,
|
|
112
|
+
BreakError,
|
|
113
|
+
ContinueError,
|
|
114
|
+
StackError,
|
|
115
|
+
MissingStackTokenError,
|
|
116
|
+
DivisionByZero,
|
|
117
|
+
InternalError,
|
|
118
|
+
MethodError,
|
|
119
|
+
PropertyError,
|
|
120
|
+
ClassError
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// parsing errors
|
|
124
|
+
class SyntaxError extends GeneralError
|
|
125
|
+
{
|
|
126
|
+
constructor(message : string, row : number, column : number)
|
|
127
|
+
{
|
|
128
|
+
super("SyntaxError", `${message} at line ${row}:${column}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
class FunctionCallError extends SyntaxError
|
|
133
|
+
{
|
|
134
|
+
constructor(message : string, row : number, column : number)
|
|
135
|
+
{
|
|
136
|
+
super(message, row, column);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
class ChainedFunctionCallError extends SyntaxError
|
|
141
|
+
{
|
|
142
|
+
constructor (name : string, row : number, column : number)
|
|
143
|
+
{
|
|
144
|
+
super(`chained function calls are not allowed: "${name}(...)()"`, row, column);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
class ChainedIncDecError extends SyntaxError
|
|
149
|
+
{
|
|
150
|
+
constructor (row : number, column : number)
|
|
151
|
+
{
|
|
152
|
+
super(`chained increment/decrement operators are not allowed`, row, column);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
class InvalidPostfixError extends SyntaxError
|
|
157
|
+
{
|
|
158
|
+
constructor (operator : string, type : string, value : any, row : number, column : number)
|
|
159
|
+
{
|
|
160
|
+
super(`cannot apply "${operator}" to ${type.toLocaleLowerCase()} "${value}"`, row, column);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
class AssignmentError extends SyntaxError
|
|
165
|
+
{
|
|
166
|
+
constructor(operator : any, row : number, column : number)
|
|
167
|
+
{
|
|
168
|
+
super(`left side of "${operator}" must be a variable`, row, column);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
class UnexpectedTokenError extends SyntaxError
|
|
173
|
+
{
|
|
174
|
+
constructor(tokenValue : any, row : number, column : number)
|
|
175
|
+
{
|
|
176
|
+
super(`unexpected token "${tokenValue}"`, row, column);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
class MissingTokenError extends SyntaxError
|
|
181
|
+
{
|
|
182
|
+
constructor(expected : string, row : number, column : number)
|
|
183
|
+
{
|
|
184
|
+
super(`expected "${expected}"`, row, column);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
class MissingRightSide extends SyntaxError
|
|
189
|
+
{
|
|
190
|
+
constructor(after : any, row : number, column : number)
|
|
191
|
+
{
|
|
192
|
+
super(`rxpected an expression or value after "${after}"`, row, column);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
class UnaryOperatorError extends SyntaxError
|
|
197
|
+
{
|
|
198
|
+
constructor(value : any, row : number, column : number)
|
|
199
|
+
{
|
|
200
|
+
super(`unknown fix type for unary operator "${value}"`, row, column);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export const parseErrors =
|
|
205
|
+
{
|
|
206
|
+
FunctionCallError,
|
|
207
|
+
ChainedFunctionCallError,
|
|
208
|
+
ChainedIncDecError,
|
|
209
|
+
AssignmentError,
|
|
210
|
+
UnexpectedTokenError,
|
|
211
|
+
MissingTokenError,
|
|
212
|
+
InvalidPostfixError,
|
|
213
|
+
MissingRightSide,
|
|
214
|
+
UnaryOperatorError
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// utils errors
|
|
218
|
+
|
|
219
|
+
class NegativeExponentError extends GeneralError
|
|
220
|
+
{
|
|
221
|
+
constructor(exponent : number | bigint | any)
|
|
222
|
+
{
|
|
223
|
+
super("NegativeExponentError", `exponent "${exponent}" must be positive when raising BigInt`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
class FunctionArgumentError extends GeneralError
|
|
228
|
+
{
|
|
229
|
+
constructor(functionName : string, maxLength : number, plural : string)
|
|
230
|
+
{
|
|
231
|
+
super("FunctionArgumentError", `function "${functionName}" only takes ${maxLength} ${plural}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export const utilsErrors =
|
|
236
|
+
{
|
|
237
|
+
NegativeExponentError,
|
|
238
|
+
FunctionArgumentError
|
|
239
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import internal "types.pds";
|
|
2
|
+
|
|
3
|
+
class AI
|
|
4
|
+
{
|
|
5
|
+
constructor(apiKey, model, url)
|
|
6
|
+
{
|
|
7
|
+
this.apiKey = apiKey;
|
|
8
|
+
this.model = model;
|
|
9
|
+
this.url = url
|
|
10
|
+
this.conversationHistory = [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
ask(prompt)
|
|
14
|
+
{
|
|
15
|
+
push(this.conversationHistory, {role: "user", content: prompt});
|
|
16
|
+
|
|
17
|
+
new requestBody =
|
|
18
|
+
{
|
|
19
|
+
model: this.model,
|
|
20
|
+
max_completion_tokens: 1024,
|
|
21
|
+
messages: this.conversationHistory
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
new headers =
|
|
25
|
+
{
|
|
26
|
+
headers:
|
|
27
|
+
{
|
|
28
|
+
"Content-Type" : "application/json",
|
|
29
|
+
"Authorization": concat("Bearer ", this.apiKey)
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
new response =
|
|
34
|
+
http_post(
|
|
35
|
+
this.url,
|
|
36
|
+
requestBody,
|
|
37
|
+
headers
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
new parsed = tobj(response);
|
|
41
|
+
new assistantMessage = parsed.choices[0].message.content;
|
|
42
|
+
|
|
43
|
+
push(this.conversationHistory, {role: "assistant", content: assistantMessage});
|
|
44
|
+
return assistantMessage;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
clearHistory()
|
|
48
|
+
{
|
|
49
|
+
this.conversationHistory = [];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setSystemPrompt(prompt)
|
|
53
|
+
{
|
|
54
|
+
this.systemPrompt = prompt;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# all errors.
|
|
2
|
+
class Error
|
|
3
|
+
{
|
|
4
|
+
constructor(x)
|
|
5
|
+
{
|
|
6
|
+
if (typeof(x) != "string")
|
|
7
|
+
throwerror("Error", concat('Parameter "__INIT__" of class "Error" must be type String. But got "', x, '"'));
|
|
8
|
+
|
|
9
|
+
this.__INIT__ = x;
|
|
10
|
+
this.name = "Error";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
throw(message)
|
|
14
|
+
{
|
|
15
|
+
if (message)
|
|
16
|
+
throwerror(this.name, message);
|
|
17
|
+
else
|
|
18
|
+
throwerror(this.name, this.__INIT__);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class TypeError extends Error
|
|
23
|
+
{
|
|
24
|
+
constructor(x)
|
|
25
|
+
{
|
|
26
|
+
super(x);
|
|
27
|
+
this.name = "TypeError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class ValueError extends Error
|
|
32
|
+
{
|
|
33
|
+
constructor(x)
|
|
34
|
+
{
|
|
35
|
+
super(x);
|
|
36
|
+
this.name = "ValueError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class IndexError extends Error
|
|
41
|
+
{
|
|
42
|
+
constructor(x)
|
|
43
|
+
{
|
|
44
|
+
super(x);
|
|
45
|
+
this.name = "IndexError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
class NotImplementedError extends Error
|
|
50
|
+
{
|
|
51
|
+
constructor(x)
|
|
52
|
+
{
|
|
53
|
+
super(x);
|
|
54
|
+
this.name = "NotImplementedError";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
class RangeError extends Error
|
|
59
|
+
{
|
|
60
|
+
constructor(x)
|
|
61
|
+
{
|
|
62
|
+
super(x);
|
|
63
|
+
this.name = "RangeError";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class InternalError extends Error
|
|
68
|
+
{
|
|
69
|
+
constructor(x)
|
|
70
|
+
{
|
|
71
|
+
super(x);
|
|
72
|
+
this.name = "InternalError";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
class gambling
|
|
2
|
+
{
|
|
3
|
+
constructor(...args : Tuple<string, float>)
|
|
4
|
+
{
|
|
5
|
+
this.__INIT__ = {};
|
|
6
|
+
|
|
7
|
+
for (new pair of args)
|
|
8
|
+
this.addItem(pair[0], pair[1]);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
addItem(name : string, rarity : float) : void
|
|
12
|
+
this.__INIT__[name] = rarity;
|
|
13
|
+
|
|
14
|
+
removeItem(name : string) : void
|
|
15
|
+
this.__INIT__[name] = null;
|
|
16
|
+
|
|
17
|
+
editItem(name : string, newLuck : float) : void
|
|
18
|
+
this.__INIT__[name] = newLuck;
|
|
19
|
+
|
|
20
|
+
roll() : string
|
|
21
|
+
{
|
|
22
|
+
new items = [];
|
|
23
|
+
new weights = [];
|
|
24
|
+
|
|
25
|
+
new itemKeys = keys(this.__INIT__);
|
|
26
|
+
for (new name of itemKeys)
|
|
27
|
+
{
|
|
28
|
+
new luck = this.__INIT__[name];
|
|
29
|
+
if (luck != null && luck != undefined)
|
|
30
|
+
{
|
|
31
|
+
push(items, name);
|
|
32
|
+
push(weights, luck);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (len(items) == 0)
|
|
37
|
+
return null;
|
|
38
|
+
|
|
39
|
+
new total = 0;
|
|
40
|
+
for (new weight of weights)
|
|
41
|
+
total += weight;
|
|
42
|
+
|
|
43
|
+
new roll = random(0, total);
|
|
44
|
+
|
|
45
|
+
new cumulative = 0;
|
|
46
|
+
new i = 0;
|
|
47
|
+
for (new weight of weights)
|
|
48
|
+
{
|
|
49
|
+
cumulative += weight;
|
|
50
|
+
if (roll <= cumulative)
|
|
51
|
+
return items[i];
|
|
52
|
+
|
|
53
|
+
i += 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return items[len(items) - 1];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
new a = inst gambling(
|
|
61
|
+
["stone", 2],
|
|
62
|
+
["rock", 1.5],
|
|
63
|
+
["bread", 1],
|
|
64
|
+
["water", 0.8],
|
|
65
|
+
|
|
66
|
+
["coral, the emperor", 0.5],
|
|
67
|
+
["vile, the soldier of death", 0.35],
|
|
68
|
+
["frant, the fallen emperor", 0.3],
|
|
69
|
+
|
|
70
|
+
["tesla, creator of AC current", 0.3],
|
|
71
|
+
["einstein, sage of theories", 0.2],
|
|
72
|
+
["newton, holder of the apple", 0.1],
|
|
73
|
+
|
|
74
|
+
["cass, holder of money", 0.08], # on a side note he killed frant, not like it's better than money
|
|
75
|
+
|
|
76
|
+
["kilnit, emperor of emperors", 0.07], # proved his strength by defeating all emeprors. This guy is SO arrogant though.
|
|
77
|
+
["cornelius, god of emperors", 0.01], # protects emperors as an emperor god, even the emperor of emperors bow down to him. Completely immortal.
|
|
78
|
+
["forthhalt, death of emperors", 0.008], # DESPISES emperors. This guy HATES cornelius and unfortunately is immortal like cornelius
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
new i = 0;
|
|
82
|
+
new results = {};
|
|
83
|
+
|
|
84
|
+
while (i < 1000)
|
|
85
|
+
{
|
|
86
|
+
new result = a.roll();
|
|
87
|
+
if (results[result] == undefined)
|
|
88
|
+
results[result] = 0;
|
|
89
|
+
results[result] += 1;
|
|
90
|
+
i += 1;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
print(results);
|