5 Commits

Author SHA1 Message Date
Bartłomiej Pluta
a1bc422fba Fix accessing properties and methods in identifiers with EQUAL 2019-07-10 16:25:06 +02:00
Bartłomiej Pluta
98d710ac97 Add equal ('==') operator to strings 2019-07-10 16:02:39 +02:00
Bartłomiej Pluta
d6fb101337 Add equal ('==') operator to both identifiers and bools 2019-07-10 15:58:37 +02:00
Bartłomiej Pluta
e008be7952 Do some refactor with multiple left associative operators 2019-07-10 15:26:35 +02:00
Bartłomiej Pluta
0a7d29d4a1 Working proof of concept of multiple left associative operators 2019-07-10 15:02:17 +02:00
166 changed files with 1457 additions and 7206 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,3 @@
__pycache__/
*.mus
.idea/*
venv/
SMNP.egg-info

15
Pipfile
View File

@@ -1,15 +0,0 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
sounddevice = "*"
soundfile = "*"
numpy = "*"
matplotlib = "*"
[requires]
python_version = "3.7"

180
Pipfile.lock generated
View File

@@ -1,180 +0,0 @@
{
"_meta": {
"hash": {
"sha256": "92b0c636f6ac9be9b32aa25b1cdc96dcbe85602d5c68a2084dc39d25392540b6"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.7"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"cffi": {
"hashes": [
"sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
"sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
"sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
"sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
"sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
"sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
"sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
"sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
"sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
"sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
"sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
"sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
"sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
"sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
"sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
"sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
"sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
"sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
"sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
"sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
"sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
"sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
"sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
"sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
"sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
"sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
"sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
"sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
],
"version": "==1.12.3"
},
"cycler": {
"hashes": [
"sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d",
"sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8"
],
"version": "==0.10.0"
},
"kiwisolver": {
"hashes": [
"sha256:05b5b061e09f60f56244adc885c4a7867da25ca387376b02c1efc29cc16bcd0f",
"sha256:26f4fbd6f5e1dabff70a9ba0d2c4bd30761086454aa30dddc5b52764ee4852b7",
"sha256:3b2378ad387f49cbb328205bda569b9f87288d6bc1bf4cd683c34523a2341efe",
"sha256:400599c0fe58d21522cae0e8b22318e09d9729451b17ee61ba8e1e7c0346565c",
"sha256:47b8cb81a7d18dbaf4fed6a61c3cecdb5adec7b4ac292bddb0d016d57e8507d5",
"sha256:53eaed412477c836e1b9522c19858a8557d6e595077830146182225613b11a75",
"sha256:58e626e1f7dfbb620d08d457325a4cdac65d1809680009f46bf41eaf74ad0187",
"sha256:5a52e1b006bfa5be04fe4debbcdd2688432a9af4b207a3f429c74ad625022641",
"sha256:5c7ca4e449ac9f99b3b9d4693debb1d6d237d1542dd6a56b3305fe8a9620f883",
"sha256:682e54f0ce8f45981878756d7203fd01e188cc6c8b2c5e2cf03675390b4534d5",
"sha256:79bfb2f0bd7cbf9ea256612c9523367e5ec51d7cd616ae20ca2c90f575d839a2",
"sha256:7f4dd50874177d2bb060d74769210f3bce1af87a8c7cf5b37d032ebf94f0aca3",
"sha256:8944a16020c07b682df861207b7e0efcd2f46c7488619cb55f65882279119389",
"sha256:8aa7009437640beb2768bfd06da049bad0df85f47ff18426261acecd1cf00897",
"sha256:939f36f21a8c571686eb491acfffa9c7f1ac345087281b412d63ea39ca14ec4a",
"sha256:9733b7f64bd9f807832d673355f79703f81f0b3e52bfce420fc00d8cb28c6a6c",
"sha256:a02f6c3e229d0b7220bd74600e9351e18bc0c361b05f29adae0d10599ae0e326",
"sha256:a0c0a9f06872330d0dd31b45607197caab3c22777600e88031bfe66799e70bb0",
"sha256:acc4df99308111585121db217681f1ce0eecb48d3a828a2f9bbf9773f4937e9e",
"sha256:b64916959e4ae0ac78af7c3e8cef4becee0c0e9694ad477b4c6b3a536de6a544",
"sha256:d3fcf0819dc3fea58be1fd1ca390851bdb719a549850e708ed858503ff25d995",
"sha256:d52e3b1868a4e8fd18b5cb15055c76820df514e26aa84cc02f593d99fef6707f",
"sha256:db1a5d3cc4ae943d674718d6c47d2d82488ddd94b93b9e12d24aabdbfe48caee",
"sha256:e3a21a720791712ed721c7b95d433e036134de6f18c77dbe96119eaf7aa08004",
"sha256:e8bf074363ce2babeb4764d94f8e65efd22e6a7c74860a4f05a6947afc020ff2",
"sha256:f16814a4a96dc04bf1da7d53ee8d5b1d6decfc1a92a63349bb15d37b6a263dd9",
"sha256:f2b22153870ca5cf2ab9c940d7bc38e8e9089fa0f7e5856ea195e1cf4ff43d5a",
"sha256:f790f8b3dff3d53453de6a7b7ddd173d2e020fb160baff578d578065b108a05f"
],
"version": "==1.1.0"
},
"matplotlib": {
"hashes": [
"sha256:1febd22afe1489b13c6749ea059d392c03261b2950d1d45c17e3aed812080c93",
"sha256:31a30d03f39528c79f3a592857be62a08595dec4ac034978ecd0f814fa0eec2d",
"sha256:4442ce720907f67a79d45de9ada47be81ce17e6c2f448b3c64765af93f6829c9",
"sha256:796edbd1182cbffa7e1e7a97f1e141f875a8501ba8dd834269ae3cd45a8c976f",
"sha256:934e6243df7165aad097572abf5b6003c77c9b6c480c3c4de6f2ef1b5fdd4ec0",
"sha256:bab9d848dbf1517bc58d1f486772e99919b19efef5dd8596d4b26f9f5ee08b6b",
"sha256:c1fe1e6cdaa53f11f088b7470c2056c0df7d80ee4858dadf6cbe433fcba4323b",
"sha256:e5b8aeca9276a3a988caebe9f08366ed519fff98f77c6df5b64d7603d0e42e36",
"sha256:ec6bd0a6a58df3628ff269978f4a4b924a0d371ad8ce1f8e2b635b99e482877a"
],
"index": "pypi",
"version": "==3.1.1"
},
"numpy": {
"hashes": [
"sha256:05dbfe72684cc14b92568de1bc1f41e5f62b00f714afc9adee42f6311738091f",
"sha256:0d82cb7271a577529d07bbb05cb58675f2deb09772175fab96dc8de025d8ac05",
"sha256:10132aa1fef99adc85a905d82e8497a580f83739837d7cbd234649f2e9b9dc58",
"sha256:12322df2e21f033a60c80319c25011194cd2a21294cc66fee0908aeae2c27832",
"sha256:16f19b3aa775dddc9814e02a46b8e6ae6a54ed8cf143962b4e53f0471dbd7b16",
"sha256:3d0b0989dd2d066db006158de7220802899a1e5c8cf622abe2d0bd158fd01c2c",
"sha256:438a3f0e7b681642898fd7993d38e2bf140a2d1eafaf3e89bb626db7f50db355",
"sha256:5fd214f482ab53f2cea57414c5fb3e58895b17df6e6f5bca5be6a0bb6aea23bb",
"sha256:73615d3edc84dd7c4aeb212fa3748fb83217e00d201875a47327f55363cef2df",
"sha256:7bd355ad7496f4ce1d235e9814ec81ee3d28308d591c067ce92e49f745ba2c2f",
"sha256:7d077f2976b8f3de08a0dcf5d72083f4af5411e8fddacd662aae27baa2601196",
"sha256:a4092682778dc48093e8bda8d26ee8360153e2047826f95a3f5eae09f0ae3abf",
"sha256:b458de8624c9f6034af492372eb2fee41a8e605f03f4732f43fc099e227858b2",
"sha256:e70fc8ff03a961f13363c2c95ef8285e0cf6a720f8271836f852cc0fa64e97c8",
"sha256:ee8e9d7cad5fe6dde50ede0d2e978d81eafeaa6233fb0b8719f60214cf226578",
"sha256:f4a4f6aba148858a5a5d546a99280f71f5ee6ec8182a7d195af1a914195b21a2"
],
"index": "pypi",
"version": "==1.17.2"
},
"pycparser": {
"hashes": [
"sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
],
"version": "==2.19"
},
"pyparsing": {
"hashes": [
"sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80",
"sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4"
],
"version": "==2.4.2"
},
"python-dateutil": {
"hashes": [
"sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
"sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
],
"version": "==2.8.0"
},
"six": {
"hashes": [
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
],
"version": "==1.12.0"
},
"sounddevice": {
"hashes": [
"sha256:8d0571349f9a438a97f2c69da760f195cf5ddf2351072199cc1dfede4785a207",
"sha256:a0dda9dea9a5038ec0dafee4cdebd6d9a09086405d4833a7e3f6b18c109f89f3",
"sha256:a71cd3daabc8cb13e0ec9a29e7d4ba9b707386f3c81b3501b20f64209bcaece7",
"sha256:b038315e3497e01b1cb22630bc9b5025fcfad40e5ef7c125a9d565befa7220e0",
"sha256:c340d0a68945439571a13b287bd11b2d2884b61cd47cc5de8356d88221edf580"
],
"index": "pypi",
"version": "==0.3.13"
},
"soundfile": {
"hashes": [
"sha256:181393f8daac38bda997c4284b760bcd726dc0e847f620020d7bf2d3d538a985",
"sha256:3f90971bb1884575ada9a0731e878c91cc1ffde14a778f0857deaa2fd04849ac",
"sha256:637f6218c867b8cae80f6989634a0813b416b3e6132480d056e6e5a89a921571",
"sha256:7fe04272cbfb94ab648acb0db31ace0800f5a4cf46e9d45b4d71ddb15abce1a0",
"sha256:80a3d2ed37199ffa7066c097d7b82b8413922e22870b62b54dc264bf0169f4c2"
],
"index": "pypi",
"version": "==0.10.2"
}
},
"develop": {}
}

2372
README.md

File diff suppressed because it is too large Load Diff

1084
STDLIB.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +0,0 @@
println("Adeste Fideles");
println("John Francis Wade");
s1 = [@g, @g:2, @d, @g, @a:2, @d:2, @h, @a, @h, @c5, @h:2, @a, @g];
s2 = [@g:2, @f#, @e, @f#, @g, @a, @h, @f#:2, @e:4d, @d:8, @d:2d, 4];
s3 = [@d5:2, @c5, @h, @c5:2, @h:2, @a, @h, @g, @a, @f#:4d, @e:8, @d];
s4 = [@g, @g, @f#, @g, @a, @g:2, @d, @h, @h, @a, @h, @c5, @h:2, @a];
s5 = [@h, @c5, @h, @a, @g, @f#:2, @g, @c5, @h:2, @a:4d, @g:8, @g:1];
S = s1 + s2 + s3 + s4 + s5;
a1 = [@d, @d:2, @d, @d, @e:2, @d:2, @d, @d, @d, @e, @d:2, @d, @h3];
a2 = [@h3, @c#, @d, @c#, @d, @d, @d, @d, @d:2, @c#:4d, @d:8, @d:2d, 4];
a3 = [@d:2, @e:8, @f#:8, @g, @g, @f#, @g:2, @d, @d, @e, @e, @d:2, @d];
a4 = [@d, @d:1, @d:2d, @d, @d:1, @d:2d];
a5 = [@g, @f#, @g, @d, @d:8, @c#:8, @d:2, @d, @e, @d:2, @d:4d, @h3:8, @h3:1];
A = a1 + a2 + a3 + a4 + a5;
t1 = [@h3, @h3:2, @h3, @h3, @c:2, @a3:2, @g3, @a3, @g3, @g3, @g3:2, @f#3, @g3];
t2 = [@g3:2, @a3, @a3, @a3, @g3, @f#3, @d3, @a3:2, @g3:4d, @f#3:8, @f#3:2d, 4];
t3 = [@h3:2, @c, @d, @c:2, @d:2, @d, @g3, @h3, @c, @a3:2, @f#3];
t4 = [@h3, @h3, @a3, @h3, @c, @h3:2d, @g3, @g3, @f#3, @g3, @a3, @g3:2, @f#3];
t5 = [@d, @d, @d, @a3, @a3, @a3:2, @g3:2, @g3:2, @f#3:4d, @g3:8, @g3:1];
T = t1 + t2 + t3 + t4 + t5;
b1 = [@g3, @g3:2, @h3, @g3, @g3:2, @f#3:2, @g3, @f#3, @g3, @c3, @d3:2, @d3, @e3];
b2 = [@e3:2, @d3, @a2, @d3, @h2, @f#2, @g2, @a2:2, @a2:4d, @d3:8, @d2:2d, 4];
b3 = [@h3:2, @a3, @g3, @a3:2, @g3:2, @f#3, @g3, @e3, @c3, @d3:2, @d3];
b4 = [4, 1, 1, 1, 2, 4];
b5 = [@g3, @a3, @g3, @f#3, @e3, @d3, @c3, @h2, @c3, @d3:2, @d3:4d, @g2:8, @g2:1];
B = b1 + b2 + b3 + b4 + b5;
synth({ tuning -> 431, attack -> 100, decay -> 1.2, overtones -> [0.7, 0, 0.2, 0.1] }, S, A, T, B);

View File

@@ -1,198 +0,0 @@
println("Praeludium C Major");
println("Acht kleine Praeludien und Fugen");
println("Johann Sebastian Bach");
config = {
overtones -> flat([0.5, 0.3, 5^0.0, 0.1, 3^0.0, 0.05, 0.0, 0.03, 0.0, 0.0, 0.01, 5^0.0, 0.005, 3^0.0, 0.002, 0.0, 0.001]),
decay -> 2,
attack -> 0,
tuning -> 432
};
s1 = [16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @h:16, @c5:16, @e, 4];
s2 = [16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @h:16, @c5:16, @a:16, @f:16, @e:16, @f:16, @c:16, @f:16, @e:16, @f:16];
s3 = [@d:16, @d5:16, @c5:16, @d5:16, @a:16, @d5:16, @c5:16, @d5:16, @h:16, @g:16, @f#:16, @g:16, @d:16, @g:16, @f#:16, @g:16];
s4 = [@e:16, @e5:16, @d5:16, @e5:16, @h:16, @e5:16, @d5:16, @e5:16, @c5:16, @a:16, @g#:16, @a:16, @e:16, @a:16, @g#:16, @a:16];
s5 = flat(2 ^ [@c5, @f#, @e, @f#], 2 ^ [@h, @g, @f#, @g]) as n ^ n.withDuration(16);
s6 = flat(2 ^ [@h, @e, @d, @e], 2 ^ [@a, @f#, @e, @f#]) as n ^ n.withDuration(16);
s7 = flat(2 ^ [@a, @d, @c, @d], 2 ^ [@g, @e, @d, @e]) as n ^ n.withDuration(16);
s8 = flat(2 ^ [@g, @c#, @h3, @c#], 2 ^ [@f#, @d, @c#, @d]) as n ^ n.withDuration(16);
s9 = [@g, @f#, @g, @d, @a, @g, @a, @d, @h, @a, @h, @d, @c5, @h, @c5, @d] as n ^ n.withDuration(16);
s10 = [@d5:4d, @d5:8, @e5:16, @g5:16, @d5:16, @g5:16, @c5:16, @g5:16, @h:16, @g5:16];
s11 = [@a, 8, @h:8, @c5:16, @d5:16, @h:16, @c5:16, @a:8d, @g:16];
s12 = [@g, 4, 2];
S1 = s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12
#
a1 = [2, 16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @h:16, @c5:16];
a2 = [@g, 8, @c5:8, @c5, 4];
a3 = [@a, 8, @d5:8, @d5, 4];
a4 = [@h, 8, @e5:8, @e5, 4];
a5 = 8 ^ @d5:8;
a6 = 8 ^ @c5:8;
a7 = 8 ^ @h:8;
a8 = 8 ^ @a:8;
a9 = [@h, @a, @g, @a];
a10 = [@h:16, @d5:16, @e5:16, @f#5:16, @h5:8, @g5:8, @g5:2];
a11 = [@g5:8, @f#5:16, @e5:16, @f#5:8, @g5:8, @a5:8, @g5:8, @d5];
a12 = [@d5, 4, 2];
A1 = transpose(-12, a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12);
#
t1 = [1];
t2 = [@e, 8, @g:8, @a, 4];
t3 = [@f#, 8, @a:8, @h, 4];
t4 = [@g#, 8, @h:8, @c5, 4];
t5 = (4 ^ @a:8) + (4 ^ @h:8);
t6 = (4 ^ @g:8) + (4 ^ @a:8);
t7 = (4 ^ @f#:8) + (4 ^ @g:8);
t8 = (4 ^ @e:8) + (4 ^ @f#:8);
t9 = [@e, @f#, @g, @f#];
t10 = [@g, @g5:8, @h:8, @c5:8, @h:8, @a:8, @g:8];
t11 = [@d5, 8, @d5:8, @d5:8, @d5:8, @d5];
t12 = [@h, 4, 2];
T1 = transpose(-12, t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10 + t11 + t12);
#
b_ = 10 ^ 1;
b11 = [2, 8, @g3, @f#3:8];
b12 = [16, @g3:16, @f#3:16, @g3:16, @d3:16, @g3:16, @f#3:16, @g3:16, @g2, 4];
B1 = b_ + b11 + b12;
#
p1 = [@c:1];
p2 = [@c, 8, @e:8, @f, 4];
p3 = [@f#, 8, @f#:8, @g, 4];
p4 = [@g#, 8, @g#:8, @a, 4];
p5 = (4 ^ @d:8) + (4 ^ @g:8);
p6 = (4 ^ @c:8) + (4 ^ @f#:8);
p7 = (4 ^ @h3:8) + (4 ^ @e:8);
p8 = (4 ^ @a3:8) + (4 ^ @d:8);
p9 = [@d:1];
p10 = [@d, 4, 2];
p11 = [4, 8, @g:8, @f#:8, @g:8, @d];
p12 = [@g3, 4, 16, @g:16, @f:16, @g:16, @e:16, @g:16, @d:16, @g:16];
P1 = transpose(-12, p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12);
PART1 = wave(config, S1, A1, T1, B1, P1);
#######
s1 = [16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @h:16, @c5:16, @a, 4];
s2 = [16, @h:16, @a:16, @h:16, @f:16, @h:16, @a:16, @h:16, @g#, 4];
s3 = flat([2 ^ [@a, @e, @d, @e], 2 ^ [@g#, @d, @c, @d]]) as n ^ n.withDuration(16);
s4 = flat([2 ^ [@a, @e, @d, @e], 2 ^ [@h, @g#, @f#, @g#]]) as n ^ n.withDuration(16);
s5 = [@c5, @h, @c5, @d5, @h, @a, @h, @c5] as n ^ n.withDuration(8);
s6 = [@a:8, @g#:8, @a:8, @h:8, @g#:8, @e:8, @c5];
s7 = [@h:8, @a:8, @g#:8d, @a:16, @a, 4];
s8 = [16, @e5:16, @d5:16, @e5:16, @h:16, @e5:16, @d5:16, @e5:16, @c5, 4];
s9 = [16, @g5:16, @f5:16, @g5:16, @d5:16, @g5:16, @f5:16, @g5:16, @e5:16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @h:16, @c5:16];
s10 = [@e, 4, 16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @h:16, @c5:16];
s11 = flat(2 ^ [@a:16, @f:16, @e:16, @f:16], [16, @d5:16, @c5:16, @d5:16, @a:16, @d5:16, @c5:16, @d5:16]);
s12 = flat(2 ^ [@h:16, @g:16, @f#:16, @g:16], [16, @e5:16, @d5:16, @e5:16, @h:16, @e5:16, @d5:16, @e5:16]);
s13 = flat(2 ^ [@c5:16, @a:16, @g#:16, @a:16], [16, @g5:16, @f5:16, @g5:16, @d5:16, @g5:16, @f5:16, @g5:16]);
s14 = [@e, @g, @e, @g, @f, @a, @f, @a, @d, @f, @d, @f, @e, @g, @e, @g] as n ^ n.withDuration(16).withOctave(5);
s15 = [@c5:16, @e5:16, @c5:16, @e5:16, @d5:16, @f5:16, @d5:16, @f5:16, @h:16, @g:16, @a:16, @h:16, @c5];
s16a = [@c5, @h, @c5, 4];
s16b = [@c5, @h, @c5:2];
S2 = s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15;
#
a1 = [@g, 4, @f5, 4];
a2 = [@f, 4, @e5, 4];
a3 = flat(2 ^ [@c, @c5, @h, @c5], 2 ^ [@e, @e5, @d5, @e5]) as n ^ n.withDuration(16);
a4 = flat(2 ^ [@c, @c5, @h, @c5], 2 ^ [@e, @e5, @d5, @e5]) as n ^ n.withDuration(16);
a5 = [@a, @c5, @g#, @c5, @a, @c5, @f#, @d5, @g, @d5, @f#, @d5, @g, @d5, @e, @e5] as n ^ n.withDuration(16);
a6 = [@f:16, @c5:16, @e:16, @c5:16, @f:16, @c5:16, @d:16, @h:16, @h, 8, @a5:8];
a7 = [@f5, @e, @e, 4];
a8 = (4 ^ @e5:8) + [@e5, 4];
a9 = (4 ^ @d5:8) + [@c5, 4];
a10 = [16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @h:16, @c5:16, @c5, 8, @c5:8];
a11 = (4 ^ @c5:8) + [@d, 8, @d:8];
a12 = (4 ^ @d5:8) + [@e, 8, @e:8];
a13 = (4 ^ @e5:8) + [@g5, 8, @g5:8];
a14 = [@c, @e, @c, @e, @c, @f, @c, @f, @h3, @d, @h3, @d, @h3, @e, @h3, @e] as n ^ n.withDuration(16).withOctave(5);
a15 = [@a:16, @c5:16, @a:16, @c5:16, @a:16, @d5:16, @a:16, @d5:16, @g:2];
a16a = [@g:2, @c, 4];
a16b = [@g:2, @g:2];
A2 = transpose(-12, a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15);
#
t1 = [@e, 4, 16, @f:16, @e:16, @f:16, @c:16, @f:16, @e:16, @f:16];
t2 = [@d, 4, 16, @e:16, @d:16, @e:16, @h3:16, @e:16, @d:16, @e:16];
t3 = [1];
t4 = [1];
t5 = [1];
t6 = [2, @e, 8, @e5:8];
t7 = [2, 16, @a:16, @g#:16, @a:16, @e:16, @a:16, @g#:16, @a:16];
t8 = (4 ^ @h:8) + [16, @h:16, @g#:16, @a:16, @e:16, @a:16, @g#:16, @a:16];
t9 = (4 ^ @h:8) + [@g, 4];
t10 = [2, @g, 8, @g:8];
t11 = (4 ^ @a:8) + [@a, 8, @a:8];
t12 = (4 ^ @h:8) + [@h, 8, @h:8];
t13 = (4 ^ @c5:8) + [@d5, 8, @d5:8];
t14 = [1];
t15 = [2, @d5, 16, @e5:16, @d5:16, @c5:16];
t16a = [@g5:4d, @f:8, @g ,4];
t16b = [@g5:4d, @f:8, @e:2];
T2 = transpose(-12, t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10 + t11 + t12 + t13 + t14 + t15);
#
b_1 = 6 ^ 1;
b7 = [@d5:8, @c5:8, @h, @c5, 4];
b_2 = 8 ^ 1;
b16a = [@d:2, @e, 4];
b16b = [@d:2, @e:2];
B2 = transpose(-12, b_1 + b7 + b_2);
#
p1 = [@c, 4, @f, 4];
p2 = [@h3, 4, @e, 4];
p3 = [@c, 4, @h3, 4];
p4 = [@c, 4, @e, 4];
p5 = [@a, 4, 2];
p6 = [2, 4, 8, @a:8];
p7 = [@d, @e, @a3, 4];
p8 = (4 ^ @g#3:8) + [@a3, 4];
p9 = (4 ^ @h3:8) + [@c, 4];
p10 = [2, @c, 8, @e:8];
p11 = (4 ^ @f:8) + [@f#, 8, @f#:8];
p12 = (4 ^ @g:8) + [@g#, 8, @g#:8];
p13 = (4 ^ @a:8) + [@h, 8, @h:8];
p14 = [@c5, @a, @h, @g];
p15 = [@a, @f, @g:2];
p16a = [@g:2, 16, @c5:16, @h:16, @c5:16, @g:16, @c5:16, @e:16, @g:16];
p16b = [@g:2, @c:2];
P2 = transpose(-12, p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15);
PART2 = wave(config, S2, A2, T2, B2, P2);
PART2a = PART2 + wave(config, s16a, a16a, t16a, b16a, p16a);
PART2b = PART2 + wave(config, s16b, a16b, t16b, b16b, p16b);
MUSIC = PART1 + PART1 + PART2a + PART2b;
synth(MUSIC);

View File

@@ -1,42 +0,0 @@
println("Bohemian Rhapsody :: part");
println("by Queen");
m1 = [@d:8, @d:8, @d:2, 8, @b3:8, @c:8, @d:16, @d:16, @d, 4, 8, @d:16, @d:16];
m2 = [@eb:8, @f:8, @eb:8, @d:8, @c, @c:8, @d:8, @eb:16, @f:8, @eb:8d, @d:8, @c, 4, @d:8, @d:8, @d:2, @d:8, @f:8];
m3 = [@a:8d, @g:16, @g:2, 8, @g:8, @b:8, @b:8, @b:8, @b:8, @b:8d, @g:16, @d:8d, @c:16, @c:2, 2];
M1 = [1, 1] + m1 + m2 + m3;
p_B = [@d:8, @f3:8, @b3:8, @d:8, @g:8, @f3:8, @f:8, @f:8];
p_g = [@d:8, @g3:8, @b3:8, @d:8, @a:8, @g3:8, @g:8, @b3:8];
p_c = [@g:8, @c:8, @eb:8, @g:8, @d5:8, @c:8, @c5:8, @c:8];
p_cF = [@b:8, @c:8, @eb:8, @g:8, @a:8, @eb:8, @f:8, @c:8];
p1 = [@eb:8, @c:8, @eb:8, @g:8, @eb:8, @g:8, @eb:8, @g:8, @eb:8, @a3:8, @eb:8, @g:8, @eb:8, @g:8, @eb:8, @g:8];
P1 = p_B + p_B + p_B + p_g + p_c + p_cF + p_B + p_g + p1;
b1 = [@b3:1, @g3:1, @c3:1, @c3:2, @f3:2];
b2 = [@b3:2d, @a3, @g3:1, @c3:2, @h2, @b2, @a2:2, @ab2, @g2];
B1 = [@b3:1, @b3:1] + b1 + b2;
# Eb
m1 = [@g:16, @g:16, @g:2, 8, @f:8, @g:16, @ab:16, @g:2, 4, 8, @g:16, @g:16, @ab:8d, @g:16, @g:8, @f:16, @f:2, @b3:16];
m2 = [@b3:8, @f:8, @f:8, @g:16, @g:8d, @ab:8, @ab:8, @b:16, @ab:16, @ab:8, @g:8, 8, @f:16, @g:16, @b:4d, @f:16, @g:16];
m3 = [@eb:4d, @b3:16, @b3:16, @h3:8, @db:8, @h3:16, @db:16, @h3:8, @b3:2, 2];
M2 = m1 + m2 + m3;
p_Eb = [@b:8, @eb:8, @eb5:8, @eb:8, @b:8, @eb:8, @f:8, @b:8];
p_f = [@ab:8, @f:8, @ab:8, @ab:8, @ab:8, @eb:8, @ab:8, @d:8];
p_B = [@d, @f, @g, @ab];
p_EbB = [@b:8, @eb:8, @eb5:8, @eb:8, @b:8, @d:8, @b:8, @d:8];
p_cf = [@g:8, @c:8, @g:8, @c:8, @h3:2];
P2 = p_Eb + p_c + p_f + p_B + p_EbB + p_cf;
b1 = [@eb3:2d, @d3, @c3:1, @f3:4d, @e3:8, @eb3, @d3, @b2, @b2, @b2, @b2, @eb3:2, @d3:2];
b2 = [@c2:2, @f2:2, @eb2:2, 2];
B2 = b1 + b2;
M = M1 + M2;
P = P1 + P2;
B = B1 + B2;
synth({ tuning -> 432, bpm -> 72, overtones -> [0.5, 0.3, 0.15, 0.05], decay -> 0.8 }, transpose(12, M), P, B);

View File

@@ -1,45 +0,0 @@
extend list as array {
function withoutIndex(integer index) {
return array as (i, element) ^ element % i != index;
}
function push(integer index, value) {
return (index as i ^ array.get(i)) + [value] + ((array.size-index) as i ^ array.get(i+index));
}
function replace(integer index, value) {
return array
.withoutIndex(index)
.push(index, value);
}
function swap(integer a, integer b) {
A = array.get(a);
B = array.get(b);
return array
.replace(a, B)
.replace(b, A);
}
}
function bubbleSort(list<integer, float> numbers) {
sorted = numbers;
-(numbers.size as n ^ n) as i ^ {
i as j ^ {
if (sorted.get(j) > sorted.get(j+1)) {
sorted = sorted.swap(j, j+1);
}
}
}
return sorted;
}
min = 0;
max = 100;
size = 30;
randList = size ^ rand(min, max);
println(randList);
println(bubbleSort(randList));

View File

@@ -1,120 +0,0 @@
println("Star Wars :: Cantina Band");
println("by John Williams");
cb1 = [@a, @d5, @a, @d5] + [@a:8, @d5, @a:8, 8, @g#:8, @a];
cb2 = [@a:8, @g#:8, @a:8, @g:8, 8, @f#:8, @g:8, @gb:8];
cb3 = [@f:4d, @d:2, 8];
cb4 = [@g:8, 8, @g:4d, @f#:8, @g];
cb5 = [@c5:8, @b, @a, @g:4d];
cb6 = [@c5:8, 8, @c5:4d, @a:8, @g];
cb7 = [@f:4d, @d:2, 8];
cb8 = [@d:2, @f:2, @a:2, @c5:2];
cb9 = [@eb5, @d5, @g#:8, @a, @f:8];
CB1 = cb1 + cb2 + cb3 + cb1 + cb4 + cb5 + cb1 + cb6 + cb7 + cb8 + cb9 + [1];
cb11 = 2 ^ [8, @a5, @f5:8, @a5:8, 8, 4];
cb12 = [8, @a5, @f5:8, @g#5:8, @a5, @f5:8];
cb13 = [@f5:4d, @d5:2, 8];
cb14 = [8, @a5, @f5:8, @g#5:8, @a5, @g5:8];
cb15 = [@g5:2, @c5:2];
cb16 = [@b:8, @d5:8, @f5, @h:8, @d5:8, @f5];
cb17 = [@g#:8, @a5, @d5:2, 8];
cb18 = [@d:8, @f:8, @h:8, @d5:8, @g#:8, @a, @f:8];
cb19 = [@f:2d, 4];
CB2 = cb11 + cb12 + cb13 + cb11 + cb14 + cb15 + cb11 + cb12 + cb13 + cb16 + cb17 + cb18 + cb19;
cb20 = [@f, 8, @ab, @f:8, @g];
cb21 = [8, @f:8, @ab:8, @f:8, @g:8, @f:8, @ab:8, @d:8];
cb22 = [@f, 8, @ab, @f:8, @g];
cb23 = [@f:8, @f:8, @ab:8, @f:8, @g:8, @f:8, @ab:8, @f:8];
cb24 = [@g:8, @f:8, @ab:8, @f:8, @g:8, @f:8, @ab:8, @d:8];
cb25 = [@f:8, @f:8, @ab:8, @f:8, @ab:8, @f, @f:8, @f:2d, 4];
CB3 = cb20 + cb21 + cb22 + cb21 + cb22 + cb21 + cb23 + cb24 + cb22 + cb21 + cb22 + cb21 + cb22 + cb21 + cb25;
cb26 = [@c5, 8, @e5:8, 4, @g5];
cb27 = [@g5:8, @g5, @g5:8, @g5, @e5:8, @c5:8];
cb28 = [@f5, @f5:8, @f5:8, @f5:8, @g5, @a5:8, @a5:1];
cb29 = [@e5, @e5, @g5:8, @g5, @c5:8];
cb30 = [@c5:8, @e5, @c5:8, @e5, @g5];
cb31 = [@f5, @f5:8, @f5, @g5, @a5:8, @a5:1];
cb32 = [@b5, @b5, @d6, @b5:8, @db6:8];
cb33 = [@db6:8, @db6:8, @b5, @db6, @b5];
cb34 = [@f5, @f5, @f5:8, @ab5, @d6:8, @d6:1];
cb35 = [8, @b, @d5:8, @g5, @g5];
cb36 = [8, @e5, 8, @e5, @e5];
cb37 = [8, @f5, @f5:8, @f5, @f5:8, @f5:8];
cb38 = [@f5:8, @f5, @f5:8, @f5:8, @f5:8, @f5];
CB4 = cb26 + cb27 + cb28 + cb29 + cb30 + cb31 + cb32 + cb33 + cb34 + cb35 + cb36 + cb37 + cb38;
cb39 = [@ab:8, @gb:8, @ab:8, @gb:8, @ab:8, @gb:8, @ab:8, @gb:8];
cb40 = [@ab:8, @db5, @ab:8, @db5, @ab:8, @db5:8];
cb41 = [8, @ab:8, @b:8, @h:8, @c5:8, @h:8, @b:8, 8];
cb42 = [@ab:8, @db5, @ab:8, @db5, @ab:8, @a:8];
cb43 = [@b:8, @a:8, @b:4d, @a:8, @b:8, @a:8];
cb44 = [@b:8, @a:8, @b:8, @h:8, @c5:8, 8, @gb:8, @g:8];
cb45 = [@b:8, @a:8, @b:4d, @a:8, @b:8, @h:8];
cb46 = [@c5:8, @g:8, @e:8, @c:8, 8, @c:8, @db:8, @c:8];
cb47 = [@db:8, @b3, @db:8, @fb:8, @db, @fb:8];
cb48 = [@f:8, @e:8, @f:8, @gb:8, @g:8, @c, @g:8];
cb49 = [@ab:8, @g:8, @ab:8, @a:8, @b:8, @a:8, @b:8, @h:8];
cb50 = [@c5:8, @c5:8, 4, @c5:8, @c5:8, 4];
cb51 = [@c5, @e5:2, @f5:8, @db5:8];
cb52 = [@ab:8, @f:8, @fb:8, @eb:8, @d:8, 4, @gb:8];
cb53 = [@c5:8, @c5, @gb:8, @c5:8, @c5, @h:8];
cb54 = [@c5:8, @c5, @h:8, @c5:8, @c5, @c5:8];
cb55 = [@db5:8, @fb:8, @db5:4d, @fb:8, @db5:8, @fb:8];
cb56 = [@db5:8, @fb:8, @db5:8, @fb:8, @eb:8, @c5, @c5:8];
cb57 = [@db5:8, @fb:8, @db5:8, @fb:8, @eb:8, @c5, @h3:8];
cb58 = [@b3:8, @db:8, @gb:8, @b:8, @c:8, @e:8, @g:8, @c5:8];
cb59 = [@db5:8, @db, @c:8, @db, 4];
cb60 = [4, @a3, @b3, @a3, @b3, @a3, @gb3:8, @f3:8, @d3:8, 8];
cb61 = [8, @a3, @a3, @a3, @a3, @a3, @a3:8, @a3:8, @a3];
CB5 = cb39 + cb40 + cb41 + cb39 + cb42 + cb43 + cb44 + cb39 + cb42 + cb45 + cb46 + cb47 + cb48 + cb49 + cb50 + cb50 + cb51 + cb52 + cb53 + cb54 + cb55 + cb56 + cb55 + cb56 + cb55 + cb57 + cb58 + cb59 + cb60 + cb60 + cb60;
CB = CB1 + CB2 + CB3 + (2 ^ CB4) + CB5;
b1 = (3 ^ [@d3, 4, @a2, 4]) + [@f3, 4, @c3, 4, @d3, 4, @a2, 4, @d3, 4, @a2, 4, @g2, 4, @g2, 4];
b2 = [@c3, @d3, @d#3, @e3, @d3, 4, @a2, 4, @d3, 4, @a2, 4, @c3, 4, @c3, 4];
b3 = [@f3, 4, @c3, 4, @b2, 4, @b2, 4, @f3, 4, @d3, 4, @g3, 4, @c3, 4, @f3, @e3, @d3, @c3];
B1 = b1 + b2 + b3;
b4 = (3 ^ [@d3, 4, @a2, 4]) + [@d3:4d, @g#2:4d, @a2];
b5 = (3 ^ [@d3, 4, @a2, 4]) + [@eb3:2, @c3, @c3];
b6 = (4 ^ [@d3, 4, @a2, 4]);
b7 = [@b2:8, @b2:8, 4, @h2:8, @h2:8, 4, @c3:4d, @d3:8, 8, @d3:8, @d3, @g2, 4, @c3:4d, @f3:4d, @e3, @d3, @c3];
B2 = b4 + b5 + b6 + b7;
b8 = 3 ^ [@d3, @c3, @b2, @a2, @g2, @f2, @e2, @d2];
b9 = [@d3, 4, 2, 2, 4, @a2];
b10 = [@d3, @b2, @a2, @a2, @d3:8, 8, 4, 2];
B3 = b8 + b9 + b8 + b10;
b11 = [@c3, 4, @g2, 4, @c3, 8, @b2:4d, @g2, @f2, 4, @c3, 4, @f3, 8, @e3:4d, @d3];
b12 = [@c3, 4, @g3, 4, @c3, 8, @b2:4d, @g2, @f2, 4, @c3, 4, @d3, 8, @f#2:4d, @a2];
b13 = [@b2, 4, @b2, 4, @h2, 4, @h2, 4, @c3, 4, @c3, 4, @d3, 8, @d3:4d, @f#2];
b14 = [@g2, 4, @d3, 4, @c3, 8, @c3:4d, @g3, @f3, 4, @db3, 4, @f3, @f3, @e3, @d3];
B4 = b11 + b12 + b13 + b14;
b15 = [@db3, @c3, @b2, @ab2, @gb2, @f2, @eb2, @db2, @db3, @b2, @a2, @ab2];
b16 = [@db3, @c3, @b2, @ab2, @gb2, @f2, @eb2, @db2, @eb2, @e2, @f2, @gb2];
b17 = [@e2, @d2, @h2, @ab2, @h2, @ab2, @f2, @eb2, @db2, @c2, @b1, @ab1];
# ^ or B?
b18 = [@gb2, @gb2, @gb2, @db3, @c3, @c3, @e3, @g3, @gb3, @gb3, @g3, @g3];
b19 = [@ab3, @db3, @c3, @c3, @f3, @c3, @gb3, @gb3, @c3, 4, @c3, 4];
b20 = [@f3, 4, @f3, 4, @c3, @c3, 4, @db3:8, @f3:8, @ab3:8, @a3:8, @b3:8, @h3:8, @c:8, 8, 8, 16, @g3:16];
b21 = [@c3, 4, @c3, 4, @f3, 4, @f3, 4, @gb2, 4, @ab2, 4, @a2, 4, @db3, 4, @gb2, 4, @ab2, 4, @a2, 4, @db3, 4, @d, 4, @eb, 4];
b22 = [@e3, 4, @f3, 4, @gb3, 4, @g3, 4, @db3, 4, @db3, 4];
B5 = b15 + b16 + b17 + b18 + b19 + b20 + b21 + b22;
B = B1 + B2 + B3 + (2 ^ B4) + B5;
synth({ tuning -> 432, bpm -> 270 }, flat(CB), flat(B));

View File

@@ -1,31 +0,0 @@
println("Les Anges dans nos campagnes");
s = [@a, @a, @a, @c5, @c5:4d, @b:8, @a:2, @a, @g, @a, @c5, @a:4d, @g:8, @f:2];
sc = [@c5:2, @d5:8, @c5:8, @b:8, @a:8, @b:2, @c5:8, @b:8, @a:8, @g:8, @a:2, @b:8, @a:8, @g:8, @f:8, @g:4d, @c:8, @c:2, @f, @g, @a, @b];
sca = [@a:2, @g, 4];
scb = [@a:2, @g:2, @f:2d, 4];
S = flat(2^s, sc, sca, sc, scb);
a = [@f, @f, @e, @e, @g, @e, @f:2, @f, @e, @f, @f, @f, @e, @f:2];
ac = [@f, @a:8, @g:8, @f:2d, @g:8, @f:8, @e:2d, @f:8, @e:8, @d:2, @c:4d, @c:8, @c:2, @c, @e, @f, @g];
aca = [@f:2, @e, 4];
acb = [@f:2, @e:2, @c:2d, 4];
A = flat(2^a, ac, aca, ac, acb);
t = [@c, @c, @c, @c, @d, @c, @c:2, @c, @c, @c, @c, @c:4d, @b3:8, @a3:2];
tc = [@a3:2, @d:1, @c:1, @b3:2, @g3, @f3, @e3:2, @f3, @c, @c, @d];
tca = [@c:2, @c, 4];
tcb = [@c:2d, @b3, @a3:2d, 4];
T = flat(2^t, tc, tca, tc, tcb);
b = [@f3, @f3, @a3, @a3, @g3, @c3, @f3:2, @f3, @c3, @f3, @a3, @c, @c3, @f3:2];
bc = [@f3:2, @d3, @f3, @g3:2, @c3, @e3, @f3:2, @b2, @d3, @e3, @d3, @c3, @b2, @a2, @c3, @f3, @b2];
bca = [@c3:2, @c3, 4];
bcb = [@c3:1, @f3:2d, 4];
B = flat(2^b, bc, bca, bc, bcb);
synth({ tuning -> 432, overtones -> [0.6, 0.3, 0.07, 0.03], attack -> 200, decay -> 0.6 }, S, A, T, B);

View File

@@ -1,18 +0,0 @@
println("Per Crucem - canon");
d1 = [@d:2, @d:2, @c:2, @f:4d, @f:8, @f, @f, @e, @d, @e:2, @d:2];
d2 = [@d:8, @f:8, @a:8, @d5:8, @b:8, @a:8, @g, @c:8, @e:8, @g:8, @c5:8, @a:8, @g:8, @f, @b3:8, @d:8, @f:8, @b:8, @g:8, @f:8, @e, @a, @e, @f:2];
d3 = [@a:2, @b:2, @c5:2, @a:4d, @a:8, @b, @f, @g, @g, @a, @e, @f:2];
d4 = [@d5:8, @c5:8, @b:8, @a:8, @g:8, @a:8, @b, @c5:8, @b:8, @a:8, @g:8, @f:8, @g:8, @a, @b:8, @a:8, @g:8, @f:8, @e:8, @f:8, @g, @a, @e, @f:2];
d5 = [@d5:2, @d5:2, @c5:2, @c5:2, @d5:8, @c5:8, @b:8, @a:8, @b, @b, @a:2, @a:2];
d6 = [@d:8, @d:8, @d:8, @d:8, @g:8, @g:8, @g, @c:8, @c:8, @c:8, @c:8, @f:8, @f:8, @f, @b3:8, @b3:8, @b3:8, @b3:8, @e:8, @e:8, @e, @a3, @a3, @d:2];
p = [1, 1, 1, 1];
S = d1 + d2 + d3 + d4 + d5 + d6 + d1 + d2 + d3;
A = p + d1 + d2 + d3 + d4 + d5 + d6 + d1 + d2;
T = p + p + d1 + d2 + d3 + d4 + d5 + d6 + d1;
B = p + p + p + d1 + d2 + d3 + d4 + d5 + d6;
wv = wave(S, A, transpose(-12, T), transpose(-12, B));
synth(wv);

View File

@@ -1,31 +0,0 @@
println("Narodził się nam Zbawiciel / Quem pastores laudavere");
println("mel.: XIV w.");
println("sł.: XV - XVI w.");
println("harm.: Bartłomiej Pluta");
s1 = [@f:2, @a, @c5:2, @a, @c5:2, @d5, @c5, @g:2];
s2 = [@a:2, @c5, @b:2, @g, @f:2, @d, @e, @c:2];
s3 = [@a:2, @b, @c5:2, @d5, @c5:2, @g, @a, @f:2];
s4 = [@b:2, @b, @a, @g, @a, @f, @d, @e, @f:2d];
a1 = [@c:2, @f, @g:2, @f, @f, @g, @f, @f, @f, @e];
a2 = [@f, @e, @eb, @d:2, @c, @d:2, @d, @c, @c, @b3];
a3 = [@c:2, @c, @f, @d, @g, @g:2, @e, @e, @d:2];
a4 = [@f:2, @f, @f, @e, @f, @c:2, @c, @c:2d];
t1 = [@a, @b, @c5, @c5, @b, @c5, @a:2, @b, @a, @c5:2];
t2 = [@c5:2, @a, @b:2, @c5, @d5, @c, @b, @g, @g:2];
t3 = [@f, @a, @g, @a:2, @b, @b:2, @g, @g, @a:2];
t4 = [@d5, @db5, @db5, @c5, @b, @a, @g:2, @b, @a:2d];
b1 = [@f:2, @f, @e:2, @f, @f:2, @f, @c, @c:2];
b2 = [@f:2, @f#, @g, @f, @e, @d, @f, @g, @c, @e:2];
b3 = [@f:2, @e, @f, @f#, @g, @e, @d, @c, @c#, @d, @c];
b4 = [@b3:2, @b, @c:2, @c, @c:2, @c, @f:2d];
S = s1 + s2 + s3 + s4;
A = a1 + a2 + a3 + a4;
T = transpose(-12, t1 + t2 + t3 + t4);
B = transpose(-12, b1 + b2 + b3 + b4);
synth({ overtones -> [0.6, 0.25, 0.1] + (2 ^ 0.0) + [0.05], attack -> 50, decay -> 1 }, S, A, T, B);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,2 +0,0 @@
You have to have installed `PortAudio` in order to use app.

View File

@@ -1,36 +0,0 @@
import os
from setuptools import setup, find_packages
def file(file):
return open(os.path.join(os.path.dirname(__file__), file)).read()
setup(
name='SMNP',
version=file('smnp/meta/__version__.txt'),
packages=find_packages(),
description=file('smnp/meta/__description__.txt'),
author='Bartlomiej P. Pluta',
url='https://gitlab.com/bartlomiej.pluta/smnp',
install_requires=[
"cffi>=1.12.3",
"cycler>=0.10.0",
"kiwisolver>=1.1.0",
"matplotlib>=3.1.1",
"numpy>=1.17.2",
"pycparser>=2.19",
"pyparsing>=2.4.2",
"python-dateutil>=2.8.0",
"six>=1.12.0",
"sounddevice>=0.3.13",
"soundfile>=0.10.2"
],
entry_points={
'console_scripts': ['smnp=smnp.main:main']
},
package_data={
'smnp.library.code': ['main.mus'],
'smnp.meta': ['__version__.txt', '__description__.txt']
}
)

56
smnp/ast/node/access.py Normal file
View File

@@ -0,0 +1,56 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.error.syntax import SyntaxException
from smnp.token.type import TokenType
class AccessNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [ NoneNode(), NoneNode() ]
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def right(self):
return self[1]
@right.setter
def right(self, value):
self[1] = value
@classmethod
def accessParser(cls):
def createNode(left, operator, right):
node = AccessNode(right.pos)
node.left = left
node.right = right
return node
return Parser.leftAssociativeOperatorParser(
cls._accessLhs(),
TokenType.DOT,
cls._accessRhs(),
createNode=createNode
)
@classmethod
def _accessLhs(cls):
raise RuntimeError(f"_accessLhs() is not implemented in {cls.__name__} class")
@staticmethod
def _accessRhs():
from smnp.ast.node.identifier import IdentifierNode
return Parser.oneOf(
IdentifierNode.functionCallParser(),
IdentifierNode.identifierParser(),
exception=lambda input: SyntaxException(f"Expected property name or method call, found '{input.current().rawValue}'", input.currentPos())
)

View File

@@ -0,0 +1,28 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
class AssignmentNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(NoneNode())
@property
def target(self):
return self[0]
@target.setter
def target(self, value):
self[0] = value
@property
def value(self):
return self[1]
@value.setter
def value(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")

28
smnp/ast/node/asterisk.py Normal file
View File

@@ -0,0 +1,28 @@
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
class AsteriskNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def iterator(self):
return self[0]
@iterator.setter
def iterator(self, value):
self[0] = value
@property
def statement(self):
return self[1]
@statement.setter
def statement(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")

View File

@@ -1,109 +0,0 @@
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Atom(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value, pos):
node = cls(pos)
node.value = value
return node
class IntegerLiteral(Atom):
pass
class FloatLiteral(Atom):
pass
class StringLiteral(Atom):
pass
class NoteLiteral(Atom):
pass
class BoolLiteral(Atom):
pass
class TypeLiteral(Atom):
pass
def IntegerParser(input):
return Parser.terminal(TokenType.INTEGER, createNode=IntegerLiteral.withValue)(input)
def FloatParser(input):
return Parser.terminal(TokenType.FLOAT, createNode=FloatLiteral.withValue)(input)
def StringParser(input):
return Parser.terminal(TokenType.STRING, createNode=StringLiteral.withValue)(input)
def NoteParser(input):
return Parser.terminal(TokenType.NOTE, createNode=NoteLiteral.withValue)(input)
def BoolParser(input):
return Parser.terminal(TokenType.BOOL, createNode=BoolLiteral.withValue)(input)
def TypeLiteralParser(input):
return Parser.terminal(TokenType.TYPE, createNode=TypeLiteral.withValue)(input)
def LiteralParser(input):
return Parser.oneOf(
IntegerParser,
FloatParser,
StringParser,
NoteParser,
BoolParser,
TypeLiteralParser,
name="literal"
)(input)
def AtomParser(input):
from smnp.ast.node.identifier import IdentifierParser
from smnp.ast.node.list import ListParser
from smnp.ast.node.map import MapParser
from smnp.ast.node.expression import ExpressionParser
parentheses = Parser.allOf(
Parser.terminal(TokenType.OPEN_PAREN),
Parser.doAssert(ExpressionParser, "expression"),
Parser.terminal(TokenType.CLOSE_PAREN),
createNode=lambda open, expr, close: expr,
name="grouping parentheses"
)
return Parser.oneOf(
parentheses,
LiteralParser,
IdentifierParser,
ListParser,
MapParser,
name="atom"
)(input)

View File

@@ -1,17 +1,20 @@
from smnp.ast.node.model import Node
from smnp.ast.node.statement import StatementParser
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Block(Node):
pass
class BlockNode(StatementNode):
@classmethod
def _parse(cls, input):
def createNode(start, items, end):
node = BlockNode(start.pos)
node.children = items
return node
def BlockParser(input):
return Parser.loop(
Parser.terminal(TokenType.OPEN_CURLY),
Parser.doAssert(StatementParser, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminal(TokenType.CLOSE_CURLY),
createNode=lambda open, statements, close: Block.withChildren(statements, open.pos)
Parser.terminalParser(TokenType.OPEN_CURLY),
Parser.doAssert(StatementNode.parse, f"statement or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminalParser(TokenType.CLOSE_CURLY),
createNode=createNode,
)(input)

32
smnp/ast/node/bool.py Normal file
View File

@@ -0,0 +1,32 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.literal import LiteralNode
from smnp.ast.node.relation import RelationOperatorNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class BoolLiteralNode(LiteralNode, AccessNode, RelationOperatorNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
@classmethod
def _getTokenType(cls):
return TokenType.BOOL
@classmethod
def _parse(cls, input):
x = Parser.oneOf(
cls.accessParser(),
cls.relationParser(),
cls.literalParser()
)(input)
return x
@classmethod
def _accessLhs(cls):
return cls.literalParser()
@classmethod
def _relationLhs(cls):
return cls.literalParser()

View File

@@ -1,74 +0,0 @@
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementParser
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class IfElse(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def condition(self):
return self[0]
@condition.setter
def condition(self, value):
self[0] = value
@property
def ifNode(self):
return self[1]
@ifNode.setter
def ifNode(self, value):
self[1] = value
@property
def elseNode(self):
return self[2]
@elseNode.setter
def elseNode(self, value):
self[2] = value
@classmethod
def createNode(cls, ifNode, condition, elseNode=NoneNode()):
node = cls(ifNode.pos)
node.ifNode = ifNode
node.condition = condition
node.elseNode = elseNode
return node
def IfElseStatementParser(input):
ifStatementParser = Parser.allOf(
Parser.terminal(TokenType.IF),
Parser.terminal(TokenType.OPEN_PAREN),
ExpressionParser,
Parser.terminal(TokenType.CLOSE_PAREN),
StatementParser,
createNode=lambda _, __, condition, ___, ifStatement: IfElse.createNode(ifStatement, condition),
name="if statement"
)
ifElseStatementParser = Parser.allOf(
Parser.terminal(TokenType.IF),
Parser.terminal(TokenType.OPEN_PAREN, doAssert=True),
Parser.doAssert(ExpressionParser, "expression"),
Parser.terminal(TokenType.CLOSE_PAREN, doAssert=True),
Parser.doAssert(StatementParser, "statement"),
Parser.terminal(TokenType.ELSE),
Parser.doAssert(StatementParser, "statement"),
createNode=lambda _, __, condition, ___, ifStatement, ____, elseStatement: IfElse.createNode(ifStatement, condition, elseStatement),
name="if-else statement"
)
return Parser.oneOf(
ifElseStatementParser,
ifStatementParser,
name="if-else/if statement"
)(input)

View File

@@ -1,128 +1,66 @@
from smnp.ast.node.asterisk import AsteriskNode
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.node.term import TermParser
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Sum(BinaryOperator):
pass
class Relation(BinaryOperator):
pass
class And(BinaryOperator):
pass
class Or(BinaryOperator):
pass
class Loop(BinaryOperator):
class ExpressionNode(Node):
def __init__(self, pos):
super().__init__(pos)
self.children.extend([NoneNode(), NoneNode()])
super().__init__(pos, [NoneNode()])
@property
def parameters(self):
return self[3]
def value(self):
return self[0]
@parameters.setter
def parameters(self, value):
self[3] = value
@property
def filter(self):
return self[4]
@value.setter
def value(self, v):
self[0] = v
@filter.setter
def filter(self, value):
self[4] = value
@classmethod
def loop(cls, left, parameters, operator, right, filter):
node = cls(left.pos)
node.left = left
node.parameters = parameters
node.operator = operator
node.right = right
node.filter = filter
def withValue(cls, val, pos):
node = cls(pos)
node.value = val
return node
class LoopParameters(Node):
pass
def ExpressionWithoutLoopParser(input):
expr1 = Parser.leftAssociativeOperatorParser(
TermParser,
[TokenType.PLUS, TokenType.MINUS],
TermParser,
lambda left, op, right: Sum.withValues(left, op, right)
)
expr2 = Parser.leftAssociativeOperatorParser(
expr1,
[TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE],
expr1,
lambda left, op, right: Relation.withValues(left, op, right)
)
expr3 = Parser.leftAssociativeOperatorParser(
expr2,
[TokenType.AND],
expr2,
lambda left, op, right: And.withValues(left, op, right)
)
return Parser.leftAssociativeOperatorParser(
expr3,
[TokenType.OR],
expr3,
lambda left, op, right: Or.withValues(left, op, right)
@classmethod
def _parse(cls, input):
return Parser.oneOf(
cls._asteriskParser(),
cls._expressionParser(),
)(input)
def LoopParser(input):
from smnp.ast.node.identifier import IdentifierLiteralParser
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.statement import StatementParser
loopParameters = Parser.allOf(
Parser.terminal(TokenType.AS),
Parser.oneOf(
Parser.wrap(IdentifierLiteralParser, lambda id: LoopParameters.withChildren([id], id.pos)),
abstractIterableParser(LoopParameters, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, IdentifierLiteralParser)
),
createNode=lambda asKeyword, parameters: parameters,
name="loop parameters"
)
loopFilter = Parser.allOf(
Parser.terminal(TokenType.PERCENT),
Parser.doAssert(ExpressionWithoutLoopParser, "filter as bool expression"),
createNode=lambda percent, expr: expr,
name="loop filter"
)
@classmethod
def _asteriskParser(cls):
def createNode(iterator, asterisk, statement):
node = AsteriskNode(asterisk.pos)
node.iterator = iterator
node.statement = statement
return node
return Parser.allOf(
ExpressionWithoutLoopParser,
Parser.optional(loopParameters),
Parser.terminal(TokenType.CARET, createNode=Operator.withValue),
StatementParser,
Parser.optional(loopFilter),
createNode=Loop.loop,
name="caret-loop"
)(input)
cls._expressionParser(),
Parser.terminalParser(TokenType.ASTERISK),
Parser.doAssert(StatementNode.parse, 'statement'),
createNode=createNode
)
@classmethod
def _expressionParser(cls):
from smnp.ast.node.bool import BoolLiteralNode
def ExpressionParser(input):
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.string import StringLiteralNode
return Parser.oneOf(
LoopParser,
ExpressionWithoutLoopParser
)(input)
#IntegerLiteralNode.parse,
StringLiteralNode.parse,
#NoteLiteralNode.parse,
BoolLiteralNode.parse,
IdentifierNode.parse,
#MapNode.parse,
#ListNode.parse,
#TypeNode.parse,
)

View File

@@ -1,14 +1,14 @@
from smnp.ast.node.block import Block
from smnp.ast.node.function import FunctionDefinitionParser
from smnp.ast.node.identifier import IdentifierLiteralParser
from smnp.ast.node.model import Node
from smnp.ast.node.block import BlockNode
from smnp.ast.node.function import FunctionDefinitionNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.none import NoneNode
from smnp.ast.node.type import TypeParser
from smnp.ast.node.statement import StatementNode
from smnp.ast.node.type import TypeNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Extend(Node):
class ExtendNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@@ -38,51 +38,33 @@ class Extend(Node):
self[2] = value
@classmethod
def withValues(cls, pos, type, variable, methods):
node = cls(pos)
def _parse(cls, input):
def createNode(extend, type, asKeyword, variable, methods):
node = ExtendNode(extend.pos)
node.type = type
node.variable = variable
node.methods = methods
return node
def ExtendParser(input):
simpleExtend = Parser.allOf(
Parser.terminal(TokenType.EXTEND),
TypeParser,
Parser.terminal(TokenType.AS),
IdentifierLiteralParser,
Parser.terminal(TokenType.WITH),
Parser.doAssert(Parser.wrap(FunctionDefinitionParser, lambda method: Block.withChildren([ method ], method.pos)), "method definition"),
createNode=lambda extend, type, _, variable, __, methods: Extend.withValues(extend.pos, type, variable, methods),
name="simple extend"
)
multiExtend = Parser.allOf(
Parser.terminal(TokenType.EXTEND),
Parser.doAssert(TypeParser, "type being extended"),
Parser.terminal(TokenType.AS, doAssert=True),
Parser.doAssert(IdentifierLiteralParser, "variable name"),
Parser.doAssert(MethodsDeclarationParser, f"block with methods definitions or '{TokenType.WITH.key}' keyword"),
createNode=lambda extend, type, _, variable, methods: Extend.withValues(extend.pos, type, variable, methods),
name="multiple extend"
)
return Parser.oneOf(
simpleExtend,
multiExtend,
name="extend"
return Parser.allOf(
Parser.terminalParser(TokenType.EXTEND),
Parser.doAssert(TypeNode.parse, "type being extended"),
Parser.terminalParser(TokenType.AS, doAssert=True),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
Parser.doAssert(cls._methodsDeclarationsParser(), "methods declarations"),
createNode=createNode
)(input)
@classmethod
def _methodsDeclarationsParser(cls):
def createNode(openBracket, items, closeBracket):
node = BlockNode(openBracket.pos)
node.children = items
return node
def MethodsDeclarationParser(input):
return Parser.loop(
Parser.terminal(TokenType.OPEN_CURLY),
Parser.doAssert(FunctionDefinitionParser, f"method definition or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminal(TokenType.CLOSE_CURLY),
createNode=lambda open, methods, close: Block.withChildren(methods, open.pos),
name="methods block"
)(input)
Parser.terminalParser(TokenType.OPEN_CURLY),
Parser.doAssert(FunctionDefinitionNode.parse, f"method declaration or '{TokenType.CLOSE_CURLY.key}'"),
Parser.terminalParser(TokenType.CLOSE_CURLY),
createNode=createNode
)

View File

@@ -1,34 +0,0 @@
from smnp.ast.node.operator import BinaryOperator, Operator, UnaryOperator
from smnp.ast.node.unit import UnitParser
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class NotOperator(UnaryOperator):
pass
class Power(BinaryOperator):
pass
def FactorParser(input):
powerFactor = Parser.leftAssociativeOperatorParser(
UnitParser,
[TokenType.DOUBLE_ASTERISK],
UnitParser,
lambda left, op, right: Power.withValues(left, op, right),
name="power operator"
)
notOperator = Parser.allOf(
Parser.terminal(TokenType.NOT, Operator.withValue),
powerFactor,
createNode=NotOperator.withValues,
name="not"
)
return Parser.oneOf(
notOperator,
powerFactor,
name="factor"
)(input)

View File

@@ -1,67 +1,83 @@
from smnp.ast.node.block import BlockParser
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.identifier import IdentifierLiteralParser
from smnp.ast.node.block import BlockNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.type import TypeParser, Type
from smnp.ast.node.statement import StatementNode
from smnp.ast.node.type import TypeNode, TypeSpecifier
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class ArgumentsDeclaration(Node):
class ArgumentsDeclarationNode(Node):
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")
class VarargNode(Node):
pass
class Argument(Node):
class ArgumentDefinitionNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), False, NoneNode()]
self.children.extend([NoneNode(), False])
@property
def type(self):
return self[0]
@type.setter
def type(self, value):
self[0] = value
@property
def variable(self):
return self[1]
@variable.setter
def variable(self, value):
self[1] = value
@property
def vararg(self):
return self[2]
@vararg.setter
def vararg(self, value):
self[2] = value
@property
def optionalValue(self):
return self[3]
@classmethod
def parser(cls):
def createNode(type, variable, dots):
node = ArgumentDefinitionNode(type.pos)
node.type = type
node.variable = variable
node.vararg = isinstance(dots, VarargNode)
return node
@optionalValue.setter
def optionalValue(self, value):
self[3] = value
return Parser.allOf(
Parser.optional(Parser.oneOf(
TypeNode.parse,
TypeSpecifier.parse
)),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
Parser.optional(Parser.terminalParser(TokenType.DOTS, lambda val, pos: VarargNode(pos))),
createNode=createNode
)
class VarargNode(Node):
pass
@classmethod
def _parse(cls, input):
#TODO
raise RuntimeError("Not implemented yet. There is still required work to correctly build AST related to IdentifierNode")
class FunctionDefinition(Node):
class FunctionDefinitionNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@@ -91,75 +107,22 @@ class FunctionDefinition(Node):
self[2] = value
@classmethod
def withValues(cls, name, arguments, body):
node = cls(name.pos)
def _parse(cls, input):
def createNode(function, name, arguments, body):
node = FunctionDefinitionNode(function.pos)
node.name = name
node.arguments = arguments
node.body = body
return node
def RegularArgumentParser(input):
def createNode(type, variable, vararg):
pos = type.pos if isinstance(type, Type) else variable.pos
node = Argument(pos)
node.type = type
node.variable = variable
node.vararg = vararg is True
return node
return Parser.allOf(
Parser.optional(TypeParser),
Parser.doAssert(IdentifierLiteralParser, "argument name"),
Parser.optional(Parser.terminal(TokenType.DOTS, lambda val, pos: True)),
createNode=createNode,
name="regular function argument"
)(input)
def OptionalArgumentParser(input):
def createNode(type, variable, _, optional):
pos = type.pos if isinstance(type, Type) else variable.pos
node = Argument(pos)
node.type = type
node.variable = variable
node.optionalValue = optional
return node
return Parser.allOf(
Parser.optional(TypeParser),
Parser.doAssert(IdentifierLiteralParser, "argument name"),
Parser.terminal(TokenType.ASSIGN),
Parser.doAssert(ExpressionParser, "expression"),
createNode=createNode,
name="optional function argument"
)(input)
def ArgumentParser(input):
return Parser.oneOf(
OptionalArgumentParser,
RegularArgumentParser,
name="function argument"
)(input)
def ArgumentsDeclarationParser(input):
return abstractIterableParser(
ArgumentsDeclaration,
TokenType.OPEN_PAREN,
TokenType.CLOSE_PAREN,
Parser.doAssert(ArgumentParser, "function/method argument")
)(input)
def FunctionDefinitionParser(input):
return Parser.allOf(
Parser.terminal(TokenType.FUNCTION),
Parser.doAssert(IdentifierLiteralParser, "function/method name"),
Parser.doAssert(ArgumentsDeclarationParser, "function/method arguments"),
Parser.doAssert(BlockParser, "function/method body"),
createNode=lambda _, name, args, body: FunctionDefinition.withValues(name, args, body),
name="function definition"
Parser.terminalParser(TokenType.FUNCTION),
Parser.doAssert(IdentifierNode.identifierParser(), "function name"),
Parser.doAssert(cls._argumentsDeclarationParser(), "arguments list"),
Parser.doAssert(BlockNode.parse, "function body"),
createNode=createNode
)(input)
@staticmethod
def _argumentsDeclarationParser():
return abstractIterableParser(ArgumentsDeclarationNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, ArgumentDefinitionNode.parser())

View File

@@ -1,74 +1,73 @@
from smnp.ast.node.atom import Atom
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.node.access import AccessNode
from smnp.ast.node.assignment import AssignmentNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.invocation import FunctionCallNode, ArgumentsListNode
from smnp.ast.node.relation import RelationOperatorNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Identifier(Atom):
pass
class FunctionCall(Node):
class IdentifierNode(AccessNode, RelationOperatorNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def name(self):
return self[0]
@name.setter
def name(self, value):
self[0] = value
@property
def arguments(self):
return self[1]
@arguments.setter
def arguments(self, value):
self[1] = value
del self.children[1]
@classmethod
def withChildren(cls, name, arguments):
node = cls(name.pos)
def _parse(cls, input):
return Parser.oneOf(
cls.relationParser(),
cls.accessParser(),
cls.literalParser()
)(input)
@classmethod
def _accessLhs(cls):
return cls.literalParser()
@classmethod
def _relationLhs(cls):
return Parser.oneOf(
cls.accessParser(),
cls.literalParser()
)
@classmethod
def literalParser(cls):
return Parser.oneOf(
IdentifierNode.functionCallParser(),
IdentifierNode._assignmentParser(),
IdentifierNode.identifierParser()
)
@staticmethod
def _assignmentParser():
def createNode(target, assignment, value):
node = AssignmentNode(assignment.pos)
node.target = target
node.value = value
return node
return Parser.allOf(
IdentifierNode.identifierParser(),
Parser.terminalParser(TokenType.ASSIGN),
Parser.doAssert(ExpressionNode.parse, "expression"),
createNode=createNode
)
@staticmethod
def functionCallParser():
def createNode(name, arguments):
node = FunctionCallNode(name.pos)
node.name = name
node.arguments = arguments
return node
class ArgumentsList(Node):
pass
class Assignment(BinaryOperator):
pass
def IdentifierLiteralParser(input):
return Parser.terminal(TokenType.IDENTIFIER, createNode=Identifier.withValue)(input)
def IdentifierParser(input):
functionCallParser = Parser.allOf(
IdentifierLiteralParser,
abstractIterableParser(ArgumentsList, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN, Parser.doAssert(ExpressionParser, "expression")),
createNode=lambda name, arguments: FunctionCall.withChildren(name, arguments)
return Parser.allOf(
IdentifierNode.identifierParser(),
ArgumentsListNode.parse,
createNode=createNode
)
assignmentParser = Parser.allOf(
IdentifierLiteralParser,
Parser.terminal(TokenType.ASSIGN, createNode=Operator.withValue),
Parser.doAssert(ExpressionParser, "expression"),
createNode=lambda identifier, assign, expr: Assignment.withValues(identifier, assign, expr)
)
return Parser.oneOf(
assignmentParser,
functionCallParser,
IdentifierLiteralParser
)(input)
@staticmethod
def identifierParser():
return Parser.terminalParser(TokenType.IDENTIFIER, lambda val, pos: IdentifierNode.withValue(val, pos))

View File

@@ -1,13 +1,16 @@
from smnp.ast.node.atom import StringParser
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.string import StringLiteralNode
from smnp.ast.node.type import TypeNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Import(Node):
class ImportNode(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def source(self):
@@ -17,17 +20,57 @@ class Import(Node):
def source(self, value):
self[0] = value
@property
def type(self):
return self[1]
@type.setter
def type(self, value):
self[1] = value
@property
def variable(self):
return self[2]
@variable.setter
def variable(self, value):
self[2] = value
@classmethod
def withValue(cls, value):
node = cls(value.pos)
node.source = value
def _parse(cls, input):
return Parser.oneOf(
cls._literalImportParser(),
cls._fileImportParser()
)(input)
@classmethod
def _literalImportParser(cls):
def createNode(importKeyword, type, fromKeyword, source, asKeyword, variable):
node = ImportNode(importKeyword.pos)
node.source = source
node.type = type
node.variable = variable
return node
def ImportParser(input):
return Parser.allOf(
Parser.terminal(TokenType.IMPORT),
Parser.doAssert(StringParser, "import source as string"),
createNode=lambda imp, source: Import.withValue(source),
name="import"
)(input)
Parser.terminalParser(TokenType.IMPORT),
TypeNode.parse,
Parser.doAssert(Parser.terminalParser(TokenType.FROM), "'from <source> as <variable name>'"),
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
Parser.doAssert(Parser.terminalParser(TokenType.AS), "'as <variable name>'"),
Parser.doAssert(IdentifierNode.identifierParser(), "variable name"),
createNode=createNode
)
@classmethod
def _fileImportParser(cls):
def createNode(importKeyword, source):
node = ImportNode(importKeyword.pos)
node.source = source
return node
return Parser.allOf(
Parser.terminalParser(TokenType.IMPORT),
Parser.doAssert(StringLiteralNode.literalParser(), "source as a string"),
createNode=createNode
)

37
smnp/ast/node/integer.py Normal file
View File

@@ -0,0 +1,37 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class IntegerLiteralNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
#TODO del self.children[1]
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls._literalParser()(input)
@classmethod
def _literalParser(cls):
return Parser.oneOf(
cls._negativeIntegerParser(),
cls._positiveIntegerParser()
)
@classmethod
def _negativeIntegerParser(cls):
def createNode(minus, integer):
return IntegerLiteralNode.withValue(-integer.value, minus.pos)
return Parser.allOf(
Parser.terminalParser(TokenType.MINUS),
Parser.doAssert(cls._positiveIntegerParser(), "integer"),
createNode=createNode
)
@classmethod
def _positiveIntegerParser(cls):
return Parser.terminalParser(TokenType.INTEGER, lambda val, pos: IntegerLiteralNode.withValue(int(val), pos))

View File

@@ -0,0 +1,40 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class ArgumentsListNode(Node):
@classmethod
def _parse(cls, input):
return abstractIterableParser(ArgumentsListNode, TokenType.OPEN_PAREN, TokenType.CLOSE_PAREN,
Parser.doAssert(ExpressionNode.parse, "expression"))(input)
class FunctionCallNode(AccessNode):
def __init__(self, pos):
super().__init__(pos)
@property
def name(self):
return self[0]
@name.setter
def name(self, value):
self[0] = value
@property
def arguments(self):
return self[1]
@arguments.setter
def arguments(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
raise RuntimeError("This class is not supposed to be automatically called")

View File

@@ -1,3 +1,4 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.none import NoneNode
@@ -6,19 +7,11 @@ from smnp.token.type import TokenType
def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, itemParser):
class AbstractIterable(Node):
class AbstractIterableTailNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
self.children.append(NoneNode())
@property
def next(self):
@@ -28,67 +21,83 @@ def abstractIterableParser(iterableNodeType, openTokenType, closeTokenType, item
def next(self, value):
self[1] = value
class AbstractIterableTail(AbstractIterable):
pass
def abstractIterableParser(input):
@classmethod
def _parse(cls, input):
return Parser.oneOf(
emptyIterable,
openIterable
AbstractIterableTailNode._parser1(),
AbstractIterableTailNode._parser2(),
)(input)
def emptyIterable(input):
def createNode(open, close):
node = AbstractIterable(open.pos)
node.value = open
node.next = close
@staticmethod
def _parser1():
return Parser.terminalParser(closeTokenType)
@staticmethod
def _parser2():
def createNode(comma, expr, iterableTail):
node = AbstractIterableTailNode(expr.pos)
node.value = expr
node.next = iterableTail
return node
return Parser.allOf(
Parser.terminal(openTokenType),
Parser.terminal(closeTokenType),
createNode=createNode
)(input)
def openIterable(input):
def createNode(open, item, tail):
node = AbstractIterable(open.pos)
node.value = item
node.next = tail
return node
return Parser.allOf(
Parser.terminal(openTokenType),
Parser.terminalParser(TokenType.COMMA, doAssert=True),
itemParser,
abstractIterableTailParser,
AbstractIterableTailNode.parse,
createNode=createNode
)(input)
)
def abstractIterableTailParser(input):
class AbstractIterableNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(NoneNode())
@property
def next(self):
return self[1]
@next.setter
def next(self, value):
self[1] = value
@classmethod
def _parse(cls, input):
return Parser.oneOf(
closeIterable,
nextItem,
AbstractIterableNode._parser1(),
AbstractIterableNode._parser2()
)(input)
def nextItem(input):
def createNode(comma, item, tail):
node = AbstractIterableTail(item.pos)
node.value = item
node.next = tail
@staticmethod
def _parser1():
def emptyIterable(openToken, closeToken):
node = AbstractIterableNode(openToken.pos)
node.value = openToken
node.next = closeToken
return node
return Parser.allOf(
Parser.doAssert(Parser.terminal(TokenType.COMMA), f"'{TokenType.COMMA.key}' or '{closeTokenType.key}'"),
Parser.terminalParser(openTokenType),
Parser.terminalParser(closeTokenType),
createNode=emptyIterable
)
@staticmethod
def _parser2():
def createNode(openParen, expr, iterableTail):
node = AbstractIterableNode(openParen.pos)
node.value = expr
node.next = iterableTail
return node
return Parser.allOf(
Parser.terminalParser(openTokenType, lambda val, pos: Node(pos)),
itemParser,
abstractIterableTailParser,
AbstractIterableTailNode.parse,
createNode=createNode
)(input)
)
def closeIterable(input):
return Parser.terminal(closeTokenType)(input)
return toFlatDesiredNode(iterableNodeType, abstractIterableParser)
return toFlatDesiredNode(iterableNodeType, AbstractIterableNode.parse)
def toFlatDesiredNode(iterableNodeType, parser):
@@ -105,7 +114,7 @@ def toFlatDesiredNode(iterableNodeType, parser):
return ParseResult.FAIL()
return Parser(parse, "flat", [parser])
return parse
def flattenList(node, output=None):

View File

@@ -1,19 +1,17 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class List(Node):
pass
class ListNode(ExpressionNode):
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls._literalParser()(input)
def ListParser(input):
from smnp.ast.node.expression import ExpressionParser
return abstractIterableParser(
List,
TokenType.OPEN_SQUARE,
TokenType.CLOSE_SQUARE,
Parser.doAssert(ExpressionParser, "expression")
)(input)
@classmethod
def _literalParser(cls):
return abstractIterableParser(ListNode, TokenType.OPEN_SQUARE, TokenType.CLOSE_SQUARE,
Parser.doAssert(ExpressionNode.parse, "expression"))

18
smnp/ast/node/literal.py Normal file
View File

@@ -0,0 +1,18 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.parser import Parser
class LiteralNode(ExpressionNode):
@classmethod
def _getTokenType(cls):
pass
@classmethod
def _processValue(cls, value):
return value
@classmethod
def literalParser(cls):
createNode = lambda val, pos: cls.withValue(cls._processValue(val), pos)
return Parser.terminalParser(cls._getTokenType(), createNode)

View File

@@ -1,13 +1,19 @@
from smnp.ast.node.atom import LiteralParser
from smnp.ast.node.identifier import IdentifierLiteralParser
from smnp.ast.node.access import AccessNode
from smnp.ast.node.bool import BoolLiteralNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.integer import IntegerLiteralNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.operator import BinaryOperator, Operator
from smnp.ast.node.none import NoneNode
from smnp.ast.node.note import NoteLiteralNode
from smnp.ast.node.string import StringLiteralNode
from smnp.ast.node.type import TypeNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class MapEntry(BinaryOperator):
class MapEntry(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def key(self):
@@ -19,36 +25,39 @@ class MapEntry(BinaryOperator):
@property
def value(self):
return self[2]
return self[1]
@value.setter
def value(self, value):
self[2] = value
self[1] = value
class MapNode(AccessNode):
class Map(Node):
pass
@classmethod
def _literalParser(cls):
return abstractIterableParser(MapNode, TokenType.OPEN_CURLY, TokenType.CLOSE_CURLY, cls._entryParser())
@classmethod
def _entryParser(cls):
def createNode(key, arrow, value):
node = MapEntry(key.pos)
node.key = key
node.value = value
return node
def MapParser(input):
from smnp.ast.node.expression import ExpressionParser
keyParser = Parser.oneOf(
LiteralParser,
IdentifierLiteralParser
)
valueParser = ExpressionParser
mapEntryParser = Parser.allOf(
keyParser,
Parser.terminal(TokenType.ARROW, createNode=Operator.withValue),
Parser.doAssert(valueParser, "expression"),
createNode=MapEntry.withValues
return Parser.allOf(
cls._keyParser(),
Parser.terminalParser(TokenType.ARROW),
ExpressionNode.parse,
createNode=createNode
)
return abstractIterableParser(
Map,
TokenType.OPEN_CURLY,
TokenType.CLOSE_CURLY,
mapEntryParser
)(input)
@classmethod
def _keyParser(cls):
return Parser.oneOf(
IntegerLiteralNode._literalParser(),
StringLiteralNode._literalParser(),
NoteLiteralNode._literalParser(),
BoolLiteralNode._literalParser(),
TypeNode.parse
)

View File

@@ -28,11 +28,26 @@ class Node:
def pop(self, index):
return self.children.pop(index)
@classmethod
def _parse(cls, input):
pass
@classmethod
def parse(cls, input):
result = cls._parse(input)
if result is None:
return ParseResult.FAIL()
if not isinstance(result, ParseResult):
raise RuntimeError(f"_parse() method of '{cls.__name__}' class haven't returned ParseResult object")
return result
def print(self):
self._print(first=True)
def _print(self, prefix="", last=True, first=False):
print(prefix, '' if first else '└─' if last else '├─', self.__class__.__name__, f" (line {self.pos[0]+1}, col {self.pos[1]+1})", sep="")
print(prefix, '' if first else '└─' if last else '├─', self.__class__.__name__, sep="")
prefix += ' ' if last else ''
for i, child in enumerate(self.children):
last = i == len(self.children) - 1

18
smnp/ast/node/note.py Normal file
View File

@@ -0,0 +1,18 @@
from smnp.ast.node.literal import LiteralNode
from smnp.token.type import TokenType
class NoteLiteralNode(LiteralNode):
def __init__(self, pos):
super().__init__(pos)
#TODO del self.children[1]
# TODO: To Remove
@classmethod
def _parse(cls, input):
return cls.literalParser()(input)
@classmethod
def _getTokenType(cls):
return TokenType.NOTE

View File

@@ -1,75 +1,7 @@
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
class UnaryOperator(Node):
def __init__(self, pos):
super().__init__(pos)
self.children=[NoneNode(), NoneNode()]
@property
def operator(self):
return self[0]
@operator.setter
def operator(self, value):
self[0] = value
@property
def value(self):
return self[1]
@value.setter
def value(self, value):
self[1] = value
@classmethod
def withValues(cls, operator, value):
node = cls(operator.pos)
node.operator = operator
node.value = value
return node
class BinaryOperator(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode(), NoneNode()]
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def operator(self):
return self[1]
@operator.setter
def operator(self, value):
self[1] = value
@property
def right(self):
return self[2]
@right.setter
def right(self, value):
self[2] = value
@classmethod
def withValues(cls, left, operator, right):
node = cls(operator.pos)
node.left = left
node.operator = operator
node.right = right
return node
class Operator(Node):
class OperatorNode(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [None]
@@ -81,9 +13,3 @@ class Operator(Node):
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value, pos):
node = cls(pos)
node.value = value
return node

View File

@@ -1,8 +1,9 @@
from smnp.ast.node.extend import ExtendParser
from smnp.ast.node.function import FunctionDefinitionParser
from smnp.ast.node.imports import ImportParser
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.extend import ExtendNode
from smnp.ast.node.function import FunctionDefinitionNode
from smnp.ast.node.imports import ImportNode
from smnp.ast.node.model import Node, ParseResult
from smnp.ast.node.statement import StatementParser
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.error.syntax import SyntaxException
@@ -11,26 +12,21 @@ class Program(Node):
def __init__(self):
super().__init__((-1, -1))
def ProgramParser(input):
def parse(input):
@classmethod
def _parse(cls, input):
def parseToken(input):
return Parser.oneOf(
FunctionDefinitionNode.parse,
ExtendNode.parse,
ExpressionNode.parse,
ImportNode.parse,
StatementNode.parse,
exception = SyntaxException(f"Invalid statement: {input.currentToEndOfLine()}", input.current().pos)
)(input)
root = Program()
# Start Symbol
startSymbolParser = Parser.oneOf(
ImportParser,
FunctionDefinitionParser,
ExtendParser,
StatementParser,
exception=lambda inp: SyntaxException(f"Invalid statement: {inp.currentToEndOfLine()}", inp.current().pos),
name="start symbol"
)
while input.hasCurrent():
result = startSymbolParser(input)
result = parseToken(input)
if result.result:
root.append(result.node)
return ParseResult.OK(root)
return Parser(parse, name="program")(input)

68
smnp/ast/node/relation.py Normal file
View File

@@ -0,0 +1,68 @@
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class RelationOperatorNode(ExpressionNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [ NoneNode(), NoneNode(), NoneNode()]
@property
def left(self):
return self[0]
@left.setter
def left(self, value):
self[0] = value
@property
def operator(self):
return self[1]
@operator.setter
def operator(self, value):
self[1] = value
@property
def right(self):
return self[2]
@right.setter
def right(self, value):
self[2] = value
@classmethod
def relationParser(cls):
def createNode(left, operator, right):
node = RelationOperatorNode(right.pos)
node.left = left
node.operator = operator
node.right = right
return node
return Parser.leftAssociativeOperatorParser(
cls._relationLhs(),
TokenType.EQUAL,
cls._relationRhs(),
createNode=createNode
)
@classmethod
def _relationLhs(cls):
raise RuntimeError(f"_relationLhs() is not implemented in {cls.__name__} class")
@staticmethod
def _relationRhs():
from smnp.ast.node.bool import BoolLiteralNode
from smnp.ast.node.identifier import IdentifierNode
from smnp.ast.node.string import StringLiteralNode
return Parser.doAssert(Parser.oneOf(
BoolLiteralNode.accessParser(),
BoolLiteralNode.literalParser(),
IdentifierNode.parse,
StringLiteralNode.accessParser(),
StringLiteralNode.literalParser()
), "expression")

View File

@@ -1,17 +1,32 @@
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.valuable import Valuable
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.none import NoneNode
from smnp.ast.node.statement import StatementNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Return(Valuable):
pass
class ReturnNode(StatementNode):
def __init__(self, pos):
super().__init__(pos)
self.children.append(NoneNode())
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def _parse(cls, input):
def createNode(ret, value):
node = ReturnNode(ret.pos)
node.value = value
return node
def ReturnParser(input):
return Parser.allOf(
Parser.terminal(TokenType.RETURN),
Parser.optional(ExpressionParser),
createNode=lambda ret, val: Return.withValue(val, ret.pos),
name="return"
Parser.terminalParser(TokenType.RETURN),
Parser.doAssert(ExpressionNode.parse, "expression"),
createNode=createNode
)(input)

View File

@@ -1,37 +1,17 @@
from smnp.ast.node.model import Node
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Statement(Node):
pass
class StatementNode(Node):
@classmethod
def _parse(cls, input):
from smnp.ast.node.block import BlockNode
from smnp.ast.node.expression import ExpressionNode
from smnp.ast.node.ret import ReturnNode
def StatementParser(input):
from smnp.ast.node.block import BlockParser
from smnp.ast.node.condition import IfElseStatementParser
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.ret import ReturnParser
from smnp.ast.node.throw import ThrowParser
return withSemicolon(
Parser.oneOf(
IfElseStatementParser,
ExpressionParser, # Must be above BlockParser because of Map's syntax with curly braces
BlockParser,
ReturnParser,
ThrowParser,
name="statement"
), optional=True)(input)
def withSemicolon(parser, optional=False, doAssert=False):
semicolonParser = Parser.optional(Parser.terminal(TokenType.SEMICOLON)) if optional else Parser.terminal(
TokenType.SEMICOLON, doAssert=doAssert)
return Parser.allOf(
parser,
semicolonParser,
createNode=lambda stmt, semicolon: stmt,
name="semicolon" + "?" if optional else ""
)
return Parser.oneOf(
ExpressionNode.parse,
BlockNode.parse,
ReturnNode.parse,
)(input)

31
smnp/ast/node/string.py Normal file
View File

@@ -0,0 +1,31 @@
from smnp.ast.node.access import AccessNode
from smnp.ast.node.literal import LiteralNode
from smnp.ast.node.relation import RelationOperatorNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class StringLiteralNode(AccessNode, RelationOperatorNode, LiteralNode):
def __init__(self, pos):
super().__init__(pos)
del self.children[1]
@classmethod
def _parse(cls, input):
return Parser.oneOf(
cls.accessParser(),
cls.relationParser(),
cls.literalParser()
)(input)
@classmethod
def _accessLhs(cls):
return cls.literalParser()
@classmethod
def _relationLhs(cls):
return cls.literalParser()
@classmethod
def _getTokenType(cls):
return TokenType.STRING

View File

@@ -1,17 +0,0 @@
from smnp.ast.node.factor import FactorParser
from smnp.ast.node.operator import BinaryOperator
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Product(BinaryOperator):
pass
def TermParser(input):
return Parser.leftAssociativeOperatorParser(
FactorParser,
[TokenType.ASTERISK, TokenType.SLASH],
FactorParser,
lambda left, op, right: Product.withValues(left, op, right)
)(input)

View File

@@ -1,17 +0,0 @@
from smnp.ast.node.expression import ExpressionParser
from smnp.ast.node.valuable import Valuable
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class Throw(Valuable):
pass
def ThrowParser(input):
return Parser.allOf(
Parser.terminal(TokenType.THROW),
Parser.doAssert(ExpressionParser, "error message as string"),
createNode=lambda throw, message: Throw.withValue(message, throw.pos),
name="throw"
)(input)

View File

@@ -1,15 +1,32 @@
from smnp.ast.node.atom import TypeLiteralParser
from smnp.ast.node.access import AccessNode
from smnp.ast.node.iterable import abstractIterableParser
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
from smnp.type.model import Type
class Type(Node):
class TypeSpecifier(Node):
@classmethod
def _parse(cls, input):
return abstractIterableParser(TypeSpecifier, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE,
Parser.doAssert(cls._specifierItem(), "type"))(input)
@classmethod
def _specifierItem(cls):
return Parser.oneOf(
TypeNode.parse,
cls.parse
)
class TypeSpecifiers(Node):
pass
class TypeNode(AccessNode):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode(), NoneNode()]
@property
def type(self):
@@ -28,40 +45,19 @@ class Type(Node):
self[1] = value
@classmethod
def withValues(cls, pos, type, specifiers=NoneNode()):
node = cls(pos)
node.type = type
def _parse(cls, input):
def createNode(type, specifiers):
node = TypeNode(type.pos)
node.type = Type[type.value.upper()]
node.specifiers = specifiers
return node
class TypesList(Node):
pass
def TypesListParser(input):
return abstractIterableParser(
TypesList,
TokenType.OPEN_ANGLE,
TokenType.CLOSE_ANGLE,
TypeParser
return Parser.allOf(
cls._rawTypeParser(),
Parser.many(TypeSpecifier.parse, lambda specifiers, pos: TypeSpecifiers.withChildren(specifiers, pos)),
createNode=createNode
)(input)
class TypeSpecifiers(Node):
pass
def TypeParser(input):
typeWithSpecifier = Parser.allOf(
TypeLiteralParser,
Parser.many(TypesListParser, createNode=TypeSpecifiers.withChildren),
createNode=lambda type, specifiers: Type.withValues(type.pos, type, specifiers),
name="type with specifiers?"
)
return Parser.oneOf(
typeWithSpecifier,
TypesListParser,
name="mult. types or type with specifier"
)(input)
@classmethod
def _rawTypeParser(cls):
return Parser.terminalParser(TokenType.TYPE, lambda val, pos: TypeNode.withValue(val, pos))

View File

@@ -1,36 +0,0 @@
from smnp.ast.node.atom import AtomParser
from smnp.ast.node.operator import BinaryOperator, UnaryOperator, Operator
from smnp.ast.parser import Parser
from smnp.token.type import TokenType
class MinusOperator(UnaryOperator):
pass
class Access(BinaryOperator):
pass
def UnitParser(input):
minusOperator = Parser.allOf(
Parser.terminal(TokenType.MINUS, createNode=Operator.withValue),
Parser.doAssert(AtomParser, "atom"),
createNode=MinusOperator.withValues,
name="minus"
)
atom2 = Parser.oneOf(
minusOperator,
AtomParser,
name="atom2"
)
return Parser.leftAssociativeOperatorParser(
atom2,
[TokenType.DOT],
Parser.doAssert(atom2, "atom"),
createNode=lambda left, op, right: Access.withValues(left, op, right),
name="unit"
)(input)

View File

@@ -1,22 +0,0 @@
from smnp.ast.node.model import Node
from smnp.ast.node.none import NoneNode
class Valuable(Node):
def __init__(self, pos):
super().__init__(pos)
self.children = [NoneNode()]
@property
def value(self):
return self[0]
@value.setter
def value(self, value):
self[0] = value
@classmethod
def withValue(cls, value, pos=None):
node = cls(value.pos if pos is None else pos)
node.value = value
return node

View File

@@ -1,47 +1,20 @@
from smnp.ast.node.ignore import IgnoredNode
from smnp.ast.node.model import ParseResult, Node
from smnp.ast.node.none import NoneNode
from smnp.ast.node.operator import OperatorNode
from smnp.error.syntax import SyntaxException
def parse(input):
from smnp.ast.node.program import ProgramParser
return ProgramParser(input).node
from smnp.ast.node.program import Program
return Program.parse(input).node
class Parser:
def __init__(self, parse, name=None, parsers=None):
if parsers is None:
parsers = []
self.parsers = parsers
self._parse = parse
if name is None:
name = parse.__name__
self.name = name
def parse(self, input):
result = self._parse(input)
if result is None:
return ParseResult.FAIL()
if not isinstance(result, ParseResult):
raise RuntimeError(f"_parse() method of '{self.__class__.__name__}' class haven't returned ParseResult object")
return result
def __call__(self, input):
return self.parse(input)
def __str__(self):
return self.name
def __repr__(self):
return self.__str__()
# a -> A
@staticmethod
def terminal(expectedType, createNode=None, doAssert=False):
def terminalParser(expectedType, createNode=None, doAssert=False):
def provideNode(value, pos):
if createNode is None:
return IgnoredNode(pos)
@@ -58,11 +31,11 @@ class Parser:
return ParseResult.FAIL()
return Parser(parse, name=expectedType.name.lower())
return parse
# oneOf -> a | b | c | ...
@staticmethod
def oneOf(*parsers, assertExpected=None, exception=None, name="or"):
def oneOf(*parsers, exception=None):
def combinedParser(input):
snap = input.snapshot()
for parser in parsers:
@@ -71,24 +44,21 @@ class Parser:
return value
input.reset(snap)
if assertExpected is not None:
found = f", found '{input.current().rawValue}'" if input.hasCurrent() else ""
raise SyntaxException(f"Expected {assertExpected}{found}", input.currentPos())
if exception is not None:
if callable(exception):
raise exception(input)
else:
raise exception
input.reset(snap)
return ParseResult.FAIL()
return Parser(combinedParser, name=name, parsers=parsers)
return combinedParser
# allOf -> a b c ...
@staticmethod
def allOf(*parsers, createNode, exception=None, name="all"):
def allOf(*parsers, createNode, exception=None):
if len(parsers) == 0:
raise RuntimeError("Pass one parser at least")
@@ -119,36 +89,33 @@ class Parser:
return ParseResult.OK(node)
return Parser(extendedParser, name=name, parsers=parsers)
return extendedParser
# leftAssociative -> left | left OP right
@staticmethod
def leftAssociativeOperatorParser(leftParser, operatorTokenTypes, rightParser, createNode, name="leftAssoc"):
from smnp.ast.node.operator import Operator
def leftAssociativeOperatorParser(leftParser, operatorTokenType, rightParser, createNode):
def parse(input):
operatorParser = Parser.oneOfTerminals(*operatorTokenTypes, createNode=lambda val, pos: Operator.withChildren([val], pos))
left = leftParser(input)
oneAtLeast = False
if left.result:
operator = operatorParser(input)
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
while operator.result:
oneAtLeast = True
right = rightParser(input)
left = ParseResult.OK(createNode(left.node, operator.node, right.node))
operator = operatorParser(input)
operator = Parser.terminalParser(operatorTokenType, lambda val, pos: OperatorNode.withChildren([val], pos))(input)
if oneAtLeast:
return left
return ParseResult.FAIL()
return Parser(parse, name=name, parsers=[leftParser, '|'.join([t.value for t in operatorTokenTypes]), rightParser])
@staticmethod
def oneOfTerminals(*tokenTypes, createNode=None):
return Parser.oneOf(*[Parser.terminal(expectedType, createNode=createNode) for expectedType in tokenTypes], name='|'.join([t.value for t in tokenTypes]))
return parse
# loop -> start item* end
@staticmethod
def loop(startParser, itemParser, endParser, createNode, name="loop"):
def loop(startParser, itemParser, endParser, createNode):
def parse(input):
items = []
start = startParser(input)
@@ -164,10 +131,10 @@ class Parser:
return ParseResult.FAIL()
return Parser(parse, name, parsers=[startParser, itemParser, endParser])
return parse
@staticmethod
def doAssert(parser, expected, name="!!"):
def doAssert(parser, expected):
def parse(input):
result = parser(input)
@@ -178,10 +145,10 @@ class Parser:
return result
return Parser(parse, name, parsers=parser)
return parse
@staticmethod
def optional(parser, name="??"):
def optional(parser):
def parse(input):
result = parser(input)
if result.result:
@@ -189,14 +156,10 @@ class Parser:
return ParseResult.OK(NoneNode())
return Parser(parse, name, parsers=[parser])
return parse
@staticmethod
def epsilon():
return lambda *args: ParseResult.OK(NoneNode())
@staticmethod
def many(parser, createNode, name="*"):
def many(parser, createNode):
def parse(input):
results = []
snap = input.snapshot()
@@ -210,15 +173,4 @@ class Parser:
input.reset(snap)
return ParseResult.OK(createNode(results, pos) if len(results) > 0 else NoneNode())
return Parser(parse, name, parsers=[parser])
@staticmethod
def wrap(parser, createNode):
def parse(input):
result = parser(input)
if result.result:
return ParseResult.OK(createNode(result.node))
return result
return parse

View File

@@ -10,9 +10,6 @@ class Sound:
def play(self):
sd.play(self.data, self.fs, blocking=True)
def __eq__(self, other):
return self.file == other.file and self.data == other.data
def __str__(self):
return f"sound[{self.file}]"

View File

View File

@@ -1,26 +0,0 @@
import argparse
from pkg_resources import resource_string
def file(file):
return resource_string('smnp.meta', file).decode("utf-8")
class CliParser(object):
def __init__(self):
self.parser = argparse.ArgumentParser(description=file("__description__.txt"))
self.parser.add_argument('file', nargs='*', help='a file containing SMNP code')
self.parser.add_argument('-c', '--code', action='append', default=[], type=str, help='a string with SMNP code')
self.parser.add_argument('-m', '--mic', action='store_true', help='test microphone level')
self.parser.add_argument('-C', '--config', type=argparse.FileType('-r'), help='a file containing settings (not implemented yet)')
self.parser.add_argument('-p', '--params', action='append', help='pass arguments to program (not implemented yet)')
self.parser.add_argument('-v', '--version', action='version')
self.parser.add_argument('--tokens', action='store_true', help='print tokens of parsed code')
self.parser.add_argument('--ast', action='store_true', help='print abstract syntax tree of parsed code')
self.parser.add_argument('--dry-run', action='store_true', help='don\'t execute passed code')
self.parser.version = file("__version__.txt")
def parse(self):
return self.parser.parse_args()

View File

@@ -1,19 +1,17 @@
from smnp.error.function import FunctionNotFoundException, MethodNotFoundException, IllegalFunctionInvocationException
from smnp.error.runtime import RuntimeException
from smnp.function.tools import argsTypesToString
from smnp.runtime.evaluators.function import BodyEvaluator, Return
from smnp.type.model import Type
from smnp.runtime.evaluators.function import BodyEvaluator
class Environment():
def __init__(self, scopes, functions, methods, source):
def __init__(self, scopes, functions, methods):
self.scopes = scopes
self.functions = functions
self.methods = methods
self.customFunctions = []
self.customMethods = []
self.callStack = []
self.source = source
def invokeMethod(self, object, name, args):
builtinMethodResult = self._invokeBuiltinMethod(object, name, args)
@@ -40,15 +38,10 @@ class Environment():
if method.typeSignature.check([object])[0] and method.name == name: #Todo sprawdzic sygnature typu
signatureCheckresult = method.signature.check(args)
if signatureCheckresult[0]:
self.scopes.append(method.defaultArgs)
self.scopes[-1].update({argName: argValue for argName, argValue in zip(method.arguments, list(signatureCheckresult[1:]))})
self.scopes.append({argName: argValue for argName, argValue in zip(method.arguments, list(signatureCheckresult[1:]))})
self.scopes[-1][method.alias] = object
self.callStack.append(CallStackItem(name))
result = Type.void()
try:
BodyEvaluator.evaluate(method.body, self).value # TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
except Return as r:
result = r.value
result = BodyEvaluator.evaluate(method.body, self).value # TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
self.callStack.pop(-1)
self.scopes.pop(-1)
return (True, result)
@@ -81,27 +74,20 @@ class Environment():
if function.name == name:
signatureCheckresult = function.signature.check(args)
if signatureCheckresult[0]:
self.appendScope(function.defaultArgs)
appendedScopeIndex = len(self.scopes)-1
self.scopes[-1].update({ argName: argValue for argName, argValue in zip(function.arguments, list(signatureCheckresult[1:])) })
self.scopes.append({ argName: argValue for argName, argValue in zip(function.arguments, list(signatureCheckresult[1:])) })
self.callStack.append(CallStackItem(name))
result = Type.void()
try:
BodyEvaluator.evaluate(function.body, self).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
except Return as r:
result = r.value
result = BodyEvaluator.evaluate(function.body, self).value #TODO check if it isn't necessary to verify 'result' attr of EvaluatioNResult
self.callStack.pop(-1)
self.popScope(mergeVariables=False)
self.removeScopesAfter(appendedScopeIndex)
self.scopes.pop(-1)
return (True, result)
raise IllegalFunctionInvocationException(f"{function.name}{function.signature.string}", f"{name}{argsTypesToString(args)}")
return (False, None)
def addCustomFunction(self, name, signature, arguments, body, defaultArguments):
def addCustomFunction(self, name, signature, arguments, body):
if len([fun for fun in self.functions + self.customFunctions if fun.name == name]) > 0:
raise RuntimeException(f"Cannot redeclare function '{name}'", None)
self.customFunctions.append(CustomFunction(name, signature, arguments, body, defaultArguments))
self.customFunctions.append(CustomFunction(name, signature, arguments, body))
# TODO:
# There is still problem with checking existing of generic types, like lists:
@@ -112,14 +98,14 @@ class Environment():
# function foo() { return 2 }
# }
# Then calling [1, 2, 3, 4].foo() will produce 1, when the second method is more suitable
def addCustomMethod(self, typeSignature, alias, name, signature, arguments, body, defaultArguments):
def addCustomMethod(self, typeSignature, alias, name, signature, arguments, body):
if len([m for m in self.methods if m.name == name and m.signature.matchers[0] == typeSignature.matchers[0]]) > 0:
raise RuntimeException(f"Cannot redeclare method '{name}' for type '{typeSignature.matchers[0]}'", None)
if len([m for m in self.customMethods if m.name == name and m.typeSignature.matchers[0] == typeSignature.matchers[0]]) > 0:
raise RuntimeException(f"Cannot redeclare method '{name}' for type '{typeSignature.matchers[0]}'", None)
self.customMethods.append(CustomMethod(typeSignature, alias, name, signature, arguments, body, defaultArguments))
self.customMethods.append(CustomMethod(typeSignature, alias, name, signature, arguments, body))
def findVariable(self, name, type=None, pos=None):
for scope in reversed(self.scopes):
@@ -142,20 +128,6 @@ class Environment():
else:
return scope
def appendScope(self, variables=None):
if variables is None:
variables = {}
self.scopes.append(variables)
def popScope(self, mergeVariables=True):
lastScope = self.scopes.pop(-1)
if mergeVariables:
self.scopes[-1].update(lastScope)
def removeScopesAfter(self, index):
del self.scopes[index:]
def scopesToString(self):
return "Scopes:\n" + ("\n".join([ f" [{i}]: {scope}" for i, scope in enumerate(self.scopes) ]))
@@ -190,23 +162,22 @@ class Environment():
class CallStackItem:
def __init__(self, function):
self.function = function
self.value = None
class CustomFunction:
def __init__(self, name, signature, arguments, body, defaultArgs):
def __init__(self, name, signature, arguments, body):
self.name = name
self.signature = signature
self.arguments = arguments
self.body = body
self.defaultArgs = defaultArgs
class CustomMethod:
def __init__(self, typeSignature, alias, name, signature, arguments, body, defaultArgs):
def __init__(self, typeSignature, alias, name, signature, arguments, body):
self.typeSignature = typeSignature
self.alias = alias
self.name = name
self.signature = signature
self.arguments = arguments
self.body = body
self.defaultArgs = defaultArgs

View File

@@ -1,3 +1,7 @@
def createEnvironment():
return
from smnp.environment.environment import Environment
from smnp.module import functions, methods
def createEnvironment():
return Environment([{}], functions, methods)

View File

@@ -2,7 +2,6 @@ class SmnpException(Exception):
def __init__(self, msg, pos):
self.msg = msg
self.pos = pos
self.file = None
def _title(self):
pass
@@ -11,10 +10,7 @@ class SmnpException(Exception):
return ""
def _position(self):
return "" if self.pos is None else f"[line {self.pos[0]+1}, col {self.pos[1]+1}]"
def _file(self):
return "" if self.file is None else f"File: {self.file}"
return "" if self.pos is None else f" [line {self.pos[0]+1}, col {self.pos[1]+1}]"
def message(self):
return f"{self._title()}\n{self._file()} {self._position()}\n\n{self.msg}\n{self._postMessage()}"
return f"{self._title()}{self._position()}:\n{self.msg}\n{self._postMessage()}"

View File

@@ -1,12 +0,0 @@
from smnp.error.runtime import RuntimeException
class CustomException(RuntimeException):
def __init__(self, message, pos):
super().__init__(message, pos)
def _title(self):
return "Execution Error"
def _postMessage(self):
return "\n" + self.environment.callStackToString() if len(self.environment.callStack) > 0 else ""

View File

@@ -12,9 +12,6 @@ class Signature:
def varargSignature(varargMatcher, *basicSignature, wrapVarargInValue=False):
def check(args):
if any([ matcher.optional for matcher in [ varargMatcher, *basicSignature ]]):
raise RuntimeError("Vararg signature can't have optional arguments")
if len(basicSignature) > len(args):
return doesNotMatchVararg(basicSignature)
@@ -41,7 +38,7 @@ def doesNotMatchVararg(basicSignature):
def signature(*signature):
def check(args):
if len(args) > len(signature) or len(args) < len([ matcher for matcher in signature if not matcher.optional ]):
if len(signature) != len(args):
return doesNotMatch(signature)
for s, a in zip(signature, args):
@@ -55,12 +52,6 @@ def signature(*signature):
return Signature(check, string, signature)
def optional(matcher):
matcher.optional = True
matcher.string += "?"
return matcher
def doesNotMatch(sign):
return (False, *[None for n in sign])

View File

@@ -1,492 +0,0 @@
function flat(list lists...) {
return _flat(lists as l ^ _flat(l, []), []);
}
function _flat(list l, list output) {
l as elem ^ {
if (typeOf(elem) == list) {
output = _flat(elem, output);
} else {
output = output + [elem];
}
}
return output;
}
extend note as n {
function withOctave(integer octave) {
return Note(n.pitch, octave, n.duration, n.dot);
}
function withDuration(integer duration) {
return Note(n.pitch, n.octave, duration, n.dot);
}
function withDot(bool dot) {
return Note(n.pitch, n.octave, n.duration, dot);
}
function toIntRepr() {
return n.octave * 12 + _pitchToNumber(n.pitch);
}
function transpose(integer value) {
return noteFromIntRepr(n.toIntRepr() + value, n.duration, n.dot);
}
}
function noteFromIntRepr(integer intRepr, integer duration, bool dot) {
pitch = _numberToPitch(mod(intRepr, 12));
octave = Integer(intRepr / 12);
return Note(pitch, octave, duration, dot);
}
function mod(integer a, integer b) {
return a - b * Integer(a/b);
}
function _pitchToNumber(string pitch) {
return _keysToIntMapper(
"C",
"CIS",
"D",
"DIS",
"E",
"F",
"FIS",
"G",
"GIS",
"A",
"AIS",
"H"
).get(pitch);
}
function _keysToIntMapper(keys...) {
return Map(keys as (i, key) ^ [key, i]);
}
function _numberToPitch(integer number) {
return ["C", "CIS", "D", "DIS", "E", "F", "FIS", "G", "GIS", "A", "AIS", "H"].get(number);
}
function transpose(integer value, <note, integer, list<note, integer>> notes...) {
if (notes.size == 1) {
first = notes.get(0);
if (typeOf(first) == integer) {
return first;
} else if (typeOf(first) == note) {
return first.transpose(value);
} else if (typeOf(first) == list) {
return _transpose(value, first);
}
}
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
output = [];
notes as n ^ {
if (typeOf(n) == integer) {
output = output + [n];
} else if (typeOf(n) == note) {
output = output + [n.transpose(value)];
} else if (typeOf(n) == list) {
output = output + [_transpose(value, n)];
}
}
return output;
}
function _transpose(integer value, list<note, integer> notes) {
output = [];
notes as n ^ {
if (typeOf(n) == integer) {
output = output + [n];
} else if (typeOf(n) == note) {
output = output + [n.transpose(value)];
}
}
return output;
}
function transposeTo(note target, <note, integer, list<note, integer>> notes...) {
if (notes.size == 1) {
first = notes.get(0);
if (typeOf(first) == integer) {
return first;
} else if (typeOf(first) == note) {
return _transposeTo(target, notes).get(0);
} else if (typeOf(first) == list) {
return _transposeTo(target, first);
}
}
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
if (noteOrInteger) {
return _transposeTo(target, notes);
}
if (lists) {
return notes as n ^ _transposeTo(target, n);
}
}
function _transposeTo(note target, list<note, integer> notes) {
if (notes.size == 0) {
throw "Provide list with one note at least";
}
firstNote = notes.get(0);
semitones = semitones(firstNote, target);
return transpose(semitones, notes);
}
function tuplet(integer n, integer m, note notes...) {
if (n != notes.size) {
throw "Expected " + n.toString() + " notes exactly, whereas " + notes.size.toString() + " was passed";
}
return notes as x ^ x.withDuration(x.duration * n / m);
}
extend list as l with function contains(expectedValue) {
return (l as value ^ value % value == expectedValue).size > 0;
}
extend map as m {
function containsKey(expectedKey) {
return m.keys.contains(expectedKey);
}
function containsValue(expectedValue) {
return m.values.contains(expectedValue);
}
function contains(key, value) {
if (m.keys.contains(key)) {
return m.get(key) == value;
}
return false;
}
}
function sample(items...) {
if (items.size == 0) {
throw "Provide one item at least";
}
if (items.size == 1 and typeOf(items) == list) {
return items.get(0).get(rand(0, items.get(0).size-1));
}
return items.get(rand(0, items.size-1));
}
extend string as s with function join(list<string> l) {
output = "";
l as (index, item) ^ {
output = output + item;
if (index < l.size - 1) {
output = output + s;
}
}
return output;
}
function random(map<string><> items...) {
accumulator = 0;
items as (index, item) ^ {
if (item.size != 2) {
throw "Expected lists with two items: percent and value";
}
if (not item.containsKey("percent")) {
throw "Item " + (index+1).toString() + " does not have 'percent' key";
}
if (not item.containsKey("value")) {
throw "Item " + (index+1).toString() + " does not have 'value' key";
}
accumulator = accumulator + item.get("percent");
}
if (accumulator != 100) {
throw "Sum of first element of each item must be equal to 100";
}
accumulator = 0;
random = rand(0, 99);
items as item ^ {
accumulator = accumulator + item.get("percent");
if (random < accumulator) {
return item.get("value");
}
}
}
function semitones(<note, integer, list<note, integer>> notes...) {
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
if (noteOrInteger) {
return _semitones(notes);
}
if (lists) {
output = [];
notes as n ^ {
output = output + [_semitones(n)];
}
#if (output.size == 1) {
# return output.get(0)
#}
return output;
}
return [];
}
function _semitones(list<note, integer> notes) {
onlyNotes = notes as n ^ n % typeOf(n) == note;
if (onlyNotes.size == 2 and typeOf(onlyNotes.get(0)) == note and typeOf(onlyNotes.get(1)) == note) {
first = onlyNotes.get(0);
second = onlyNotes.get(1);
return second.toIntRepr() - first.toIntRepr();
}
if (onlyNotes.size < 2) {
throw "Provide 2 notes at least to evaluate semitones between them";
}
output = [];
range(1, onlyNotes.size-1) as i ^ {
output = output + [onlyNotes.get(i).toIntRepr() - onlyNotes.get(i-1).toIntRepr()];
}
return output;
}
function stringInterval(integer semitones) {
return [
"1",
"2m",
"2M",
"3m",
"3M",
"4",
"5d/4A",
"5",
"6m",
"6M",
"7m",
"7M"
].get(semitones);
}
function interval(<note, integer, list<note, integer>> notes...) {
noteOrInteger = false;
lists = false;
notes as n ^ {
if (typeOf(n) == note or typeOf(n) == integer) {
noteOrInteger = true;
if (lists) {
throw "Mixing notes and integers with lists of them is not supported";
}
} else if (typeOf(n) == list) {
lists = true;
if (noteOrInteger) {
throw "Mixing notes and integers with lists of them is not supported";
}
}
}
if (noteOrInteger) {
semitones = _semitones(notes);
if (typeOf(semitones) == list) {
return semitones as n ^ stringInterval(n);
} else {
return stringInterval(semitones);
}
}
if (lists) {
output = [];
notes as n ^ {
semitones = _semitones(n);
if (typeOf(semitones) == list) {
output = output + [_semitones(n) as semitone ^ stringInterval(semitone)];
} else {
output = output + [stringInterval(semitones)];
}
}
#if (output.size == 1) {
# return output.get(0);
#}
return output;
}
return [];
}
function noteRange(note a, note b, string filter = "all") {
filters = {
"all" -> [ "C", "CIS", "D", "DIS", "E", "F", "FIS", "G", "GIS", "A", "AIS", "H" ],
"diatonic" -> [ "C", "D", "E", "F", "G", "A", "H" ],
"chromatic" -> [ "CIS", "DIS", "FIS", "GIS", "AIS" ]
};
if (not filters.containsKey(filter)) {
throw "Unknown filter: '" + filter + "'";
}
notes = range(a.toIntRepr(), b.toIntRepr()) as intRepr ^ noteFromIntRepr(intRepr, a.duration, a.dot);
return notes as n ^ n % filters.get(filter).contains(n.pitch);
}
function range(<integer, float> a, <integer, float> b, <integer, float> step = 1) {
if (not (step > 0)) {
throw "Step should be greater than 0";
}
if (a > b) {
throw "Upper range value should be greater than lower or equal to";
}
output = [];
i = a;
i <= b ^ {
output = output + [i];
i = i + step;
}
return output;
}
function alert(<integer, bool> cycles = true, string melody = "beep", list<float, integer> overtones = [0.5, 0.0, 0.0, 0.5]) {
if (not [integer, bool].contains(typeOf(cycles))) {
throw "Provide 'true' or number of cycles as first argument";
}
if (typeOf(cycles) == integer) {
if (cycles < 1) {
throw "Number of cycles cannot be less than 1";
}
}
if (typeOf(cycles) == bool) {
if (not cycles) {
throw "Provide 'true' or number of cycles as first argument";
}
}
notes = {
"beep" -> [@c5:16, 32, @c5:16, 3],
"s1" -> noteRange(@c5:32, @g5:32),
"s2" -> _upDown(noteRange(@c5:32, @g5:32)),
"s3" -> [@a5:16, @d5:16],
"semitone" -> [@c5:16, @db5:16]
};
if (not notes.containsKey(melody)) {
throw "Unknown melody '" + melody + "'. Available: 'beep', 's1', 's2', 's3' and 'semitone'";
}
config = {
bpm -> 120,
decay -> 0.5,
attack -> 200,
overtones -> overtones
};
wave = wave(config, notes.get(melody));
cycles ^ synth(wave);
}
function _upDown(list l) {
return l + -l;
}
function metronome(integer bpm = 120, integer beats = 4, countMeasures = false) {
accent = wave({
overtones -> flat([0.5, 0.1, 10^0, 0.1, 10^0, 0.1, 20^0, 0.1, 25^0, 0.05, 25^0, 0.05]),
attack -> 0,
decay -> 5,
bpm -> bpm
}, @c);
beat = wave({
overtones -> flat([0.5, 10^0, 0.3, 10^0, 0.2]),
attack -> 0,
decay -> 100,
bpm -> bpm
}, @c);
measure = 1;
true ^ {
if (countMeasures) {
println(measure);
measure = measure + 1;
}
synth(accent);
beats - 1 ^ synth(beat);
}
}

View File

@@ -5,5 +5,7 @@ from smnp.program.interpreter import Interpreter
def loadStandardLibrary():
mainSource = resource_string('smnp.library.code', 'main.mus').decode("utf-8")
env = Interpreter.interpretString(mainSource, "<stdlib>")
return env
boolSource = resource_string('smnp.library.code', 'bool.mus').decode("utf-8")
env = Interpreter.interpretString(mainSource)
return Interpreter.interpretString(boolSource, baseEnvironment=env)

View File

@@ -1,38 +1,16 @@
from smnp.cli.parser import CliParser
import sys
from smnp.error.base import SmnpException
from smnp.library.loader import loadStandardLibrary
from smnp.module.mic.lib.detector.noise import NoiseDetector
from smnp.program.interpreter import Interpreter
def interpretFile(args, file):
stdLibraryEnv = loadStandardLibrary() if not args.dry_run else None
Interpreter.interpretFile(file, printTokens=args.tokens, printAst=args.ast, execute=not args.dry_run, baseEnvironment=stdLibraryEnv)
def interpretString(args, string):
stdLibraryEnv = loadStandardLibrary() if not args.dry_run else None
Interpreter.interpretString(string, printTokens=args.tokens, printAst=args.ast, execute=not args.dry_run, baseEnvironment=stdLibraryEnv, source='<cli>')
def main():
try:
parser = CliParser()
args = parser.parse()
if args.mic:
nd = NoiseDetector()
nd.test()
for code in args.code:
interpretString(args, code)
for file in args.file:
interpretFile(args, file)
#stdLibraryEnv = loadStandardLibrary()
Interpreter.interpretFile(sys.argv[1], printTokens=False, printAst=True, baseEnvironment=None)
except SmnpException as e:
print(e.message())
except KeyboardInterrupt:
print("Program interrupted")

View File

@@ -1 +0,0 @@
Simple Music Notation Processor is a command line tool enabling you to do some music stuff using custom domain-specific language.

View File

View File

@@ -1 +0,0 @@
0.1

View File

@@ -1,4 +1,4 @@
from smnp.module import system, mic, note, iterable, sound, synth, string, util, integer, float
from smnp.module import system, mic, note, iterable, sound, synth, string, util
functions = [ *system.functions, *mic.functions, *note.functions, *iterable.functions, *sound.functions, *synth.functions, *string.functions, *util.functions, *integer.functions, *float.functions ]
methods = [ *system.methods, *mic.methods, *note.methods, *iterable.methods, *sound.methods, *synth.methods, *string.methods, *util.methods, *integer.methods, *float.methods ]
functions = [ *system.functions, *mic.functions, *note.functions, *iterable.functions, *sound.functions, *synth.functions, *string.functions, *util.functions ]
methods = [ *system.methods, *mic.methods, *note.methods, *iterable.methods, *sound.methods, *synth.methods, *string.functions, *util.methods ]

View File

@@ -1,4 +0,0 @@
from smnp.module.float.function import float
functions = [ float.function ]
methods = []

View File

@@ -1,26 +0,0 @@
from smnp.function.model import CombinedFunction, Function
from smnp.function.signature import signature
from smnp.type.model import Type
from smnp.type.signature.matcher.type import ofType
_signature1 = signature(ofType(Type.INTEGER))
def _function1(env, value):
return Type.float(float(value.value))
_signature2 = signature(ofType(Type.STRING))
def _function2(env, value):
return Type.float(float(value.value))
_signature3 = signature(ofType(Type.FLOAT))
def _function3(env, value):
return value
function = CombinedFunction(
'Float',
Function(_signature1, _function1),
Function(_signature2, _function2),
Function(_signature3, _function3),
)

View File

@@ -1,4 +0,0 @@
from smnp.module.integer.function import integer
functions = [ integer.function ]
methods = []

View File

@@ -1,25 +0,0 @@
from smnp.function.model import CombinedFunction, Function
from smnp.function.signature import signature
from smnp.type.model import Type
from smnp.type.signature.matcher.type import ofType
_signature1 = signature(ofType(Type.FLOAT))
def _function1(env, value):
return Type.integer(int(value.value))
_signature2 = signature(ofType(Type.STRING))
def _function2(env, value):
return Type.integer(int(value.value))
_signature3 = signature(ofType(Type.INTEGER))
def _function3(env, value):
return value
function = CombinedFunction(
'Integer',
Function(_signature1, _function1),
Function(_signature2, _function2),
Function(_signature3, _function3),
)

Some files were not shown because too many files have changed in this diff Show More