@hoox-sh/pynets 0.1.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/CHANGELOG.md +30 -0
- package/LICENSE +661 -0
- package/NOTICE +46 -0
- package/README.md +327 -0
- package/dist/browser.js +44 -0
- package/dist/index.d.ts +348 -0
- package/dist/index.js +41741 -0
- package/package.json +77 -0
- package/src/ast/builder.ts +1002 -0
- package/src/ast/dump.ts +43 -0
- package/src/ast/helper.ts +77 -0
- package/src/ast/nodes.ts +570 -0
- package/src/ast/unparse.ts +360 -0
- package/src/cli/rich.ts +378 -0
- package/src/cli.ts +627 -0
- package/src/generated/PinescriptLexer.interp +267 -0
- package/src/generated/PinescriptLexer.tokens +131 -0
- package/src/generated/PinescriptLexer.ts +673 -0
- package/src/generated/PinescriptLexerBase.ts +395 -0
- package/src/generated/PinescriptParser.interp +267 -0
- package/src/generated/PinescriptParser.tokens +131 -0
- package/src/generated/PinescriptParser.ts +8863 -0
- package/src/generated/PinescriptParserBase.ts +21 -0
- package/src/generated/PinescriptParserVisitor.ts +840 -0
- package/src/index.ts +55 -0
- package/src/parser/LexerBase.ts +395 -0
- package/src/parser/ParserBase.ts +21 -0
- package/src/parser/error.ts +33 -0
- package/src/runtime/array.ts +486 -0
- package/src/runtime/color.ts +164 -0
- package/src/runtime/drawings.ts +510 -0
- package/src/runtime/input.ts +102 -0
- package/src/runtime/interpret.ts +3897 -0
- package/src/runtime/library.ts +282 -0
- package/src/runtime/log.ts +69 -0
- package/src/runtime/map.ts +85 -0
- package/src/runtime/math.ts +231 -0
- package/src/runtime/matrix.ts +1154 -0
- package/src/runtime/provider.ts +232 -0
- package/src/runtime/request.ts +372 -0
- package/src/runtime/series.ts +44 -0
- package/src/runtime/str.ts +433 -0
- package/src/runtime/strategy.ts +1105 -0
- package/src/runtime/ta.ts +2093 -0
- package/src/runtime/ticker.ts +81 -0
- package/src/runtime/time.ts +439 -0
- package/src/runtime/timeframe.ts +85 -0
- package/src/runtime/udt.ts +119 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (C) 2024-2026 jango_blockchained
|
|
3
|
+
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
*
|
|
5
|
+
* Slice-1 unparser: expressions plus Assign / ReAssign / var / varip,
|
|
6
|
+
* Tuple / Conditional / ForTo / ForIn / While / Switch / Case /
|
|
7
|
+
* BoolOp / Break / Continue / TypeDef / EnumDef.
|
|
8
|
+
*/
|
|
9
|
+
import type {
|
|
10
|
+
AST,
|
|
11
|
+
Arg,
|
|
12
|
+
Assign,
|
|
13
|
+
Attribute,
|
|
14
|
+
BinOp,
|
|
15
|
+
BoolOp,
|
|
16
|
+
Call,
|
|
17
|
+
Case,
|
|
18
|
+
Compare,
|
|
19
|
+
Conditional,
|
|
20
|
+
Constant,
|
|
21
|
+
EnumDef,
|
|
22
|
+
Expr,
|
|
23
|
+
Expression,
|
|
24
|
+
ForIn,
|
|
25
|
+
ForTo,
|
|
26
|
+
FunctionDef,
|
|
27
|
+
If,
|
|
28
|
+
Import,
|
|
29
|
+
Name,
|
|
30
|
+
Param,
|
|
31
|
+
ReAssign,
|
|
32
|
+
Script,
|
|
33
|
+
Subscript,
|
|
34
|
+
Switch,
|
|
35
|
+
Tuple,
|
|
36
|
+
TypeDef,
|
|
37
|
+
UnaryOp,
|
|
38
|
+
While,
|
|
39
|
+
expr,
|
|
40
|
+
stmt,
|
|
41
|
+
} from "./nodes.ts";
|
|
42
|
+
|
|
43
|
+
const OP: Record<string, string> = {
|
|
44
|
+
Add: "+",
|
|
45
|
+
Sub: "-",
|
|
46
|
+
Mult: "*",
|
|
47
|
+
Div: "/",
|
|
48
|
+
Mod: "%",
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const UOP: Record<string, string> = {
|
|
52
|
+
UAdd: "+",
|
|
53
|
+
USub: "-",
|
|
54
|
+
Not: "not ",
|
|
55
|
+
Invert: "~",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const CMP: Record<string, string> = {
|
|
59
|
+
Eq: "==",
|
|
60
|
+
NotEq: "!=",
|
|
61
|
+
Lt: "<",
|
|
62
|
+
LtE: "<=",
|
|
63
|
+
Gt: ">",
|
|
64
|
+
GtE: ">=",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const BOOLOP: Record<string, string> = {
|
|
68
|
+
And: "and",
|
|
69
|
+
Or: "or",
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function quoteString(value: string): string {
|
|
73
|
+
if (value.includes("\n") || value.includes("\r")) {
|
|
74
|
+
if (!value.includes('"""')) return `"""${value}"""`;
|
|
75
|
+
if (!value.includes("'''")) return `'''${value}'''`;
|
|
76
|
+
}
|
|
77
|
+
return JSON.stringify(value);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function emitExpr(node: expr): string {
|
|
81
|
+
switch (node.kind) {
|
|
82
|
+
case "Name":
|
|
83
|
+
return node.id;
|
|
84
|
+
case "Constant":
|
|
85
|
+
return emitConstant(node);
|
|
86
|
+
case "Call":
|
|
87
|
+
return emitCall(node);
|
|
88
|
+
case "Attribute":
|
|
89
|
+
return `${emitExpr(node.value)}.${node.attr}`;
|
|
90
|
+
case "Subscript":
|
|
91
|
+
return `${emitExpr(node.value)}[${emitSlice(node.slice)}]`;
|
|
92
|
+
case "BinOp":
|
|
93
|
+
return `${emitExpr(node.left)} ${OP[node.op.kind] ?? "?"} ${emitExpr(node.right)}`;
|
|
94
|
+
case "UnaryOp":
|
|
95
|
+
return `${UOP[node.op.kind] ?? ""}${emitExpr(node.operand)}`;
|
|
96
|
+
case "Compare":
|
|
97
|
+
return emitCompare(node);
|
|
98
|
+
case "If":
|
|
99
|
+
return emitIf(node);
|
|
100
|
+
case "Tuple":
|
|
101
|
+
return emitTuple(node);
|
|
102
|
+
case "Conditional":
|
|
103
|
+
return emitConditional(node);
|
|
104
|
+
case "ForTo":
|
|
105
|
+
return emitForTo(node);
|
|
106
|
+
case "ForIn":
|
|
107
|
+
return emitForIn(node);
|
|
108
|
+
case "While":
|
|
109
|
+
return emitWhile(node);
|
|
110
|
+
case "Switch":
|
|
111
|
+
return emitSwitch(node);
|
|
112
|
+
case "BoolOp":
|
|
113
|
+
return emitBoolOp(node);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function emitCompare(node: Compare): string {
|
|
118
|
+
let out = emitExpr(node.left);
|
|
119
|
+
for (let i = 0; i < node.ops.length; i++) {
|
|
120
|
+
out += ` ${CMP[node.ops[i]!.kind] ?? "??"} ${emitExpr(node.comparators[i]!)}`;
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function emitIf(node: If): string {
|
|
126
|
+
const body = node.body.map(emitStmt).join("; ");
|
|
127
|
+
if (node.orelse.length === 0) return `if ${emitExpr(node.test)}\n ${body}`;
|
|
128
|
+
const els = node.orelse.map(emitStmt).join("; ");
|
|
129
|
+
return `if ${emitExpr(node.test)}\n ${body}\nelse\n ${els}`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function emitTuple(node: Tuple): string {
|
|
133
|
+
return `[${node.elts.map(emitExpr).join(", ")}]`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function emitSlice(slice: expr | null | undefined): string {
|
|
137
|
+
if (slice == null) return "";
|
|
138
|
+
if (slice.kind === "Tuple") return slice.elts.map(emitExpr).join(", ");
|
|
139
|
+
return emitExpr(slice);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function emitConditional(node: Conditional): string {
|
|
143
|
+
return `${emitExpr(node.test)} ? ${emitExpr(node.body)} : ${emitExpr(node.orelse)}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function emitForBody(body: stmt[]): string {
|
|
147
|
+
if (!body.length) return "";
|
|
148
|
+
const parts = body.map(emitStmt);
|
|
149
|
+
if (parts.length === 1 && !parts[0]!.includes("\n")) return ` ${parts[0]}`;
|
|
150
|
+
return parts.map((p) => `\n ${p.replaceAll("\n", "\n ")}`).join("");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function emitForTo(node: ForTo): string {
|
|
154
|
+
let head = `for ${emitExpr(node.target)} = ${emitExpr(node.start)} to ${emitExpr(node.end)}`;
|
|
155
|
+
if (node.step) head += ` by ${emitExpr(node.step)}`;
|
|
156
|
+
return head + emitForBody(node.body);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function emitForIn(node: ForIn): string {
|
|
160
|
+
return `for ${emitExpr(node.target)} in ${emitExpr(node.iter)}${emitForBody(node.body)}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function emitIndentedBody(body: stmt[]): string {
|
|
164
|
+
if (!body.length) return "";
|
|
165
|
+
return body.map((st) => `\n ${emitStmt(st).replaceAll("\n", "\n ")}`).join("");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function emitWhile(node: While): string {
|
|
169
|
+
return `while ${emitExpr(node.test)}${emitIndentedBody(node.body)}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function emitCaseBody(body: stmt[]): string {
|
|
173
|
+
if (!body.length) return "";
|
|
174
|
+
if (body.length === 1 && body[0]!.kind === "Expr") {
|
|
175
|
+
return ` ${emitExpr(body[0]!.value)}`;
|
|
176
|
+
}
|
|
177
|
+
const parts = body.map(emitStmt);
|
|
178
|
+
if (parts.length === 1 && !parts[0]!.includes("\n")) return ` ${parts[0]}`;
|
|
179
|
+
return parts.map((p) => `\n ${p.replaceAll("\n", "\n ")}`).join("");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function emitCase(node: Case): string {
|
|
183
|
+
const prefix = node.pattern ? `${emitExpr(node.pattern)} =>` : "=>";
|
|
184
|
+
return prefix + emitCaseBody(node.body);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function emitSwitch(node: Switch): string {
|
|
188
|
+
const head = node.subject ? `switch ${emitExpr(node.subject)}` : "switch";
|
|
189
|
+
if (!node.cases.length) return head;
|
|
190
|
+
return head + node.cases.map((c) => `\n ${emitCase(c).replaceAll("\n", "\n ")}`).join("");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function emitBoolOp(node: BoolOp): string {
|
|
194
|
+
const op = BOOLOP[node.op.kind] ?? "and";
|
|
195
|
+
return node.values.map(emitExpr).join(` ${op} `);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function emitConstant(node: Constant): string {
|
|
199
|
+
if (node.kind_lit) return String(node.value);
|
|
200
|
+
const v = node.value;
|
|
201
|
+
if (v === true) return "true";
|
|
202
|
+
if (v === false) return "false";
|
|
203
|
+
if (v === null || v === undefined) return "na";
|
|
204
|
+
if (typeof v === "string") return quoteString(v);
|
|
205
|
+
return String(v);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function emitArg(node: Arg): string {
|
|
209
|
+
const inner = emitExpr(node.value);
|
|
210
|
+
return node.name ? `${node.name}=${inner}` : inner;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function asArgs(args: Arg | Arg[] | null | undefined): Arg[] {
|
|
214
|
+
if (args == null) return [];
|
|
215
|
+
return Array.isArray(args) ? args : [args];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function emitCall(node: Call): string {
|
|
219
|
+
return `${emitExpr(node.func)}(${asArgs(node.args).map(emitArg).join(", ")})`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function emitImport(node: Import): string {
|
|
223
|
+
const path = `import ${node.namespace}/${node.name}/${node.version}`;
|
|
224
|
+
return node.alias ? `${path} as ${node.alias}` : path;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function emitStmt(node: stmt): string {
|
|
228
|
+
if (node == null || typeof node !== "object") return "";
|
|
229
|
+
if (node.kind === "Expr") return emitExpr(node.value);
|
|
230
|
+
if (node.kind === "Assign") return emitAssign(node);
|
|
231
|
+
if (node.kind === "ReAssign") return emitReAssign(node);
|
|
232
|
+
if (node.kind === "FunctionDef") return emitFunctionDef(node);
|
|
233
|
+
if (node.kind === "TypeDef") return emitTypeDef(node);
|
|
234
|
+
if (node.kind === "EnumDef") return emitEnumDef(node);
|
|
235
|
+
if (node.kind === "Import") return emitImport(node);
|
|
236
|
+
if (node.kind === "Break") return "break";
|
|
237
|
+
if (node.kind === "Continue") return "continue";
|
|
238
|
+
return "";
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function asParams(args: Param | Param[] | null | undefined): Param[] {
|
|
242
|
+
if (args == null) return [];
|
|
243
|
+
return Array.isArray(args) ? args : [args];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function emitParam(node: Param): string {
|
|
247
|
+
let out = node.name;
|
|
248
|
+
if (node.type) out = `${emitExpr(node.type)} ${out}`;
|
|
249
|
+
if (node.default) out += `=${emitExpr(node.default)}`;
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function emitTypeDef(node: TypeDef): string {
|
|
254
|
+
const chunks: string[] = [];
|
|
255
|
+
if (node.export) chunks.push("export");
|
|
256
|
+
chunks.push("type");
|
|
257
|
+
chunks.push(node.name);
|
|
258
|
+
const line = `${chunks.join(" ")}${emitIndentedBody(node.body)}`;
|
|
259
|
+
if (node.annotations.length) return `${node.annotations.join("\n")}\n${line}`;
|
|
260
|
+
return line;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function emitEnumDef(node: EnumDef): string {
|
|
264
|
+
const chunks: string[] = [];
|
|
265
|
+
if (node.export) chunks.push("export");
|
|
266
|
+
chunks.push("enum");
|
|
267
|
+
chunks.push(node.name);
|
|
268
|
+
const line = `${chunks.join(" ")}${emitIndentedBody(node.body)}`;
|
|
269
|
+
if (node.annotations.length) return `${node.annotations.join("\n")}\n${line}`;
|
|
270
|
+
return line;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function emitFunctionDef(node: FunctionDef): string {
|
|
274
|
+
const chunks: string[] = [];
|
|
275
|
+
if (node.export) chunks.push("export");
|
|
276
|
+
if (node.method) chunks.push("method");
|
|
277
|
+
chunks.push(`${node.name}(${asParams(node.args).map(emitParam).join(", ")}) =>`);
|
|
278
|
+
const head = chunks.join(" ");
|
|
279
|
+
const body = node.body;
|
|
280
|
+
let line: string;
|
|
281
|
+
if (body.length === 1 && body[0]!.kind === "Expr") {
|
|
282
|
+
line = `${head} ${emitExpr(body[0]!.value)}`;
|
|
283
|
+
} else if (!body.length) {
|
|
284
|
+
line = head;
|
|
285
|
+
} else {
|
|
286
|
+
line = `${head}${body.map((st) => `\n ${emitStmt(st).replaceAll("\n", "\n ")}`).join("")}`;
|
|
287
|
+
}
|
|
288
|
+
if (node.annotations.length) return `${node.annotations.join("\n")}\n${line}`;
|
|
289
|
+
return line;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function emitAssign(node: Assign): string {
|
|
293
|
+
const chunks: string[] = [];
|
|
294
|
+
if (node.export) chunks.push("export");
|
|
295
|
+
if (node.mode) chunks.push(node.mode.kind === "VarIp" ? "varip" : "var");
|
|
296
|
+
if (node.type) chunks.push(emitExpr(node.type));
|
|
297
|
+
chunks.push(emitExpr(node.target));
|
|
298
|
+
const head = chunks.join(" ");
|
|
299
|
+
const line = node.value == null ? head : `${head} = ${emitExpr(node.value)}`;
|
|
300
|
+
if (node.annotations.length) return `${node.annotations.join("\n")}\n${line}`;
|
|
301
|
+
return line;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function emitReAssign(node: ReAssign): string {
|
|
305
|
+
return `${emitExpr(node.target)} := ${emitExpr(node.value)}`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function unparse(node: AST): string {
|
|
309
|
+
if (node.kind === "Script") {
|
|
310
|
+
const s = node as Script;
|
|
311
|
+
const lines: string[] = [];
|
|
312
|
+
for (const ann of s.annotations) lines.push(ann);
|
|
313
|
+
for (const st of s.body) lines.push(emitStmt(st));
|
|
314
|
+
return lines.join("\n");
|
|
315
|
+
}
|
|
316
|
+
if (node.kind === "Expression") return emitExpr((node as Expression).body);
|
|
317
|
+
if (node.kind === "Expr") return emitExpr((node as Expr).value);
|
|
318
|
+
if (node.kind === "Assign") return emitAssign(node as Assign);
|
|
319
|
+
if (node.kind === "ReAssign") return emitReAssign(node as ReAssign);
|
|
320
|
+
if (node.kind === "FunctionDef") return emitFunctionDef(node as FunctionDef);
|
|
321
|
+
if (node.kind === "TypeDef") return emitTypeDef(node as TypeDef);
|
|
322
|
+
if (node.kind === "EnumDef") return emitEnumDef(node as EnumDef);
|
|
323
|
+
if (node.kind === "Param") return emitParam(node as Param);
|
|
324
|
+
if (node.kind === "Var") return "var";
|
|
325
|
+
if (node.kind === "VarIp") return "varip";
|
|
326
|
+
if (node.kind === "Call") return emitCall(node as Call);
|
|
327
|
+
if (node.kind === "Name") return (node as Name).id;
|
|
328
|
+
if (node.kind === "Constant") return emitConstant(node as Constant);
|
|
329
|
+
if (node.kind === "Arg") return emitArg(node as Arg);
|
|
330
|
+
if (node.kind === "Attribute") {
|
|
331
|
+
const a = node as Attribute;
|
|
332
|
+
return `${emitExpr(a.value)}.${a.attr}`;
|
|
333
|
+
}
|
|
334
|
+
if (node.kind === "Subscript") {
|
|
335
|
+
const s = node as Subscript;
|
|
336
|
+
return `${emitExpr(s.value)}[${emitSlice(s.slice)}]`;
|
|
337
|
+
}
|
|
338
|
+
if (node.kind === "BinOp") {
|
|
339
|
+
const b = node as BinOp;
|
|
340
|
+
return `${emitExpr(b.left)} ${OP[b.op.kind] ?? "?"} ${emitExpr(b.right)}`;
|
|
341
|
+
}
|
|
342
|
+
if (node.kind === "UnaryOp") {
|
|
343
|
+
const u = node as UnaryOp;
|
|
344
|
+
return `${UOP[u.op.kind] ?? ""}${emitExpr(u.operand)}`;
|
|
345
|
+
}
|
|
346
|
+
if (node.kind === "Compare") return emitCompare(node as Compare);
|
|
347
|
+
if (node.kind === "If") return emitIf(node as If);
|
|
348
|
+
if (node.kind === "Tuple") return emitTuple(node as Tuple);
|
|
349
|
+
if (node.kind === "Conditional") return emitConditional(node as Conditional);
|
|
350
|
+
if (node.kind === "ForTo") return emitForTo(node as ForTo);
|
|
351
|
+
if (node.kind === "ForIn") return emitForIn(node as ForIn);
|
|
352
|
+
if (node.kind === "While") return emitWhile(node as While);
|
|
353
|
+
if (node.kind === "Switch") return emitSwitch(node as Switch);
|
|
354
|
+
if (node.kind === "Case") return emitCase(node as Case);
|
|
355
|
+
if (node.kind === "BoolOp") return emitBoolOp(node as BoolOp);
|
|
356
|
+
if (node.kind === "Import") return emitImport(node as Import);
|
|
357
|
+
if (node.kind === "Break") return "break";
|
|
358
|
+
if (node.kind === "Continue") return "continue";
|
|
359
|
+
return "";
|
|
360
|
+
}
|