Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 86a41fc

Browse files
committed
Fixed an issue with conflicting prototype methods. #37
1 parent 9ddcfb0 commit 86a41fc

File tree

6 files changed

+111
-63
lines changed

6 files changed

+111
-63
lines changed

‎package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jspython-interpreter",
3-
"version": "2.1.13",
3+
"version": "2.1.14",
44
"description": "JSPython is a javascript implementation of Python language that runs within web browser or NodeJS environment",
55
"keywords": [
66
"python",

‎src/common/operators.ts

Lines changed: 74 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,38 @@ export type Operators =
1919
| LogicalOperators
2020
| MembershipOperators;
2121

22-
export const OperatorsMap: Record<Operators, OperationTypes> = {
23-
'+': OperationTypes.Arithmetic,
24-
'-': OperationTypes.Arithmetic,
25-
'*': OperationTypes.Arithmetic,
26-
'/': OperationTypes.Arithmetic,
27-
'%': OperationTypes.Arithmetic,
28-
'**': OperationTypes.Arithmetic,
29-
'//': OperationTypes.Arithmetic,
30-
31-
'>': OperationTypes.Comparison,
32-
'>=': OperationTypes.Comparison,
33-
'==': OperationTypes.Comparison,
34-
'!=': OperationTypes.Comparison,
35-
'<>': OperationTypes.Comparison,
36-
'<': OperationTypes.Comparison,
37-
'<=': OperationTypes.Comparison,
38-
39-
and: OperationTypes.Logical,
40-
or: OperationTypes.Logical,
41-
// "not": OperationTypes.Logical,
42-
// "not in": OperationTypes.Logical,
43-
44-
in: OperationTypes.Membership,
45-
46-
'=': OperationTypes.Assignment,
47-
'+=': OperationTypes.Assignment,
48-
'-=': OperationTypes.Assignment,
49-
'*=': OperationTypes.Assignment,
50-
'/=': OperationTypes.Assignment,
51-
'++': OperationTypes.Assignment,
52-
'--': OperationTypes.Assignment
53-
};
22+
export const OperatorsMap: Map<Operators, OperationTypes> = newMap<Operators,OperationTypes>([
23+
['+', OperationTypes.Arithmetic],
24+
['-', OperationTypes.Arithmetic],
25+
['*', OperationTypes.Arithmetic],
26+
['/', OperationTypes.Arithmetic],
27+
['%', OperationTypes.Arithmetic],
28+
['**', OperationTypes.Arithmetic],
29+
['//', OperationTypes.Arithmetic],
30+
31+
['>', OperationTypes.Comparison],
32+
['>=', OperationTypes.Comparison],
33+
['==', OperationTypes.Comparison],
34+
['!=', OperationTypes.Comparison],
35+
['<>', OperationTypes.Comparison],
36+
['<', OperationTypes.Comparison],
37+
['<=', OperationTypes.Comparison],
38+
39+
['and', OperationTypes.Logical],
40+
['or', OperationTypes.Logical],
41+
// "not", OperationTypes.Logical],
42+
// "not in", OperationTypes.Logical],
43+
44+
['in', OperationTypes.Membership],
45+
46+
['=', OperationTypes.Assignment],
47+
['+=', OperationTypes.Assignment],
48+
['-=', OperationTypes.Assignment],
49+
['*=', OperationTypes.Assignment],
50+
['/=', OperationTypes.Assignment],
51+
['++', OperationTypes.Assignment],
52+
['--', OperationTypes.Assignment]
53+
]);
5454

5555
export type Primitive = string | number | boolean | null;
5656

@@ -61,30 +61,48 @@ export type ExpressionOperators =
6161
| MembershipOperators;
6262
type ExpressionOperation = (l: Primitive, r: Primitive) => Primitive;
6363

64-
export const OperationFuncs: Record<ExpressionOperators, ExpressionOperation> = {
65-
'+': (l, r) => arithmeticOperation(l, r, '+'),
66-
'-': (l, r) => arithmeticOperation(l, r, '-'),
67-
'/': (l, r) => arithmeticOperation(l, r, '/'),
68-
'*': (l, r) => arithmeticOperation(l, r, '*'),
69-
'%': (l, r) => arithmeticOperation(l, r, '%'),
70-
'**': (l, r) => arithmeticOperation(l, r, '**'),
71-
'//': (l, r) => arithmeticOperation(l, r, '//'),
72-
73-
'>': (l, r) => comparissonOperation(l, r, '>'),
74-
'>=': (l, r) => comparissonOperation(l, r, '>='),
75-
'<': (l, r) => comparissonOperation(l, r, '<'),
76-
'<=': (l, r) => comparissonOperation(l, r, '<='),
77-
'==': (l, r) => comparissonOperation(l, r, '=='),
78-
'!=': (l, r) => comparissonOperation(l, r, '!='),
79-
'<>': (l, r) => comparissonOperation(l, r, '<>'),
80-
81-
and: (l, r) => logicalOperation(l, r, 'and'),
82-
or: (l, r) => logicalOperation(l, r, 'or'),
83-
// "not": (l, r) => logicalOperation(l, r, "not"),
84-
// "not in": (l, r) => logicalOperation(l, r, "not in"),
85-
86-
in: (l, r) => membershipOperation(l, r, 'in')
87-
};
64+
export const OperationFuncs: Map<ExpressionOperators, ExpressionOperation> = new Map<
65+
ExpressionOperators,
66+
ExpressionOperation
67+
>([
68+
['+' as ExpressionOperators, ((l, r) => arithmeticOperation(l, r, '+')) as ExpressionOperation],
69+
['-' as ExpressionOperators, ((l, r) => arithmeticOperation(l, r, '-')) as ExpressionOperation],
70+
['/' as ExpressionOperators, ((l, r) => arithmeticOperation(l, r, '/')) as ExpressionOperation],
71+
['*' as ExpressionOperators, ((l, r) => arithmeticOperation(l, r, '*')) as ExpressionOperation],
72+
['%' as ExpressionOperators, ((l, r) => arithmeticOperation(l, r, '%')) as ExpressionOperation],
73+
['**' as ExpressionOperators, ((l, r) => arithmeticOperation(l, r, '**')) as ExpressionOperation],
74+
['//' as ExpressionOperators, ((l, r) => arithmeticOperation(l, r, '//')) as ExpressionOperation],
75+
76+
['>' as ExpressionOperators, ((l, r) => comparissonOperation(l, r, '>')) as ExpressionOperation],
77+
[
78+
'>=' as ExpressionOperators,
79+
((l, r) => comparissonOperation(l, r, '>=')) as ExpressionOperation
80+
],
81+
['<' as ExpressionOperators, ((l, r) => comparissonOperation(l, r, '<')) as ExpressionOperation],
82+
[
83+
'<=' as ExpressionOperators,
84+
((l, r) => comparissonOperation(l, r, '<=')) as ExpressionOperation
85+
],
86+
[
87+
'==' as ExpressionOperators,
88+
((l, r) => comparissonOperation(l, r, '==')) as ExpressionOperation
89+
],
90+
[
91+
'!=' as ExpressionOperators,
92+
((l, r) => comparissonOperation(l, r, '!=')) as ExpressionOperation
93+
],
94+
[
95+
'<>' as ExpressionOperators,
96+
((l, r) => comparissonOperation(l, r, '<>')) as ExpressionOperation
97+
],
98+
99+
['and' as ExpressionOperators, ((l, r) => logicalOperation(l, r, 'and')) as ExpressionOperation],
100+
['or' as ExpressionOperators, ((l, r) => logicalOperation(l, r, 'or')) as ExpressionOperation],
101+
// "not" as ExpressionOperators, ((l, r) => logicalOperation(l, r, "not")) as ExpressionOperation],
102+
// "not in" as ExpressionOperators, ((l, r) => logicalOperation(l, r, "not in")) as ExpressionOperation],
103+
104+
['in' as ExpressionOperators, ((l, r) => membershipOperation(l, r, 'in')) as ExpressionOperation]
105+
]);
88106

89107
function membershipOperation(l: Primitive, r: Primitive, op: MembershipOperators): Primitive {
90108
if (typeof l === 'string') {

‎src/common/token-types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,11 @@ export function findOperators(
182182
operationType: OperationTypes | null = null
183183
): number[] {
184184
return !operationType
185-
? findTokenValueIndexes(tokens, value => OperatorsMap[value as Operators] !== undefined)
186-
: findTokenValueIndexes(tokens, value => OperatorsMap[value as Operators] === operationType);
185+
? findTokenValueIndexes(tokens, value => OperatorsMap.has(value as Operators))
186+
: findTokenValueIndexes(
187+
tokens,
188+
value => OperatorsMap.get(value as Operators) === operationType
189+
);
187190
}
188191

189192
function skipInnerBrackets(

‎src/evaluator/evaluator.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export class Evaluator {
160160
}
161161
}
162162
}
163-
163+
164164
if (doElse && ifNode.elseBody) {
165165
this.evalBlock(
166166
{ name: blockContext.moduleName, type: 'if', body: ifNode.elseBody } as AstBlock,
@@ -332,7 +332,9 @@ export class Evaluator {
332332
const binOpNode = node as BinOpNode;
333333
const left = this.evalNode(binOpNode.left, blockContext);
334334
const right = this.evalNode(binOpNode.right, blockContext);
335-
return OperationFuncs[binOpNode.op](left as Primitive, right as Primitive);
335+
const func = OperationFuncs.get(binOpNode.op);
336+
if (typeof func === 'function') return func(left as Primitive, right as Primitive);
337+
else throw new Error('Unknown binary oprastion');
336338
}
337339

338340
if (node.type === 'logicalOp') {

‎src/evaluator/evaluatorAsync.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,10 @@ export class EvaluatorAsync {
436436
const binOpNode = node as BinOpNode;
437437
const left = await this.evalNodeAsync(binOpNode.left, blockContext);
438438
const right = await this.evalNodeAsync(binOpNode.right, blockContext);
439-
return OperationFuncs[binOpNode.op](left as Primitive, right as Primitive);
439+
440+
const func = OperationFuncs.get(binOpNode.op);
441+
if (typeof func === 'function') return func(left as Primitive, right as Primitive);
442+
else throw new Error('Unknown binary oprastion');
440443
}
441444

442445
if (node.type === 'logicalOp') {

‎src/parser/parser.spec.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,28 @@ describe('Parser => ', () => {
157157
expect(!!(innerNodes[3] as ChainingObjectAccessNode).nullCoelsing).toBe(true);
158158
expect(!!(innerNodes[4] as ChainingObjectAccessNode).nullCoelsing).toBe(true);
159159
expect(!!(innerNodes[5] as ChainingObjectAccessNode).nullCoelsing).toBe(false);
160-
});
160+
});
161+
162+
it('chaining calls 1 with ? ', async () => {
163+
const script = `"1,2,3".split(',')?[0]`;
164+
const ast = new Parser().parse(new Tokenizer().tokenize(script));
165+
expect(ast.body.length).toBe(1);
166+
const innerNodes = (ast.body[0] as ChainingCallsNode).innerNodes;
167+
168+
expect(ast.body[0].type).toBe("chainingCalls");
169+
expect(innerNodes.length).toBe(3);
170+
expect(innerNodes[2].type).toBe("chainingObjectAccess");
171+
172+
expect(!!(innerNodes[0] as ChainingObjectAccessNode).nullCoelsing).toBe(false);
173+
expect((innerNodes[1] as ChainingObjectAccessNode).nullCoelsing).toBe(true);
174+
expect(!!(innerNodes[2] as ChainingObjectAccessNode).nullCoelsing).toBe(false);
175+
});
176+
177+
it('prototype methods call ', async () => {
178+
expect(new Parser().parse(new Tokenizer().tokenize(`t.toString`)).body.length).toBe(1);
179+
expect(new Parser().parse(new Tokenizer().tokenize(`t.toString()`)).body.length).toBe(1);
180+
expect(new Parser().parse(new Tokenizer().tokenize(`t.valueOf`)).body.length).toBe(1);
181+
expect(new Parser().parse(new Tokenizer().tokenize(`t.valueOf()`)).body.length).toBe(1);
182+
});
161183

162184
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /