Skip to content

Commit 0effefb

Browse files
committed
fixed dynamic property issue. bumped version to v0.1.0
1 parent d7f72a6 commit 0effefb

File tree

6 files changed

+133
-142
lines changed

6 files changed

+133
-142
lines changed

index.html

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,10 @@
2828
<div class="container">
2929
<h4>JSPython development console</h4>
3030
<div id="editor">
31-
x = {
32-
p1: 11,
33-
p2: "]][[[[}}}{{{{",
34-
p3: {
35-
p31: 12,
36-
p32: "another string"
37-
},
38-
p4: [2,4,6,7],
39-
p5: [
40-
{a1: 11, a2: 12, a3: "r1"},
41-
{a1: 21, a2: 22, a3: "r2"},
42-
{a1: 31, a2: 33, a3: "r3"}
43-
]
44-
}
45-
x
46-
</div>
31+
issue = {}
32+
issue["ddd"] = 333
33+
issue
34+
</div>
4735
<button onclick="runInterpreter()">Run</button>
4836
<textarea id="result"></textarea>
4937
</div>

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jspython-interpreter",
3-
"version": "0.0.4",
3+
"version": "0.1.0",
44
"description": "JSPython is a javascript implementation of Python language that runs within web browser or NodeJS environment",
55
"keywords": [
66
"python",
@@ -18,7 +18,8 @@
1818
"test": "jest",
1919
"test:dev": "jest --watch",
2020
"test:dev:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --watch",
21-
"build": "npx rollup -c && npm pack",
21+
"build": "npx rollup -c",
22+
"build:publish": "npx rollup -c && npm publish",
2223
"dev": "npx rollup --config rollup.config.dev.js --watch"
2324
},
2425
"repository": {

src/assets/mode-jspython.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
77
var PythonHighlightRules = function() {
88

99
var keywords = (
10-
"async|def|if|return|and|or|while|for|in|break|continue|else"
10+
"async|def|if|return|and|or|while|for|in|break|continue|else|from|import"
1111
);
1212

1313
var builtinConstants = (

src/eval/common.ts

Lines changed: 97 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,125 @@
11
import { CodeLine } from "../tokenizer";
22

33
export interface BlockContext {
4-
returnCalled: boolean;
5-
breakCalled: boolean;
6-
continueCalled: boolean;
7-
returnObject: any;
8-
currentLevel: string;
9-
namelessFuncsCount: number;
10-
blockScope: { [index: string]: any }
4+
returnCalled: boolean;
5+
breakCalled: boolean;
6+
continueCalled: boolean;
7+
returnObject: any;
8+
currentLevel: string;
9+
namelessFuncsCount: number;
10+
blockScope: { [index: string]: any }
1111
}
1212

1313
export type AnyFunc = (...args: any[]) => void | any | Promise<any>;
1414

1515
export interface FuncInfo {
16-
name: string;
17-
params: string[];
18-
instructions: CodeLine[];
16+
name: string;
17+
params: string[];
18+
instructions: CodeLine[];
1919
}
2020

2121
export const OPERATIONS: { [index: string]: any } = {
22-
'+': (a: any, b: any) => a + b,
23-
'-': (a: any, b: any) => a - b,
24-
'*': (a: any, b: any) => a * b,
25-
'/': (a: any, b: any) => a / b,
26-
'%': (a: any, b: any) => a % b,
27-
'**': (a: any, b: any) => Math.pow(a, b),
28-
'==': (a: any, b: any) => a === b,
29-
'!=': (a: any, b: any) => a !== b,
30-
'<>': (a: any, b: any) => a !== b,
31-
'>': (a: any, b: any) => a > b,
32-
'<': (a: any, b: any) => a < b,
33-
'>=': (a: any, b: any) => a >= b,
34-
'<=': (a: any, b: any) => a <= b,
22+
'+': (a: any, b: any) => a + b,
23+
'-': (a: any, b: any) => a - b,
24+
'*': (a: any, b: any) => a * b,
25+
'/': (a: any, b: any) => a / b,
26+
'%': (a: any, b: any) => a % b,
27+
'**': (a: any, b: any) => Math.pow(a, b),
28+
'==': (a: any, b: any) => a === b,
29+
'!=': (a: any, b: any) => a !== b,
30+
'<>': (a: any, b: any) => a !== b,
31+
'>': (a: any, b: any) => a > b,
32+
'<': (a: any, b: any) => a < b,
33+
'>=': (a: any, b: any) => a >= b,
34+
'<=': (a: any, b: any) => a <= b,
3535
};
3636

3737
export const INDENT_SIZE = 2;
3838

3939
export function lastItem(arr: string | any[]): string | any {
40-
return (arr?.length) ? arr[arr.length - 1] : null;
40+
return (arr?.length) ? arr[arr.length - 1] : null;
4141
}
4242

4343
export function getLineIndent(line: string): number {
44-
let cc = 0;
45-
while (line[cc] === ' ') { cc++; }
46-
return cc;
44+
let cc = 0;
45+
while (line[cc] === ' ') { cc++; }
46+
return cc;
4747
}
4848

4949
export function sliceBlock(instuctionLines: CodeLine[], start: number): CodeLine[] {
50-
const blockLineIndent = getLineIndent(instuctionLines[start].line);
51-
const blockEndIndex = instuctionLines
52-
.findIndex((cl, i) => i > start && getLineIndent(cl.line) < blockLineIndent)
50+
const blockLineIndent = getLineIndent(instuctionLines[start].line);
51+
const blockEndIndex = instuctionLines
52+
.findIndex((cl, i) => i > start && getLineIndent(cl.line) < blockLineIndent)
5353

54-
return instuctionLines.slice(start, blockEndIndex > 0 ? blockEndIndex : undefined)
54+
return instuctionLines.slice(start, blockEndIndex > 0 ? blockEndIndex : undefined)
5555
}
5656

5757
export function parseDatetimeOrNull(value: string | Date): Date | null {
58-
if (!value) { return null; }
59-
if (value instanceof Date && !isNaN(value.valueOf())) { return value; }
60-
// only string values can be converted to Date
61-
if (typeof value !== 'string') { return null; }
62-
63-
const strValue = String(value);
64-
if (!strValue.length) { return null; }
65-
66-
const parseMonth = (mm: string): number => {
67-
if (!mm || !mm.length) {
68-
return NaN;
69-
}
70-
71-
const m = parseInt(mm, 10);
72-
if (!isNaN(m)) {
73-
return m - 1;
74-
}
75-
76-
// make sure english months are coming through
77-
if (mm.startsWith('jan')) { return 0; }
78-
if (mm.startsWith('feb')) { return 1; }
79-
if (mm.startsWith('mar')) { return 2; }
80-
if (mm.startsWith('apr')) { return 3; }
81-
if (mm.startsWith('may')) { return 4; }
82-
if (mm.startsWith('jun')) { return 5; }
83-
if (mm.startsWith('jul')) { return 6; }
84-
if (mm.startsWith('aug')) { return 7; }
85-
if (mm.startsWith('sep')) { return 8; }
86-
if (mm.startsWith('oct')) { return 9; }
87-
if (mm.startsWith('nov')) { return 10; }
88-
if (mm.startsWith('dec')) { return 11; }
89-
58+
if (!value) { return null; }
59+
if (value instanceof Date && !isNaN(value.valueOf())) { return value; }
60+
// only string values can be converted to Date
61+
if (typeof value !== 'string') { return null; }
62+
63+
const strValue = String(value);
64+
if (!strValue.length) { return null; }
65+
66+
const parseMonth = (mm: string): number => {
67+
if (!mm || !mm.length) {
9068
return NaN;
69+
}
70+
71+
const m = parseInt(mm, 10);
72+
if (!isNaN(m)) {
73+
return m - 1;
74+
}
75+
76+
// make sure english months are coming through
77+
if (mm.startsWith('jan')) { return 0; }
78+
if (mm.startsWith('feb')) { return 1; }
79+
if (mm.startsWith('mar')) { return 2; }
80+
if (mm.startsWith('apr')) { return 3; }
81+
if (mm.startsWith('may')) { return 4; }
82+
if (mm.startsWith('jun')) { return 5; }
83+
if (mm.startsWith('jul')) { return 6; }
84+
if (mm.startsWith('aug')) { return 7; }
85+
if (mm.startsWith('sep')) { return 8; }
86+
if (mm.startsWith('oct')) { return 9; }
87+
if (mm.startsWith('nov')) { return 10; }
88+
if (mm.startsWith('dec')) { return 11; }
89+
90+
return NaN;
91+
};
92+
93+
const correctYear = (yy: number) => {
94+
if (yy < 100) {
95+
return yy < 68 ? yy + 2000 : yy + 1900;
96+
} else {
97+
return yy;
98+
}
99+
};
100+
101+
const validDateOrNull =
102+
(yyyy: number, month: number, day: number, hours: number, mins: number, ss: number): Date | null => {
103+
if (month > 11 || day > 31 || hours >= 60 || mins >= 60 || ss >= 60) { return null; }
104+
105+
const dd = new Date(yyyy, month, day, hours, mins, ss, 0);
106+
return !isNaN(dd.valueOf()) ? dd : null;
91107
};
92-
93-
const correctYear = (yy: number) => {
94-
if (yy < 100) {
95-
return yy < 68 ? yy + 2000 : yy + 1900;
96-
} else {
97-
return yy;
98-
}
99-
};
100-
101-
const validDateOrNull =
102-
(yyyy: number, month: number, day: number, hours: number, mins: number, ss: number): Date | null => {
103-
if (month > 11 || day > 31 || hours >= 60 || mins >= 60 || ss >= 60) { return null; }
104-
105-
const dd = new Date(yyyy, month, day, hours, mins, ss, 0);
106-
return !isNaN(dd.valueOf()) ? dd : null;
107-
};
108-
109-
const strTokens = strValue.replace('T', ' ').toLowerCase().split(/[: /-]/);
110-
const dt = strTokens.map(parseFloat);
111-
112-
// try ISO first
113-
let d = validDateOrNull(dt[0], dt[1] - 1, dt[2], dt[3] || 0, dt[4] || 0, dt[5] || 0);
114-
if (d) { return d; }
115-
116-
// then UK
117-
d = validDateOrNull(correctYear(dt[2]), parseMonth(strTokens[1]), dt[0], dt[3] || 0, dt[4] || 0, dt[5] || 0);
118-
if (d) { return d; }
119-
120-
// then US
121-
d = validDateOrNull(correctYear(dt[2]), parseMonth(strTokens[0]), correctYear(dt[1]), dt[3] || 0, dt[4] || 0, dt[5] || 0);
122-
if (d) { return d; }
123-
124-
return null;
125-
}
126-
108+
109+
const strTokens = strValue.replace('T', ' ').toLowerCase().split(/[: /-]/);
110+
const dt = strTokens.map(parseFloat);
111+
112+
// try ISO first
113+
let d = validDateOrNull(dt[0], dt[1] - 1, dt[2], dt[3] || 0, dt[4] || 0, dt[5] || 0);
114+
if (d) { return d; }
115+
116+
// then UK
117+
d = validDateOrNull(correctYear(dt[2]), parseMonth(strTokens[1]), dt[0], dt[3] || 0, dt[4] || 0, dt[5] || 0);
118+
if (d) { return d; }
119+
120+
// then US
121+
d = validDateOrNull(correctYear(dt[2]), parseMonth(strTokens[0]), correctYear(dt[1]), dt[3] || 0, dt[4] || 0, dt[5] || 0);
122+
if (d) { return d; }
123+
124+
return null;
125+
}

src/eval/eval.instruction.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class EvalInstruction {
2121
}
2222
obj = obj[pathParts[i]];
2323
} else {
24-
const n = propName.substring(openBr + 1, propName.length - openBr)
24+
const n = propName.substring(openBr + 1, propName.length - 1)
2525
const pName = propName.substring(0, openBr)
2626
const ind = parseInt(n);
2727
if (!isNaN(ind)) {
@@ -45,7 +45,7 @@ export class EvalInstruction {
4545
if (openBr < 0) {
4646
obj[propName] = value;
4747
} else {
48-
const n = propName.substring(openBr + 1, propName.length - openBr)
48+
const n = propName.substring(openBr + 1, propName.length - 1)
4949
const pName = propName.substring(0, openBr)
5050
const ind = parseInt(n);
5151
if (!isNaN(ind)) {
@@ -72,7 +72,7 @@ export class EvalInstruction {
7272
}
7373
obj = obj[pathParts[i]];
7474
} else {
75-
const n = propName.substring(openBr + 1, propName.length - openBr)
75+
const n = propName.substring(openBr + 1, propName.length - 1)
7676
const pName = propName.substring(0, openBr)
7777
const ind = parseInt(n);
7878
if (!isNaN(ind)) {
@@ -96,7 +96,7 @@ export class EvalInstruction {
9696
if (openBr < 0) {
9797
obj[propName] = value;
9898
} else {
99-
const n = propName.substring(openBr + 1, propName.length - openBr)
99+
const n = propName.substring(openBr + 1, propName.length - 1)
100100
const pName = propName.substring(0, openBr)
101101
const ind = parseInt(n);
102102
if (!isNaN(ind)) {

src/interpreter.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ function range(start: number, stop: number = NaN, step: number = 1): number[] {
2020
}
2121

2222
const INITIAL_SCOPE = {
23+
jsPython(): string {
24+
return ["JSPython v0.1.0", "(c) FalconSoft Ltd"].join('\n')
25+
},
2326
dateTime: (str: number | string | any = null) => (str && str.length)
2427
? parseDatetimeOrNull(str) || new Date() : new Date(),
2528
range: range,
@@ -102,7 +105,7 @@ export class Interpreter {
102105

103106
if (importLines.length && this.packageLoader) {
104107
const libraries = this.packageResolver(Tokenizer.getPackagesList(importLines));
105-
context = {...context, ...libraries};
108+
context = { ...context, ...libraries };
106109
}
107110

108111
this.globalScope = {
@@ -179,26 +182,26 @@ export class Interpreter {
179182
}
180183

181184
private packageResolver(packages: PackageToImport[]): object {
182-
if (!this.packageLoader) {
183-
throw Error('Package loader not provided.');
184-
}
185-
const libraries: any = {};
186-
packages.forEach(({ name, as, properties }: PackageToImport) => {
187-
const lib = this.packageLoader && this.packageLoader(name);
188-
if (properties?.length) {
189-
properties.forEach((prop) => {
190-
libraries[prop.as || prop.name] = lib[prop.name];
191-
})
192-
} else if (as) {
193-
libraries[as] = lib;
194-
} else {
195-
libraries[name] = lib;
196-
}
197-
if (as) {
198-
libraries[as] = lib;
199-
}
200-
});
201-
return libraries;
185+
if (!this.packageLoader) {
186+
throw Error('Package loader not provided.');
187+
}
188+
const libraries: any = {};
189+
packages.forEach(({ name, as, properties }: PackageToImport) => {
190+
const lib = this.packageLoader && this.packageLoader(name);
191+
if (properties?.length) {
192+
properties.forEach((prop) => {
193+
libraries[prop.as || prop.name] = lib[prop.name];
194+
})
195+
} else if (as) {
196+
libraries[as] = lib;
197+
} else {
198+
libraries[name] = lib;
199+
}
200+
if (as) {
201+
libraries[as] = lib;
202+
}
203+
});
204+
return libraries;
202205
}
203206

204207
}

0 commit comments

Comments
 (0)