Skip to content

Commit d2f3219

Browse files
committed
Documentation
1 parent 5f0efd0 commit d2f3219

22 files changed

+1870
-125
lines changed

Makefile

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ else
77
LIB_PATH = lib/:lib/
88
endif
99

10-
all: parser libs exe
10+
all: parser libs exe docs
1111

1212
parser:
1313
"$(MAKE)" parser -C src
@@ -18,7 +18,12 @@ libs:
1818
exe:
1919
"$(PYTHON)" -m PyInstaller --hidden-import=decorator --add-data "$(LIB_PATH)" pyxell.py --noconfirm
2020

21+
.PHONY: docs
22+
docs:
23+
"$(MAKE)" docs -C docs
24+
2125
clean:
2226
"$(MAKE)" clean -C src
2327
rm -f lib/*.ll lib/*.json
2428
rm -rf build/ dist/
29+
"$(MAKE)" clean -C docs

README.md

+31-91
Original file line numberDiff line numberDiff line change
@@ -4,89 +4,24 @@ Pyxell
44
### Clean and easy-to-use multi-paradigm programming language with static typing. ###
55

66

7+
Documentation
8+
-------------
9+
10+
https://www.pyxell.org/docs/
11+
12+
713
Motivation
814
----------
915

10-
The project aims to combine the best features of different programming languages,
16+
Pyxell [_pixel_] aims to combine the best features of different programming languages,
1117
pack them into a clean and consistent syntax,
1218
and provide the execution speed of native machine code.
1319

1420
It draws mainly from Python, C++, C#, and Haskell,
15-
and tries to avoid common design flaws that have been nicely described
21+
trying to avoid common design flaws that have been nicely described
1622
[in this blog post](https://eev.ee/blog/2016/12/01/lets-stop-copying-c/).
1723

1824

19-
Examples
20-
--------
21-
22-
Rational numbers:
23-
24-
```
25-
print 1/10 + 5^-1 # 3/10
26-
```
27-
28-
Range literals, for-loops, string interpolation:
29-
30-
```
31-
a = ['A'..'Z']
32-
for x, i in a, 0... by 5 do
33-
print "a[{i}] = {x}"
34-
```
35-
36-
Dynamic containers:
37-
38-
```
39-
[Int] a = [1] # array (Python's list / C++'s vector)
40-
a.push(2)
41-
42-
{Float} b = {3.0} # hash set
43-
b.add(4.0)
44-
45-
{Char:String} c = {'5': "6"} # dictionary (hash map)
46-
c['7'] = "8"
47-
```
48-
49-
Generic functions, lambda expressions:
50-
51-
```
52-
func fold<A,B>([A] a, A->B->B f, B r) B def
53-
for x in a do
54-
r = f(x, r)
55-
return r
56-
57-
print fold([2, 3, 4], _*_, 1) # 24
58-
59-
-- There are built-in methods like this:
60-
print [0..10 by 2].reduce(_+_) # 30
61-
```
62-
63-
Generators, tuples, spread syntax:
64-
65-
```
66-
fib = lambda* n def
67-
if n <= 0 do
68-
return
69-
a, b = 0, 1
70-
yield a
71-
for _ in 2..n do
72-
yield b
73-
a, b = b, a+b
74-
75-
print [...fib(10)]
76-
```
77-
78-
Classes, nullable types:
79-
80-
```
81-
class C def
82-
String? s: null
83-
84-
c = C()
85-
print c.s?.length
86-
print c.s ?? "---"
87-
```
88-
89-
9025
Features
9126
--------
9227

@@ -115,12 +50,14 @@ Features
11550
To do:
11651

11752
* Exception handling
118-
* Unicode
53+
* Static class fields and methods
54+
* Complex numbers
55+
* Unicode support
56+
* Module system
57+
* Multiple inheritance
11958
* Generic classes
12059
* Operator overloading
121-
* Multiple inheritance
122-
* Concurrency
123-
* Module system
60+
* Asynchronous programming
12461

12562

12663
Requirements
@@ -134,8 +71,10 @@ python -m pip install -r requirements.txt
13471

13572
* C++17 compiler: Clang 5+ or GCC 7+.
13673

137-
Note that generators are currently supported only in Clang, since they are based on C++'s coroutines
138-
(GCC 10 also supports coroutines, but as of version 10.1 the implementation is buggy, so it is not yet supported by Pyxell).
74+
Note that generators are currently available only with Clang, since they are based on C++'s coroutines.
75+
Though GCC 10 also supports coroutines, as of version 10.2 the implementation is buggy
76+
(see [here](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95591) or [here](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95823)),
77+
so it is not yet supported by Pyxell.
13978

14079

14180
Usage
@@ -145,28 +84,29 @@ Usage
14584
python pyxell.py program.px
14685
```
14786

148-
If the program is correct, `program.cpp` file and `program.exe` executable will be created in the same folder,
87+
If the program is valid, `program.cpp` file and `program.exe` executable will be created in the same folder,
14988
and it will be automatically executed (unless you add `-n` option).
15089
Otherwise, errors will be displayed, pointing to the erroneous code location.
15190

15291
By default, `clang` command is used to compile the code.
15392
You can pick a different compiler using `-c` option.
15493

155-
Use `-s` to skip the compilation step and obtain transpiled C++ code with all headers included,
156-
ready for manual compilation (with -std=c++17 option, and with -fcoroutines-ts in the case of Clang).
157-
15894
The executable is not optimized by default.
15995
You can set the optimization level with `-O` option, e.g. `-O2`.
16096
This will make the program run faster, but also make the compilation slower.
16197

98+
Use `-s` to skip the compilation step and obtain transpiled C++ code with all headers included,
99+
ready for manual compilation (with `-std=c++17` option, and with `-fcoroutines-ts` in the case of Clang).
100+
162101
To see all options, use `-h`.
163102

164103

165104
PyInstaller
166105
-----------
167106

168-
You can build a standalone application using `PyInstaller`. Install it using `pip`, then run `make exe`.
169-
An executable `pyxell.exe` (not requiring Python to run) will be created in the `dist/pyxell` folder.
107+
You can build a standalone compiler application using `PyInstaller`.
108+
Install `PyInstaller` with `pip`, then run `make exe`.
109+
An executable (not requiring Python to run) will be created in the `dist/pyxell` folder.
170110

171111

172112
Development
@@ -180,19 +120,22 @@ then run `make parser`.
180120
After changing the code of Pyxell libraries (`lib/*.px` files),
181121
run `make libs` to rebuild them.
182122

123+
To build the documentation, go to the `docs` folder, run `npm install`, then `make`.
124+
To start a documentation server locally, install `flask` and run `server.py` in the same folder.
125+
183126

184127
Tests
185128
-----
186129

187130
```
188-
python test.py [-v]
131+
python test.py
189132
```
190133

191134
Tests are divided into good (supposed to compile and run properly) and bad (should throw compilation errors).
192135

193-
By default, the whole C++ code for correct tests is merged, so that only one file is compiled,
136+
By default, the whole C++ code for valid tests is merged, so that only one file is compiled,
194137
which is faster than compiling hundreds of files individually, even using multiple threads.
195-
Total execution time should be around 30-60 seconds.
138+
Total execution time (with default settings) should be around 30-60 seconds.
196139

197140
If, however, the script fails with an error like this: `too many sections` / `file too big`
198141
(seen with GCC 7.2 on Windows), or there is another compilation error that is hard to decipher,
@@ -202,9 +145,6 @@ You can pass a path pattern to run only selected tests (e.g. `python test.py arr
202145

203146
To see all options, run the script with `-h`.
204147

205-
Tests serve currently also as a documentation of the language.
206-
You can browse them to learn the syntax and semantics.
207-
208148

209149
Alternatives
210150
------------

docs/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
package-lock.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
2+
<template>
3+
<div>
4+
<VueCodemirror v-model="code" ref="code" :options="options" />
5+
<label title="Standard input for your program.">
6+
<input v-model="show_input" type="checkbox" />
7+
Input
8+
</label>
9+
<label style="padding-left: 6px" title="Will make the compilation slower, but the program may run faster.">
10+
<input v-model="optimization" type="checkbox" />
11+
Optimizations
12+
</label>
13+
<div class="input" :style="{ 'max-height': show_input ? INPUT_HEIGHT : 0 }">
14+
<VueCodemirror v-model="input" ref="input" :options="{ mode: null, theme: THEME }" />
15+
</div>
16+
<div style="text-align: right">
17+
<button :disabled="running" class="run" @click="run">
18+
<span v-if="running" class="spin">
19+
&#x25e0;
20+
</span>
21+
<span v-else>
22+
&#x25B6;
23+
</span>
24+
Run
25+
</button>
26+
</div>
27+
<pre class="language-output" :style="{ color: error ? 'red' : 'inherit' }">{{ output }}</pre>
28+
</div>
29+
</template>
30+
31+
<script>
32+
import axios from 'axios';
33+
import VueCodemirror from 'vue-codemirror/src/codemirror.vue';
34+
import { CodeMirror } from 'vue-codemirror';
35+
import 'codemirror/lib/codemirror.css';
36+
import 'codemirror/theme/dracula.css';
37+
import 'codemirror/addon/mode/simple.js';
38+
39+
import syntax from '../utils/pyxell-syntax.js';
40+
41+
CodeMirror.defineSimpleMode('pyxell', {
42+
start: [
43+
{ token: 'comment', regex: /#.*/ },
44+
{ token: 'comment', regex: /{#/, next: 'comment' },
45+
{ token: 'variable', regex: /\bprint\b/ },
46+
{ token: 'atom', regex: syntax.atom },
47+
{ token: 'keyword', regex: syntax.keyword },
48+
{ token: 'variable-2', regex: syntax.variable_name },
49+
{ token: 'variable-3', regex: syntax.type_name },
50+
{ token: 'number', regex: syntax.number },
51+
{ token: 'string', regex: syntax.string },
52+
],
53+
comment: [
54+
{ token: 'comment', regex: /.*?#}/, next: 'start' },
55+
{ token: 'comment', regex: /.*/ },
56+
],
57+
});
58+
59+
export default {
60+
components: { VueCodemirror },
61+
data: () => ({
62+
CODE_HEIGHT: '450px',
63+
INPUT_HEIGHT: '120px',
64+
THEME: 'dracula',
65+
66+
code: '',
67+
input: '',
68+
show_input: false,
69+
optimization: false,
70+
running: false,
71+
error: false,
72+
output: '',
73+
}),
74+
computed: {
75+
options() {
76+
return {
77+
mode: 'pyxell',
78+
theme: this.THEME,
79+
lineNumbers: true,
80+
indentUnit: 4,
81+
extraKeys: {
82+
'Tab': cm => {
83+
if (cm.getMode().name === 'null') {
84+
cm.execCommand('insertTab');
85+
} else {
86+
if (cm.somethingSelected()) {
87+
cm.execCommand('indentMore');
88+
} else {
89+
cm.execCommand('insertSoftTab');
90+
}
91+
}
92+
},
93+
'Shift-Tab': cm => {
94+
cm.execCommand('indentLess');
95+
},
96+
},
97+
};
98+
},
99+
},
100+
methods: {
101+
async run() {
102+
localStorage.setItem('code', this.code);
103+
this.output = '';
104+
this.running = true;
105+
106+
let response = await axios.post('/transpile/', {
107+
code: this.code,
108+
});
109+
if (response.data.error) {
110+
this.error = true;
111+
this.output = response.data.error;
112+
} else {
113+
const params = {
114+
'LanguageChoice': 27, // C++ (clang)
115+
'Program': response.data.cpp_code,
116+
'Input': this.input,
117+
'CompilerArgs': '-std=c++17 -fcoroutines-ts -o a.out source_file.cpp' +
118+
(this.optimization ? ' -O2' : ''),
119+
};
120+
const form_data = new FormData();
121+
for (const [name, value] of Object.entries(params)) {
122+
form_data.set(name, value);
123+
}
124+
response = await axios.post('https://rextester.com/rundotnet/api/', form_data);
125+
this.error = !!response.data.Errors;
126+
this.output = response.data.Errors || response.data.Result;
127+
}
128+
this.running = false;
129+
},
130+
},
131+
created() {
132+
this.code = localStorage.getItem('code') || '\nprint "Hello, world!"\n';
133+
},
134+
mounted() {
135+
this.$refs.code.codemirror.setSize('auto', this.CODE_HEIGHT);
136+
this.$refs.input.codemirror.setSize('auto', this.INPUT_HEIGHT);
137+
},
138+
};
139+
</script>
140+
141+
<style lang="stylus">
142+
.CodeMirror
143+
border: 1px solid #eee
144+
box-sizing: border-box
145+
146+
div.input
147+
overflow: hidden
148+
transition: max-height 0.4s
149+
150+
button.run
151+
background-color: $accentColor
152+
border: none
153+
border-radius: 5px
154+
color: white
155+
font-size: 1.2em
156+
padding: 5px 25px
157+
158+
&:not(:disabled)
159+
cursor: pointer
160+
161+
.spin
162+
animation: spin 1s linear infinite
163+
display: inline-block
164+
165+
@keyframes spin
166+
from
167+
transform: rotate(0deg)
168+
to
169+
transform: rotate(360deg)
170+
</style>

0 commit comments

Comments
 (0)