jpsx 0.1.18 → 0.1.19
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/README.md +73 -173
- package/dist/api/__tests__/runtime.test.js +112 -112
- package/package.json +85 -82
package/README.md
CHANGED
|
@@ -3,29 +3,30 @@
|
|
|
3
3
|
|
|
4
4
|
A Python-like language that compiles to JavaScript, designed to integrate seamlessly with **any frontend framework**.
|
|
5
5
|
|
|
6
|
-
[](https://www.npmjs.com/package/jpsx)
|
|
7
7
|
[](LICENSE)
|
|
8
|
+
<a href="https://www.producthunt.com/products/jps?embed=true&utm_source=badge-featured&utm_medium=badge&utm_campaign=badge-jps" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1067365&theme=light" alt="JPS - New Programming Language | Write Python-like in Javascript | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- 🐍 **Python-like syntax** that compiles to clean JavaScript
|
|
12
|
-
- ⚡ **Standalone file integration** - Import `.jps` files like `.jsx/.tsx` files!
|
|
13
|
-
- 🔥 **Hot Module Replacement (HMR)** - Instant feedback during development
|
|
14
|
-
- ⚡ **Zero-config integration** with React, Vue, Svelte, Angular, and more
|
|
15
|
-
- 📦 **Multiple output formats**: ESM, CommonJS, IIFE, UMD
|
|
16
|
-
- 🔌 **Flexible runtime modes**: Inline, external, CDN, or custom
|
|
17
|
-
- 🛠️ **Build tool plugins** for Vite, Webpack, Rollup, esbuild
|
|
18
|
-
- 🌐 **Browser-ready**: Works without any build step
|
|
19
|
-
- 📝 **TypeScript support** with auto-generated declarations
|
|
10
|
+
---
|
|
20
11
|
|
|
21
12
|
## 🚀 Quick Start
|
|
22
13
|
|
|
23
|
-
###
|
|
14
|
+
### Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Install as a library in your project
|
|
18
|
+
npm install jpsx
|
|
19
|
+
|
|
20
|
+
# Or install globally as a CLI tool
|
|
21
|
+
npm install -g jpsx
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### ⚡ Standalone File Integration (Recommended)
|
|
24
25
|
|
|
25
26
|
Import `.jps` files directly in your code - just like `.tsx` files!
|
|
26
27
|
|
|
28
|
+
**math.jps**
|
|
27
29
|
```python
|
|
28
|
-
# math.jps - a real file!
|
|
29
30
|
def add(a, b):
|
|
30
31
|
return a + b
|
|
31
32
|
|
|
@@ -34,210 +35,109 @@ class Calculator:
|
|
|
34
35
|
self.value = 0
|
|
35
36
|
```
|
|
36
37
|
|
|
38
|
+
**App.tsx**
|
|
37
39
|
```typescript
|
|
38
|
-
// App.tsx - just import and use!
|
|
39
40
|
import { add, Calculator } from './math.jps';
|
|
40
41
|
|
|
41
42
|
const sum = add(10, 20);
|
|
42
43
|
const calc = new Calculator();
|
|
43
44
|
```
|
|
44
45
|
|
|
45
|
-
**[See full example →](examples/react-vite-standalone/)**
|
|
46
|
-
|
|
47
46
|
---
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
# Install globally
|
|
53
|
-
npm install -g jps
|
|
54
|
-
|
|
55
|
-
# Create a new project
|
|
56
|
-
jps init my-project
|
|
57
|
-
cd my-project
|
|
58
|
-
jps run main.jps
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### As a Library (Runtime Compilation)
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
# Install in your project
|
|
65
|
-
npm install jps
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
#### React
|
|
69
|
-
|
|
70
|
-
```javascript
|
|
71
|
-
import { compile } from 'jps';
|
|
72
|
-
|
|
73
|
-
function App() {
|
|
74
|
-
const jpsCode = `
|
|
75
|
-
def greet(name):
|
|
76
|
-
return "Hello, " + name
|
|
77
|
-
|
|
78
|
-
print(greet("React"))
|
|
79
|
-
`;
|
|
80
|
-
|
|
81
|
-
const result = compile(jpsCode, {
|
|
82
|
-
format: 'iife',
|
|
83
|
-
runtimeMode: 'inline'
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
eval(result.code); // Outputs: Hello, React
|
|
87
|
-
}
|
|
88
|
-
```
|
|
48
|
+
## ✨ Features
|
|
89
49
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
eval(result.code);
|
|
100
|
-
</script>
|
|
101
|
-
```
|
|
50
|
+
- 🐍 **Python-like syntax** that compiles to clean JavaScript
|
|
51
|
+
- ⚡ **Standalone file integration** - Import `.jps` files like `.jsx/.tsx` files!
|
|
52
|
+
- 🔥 **Hot Module Replacement (HMR)** - Instant feedback during development
|
|
53
|
+
- ⚡ **Zero-config integration** with React, Vue, Svelte, Angular, and more
|
|
54
|
+
- 📦 **Multiple output formats**: ESM, CommonJS, IIFE, UMD
|
|
55
|
+
- 🔌 **Flexible runtime modes**: Inline, external, CDN, or custom
|
|
56
|
+
- 🛠️ **Build tool plugins** for Vite, Webpack, Rollup, esbuild
|
|
57
|
+
- 🌐 **Browser-ready**: Works without any build step
|
|
58
|
+
- 📝 **TypeScript support** with auto-generated declarations
|
|
102
59
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
```html
|
|
106
|
-
<script type="module">
|
|
107
|
-
import { compile } from 'https://cdn.jsdelivr.net/npm/jps@latest/dist/api/index.js';
|
|
108
|
-
const result = compile('print("Hello Browser!")', {
|
|
109
|
-
format: 'iife',
|
|
110
|
-
runtimeMode: 'inline'
|
|
111
|
-
});
|
|
112
|
-
eval(result.code);
|
|
113
|
-
</script>
|
|
114
|
-
```
|
|
60
|
+
---
|
|
115
61
|
|
|
116
|
-
## 📖 Documentation
|
|
62
|
+
## 📖 Documentation & Guidelines
|
|
117
63
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
- **[Quick Start](docs/QUICKSTART.md)** - 30-second integration examples
|
|
121
|
-
- **[Syntax Guide](docs/syntax.md)** - JPS language syntax
|
|
122
|
-
- **[Standard Library](docs/stdlib.md)** - Built-in functions
|
|
123
|
-
- **[API Reference](docs/API.md)** - Programmatic API
|
|
64
|
+
### 1. Language Syntax
|
|
65
|
+
JPS supports core Python syntax tailored for the JavaScript ecosystem.
|
|
124
66
|
|
|
125
|
-
|
|
67
|
+
| Feature | JPS Syntax | Compiles to JS |
|
|
68
|
+
|---------|------------|----------------|
|
|
69
|
+
| **Function** | `def foo(a): return a` | `function foo(a) { return a; }` |
|
|
70
|
+
| **Class** | `class User: ...` | `class User { ... }` |
|
|
71
|
+
| **Loop** | `for i in range(5): ...` | `for (let i = 0; i < 5; i++) ...` |
|
|
72
|
+
| **List Comp** | `[x*2 for x in nums]` | `nums.map(x => x * 2)` |
|
|
126
73
|
|
|
127
|
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
131
|
-
-
|
|
74
|
+
### 2. Runtime Functions
|
|
75
|
+
Built-in Python-like functions available globally:
|
|
76
|
+
- `print(args)`
|
|
77
|
+
- `len(obj)`
|
|
78
|
+
- `range(start, stop, step)`
|
|
79
|
+
- `sum(iterable)`
|
|
80
|
+
- `min() / max()`
|
|
81
|
+
- `sorted(iterable)`
|
|
132
82
|
|
|
133
|
-
|
|
83
|
+
### 3. CLI Usage
|
|
134
84
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- `jps doctor` - Verify environment setup
|
|
85
|
+
```bash
|
|
86
|
+
# Initialize a new JPS project
|
|
87
|
+
jps init my-project
|
|
88
|
+
cd my-project
|
|
140
89
|
|
|
141
|
-
|
|
90
|
+
# Run a JPS file directly
|
|
91
|
+
jps run main.jps
|
|
142
92
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// Full API with metadata
|
|
147
|
-
const result = compile(source, {
|
|
148
|
-
format: 'esm', // Output format: 'esm' | 'cjs' | 'iife' | 'umd'
|
|
149
|
-
runtimeMode: 'inline', // Runtime: 'inline' | 'external' | 'cdn' | 'none'
|
|
150
|
-
moduleName: 'MyApp', // For IIFE/UMD
|
|
151
|
-
sourceMap: true, // Include source maps
|
|
152
|
-
standalone: false // Bundle everything
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// Simple API (just returns code)
|
|
156
|
-
const jsCode = compileToJS(source);
|
|
157
|
-
|
|
158
|
-
// Get runtime library code
|
|
159
|
-
const runtime = getRuntime();
|
|
93
|
+
# Build for production
|
|
94
|
+
jps build main.jps --format esm
|
|
160
95
|
```
|
|
161
96
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
Check out the [examples/](examples/) directory for complete working examples:
|
|
165
|
-
|
|
166
|
-
- **React** - Vite plugin, Webpack loader, runtime compilation
|
|
167
|
-
- **Vue 3** - Composition API integration
|
|
168
|
-
- **Svelte** - Component integration
|
|
169
|
-
- **Angular** - Service integration
|
|
170
|
-
- **Next.js** - App Router and Pages Router
|
|
171
|
-
- **Vanilla Browser** - No build step required
|
|
172
|
-
|
|
173
|
-
## 🛠️ Build Tool Plugins
|
|
174
|
-
|
|
175
|
-
### Vite
|
|
97
|
+
### 4. Integration Guide
|
|
176
98
|
|
|
99
|
+
**Vite Plugin**
|
|
177
100
|
```javascript
|
|
178
101
|
// vite.config.js
|
|
179
|
-
import { jpsPlugin } from '
|
|
102
|
+
import { jpsPlugin } from 'vite-plugin-jpsx';
|
|
180
103
|
|
|
181
104
|
export default {
|
|
182
105
|
plugins: [jpsPlugin()]
|
|
183
106
|
};
|
|
184
107
|
```
|
|
185
108
|
|
|
186
|
-
|
|
187
|
-
|
|
109
|
+
**Webpack Loader**
|
|
188
110
|
```javascript
|
|
189
111
|
// webpack.config.js
|
|
190
112
|
module.exports = {
|
|
191
113
|
module: {
|
|
192
114
|
rules: [
|
|
193
|
-
{ test: /\.jps$/, use: '
|
|
115
|
+
{ test: /\.jps$/, use: 'jpsx-loader' }
|
|
194
116
|
]
|
|
195
117
|
}
|
|
196
118
|
};
|
|
197
119
|
```
|
|
198
120
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
## 🌟 Why JPS?
|
|
202
|
-
|
|
203
|
-
1. **Framework Agnostic**: Works with React, Vue, Svelte, Angular, and vanilla JS
|
|
204
|
-
2. **Flexible Output**: Choose the format that fits your needs
|
|
205
|
-
3. **Modern & Production-Ready**: Built with TypeScript, full test coverage
|
|
206
|
-
4. **Developer Friendly**: Simple API, great error messages, comprehensive docs
|
|
207
|
-
5. **Lightweight**: Minimal dependencies, tree-shakeable
|
|
208
|
-
|
|
209
|
-
## 🏗️ Development
|
|
210
|
-
|
|
211
|
-
Prerequisites: Node.js 18+
|
|
121
|
+
---
|
|
212
122
|
|
|
213
|
-
|
|
214
|
-
# Clone the repository
|
|
215
|
-
git clone https://github.com/your-repo/jps.git
|
|
216
|
-
cd jps
|
|
123
|
+
## 🌟 Support Us
|
|
217
124
|
|
|
218
|
-
|
|
219
|
-
npm install
|
|
125
|
+
We are live on Product Hunt! If you like JPS, please support us:
|
|
220
126
|
|
|
221
|
-
|
|
222
|
-
|
|
127
|
+
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; border: 1px solid rgb(224, 224, 224); border-radius: 12px; padding: 20px; max-width: 500px; background: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.05) 0px 2px 8px;">
|
|
128
|
+
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 12px;">
|
|
129
|
+
<img alt="JPS" src="https://ph-files.imgix.net/99b42643-283d-47de-970f-27ae2be5a99a.jpeg?auto=format&fit=crop&w=80&h=80" style="width: 64px; height: 64px; border-radius: 8px; object-fit: cover; flex-shrink: 0;">
|
|
130
|
+
<div style="flex: 1 1 0%; min-width: 0px;">
|
|
131
|
+
<h3 style="margin: 0px; font-size: 18px; font-weight: 600; color: rgb(26, 26, 26); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">JPS</h3>
|
|
132
|
+
<p style="margin: 4px 0px 0px; font-size: 14px; color: rgb(102, 102, 102); line-height: 1.4; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">New Programming Language | Write Python-like in Javascript</p>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
<a href="https://www.producthunt.com/products/jps?embed=true&utm_source=embed&utm_medium=post_embed" target="_blank" rel="noopener" style="display: inline-flex; align-items: center; gap: 4px; margin-top: 12px; padding: 8px 16px; background: rgb(255, 97, 84); color: rgb(255, 255, 255); text-decoration: none; border-radius: 8px; font-size: 14px; font-weight: 600;">Check it out on Product Hunt →</a>
|
|
136
|
+
</div>
|
|
223
137
|
|
|
224
|
-
|
|
225
|
-
npm test
|
|
226
|
-
```
|
|
138
|
+
---
|
|
227
139
|
|
|
228
140
|
## 📄 License
|
|
229
|
-
|
|
230
|
-
ISC - See [LICENSE](LICENSE) file for details
|
|
231
|
-
|
|
232
|
-
## 🤝 Contributing
|
|
233
|
-
|
|
234
|
-
Contributions are welcome! Please read our contributing guidelines first.
|
|
235
|
-
|
|
236
|
-
## 📮 Support
|
|
237
|
-
|
|
238
|
-
- **Issues**: [GitHub Issues](https://github.com/your-repo/jps/issues)
|
|
239
|
-
- **Discussions**: [GitHub Discussions](https://github.com/your-repo/jps/discussions)
|
|
240
|
-
|
|
241
|
-
---
|
|
141
|
+
ISC - See [LICENSE](LICENSE)
|
|
242
142
|
|
|
243
143
|
**Made with ❤️ by Loaii abdalslam**
|
|
@@ -40,140 +40,140 @@ describe("Runtime Functions - Execution Tests", () => {
|
|
|
40
40
|
// TODO: Fix parser bug where function calls inside for loop body are not parsed correctly
|
|
41
41
|
// The parser generates `print; n;` instead of `print(n);`
|
|
42
42
|
test.skip("should generate range with single argument", () => {
|
|
43
|
-
const output = executeCode(`
|
|
44
|
-
numbers = range(5)
|
|
45
|
-
for n in numbers:
|
|
46
|
-
print(n)
|
|
43
|
+
const output = executeCode(`
|
|
44
|
+
numbers = range(5)
|
|
45
|
+
for n in numbers:
|
|
46
|
+
print(n)
|
|
47
47
|
`);
|
|
48
48
|
expect(output).toHaveLength(5);
|
|
49
49
|
expect(output).toEqual(["0", "1", "2", "3", "4"]);
|
|
50
50
|
});
|
|
51
51
|
test.skip("should generate range with start and stop", () => {
|
|
52
|
-
const output = executeCode(`
|
|
53
|
-
numbers = range(2, 5)
|
|
54
|
-
for n in numbers:
|
|
55
|
-
print(n)
|
|
52
|
+
const output = executeCode(`
|
|
53
|
+
numbers = range(2, 5)
|
|
54
|
+
for n in numbers:
|
|
55
|
+
print(n)
|
|
56
56
|
`);
|
|
57
57
|
expect(output).toEqual(["2", "3", "4"]);
|
|
58
58
|
});
|
|
59
59
|
test.skip("should generate range with step", () => {
|
|
60
|
-
const output = executeCode(`
|
|
61
|
-
numbers = range(0, 10, 2)
|
|
62
|
-
for n in numbers:
|
|
63
|
-
print(n)
|
|
60
|
+
const output = executeCode(`
|
|
61
|
+
numbers = range(0, 10, 2)
|
|
62
|
+
for n in numbers:
|
|
63
|
+
print(n)
|
|
64
64
|
`);
|
|
65
65
|
expect(output).toEqual(["0", "2", "4", "6", "8"]);
|
|
66
66
|
});
|
|
67
67
|
});
|
|
68
68
|
describe("sum() function", () => {
|
|
69
69
|
test("should sum array of numbers", () => {
|
|
70
|
-
const output = executeCode(`
|
|
71
|
-
numbers = [1, 2, 3, 4, 5]
|
|
72
|
-
total = sum(numbers)
|
|
73
|
-
print(total)
|
|
70
|
+
const output = executeCode(`
|
|
71
|
+
numbers = [1, 2, 3, 4, 5]
|
|
72
|
+
total = sum(numbers)
|
|
73
|
+
print(total)
|
|
74
74
|
`);
|
|
75
75
|
expect(output).toContain("15");
|
|
76
76
|
});
|
|
77
77
|
test("should sum range", () => {
|
|
78
|
-
const output = executeCode(`
|
|
79
|
-
total = sum(range(1, 11))
|
|
80
|
-
print(total)
|
|
78
|
+
const output = executeCode(`
|
|
79
|
+
total = sum(range(1, 11))
|
|
80
|
+
print(total)
|
|
81
81
|
`);
|
|
82
82
|
expect(output).toContain("55");
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
85
|
describe("len() function", () => {
|
|
86
86
|
test("should return length of array", () => {
|
|
87
|
-
const output = executeCode(`
|
|
88
|
-
arr = [1, 2, 3, 4, 5]
|
|
89
|
-
print(len(arr))
|
|
87
|
+
const output = executeCode(`
|
|
88
|
+
arr = [1, 2, 3, 4, 5]
|
|
89
|
+
print(len(arr))
|
|
90
90
|
`);
|
|
91
91
|
expect(output).toContain("5");
|
|
92
92
|
});
|
|
93
93
|
test("should return length of string", () => {
|
|
94
|
-
const output = executeCode(`
|
|
95
|
-
text = "Hello"
|
|
96
|
-
print(len(text))
|
|
94
|
+
const output = executeCode(`
|
|
95
|
+
text = "Hello"
|
|
96
|
+
print(len(text))
|
|
97
97
|
`);
|
|
98
98
|
expect(output).toContain("5");
|
|
99
99
|
});
|
|
100
100
|
});
|
|
101
101
|
describe("min() and max() functions", () => {
|
|
102
102
|
test("should find minimum", () => {
|
|
103
|
-
const output = executeCode(`
|
|
104
|
-
numbers = [5, 2, 8, 1, 9]
|
|
105
|
-
print(min(numbers))
|
|
103
|
+
const output = executeCode(`
|
|
104
|
+
numbers = [5, 2, 8, 1, 9]
|
|
105
|
+
print(min(numbers))
|
|
106
106
|
`);
|
|
107
107
|
expect(output).toContain("1");
|
|
108
108
|
});
|
|
109
109
|
test("should find maximum", () => {
|
|
110
|
-
const output = executeCode(`
|
|
111
|
-
numbers = [5, 2, 8, 1, 9]
|
|
112
|
-
print(max(numbers))
|
|
110
|
+
const output = executeCode(`
|
|
111
|
+
numbers = [5, 2, 8, 1, 9]
|
|
112
|
+
print(max(numbers))
|
|
113
113
|
`);
|
|
114
114
|
expect(output).toContain("9");
|
|
115
115
|
});
|
|
116
116
|
});
|
|
117
117
|
describe("sorted() function", () => {
|
|
118
118
|
test("should sort array ascending", () => {
|
|
119
|
-
const output = executeCode(`
|
|
120
|
-
numbers = [5, 2, 8, 1, 9]
|
|
121
|
-
sorted_nums = sorted(numbers)
|
|
122
|
-
print(sorted_nums)
|
|
119
|
+
const output = executeCode(`
|
|
120
|
+
numbers = [5, 2, 8, 1, 9]
|
|
121
|
+
sorted_nums = sorted(numbers)
|
|
122
|
+
print(sorted_nums)
|
|
123
123
|
`);
|
|
124
124
|
expect(output[0]).toContain("1");
|
|
125
125
|
expect(output[0]).toContain("9");
|
|
126
126
|
});
|
|
127
127
|
test("should sort array descending", () => {
|
|
128
|
-
const output = executeCode(`
|
|
129
|
-
numbers = [5, 2, 8, 1, 9]
|
|
130
|
-
sorted_nums = sorted(numbers, True)
|
|
131
|
-
print(sorted_nums[0])
|
|
128
|
+
const output = executeCode(`
|
|
129
|
+
numbers = [5, 2, 8, 1, 9]
|
|
130
|
+
sorted_nums = sorted(numbers, True)
|
|
131
|
+
print(sorted_nums[0])
|
|
132
132
|
`);
|
|
133
133
|
expect(output[0]).toContain("9");
|
|
134
134
|
});
|
|
135
135
|
});
|
|
136
136
|
describe("Type conversion functions", () => {
|
|
137
137
|
test("str() should convert to string", () => {
|
|
138
|
-
const output = executeCode(`
|
|
139
|
-
num = 42
|
|
140
|
-
text = str(num)
|
|
141
|
-
print(text)
|
|
138
|
+
const output = executeCode(`
|
|
139
|
+
num = 42
|
|
140
|
+
text = str(num)
|
|
141
|
+
print(text)
|
|
142
142
|
`);
|
|
143
143
|
expect(output).toContain("42");
|
|
144
144
|
});
|
|
145
145
|
test("int() should convert to integer", () => {
|
|
146
|
-
const output = executeCode(`
|
|
147
|
-
text = "42"
|
|
148
|
-
num = int(text)
|
|
149
|
-
print(num)
|
|
146
|
+
const output = executeCode(`
|
|
147
|
+
text = "42"
|
|
148
|
+
num = int(text)
|
|
149
|
+
print(num)
|
|
150
150
|
`);
|
|
151
151
|
expect(output).toContain("42");
|
|
152
152
|
});
|
|
153
153
|
test("float() should convert to float", () => {
|
|
154
|
-
const output = executeCode(`
|
|
155
|
-
text = "3.14"
|
|
156
|
-
num = float(text)
|
|
157
|
-
print(num)
|
|
154
|
+
const output = executeCode(`
|
|
155
|
+
text = "3.14"
|
|
156
|
+
num = float(text)
|
|
157
|
+
print(num)
|
|
158
158
|
`);
|
|
159
159
|
expect(output).toContain("3.14");
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
162
|
describe("List comprehensions", () => {
|
|
163
163
|
test("should execute simple list comprehension", () => {
|
|
164
|
-
const output = executeCode(`
|
|
165
|
-
numbers = [x * 2 for x in range(5)]
|
|
166
|
-
print(numbers)
|
|
164
|
+
const output = executeCode(`
|
|
165
|
+
numbers = [x * 2 for x in range(5)]
|
|
166
|
+
print(numbers)
|
|
167
167
|
`);
|
|
168
168
|
expect(output[0]).toContain("0");
|
|
169
169
|
expect(output[0]).toContain("8");
|
|
170
170
|
});
|
|
171
171
|
// TODO: Fix parser bug where function calls inside for loop body are not parsed correctly
|
|
172
172
|
test.skip("should execute nested list comprehension", () => {
|
|
173
|
-
const output = executeCode(`
|
|
174
|
-
squares = [x * x for x in range(1, 6)]
|
|
175
|
-
for s in squares:
|
|
176
|
-
print(s)
|
|
173
|
+
const output = executeCode(`
|
|
174
|
+
squares = [x * x for x in range(1, 6)]
|
|
175
|
+
for s in squares:
|
|
176
|
+
print(s)
|
|
177
177
|
`);
|
|
178
178
|
expect(output).toEqual(["1", "4", "9", "16", "25"]);
|
|
179
179
|
});
|
|
@@ -181,63 +181,63 @@ for s in squares:
|
|
|
181
181
|
describe("Functions", () => {
|
|
182
182
|
// TODO: Fix parser bug where function calls are not correctly parsed in certain contexts
|
|
183
183
|
test.skip("should define and call function", () => {
|
|
184
|
-
const output = executeCode(`
|
|
185
|
-
def greet(name):
|
|
186
|
-
return "Hello, " + name
|
|
187
|
-
|
|
188
|
-
message = greet("World")
|
|
189
|
-
print(message)
|
|
184
|
+
const output = executeCode(`
|
|
185
|
+
def greet(name):
|
|
186
|
+
return "Hello, " + name
|
|
187
|
+
|
|
188
|
+
message = greet("World")
|
|
189
|
+
print(message)
|
|
190
190
|
`);
|
|
191
191
|
expect(output).toContain("Hello, World");
|
|
192
192
|
});
|
|
193
193
|
test.skip("should handle multiple parameters", () => {
|
|
194
|
-
const output = executeCode(`
|
|
195
|
-
def add(a, b):
|
|
196
|
-
return a + b
|
|
197
|
-
|
|
198
|
-
result = add(5, 3)
|
|
199
|
-
print(result)
|
|
194
|
+
const output = executeCode(`
|
|
195
|
+
def add(a, b):
|
|
196
|
+
return a + b
|
|
197
|
+
|
|
198
|
+
result = add(5, 3)
|
|
199
|
+
print(result)
|
|
200
200
|
`);
|
|
201
201
|
expect(output).toContain("8");
|
|
202
202
|
});
|
|
203
203
|
test.skip("should support recursion", () => {
|
|
204
|
-
const output = executeCode(`
|
|
205
|
-
def factorial(n):
|
|
206
|
-
if n <= 1:
|
|
207
|
-
return 1
|
|
208
|
-
return n * factorial(n - 1)
|
|
209
|
-
|
|
210
|
-
result = factorial(5)
|
|
211
|
-
print(result)
|
|
204
|
+
const output = executeCode(`
|
|
205
|
+
def factorial(n):
|
|
206
|
+
if n <= 1:
|
|
207
|
+
return 1
|
|
208
|
+
return n * factorial(n - 1)
|
|
209
|
+
|
|
210
|
+
result = factorial(5)
|
|
211
|
+
print(result)
|
|
212
212
|
`);
|
|
213
213
|
expect(output).toContain("120");
|
|
214
214
|
});
|
|
215
215
|
});
|
|
216
216
|
describe("Control Flow", () => {
|
|
217
217
|
test("should execute if-else", () => {
|
|
218
|
-
const output = executeCode(`
|
|
219
|
-
x = 10
|
|
220
|
-
if x > 5:
|
|
221
|
-
print("big")
|
|
222
|
-
else:
|
|
223
|
-
print("small")
|
|
218
|
+
const output = executeCode(`
|
|
219
|
+
x = 10
|
|
220
|
+
if x > 5:
|
|
221
|
+
print("big")
|
|
222
|
+
else:
|
|
223
|
+
print("small")
|
|
224
224
|
`);
|
|
225
225
|
expect(output).toContain("big");
|
|
226
226
|
});
|
|
227
227
|
// TODO: Fix parser bug where function calls inside for loop body are not parsed correctly
|
|
228
228
|
test.skip("should execute for loops", () => {
|
|
229
|
-
const output = executeCode(`
|
|
230
|
-
for i in range(3):
|
|
231
|
-
print(i)
|
|
229
|
+
const output = executeCode(`
|
|
230
|
+
for i in range(3):
|
|
231
|
+
print(i)
|
|
232
232
|
`);
|
|
233
233
|
expect(output).toEqual(["0", "1", "2"]);
|
|
234
234
|
});
|
|
235
235
|
test.skip("should execute while loops", () => {
|
|
236
|
-
const output = executeCode(`
|
|
237
|
-
x = 0
|
|
238
|
-
while x < 3:
|
|
239
|
-
print(x)
|
|
240
|
-
x = x + 1
|
|
236
|
+
const output = executeCode(`
|
|
237
|
+
x = 0
|
|
238
|
+
while x < 3:
|
|
239
|
+
print(x)
|
|
240
|
+
x = x + 1
|
|
241
241
|
`);
|
|
242
242
|
expect(output).toEqual(["0", "1", "2"]);
|
|
243
243
|
});
|
|
@@ -245,35 +245,35 @@ while x < 3:
|
|
|
245
245
|
describe("Complex Programs", () => {
|
|
246
246
|
// TODO: Fix parser bug where recursive function calls are not parsed correctly
|
|
247
247
|
test.skip("should calculate fibonacci", () => {
|
|
248
|
-
const output = executeCode(`
|
|
249
|
-
def fib(n):
|
|
250
|
-
if n <= 1:
|
|
251
|
-
return n
|
|
252
|
-
return fib(n - 1) + fib(n - 2)
|
|
253
|
-
|
|
254
|
-
result = fib(10)
|
|
255
|
-
print(result)
|
|
248
|
+
const output = executeCode(`
|
|
249
|
+
def fib(n):
|
|
250
|
+
if n <= 1:
|
|
251
|
+
return n
|
|
252
|
+
return fib(n - 1) + fib(n - 2)
|
|
253
|
+
|
|
254
|
+
result = fib(10)
|
|
255
|
+
print(result)
|
|
256
256
|
`);
|
|
257
257
|
expect(output).toContain("55");
|
|
258
258
|
});
|
|
259
259
|
test("should filter even numbers", () => {
|
|
260
|
-
const output = executeCode(`
|
|
261
|
-
numbers = range(10)
|
|
262
|
-
evens = [x for x in numbers if x % 2 == 0]
|
|
263
|
-
print(evens)
|
|
260
|
+
const output = executeCode(`
|
|
261
|
+
numbers = range(10)
|
|
262
|
+
evens = [x for x in numbers if x % 2 == 0]
|
|
263
|
+
print(evens)
|
|
264
264
|
`);
|
|
265
265
|
expect(output[0]).toContain("0");
|
|
266
266
|
expect(output[0]).toContain("8");
|
|
267
267
|
});
|
|
268
268
|
test.skip("should combine multiple operations", () => {
|
|
269
|
-
const output = executeCode(`
|
|
270
|
-
def square(x):
|
|
271
|
-
return x * x
|
|
272
|
-
|
|
273
|
-
numbers = range(1, 6)
|
|
274
|
-
squares = [square(x) for x in numbers]
|
|
275
|
-
total = sum(squares)
|
|
276
|
-
print(total)
|
|
269
|
+
const output = executeCode(`
|
|
270
|
+
def square(x):
|
|
271
|
+
return x * x
|
|
272
|
+
|
|
273
|
+
numbers = range(1, 6)
|
|
274
|
+
squares = [square(x) for x in numbers]
|
|
275
|
+
total = sum(squares)
|
|
276
|
+
print(total)
|
|
277
277
|
`);
|
|
278
278
|
expect(output).toContain("55");
|
|
279
279
|
});
|
package/package.json
CHANGED
|
@@ -1,83 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "jpsx",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Just Python Script (JPS) - A Python-like language that compiles to JavaScript",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"compiler",
|
|
7
|
-
"python",
|
|
8
|
-
"javascript",
|
|
9
|
-
"jps",
|
|
10
|
-
"jpsx",
|
|
11
|
-
"react",
|
|
12
|
-
"vue",
|
|
13
|
-
"svelte",
|
|
14
|
-
"angular",
|
|
15
|
-
"nextjs",
|
|
16
|
-
"nuxtjs",
|
|
17
|
-
"sveltekit",
|
|
18
|
-
"remix",
|
|
19
|
-
"astro",
|
|
20
|
-
"solidjs",
|
|
21
|
-
"qwik",
|
|
22
|
-
"bun",
|
|
23
|
-
"deno",
|
|
24
|
-
"node",
|
|
25
|
-
"react",
|
|
26
|
-
"vue",
|
|
27
|
-
"svelte",
|
|
28
|
-
"angular",
|
|
29
|
-
"nextjs",
|
|
30
|
-
"nuxtjs",
|
|
31
|
-
"sveltekit",
|
|
32
|
-
"remix",
|
|
33
|
-
"astro",
|
|
34
|
-
"solidjs",
|
|
35
|
-
"qwik",
|
|
36
|
-
"bun",
|
|
37
|
-
"deno",
|
|
38
|
-
"node"
|
|
39
|
-
],
|
|
40
|
-
"author": "Loaii abdalslam",
|
|
41
|
-
"license": "ISC",
|
|
42
|
-
"files": [
|
|
43
|
-
"dist"
|
|
44
|
-
],
|
|
45
|
-
"bin": {
|
|
46
|
-
"jps": "./dist/cli/index.js"
|
|
47
|
-
},
|
|
48
|
-
"main": "./dist/api/index.js",
|
|
49
|
-
"types": "./dist/api/index.d.ts",
|
|
50
|
-
"exports": {
|
|
51
|
-
".": {
|
|
52
|
-
"types": "./dist/api/index.d.ts",
|
|
53
|
-
"import": "./dist/api/index.js",
|
|
54
|
-
"require": "./dist/api/index.cjs"
|
|
55
|
-
},
|
|
56
|
-
"./cli": "./dist/cli/index.js",
|
|
57
|
-
"./runtime": "./dist/runtime/index.js",
|
|
58
|
-
"./package.json": "./package.json"
|
|
59
|
-
},
|
|
60
|
-
"private": false,
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"@types/
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "jpsx",
|
|
3
|
+
"version": "0.1.19",
|
|
4
|
+
"description": "Just Python Script (JPS) - A Python-like language that compiles to JavaScript",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"compiler",
|
|
7
|
+
"python",
|
|
8
|
+
"javascript",
|
|
9
|
+
"jps",
|
|
10
|
+
"jpsx",
|
|
11
|
+
"react",
|
|
12
|
+
"vue",
|
|
13
|
+
"svelte",
|
|
14
|
+
"angular",
|
|
15
|
+
"nextjs",
|
|
16
|
+
"nuxtjs",
|
|
17
|
+
"sveltekit",
|
|
18
|
+
"remix",
|
|
19
|
+
"astro",
|
|
20
|
+
"solidjs",
|
|
21
|
+
"qwik",
|
|
22
|
+
"bun",
|
|
23
|
+
"deno",
|
|
24
|
+
"node",
|
|
25
|
+
"react",
|
|
26
|
+
"vue",
|
|
27
|
+
"svelte",
|
|
28
|
+
"angular",
|
|
29
|
+
"nextjs",
|
|
30
|
+
"nuxtjs",
|
|
31
|
+
"sveltekit",
|
|
32
|
+
"remix",
|
|
33
|
+
"astro",
|
|
34
|
+
"solidjs",
|
|
35
|
+
"qwik",
|
|
36
|
+
"bun",
|
|
37
|
+
"deno",
|
|
38
|
+
"node"
|
|
39
|
+
],
|
|
40
|
+
"author": "Loaii abdalslam",
|
|
41
|
+
"license": "ISC",
|
|
42
|
+
"files": [
|
|
43
|
+
"dist"
|
|
44
|
+
],
|
|
45
|
+
"bin": {
|
|
46
|
+
"jps": "./dist/cli/index.js"
|
|
47
|
+
},
|
|
48
|
+
"main": "./dist/api/index.js",
|
|
49
|
+
"types": "./dist/api/index.d.ts",
|
|
50
|
+
"exports": {
|
|
51
|
+
".": {
|
|
52
|
+
"types": "./dist/api/index.d.ts",
|
|
53
|
+
"import": "./dist/api/index.js",
|
|
54
|
+
"require": "./dist/api/index.cjs"
|
|
55
|
+
},
|
|
56
|
+
"./cli": "./dist/cli/index.js",
|
|
57
|
+
"./runtime": "./dist/runtime/index.js",
|
|
58
|
+
"./package.json": "./package.json"
|
|
59
|
+
},
|
|
60
|
+
"private": false,
|
|
61
|
+
"workspaces": [
|
|
62
|
+
"packages/*"
|
|
63
|
+
],
|
|
64
|
+
"type": "module",
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsc -p tsconfig.json",
|
|
67
|
+
"start": "node dist/cli/index.js",
|
|
68
|
+
"test": "jest"
|
|
69
|
+
},
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"chalk": "^5.6.2",
|
|
72
|
+
"commander": "^14.0.2",
|
|
73
|
+
"moo": "^0.5.2",
|
|
74
|
+
"nearley": "^2.20.1"
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@types/jest": "^29.5.12",
|
|
78
|
+
"@types/moo": "^0.5.10",
|
|
79
|
+
"@types/nearley": "^2.11.5",
|
|
80
|
+
"@types/node": "^22.19.7",
|
|
81
|
+
"jest": "^29.7.0",
|
|
82
|
+
"ts-jest": "^29.1.2",
|
|
83
|
+
"ts-node": "^10.9.2",
|
|
84
|
+
"typescript": "^5.3.3"
|
|
85
|
+
}
|
|
83
86
|
}
|