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/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,11 @@
1
+ export const constants = Object.create(null);
2
+
3
+ constants["undefined"] = true;
4
+ constants["null"] = true;
5
+ constants["true"] = true;
6
+ constants["false"] = true;
7
+
8
+ export function isConstant(name: string)
9
+ {
10
+ return constants[name] === true;
11
+ }
@@ -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);