├── .github └── FUNDING.yml ├── .gitignore ├── CODING_GUIDELINES.md ├── LEIAME.md ├── LICENSE ├── README.md ├── VimSyntaxHighlight └── vim │ ├── filetype.vim │ ├── ftdetect │ └── w.vim │ └── syntax │ └── w.vim ├── art ├── Guidelines.txt ├── logo.svg └── logo1.svg ├── core ├── assets │ ├── LICENSE.txt │ ├── Roboto-Bold.ttf │ ├── Roboto-BoldItalic.ttf │ └── Roboto-Italic.ttf ├── builder.py ├── dependencies.py ├── engines │ └── pyEngine.py ├── grammar │ ├── exampleGrammar.py │ ├── genGrammar.py │ ├── generatedGrammar.py │ └── grammar ├── interpreter.py ├── lexer.py ├── libs │ ├── http │ │ └── server.w │ ├── lol │ │ └── test.w │ ├── native │ │ ├── c │ │ │ ├── _httpserver.h │ │ │ ├── _requests.h │ │ │ ├── asprintf.h │ │ │ ├── dict_int.template │ │ │ ├── dict_str.template │ │ │ ├── list_float.h │ │ │ ├── list_int.h │ │ │ ├── list_str.h │ │ │ ├── list_template.h │ │ │ └── photonInput.h │ │ ├── d │ │ │ └── dontRemove │ │ ├── haxe │ │ │ └── dontRemove │ │ ├── js │ │ │ └── dontRemove │ │ └── py │ │ │ └── dontRemove │ ├── random.w │ ├── requests.w │ ├── wui.w │ ├── wui │ │ ├── widgets.w │ │ └── wuiGraphics.w │ └── wuiGraphics.w ├── pattern_cli.py ├── photon.py ├── photonParser.py ├── toolchains │ ├── shared.py │ └── toolchain.py └── transpilers │ ├── baseTranspiler.py │ ├── baseType.py │ ├── cTokens.py │ ├── cTranspiler.py │ ├── dTranspiler.py │ ├── jsTokens.py │ ├── jsTranspiler.py │ ├── pyTokens.py │ ├── pyTranspiler.py │ ├── tokens.py │ └── tsTranspiler.py ├── examples ├── callback_ex.w ├── class_ex.w ├── conditionals_ex.w ├── dict_ex.w ├── ffi │ ├── ffi_photon.py │ ├── main.so │ └── main.w ├── for_target_ex.w ├── functions_ex.w ├── list_ex.w ├── loops_ex.w ├── print_and_input_ex.w ├── random_ex.w ├── run_all_ex.w ├── test_ex.w └── variables_ex.w ├── install.py ├── linuxInstaller.sh ├── tests ├── parserTest.py ├── testFiles │ ├── assign │ │ ├── floatVarEqualInt.w │ │ ├── intVarEqualInt.w │ │ ├── modifierWithVar.w │ │ ├── varEqualExpr.w │ │ ├── varEqualExprGroup.w │ │ ├── varEqualGroup.w │ │ ├── varEqualInt.w │ │ ├── varEqualModifierExpr.w │ │ └── varEqualModifierGroup.w │ ├── printFunc │ │ ├── printFloat.w │ │ ├── printFloatDot.w │ │ ├── printInt.w │ │ ├── printStr.w │ │ └── printVar.w │ └── varInit │ │ ├── initClass.w │ │ ├── initClassArray.w │ │ ├── initClassStrMap.w │ │ ├── initFloat.w │ │ ├── initInt.w │ │ ├── initStr.w │ │ ├── initStrArray.w │ │ ├── initStrClassMap.w │ │ └── initStrStrMap.w └── transpilersTest.py ├── uninstall.py ├── windowsInstaller.bat └── windowsInstaller.ps1 /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: HashLDash 4 | custom: ['www.hashldash.com/doacao'] 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .coverage 3 | _build 4 | .DS_Store 5 | .vscode 6 | docs/_static/pypi.svg 7 | .tox 8 | __pycache__/ 9 | black.egg-info 10 | build/ 11 | dist/ 12 | pip-wheel-metadata/ 13 | src/_black_version.py 14 | .idea 15 | .eggs 16 | .dmypy.json 17 | *.swp 18 | .hypothesis/ 19 | venv/ 20 | examples/Sources/ 21 | examples/future/ 22 | tests/Sources/ 23 | -------------------------------------------------------------------------------- /CODING_GUIDELINES.md: -------------------------------------------------------------------------------- 1 | # Please, consider using the following when contributing 2 | 3 | - Variables, functions should use camel case, starting with lower-case 4 | - Classes should be pascal case, starting with upper-case 5 | - Global variables should be all upper-case 6 | 7 | # Naming conventions 8 | 9 | Please use short, but descriptive function names. 10 | Example: 11 | 12 | - Prefer programInstalled instead of programIsInstalled, or programAvailableInPath 13 | 14 | # Functions and method explanations 15 | 16 | - Please use docstrings to explain what is the function or method doing 17 | - Use comments to explain a specific line 18 | 19 | # Coding Style 20 | 21 | Please avoid defining very specific functions when a general form is available. 22 | 23 | Example: 24 | 25 | - If we have a programInstalled function, avoid writing a gccIsInstalled. Use programInstalled instead. 26 | -------------------------------------------------------------------------------- /LEIAME.md: -------------------------------------------------------------------------------- 1 |

Photon

2 | 3 |

Install on 4 | Convert to 5 | Run in

6 | 7 | 8 |

PT-BR Channeç 9 | Contributions Welcome 10 | Discord Server

11 | 12 | 13 | 14 | # Photon 15 | Linguagem de programação extremamente rápida e portátil do Will! 16 | 17 | # O que é Photon? 18 | 19 | Photon é uma linguagem de programação com uma sintaxe bem amigável e parecida com Python, porém muuuiitoo mais rápida :) 20 | É uma linguagem que pode ser compilada para todas as plataformas e também possui um interpretador (REPL). 21 | 22 | Basicamente, o objetivo da linguagem é preencher as lacunas do Python em performance e portabilidade. Atualmente o Wlang já tem uma performance muito superior ao Python e pode ser compilada e distribuída para qualquer plataforma, de forma nativa ou não, e utilizando diversos frameworks para parte gráfica como Kha, Cordova, Flutter e Raylib. 23 | 24 | # Demonstração 25 | 26 | Para ter uma idéia de como é a linguagem e como ela se compara as outras, veja esse vídeo [aqui](https://www.youtube.com/watch?v=_8xtTyCTPXI). 27 | 28 | # Estágio ALPHA 29 | 30 | Esta é uma linguagem em desenvolvimento e ainda não está disponível para o público. 31 | 32 | Ta ansioso para testar?? Eu também to ansioso para lançar! Mas infelizmente tenho que dar prioridade a outros projetos que me sustentam. Caso queira ajudar e tornar esse projeto realidade o quanto antes, considere fazer uma doação, virar um membro do canal ou até se inscrever no canal que já ajuda bastante :) 33 | 34 | Para outras formas de contribuição, envie um email para digameoquepensas@gmail.com 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Photon

2 | 3 |

Install on 4 | Convert to 5 | Run in

6 | 7 |

PT-BR Channel 8 | Contributions Welcome 9 | Discord Server

10 | 11 | 12 |
Documentation in English 13 | 14 | Lightning fast and portable programming language! 15 | 16 | ## What is Photon? 17 | 18 | Photon is a programming language aimed at filling the gaps of the Python language with respect to performance and portability. I love Python, but I cannot use it anywhere I want because it is not a supported language of the platform, lacks performance or is very cumbersome to actually package it or deploy it. 19 | Photon applications can run in any platform. Some examples are: Windows, Linux, MacOS, BSD, Android, IOs, RaspberryPi, HTML5, Xbox, Playstation, etc. 20 | 21 | ## I want to see it! 22 | 23 | Devlog is available [here](https://www.youtube.com/watch?v=Seu5q_hc6go&list=PL89TmjrkwpOfteQJRptqmK-y8pr6uJdlc). 24 | I also uploaded a video on my portuguese channel comparing it to Python and C, check it out [here](https://youtu.be/_8xtTyCTPXI). 25 | 26 | ## Quickstart 27 | 28 | Download or clone (preferred) the repository where you want to install it. Execute the windowsInstaller.bat if you are in Windows or linuxInstaller.sh if you are in Linux. After the installation process, you should have photon installed and available in your PATH. 29 | Now you can write this simple Hello World, with any text editor of your choice. 30 | 31 | ```python 32 | print("Hello World!") 33 | ``` 34 | 35 | Save it as hello.w and then execute it in your cmd or powershell with 36 | 37 | ``` 38 | photon hello.w 39 | ``` 40 | 41 | And you should see the Hello World! output in your console! 42 | 43 | In the devlog 1, I show how to install and create your first hello world program. [Click here to see it.](https://www.youtube.com/watch?v=5QtISBpOlr0) 44 | 45 | ## ALPHA Stage 46 | 47 | Photon is currently in early alpha. 48 | If you like this project and want to contribute, please consider donating or subscribing to my youtube [channel](https://www.youtube.com/channel/UChE5M9BAsdtlllOpfhIu8Tw), where I'll post a dev log of this language ([devlog](https://www.youtube.com/watch?v=Seu5q_hc6go&list=PL89TmjrkwpOfteQJRptqmK-y8pr6uJdlc)). 49 | Also, join the discussion here on github about the future and your thoughts on the language! 50 | 51 |
52 | 53 |
Documentação em português 54 | Linguagem de programação extremamente rápida e portátil! 55 | 56 | ## O que é Photon? 57 | 58 | Photon é uma linguagem de programação que visa preencher as lacunas da linguagem Python no que diz respeito ao desempenho e portabilidade. Eu amo Python, mas não posso usá-lo em qualquer lugar que eu queira porque não é uma nativamente suportada, não tem desempenho suficiente ou aprensenta muitas complicações para distribuir um executável na plataforma de destino. 59 | Por outro lado, os aplicativos Photon podem ser facilmente executados em qualquer plataforma. Alguns exemplos são: Windows, Linux, MacOS, BSD, Android, IOs, RaspberryPi, HTML5, Xbox, Playstation, etc. 60 | 61 | ## Quero ver! 62 | 63 | O Devlog está disponível [aqui](https://www.youtube.com/watch?v=Seu5q_hc6go&list=PL89TmjrkwpOfteQJRptqmK-y8pr6uJdlc). 64 | Também carreguei um vídeo no meu canal português comparando-o com Python e C, confira [aqui](https://youtu.be/_8xtTyCTPXI). 65 | 66 | ## Começo rápido 67 | 68 | Baixe ou clone (preferencialmente) o repositório onde deseja instalá-lo. Execute o windowsInstaller.bat se você estiver no Windows ou linuxInstaller.sh se você estiver no Linux. Após o processo de instalação, você deve ter o photon instalado e disponível na sua PATH (como variável do seu sistema). 69 | Agora você pode escrever este simples Hello World, com qualquer editor de texto de sua escolha. 70 | 71 | ```python 72 | print("Olá, mundo!") 73 | ``` 74 | 75 | Salve-o como hello.w e execute-o em seu cmd ou powershell com 76 | 77 | ``` 78 | photon hello.w 79 | ``` 80 | 81 | E você deverá ver o Hello World! em seu console! 82 | 83 | No devlog 1, mostro como instalar e criar seu primeiro programa hello world. [Clique aqui para ver.](Https://www.youtube.com/watch?v=5QtISBpOlr0) 84 | 85 | 86 | ## Estágio ALPHA 87 | 88 | Photon está atualmente em alfa. 89 | Se você gosta deste projeto e deseja contribuir, considere doar ou se inscrever no meu [canal youtube](https://www.youtube.com/channel/UChE5M9BAsdtlllOpfhIu8Tw) , onde postarei um dev log desta linguagem ([devlog](https://www.youtube.com/watch?v=Seu5q_hc6go&list=PL89TmjrkwpOfteQJRptqmK-y8pr6uJdlc)). 90 | Além disso, participe da discussão aqui no github sobre o futuro e sua opinião sobre a linguagem! 91 | 92 |
93 | 94 | 95 | 96 |
Documentación en español 97 | ¡Lenguaje de programación extremadamente rápido y portátil! 98 | 99 | ## ¿Qué es Photon? 100 | 101 | Photon es un lenguaje de programación que tiene como objetivo llenar los vacíos en el lenguaje Python con respecto al rendimiento y la portabilidad. Me encanta Python, pero no puedo usarlo en cualquier lugar que quiera porque no es compatible de forma nativa, no tiene suficiente rendimiento o tiene muchas complicaciones para distribuir un ejecutable en la plataforma de destino. 102 | Por otro lado, las aplicaciones Photon se pueden ejecutar fácilmente en cualquier plataforma. Algunos ejemplos son: Windows, Linux, MacOS, BSD, Android, IOs, RaspberryPi, HTML5, Xbox, Playstation, etc. 103 | 104 | ## ¡Quiero ver! 105 | 106 | El Devlog está disponible [aquí](https://www.youtube.com/watch?v=Your5q_hc6go&list=PL89TmjrkwpOfteQJRptqmK-y8pr6uJdlc). 107 | También subí un video en mi canal portugués comparándolo con Python y C, compruébalo [aquí](https://youtu.be/_8xtTyCTPXI). 108 | 109 | ## Etapa ALPHA 110 | 111 | Photon se encuentra actualmente en alfa. 112 | Si te gusta este proyecto y quieres contribuir, considera hacer una donación o suscribirte a mi [canal de youtube](https://www.youtube.com/channel/UChE5M9BAsdtlllOpfhIu8Tw), donde publicaré un registro de desarrollo de este idioma [devlog](https://www.youtube.com/watch?v=Your5q_hc6go&list=PL89TmjrkwpOfteQJRptqmK-y8pr6uJdlc) 113 | ¡Además, participa en la discusión aquí en github sobre el futuro y tu opinión sobre el lenguaje! 114 | 115 |
116 | -------------------------------------------------------------------------------- /VimSyntaxHighlight/vim/filetype.vim: -------------------------------------------------------------------------------- 1 | " my filetype file 2 | if exists("did_load_filetypes") 3 | finish 4 | endif 5 | 6 | augroup filetypedetect 7 | au! BufRead,BufNewFile *.w setfiletype w 8 | augroup END 9 | -------------------------------------------------------------------------------- /VimSyntaxHighlight/vim/ftdetect/w.vim: -------------------------------------------------------------------------------- 1 | autocmd BufRead,BufNewFile *.w setf=w 2 | -------------------------------------------------------------------------------- /VimSyntaxHighlight/vim/syntax/w.vim: -------------------------------------------------------------------------------- 1 | " Wlang syntax highlight for Vim - Version 0.1 2 | " Author: Will - HashLDash 3 | 4 | set termguicolors 5 | 6 | " Quit when a syntax file was already loaded. 7 | if exists('b:current_syntax') | finish| endif 8 | 9 | syntax match wVar "\k\+" 10 | syntax match wNumber "\v<\d+>" 11 | syntax match wNumber "\v<\d+\.\d+>" 12 | syntax match wNumber "\v<\d*\.?\d+([Ee]-?)?\d+>" 13 | syntax match wNumber "\v<0x\x+([Pp]-?)?\x+>" 14 | syntax match wNumber "\v<0b[01]+>" 15 | syntax match wNumber "\v<0o\o+>" 16 | syntax match wNumber " *True" 17 | syntax match wNumber " *False" 18 | syntax match wNumber " *null" 19 | syntax region wString start=/\v"/ skip=/\v(\\[\\"]){-1}/ end=/\v"/ 20 | syntax region wString start=/\v'/ end=/\v'/ 21 | syntax match wComment " *#.*$" 22 | syntax match wFuncName "\v[[:alpha:]_.]+\ze(\s?\()" 23 | syntax keyword wStatement class def cdef if elif else for in return not while and or break continue del 24 | syntax match wBuiltinFunc "\v(len|print|time|open|collidedRecs|collidedPointRec|uniform|randInt|choose|post|chop|exitApp|localSetItem|localGetItem|localClear|abs|decimal|pass)+\ze(\s?\()" 25 | syntax keyword wBuiltinFunc native import from 26 | syntax keyword wTypes str cstr int float func struct const char double 27 | syntax keyword wPlatforms android Android HTML5 html5 linux Linux Web C c Python python Py py JS js JavaScript 28 | 29 | hi def link wVar ModeMsg 30 | hi def link wString String 31 | hi wNumber ctermfg=Magenta guifg=#FFAAFF cterm=bold 32 | hi wComment ctermfg=DarkGray 33 | hi wFuncName ctermfg=Cyan guifg=#33BBCC cterm=bold 34 | hi wStatement ctermfg=Yellow guifg=#FFFF77 cterm=bold 35 | hi wTypes ctermfg=Blue guifg=#8888FF cterm=bold 36 | hi wBuiltinFunc ctermfg=Blue guifg=#4466FF cterm=bold 37 | hi def link wPlatforms Type 38 | 39 | let b:current_syntax = 'w' 40 | -------------------------------------------------------------------------------- /art/Guidelines.txt: -------------------------------------------------------------------------------- 1 | 2 | English: 3 | - Logos must be unique 4 | - Don't use images from the internet in the design 5 | - Logos that are similar to other logos will not be added 6 | - Save your logo ideas into a separate svg file (You can add as many ideas as you want in your svg file) 7 | - If you followed all of these guidelines, send a PR 8 | 9 | Português: 10 | - Os logotipos devem ser únicos 11 | - Não use imagens da internet no design 12 | - Logotipos semelhantes a outros logotipos não serão adicionados 13 | - Salve suas ideias de logotipo em um arquivo SVG separado (você pode adicionar quantas ideias quiser em seu arquivo SVG) 14 | - Se você seguiu todas essas diretrizes, envie um PR 15 | -------------------------------------------------------------------------------- /art/logo1.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 38 | 40 | 41 | 43 | image/svg+xml 44 | 46 | 47 | 48 | 49 | 50 | 54 | 62 | 66 | 74 | 78 | 82 | 86 | 94 | 101 | 108 | 115 | 122 | 129 | 136 | 143 | 150 | 157 | 164 | 171 | 178 | 185 | 192 | 199 | 206 | 213 | 220 | 227 | 234 | 241 | 248 | 255 | 262 | 263 | 264 | -------------------------------------------------------------------------------- /core/assets/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /core/assets/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/core/assets/Roboto-Bold.ttf -------------------------------------------------------------------------------- /core/assets/Roboto-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/core/assets/Roboto-BoldItalic.ttf -------------------------------------------------------------------------------- /core/assets/Roboto-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/core/assets/Roboto-Italic.ttf -------------------------------------------------------------------------------- /core/builder.py: -------------------------------------------------------------------------------- 1 | # Photon builder 2 | # This script is used to generate a Photon project 3 | # according to the target platform and preferences 4 | # Each target is handled by its Toolchain 5 | 6 | import sys 7 | 8 | class Builder(): 9 | def __init__(self, platform, filename="main.w", standardLibs='', **kwargs): 10 | print(f'Platform: {platform}') 11 | print(f'Filename: {filename}') 12 | if platform == 'shared': 13 | from toolchains.shared import Toolchain 14 | else: 15 | print('This platform is not supported yet.') 16 | sys.exit() 17 | Toolchain(platform, filename=filename, standardLibs=standardLibs).getBuildFiles() 18 | Toolchain(platform, filename=filename, standardLibs=standardLibs).transpile() 19 | Toolchain(platform, filename=filename, standardLibs=standardLibs).prepare() 20 | Toolchain(platform, filename=filename, standardLibs=standardLibs).make() 21 | Toolchain(platform, filename=filename, standardLibs=standardLibs).runProject() 22 | -------------------------------------------------------------------------------- /core/dependencies.py: -------------------------------------------------------------------------------- 1 | ''' Install all dependencies for running projects with 2 | the corresponding language on the target platform. ''' 3 | 4 | import os 5 | import sys 6 | 7 | UPDATED_REPO = False 8 | 9 | def commandName(package): 10 | ''' Return the command line name of the given package ''' 11 | if package == 'nodejs': 12 | return 'node' 13 | return package 14 | 15 | def haveDependencies(lang, platform): 16 | ''' Return True if all dependencies are installed 17 | for the corresponding lang and platform or 18 | False otherwise. ''' 19 | for dep in deps[(lang, platform)]: 20 | if not programIsInstalled(dep): 21 | break 22 | else: 23 | return True 24 | print('Some dependencies must be installed for this target language.') 25 | return False 26 | 27 | def resolveDependencies(lang, platform): 28 | ''' Run the corresponding dependency solver. ''' 29 | global solver 30 | solver[(lang, platform)]() 31 | #TODO: Check if the installation was successful 32 | # or print the error message and terminate the program 33 | 34 | def getSystem(): 35 | ''' Obtains a simple description of the current operating system platform. ''' 36 | if sys.platform in {'linux', 'linux2', 'darwin'}: 37 | return "unix" 38 | elif os.name == "nt" or os.environ.get('OS', '') != 'Windows_NT' or sys.platform in {'win32', 'cygwin', 'msys'}: 39 | return "win" 40 | return None 41 | 42 | def programIsInstalled(name): 43 | ''' Verify if program is installed it system. ''' 44 | try: 45 | platform_os = getSystem() 46 | if platform_os == "win": 47 | return str(os.popen(f'where /q {name} && echo %ERRORLEVEL%').read()).strip() == "0" 48 | elif platform_os == "unix": 49 | return str(os.popen(f'command -v {name}').read()).strip() != "" 50 | else: 51 | raise Exception('`platform_os` not supported') 52 | except Exception as e: 53 | print(f"error: {e}") 54 | return False 55 | 56 | # INIT - Installer for Win32/Windows (Chocolatey) 57 | def powershellIsInstalled(): 58 | if programIsInstalled("powershell"): 59 | print("# PowerShell is installed!") 60 | return True 61 | else: 62 | print("# PowerShell was not found!") 63 | return False 64 | 65 | def chocoIsInstalled(): 66 | if programIsInstalled("choco"): 67 | print("# Chocolatey is installed!") 68 | return True 69 | else: 70 | print("# Chocolatey was not found!") 71 | return False 72 | 73 | def chocoInstall(): 74 | if not powershellIsInstalled(): 75 | return False 76 | if chocoIsInstalled(): 77 | return True 78 | shell_exec_cmd = "powershell -Command \"Start-Process powershell -Verb RunAs -PassThru -Wait -ArgumentList \\\"/c Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')); ; timeout /t 5; exit\\\"\"" 79 | print('# Installing Chocolatey - Command: \r\n') 80 | print(f'{shell_exec_cmd}\r\n') 81 | print('# Result:') 82 | print(str(os.popen(shell_exec_cmd).read())) 83 | return chocoIsInstalled() 84 | 85 | def chocoInstaller(name): 86 | if not chocoInstall(): 87 | return False 88 | shell_exec_cmd = "powershell -Command \"Start-Process powershell -Verb RunAs -PassThru -Wait -ArgumentList \\\"/c choco install " + name + "; timeout /t 5; exit\\\"\"" 89 | print('# Installing dependency with Chocolatey - Command: \r\n') 90 | print(f'{shell_exec_cmd}\r\n') 91 | print('# Result:') 92 | print(str(os.popen(shell_exec_cmd).read())) 93 | return True 94 | 95 | # INIT - Installer for Darwin/macOS (HomeBrew) 96 | 97 | def brewInstall(): 98 | if not programIsInstalled('bash'): 99 | return False 100 | if programIsInstalled('brew'): 101 | return True 102 | shell_exec_cmd = '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' 103 | print('# Installing HomeBrew - Command: \r\n') 104 | print(f'{shell_exec_cmd}\r\n') 105 | print('# Result:') 106 | print(str(os.popen(shell_exec_cmd).read())) 107 | return brewIsInstalled() 108 | 109 | def brewInstaller(name): 110 | shell_exec_cmd = "" 111 | if not brewInstall(): 112 | return False 113 | if name == "dart": 114 | shell_exec_cmd = "brew tap dart-lang/dart; " 115 | shell_exec_cmd += f'brew install {name}' 116 | print('# Installing dependency with HomeBrew - Command: \r\n') 117 | print(f'{shell_exec_cmd}\r\n') 118 | print('# Result:') 119 | print(str(os.popen(shell_exec_cmd).read())) 120 | return True 121 | 122 | # INIT - Installers for Linux (APT, PACMAN, EMERGE, ZYPPER and DNF) 123 | linux_cmds = {'dmd': 'curl https://dlang.org/install.sh | bash -s || (mkdir -p ~/dlang && wget ' 124 | 'https://dlang.org/install.sh -O ~/dlang/install.sh && chmod +x ~/dlang/install.sh && ' 125 | '~/dlang/install.sh)'} 126 | linux_cmds['node prompt-sync'] = 'sudo npm install -g prompt-sync' 127 | win_cmds = {'node prompt-sync': 'npm install prompt-sync'} 128 | linux_cmds['deno'] = 'curl -fsSL https://deno.land/x/install/install.sh | sudo DENO_INSTALL=/usr/local sh' 129 | if os.path.exists('/etc/debian_version'): # debian, ubuntu, pop!_os, zorin os 130 | linux_cmds['before'] = 'sudo apt-get update' 131 | linux_cmds['gcc'] = 'sudo apt install build-essential' 132 | linux_cmds['dmd'] = 'sudo wget https://netcologne.dl.sourceforge.net/project/d-apt/files/d-apt.list -O ' \ 133 | '/etc/apt/sources.list.d/d-apt.list && sudo apt-get update --allow-insecure-repositories && ' \ 134 | 'sudo apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring && sudo apt-get ' \ 135 | 'update && sudo apt install dmd-compiler dub libcurl3 libphobos2-79 libphobos2-dev ' 136 | linux_cmds['haxe'] = 'sudo apt-get install haxe && mkdir ~/haxelib && haxelib setup ~/haxelib' 137 | linux_cmds['nodejs'] = 'sudo apt install nodejs' 138 | linux_cmds['dart'] = "sudo apt-get install apt-transport-https && sudo sh -c 'wget -qO- " \ 139 | "https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' && sudo sh -c 'wget " \ 140 | "-qO- https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > " \ 141 | "/etc/apt/sources.list.d/dart_stable.list' && sudo apt-get update && sudo apt-get install " \ 142 | "dart " 143 | elif os.path.exists('/etc/arch-release'): # arch, manjaro 144 | linux_cmds['before'] = 'sudo pacman -Syy' 145 | linux_cmds['gcc'] = 'sudo pacman -S gcc' 146 | linux_cmds['dmd'] = 'sudo pacman -S dmd' 147 | linux_cmds['haxe'] = 'sudo pacman -S haxe' 148 | linux_cmds['nodejs'] = 'sudo pacman -S nodejs' 149 | linux_cmds['deno'] = 'sudo pacman -S deno' 150 | linux_cmds['npm'] = 'sudo pacman -S npm' 151 | linux_cmds['dart'] = 'sudo pacman -S dart' 152 | elif os.path.exists('/etc/gentoo-release'): # gentoo 153 | linux_cmds['before'] = 'sudo emerge --sync' 154 | linux_cmds['gcc'] = 'sudo emerge sys-devel/gcc' 155 | linux_cmds['dmd'] = 'sudo emerge app-portage/layman && sudo layman -f -a dlang && sudo emerge dev-lang/dmd' 156 | linux_cmds['nodejs'] = 'sudo emerge nodejs' 157 | elif os.path.exists('/etc/SuSE-release'): # opensuse 158 | linux_cmds['before'] = 'sudo zypper refresh' 159 | linux_cmds['gcc'] = 'sudo zypper install gcc' 160 | linux_cmds['haxe'] = 'sudo zypper install haxe && mkdir ~/haxelib && haxelib setup ~/haxelib' 161 | linux_cmds['nodejs'] = 'sudo zypper install nodejs4' 162 | elif os.path.exists('/etc/redhat-release'): # red hat, centos, fedora 163 | linux_cmds['before'] = 'sudo dnf check-update; sudo yum check-update' 164 | linux_cmds['gcc'] = 'sudo dnf install gcc || sudo yum install gcc' 165 | linux_cmds['haxe'] = '(sudo dnf install haxe || (sudo yum install epel-release; sudo yum install haxe)) && mkdir ' \ 166 | '~/haxelib && haxelib setup ~/haxelib' 167 | linux_cmds['nodejs'] = 'sudo dnf module install nodejs:12' 168 | 169 | def linuxInstaller(package): 170 | global UPDATED_REPO 171 | if package in linux_cmds: 172 | if 'before' in linux_cmds and not UPDATED_REPO: 173 | os.system(f'sh -c "{linux_cmds["before"]}"') 174 | UPDATED_REPO = True 175 | 176 | shell_exec_cmd = f'sh -c "{linux_cmds[package]}"' 177 | print('# Installing dependency - Command: \r\n') 178 | print(f'{shell_exec_cmd}\r\n') 179 | print('# Result:') 180 | os.system(shell_exec_cmd) 181 | else: 182 | print(f"We couldn't try to automatically install `{package}`, please install it manually.") 183 | return False 184 | 185 | if programIsInstalled(commandName(package)): 186 | print(f'Dependency `{package}` has been successfully installed!') 187 | return True 188 | else: 189 | print(f'Dependency `{package}` was not found.') 190 | return False 191 | 192 | # INIT - Linux 193 | def resolveCLinux(): 194 | ''' Install gcc ''' 195 | return linuxInstaller('gcc') 196 | 197 | def resolvePyLinux(): 198 | ''' Install python ''' 199 | return linuxInstaller('python') 200 | 201 | def resolveDLinux(): 202 | ''' Install dmd ''' 203 | return linuxInstaller('dmd') 204 | 205 | def resolveHaxeLinux(): 206 | ''' Install haxe ''' 207 | return linuxInstaller('haxe') 208 | 209 | def resolveJsLinux(): 210 | ''' Install nodejs and deps ''' 211 | return linuxInstaller('nodejs') and linuxInstaller('npm') and linuxInstaller('node prompt-sync') 212 | 213 | def resolveTsLinux(): 214 | ''' Install deno and deps ''' 215 | return linuxInstaller('deno') 216 | 217 | def resolveDartLinux(): 218 | ''' Install dart ''' 219 | return linuxInstaller('dart') 220 | 221 | # INIT - Win32 222 | def resolveCWin32(): 223 | ''' Install gcc ''' 224 | chocoInstaller("mingw") 225 | return programIsInstalled("gcc") 226 | 227 | def resolvePyWin32(): 228 | ''' Install python ''' 229 | chocoInstaller("python") 230 | return programIsInstalled("python") 231 | 232 | def resolveDWin32(): 233 | ''' Install dmd ''' 234 | chocoInstaller("dmd") 235 | return programIsInstalled("dmd") 236 | 237 | def resolveHaxeWin32(): 238 | ''' Install haxe ''' 239 | chocoInstaller("haxe") 240 | return programIsInstalled("haxe") 241 | 242 | def resolveJsWin32(): 243 | ''' Install nodejs ''' 244 | chocoInstaller("nodejs") # npm is also installed with nodejs 245 | os.system(win_cmds["node prompt-sync"]) 246 | return programIsInstalled("node") and programIsInstalled("npm") 247 | 248 | def resolveTsWin32(): 249 | ''' Install deno ''' 250 | chocoInstaller("deno") 251 | return programIsInstalled("deno") 252 | 253 | def resolveDartWin32(): 254 | ''' Install dart ''' 255 | chocoInstaller("dart-sdk") 256 | return programIsInstalled("dart") 257 | 258 | # INIT - Darwin 259 | def resolveCDarwin(): 260 | ''' Install gcc ''' 261 | brewInstaller("gcc") 262 | return programIsInstalled("gcc") 263 | 264 | def resolvePyDarwin(): 265 | ''' Install gcc ''' 266 | brewInstaller("gcc") 267 | return programIsInstalled("gcc") 268 | 269 | def resolveDDarwin(): 270 | ''' Install dmd ''' 271 | brewInstaller("dmd") 272 | return programIsInstalled("dmd") 273 | 274 | def resolveHaxeDarwin(): 275 | ''' Install haxe ''' 276 | brewInstaller("haxe") 277 | return programIsInstalled("haxe") 278 | 279 | def resolveJsDarwin(): 280 | ''' Install nodejs ''' 281 | brewInstaller("nodejs") 282 | brewInstaller("npm") 283 | os.system(linux_cmds["node prompt-sync"]) 284 | return programIsInstalled("node") and programIsInstalled("npm") 285 | 286 | def resolveTsDarwin(): 287 | ''' Install deno ''' 288 | brewInstaller("deno") 289 | return programIsInstalled("deno") 290 | 291 | def resolveDartDarwin(): 292 | ''' Install dart ''' 293 | brewInstaller("dart") 294 | return programIsInstalled("dart") 295 | 296 | solver = { 297 | ('c', 'linux'): resolveCLinux, 298 | ('c', 'win32'): resolveCWin32, 299 | ('c', 'darwin'): resolveCDarwin, 300 | ('python', 'linux'): resolvePyLinux, 301 | ('python', 'win32'): resolvePyWin32, 302 | ('python', 'darwin'): resolvePyDarwin, 303 | ('d', 'linux'): resolveDLinux, 304 | ('d', 'win32'): resolveDWin32, 305 | ('d', 'darwin'): resolveDDarwin, 306 | ('haxe', 'linux'): resolveHaxeLinux, 307 | ('haxe', 'win32'): resolveHaxeWin32, 308 | ('haxe', 'darwin'): resolveHaxeDarwin, 309 | ('js', 'linux'): resolveJsLinux, 310 | ('js', 'win32'): resolveJsWin32, 311 | ('js', 'darwin'): resolveJsDarwin, 312 | ('ts', 'linux'): resolveTsLinux, 313 | ('ts', 'win32'): resolveTsWin32, 314 | ('ts', 'darwin'): resolveTsDarwin, 315 | ('dart', 'linux'): resolveDartLinux, 316 | ('dart', 'win32'): resolveDartWin32, 317 | ('dart', 'darwin'): resolveDartDarwin, 318 | } 319 | 320 | deps = { 321 | ('c', 'linux'): ['gcc'], 322 | ('c', 'win32'): ['gcc'], 323 | ('c', 'darwin'): ['gcc'], 324 | ('python', 'linux'): ['python'], 325 | ('python', 'win32'): ['python'], 326 | ('python', 'darwin'): ['python'], 327 | ('d', 'linux'): ['dmd'], 328 | ('d', 'win32'): ['dmd'], 329 | ('d', 'darwin'): ['dmd'], 330 | ('haxe', 'linux'): ['haxe'], 331 | ('haxe', 'win32'): ['haxe'], 332 | ('haxe', 'darwin'): ['haxe'], 333 | ('js', 'linux'): ['node','npm'], 334 | ('js', 'win32'): ['node','npm'], 335 | ('js', 'darwin'): ['node','npm'], 336 | ('ts', 'linux'): ['deno'], 337 | ('ts', 'win32'): ['deno'], 338 | ('ts', 'darwin'): ['deno'], 339 | ('dart', 'linux'): ['dart'], 340 | ('dart', 'win32'): ['dart'], 341 | ('dart', 'darwin'): ['dart'], 342 | } 343 | -------------------------------------------------------------------------------- /core/engines/pyEngine.py: -------------------------------------------------------------------------------- 1 | from transpilers.pyTranspiler import Transpiler 2 | from transpilers.pyTokens import Sequence, Print 3 | import os 4 | 5 | def debug(*args): 6 | #print(*args) 7 | pass 8 | 9 | class Engine(): 10 | def __init__(self, filename, **kwargs): 11 | self.transpiler = Transpiler(filename, **kwargs) 12 | self.globals = {} 13 | self.importedLibs = set() 14 | 15 | def process(self, token): 16 | if token: 17 | self.transpiler.process(token) 18 | for lib in self.transpiler.imports - self.importedLibs: 19 | bytecode = compile(lib,'','exec') 20 | exec(bytecode, self.globals, self.globals) 21 | self.importedLibs.add(lib) 22 | try: 23 | if token['token'] in {'expr'}: 24 | code = repr(Print(args=[self.transpiler.sequence[-1]])) 25 | bytecode = compile(code,'','exec') 26 | exec(bytecode, self.globals, self.globals) 27 | else: 28 | code = repr(self.transpiler.sequence[-1]) 29 | bytecode = compile(code,'','exec') 30 | exec(code, self.globals, self.globals) 31 | except Exception as e: 32 | print(f'RuntimeError: {e}') 33 | #self.transpiler.sequence = Sequence() 34 | #self.transpiler.imports = set() 35 | -------------------------------------------------------------------------------- /core/grammar/genGrammar.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | from itertools import product 4 | from pprint import pprint 5 | 6 | try: 7 | grammar = sys.argv[1] 8 | except: 9 | print('Please, provide a grammar') 10 | sys.exit() 11 | 12 | def genRules(val): 13 | vals = [ i for i in re.split('(\W)', val) if not (i=='' or i==' ' or i=='\n') ] 14 | terms = [] 15 | current = [] 16 | inGroup = False 17 | for v in vals: 18 | if v == ')': 19 | terms.append(tuple(current)) 20 | current = [] 21 | inGroup = False 22 | elif v == '(': 23 | inGroup = True 24 | elif inGroup: 25 | current.append(v) 26 | else: 27 | terms.append((v,)) 28 | return list(product(*terms)) 29 | 30 | def createGrammar(grammar): 31 | with open('generatedGrammar.py', 'w') as g: 32 | g.write('patterns = {\n') 33 | for feature, patterns in grammar.items(): 34 | for pattern in patterns: 35 | g.write(f' {pattern}: {feature},\n') 36 | g.write('}') 37 | 38 | with open(grammar, 'r') as g: 39 | generated = {} 40 | inDefinition = '' 41 | patterns = [] 42 | for l in g: 43 | if l.startswith('#'): 44 | continue 45 | if '=' in l: 46 | if patterns: 47 | generated[inDefinition] = list(patterns) 48 | patterns = [] 49 | definition, val = l.split('=') 50 | inDefinition = definition.strip() 51 | patterns += genRules(val) 52 | elif l.strip().startswith('|'): 53 | patterns += genRules(l.strip()[1:]) 54 | if patterns: 55 | generated[inDefinition] = list(patterns) 56 | patterns = [] 57 | createGrammar(generated) 58 | -------------------------------------------------------------------------------- /core/grammar/generatedGrammar.py: -------------------------------------------------------------------------------- 1 | patterns = { 2 | ('hashtag',): comment, 3 | ('singleQuote',): string, 4 | ('doubleQuote',): string, 5 | ('type', 'lbracket', 'rbracket', 'var'): arrayType, 6 | ('type', 'lbracket', 'rbracket', 'space'): arrayType, 7 | ('var', 'lbracket', 'rbracket', 'var'): arrayType, 8 | ('var', 'lbracket', 'rbracket', 'space'): arrayType, 9 | ('expr', 'lbracket', 'rbracket', 'var'): arrayType, 10 | ('expr', 'lbracket', 'rbracket', 'space'): arrayType, 11 | ('type', 'lbracket', 'num', 'rbracket', 'var'): arrayType, 12 | ('type', 'lbracket', 'num', 'rbracket', 'space'): arrayType, 13 | ('var', 'lbracket', 'num', 'rbracket', 'var'): arrayType, 14 | ('var', 'lbracket', 'num', 'rbracket', 'space'): arrayType, 15 | ('expr', 'lbracket', 'num', 'rbracket', 'var'): arrayType, 16 | ('expr', 'lbracket', 'num', 'rbracket', 'space'): arrayType, 17 | ('type', 'beginBlock', 'type'): mapType, 18 | ('type', 'beginBlock', 'var'): mapType, 19 | ('var', 'beginBlock', 'type'): mapType, 20 | ('var', 'beginBlock', 'var'): mapType, 21 | ('var', 'underline', 'var'): var, 22 | ('underline', 'var'): var, 23 | ('var', 'underline'): var, 24 | ('underline',): var, 25 | ('num', 'dot', 'num'): floatNumber, 26 | ('num', 'dot'): floatNumber, 27 | ('expr', 'dot', 'expr'): dotAccess, 28 | ('type', 'space', 'dot', 'expr'): dotAccess, 29 | ('expr', 'space', 'dot', 'expr'): dotAccess, 30 | ('dot', 'expr'): dotAccess, 31 | ('type', 'var'): typeDeclaration, 32 | ('expr', 'var'): typeDeclaration, 33 | ('lparen', 'expr', 'rparen'): group, 34 | ('equal', 'equal'): operator, 35 | ('equal', 'operator'): operator, 36 | ('operator', 'equal'): operator, 37 | ('operator', 'operator'): operator, 38 | ('type', 'lparen', 'expr', 'rparen'): cast, 39 | ('expr', 'lparen', 'rparen'): call, 40 | ('expr', 'lparen', 'expr', 'rparen'): call, 41 | ('expr', 'lparen', 'args', 'rparen'): call, 42 | ('expr', 'lparen', 'assign', 'rparen'): call, 43 | ('expr', 'lparen', 'kwargs', 'rparen'): call, 44 | ('expr', 'lparen', 'expr', 'comma', 'assign', 'rparen'): call, 45 | ('expr', 'lparen', 'expr', 'comma', 'kwargs', 'rparen'): call, 46 | ('expr', 'lparen', 'args', 'comma', 'assign', 'rparen'): call, 47 | ('expr', 'lparen', 'args', 'comma', 'kwargs', 'rparen'): call, 48 | ('num',): expr, 49 | ('floatNumber',): expr, 50 | ('var',): expr, 51 | ('dotAccess',): expr, 52 | ('group',): expr, 53 | ('num', 'operator', 'num'): expr, 54 | ('num', 'operator', 'var'): expr, 55 | ('num', 'operator', 'expr'): expr, 56 | ('var', 'operator', 'num'): expr, 57 | ('var', 'operator', 'var'): expr, 58 | ('var', 'operator', 'expr'): expr, 59 | ('expr', 'operator', 'num'): expr, 60 | ('expr', 'operator', 'var'): expr, 61 | ('expr', 'operator', 'expr'): expr, 62 | ('operator', 'expr'): expr, 63 | ('expr', 'beginBlock', 'expr'): keyVal, 64 | ('keyVals', 'comma', 'keyVal'): keyVals, 65 | ('keyVals', 'comma', 'keyVals'): keyVals, 66 | ('keyVal', 'comma', 'keyVal'): keyVals, 67 | ('keyVal', 'comma', 'keyVals'): keyVals, 68 | ('expr', 'lbracket', 'expr', 'rbracket'): indexAccess, 69 | ('lbracket', 'args', 'rbracket'): array, 70 | ('lbracket', 'expr', 'rbracket'): array, 71 | ('lbracket', 'rbracket'): array, 72 | ('lbrace', 'rbrace'): hashmap, 73 | ('lbrace', 'keyVal', 'rbrace'): hashmap, 74 | ('lbrace', 'keyVals', 'rbrace'): hashmap, 75 | ('returnStatement',): funcReturn, 76 | ('returnStatement', 'expr'): funcReturn, 77 | ('expr', 'dot', 'dot', 'expr'): rangeExpr, 78 | ('expr', 'dot', 'dot', 'expr', 'dot', 'dot', 'expr'): rangeExpr, 79 | ('ifStatement', 'expr', 'beginBlock'): ifelif, 80 | ('elifStatement', 'expr', 'beginBlock'): ifelif, 81 | ('forStatement', 'args', 'inStatement', 'range', 'beginBlock'): forLoop, 82 | ('forStatement', 'args', 'inStatement', 'expr', 'beginBlock'): forLoop, 83 | ('forStatement', 'expr', 'inStatement', 'range', 'beginBlock'): forLoop, 84 | ('forStatement', 'expr', 'inStatement', 'expr', 'beginBlock'): forLoop, 85 | ('forStatement', 'expr', 'beginBlock'): forTarget, 86 | ('whileStatement', 'expr', 'beginBlock'): whileLoop, 87 | ('args', 'comma', 'args'): args, 88 | ('args', 'comma', 'expr'): args, 89 | ('expr', 'comma', 'args'): args, 90 | ('expr', 'comma', 'expr'): args, 91 | ('assign', 'comma', 'assign'): kwargs, 92 | ('assign', 'comma', 'kwargs'): kwargs, 93 | ('kwargs', 'comma', 'assign'): kwargs, 94 | ('kwargs', 'comma', 'kwargs'): kwargs, 95 | ('expr', 'operator', 'equal', 'expr'): augAssign, 96 | ('expr', 'equal', 'expr'): assign, 97 | ('fromStatement', 'expr', 'importStatement', 'expr'): fromImport, 98 | ('fromStatement', 'expr', 'importStatement', 'args'): fromImport, 99 | ('fromStatement', 'expr', 'importStatement', 'operator'): fromImport, 100 | ('nativeStatement', 'importStatement', 'expr'): imports, 101 | ('importStatement', 'expr'): imports, 102 | ('delStatement', 'expr'): delete, 103 | ('defStatement', 'expr', 'lparen', 'expr', 'rparen', 'beginBlock'): function, 104 | ('defStatement', 'expr', 'lparen', 'args', 'rparen', 'beginBlock'): function, 105 | ('defStatement', 'expr', 'lparen', 'assign', 'rparen', 'beginBlock'): function, 106 | ('defStatement', 'expr', 'lparen', 'kwargs', 'rparen', 'beginBlock'): function, 107 | ('defStatement', 'expr', 'lparen', 'expr', 'comma', 'assign', 'rparen', 'beginBlock'): function, 108 | ('defStatement', 'expr', 'lparen', 'expr', 'comma', 'kwargs', 'rparen', 'beginBlock'): function, 109 | ('defStatement', 'expr', 'lparen', 'args', 'comma', 'assign', 'rparen', 'beginBlock'): function, 110 | ('defStatement', 'expr', 'lparen', 'args', 'comma', 'kwargs', 'rparen', 'beginBlock'): function, 111 | ('defStatement', 'expr', 'lparen', 'rparen', 'beginBlock'): function, 112 | ('classStatement', 'expr', 'lparen', 'rparen', 'beginBlock'): classDefinition, 113 | ('classStatement', 'expr', 'lparen', 'expr', 'rparen', 'beginBlock'): classDefinition, 114 | ('classStatement', 'expr', 'lparen', 'args', 'rparen', 'beginBlock'): classDefinition, 115 | ('open', 'lparen', 'args', 'rparen'): openFunc, 116 | ('open', 'lparen', 'expr', 'rparen'): openFunc, 117 | ('input', 'lparen', 'expr', 'rparen'): inputFunc, 118 | ('input', 'lparen', 'rparen'): inputFunc, 119 | } -------------------------------------------------------------------------------- /core/grammar/grammar: -------------------------------------------------------------------------------- 1 | comment = hashtag 2 | 3 | string = singleQuote 4 | | doubleQuote 5 | 6 | arrayType = (type var expr) lbracket rbracket (var space) 7 | | (type var expr) lbracket num rbracket (var space) 8 | 9 | mapType = (type var) beginBlock (type var) 10 | 11 | var = var underline var 12 | | underline var 13 | | var underline 14 | | underline 15 | 16 | floatNumber = num dot num 17 | | num dot 18 | 19 | dotAccess = expr dot expr 20 | | (type expr) space dot expr 21 | | dot expr 22 | 23 | typeDeclaration = (type expr) var 24 | 25 | group = lparen expr rparen 26 | 27 | operator = (equal operator) (equal operator) 28 | 29 | cast = type lparen (expr) rparen 30 | 31 | call = expr lparen rparen 32 | | expr lparen (expr args assign kwargs) rparen 33 | | expr lparen (expr args) comma (assign kwargs) rparen 34 | 35 | expr = num 36 | | floatNumber 37 | | var 38 | | dotAccess 39 | | group 40 | | (num var expr) operator (num var expr) 41 | | operator (expr) 42 | 43 | keyVal = expr beginBlock expr 44 | 45 | keyVals = (keyVals keyVal) comma (keyVal keyVals) 46 | 47 | indexAccess = expr lbracket (expr) rbracket 48 | 49 | array = lbracket (args expr) rbracket 50 | | lbracket rbracket 51 | 52 | hashmap = lbrace rbrace 53 | | lbrace (keyVal keyVals) rbrace 54 | 55 | funcReturn = returnStatement 56 | | returnStatement expr 57 | 58 | rangeExpr = expr dot dot expr 59 | | expr dot dot expr dot dot expr 60 | 61 | ifelif = (ifStatement elifStatement) expr beginBlock 62 | 63 | forLoop = forStatement (args expr) inStatement (range expr) beginBlock 64 | 65 | forTarget = forStatement expr beginBlock 66 | 67 | whileLoop = whileStatement expr beginBlock 68 | 69 | args = (args expr) comma (args expr) 70 | 71 | kwargs = (assign kwargs) comma (assign kwargs) 72 | 73 | augAssign = expr operator equal expr 74 | 75 | assign = expr equal expr 76 | 77 | fromImport = fromStatement expr importStatement (expr args operator) 78 | 79 | imports = nativeStatement importStatement expr 80 | | importStatement expr 81 | 82 | delete = delStatement expr 83 | 84 | function = defStatement expr lparen (expr args assign kwargs) rparen beginBlock 85 | | defStatement expr lparen (expr args) comma (assign kwargs) rparen beginBlock 86 | | defStatement expr lparen rparen beginBlock 87 | 88 | classDefinition = classStatement expr lparen rparen beginBlock 89 | | classStatement expr lparen (expr args) rparen beginBlock 90 | 91 | openFunc = open lparen (args expr) rparen 92 | 93 | inputFunc = input lparen (expr) rparen 94 | | input lparen rparen 95 | -------------------------------------------------------------------------------- /core/interpreter.py: -------------------------------------------------------------------------------- 1 | # Photon Interpreter 2 | # 3 | # This script funcion is: 4 | # - Get lines of code from a file or interpreter 5 | # - Call the parser to generate tokens and the struct 6 | # - Call the engine to Process the struct 7 | # - Run the processed struct 8 | 9 | from photonParser import parse, assembly, showError 10 | from photonParser import debug as debugFunc 11 | import sys 12 | 13 | class Interpreter(): 14 | def __init__(self, filename='', lang='c', platform=sys.platform, framework='', module=False, standardLibs='', debug=False, transpileOnly=False): 15 | self.debug = debug 16 | if lang == 'c': 17 | from transpilers.cTranspiler import Transpiler 18 | elif lang in {'py', 'python'}: 19 | from transpilers.pyTranspiler import Transpiler 20 | elif lang == 'dart': 21 | from transpilers.dartTranspiler import Transpiler 22 | elif lang in ['js', 'javascript']: 23 | from transpilers.jsTranspiler import Transpiler 24 | elif lang == 'ts': 25 | from transpilers.tsTranspiler import Transpiler 26 | elif lang == 'haxe': 27 | from transpilers.haxeTranspiler import Transpiler 28 | elif lang == 'd': 29 | from transpilers.dTranspiler import Transpiler 30 | else: 31 | print(f'Invalid language {lang}') 32 | sys.exit() 33 | self.filename = filename 34 | if filename: 35 | self.engine = Transpiler(filename=filename, platform=platform, framework=framework, module=module, standardLibs=standardLibs, debug=debug) 36 | self.input = self.file 37 | try: 38 | # Read utf8 but write as the default on the OS 39 | with open(filename,'r',encoding='utf8') as f: 40 | self.source = [line for line in f] 41 | except UnicodeDecodeError: 42 | with open(filename,'r') as f: 43 | self.source = [line for line in f] 44 | except FileNotFoundError as e: 45 | print(f"File not found: can't open file {filename}: {e}") 46 | sys.exit() 47 | else: 48 | try: 49 | import readline 50 | except ModuleNotFoundError: 51 | # Windows doesn't have readline 52 | try: 53 | import pyreadline 54 | except ModuleNotFoundError: 55 | # Run without history and arrow key functionality 56 | pass 57 | from engines.pyEngine import Engine 58 | self.engine = Engine(filename=filename, platform=platform, framework=framework, module=module, standardLibs=standardLibs) 59 | self.input = self.console 60 | self.end = False 61 | self.processing = True 62 | self.transpileOnly = transpileOnly 63 | self.lineNumber = 0 64 | 65 | def console(self, glyph='>>> '): 66 | return input(glyph) 67 | 68 | def file(self, *args): 69 | try: 70 | line = self.source.pop(0) 71 | self.lineNumber += 1 72 | while line.strip() == '': 73 | line = self.source.pop(0) 74 | self.lineNumber += 1 75 | rest = '' 76 | count = 1 # checking where is the end of the function call. When it ends, count is 0 77 | while line[-2:] in {'(\n',',\n','{\n','[\n'} or rest.lstrip() in {')\n',']\n','}\n'} and count > 0: 78 | line = line.replace('\n','') 79 | rest = self.source.pop(0).lstrip() 80 | self.lineNumber += 1 81 | while rest.strip() == '': 82 | rest = self.source.pop(0) 83 | self.lineNumber += 1 84 | if rest.lstrip() in {')\n',']\n','}\n'}: 85 | if ')' in rest: 86 | count -= 1 87 | if line[-1] == ',': 88 | line = line[:-1] 89 | rest = rest.lstrip() 90 | line += rest 91 | return line 92 | except IndexError: 93 | if self.processing: 94 | return '' 95 | else: 96 | if not self.transpileOnly: 97 | self.engine.run() 98 | sys.exit() 99 | else: 100 | self.engine.write() 101 | self.classes = self.engine.classes 102 | return 'exit' 103 | 104 | def getBlock(self, indent): 105 | ''' Return a list of code corresponding to the indentation level 106 | ''' 107 | self.line = self.input('... ') 108 | debugFunc('In a block', center=True) 109 | blockTokenized = parse(self.line, filename=self.filename, 110 | no=self.lineNumber, debug=self.debug) 111 | blockIndent = blockTokenized[0]['indent'] 112 | block = [] 113 | if blockIndent > indent: 114 | struct, nextLine = self.handleTokenized(blockTokenized) 115 | block.append(struct) 116 | if not nextLine: 117 | self.line = self.input('... ') 118 | blockTokenized = parse(self.line, filename=self.filename, 119 | no=self.lineNumber, debug=self.debug) 120 | while blockTokenized[0]['indent'] == blockIndent: 121 | struct, nextLine = self.handleTokenized(blockTokenized) 122 | block.append(struct) 123 | if not nextLine: 124 | self.line = self.input('... ') 125 | blockTokenized = parse(self.line, filename=self.filename, 126 | no=self.lineNumber, debug=self.debug) 127 | debugFunc('Out of a block', center=True) 128 | return block, blockTokenized 129 | else: 130 | debugFunc('Out of a block', center=True) 131 | return block, blockTokenized 132 | raise SyntaxError(f'Expecting an indented block here.\nLine: {self.line}') 133 | 134 | def handleBlock(self, tokenized): 135 | ''' Return a struct with a block and possibly modifiers ''' 136 | indent = tokenized[0]['indent'] 137 | block, nextTokenized = self.getBlock(indent) 138 | tokenized = assembly(tokenized, block=block) 139 | if len(nextTokenized) > 1: 140 | while nextTokenized[1]['token'] in {'elifStatement','elseStatement'} and nextTokenized[0]['indent'] == indent: 141 | block, afterTokenized = self.getBlock(indent) 142 | nextTokenized = assembly(nextTokenized, block=block) 143 | tokenized = assembly(tokenized, modifier=nextTokenized) 144 | nextTokenized = afterTokenized 145 | if len(nextTokenized) == 1: 146 | break 147 | struct = assembly(tokenized) 148 | return struct 149 | 150 | def handleTokenized(self, tokenized): 151 | ''' Return a struct to be processed by the VM ''' 152 | ''' And if there is a line to be processed in the buffer (self.line) ''' 153 | if tokenized[-1]['token'] == 'beginBlock': 154 | struct = self.handleBlock(tokenized) 155 | return struct, True 156 | else: 157 | struct = assembly(tokenized) 158 | return struct, False 159 | 160 | def run(self): 161 | nextLine = False 162 | while True: 163 | if not nextLine or self.line == '': 164 | self.line = self.input('>>> ') 165 | self.processing = True 166 | if self.line == 'exit': 167 | break 168 | try: 169 | tokenized = parse(self.line, filename=self.filename, no=self.lineNumber, debug=self.debug) 170 | struct, nextLine = self.handleTokenized(tokenized) 171 | except Exception as e: 172 | showError(e) 173 | self.engine.process(struct) 174 | self.processing = False 175 | 176 | if __name__ == "__main__": 177 | try: 178 | filename = sys.argv[1] 179 | except IndexError: 180 | filename = '' 181 | Interpreter(filename).run() 182 | -------------------------------------------------------------------------------- /core/libs/http/server.w: -------------------------------------------------------------------------------- 1 | native import _httpserver 2 | 3 | def run(): 4 | _httpserver.photon_run_http_server() 5 | -------------------------------------------------------------------------------- /core/libs/lol/test.w: -------------------------------------------------------------------------------- 1 | print('hey') 2 | -------------------------------------------------------------------------------- /core/libs/native/c/_httpserver.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int photon_run_http_server(char* addr, int port) { 8 | int server_fd, new_socket; 9 | struct sockaddr_in address; 10 | int addrlen = sizeof(address); 11 | char buffer[1024] = {0}; 12 | 13 | // Creating socket file descriptor 14 | if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { 15 | perror("Socket failed"); 16 | exit(EXIT_FAILURE); 17 | } 18 | 19 | // Setting up the address structure 20 | address.sin_family = AF_INET; 21 | address.sin_addr.s_addr = INADDR_ANY; 22 | address.sin_port = htons(port); 23 | 24 | // Binding the socket to the specified port 25 | if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { 26 | perror("Bind failed"); 27 | close(server_fd); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | // Start listening for incoming connections 32 | if (listen(server_fd, 3) < 0) { 33 | perror("Listen failed"); 34 | close(server_fd); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | printf("Server is listening on port %d\n", PORT); 39 | 40 | while (1) { 41 | // Accept a new connection 42 | if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { 43 | perror("Accept failed"); 44 | close(server_fd); 45 | exit(EXIT_FAILURE); 46 | } 47 | 48 | // Read the incoming HTTP request 49 | read(new_socket, buffer, 1024); 50 | printf("Received request:\n%s\n", buffer); 51 | 52 | // Send the HTTP response 53 | write(new_socket, http_response, strlen(http_response)); 54 | 55 | // Close the socket for this connection 56 | close(new_socket); 57 | } 58 | 59 | // Close the server socket 60 | close(server_fd); 61 | return 0; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /core/libs/native/c/_requests.h: -------------------------------------------------------------------------------- 1 | //PHOTON_FLAGS -lcurl 2 | //PHOTON_INCLUDES asprintf.h 3 | #include 4 | #include 5 | #include "asprintf.h" 6 | 7 | size_t get_data(char* buffer, size_t itemsize, size_t nitems, void* obj) { 8 | char** old = (char**) obj; 9 | asprintf(old, "%s%s", *old, buffer); 10 | return itemsize * nitems; 11 | } 12 | 13 | char* get(char* url) { 14 | CURL* curl; 15 | CURLcode resp; 16 | 17 | curl = curl_easy_init(); 18 | if (curl) { 19 | curl_easy_setopt(curl, CURLOPT_URL, url); 20 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 21 | char* result = ""; 22 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result); 23 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, get_data); 24 | 25 | resp = curl_easy_perform(curl); 26 | if (resp != CURLE_OK) { 27 | printf("GET failed: %s\n", curl_easy_strerror(resp)); 28 | } 29 | 30 | curl_easy_cleanup(curl); 31 | return result; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/libs/native/c/asprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef __asprintf 2 | # define __asprintf 3 | 4 | #include /* needed for vsnprintf */ 5 | #include /* needed for malloc-free */ 6 | #include /* needed for va_list */ 7 | 8 | #ifndef _vscprintf 9 | /* For some reason, MSVC fails to honour this #ifndef. */ 10 | /* Hence function renamed to _vscprintf_so(). */ 11 | int _vscprintf_so(const char* format, va_list pargs) { 12 | int retval; 13 | va_list argcopy; 14 | va_copy(argcopy, pargs); 15 | retval = vsnprintf(NULL, 0, format, argcopy); 16 | va_end(argcopy); 17 | return retval; 18 | } 19 | #endif // _vscprintf 20 | 21 | #ifndef vasprintf 22 | int vasprintf(char** strp, const char* fmt, va_list ap) { 23 | int len = _vscprintf_so(fmt, ap); 24 | if (len == -1) return -1; 25 | char* str = malloc((size_t) len + 1); 26 | if (!str) return -1; 27 | int r = vsnprintf(str, len + 1, fmt, ap); /* "secure" version of vsprintf */ 28 | if (r == -1) return free(str), -1; 29 | *strp = str; 30 | return r; 31 | } 32 | #endif // vasprintf 33 | 34 | #ifndef asprintf 35 | int asprintf(char* strp[], const char* fmt, ...) { 36 | va_list ap; 37 | va_start(ap, fmt); 38 | int r = vasprintf(strp, fmt, ap); 39 | va_end(ap); 40 | return r; 41 | } 42 | #endif 43 | // asprintf 44 | 45 | #ifndef __photon_format_str 46 | char* __photon_format_str(const char* fmt, ...) { 47 | char* str = malloc(sizeof(char)); 48 | if (!str) return ""; 49 | va_list ap; 50 | va_start(ap, fmt); 51 | vasprintf(&str, fmt, ap); 52 | va_end(ap); 53 | return str; 54 | } 55 | #endif 56 | // __photon_format_str 57 | #endif 58 | -------------------------------------------------------------------------------- /core/libs/native/c/dict_int.template: -------------------------------------------------------------------------------- 1 | #ifndef __dict_int_!@valType@! 2 | #define __dict_int_!@valType@! 3 | #include "main.h" 4 | #include "asprintf.h" 5 | 6 | typedef struct dict_int_!@valType@!_entry { 7 | int prehash; 8 | long key; 9 | !@valNativeType@! val; 10 | } dict_int_!@valType@!_entry; 11 | 12 | typedef struct dict_int_!@valType@! { 13 | int len; 14 | int size; 15 | int* indices; 16 | dict_int_!@valType@!_entry* entries; 17 | } dict_int_!@valType@!; 18 | 19 | !@valNativeType@! dict_int_!@valType@!_get(dict_int_!@valType@!* self, long key) { 20 | int size = self->size; 21 | int index = key % size; 22 | if (self->indices[index] != -1) { 23 | while (self->entries[self->indices[index]].key != key) { 24 | index = (index + 1) % size; 25 | if (self->indices[index] == -1) { 26 | printf("KeyError: The key %ld was not found.\n", key); 27 | exit(-1); 28 | } 29 | } 30 | } else { 31 | printf("KeyError: The key %ld was not found.\n", key); 32 | exit(-1); 33 | } 34 | return self->entries[self->indices[index]].val; 35 | } 36 | 37 | void dict_int_!@valType@!_set(dict_int_!@valType@!* self, long key, !@valNativeType@! value) { 38 | // Check if key already exists 39 | int size = self->size; 40 | int index = key % size; 41 | while (self->indices[index] != -1) { 42 | if (self->entries[self->indices[index]].key == key) { 43 | // found, just update its value 44 | self->entries[self->indices[index]].val = value; 45 | return; 46 | } 47 | index = (index + 1) % size; 48 | } 49 | // Insert new key and val 50 | int dictLen = self->len; 51 | self->indices[index] = dictLen; 52 | self->entries[dictLen].prehash = key; 53 | self->entries[dictLen].key = key; 54 | self->entries[dictLen].val = value; 55 | self->len += 1; 56 | dictLen++; 57 | if (dictLen == self->size) { 58 | self->size *= 2; 59 | int size = self->size; 60 | // recompute entries 61 | self->indices = realloc(self->indices, sizeof(int)*size); 62 | self->entries = realloc(self->entries, sizeof(dict_int_!@valType@!_entry)*size); 63 | for (int i=0; iindices[i] = -1; // -1 is None 65 | } 66 | for (int i=0; ientries[i].prehash % size; 68 | while (self->indices[index] != -1) { 69 | index = (index + 1) % size; 70 | } 71 | self->indices[index] = i; 72 | } 73 | } 74 | } 75 | 76 | dict_int_!@valType@!* dict_int_!@valType@!_constructor(int len, int size, ...) { 77 | dict_int_!@valType@!* dict = malloc(sizeof(dict_int_!@valType@!)); 78 | dict->len = 0; 79 | dict->size = size; 80 | dict->entries = malloc(sizeof(dict_int_!@valType@!_entry)*size); 81 | dict->indices = malloc(sizeof(int)*size); 82 | for (int i = 0; i < size; i++) { 83 | dict->indices[i] = -1; 84 | } 85 | 86 | va_list ptr; 87 | va_start(ptr, size); // size is the last argument before the ellipsis 88 | 89 | for (int i = 0; i < len; i++) { 90 | long tempKey = va_arg(ptr, long); 91 | !@valNativeType@! tempVal = va_arg(ptr, !@valNativeType@!); 92 | dict_int_!@valType@!_set(dict, tempKey, tempVal); 93 | } 94 | va_end(ptr); 95 | return dict; 96 | } 97 | 98 | void dict_int_!@valType@!_del(dict_int_!@valType@!* self, long key) { 99 | int size = self->size; 100 | int index = key % size; 101 | while (self->entries[self->indices[index]].key != key) { 102 | index = (index + 1) % size; 103 | if (self->indices[index] == -1) { 104 | printf("KeyError: The key %ld was not found.\n", key); 105 | exit(-1); 106 | } 107 | } 108 | int dictLen = self->len - 1; 109 | int removedPos = self->indices[index]; 110 | self->indices[index] = -2; // flag as deleted 111 | // put the last entry in this spot 112 | if (removedPos != dictLen) { 113 | self->entries[removedPos] = self->entries[dictLen]; 114 | // update index for this entry 115 | index = self->entries[removedPos].key % size; 116 | while (self->indices[index] != dictLen) { 117 | index++; 118 | } 119 | self->indices[index] = removedPos; 120 | } 121 | 122 | if (dictLen > 10 && dictLen < size/4) { 123 | size /= 2; 124 | // Clear indices at the new size 125 | for (int i=0; i < size; i++) { 126 | self->indices[i] = -1; 127 | } 128 | // Recompute entries; 129 | for (int i=0; ientries[i].prehash % size; 131 | while (self->indices[index] != -1) { 132 | index = (index + 1) % size; 133 | } 134 | self->indices[index] = i; 135 | } 136 | // Reallocate indices and entries 137 | self->indices = realloc(self->indices, sizeof(int)*size); 138 | self->entries = realloc(self->entries, sizeof(dict_int_!@valType@!_entry)*size); 139 | self->size = size; 140 | } 141 | self->len--; 142 | } 143 | 144 | char* dict_int_!@valType@!_str(dict_int_!@valType@!* self) { 145 | int dictLen = self->len-1; 146 | char* out = "{"; 147 | for (int i=0; ientries[i].key, self->entries[i].val); 149 | } 150 | if (dictLen > -1) { 151 | asprintf(&out, "%s%ld: !@formatCode@!}", out, self->entries[dictLen].key, self->entries[dictLen].val); 152 | } else { 153 | asprintf(&out, "%s}", out); 154 | } 155 | return out; 156 | } 157 | 158 | void dict_int_!@valType@!_repr(dict_int_!@valType@!* self) { 159 | int dictLen = self->len-1; 160 | printf("{\n"); 161 | for (int i=0; ientries[i].key, self->entries[i].val); 163 | } 164 | if (dictLen > -1) { 165 | printf(" %ld: !@formatCode@!\n", self->entries[dictLen].key, self->entries[dictLen].val); 166 | } 167 | printf("}\n"); 168 | } 169 | #endif 170 | -------------------------------------------------------------------------------- /core/libs/native/c/dict_str.template: -------------------------------------------------------------------------------- 1 | #ifndef __dict_str_!@valType@! 2 | #define __dict_str_!@valType@! 3 | #include "main.h" 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct dict_str_!@valType@!_entry { 9 | int prehash; 10 | char* key; 11 | !@valNativeType@! val; 12 | } dict_str_!@valType@!_entry; 13 | 14 | typedef struct dict_str_!@valType@! { 15 | int len; 16 | int size; 17 | int* indices; 18 | dict_str_!@valType@!_entry* entries; 19 | } dict_str_!@valType@!; 20 | 21 | int str_prehash(char* value) { 22 | // P and M 23 | const int p = 31; 24 | const int m = 1e9 + 9; 25 | int power_of_p = 1; 26 | int hash_val = 0; 27 | 28 | // Loop to calculate the hash value 29 | // by iterating over the elements of string 30 | int length = strlen(value); 31 | for (int i = 0; i < length; i++) { 32 | // if hash_val overflows, abs turns it into positive again 33 | hash_val = abs((hash_val + (value[i] - 'a' + 1) * power_of_p) % m); 34 | power_of_p = (power_of_p * p) % m; 35 | } 36 | 37 | return hash_val; 38 | } 39 | 40 | !@valNativeType@! dict_str_!@valType@!_get(dict_str_!@valType@!* self, char* key) { 41 | int size = self->size; 42 | int index = str_prehash(key) % size; 43 | if (self->indices[index] != -1) { 44 | while (strcmp(self->entries[self->indices[index]].key, key)) { 45 | index = (index + 1) % size; 46 | if (self->indices[index] == -1) { 47 | printf("KeyError: The key \"%s\" was not found.\n", key); 48 | exit(-1); 49 | } 50 | } 51 | } else { 52 | printf("KeyError: The key \"%s\" was not found.\n", key); 53 | exit(-1); 54 | } 55 | return self->entries[self->indices[index]].val; 56 | } 57 | 58 | void dict_str_!@valType@!_set(dict_str_!@valType@!* self, char* key, !@valNativeType@! value) { 59 | // Check if key already exists 60 | int size = self->size; 61 | int index = str_prehash(key) % size; 62 | while (self->indices[index] != -1) { 63 | if (!strcmp(self->entries[self->indices[index]].key, key)) { 64 | // found, just update its value 65 | self->entries[self->indices[index]].val = value; 66 | return; 67 | } 68 | index = (index + 1) % size; 69 | } 70 | // Insert new key and val 71 | int dictLen = self->len; 72 | self->indices[index] = dictLen; 73 | self->entries[dictLen].prehash = str_prehash(key); 74 | self->entries[dictLen].key = key; 75 | self->entries[dictLen].val = value; 76 | self->len += 1; 77 | dictLen++; 78 | if (dictLen == self->size) { 79 | self->size *= 2; 80 | int size = self->size; 81 | // recompute entries 82 | self->indices = realloc(self->indices, sizeof(int)*size); 83 | self->entries = realloc(self->entries, sizeof(dict_str_!@valType@!_entry)*size); 84 | for (int i=0; iindices[i] = -1; // -1 is None 86 | } 87 | for (int i=0; ientries[i].prehash % size; 89 | while (self->indices[index] != -1) { 90 | index = (index + 1) % size; 91 | } 92 | self->indices[index] = i; 93 | } 94 | } 95 | } 96 | 97 | dict_str_!@valType@!* dict_str_!@valType@!_constructor(int len, int size, ...) { 98 | dict_str_!@valType@!* dict = malloc(sizeof(dict_str_!@valType@!)); 99 | dict->len = 0; 100 | dict->size = size; 101 | dict->entries = malloc(sizeof(dict_str_!@valType@!_entry)*size); 102 | dict->indices = malloc(sizeof(int)*size); 103 | for (int i = 0; i < size; i++) { 104 | dict->indices[i] = -1; 105 | } 106 | 107 | va_list ptr; 108 | va_start(ptr, size); // size is the last argument before the ellipsis 109 | 110 | for (int i = 0; i < len; i++) { 111 | char* tempKey = va_arg(ptr, char*); 112 | !@valNativeType@! tempVal = va_arg(ptr, !@valNativeType@!); 113 | dict_str_!@valType@!_set(dict, tempKey, tempVal); 114 | } 115 | va_end(ptr); 116 | return dict; 117 | } 118 | 119 | void dict_str_!@valType@!_del(dict_str_!@valType@!* self, char* key) { 120 | int size = self->size; 121 | int index = str_prehash(key) % size; 122 | while (strcmp(self->entries[self->indices[index]].key, key)) { 123 | index = (index + 1) % size; 124 | if (self->indices[index] == -1) { 125 | printf("KeyError: The key \"%s\" was not found.\n", key); 126 | exit(-1); 127 | } 128 | } 129 | int dictLen = self->len - 1; 130 | int removedPos = self->indices[index]; 131 | self->indices[index] = -2; // flag as deleted 132 | // put the last entry in this spot 133 | if (removedPos != dictLen) { 134 | self->entries[removedPos] = self->entries[dictLen]; 135 | // update index for this entry 136 | index = self->entries[removedPos].prehash % size; 137 | while (self->indices[index] != dictLen) { 138 | index++; 139 | } 140 | self->indices[index] = removedPos; 141 | } 142 | 143 | if (dictLen > 10 && dictLen < size/4) { 144 | size /= 2; 145 | // Clear indices at the new size 146 | for (int i=0; i < size; i++) { 147 | self->indices[i] = -1; 148 | } 149 | // Recompute entries; 150 | for (int i=0; ientries[i].prehash % size; 152 | while (self->indices[index] != -1) { 153 | index = (index + 1) % size; 154 | } 155 | self->indices[index] = i; 156 | } 157 | // Reallocate indices and entries 158 | self->indices = realloc(self->indices, sizeof(int)*size); 159 | self->entries = realloc(self->entries, sizeof(dict_str_!@valType@!_entry)*size); 160 | self->size = size; 161 | } 162 | self->len--; 163 | } 164 | 165 | char* dict_str_!@valType@!_str(dict_str_!@valType@!* self) { 166 | int dictLen = self->len-1; 167 | char* out = "{"; 168 | for (int i=0; ientries[i].key, self->entries[i].val); 170 | } 171 | if (dictLen > -1) { 172 | asprintf(&out, "%s\"%s\": !@formatCode@!}", out, self->entries[dictLen].key, self->entries[dictLen].val); 173 | } else { 174 | asprintf(&out, "%s}", out); 175 | } 176 | return out; 177 | } 178 | 179 | void dict_str_!@valType@!_repr(dict_str_!@valType@!* self) { 180 | int dictLen = self->len-1; 181 | printf("{\n"); 182 | for (int i=0; ientries[i].key, self->entries[i].val); 184 | } 185 | if (dictLen > -1) { 186 | printf(" %s: !@formatCode@!\n", self->entries[dictLen].key, self->entries[dictLen].val); 187 | } 188 | printf("}\n"); 189 | } 190 | #endif 191 | -------------------------------------------------------------------------------- /core/libs/native/c/list_float.h: -------------------------------------------------------------------------------- 1 | #ifndef __list_float 2 | #define __list_float 3 | 4 | #include 5 | #include 6 | #include "asprintf.h" 7 | 8 | typedef struct list_float { 9 | int len; 10 | int size; 11 | double* values; 12 | } list_float; 13 | 14 | list_float* list_float_constructor(int len, int size, ...) { 15 | list_float* list = malloc(sizeof(list_float)); 16 | list->len = len; 17 | list->size = size; 18 | list->values = malloc(sizeof(double)*size); 19 | 20 | va_list ptr; 21 | va_start(ptr, size); // size is the last argument before the ellipsis 22 | 23 | for (int i = 0; i < len; i++) { 24 | list->values[i] = va_arg(ptr, double); 25 | } 26 | va_end(ptr); 27 | return list; 28 | } 29 | 30 | double list_float_get(list_float* list, int index) { 31 | if (index < 0) { 32 | // -1 is equivalent to the last element 33 | index = list->len + index; 34 | } 35 | if (index < 0 || index > list->len) { 36 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 37 | exit(-1); 38 | } 39 | return list->values[index]; 40 | } 41 | 42 | void list_float_set(list_float* list, int index, double value) { 43 | if (index < 0) { 44 | // -1 is equivalent to the last element 45 | index = list->len + index; 46 | } 47 | if (index < 0 || index > list->len) { 48 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 49 | exit(-1); 50 | } 51 | list->values[index] = value; 52 | } 53 | 54 | void list_float_append(list_float* list, double value) { 55 | if (list->len >= list->size) { 56 | list->size = list->size * 2; 57 | list->values = realloc(list->values, sizeof(double) * list->size); 58 | } 59 | list->values[list->len] = value; 60 | list->len += 1; 61 | } 62 | 63 | static inline int float_equals(double v1, double v2) { 64 | double delta = 0.0000000001; 65 | if (v1 >= v2 - delta && v1 <= v2 + delta) { 66 | return 1; 67 | } else { 68 | return 0; 69 | } 70 | } 71 | 72 | void list_float_removeAll(list_float* list, double value) { 73 | int removedItems = 0; 74 | int listLen = list->len; 75 | for (int i=0; ivalues[i], value)) { 77 | removedItems = 1; 78 | for (i=i; ivalues[i], value)) { 80 | removedItems++; 81 | } 82 | list->values[i] = list->values[i+removedItems]; 83 | } 84 | break; 85 | } 86 | } 87 | list->len -= removedItems; 88 | if (list->size >= 4*list->len) { 89 | list->size = list->size / 2; 90 | list->values = realloc(list->values, sizeof(long) * list->size); 91 | } 92 | } 93 | 94 | void list_float_del(list_float* list, int index) { 95 | int listLen = list->len; 96 | for (int i=index; ivalues[i] = list->values[i+1]; 98 | } 99 | list->len -= 1; 100 | if (list->size >= 4*list->len) { 101 | list->size = list->size / 2; 102 | list->values = realloc(list->values, sizeof(long) * list->size); 103 | } 104 | } 105 | void list_float_inc(list_float* list, int index, double value) { 106 | if (index < 0) { 107 | // -1 is equivalent to the last element 108 | index = list->len + index; 109 | } 110 | if (index < 0 || index > list->len) { 111 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 112 | exit(-1); 113 | } 114 | list->values[index] += value; 115 | } 116 | 117 | void list_float_repr(list_float* list) { 118 | int listLen = list->len; 119 | printf("["); 120 | for (int i=0; ivalues[i]); 122 | } 123 | if (listLen > 0) { 124 | printf("%lg]\n", list->values[listLen-1]); 125 | } else { 126 | printf("]\n"); 127 | } 128 | } 129 | 130 | char* list_float_str(list_float* list) { 131 | int listLen = list->len; 132 | char* out = "["; 133 | for (int i=0; ivalues[i]); 135 | } 136 | if (listLen > 0) { 137 | asprintf(&out, "%s%lg]", out, list->values[listLen-1]); 138 | } else { 139 | asprintf(&out, "%s]", out); 140 | } 141 | return out; 142 | } 143 | 144 | void list_float_clear(list_float* list) { 145 | list->len = 0; 146 | } 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /core/libs/native/c/list_int.h: -------------------------------------------------------------------------------- 1 | #ifndef __list_int 2 | #define __list_int 3 | 4 | #include 5 | #include 6 | #include 7 | #include "asprintf.h" 8 | 9 | typedef struct list_int { 10 | int len; // number of element stored 11 | int size; // allocated array size 12 | long* values; 13 | } list_int; 14 | 15 | list_int* list_int_constructor(int len, int size, ...) { 16 | list_int* list = malloc(sizeof(list_int)); 17 | list->len = len; 18 | list->size = size; 19 | list->values = malloc(sizeof(long)*size); 20 | 21 | va_list ptr; 22 | va_start(ptr, size); // size is the last argument before the ellipsis 23 | 24 | for (int i = 0; i < len; i++) { 25 | list->values[i] = va_arg(ptr, long); 26 | } 27 | va_end(ptr); 28 | return list; 29 | } 30 | 31 | int list_int_get(list_int* list, int index) { 32 | if (index < 0) { 33 | // -1 is equivalent to the last element 34 | index = list->len + index; 35 | } 36 | if (index < 0 || index > list->len) { 37 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 38 | exit(-1); 39 | } 40 | return list->values[index]; 41 | } 42 | 43 | void list_int_set(list_int* list, int index, long value) { 44 | if (index < 0) { 45 | // -1 is equivalent to the last element 46 | index = list->len + index; 47 | } 48 | if (index < 0 || index > list->len) { 49 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 50 | exit(-1); 51 | } 52 | list->values[index] = value; 53 | } 54 | 55 | void list_int_append(list_int* list, long value) { 56 | if (list->len >= list->size) { 57 | list->size = list->size * 2; 58 | list->values = realloc(list->values, sizeof(long) * list->size); 59 | } 60 | list->values[list->len] = value; 61 | list->len += 1; 62 | } 63 | 64 | void list_int_removeAll(list_int* list, long value) { 65 | int removedItems = 0; 66 | int listLen = list->len; 67 | for (int i=0; ivalues[i] == value) { 69 | removedItems = 1; 70 | for (i=i; ivalues[i] == value) { 72 | removedItems++; 73 | } 74 | list->values[i] = list->values[i+removedItems]; 75 | } 76 | break; 77 | } 78 | } 79 | list->len -= removedItems; 80 | if (list->size >= 4*list->len) { 81 | list->size = list->size / 2; 82 | list->values = realloc(list->values, sizeof(long) * list->size); 83 | } 84 | } 85 | 86 | void list_int_del(list_int* list, int index) { 87 | int listLen = list->len; 88 | for (int i=index; ivalues[i] = list->values[i+1]; 90 | } 91 | list->len -= 1; 92 | if (list->size >= 4*list->len) { 93 | list->size = list->size / 2; 94 | list->values = realloc(list->values, sizeof(long) * list->size); 95 | } 96 | } 97 | 98 | void list_int_inc(list_int* list, int index, long value) { 99 | if (index < 0) { 100 | // -1 is equivalent to the last element 101 | index = list->len + index; 102 | } 103 | if (index < 0 || index > list->len) { 104 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 105 | exit(-1); 106 | } 107 | list->values[index] += value; 108 | } 109 | 110 | void list_int_repr(list_int* list) { 111 | int listLen = list->len; 112 | printf("["); 113 | for (int i=0; ivalues[i]); 115 | } 116 | if (listLen > 0) { 117 | printf("%ld]\n", list->values[listLen-1]); 118 | } else { 119 | printf("]\n"); 120 | } 121 | } 122 | 123 | char* list_int_str(list_int* list) { 124 | int listLen = list->len; 125 | char* out = "["; 126 | for (int i=0; ivalues[i]); 128 | } 129 | if (listLen > 0) { 130 | asprintf(&out, "%s%ld]", out, list->values[listLen-1]); 131 | } else { 132 | asprintf(&out, "%s]", out); 133 | } 134 | return out; 135 | } 136 | 137 | void list_int_clear(list_int* list) { 138 | list->len = 0; 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /core/libs/native/c/list_str.h: -------------------------------------------------------------------------------- 1 | #ifndef __list_str 2 | #define __list_str 3 | 4 | #include 5 | #include 6 | #include 7 | #include "asprintf.h" 8 | 9 | typedef struct list_str { 10 | int len; // number of element stored 11 | int size; // allocated array size 12 | char** values; 13 | } list_str; 14 | 15 | list_str* list_str_constructor(int len, int size, ...) { 16 | list_str* list = malloc(sizeof(list_str)); 17 | list->len = len; 18 | list->size = size; 19 | list->values = malloc(sizeof(char*)*size); 20 | 21 | va_list ptr; 22 | va_start(ptr, size); // size is the last argument before the ellipsis 23 | 24 | for (int i = 0; i < len; i++) { 25 | list->values[i] = va_arg(ptr, char*); 26 | } 27 | va_end(ptr); 28 | return list; 29 | } 30 | 31 | char* list_str_get(list_str* list, int index) { 32 | if (index < 0) { 33 | // -1 is equivalent to the last element 34 | index = list->len + index; 35 | } 36 | if (index < 0 || index > list->len) { 37 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 38 | exit(-1); 39 | } 40 | return list->values[index]; 41 | } 42 | 43 | void list_str_set(list_str* list, int index, char* value) { 44 | if (index < 0) { 45 | // -1 is equivalent to the last element 46 | index = list->len + index; 47 | } 48 | if (index < 0 || index > list->len) { 49 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 50 | exit(-1); 51 | } 52 | list->values[index] = value; 53 | } 54 | 55 | void list_str_append(list_str* list, char* value) { 56 | if (list->len >= list->size) { 57 | list->size = list->size * 2; 58 | list->values = realloc(list->values, sizeof(char*) * list->size); 59 | } 60 | char * copy = malloc(strlen(value) + 1); 61 | strcpy(copy, value); 62 | list->values[list->len] = copy; 63 | list->len += 1; 64 | } 65 | 66 | void list_str_removeAll(list_str* list, char* value) { 67 | int removedItems = 0; 68 | int listLen = list->len; 69 | for (int i=0; ivalues[i], value)) { 71 | removedItems = 1; 72 | for (i=i; ivalues[i], value)) { 74 | removedItems++; 75 | } 76 | list->values[i] = list->values[i+removedItems]; 77 | } 78 | break; 79 | } 80 | } 81 | list->len -= removedItems; 82 | if (list->size >= 4*list->len) { 83 | list->size = list->size / 2; 84 | list->values = realloc(list->values, sizeof(long) * list->size); 85 | } 86 | } 87 | 88 | void list_str_del(list_str* list, int index) { 89 | int listLen = list->len; 90 | for (int i=index; ivalues[i] = list->values[i+1]; 92 | } 93 | list->len -= 1; 94 | if (list->size >= 4*list->len) { 95 | list->size = list->size / 2; 96 | list->values = realloc(list->values, sizeof(long) * list->size); 97 | } 98 | } 99 | 100 | void list_str_inc(list_str* list, int index, char* value) { 101 | if (index < 0) { 102 | // -1 is equivalent to the last element 103 | index = list->len + index; 104 | } 105 | if (index < 0 || index > list->len) { 106 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 107 | exit(-1); 108 | } 109 | asprintf(&list->values[index], "%s%s", list->values[index], value); 110 | } 111 | 112 | void list_str_repr(list_str* list) { 113 | int listLen = list->len; 114 | printf("["); 115 | for (int i=0; ivalues[i]); 117 | } 118 | if (listLen > 0) { 119 | printf("\"%s\"]\n", list->values[listLen-1]); 120 | } else { 121 | printf("]\n"); 122 | } 123 | } 124 | 125 | char* list_str_str(list_str* list) { 126 | int listLen = list->len; 127 | char* out = "["; 128 | for (int i=0; ivalues[i]); 130 | } 131 | if (listLen > 0) { 132 | asprintf(&out, "%s\"%s\"]", out, list->values[listLen-1]); 133 | } else { 134 | asprintf(&out, "%s]", out); 135 | } 136 | return out; 137 | } 138 | 139 | void list_str_clear(list_str* list) { 140 | list->len = 0; 141 | } 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /core/libs/native/c/list_template.h: -------------------------------------------------------------------------------- 1 | #ifndef __list_!@valType@! 2 | #define __list_!@valType@! 3 | 4 | #include 5 | #include 6 | #include "asprintf.h" 7 | 8 | typedef struct !@valType@! !@valType@!; 9 | 10 | typedef struct list_!@valType@! { 11 | int len; 12 | int size; 13 | !@valType@!** values; 14 | } list_!@valType@!; 15 | 16 | list_!@valType@!* list_!@valType@!_constructor(int len, int size, ...) { 17 | list_!@valType@!* list = malloc(sizeof(list_!@valType@!)); 18 | list->len = len; 19 | list->size = size; 20 | list->values = malloc(sizeof(!@valType@!*)*size); 21 | 22 | va_list ptr; 23 | va_start(ptr, size); // size is the last argument before the ellipsis 24 | 25 | for (int i = 0; i < len; i++) { 26 | list->values[i] = va_arg(ptr, !@valType@!*); 27 | } 28 | va_end(ptr); 29 | return list; 30 | } 31 | 32 | !@valType@!* list_!@valType@!_get(list_!@valType@!* list, int index) { 33 | if (index < 0) { 34 | // -1 is equivalent to the last element 35 | index = list->len + index; 36 | } 37 | if (index < 0 || index > list->len) { 38 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 39 | exit(-1); 40 | } 41 | return list->values[index]; 42 | } 43 | 44 | void list_!@valType@!_set(list_!@valType@!* list, int index, !@valType@!* value) { 45 | if (index < 0) { 46 | // -1 is equivalent to the last element 47 | index = list->len + index; 48 | } 49 | if (index < 0 || index > list->len) { 50 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 51 | exit(-1); 52 | } 53 | list->values[index] = value; 54 | } 55 | 56 | void list_!@valType@!_append(list_!@valType@!* list, !@valType@!* value) { 57 | if (list->len >= list->size) { 58 | list->size = list->size * 2; 59 | list->values = realloc(list->values, sizeof(!@valType@!) * list->size); 60 | } 61 | list->values[list->len] = value; 62 | list->len += 1; 63 | } 64 | 65 | void list_!@valType@!_remove(list_!@valType@!* list, !@valType@!* value) { 66 | int removedItems = 0; 67 | int listLen = list->len; 68 | for (int i=0; ivalues[i] == value) { 70 | removedItems = 1; 71 | for (i=i; ivalues[i] = list->values[i+removedItems]; 73 | } 74 | break; 75 | } 76 | } 77 | list->len -= removedItems; 78 | if (list->size >= 4*list->len) { 79 | list->size = list->size / 2; 80 | list->values = realloc(list->values, sizeof(!@valType@!) * list->size); 81 | } 82 | } 83 | 84 | void list_!@valType@!_removeAll(list_!@valType@!* list, !@valType@!* value) { 85 | int removedItems = 0; 86 | int listLen = list->len; 87 | for (int i=0; ivalues[i] == value) { 89 | removedItems = 1; 90 | for (i=i; ivalues[i] == value) { 92 | removedItems++; 93 | } 94 | list->values[i] = list->values[i+removedItems]; 95 | } 96 | break; 97 | } 98 | } 99 | list->len -= removedItems; 100 | if (list->size >= 4*list->len) { 101 | list->size = list->size / 2; 102 | list->values = realloc(list->values, sizeof(!@valType@!) * list->size); 103 | } 104 | } 105 | 106 | void list_!@valType@!_del(list_!@valType@!* list, int index) { 107 | int listLen = list->len; 108 | for (int i=index; ivalues[i] = list->values[i+1]; 110 | } 111 | list->len -= 1; 112 | if (list->size >= 4*list->len) { 113 | list->size = list->size / 2; 114 | list->values = realloc(list->values, sizeof(!@valType@!) * list->size); 115 | } 116 | } 117 | 118 | /* TODO: this makes sense for class? 119 | void list_!@valType@!_inc(list_!@valType@!* list, int index, double value) { 120 | if (index < 0) { 121 | // -1 is equivalent to the last element 122 | index = list->len + index; 123 | } 124 | if (index < 0 || index > list->len) { 125 | printf("IndexError: The array has %d elements, but you required the %d index\n", list->len, index); 126 | exit(-1); 127 | } 128 | list->values[index] += value; 129 | } 130 | */ 131 | 132 | void list_!@valType@!_repr(list_!@valType@!* list) { 133 | int listLen = list->len; 134 | printf("["); 135 | for (int i=0; i, "); 137 | } 138 | if (listLen > 0) { 139 | printf("]\n"); 140 | } else { 141 | printf("]\n"); 142 | } 143 | } 144 | 145 | char* list_!@valType@!_str(list_!@valType@!* list) { 146 | int listLen = list->len; 147 | char* out = "["; 148 | // TODO: change to class_repr 149 | for (int i=0; i, ", out); 151 | } 152 | if (listLen > 0) { 153 | asprintf(&out, "%s]", out); 154 | } else { 155 | asprintf(&out, "%s]", out); 156 | } 157 | return out; 158 | } 159 | 160 | void list_!@valType@!_clear(list_!@valType@!* list) { 161 | list->len = 0; 162 | } 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /core/libs/native/c/photonInput.h: -------------------------------------------------------------------------------- 1 | #ifndef __photonInput 2 | #define __photonInput 3 | 4 | #include 5 | #include 6 | 7 | char *photonInput(char* message) 8 | { 9 | printf(message); 10 | int c; 11 | size_t size = 5; 12 | size_t read_size = 0; 13 | char *line = malloc(size); 14 | if (!line) 15 | { 16 | perror("malloc"); 17 | return line; 18 | } 19 | 20 | line[0] = '\0'; 21 | 22 | c = fgetc(stdin); 23 | while (c != EOF && c!= '\n') 24 | { 25 | line[read_size] = c; 26 | ++read_size; 27 | if (read_size == size) 28 | { 29 | size += 5; 30 | char *test = realloc(line, size); 31 | if (!test) 32 | { 33 | perror("realloc"); 34 | return line; 35 | } 36 | line = test; 37 | } 38 | c = fgetc(stdin); 39 | } 40 | line[read_size] = '\0'; 41 | return line; 42 | } 43 | 44 | char *photonRead(FILE* file) 45 | { 46 | int c; 47 | size_t size = 5; 48 | size_t read_size = 0; 49 | char *line = malloc(size); 50 | if (!line) 51 | { 52 | perror("malloc"); 53 | return line; 54 | } 55 | 56 | line[0] = '\0'; 57 | 58 | c = fgetc(file); 59 | while (c != EOF && c!= '\n') 60 | { 61 | line[read_size] = c; 62 | ++read_size; 63 | if (read_size == size) 64 | { 65 | size += 5; 66 | char *test = realloc(line, size); 67 | if (!test) 68 | { 69 | perror("realloc"); 70 | return line; 71 | } 72 | line = test; 73 | } 74 | c = fgetc(file); 75 | } 76 | line[read_size] = '\0'; 77 | if (!read_size) { 78 | return NULL; 79 | } 80 | return line; 81 | } 82 | #endif 83 | -------------------------------------------------------------------------------- /core/libs/native/d/dontRemove: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/core/libs/native/d/dontRemove -------------------------------------------------------------------------------- /core/libs/native/haxe/dontRemove: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/core/libs/native/haxe/dontRemove -------------------------------------------------------------------------------- /core/libs/native/js/dontRemove: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/core/libs/native/js/dontRemove -------------------------------------------------------------------------------- /core/libs/native/py/dontRemove: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/core/libs/native/py/dontRemove -------------------------------------------------------------------------------- /core/libs/random.w: -------------------------------------------------------------------------------- 1 | for C: 2 | native import time 3 | 4 | time.srand(time.time(null)) 5 | def random(): 6 | float maxNumber = time.RAND_MAX 7 | float a = time.rand() / maxNumber 8 | return a 9 | 10 | for Python: 11 | native import random 12 | 13 | def random(): 14 | float a = random.random() 15 | return a 16 | 17 | for Javascript: 18 | def random(): 19 | float a = Math.random() 20 | return a 21 | 22 | def randint(int begin, int end): 23 | int a = random()*(end-begin)+begin 24 | return a 25 | 26 | def randfloat(float begin, float end): 27 | float a = random()*(end-begin)+begin 28 | return a 29 | -------------------------------------------------------------------------------- /core/libs/requests.w: -------------------------------------------------------------------------------- 1 | import _requests 2 | 3 | def get(str url): 4 | str resp = _requests.get(url) 5 | return resp 6 | -------------------------------------------------------------------------------- /core/libs/wui.w: -------------------------------------------------------------------------------- 1 | import wuiGraphics 2 | native import raylib 3 | 4 | def pass(): 5 | print("Apertou!!") 6 | 7 | class Widget(): 8 | def new(.x=0.0, .y=0.0, .width=100.0, .height=100.0): 9 | 10 | def onKeyPress(int a): 11 | 12 | def update(): 13 | 14 | def render(): 15 | 16 | class Label(Widget): 17 | Font font 18 | str[] lines = [] 19 | def new(.text="", .fontSize=40, .align="center", .valign="center", .color=wuiGraphics.Color()): 20 | 21 | def render(): 22 | for C: 23 | if .font.baseSize == 0: 24 | .font = raylib.LoadFontEx("assets/Roboto-Italic.ttf", .fontSize, 0, 250) 25 | for Python: 26 | if not .font: 27 | fontName = "assets/Roboto-Italic.ttf" 28 | .font = raylib.LoadFontEx(fontName.encode(), .fontSize, raylib.ffi.new("int *", 0), 250) 29 | 30 | lineBuffer = '' 31 | word = '' 32 | .lines = [] 33 | for c in .text: 34 | if c == ' ': 35 | if wuiGraphics.measureText(.font, lineBuffer+' '+word, .fontSize) > .width: 36 | .lines.append(lineBuffer) 37 | lineBuffer = word 38 | else: 39 | if lineBuffer == '': 40 | lineBuffer = word 41 | else: 42 | lineBuffer += ' ' + word 43 | word = '' 44 | elif c == '\n': 45 | if wuiGraphics.measureText(.font, lineBuffer+' '+word, .fontSize) > .width: 46 | .lines.append(lineBuffer) 47 | .lines.append(word) 48 | else: 49 | if lineBuffer == '': 50 | .lines.append(word) 51 | else: 52 | .lines.append(lineBuffer + ' ' + word) 53 | lineBuffer = '' 54 | word = '' 55 | else: 56 | word += c 57 | if wuiGraphics.measureText(.font, lineBuffer+word, .fontSize) > .width: 58 | .lines.append(lineBuffer) 59 | .lines.append(word) 60 | else: 61 | .lines.append(lineBuffer + word) 62 | 63 | dy = .y 64 | if .valign == "center": 65 | dy += (.height - .lines.len * .fontSize)/2 66 | elif .valign == "bottom": 67 | dy += .height - .lines.len * .fontSize 68 | 69 | dx = 0.0 70 | for line in .lines: 71 | textWidth = wuiGraphics.measureText(.font, line, .fontSize) 72 | if .align == "center": 73 | dx = .x + (.width - textWidth)/2 74 | elif .align == "left": 75 | dx = .x 76 | elif .align == "right": 77 | dx = .x + .width - textWidth 78 | wuiGraphics.drawText(.font, line, dx, dy, .fontSize, .color) 79 | dy += .fontSize 80 | for C: 81 | .lines.len = 0 82 | for Python: 83 | .lines = [] 84 | 85 | class Button(Label): 86 | def new(func .onPress=pass, func .onRelease=pass, .radius=0.5, .buttonColor=wuiGraphics.Color(b=255)): 87 | 88 | def render(): 89 | int posX = raylib.GetMouseX() 90 | int posY = raylib.GetMouseY() 91 | if posX > .x and posX < .x + .width and posY > .y and posY < .y + .height: 92 | if raylib.IsMouseButtonPressed(raylib.MOUSE_LEFT_BUTTON): 93 | .onPress() 94 | elif raylib.IsMouseButtonReleased(raylib.MOUSE_LEFT_BUTTON): 95 | .onRelease() 96 | wuiGraphics.drawRoundedRectangle(.x, .y, .width, .height, .radius, .buttonColor) 97 | super.render() 98 | 99 | class Layout(Widget): 100 | def new(Widget[] .children=[]): 101 | 102 | def update(): 103 | for child in .children: 104 | child.update() 105 | 106 | def render(): 107 | for child in .children: 108 | child.render() 109 | 110 | def addWidget(Widget widget): 111 | .children.append(widget) 112 | 113 | def removeWidget(Widget widget): 114 | .children.remove(widget) 115 | 116 | class Box(Layout): 117 | def new(.orientation='vertical'): 118 | 119 | def render(): 120 | dx = .x 121 | dy = .y 122 | if .children.len > 0: 123 | if .orientation == 'vertical': 124 | wHeight = .height / .children.len 125 | for child in .children: 126 | child.x = dx 127 | child.y = dy 128 | child.width = .width 129 | child.height = wHeight 130 | child.render() 131 | dy += wHeight 132 | else: 133 | wWidth = .width / .children.len 134 | for child in .children: 135 | child.x = dx 136 | child.y = dy 137 | child.width = wWidth 138 | child.height = .height 139 | child.render() 140 | dx += wWidth 141 | 142 | class App(): 143 | def new(.background=wuiGraphics.Color(r=255, g=255, b=255), .fps=60, .width=800, .height=600, .title="Photon"): 144 | 145 | def run(Widget widget): 146 | widget.width = .width 147 | widget.height = .height 148 | for C: 149 | raylib.InitWindow(.width, .height, .title) 150 | for Javascript: 151 | raylib.InitWindow(.width, .height, .title) 152 | for Python: 153 | raylib.InitWindow(.width, .height, .title.encode()) 154 | raylib.SetTargetFPS(.fps) 155 | while not raylib.WindowShouldClose(): 156 | raylib.BeginDrawing() 157 | raylib.ClearBackground(.background.toNative()) 158 | widget.update() 159 | widget.render() 160 | raylib.EndDrawing() 161 | 162 | -------------------------------------------------------------------------------- /core/libs/wui/widgets.w: -------------------------------------------------------------------------------- 1 | print('Imported widgets') 2 | -------------------------------------------------------------------------------- /core/libs/wui/wuiGraphics.w: -------------------------------------------------------------------------------- 1 | native import raylib 2 | for Python: 3 | native import pyray 4 | 5 | class Color(): 6 | def new(.r=0.0, .g=0.0, .b=0.0, .a=255.0): 7 | 8 | def toNative(): 9 | for JavaScript: 10 | raylib.Color color = raylib.Color(.r, .g, .b, .a) 11 | for C: 12 | raylib.Color color = raylib.BLACK 13 | color.r = .r 14 | color.g = .g 15 | color.b = .b 16 | color.a = .a 17 | for Python: 18 | pyray.Color color = pyray.Color(int(.r), int(.g), int(.b), int(.a)) 19 | return color 20 | 21 | def drawText(Font font, str text, float x, float y, int fontSize, Color color): 22 | for JavaScript: 23 | raylib.DrawTextEx(font, text.encode(), raylib.Vector2(x, y), fontSize, 0.0, color.toNative()) 24 | for C: 25 | Vector2 pos 26 | pos.x = x 27 | pos.y = y 28 | raylib.DrawTextEx(font, text, pos, fontSize, 0.0, color.toNative()) 29 | for Python: 30 | raylib.DrawTextEx(font, text.encode(), pyray.Vector2(x, y), fontSize, 0.0, color.toNative()) 31 | 32 | def measureText(Font font, str text, int fontSize): 33 | for JavaScript: 34 | int width = raylib.MeasureTextEx(font, text, fontSize, 0).x 35 | for C: 36 | int width = raylib.MeasureTextEx(font, text, fontSize, 0).x 37 | for Python: 38 | int width = raylib.MeasureTextEx(font, text.encode(), fontSize, 0).x 39 | return width 40 | 41 | def drawRoundedRectangle(float x, float y, float width, float height, float radius, Color color): 42 | segments = 10 43 | for JavaScript: 44 | rec = raylib.Rectangle(x, y, width, height) 45 | for C: 46 | Rectangle rec 47 | rec.x = x 48 | rec.y = y 49 | rec.width = width 50 | rec.height = height 51 | for Python: 52 | rec = pyray.Rectangle(x, y, width, height) 53 | raylib.DrawRectangleRounded(rec, radius, segments, color.toNative()) 54 | 55 | def drawRectangle(float x, float y, float width, float height, Color color): 56 | for JavaScript: 57 | raylib.DrawRectangle(x, y, width, height, color.toNative()) 58 | for C: 59 | raylib.DrawRectangle(x, y, width, height, color.toNative()) 60 | for Python: 61 | int xi = x 62 | int yi = y 63 | int widthi = width 64 | int heighti = height 65 | raylib.DrawRectangle(xi, yi, widthi, heighti, color.toNative()) 66 | 67 | def drawCircle(float x, float y, float radius, Color color): 68 | for JavaScript: 69 | raylib.DrawCircle(x, y, radius, color.toNative()) 70 | for C: 71 | raylib.DrawCircle(x, y, radius, color.toNative()) 72 | for Python: 73 | raylib.DrawCircle(int(x), int(y), radius, color.toNative()) 74 | -------------------------------------------------------------------------------- /core/libs/wuiGraphics.w: -------------------------------------------------------------------------------- 1 | native import raylib 2 | for Python: 3 | native import pyray 4 | 5 | class Color(): 6 | def new(.r=0.0, .g=0.0, .b=0.0, .a=255.0): 7 | 8 | def toNative(): 9 | for JavaScript: 10 | raylib.Color color = raylib.Color(.r, .g, .b, .a) 11 | for C: 12 | raylib.Color color = raylib.BLACK 13 | color.r = .r 14 | color.g = .g 15 | color.b = .b 16 | color.a = .a 17 | for Python: 18 | pyray.Color color = pyray.Color(int(.r), int(.g), int(.b), int(.a)) 19 | return color 20 | 21 | def drawText(Font font, str text, float x, float y, int fontSize, Color color): 22 | for JavaScript: 23 | raylib.DrawTextEx(font, text.encode(), raylib.Vector2(x, y), fontSize, 0.0, color.toNative()) 24 | for C: 25 | Vector2 pos 26 | pos.x = x 27 | pos.y = y 28 | raylib.DrawTextEx(font, text, pos, fontSize, 0.0, color.toNative()) 29 | for Python: 30 | raylib.DrawTextEx(font, text.encode(), pyray.Vector2(x, y), fontSize, 0.0, color.toNative()) 31 | 32 | def measureText(Font font, str text, int fontSize): 33 | for JavaScript: 34 | int width = raylib.MeasureTextEx(font, text, fontSize, 0).x 35 | for C: 36 | int width = raylib.MeasureTextEx(font, text, fontSize, 0).x 37 | for Python: 38 | int width = raylib.MeasureTextEx(font, text.encode(), fontSize, 0).x 39 | return width 40 | 41 | def drawRoundedRectangle(float x, float y, float width, float height, float radius, Color color): 42 | segments = 10 43 | for JavaScript: 44 | rec = raylib.Rectangle(x, y, width, height) 45 | for C: 46 | Rectangle rec 47 | rec.x = x 48 | rec.y = y 49 | rec.width = width 50 | rec.height = height 51 | for Python: 52 | rec = pyray.Rectangle(x, y, width, height) 53 | raylib.DrawRectangleRounded(rec, radius, segments, color.toNative()) 54 | 55 | def drawRectangle(float x, float y, float width, float height, Color color): 56 | for JavaScript: 57 | raylib.DrawRectangle(x, y, width, height, color.toNative()) 58 | for C: 59 | raylib.DrawRectangle(x, y, width, height, color.toNative()) 60 | for Python: 61 | int xi = x 62 | int yi = y 63 | int widthi = width 64 | int heighti = height 65 | raylib.DrawRectangle(xi, yi, widthi, heighti, color.toNative()) 66 | 67 | def drawCircle(float x, float y, float radius, Color color): 68 | for JavaScript: 69 | raylib.DrawCircle(x, y, radius, color.toNative()) 70 | for C: 71 | raylib.DrawCircle(x, y, radius, color.toNative()) 72 | for Python: 73 | raylib.DrawCircle(int(x), int(y), radius, color.toNative()) 74 | -------------------------------------------------------------------------------- /core/pattern_cli.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import atexit 3 | import os 4 | import builtins 5 | import traceback 6 | 7 | __version__ = '0.0.4' 8 | 9 | terms = sys.argv[1:] 10 | 11 | flags = [flag for flag in terms if flag.startswith('-')] 12 | kwargs = dict([kw.split('=') for kw in terms if '=' in kw]) 13 | route = [term for term in terms if not term.startswith('-') and not '=' in term] 14 | 15 | def cli_help(subcommand=None): 16 | print(f'{sys.argv[0]} help') 17 | if subcommand is not None: 18 | print(f'Help for subcommand {subcommand}') 19 | print() 20 | for route in routes: 21 | if subcommand is None or route.startswith(subcommand): 22 | if 'doc' in routes[route]: 23 | print(f' {route} - {routes[route]["doc"].strip()}') 24 | 25 | routes = { 26 | 'help':{'func':cli_help}, 27 | '-h':{'func':cli_help}, 28 | '--help':{'func':cli_help}, 29 | } 30 | 31 | def cli(route, methods=None): 32 | def decorator(f): 33 | def wrapped(*args, **kwargs): 34 | try: 35 | resp = f(*args, **kwargs) 36 | except Exception as e: 37 | tb = traceback.format_exc().replace('"', '\"').replace("'", "\'") 38 | print(tb, file=sys.stderr) 39 | return 40 | routes[route] = {'func':wrapped} 41 | if f.__doc__: 42 | routes[route]['doc'] = f.__doc__ 43 | return wrapped 44 | return decorator 45 | 46 | def cast(part, varType): 47 | varType = varType.replace('string', 'str') 48 | if varType in builtins.__dict__: 49 | return getattr(builtins, varType)(part) 50 | raise TypeError 51 | 52 | def isCompatible(pattern, part): 53 | if pattern.startswith('<') and pattern.endswith('>'): 54 | if ':' in pattern: 55 | *varType, var = pattern[1:-1].split(':') 56 | if varType[0] == 'path': 57 | return True, var, part 58 | try: 59 | return True, var, cast(part, varType[0]) 60 | except TypeError: 61 | return None 62 | else: 63 | return True 64 | elif pattern == part: 65 | return True 66 | return None 67 | 68 | def checkArgsLen(command, pattern, variables): 69 | if len(command) == len(pattern): 70 | return True 71 | return False 72 | 73 | def parseRoute(pattern, command): 74 | pattern = pattern.split(' ') 75 | path = '' 76 | offset = 0 77 | variables = {} 78 | for n, part in enumerate(pattern): 79 | if '"' in part: 80 | offset = len(command)-len(pattern) 81 | if offset >= 0: 82 | *varType, var = part[1:-1].split(':') 83 | variables[var] = ' '.join(command[n:n+offset+1]) 84 | else: 85 | # Route is not compatible 86 | return None, None 87 | else: 88 | result = isCompatible(part, command[n+offset]) 89 | if result is None: 90 | # Route is not compatible 91 | return None, None 92 | else: 93 | if result is not True and len(result) > 1: 94 | variables[result[1]] = result[2] 95 | # yep, proceed 96 | continue 97 | if checkArgsLen(command, pattern, variables): 98 | # Route {pattern} is compatible with {command} 99 | return variables, ' '.join(pattern) 100 | return None, None 101 | 102 | def run(): 103 | global route 104 | if route and route[-1] == 'help': 105 | cli_help(subcommand=' '.join(route[:-1])) 106 | return 107 | variables = {} 108 | if not ' '.join(route) in routes: 109 | for r in routes: 110 | variables, rule = parseRoute(r, route) 111 | if rule is not None: 112 | route = rule 113 | break 114 | else: 115 | print('Invalid command.') 116 | return 117 | else: 118 | route = ' '.join(route) 119 | try: 120 | if kwargs: 121 | routes[route]['func'](**variables, **kwargs) 122 | else: 123 | routes[route]['func'](**variables) 124 | except SystemExit as e: 125 | atexit.set_exit_code = e 126 | 127 | atexit.register(run) 128 | -------------------------------------------------------------------------------- /core/photon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ''' Photon command-line interface. ''' 3 | 4 | import os, sys 5 | from pattern_cli import cli, flags, kwargs, cli_help 6 | 7 | PHOTON_INSTALL_PATH = getattr(sys, '_MEIPASS', os.path.dirname(os.path.realpath(__file__))) 8 | sys.path.insert(0, PHOTON_INSTALL_PATH) 9 | 10 | __version__ = '0.0.10' 11 | 12 | allowed_kwargs = { 13 | 'lang': ['c', 'd', 'js', 'ts', 'dart', 'haxe', 'python'], 14 | 'platform': ['linux', 'windows', 'mac', 'android', 'web'], 15 | 'framework': ['raylib', 'html5', 'flutter', 'opengl', 'canvas'], 16 | } 17 | 18 | def get_home(): 19 | import json 20 | import pathlib 21 | return pathlib.Path.home() 22 | 23 | def get_conf(): 24 | import json 25 | try: 26 | with open(f'{get_home()}/.photon/photon.conf') as c: 27 | return json.load(c) 28 | except FileNotFoundError: 29 | createConfFolder() 30 | return {'lang':'c'} 31 | 32 | def set_conf(**kwargs): 33 | import json 34 | data = get_conf() 35 | for key, val in kwargs.items(): 36 | if key in allowed_kwargs: 37 | if val in allowed_kwargs[key]: 38 | data[key] = val 39 | if key == 'lang': 40 | from dependencies import haveDependencies, resolveDependencies 41 | if not haveDependencies(val, sys.platform): 42 | resolveDependencies(val, sys.platform) 43 | print('Dependencies successfuly installed.') 44 | else: 45 | print(f'Value {val} is not allowed. You can try these: {", ".join(allowed_kwargs[key])}') 46 | else: 47 | print(f'Value {key} or {val} is not allowed. You can try these:') 48 | print(f'{"\n ".join([""] + allowed_kwargs)}') 49 | with open(f'{get_home()}/.photon/photon.conf', 'w') as c: 50 | json.dump(data, c) 51 | 52 | def getParameters(): 53 | parameters = get_conf() 54 | parameters.update(kwargs) 55 | return parameters 56 | 57 | def createConfFolder(): 58 | home = get_home() 59 | if not '.photon' in os.listdir(home): 60 | os.mkdir(f'{home}/.photon') 61 | 62 | @cli('version') 63 | def version(): 64 | 'Show photon version' 65 | print(f'Photon {__version__}') 66 | 67 | @cli('update') 68 | def update(): 69 | 'Update photon' 70 | os.system(f'git -C {PHOTON_INSTALL_PATH} pull') 71 | 72 | @cli('set') 73 | def set_config(**kwargs): 74 | 'Set a default parameter in the photon config' 75 | set_conf(**kwargs) 76 | 77 | @cli('') 78 | def run(filename, **kwargs): 79 | 'Run a script' 80 | from interpreter import Interpreter 81 | DEBUG = '-d' in flags or '--debug' in flags 82 | Interpreter( 83 | filename=filename, 84 | standardLibs=os.path.join( 85 | PHOTON_INSTALL_PATH, 'libs'), 86 | debug=DEBUG, 87 | **getParameters()).run() 88 | 89 | @cli('') 90 | def interpreter(): 91 | 'Open the interpreter' 92 | if flags: 93 | if '-v' in flags or '--version' in flags: 94 | version() 95 | elif '-h' in flags or '--help' in flags: 96 | cli_help() 97 | else: 98 | print(f'Flag {flags[0]} not valid here') 99 | else: 100 | from interpreter import Interpreter 101 | DEBUG = '-d' in flags or '--debug' in flags 102 | print(f'Photon - {__version__} - pyEngine') 103 | Interpreter( 104 | standardLibs=os.path.join( 105 | PHOTON_INSTALL_PATH, 'libs'), 106 | debug=DEBUG).run() 107 | -------------------------------------------------------------------------------- /core/photonParser.py: -------------------------------------------------------------------------------- 1 | # Photon parser 2 | # This script converts lines of photon code into tokens 3 | # and also generates the struct of the code. 4 | # This struct is used by the Engine to execute the code. 5 | 6 | import re 7 | from lexer import * 8 | 9 | statements = ['if','else','elif','def','cdef','for','in','as','return','import','class','while','break','continue','try', 'del', 'native', 'from'] 10 | operators = ['+','-','%','/','*','**','<','>','not', '!', 'and','or','is', '&'] 11 | builtins = ['open','input','sizeof','addr'] 12 | types = ['str','cstr','const','struct','char','int','float','double','struct', 'func','uint','ulong','ubyte','file'] 13 | symbols = { 14 | '.':'dot', 15 | '=':'equal', 16 | ':':'beginBlock', 17 | '(':'lparen', 18 | ')':'rparen', 19 | ',':'comma', 20 | '[':'lbracket', 21 | ']':'rbracket', 22 | "'":'singleQuote', 23 | '"':'doubleQuote', 24 | '#':'hashtag', 25 | ' ':'space', 26 | '\n':'newLine', 27 | '\t':'tab', 28 | '{':'lbrace', 29 | '}':'rbrace', 30 | '>':'greaterThan', 31 | '<':'lessThan', 32 | '_':'underline' 33 | } 34 | 35 | lineNumber = 0 36 | currentFilename = '' 37 | currentLine = '' 38 | parsePhrase = '' 39 | 40 | DEBUG = False 41 | 42 | def debug(*args, center=False): 43 | if DEBUG: 44 | if center: 45 | consoleWidth = os.get_terminal_size()[0] 46 | print(args[0].center(consoleWidth, '-')) 47 | else: 48 | print(*args) 49 | 50 | def parse(line, filename='', no=-1, debug=False): 51 | global currentLine, lineNumber, currentFilename, DEBUG 52 | ''' Return a list of tokens for the given line ''' 53 | DEBUG = debug 54 | lineNumber = no 55 | currentFilename = filename 56 | currentLine = line 57 | tokens = [i for i in re.split(r'(\W)',line) if not i == '' ] 58 | indentation = 0 59 | indentationSet = False 60 | tokenized = [] 61 | preserveSpace = False 62 | quote = '' 63 | for n, i in enumerate(tokens): 64 | if not indentationSet and not (i == ' ' or i == '\t'): 65 | indentationSet = True 66 | tokenized.append({'token':'indent','indent':indentation}) 67 | if (i == ' ' or i == '\t') and not indentationSet: 68 | indentation += 1 69 | elif i in statements: 70 | tokenized.append({'token':i+'Statement'}) 71 | elif i in operators: 72 | tokenized.append({'token':'operator','operator':i}) 73 | elif i in types: 74 | tokenized.append({'token':'type','type':i}) 75 | elif i in symbols: 76 | if i == ' ' and tokens[n+1] == '.' and tokenized[-1]['token'] in {'var', 'type', 'rbracket'}: 77 | tokenized.append({'token':symbols[i], 'symbol':i}) 78 | continue 79 | if i == "'" or i == '"': 80 | if not preserveSpace: 81 | preserveSpace = True 82 | quote = i 83 | elif preserveSpace and i == quote: 84 | tokenized.append({'token':symbols[i],'symbol':i}) 85 | preserveSpace = False 86 | quote = '' 87 | if not i in {'"', "'", ' ','\t','\n'} or (i in {'"',"'",' ','\t','\n'} and preserveSpace): 88 | tokenized.append({'token':symbols[i],'symbol':i}) 89 | elif i in builtins: 90 | tokenized.append({'token':i}) 91 | else: 92 | tokenized.append(inference(i)) 93 | 94 | if tokenized == []: 95 | tokenized = [{'token':'indent','indent':0}] 96 | return tokenized 97 | 98 | def token2word(tokens): 99 | phrase = '' 100 | for t in tokens: 101 | if t['token'] == 'indent': 102 | continue 103 | elif 'symbol' in t: 104 | phrase += t['symbol'] 105 | elif t['token'] in {'num', 'var', 'expr','print','printFunc', 106 | 'floatNumber', 'type', 'cast', 'special','open','openFunc', 107 | 'assign','operator','group','ifStatement','if','elifStatement', 108 | 'elif','else', 'elseStatement','input','inputFunc', 'args','call', 109 | 'whileStatement','while','forStatement','inStatement','for','range', 110 | 'defStatement','func','returnStatement','return','breakStatement', 111 | 'comment','augAssign','classStatement','class','dotAccess', 112 | 'importStatement','import', 'kwargs','keyVal','keyVals','forTarget', 113 | 'delStatement','delete', 'asStatement', 'nativeStatement', 'fromStatement', 114 | 'fromImport'}: 115 | phrase += t['token'] 116 | else: 117 | raise Exception(f'Cannot convert the token {t["token"]} to a word') 118 | phrase += ' ' 119 | return phrase[:-1] 120 | 121 | def reduceToken(tokens): 122 | ''' Find patterns that can be reduced to a single token 123 | and return the reduced list of tokens 124 | ''' 125 | global parsePhrase 126 | def reduce(): 127 | for pattern in patterns: 128 | for i in range(len(tokenList)): 129 | if pattern == tuple(tokenList[i:i+len(pattern)]): 130 | debug(pattern) 131 | result = reduceToken(patterns[pattern](i+1,tokens)) 132 | if result == 'continue': 133 | continue 134 | else: 135 | return result 136 | 137 | if tokens == 'continue': 138 | return 'continue' 139 | tokenList = [ token['token'] for token in tokens if not token['token'] == 'indent' ] 140 | parsePhrase = token2word(tokens) 141 | debug(parsePhrase) 142 | reducedTokens = reduce() 143 | if reducedTokens: 144 | tokens = reducedTokens 145 | 146 | # No patterns were found, reduced to maximum 147 | if len(tokens) > 2: #indent reducedToken (beginBlock) 148 | if not 'symbol' in tokens[0]: 149 | if 'indent' in tokens[0] and not 'symbol' in tokens[1]: 150 | showError(f'SyntaxError') 151 | return tokens 152 | 153 | def assembly(tokens, block=None, modifier=None): 154 | ''' Match the given list of tokens with the corresponding ''' 155 | ''' grammar and return a struct with its properties ''' 156 | if not block == None: 157 | if not 'block' in tokens[1]: 158 | tokens[1]['block'] = block 159 | return tokens 160 | else: 161 | showError('Not expecting an ifBlock here...') 162 | elif not modifier == None: 163 | if modifier[1]['token'] == 'elifStatement': 164 | if not 'elifs' in tokens[1]: 165 | tokens[1]['elifs'] = [] 166 | modifier = assembly(modifier) 167 | tokens[1]['elifs'].append({'expr':modifier['expr'], 'elifBlock':modifier['block']}) 168 | return tokens 169 | elif modifier[1]['token'] == 'elseStatement': 170 | if not 'else' in tokens[1]: 171 | tokens[1]['else'] = modifier[1]['block'] 172 | return tokens 173 | else: 174 | showError('Multiple else statements is not permitted') 175 | else: 176 | showError(f"Not implemented modifier handling for {modifier[1]['token']}") 177 | 178 | else: 179 | reduced = reduceToken(tokens) 180 | if len(reduced) > 1: 181 | struct = reduced[1] 182 | struct['opcode'] = struct['token'] 183 | return struct 184 | 185 | def showError(error): 186 | global currentLine, lineNumber, currentFilename 187 | msg = f''' 188 | 189 | 190 | Ops!! This is a syntax error or a parser error. 191 | Common causes: Missing "," ")" "}}" 192 | {error} 193 | This happened in line {currentFilename}:{lineNumber}. 194 | Last parsed line is "\n 195 | {currentLine}\n" 196 | Last Parse attempt was:\n "{parsePhrase}" 197 | ''' 198 | raise SyntaxError(msg) 199 | 200 | # Load grammar 201 | import os 202 | with open(f'{os.path.dirname(__file__)}/grammar/generatedGrammar.py') as g: 203 | exec(g.read()) 204 | 205 | -------------------------------------------------------------------------------- /core/toolchains/shared.py: -------------------------------------------------------------------------------- 1 | from toolchains.toolchain import BaseToolchain 2 | from photonParser import debug 3 | 4 | class Toolchain(BaseToolchain): 5 | def transpile(self): 6 | self.interpreter.run() 7 | 8 | def make(self): 9 | from subprocess import call, check_call 10 | debug(f'Compiling shared library...') 11 | links = list(self.interpreter.engine.links) 12 | filename = self.interpreter.engine.filename.split('.')[0] + '.c' 13 | libraryName = self.interpreter.filename.split('.')[0] + '.so' 14 | try: 15 | debug(' '.join(['gcc', '-O2', '-std=c99', f'Sources/c/{filename}'] + links + ['-o', 'Sources/c/main'])) 16 | check_call(['gcc', '-O2', '-std=c99', '-fPIC', '-shared', f'Sources/c/{filename}'] + links + ['-o', libraryName]) 17 | except Exception as e: 18 | print(e) 19 | print('Compilation error. Check errors above.') 20 | -------------------------------------------------------------------------------- /core/toolchains/toolchain.py: -------------------------------------------------------------------------------- 1 | from interpreter import Interpreter 2 | 3 | class BaseToolchain(): 4 | def __init__(self, platform, filename='main.w', test=False, standardLibs=''): 5 | self.standardLibs = standardLibs 6 | self.platform = platform 7 | self.test = test 8 | self.interpreter = Interpreter(filename, standardLibs=standardLibs, transpileOnly=True) 9 | 10 | def logcat(self): 11 | pass 12 | 13 | def getBuildFiles(self): 14 | pass 15 | 16 | def transpile(self): 17 | pass 18 | 19 | def prepare(self): 20 | pass 21 | 22 | def make(self): 23 | pass 24 | 25 | def runProject(self): 26 | pass 27 | -------------------------------------------------------------------------------- /core/transpilers/baseType.py: -------------------------------------------------------------------------------- 1 | class BaseType(): 2 | nativeTypes = { 3 | 'int':'int', 4 | 'str':'str', 5 | 'float':'float', 6 | 'bool':'bool', 7 | 'unknown':'unknown', 8 | '':'unknown', 9 | 'obj':'obj', 10 | 'file':'file', 11 | } 12 | 13 | def __init__(self, type, elementType=None, keyType=None, valType=None, returnType=None, funcName=None, argsTypes=None, name=None, namespace='', native=False, **kwargs): 14 | if isinstance(type, self.__class__): 15 | self.native = type.native 16 | self.namespace = type.namespace 17 | self.type = type.type 18 | self.elementType = type.elementType 19 | self.keyType = type.keyType 20 | self.valType = type.valType 21 | self.returnType = type.returnType 22 | self.funcName = type.funcName 23 | self.argsTypes = type.argsTypes 24 | self.name = type.name 25 | else: 26 | if type is not None and type.split(' ')[-1] == 'func': 27 | if ' ' in type: 28 | returnType, type = type.split(' ') 29 | else: 30 | type = 'func' 31 | returnType = '' 32 | self.native = native 33 | self.namespace = namespace 34 | self.type = type if type is not None else 'unknown' 35 | self.elementType = self.__class__(elementType) if self.isKnown(self.type) else 'unknown' 36 | self.keyType = self.__class__(keyType) if self.isKnown(self.type) else 'unknown' 37 | self.valType = self.__class__(valType) if self.isKnown(self.type) else 'unknown' 38 | self.returnType = self.__class__(returnType) if self.isKnown(self.type) else 'unknown' 39 | self.funcName = funcName if self.isKnown(self.type) else None 40 | self.argsTypes = argsTypes if self.isKnown(self.type) and isinstance(argsTypes, list) else [] 41 | self.name = name 42 | 43 | @property 44 | def known(self): 45 | if self.type == 'array' and self.isKnown(self.elementType): 46 | return True 47 | elif self.type == 'map' and self.isKnown(self.valType) and self.isKnown(self.keyType): 48 | return True 49 | elif self.type == 'func' and self.isKnown(self.returnType): 50 | return True 51 | elif self.type not in ['array', 'map'] and self.isKnown(self.type): 52 | return True 53 | else: 54 | return False 55 | 56 | @property 57 | def isPackage(self): 58 | if self.type == 'package' and self.name is not None: 59 | return True 60 | else: 61 | return False 62 | 63 | @property 64 | def isModule(self): 65 | if self.type == 'module' and self.name is not None: 66 | return True 67 | else: 68 | return False 69 | 70 | @property 71 | def isClass(self): 72 | if self.known and self.type in self.nativeTypes: 73 | return False 74 | elif self.known and not self.native and not self.type in self.nativeTypes and self.type not in ['array', 'map', 'module','package'] and not 'func' in self.type.split(' '): 75 | return True 76 | else: 77 | return False 78 | 79 | def isKnown(self, type): 80 | if isinstance(type, self.__class__): 81 | return type.known 82 | if type not in ['unknown', '']: 83 | return True 84 | return False 85 | 86 | def __str__(self): 87 | return repr(self) 88 | 89 | def __repr__(self): 90 | raise NotImplemented 91 | 92 | def __hash__(self): 93 | return hash((self.type, self.elementType, self.keyType, self.valType)) 94 | 95 | def __eq__(self, obj): 96 | return hash(obj) == self.__hash__() 97 | -------------------------------------------------------------------------------- /core/transpilers/cTranspiler.py: -------------------------------------------------------------------------------- 1 | from transpilers.baseTranspiler import BaseTranspiler 2 | from copy import deepcopy 3 | import os 4 | from string import Formatter 5 | 6 | def debug(*args): 7 | #print(*args) 8 | pass 9 | 10 | class Transpiler(BaseTranspiler): 11 | def __init__(self, filename, **kwargs): 12 | self.lang = 'c' 13 | self.loadTokens(self.lang) 14 | super().__init__(filename, **kwargs) 15 | self.libExtension = 'h' 16 | self.filename = self.filename.replace('.w', '.c') 17 | self.imports = {'#include ', '#include ', '#include ', '#include "main.h"'} 18 | self.links = set() 19 | if self.debug: 20 | # compile with debug symbols for gdb 21 | self.links.add('-g') 22 | self.links.add('-Wall') 23 | self.listTypes = set() 24 | self.dictTypes = set() 25 | self.classes = {} 26 | self.nativeTypes = { 27 | 'float': 'double', 28 | 'int': 'long', 29 | 'str': 'char*', 30 | 'bool': 'int', 31 | 'void': 'void', 32 | 'func': 'void', 33 | 'unknown': 'auto', 34 | 'file': 'FILE*' 35 | } 36 | self.builtins = { 37 | 'open':{'type':'file', 'value':'fopen'}, 38 | } 39 | 40 | def renderDictTemplate(self, keyType, valType): 41 | formatCodes = {'int':'%ld', 'str':'\\"%s\\"', 'float':'%lf'} 42 | with open(f'{self.standardLibs}/native/c/dict_{keyType}.template') as template: 43 | dictLib = template.read() 44 | if valType in self.classes: 45 | valNativeType = f"{valType}*" 46 | else: 47 | valNativeType = self.nativeTypes[valType] 48 | #TODO: Call instance repr if it exists instead of the placeholder 49 | dictLib = dictLib.replace('!@valType@!', valType).replace('!@valNativeType@!', valNativeType).replace('!@formatCode@!', formatCodes[valType] if valType in formatCodes else f'') 50 | with open(f'Sources/c/dict_{keyType}_{valType}.h', 'w') as lib: 51 | lib.write(dictLib) 52 | 53 | def renderListTemplate(self, valType): 54 | if not valType in {'str', 'int', 'float'}: 55 | with open(f'{self.standardLibs}/native/c/list_template.h') as template: 56 | listLib = template.read() 57 | listLib = listLib.replace('!@valType@!', valType) 58 | with open(f'Sources/c/list_{valType}.h', 'w') as lib: 59 | lib.write(listLib) 60 | 61 | def write(self): 62 | boilerPlateStart = [ 63 | 'int main() {', 64 | 'setlocale(LC_ALL, "");', 65 | ] 66 | boilerPlateEnd = [ 67 | 'return 0;', 68 | '}' 69 | ] 70 | if not 'Sources' in os.listdir(): 71 | os.mkdir('Sources') 72 | if not 'c' in os.listdir('Sources'): 73 | os.mkdir('Sources/c') 74 | if not self.module: 75 | self.filename = 'main.c' 76 | else: 77 | moduleName = self.filename.split('.')[0] 78 | self.filename = f'{moduleName}.c' 79 | boilerPlateStart = [] 80 | boilerPlateEnd = [] 81 | with open(f'Sources/c/main.h', 'w') as f: 82 | indent = 0 83 | f.write('#ifndef __main_h\n#define __main_h\n') 84 | if self.listTypes or self.dictTypes: 85 | self.imports.add('#include "asprintf.h"') 86 | listTypeHints = [] 87 | dictTypeHints = [] 88 | for listType in self.listTypes: 89 | if listType in self.classes: 90 | listTypeHints.append(f'typedef struct list_{listType} list_{listType};') 91 | self.classes[listType].postCode=f'\n#include "list_{listType}.h"\n' 92 | for keyType, valType in self.dictTypes: 93 | if valType in self.classes: 94 | dictTypeHints.append(f'typedef struct dict_{keyType}_{valType} dict_{keyType}_{valType};') 95 | self.classes[valType].postCode+=f'\n#include "dict_{keyType}_{valType}.h"\n' 96 | #TODO: do the same type hint for dicts 97 | for line in listTypeHints + dictTypeHints: 98 | #if '}' in line: 99 | # indent -= 4 100 | f.write(' '*indent + line+'\n') 101 | #if self.isBlock(line) and not ';' in line[-1]: 102 | # indent += 4 103 | f.write('#endif') 104 | with open(f'Sources/c/{self.filename}', 'w') as f: 105 | f.write('#ifndef __main\n#define __main\n') 106 | for imp in sorted(self.imports): 107 | module = imp.split(' ')[-1].replace('.w', '').replace('"', '') 108 | debug(f'Importing {module}') 109 | if module in os.listdir(f'{self.standardLibs}/native/c'): 110 | from shutil import copyfile 111 | copyfile(f'{self.standardLibs}/native/c/{module}', f'Sources/c/{module}') 112 | if not f'{module}.c' in os.listdir('Sources/c'): 113 | # native import 114 | f.write(imp + '\n') 115 | for valType in self.listTypes: 116 | self.renderListTemplate(valType) 117 | for keyType, valType in self.dictTypes: 118 | self.renderDictTemplate(keyType, valType) 119 | for line in [''] + boilerPlateStart + [''] + [self.sequence] + boilerPlateEnd: 120 | f.write(f'{line}\n') 121 | f.write('#endif') 122 | debug('Generated ' + self.filename) 123 | 124 | def run(self): 125 | from subprocess import call, check_call 126 | import sys 127 | self.write() 128 | debug(f'Running {self.filename}') 129 | try: 130 | if self.debug: 131 | optimizationFlags = ['-ggdb'] 132 | elif sys.platform == 'darwin': 133 | optimizationFlags = ['-Ofast'] 134 | else: 135 | optimizationFlags = ['-Ofast', '-frename-registers', '-funroll-loops'] 136 | debug(' '.join(['gcc', '-O2', '-std=c99', f'Sources/c/{self.filename}'] + list(self.links) + ['-o', 'Sources/c/main'])) 137 | check_call(['gcc'] + optimizationFlags + ['-std=c99', f'Sources/c/{self.filename}'] + list(self.links) + ['-o', 'Sources/c/main']) 138 | except Exception as e: 139 | print(e) 140 | print('Compilation error. Check errors above.') 141 | exit() 142 | else: 143 | if self.platform in {'linux', 'darwin'}: 144 | # don't call on Sources/c folder because of file paths 145 | call('./Sources/c/main') 146 | #call('./main', cwd='Sources/c') 147 | else: 148 | call('main', cwd='Sources/c', shell=True) 149 | -------------------------------------------------------------------------------- /core/transpilers/dTranspiler.py: -------------------------------------------------------------------------------- 1 | class Transpiler(): 2 | pass 3 | -------------------------------------------------------------------------------- /core/transpilers/jsTranspiler.py: -------------------------------------------------------------------------------- 1 | from transpilers.baseTranspiler import BaseTranspiler 2 | import os 3 | 4 | def debug(*args): 5 | #print(*args) 6 | pass 7 | 8 | class Transpiler(BaseTranspiler): 9 | def __init__(self, filename, **kwargs): 10 | self.lang = 'javascript' 11 | self.loadTokens('js') 12 | super().__init__(filename, **kwargs) 13 | self.filename = self.filename.replace('.w','.js') 14 | self.libExtension = 'js' 15 | self.imports = set() 16 | self.links = set() 17 | self.listTypes = set() 18 | self.dictTypes = set() 19 | self.classes = {} 20 | self.nativeTypes = { 21 | 'float':'float', 22 | 'int':'int', 23 | 'str':'str', 24 | 'bool':'bool', 25 | 'array':'list', 26 | 'unknown':'any', 27 | 'void':'None', 28 | } 29 | self.builtins = { 30 | 'open':{'type':'file', 'value':'open'}, 31 | } 32 | 33 | def write(self): 34 | boilerPlateStart = [ 35 | ] 36 | boilerPlateEnd = [ 37 | ] 38 | indent = 0 39 | count = 0 40 | if not 'Sources' in os.listdir(): 41 | os.mkdir('Sources') 42 | if not 'js' in os.listdir('Sources'): 43 | os.mkdir('Sources/js') 44 | if not self.module: 45 | self.filename = 'main.js' 46 | else: 47 | boilerPlateStart = [] 48 | boilerPlateEnd = [] 49 | with open(f'Sources/js/{self.filename}', 'w') as f: 50 | for imp in self.imports: 51 | module = imp.split(' ')[-1].replace('.w', '').replace('"', '') 52 | debug(f'Importing {module}') 53 | if f'{module}.js' in os.listdir('Sources/js'): 54 | with open(f'Sources/js/{module}.js', 'r') as m: 55 | for line in m: 56 | f.write(line) 57 | else: 58 | f.write(imp + '\n') 59 | for line in [''] + boilerPlateStart + [self.sequence] + boilerPlateEnd: 60 | f.write(f'{line}\n') 61 | debug('Generated ' + self.filename) 62 | 63 | def run(self): 64 | from subprocess import call, check_call 65 | self.write() 66 | debug(f'Running {self.filename}') 67 | try: 68 | check_call(['node', f'Sources/js/{self.filename}']) 69 | except: 70 | print('Compilation error. Check errors above.') 71 | -------------------------------------------------------------------------------- /core/transpilers/pyTokens.py: -------------------------------------------------------------------------------- 1 | # Basic Types 2 | from copy import deepcopy 3 | from pprint import pprint 4 | from .baseType import BaseType 5 | 6 | class Type(BaseType): 7 | nativeTypes = { 8 | 'int':'int', 9 | 'str':'str', 10 | 'float':'float', 11 | 'bool':'bool', 12 | 'unknown':'None', 13 | '':'None', 14 | 'obj':'obj', 15 | 'file':'TypeVar("file")', 16 | } 17 | 18 | def __repr__(self): 19 | if self.native: 20 | return f'TypeVar("{self.type}")' 21 | elif self.type == 'array': 22 | return f'list[{self.elementType.type}]' 23 | elif self.type == 'map': 24 | return f'dict[{self.keyType.type}, {self.valType.type}]' 25 | elif self.type == 'func': 26 | return f'Callable[[{", ".join(self.argsTypes)}], {self.returnType}]' 27 | elif self.type in self.nativeTypes: 28 | return self.nativeTypes[self.type] 29 | elif self.isClass: 30 | return f'TypeVar("{self.type}")' 31 | else: 32 | return f'TypeVar("{self.type}")' 33 | 34 | exec(open(__file__.rsplit('/', 1)[0]+"/tokens.py").read()) 35 | 36 | class Comment(Comment): 37 | pass 38 | 39 | class Null(Null): 40 | def __repr__(self): 41 | return 'None' 42 | 43 | class Module(Module): 44 | def __init__(self, expr, name, namespace, native=False, scope=None, filepath=''): 45 | super().__init__(expr, name, namespace, native=native, scope=scope, filepath='') 46 | if self.native: 47 | self.imports = [f'import {self.name}'] 48 | 49 | def __repr__(self): 50 | return f'#module {self.name}' 51 | 52 | class Group(Group): 53 | pass 54 | 55 | class Scope(Scope): 56 | beginSymbol = ':' 57 | endSymbol = '' 58 | def __repr__(self): 59 | if repr(self.sequence).strip(): 60 | return super().__repr__() 61 | else: 62 | return f':\n{self.indent}pass\n' 63 | 64 | class NativeCode(NativeCode): 65 | pass 66 | 67 | class Bool(Bool): 68 | def format(self): 69 | return f'"true" if {self.expression()} else "false"' 70 | 71 | def expression(self): 72 | return '1' if self.value == 'true' else '0' 73 | 74 | class Num(Num): 75 | pass 76 | 77 | class String(String): 78 | imports = [] 79 | def __repr__(self): 80 | if self.expressions: 81 | return f'{self.value}.format({", ".join([repr(expr) for expr in self.expressions])})' 82 | return self.value 83 | 84 | class Var(Var): 85 | imports = [] 86 | def prepare(self): 87 | if self.namespace: 88 | self.name = f'{self.namespace}__{self.value}' 89 | else: 90 | self.name = self.value 91 | 92 | def declaration(self): 93 | return f'{self.value}:{self.type}' 94 | 95 | def format(self): 96 | if self.type.type in ['map', 'array']: 97 | if not self.indexAccess: 98 | return f'str({self.name})' 99 | return self.expression() 100 | if self.type.type == 'bool': 101 | return f'"true" if {self.name} else "false"' 102 | if self.type.type not in ['str','int','float', 'bool']: 103 | if self.type.isClass: 104 | return f'""' 105 | return f'str({self.name})' 106 | return self.name 107 | 108 | def method(self): 109 | return f'{self.name}' 110 | 111 | def expression(self): 112 | if self.indexAccess: 113 | if self.type.type == 'array': 114 | return f'{self.name}[{self.indexAccess}]' 115 | if self.type.type == 'map': 116 | return f'{self.name}[{self.indexAccess}]' 117 | else: 118 | return f'{self.name}[{self.indexAccess}]' 119 | return self.name 120 | 121 | class Expr(Expr): 122 | operatorOrder = [ 123 | 'not','**','*','%','/','-','+','==','!=','>','<','>=','<=', 124 | 'is','in','andnot','and','or','&', '<<', '>>' 125 | ] 126 | opConversions = { 127 | 'and': 'and', 128 | 'or': 'or', 129 | 'not': 'not', 130 | } 131 | def concatenate(self, arg1, arg2, t): 132 | return Expr(value=f'{arg1} + {arg2}', type=t) 133 | 134 | class Delete(Delete): 135 | def __repr__(self): 136 | self.expr.mode = 'method' 137 | if self.expr.type.type in ['array', 'map']: 138 | return f'del {self.expr}[{self.expr.value.indexAccess}]' 139 | if isinstance(self.expr.value, DotAccess): 140 | return f'del {self.expr}[{self.expr.value.indexAccess}]' 141 | raise SyntaxError(f'Delete not supported for type {type(self.expr.value)}') 142 | 143 | class DotAccess(DotAccess): 144 | imports = [] 145 | def format(self): 146 | if self.type.isClass or self.type.type in ['array', 'map']: 147 | return f'str({self.value})' 148 | return self.value 149 | 150 | def expression(self): 151 | if self.chain[0].type.isModule: 152 | self.chain[0].namespace = '' 153 | chain = [repr(self.chain[0])] 154 | currentType = self.chain[0].type 155 | for n, c in enumerate(self.chain[1:]): 156 | if currentType.native: 157 | chain.append('.') 158 | chain.append(repr(c)) 159 | elif currentType.type == 'file': 160 | if isinstance(c, Call): 161 | if repr(c.name) in ['write', 'close', 'read']: 162 | if repr(c.name) == 'read' and not c.args: 163 | c.name.value = 'readline' 164 | chain.append('.') 165 | chain.append(repr(c)) 166 | else: 167 | raise SyntaxError(f'File object has no method {c.name}') 168 | else: 169 | raise SyntaxError(f'File object has no attribute {c}') 170 | elif currentType.type == 'array' and isinstance(c, Call): 171 | chain.append('.') 172 | chain.append(repr(c)) 173 | elif currentType.type == 'array' and isinstance(c, Var): 174 | if repr(c) == 'len': 175 | varName = ''.join(chain) 176 | chain = [f'len({varName})'] 177 | else: 178 | chain.append('.') 179 | chain.append(c.name) 180 | elif c.type.type == 'array' and getattr(c, 'indexAccess', None): 181 | chain.append('.') 182 | chain.append(repr(c)) 183 | c.type = c.type.elementType 184 | elif currentType.isClass and isinstance(c, Call): 185 | instanceName = ''.join(chain) 186 | #TODO this fails sometimes but a method 187 | # always should have the self... 188 | if c.signature: 189 | del c.signature[0] 190 | if c.args.args: 191 | del c.args.args[0] 192 | if instanceName == 'super': 193 | chain.append('().') 194 | chain.append(repr(c)) 195 | else: 196 | chain.append('.') 197 | chain.append(repr(c)) 198 | elif currentType.isModule: 199 | if currentType.native: 200 | input(f'Is native {c}') 201 | else: 202 | chain = [repr(c)] 203 | else: 204 | chain.append('.') 205 | chain.append(repr(c)) 206 | currentType = c.type 207 | if self.mode == 'method': 208 | self.chain[-1].mode = 'method' 209 | chain[-1] = repr(self.chain[-1]) 210 | self.chain[-1].mode = 'expr' 211 | self.processed = True 212 | return ''.join(chain) 213 | 214 | class Return(Return): 215 | def __repr__(self): 216 | return f'return {self.expr}' 217 | 218 | class Array(Array): 219 | imports = [] 220 | def prepare(self): 221 | self.len = len(self.elements) 222 | self.size = 8 if self.len < 8 else self.len 223 | 224 | def expression(self): 225 | return '[' + ','.join([repr(e) for e in self.elements]) + ']' 226 | 227 | def __repr__(self): 228 | self.prepare() 229 | value = self.expression() 230 | if self.mode == 'format': 231 | return f'str({value})' 232 | return value 233 | 234 | class KeyVal(KeyVal): 235 | def __repr__(self): 236 | return f'{self.key}:{self.val}' 237 | 238 | class Map(Map): 239 | def __repr__(self): 240 | return '{' + ', '.join([repr(kv) for kv in self.keyVals])+ '}' 241 | 242 | class Open(Open): 243 | def __repr__(self): 244 | return f'open({self.args})' 245 | 246 | class Input(Input): 247 | imports = [] 248 | def __repr__(self): 249 | return f'input({self.expr})' 250 | 251 | class Break(Break): 252 | def __repr__(self): 253 | return f'break' 254 | 255 | # Representation Types 256 | 257 | class Sequence(Sequence): 258 | def __init__(self, objs=None, terminator='', apply=None): 259 | super().__init__(objs=objs, terminator=terminator, apply=apply) 260 | 261 | class Cast(Cast): 262 | conversion = { 263 | 'int':{ 264 | 'str': 'int({self.expr})', 265 | 'float': 'int({self.expr})', 266 | }, 267 | 'float':{ 268 | 'str': 'float({self.expr})', 269 | 'int': 'float({self.expr})', 270 | }, 271 | 'str':{ 272 | 'int': 'str({self.expr})', 273 | 'float': 'str({self.expr})', 274 | }, 275 | } 276 | 277 | def __repr__(self): 278 | self.expr.namespace = self.namespace 279 | castFrom = self.expr.type.type 280 | castTo = self.castTo.type 281 | if castTo == 'map': 282 | castTo = self.castTo.valType.type 283 | elif castTo == 'array' and castFrom == 'array': 284 | return f'{self.expr}' 285 | elif castTo == 'array': 286 | castTo = self.castTo.elementType.type 287 | if castFrom == 'map' and self.expr.indexAccess is not None: 288 | castFrom = self.expr.type.valType 289 | elif castFrom == 'array' and self.expr.indexAccess is not None: 290 | castFrom = self.expr.type.elementType 291 | try: 292 | if self.castTo.isClass: 293 | return f'{self.expr}' 294 | elif castTo != castFrom and castTo in self.conversion: 295 | return self.conversion[castTo][castFrom].format(self=self) 296 | return repr(self.expr) 297 | except KeyError as e: 298 | raise SyntaxError(f'Cast not implemented for type {castTo} from {castFrom} {e}') 299 | 300 | class Assign(Assign): 301 | def declaration(self): 302 | return f'{self.target}:{self.target.type}' 303 | 304 | def expression(self): 305 | if self.inMemory or isinstance(self.target, DotAccess): 306 | if self.target.indexAccess: 307 | if self.target.type.type == 'array': 308 | return f'{self.target.name}[{self.target.indexAccess}] = {self.value}' 309 | if self.target.type.type == 'map': 310 | return f'{self.target.name}[{self.target.indexAccess}] = {self.value}' 311 | else: 312 | # indexAccess already processed in self.target 313 | return f'{self.target} = {self.value}' 314 | return f'{self.target} = {self.value}' 315 | else: 316 | return f'{self.target}:{self.target.type} = {self.value}' 317 | 318 | class Args(Args): 319 | pass 320 | 321 | class Kwargs(Kwargs): 322 | def __repr__(self): 323 | self.prepare() 324 | if self.mode == 'value': 325 | return ', '.join([repr(kwarg.value) for kwarg in self.kwargs]) 326 | return ', '.join([repr(kwarg) for kwarg in self.kwargs]) 327 | 328 | class Call(Call): 329 | def __repr__(self): 330 | if self.mode == 'format' and self.type.isClass: 331 | return f'""' 332 | if self.signature: 333 | kwargs = [] 334 | args = [] 335 | # allocate args then sort kwargs 336 | for s in self.signature[len(self.args.args):]: 337 | for kwarg in self.kwargs.kwargs: 338 | if isinstance(s, Assign): 339 | kwarg.target.namespace = '' 340 | if s.target.index == kwarg.target.index: 341 | if kwarg.type != s.type: 342 | kwarg = Cast(Expr(kwarg.value), s.type) 343 | kwargs.append(kwarg) 344 | break 345 | else: 346 | kwargs.append(s) 347 | kwargs = Kwargs(kwargs, mode='value') 348 | for arg, sig in zip(self.args, self.signature): 349 | if arg.type != sig.type: 350 | args.append(Cast(arg, sig.type)) 351 | else: 352 | args.append(arg) 353 | args = Args(args, mode='expr') 354 | else: 355 | kwargs = [] 356 | for kwarg in self.kwargs.kwargs: 357 | kwarg.namespace = '' 358 | kwargs.append(kwarg) 359 | kwargs = Kwargs(kwargs, mode='value') 360 | args = self.args 361 | separator = ', ' if args and kwargs else '' 362 | if self.type.isClass: 363 | return f'{self.name}({args}{separator}{kwargs})' 364 | else: 365 | return f'{self.name}({args}{separator}{kwargs})' 366 | 367 | class Print(Print): 368 | def __repr__(self): 369 | return f'print({self.args})' 370 | 371 | class Function(Function): 372 | def expression(self): 373 | return f'def {self.name}({self.args}{self.separator}{self.kwargs}) -> {self.name.type} {self.code}' 374 | 375 | class Class(Class): 376 | def formatNewMethod(self): 377 | paramsInit = [] 378 | for p in self.parameters.values(): 379 | if isinstance(p, Assign): 380 | if not p.target.attribute: 381 | paramsInit.append( 382 | NativeCode(f'self.{p.target} = {p.value}')) 383 | else: 384 | paramsInit.append( 385 | NativeCode(f'self.{p.target} = {p.target}')) 386 | elif isinstance(p, Expr): 387 | paramsInit.append( 388 | NativeCode(f'self.{p} = None')) 389 | code = paramsInit + self.new.code.sequence.sequence 390 | self.new.code = Scope(code) 391 | 392 | def __repr__(self): 393 | value = f'class {self.name}({self.args}):\n' 394 | self.writeMode() 395 | for method in self.methods.values(): 396 | if method.name.value == 'new': 397 | method = deepcopy(method) 398 | method.name.value = '__init__' 399 | method.name.type = Type('unknown') 400 | if not method.args.args or not repr(method.args.args[0].name) != "self": 401 | method.args.args.insert(0, Var('self', repr(self.name))) 402 | method.namespace = '' 403 | method.code.indent = ' '*8 404 | value += f' {method}\n' 405 | return value+self.postCode 406 | 407 | class Elif(Elif): 408 | def __repr__(self): 409 | return f'elif {self.expr} {self.block}' 410 | 411 | class Else(Else): 412 | def __repr__(self): 413 | return f'else {self.block}' 414 | 415 | class If(If): 416 | def __repr__(self): 417 | return f'if {self.expr} {self.ifBlock}{"".join(repr(e) for e in self.elifs)}{self.elseBlock}' 418 | 419 | class While(While): 420 | def __repr__(self): 421 | return f'while {self.expr} {self.block}' 422 | 423 | class For(For): 424 | def __repr__(self): 425 | if isinstance(self.iterable, Range): 426 | if len(self.args.args) == 1: 427 | return f'for {self.args[0]} in range({self.iterable.initial}, {self.iterable.final}, {self.iterable.step}) {self.code}' 428 | if len(self.args.args) == 2: 429 | return f'for {self.args[0]}, {self.args[1]} in enumerate(range({self.iterable.initial}, {self.iterable.final}, {self.iterable.step})) {self.code}' 430 | elif isinstance(self.iterable, Expr): 431 | if self.iterable.type.type == 'array': 432 | if len(self.args.args) == 1: 433 | return f'for {self.args[0]} in {self.iterable} {self.code}' 434 | if len(self.args.args) == 2: 435 | return f'for {self.args[0]}, {self.args[1]} in enumerate({self.iterable}) {self.code}' 436 | if self.iterable.type.type == 'map': 437 | if len(self.args.args) == 1: 438 | return f'for {self.args[0]} in {self.iterable} {self.code}' 439 | if len(self.args.args) == 2: 440 | return f'for {self.args[0]}, {self.args[1]} in {self.iterable}.items() {self.code}' 441 | if self.iterable.type.type == 'str': 442 | if len(self.args.args) == 1: 443 | return f'for {self.args[0]} in {self.iterable} {self.code}' 444 | if len(self.args.args) == 2: 445 | return f'for {self.args[0]}, {self.args[1]} in enumerate({self.iterable}) {self.code}' 446 | else: 447 | raise TypeError('Iterable type is unknown') 448 | else: 449 | raise ValueError(f'Iterable of type {type(self.iterable)} no supported in for.') 450 | 451 | class Range(Range): 452 | pass 453 | 454 | class AugAssign(AugAssign): 455 | pass 456 | -------------------------------------------------------------------------------- /core/transpilers/pyTranspiler.py: -------------------------------------------------------------------------------- 1 | from transpilers.baseTranspiler import BaseTranspiler 2 | import os 3 | 4 | def debug(*args): 5 | #print(*args) 6 | pass 7 | 8 | class Transpiler(BaseTranspiler): 9 | def __init__(self, filename, **kwargs): 10 | self.lang = 'python' 11 | self.loadTokens('py') 12 | super().__init__(filename, **kwargs) 13 | self.filename = self.filename.replace('.w','.py') 14 | self.libExtension = 'py' 15 | self.imports = {"from collections.abc import Callable","from typing import TypeVar"} 16 | self.links = set() 17 | self.listTypes = set() 18 | self.dictTypes = set() 19 | self.classes = {} 20 | self.nativeTypes = { 21 | 'float':'float', 22 | 'int':'int', 23 | 'str':'str', 24 | 'bool':'bool', 25 | 'array':'list', 26 | 'unknown':'any', 27 | 'void':'None', 28 | } 29 | self.builtins = { 30 | 'open':{'type':'file', 'value':'open'}, 31 | } 32 | 33 | def write(self): 34 | boilerPlateStart = [ 35 | ] 36 | boilerPlateEnd = [ 37 | ] 38 | indent = 0 39 | count = 0 40 | if not 'Sources' in os.listdir(): 41 | os.mkdir('Sources') 42 | if not 'py' in os.listdir('Sources'): 43 | os.mkdir('Sources/py') 44 | if not self.module: 45 | self.filename = 'main.py' 46 | else: 47 | #self.filename = f'{moduleName}.py' 48 | boilerPlateStart = [] 49 | boilerPlateEnd = [] 50 | with open(f'Sources/py/{self.filename}', 'w') as f: 51 | for imp in self.imports: 52 | module = imp.split(' ')[-1].replace('.w', '').replace('"', '') 53 | debug(f'Importing {module}') 54 | if f'{module}.py' in os.listdir('Sources/py'): 55 | with open(f'Sources/py/{module}.py', 'r') as m: 56 | for line in m: 57 | f.write(line) 58 | else: 59 | f.write(imp + '\n') 60 | for line in [''] + boilerPlateStart + [self.sequence] + boilerPlateEnd: 61 | f.write(f'{line}\n') 62 | debug('Generated ' + self.filename) 63 | 64 | def run(self): 65 | from subprocess import call, check_call 66 | self.write() 67 | debug(f'Running {self.filename}') 68 | try: 69 | check_call(['python', f'Sources/py/{self.filename}']) 70 | except: 71 | print('Compilation error. Check errors above.') 72 | -------------------------------------------------------------------------------- /core/transpilers/tsTranspiler.py: -------------------------------------------------------------------------------- 1 | from transpilers.jsTranspiler import Transpiler as JSTranspiler 2 | import os 3 | 4 | def debug(*args): 5 | #print(*args) 6 | pass 7 | 8 | class Transpiler(JSTranspiler): 9 | def __init__(self, filename, **kwargs): 10 | super().__init__(filename, **kwargs) 11 | self.filename = self.filename.replace('.w','.ts') 12 | self.lang = 'ts' 13 | 14 | def formatInput(self, expr): 15 | message = expr['value'] 16 | message = message[:-2] + '"' 17 | return f'prompt({message})' 18 | 19 | def formatFor(self, variables, iterable): 20 | if iterable['type'] in {'array', 'str'}: 21 | jsFormatFor = super().formatFor(variables, iterable) 22 | # now self.iterVar is updated, we can use it 23 | return f'var {self.iterVar[-1][0]}; ' + jsFormatFor 24 | return super().formatFor(variables, iterable) 25 | 26 | def formatPrint(self, value, terminator='\\n'): 27 | if value['value']: 28 | return f'Deno.writeAll(Deno.stdout, new TextEncoder().encode(JSON.stringify({value["value"]})+"{terminator}"))' 29 | return f'Deno.writeAll(Deno.stdout, new TextEncoder().encode("{terminator}"))' 30 | 31 | def write(self): 32 | boilerPlateStart = [ 33 | ] 34 | boilerPlateEnd = [ 35 | ] 36 | indent = 0 37 | count = 0 38 | if not 'Sources' in os.listdir(): 39 | os.mkdir('Sources') 40 | if not 'ts' in os.listdir('Sources'): 41 | os.mkdir('Sources/ts') 42 | if not self.module: 43 | self.filename = 'main.js' 44 | else: 45 | self.filename = f'{moduleName}.js' 46 | boilerPlateStart = [] 47 | boilerPlateEnd = [] 48 | del self.imports[0] 49 | del self.imports[0] 50 | del self.imports[0] 51 | # Force utf8 on windows 52 | with open(f'Sources/ts/{self.filename}', 'w', encoding='utf8') as f: 53 | for imp in self.imports: 54 | module = imp.split(' ')[-1].replace('.w', '').replace('"', '') 55 | debug(f'Importing {module}') 56 | if f'{module}.ts' in os.listdir('Sources/ts'): 57 | with open(f'Sources/ts/{module}.js', 'r') as m: 58 | for line in m: 59 | f.write(line) 60 | else: 61 | f.write(imp + '\n') 62 | for line in [''] + self.outOfMain + [''] + boilerPlateStart + self.source + boilerPlateEnd: 63 | if line: 64 | if line.startswith('}'): 65 | indent -= 4 66 | f.write(' ' * indent + line.replace('/*def*/', '') + '\n') 67 | if self.isBlock(line): 68 | indent += 4 69 | debug('Generated ' + self.filename) 70 | 71 | def run(self): 72 | from subprocess import call, check_call 73 | self.write() 74 | debug(f'Running {self.filename}') 75 | try: 76 | check_call(['deno', 'run', f'Sources/ts/{self.filename}']) 77 | except Exception as e: 78 | print(f'Compilation error {e}. Check errors above.') 79 | -------------------------------------------------------------------------------- /examples/callback_ex.w: -------------------------------------------------------------------------------- 1 | 2 | def xyz(int a, float b, str c, int d = [], float e = [], str f = []): 3 | print("{a} | {b} | {c} | {d} | {e} | {f}") 4 | 5 | def test(func callback): 6 | callback(1, 2.0, "Matheus", [1, 2], [1.0, 2.0], ["PHO", "TON"]) 7 | 8 | test(xyz) 9 | -------------------------------------------------------------------------------- /examples/class_ex.w: -------------------------------------------------------------------------------- 1 | 2 | class Person(): 3 | 4 | def new(.name = "Matheus", .age = 23, .gen = "1"): 5 | 6 | def print_name(): 7 | print("My name is {.name}") 8 | 9 | def print_age(): 10 | print("My age is {.age} years old") 11 | 12 | def print_gen(): 13 | if .gen == "1" or .gen == "Man": 14 | .gen = "Man" 15 | elif .gen == "0" or .gen == "Woman": 16 | .gen = "Woman" 17 | else: 18 | .gen = "Undefined" 19 | print("I am a {.gen}") 20 | 21 | person = Person() 22 | person.print_name() 23 | person.print_age() 24 | person.print_gen() 25 | 26 | print() 27 | 28 | person = Person(age=30) 29 | person.name = "William" 30 | person.print_name() 31 | person.print_age() 32 | -------------------------------------------------------------------------------- /examples/conditionals_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # Variable that is used in the conditional logic test below 3 | int num = 3 4 | 5 | # If the value stored in the variable `num` is equal to 3 do: 6 | if num == 3: 7 | print("The number entered in the variable `num` is 3") 8 | 9 | # Otherwise, if the value stored in the variable `num` is equal to 4, do: 10 | elif num == 4: 11 | print("The number entered in the variable `num` is 4") 12 | 13 | # If the value is neither 3 nor 4 do: 14 | else: 15 | print("The number entered in the variable `num` is neither 3 nor 4") 16 | -------------------------------------------------------------------------------- /examples/dict_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # The dictionary structure is a way of relating a key to a value. 3 | # Where the pair (key:value) must have their respective types. 4 | 5 | # Type examples for (key:value dictionary_name): 6 | # int:int `dictionary_name` 7 | # int:float `dictionary_name` 8 | # int:str `dictionary_name` 9 | 10 | # Example of creating and assigning keys and values to the dictionary 11 | #int:int my_dict = { 1:1, 2:4, 3:9, 4:16 } 12 | 13 | int:int dict_int = {} 14 | dict_int[1] = 1 15 | dict_int[2] = 4 16 | dict_int[3] = 9 17 | dict_int[4] = 16 18 | 19 | print("# Iterating by index") 20 | # This structure only works if the key is a sequence of integers. 21 | for i in 1..dict_int.len + 1: 22 | print("The key {i} contains the value {dict_int[i]}") 23 | 24 | # Deletes an element from the dictionary using the entered key 25 | del dict_int[2] 26 | 27 | # Line break 28 | print() 29 | 30 | print("# Gets the key and value in each dictionary iteration") 31 | for key, value in dict_int: 32 | print("The key {key} contains the value {value}") 33 | 34 | # Line break 35 | print() 36 | 37 | int:str dict_str = {} 38 | dict_str[1] = "P" 39 | dict_str[2] = "H" 40 | dict_str[3] = "O" 41 | dict_str[4] = "T" 42 | dict_str[5] = "O" 43 | dict_str[6] = "N" 44 | 45 | print(dict_str) 46 | -------------------------------------------------------------------------------- /examples/ffi/ffi_photon.py: -------------------------------------------------------------------------------- 1 | 2 | # pip install photon-lang 3 | # python ffi_photon.py 4 | import photon_lang 5 | 6 | # Name of `main.so` 7 | import main 8 | 9 | # Calling function implemented through photon 10 | main.compute() 11 | -------------------------------------------------------------------------------- /examples/ffi/main.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HashLDash/Photon/bfd206db3b91b695139cbde47bc39ba59057d122/examples/ffi/main.so -------------------------------------------------------------------------------- /examples/ffi/main.w: -------------------------------------------------------------------------------- 1 | 2 | # To generate the shared constructor file (`main.so` or `main.dll`) you need to use the command: 3 | # photon --build shared 4 | 5 | def compute(): 6 | for i in 0..10: 7 | print("Ok {i}") 8 | -------------------------------------------------------------------------------- /examples/for_target_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # On the `C` target, do: 3 | for C: 4 | print("Target C") 5 | 6 | # On the `D` target, do: 7 | for D: 8 | print("Target D") 9 | 10 | # On the `JS` target, do: 11 | for JS: 12 | print("Target JavaScript") 13 | 14 | # On the `TS` target, do: 15 | for TS: 16 | print("Target TypeScript") 17 | 18 | # On the `DART` target, do: 19 | for DART: 20 | print("Target Dart") 21 | 22 | # On the `HAXE` target, do: 23 | for HAXE: 24 | print("Target Haxe") 25 | 26 | # On the `PY` target, do: 27 | for PY: 28 | print("Target Python") 29 | -------------------------------------------------------------------------------- /examples/functions_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # Functions are made up of parameters and a return value type. 3 | # Data types that can be used to define parameters/return: int, float, str... 4 | # Every function has def `return type` `function name` (`parameter type and name, next parameter`) 5 | 6 | def int add(int x, int y): 7 | return x + y 8 | 9 | def float sub(float x, float y): 10 | return x - y 11 | 12 | def example(int a = 0, int b = 0): 13 | print("A = {a} | B = {b}") 14 | 15 | def add_list(int list = []): 16 | int sum = 0 17 | for num in list: 18 | sum += num 19 | return sum 20 | 21 | print("Add 3 + 1 = {add(3, 1)}") 22 | 23 | # Line break 24 | print() 25 | 26 | print("Sub 5 - 2.1 = {sub(5, 2.1)}") 27 | 28 | # Line break 29 | print() 30 | 31 | # Line break 32 | example() 33 | # You must specify the name of each argument that has a default value, 34 | # otherwise the entered value will be ignored and the default value applied. 35 | example(1, 2) # Don't do like that 36 | example(a = 1, b = 2) # Do like this 37 | example(b = 1, a = 2) # Do like this 38 | 39 | # Line break 40 | print() 41 | 42 | int list = [1, 2, 3, 4] 43 | 44 | print("Add {list} = {add_list(list=list)}") 45 | 46 | # Line break 47 | #print() 48 | 49 | #def test(func callback): 50 | # print(callback(1, 2)) 51 | 52 | #test(add) 53 | -------------------------------------------------------------------------------- /examples/list_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # The list starts with index 0 3 | list = [1, 2, 3, 4] 4 | print("List: {list}") 5 | 6 | # Removing the second element from the list 7 | del list[2] 8 | print("The element in index 2 has been removed.") 9 | 10 | print("List: {list}") 11 | 12 | # Line break 13 | print() 14 | 15 | # A list of strings 16 | str list_of_str = [] 17 | 18 | # Adding elements to the list 19 | # At each call of `+=` a new element will be assigned to a new index 20 | list_of_str += "P" 21 | list_of_str += "h" 22 | list_of_str += "o" 23 | list_of_str += "t" 24 | list_of_str += "o" 25 | list_of_str += "n" 26 | 27 | # Iterating a list through variable i 28 | for i in 0..list_of_str.len: 29 | print("The key {i} contains the value {list_of_str[i]}") 30 | 31 | # Line break 32 | print() 33 | 34 | # The foreach cycles through the list and returns a key-value pair 35 | for key, value in list_of_str: 36 | print("The key {key} contains the value {value}") 37 | 38 | # Line break 39 | print() 40 | 41 | # The foreach is also capable of traversing a string (list of characters) 42 | for index, caracter in "Photon": 43 | print('The {index + 1}st character of the string is: {caracter}') 44 | 45 | -------------------------------------------------------------------------------- /examples/loops_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # FOR iteration structure 3 | # This loop will go from 0 to 4, and at each iteration the variable `i` will be incremented from 1 in 1. 4 | for i in 0..5: 5 | print("For: {i}") 6 | 7 | # Separate output with a new line 8 | print() 9 | 10 | i = 5 11 | # WHILE iteration structure 12 | 13 | while i >= 0: 14 | print("While: {i}") 15 | i = i - 1 16 | -------------------------------------------------------------------------------- /examples/print_and_input_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # The `print` function allows displaying in the command line interface (CLI) a certain value 3 | # informed in the argument. 4 | print("Hi.") 5 | 6 | # The `input` function allows to obtain a textual value informed in the command line 7 | # interface (CLI), the function's return will always be a string. 8 | name = input("What is your name? ") 9 | 10 | # Displaying the string with the value 'Hello, ' along with the name given above. 11 | # In the example below, the string interpolation technique is used to include the name value. 12 | print("Hello, {name}") 13 | 14 | # Displays a line break. 15 | print() 16 | 17 | # In this case, the input function's return is cast from string to integer 18 | int a = input("Enter an integer: ") 19 | # or float in this case 20 | float b = input("Enter a number with decimal places: ") 21 | 22 | # Displaying the sum result. 23 | print("The sum of {a} + {b} = {a + b}") 24 | -------------------------------------------------------------------------------- /examples/random_ex.w: -------------------------------------------------------------------------------- 1 | 2 | for C: 3 | 4 | import time 5 | 6 | srand(time(NULL)) 7 | 8 | def float random_example(float begin = 0.0, float end = 0.0): 9 | float gen = rand() / RAND_MAX 10 | if begin != 0.0 or end != 0.0: 11 | gen = gen * (end - begin) + begin 12 | return gen 13 | 14 | def test_random_example(float begin, float end, int max_iteration = 100000): 15 | x = 0 16 | y = 0 17 | z = 0 18 | float k = [] 19 | for i in 0..max_iteration: 20 | gen = random_example(begin = begin, end = end) 21 | if gen == begin: 22 | x += 1 23 | elif gen == end: 24 | y += 1 25 | else: 26 | z += 1 27 | k += gen 28 | print("max_iteration: {max_iteration == (x + y + z)}") 29 | print("x: {x} | Begin: {begin}") 30 | print("y: {y} | End: {end}") 31 | print("z: {z} | Interval: {begin}..{end}") 32 | #print("k: ", end='') 33 | #print(k) 34 | print() 35 | 36 | test_random_example(-5, 5) 37 | -------------------------------------------------------------------------------- /examples/run_all_ex.w: -------------------------------------------------------------------------------- 1 | # File import example 2 | 3 | print("---------------------------------------------") 4 | print("# import callback_ex") 5 | import callback_ex 6 | 7 | print("---------------------------------------------") 8 | print("# import class_ex") 9 | import class_ex 10 | 11 | print("---------------------------------------------") 12 | print("# import conditionals_ex") 13 | import conditionals_ex 14 | 15 | #print("---------------------------------------------") 16 | #print("# import dict_ex") 17 | #import dict_ex 18 | 19 | print("---------------------------------------------") 20 | print("# import for_target_ex") 21 | import for_target_ex 22 | 23 | print("---------------------------------------------") 24 | print("# import functions_ex") 25 | import functions_ex 26 | 27 | #print("---------------------------------------------") 28 | #print("# import list_ex") 29 | #import list_ex 30 | 31 | print("---------------------------------------------") 32 | print("# import loops_ex") 33 | import loops_ex 34 | 35 | print("---------------------------------------------") 36 | print("# import variables_ex") 37 | import variables_ex 38 | 39 | print("---------------------------------------------") 40 | print("# import random_ex") 41 | import random_ex 42 | 43 | print("---------------------------------------------") 44 | print("# import print_and_input_ex") 45 | import print_and_input_ex 46 | -------------------------------------------------------------------------------- /examples/test_ex.w: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/variables_ex.w: -------------------------------------------------------------------------------- 1 | 2 | # Variables in the photon language can be inferred or explicitly typed. 3 | #----------------------------------------------------------------------------------------- 4 | # Every variable contains three elements. Type, Name and Value. By default, Photon 5 | # tries to infer the type of the variable based on the assigned value. 6 | 7 | #----------------------------------------------------------------------------------------- 8 | # Type inference in action 9 | my_int = 1 10 | my_float = 3.1415 11 | my_string = "The name of this programming language is called Photon" 12 | my_int_array = [1, 2, 3] 13 | my_float_array = [1.1, 2.1, 3.1] 14 | my_str_array = ["My name", "is Johann"] 15 | 16 | print("Variables typed by inference:") 17 | print(my_int) 18 | print(my_float) 19 | print(my_string) 20 | print(my_int_array) 21 | print(my_float_array) 22 | print(my_str_array) 23 | print() 24 | 25 | #----------------------------------------------------------------------------------------- 26 | # Explicitly typed variables 27 | 28 | # Integer number 29 | int number_int = 1 30 | 31 | # Floating point number 32 | float number_real = 3.1415 33 | 34 | # String of characters 35 | str text = "The name of this programming language is called Photon" 36 | 37 | # Array of integers 38 | int array_int = [] 39 | # Append elements on array of integers 40 | array_int += 1 41 | array_int += 2 42 | array_int += 3 43 | 44 | # Array of floats 45 | float array_float = [] 46 | # Append elements on array of floats 47 | array_float += 1.1 48 | array_float += 2.1 49 | array_float += 3.1 50 | 51 | # Array of strings 52 | str array_str = [] 53 | array_str += "My name" 54 | array_str += "is Johann" 55 | 56 | print("Variables explicitly typed:") 57 | print(number_int) 58 | print(number_real) 59 | print(text) 60 | print(array_int) 61 | print(array_float) 62 | print(array_str) 63 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' Photon installer script. ''' 4 | 5 | import os 6 | import sys 7 | from core.dependencies import haveDependencies, resolveDependencies 8 | 9 | PHOTON_PATH = os.path.join(os.path.dirname(__file__), 'core', 'photon.py') 10 | 11 | try: 12 | if sys.platform in {'linux', 'linux2', 'darwin'}: 13 | p_path = '/usr/local/bin/photon' 14 | try: 15 | os.remove(p_path) 16 | except FileNotFoundError: 17 | pass # Ensure the path does not exists. 18 | else: 19 | print('Removing and creating new symlink') 20 | os.symlink(PHOTON_PATH, p_path) 21 | os.chmod(PHOTON_PATH, 0o777) 22 | print(f'Photon Command Path: {p_path}') 23 | elif sys.platform in {'win32', 'cygwin', 'msys'} or os.name == "nt" or os.environ.get('OS', '') == 'Windows_NT': 24 | p_dir = os.path.expandvars('%ProgramFiles%\\Photon') 25 | if not os.path.exists(p_dir): 26 | os.mkdir(p_dir) 27 | with open(os.path.join(p_dir, 'photon.bat'), 'w', encoding='utf-8') as w: 28 | w.write(f'@echo off\npython "{PHOTON_PATH}" %*') 29 | if p_dir in os.environ.get("PATH"): 30 | print('Photon already on PATH, skipping') 31 | else: 32 | os.system(f'setx /M PATH "%PATH%;{p_dir}"') 33 | print(f'Photon Command Path: {os.path.join(p_dir, "photon")}') 34 | else: 35 | print('Automatic installation in this system is not supported yet.') 36 | sys.exit(1) 37 | except PermissionError: 38 | print('The installation failed due to lack of permissions.', 39 | 'Run the proper script for your operational system or try to execute this as super user/administrator', 40 | sep='\n') 41 | sys.exit(1) 42 | 43 | if not haveDependencies('c', sys.platform): 44 | resolveDependencies('c', sys.platform) 45 | 46 | print("Successfully installed! Now you can use the photon command!") 47 | -------------------------------------------------------------------------------- /linuxInstaller.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | red='\033[0;31m' 3 | green='\033[0;32m' 4 | normal='\033[0m' 5 | 6 | printf "${green}Linux Installer - Photon${normal}\n" 7 | 8 | printf "Checking Photon dependencies...\n" 9 | 10 | installDeps="false"; 11 | 12 | if ! command -v git &> /dev/null 13 | then 14 | echo "git could not be found" 15 | installDeps="true"; 16 | else 17 | echo "You already have git installed." 18 | fi 19 | if ! command -v gcc &> /dev/null 20 | then 21 | echo "gcc could not be found" 22 | installDeps="true"; 23 | else 24 | echo "You already have gcc installed." 25 | fi 26 | if ! command -v python3 &> /dev/null 27 | then 28 | echo "python3 could not be found" 29 | installDeps="true"; 30 | else 31 | echo "You already have python3 installed." 32 | fi 33 | 34 | SUDO='' 35 | if [ $(id -u) -ne 0 ] ; then 36 | SUDO='sudo' 37 | fi 38 | if [ "$installDeps" == "true" ]; then 39 | echo "Preparing to install dependencies..." 40 | 41 | 42 | if [ -f '/etc/debian_version' ]; then 43 | $SUDO apt update && $SUDO apt install python3 build-essential git 44 | elif [ -f '/etc/arch-release' ]; then 45 | $SUDO pacman -Syy python gcc git glibc 46 | elif [ -f '/etc/gentoo-release' ]; then 47 | $SUDO emerge --sync && $SUDO emerge dev-lang/python sys-devel/gcc dev-vcs/git 48 | elif [ -f '/etc/SuSE-release' ]; then 49 | $SUDO zypper refresh && $SUDO zypper install python3 gcc git 50 | elif [ -f '/etc/redhat-release' ]; then 51 | ($SUDO dnf check-update && $SUDO dnf install python3 gcc git) || 52 | ($SUDO yum check-update && $SUDO yum install python3 gcc git) 53 | elif [ "$(uname)" == "Darwin" ]; then 54 | if ! command -v brew &> /dev/null 55 | then 56 | echo "brew could not be found. Installing it..." 57 | $SUDO /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 58 | fi 59 | $SUDO brew install gcc git python3 60 | else 61 | printf "${red}Automatic installation in this system is not supported yet.\n${normal}" 62 | printf "Photon needs Python>=3.6, gcc and git on your PATH to work properly." 63 | exit 1 64 | fi 65 | fi 66 | echo "Dependencies installed. Installing Photon command-line interface..." 67 | 68 | SCRIPT=$(readlink -f "$0") 69 | SCRIPTPATH=$(dirname "$SCRIPT") 70 | 71 | if command -v python3; then 72 | $SUDO python3 "$SCRIPTPATH/install.py" 73 | elif command -v python; then 74 | $SUDO python "$SCRIPTPATH/install.py" 75 | else 76 | printf "${red}Was not possible to install Python >= 3.6, please do it manually\n${normal}" 77 | exit 1 78 | fi 79 | 80 | -------------------------------------------------------------------------------- /tests/parserTest.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | sys.path.insert(1, os.path.pardir+'/core') 3 | from photonParser import parse 4 | from interpreter import Interpreter 5 | import unittest 6 | 7 | class ParserTest(unittest.TestCase): 8 | def runFile(self, file): 9 | i = Interpreter(os.path.pardir+'/tests/testFiles/'+file) 10 | 11 | nextLine = False 12 | while True: 13 | if not nextLine or i.line == '': 14 | i.line = i.input('>>> ') 15 | i.processing = True 16 | if i.line == 'exit' or not i.line: 17 | break 18 | tokenized = parse(i.line, filename=i.filename, no=i.lineNumber) 19 | struct, nextLine = i.handleTokenized(tokenized) 20 | return struct 21 | 22 | def test_printStr(self): 23 | struct = self.runFile('printFunc/printStr.w') 24 | self.assertEqual(struct['token'], 'printFunc') 25 | self.assertEqual(struct['expr']['args'][0], {'token':'str', 26 | 'type':'str', 'value':'"Hello World"', 'expressions':[]}) 27 | 28 | def test_printInt(self): 29 | struct = self.runFile('printFunc/printInt.w') 30 | self.assertEqual(struct['token'], 'printFunc') 31 | self.assertEqual(struct['expr']['args'][0], {'token':'num', 'type':'int', 'value':'26'}) 32 | 33 | def test_printFloat(self): 34 | struct = self.runFile('printFunc/printFloat.w') 35 | self.assertEqual(struct['token'], 'printFunc') 36 | self.assertEqual(struct['expr']['args'][0], {'token':'floatNumber','type':'float', 'value':'4.7'}) 37 | 38 | def test_printFloatDot(self): 39 | struct = self.runFile('printFunc/printFloatDot.w') 40 | self.assertEqual(struct['token'], 'printFunc') 41 | self.assertEqual(struct['expr']['args'][0], {'token':'floatNumber','type':'float', 'value':'2.'}) 42 | 43 | def test_printVar(self): 44 | struct = self.runFile('printFunc/printVar.w') 45 | self.assertEqual(struct['token'], 'printFunc') 46 | self.assertEqual(struct['expr']['args'][0]['name'], 'var') 47 | 48 | def test_varInitInt(self): 49 | struct = self.runFile('varInit/initInt.w') 50 | self.assertEqual(struct['token'], 'expr') 51 | self.assertEqual(struct['args'][0]['name'], 'a') 52 | self.assertEqual(struct['args'][0]['type'], 'int') 53 | 54 | def test_varInitFloat(self): 55 | struct = self.runFile('varInit/initFloat.w') 56 | self.assertEqual(struct['token'], 'expr') 57 | self.assertEqual(struct['args'][0]['name'], 'a') 58 | self.assertEqual(struct['args'][0]['type'], 'float') 59 | 60 | def test_varInitStr(self): 61 | struct = self.runFile('varInit/initStr.w') 62 | self.assertEqual(struct['token'], 'expr') 63 | self.assertEqual(struct['args'][0]['name'], 'a') 64 | self.assertEqual(struct['args'][0]['type'], 'str') 65 | 66 | def test_varInitClass(self): 67 | struct = self.runFile('varInit/initClass.w') 68 | self.assertEqual(struct['token'], 'expr') 69 | self.assertEqual(struct['args'][0]['name'], 'a') 70 | self.assertEqual(struct['args'][0]['type'], 'SomeClass') 71 | 72 | def test_varInitStrArray(self): 73 | struct = self.runFile('varInit/initStrArray.w') 74 | self.assertEqual(struct['token'], 'expr') 75 | self.assertEqual(struct['args'][0]['name'], 'array') 76 | self.assertEqual(struct['args'][0]['elementType'], 'str') 77 | self.assertEqual(struct['args'][0]['size'], '10') 78 | 79 | def test_varInitClassArray(self): 80 | struct = self.runFile('varInit/initClassArray.w') 81 | self.assertEqual(struct['token'], 'expr') 82 | self.assertEqual(struct['args'][0]['name'], 'array') 83 | self.assertEqual(struct['args'][0]['type'], 'array') 84 | self.assertEqual(struct['args'][0]['elementType'], 'SomeClass') 85 | self.assertEqual(struct['args'][0]['size'], '10') 86 | 87 | def test_varInitStrStrMap(self): 88 | struct = self.runFile('varInit/initStrStrMap.w') 89 | self.assertEqual(struct['token'], 'expr') 90 | self.assertEqual(struct['args'][0]['name'], 'var') 91 | self.assertEqual(struct['args'][0]['type'], 'map') 92 | self.assertEqual(struct['args'][0]['keyType'], 'str') 93 | self.assertEqual(struct['args'][0]['valType'], 'str') 94 | 95 | def test_varInitClassStrMap(self): 96 | struct = self.runFile('varInit/initClassStrMap.w') 97 | self.assertEqual(struct['token'], 'expr') 98 | self.assertEqual(struct['args'][0]['name'], 'var') 99 | self.assertEqual(struct['args'][0]['type'], 'map') 100 | self.assertEqual(struct['args'][0]['keyType'], 'SomeClass') 101 | self.assertEqual(struct['args'][0]['valType'], 'str') 102 | 103 | def test_varInitStrClassMap(self): 104 | struct = self.runFile('varInit/initStrClassMap.w') 105 | self.assertEqual(struct['token'], 'expr') 106 | self.assertEqual(struct['args'][0]['name'], 'var') 107 | self.assertEqual(struct['args'][0]['type'], 'map') 108 | self.assertEqual(struct['args'][0]['keyType'], 'str') 109 | self.assertEqual(struct['args'][0]['valType'], 'SomeClass') 110 | 111 | def test_assignImplicitInt(self): 112 | struct = self.runFile('assign/varEqualInt.w') 113 | self.assertEqual(struct['token'], 'assign') 114 | self.assertEqual(struct['target']['token'], 'var') 115 | self.assertEqual(struct['expr']['args'][0]['value'], '1') 116 | self.assertEqual(struct['expr']['args'][0]['type'], 'int') 117 | 118 | def test_assignExplicitInt(self): 119 | struct = self.runFile('assign/varEqualInt.w') 120 | self.assertEqual(struct['token'], 'assign') 121 | self.assertEqual(struct['target']['token'], 'var') 122 | self.assertEqual(struct['expr']['args'][0]['value'], '1') 123 | self.assertEqual(struct['expr']['args'][0]['type'], 'int') 124 | 125 | def test_assignExplicitFloatVarInt(self): 126 | struct = self.runFile('assign/floatVarEqualInt.w') 127 | self.assertEqual(struct['token'], 'assign') 128 | self.assertEqual(struct['target']['token'], 'var') 129 | self.assertEqual(struct['target']['type'], 'float') 130 | self.assertEqual(struct['expr']['args'][0]['value'], '4') 131 | 132 | def test_assignVarEqualExpr(self): 133 | struct = self.runFile('assign/varEqualExpr.w') 134 | self.assertEqual(struct['token'], 'assign') 135 | self.assertEqual(struct['target']['token'], 'var') 136 | self.assertEqual(struct['target']['type'], 'unknown') 137 | self.assertEqual(struct['expr']['args'][0]['value'], '1') 138 | self.assertEqual(struct['expr']['args'][1]['value'], '2') 139 | self.assertEqual(struct['expr']['ops'], ['+']) 140 | 141 | def test_assignVarEqualModifierExpr(self): 142 | struct = self.runFile('assign/varEqualModifierExpr.w') 143 | self.assertEqual(struct['token'], 'assign') 144 | self.assertEqual(struct['target']['token'], 'var') 145 | self.assertEqual(struct['target']['type'], 'unknown') 146 | self.assertEqual(struct['expr']['args'][0]['value'], '1') 147 | self.assertEqual(struct['expr']['args'][0]['modifier'], '-') 148 | self.assertEqual(struct['expr']['args'][1]['value'], '2') 149 | self.assertEqual(struct['expr']['args'][2]['value'], '6') 150 | self.assertEqual(struct['expr']['ops'], ['+','-']) 151 | 152 | def test_assignVarEqualExprGroup(self): 153 | struct = self.runFile('assign/varEqualExprGroup.w') 154 | self.assertEqual(struct['token'], 'assign') 155 | self.assertEqual(struct['target']['token'], 'var') 156 | self.assertEqual(struct['target']['type'], 'unknown') 157 | self.assertEqual(struct['expr']['ops'], ['+']) 158 | self.assertEqual(struct['expr']['args'][0]['expr']['args'][0]['value'], '1') 159 | self.assertEqual(struct['expr']['args'][0]['expr']['args'][1]['value'], '2') 160 | self.assertEqual(struct['expr']['args'][0]['expr']['ops'], ['+']) 161 | self.assertEqual(struct['expr']['args'][1]['value'], '5') 162 | 163 | def test_assignModifierWithVar(self): 164 | struct = self.runFile('assign/modifierWithVar.w') 165 | self.assertEqual(struct['token'], 'assign') 166 | self.assertEqual(struct['target']['token'], 'var') 167 | self.assertEqual(struct['target']['type'], 'unknown') 168 | self.assertEqual(struct['expr']['args'][0]['name'], 'b') 169 | self.assertEqual(struct['expr']['args'][0]['modifier'], '-') 170 | self.assertEqual(struct['expr']['args'][1]['value'], '1') 171 | self.assertEqual(struct['expr']['ops'], ['+']) 172 | 173 | def test_assignGroup(self): 174 | struct = self.runFile('assign/varEqualGroup.w') 175 | self.assertEqual(struct['token'], 'assign') 176 | self.assertEqual(struct['target']['token'], 'var') 177 | self.assertEqual(struct['target']['type'], 'unknown') 178 | self.assertEqual(struct['expr']['args'][0]['token'], 'group') 179 | self.assertEqual(struct['expr']['args'][0]['expr']['args'][0]['value'], '1') 180 | self.assertEqual(struct['expr']['args'][0]['expr']['args'][1]['value'], '2') 181 | self.assertEqual(struct['expr']['args'][0]['expr']['ops'], ['+']) 182 | 183 | def test_assignModifierGroup(self): 184 | struct = self.runFile('assign/varEqualModifierGroup.w') 185 | self.assertEqual(struct['token'], 'assign') 186 | self.assertEqual(struct['target']['token'], 'var') 187 | self.assertEqual(struct['target']['type'], 'unknown') 188 | self.assertEqual(struct['expr']['args'][0]['token'], 'group') 189 | self.assertEqual(struct['expr']['args'][0]['expr']['args'][0]['value'], '1') 190 | self.assertEqual(struct['expr']['args'][0]['expr']['args'][1]['value'], '2') 191 | self.assertEqual(struct['expr']['args'][0]['expr']['ops'], ['+']) 192 | self.assertEqual(struct['expr']['args'][0]['modifier'], '-') 193 | 194 | if __name__ == "__main__": 195 | unittest.main() 196 | -------------------------------------------------------------------------------- /tests/testFiles/assign/floatVarEqualInt.w: -------------------------------------------------------------------------------- 1 | float var = 4 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/intVarEqualInt.w: -------------------------------------------------------------------------------- 1 | int var = 1 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/modifierWithVar.w: -------------------------------------------------------------------------------- 1 | a = -b + 1 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/varEqualExpr.w: -------------------------------------------------------------------------------- 1 | a = 1 + 2 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/varEqualExprGroup.w: -------------------------------------------------------------------------------- 1 | a = (1+2) + 5 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/varEqualGroup.w: -------------------------------------------------------------------------------- 1 | a = (1+2) 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/varEqualInt.w: -------------------------------------------------------------------------------- 1 | var = 1 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/varEqualModifierExpr.w: -------------------------------------------------------------------------------- 1 | a = -1 + 2 - 6 2 | -------------------------------------------------------------------------------- /tests/testFiles/assign/varEqualModifierGroup.w: -------------------------------------------------------------------------------- 1 | a = -(1+2) 2 | -------------------------------------------------------------------------------- /tests/testFiles/printFunc/printFloat.w: -------------------------------------------------------------------------------- 1 | print(4.7) 2 | -------------------------------------------------------------------------------- /tests/testFiles/printFunc/printFloatDot.w: -------------------------------------------------------------------------------- 1 | print(2.) 2 | -------------------------------------------------------------------------------- /tests/testFiles/printFunc/printInt.w: -------------------------------------------------------------------------------- 1 | print(26) 2 | -------------------------------------------------------------------------------- /tests/testFiles/printFunc/printStr.w: -------------------------------------------------------------------------------- 1 | print("Hello World") 2 | -------------------------------------------------------------------------------- /tests/testFiles/printFunc/printVar.w: -------------------------------------------------------------------------------- 1 | var = 2 2 | print(var) 3 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initClass.w: -------------------------------------------------------------------------------- 1 | SomeClass a 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initClassArray.w: -------------------------------------------------------------------------------- 1 | SomeClass:10 array 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initClassStrMap.w: -------------------------------------------------------------------------------- 1 | SomeClass:str var 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initFloat.w: -------------------------------------------------------------------------------- 1 | float a 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initInt.w: -------------------------------------------------------------------------------- 1 | int a 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initStr.w: -------------------------------------------------------------------------------- 1 | str a 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initStrArray.w: -------------------------------------------------------------------------------- 1 | str:10 array 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initStrClassMap.w: -------------------------------------------------------------------------------- 1 | str:SomeClass var 2 | -------------------------------------------------------------------------------- /tests/testFiles/varInit/initStrStrMap.w: -------------------------------------------------------------------------------- 1 | str:str var 2 | -------------------------------------------------------------------------------- /tests/transpilersTest.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | sys.path.insert(1, os.path.pardir+'/core') 3 | from photonParser import parse 4 | from interpreter import Interpreter 5 | import unittest 6 | from subprocess import Popen, PIPE 7 | 8 | class TranspilersTest(unittest.TestCase): 9 | langs = ['c', 'py', 'js'] 10 | 11 | def runFile(self, file, lang='c'): 12 | out = '' 13 | result = Popen(f'photon testFiles/{file} lang={lang}', shell=True, stdout=PIPE) 14 | for line in result.stdout: 15 | out += str(line, encoding='utf8').strip() 16 | sys.stdout.buffer.write(line) 17 | sys.stdout.buffer.flush() 18 | break 19 | result.stdout.close() 20 | result.wait() 21 | return out 22 | 23 | def checkFile(self, filename, result=None): 24 | for lang in self.langs: 25 | out = self.runFile(filename, lang=lang) 26 | if isinstance(result, int): 27 | self.assertEqual(int(out), result) 28 | elif isinstance(result, str): 29 | self.assertEqual(str(out), result) 30 | elif isinstance(result, float): 31 | self.assertAlmostEqual(float(out), result) 32 | else: 33 | raise NotImplemented 34 | 35 | def test_printInt(self): 36 | out = self.checkFile('printFunc/printInt.w', 26) 37 | 38 | def test_printFloat(self): 39 | self.checkFile('printFunc/printFloat.w', 4.7) 40 | 41 | def test_printFloatDot(self): 42 | self.checkFile('printFunc/printFloatDot.w', 2.0) 43 | 44 | def test_printStr(self): 45 | self.checkFile('printFunc/printStr.w', 'Hello World') 46 | 47 | def test_printVar(self): 48 | self.runFile('printFunc/printVar.w', 2) 49 | 50 | if __name__ == "__main__": 51 | unittest.main() 52 | -------------------------------------------------------------------------------- /uninstall.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | local = '/usr/local/bin/photon' 4 | 5 | try: 6 | if os.path.isfile(local): 7 | print(f'Removing the file {local}.') 8 | os.remove(local) 9 | print('Successfully removed!') 10 | 11 | else: 12 | print("It has nothing to be removed!") 13 | except PermissionError: 14 | print( 15 | " Please run this script with the 'sudo' command\n", 16 | "Example:\n 'sudo python3 uninstall.py'") 17 | -------------------------------------------------------------------------------- /windowsInstaller.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | title Windows Installer - Photon 3 | set mydir=%~dp0 4 | powershell -command "Start-Process powershell -Verb RunAs -PassThru -ArgumentList '-ExecutionPolicy RemoteSigned -NoProfile -File \"%mydir%\windowsInstaller.ps1\"'" 5 | timeout /t 3 6 | exit 7 | -------------------------------------------------------------------------------- /windowsInstaller.ps1: -------------------------------------------------------------------------------- 1 | # $ErrorActionPreference = "Stop" 2 | 3 | $host.UI.RawUI.WindowTitle = "Windows Installer - Photon" 4 | 5 | if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) 6 | { 7 | echo "To install Photon, you need administrator privileges!" 8 | timeout /t 3 9 | exit 10 | } 11 | 12 | while ((Get-Command "choco.exe" -ErrorAction SilentlyContinue) -eq $null) 13 | { 14 | echo "Chocolatey was not found! Do you want to install it?" 15 | pause 16 | Set-ExecutionPolicy Bypass -Scope Process -Force 17 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 18 | iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) 19 | $env:Path = "$env:Path;$env:AllUsersProfile\chocolatey\bin" 20 | } 21 | 22 | $dependencies = "" 23 | $show_dependencies = "" 24 | 25 | if (((Get-Command "python.exe" -ErrorAction SilentlyContinue) -eq $null) -or ((Get-Item (Get-Command "python.exe").Path).length -eq 0)) 26 | { 27 | $dependencies = "python;" 28 | $show_dependencies = "python " 29 | } 30 | 31 | if ((Get-Command "gcc.exe" -ErrorAction SilentlyContinue) -eq $null) 32 | { 33 | $dependencies = "${dependencies}mingw;" 34 | $show_dependencies = "${show_dependencies}mingw " 35 | } 36 | 37 | if ((Get-Command "git.exe" -ErrorAction SilentlyContinue) -eq $null) 38 | { 39 | $dependencies = "${dependencies}git;" 40 | $show_dependencies = "${show_dependencies}git " 41 | } 42 | 43 | if ($dependencies -ne "") 44 | { 45 | echo "To use Photon, you need to install the following programs: ${show_dependencies}" 46 | pause 47 | choco install -y "$dependencies" 48 | } 49 | else 50 | { 51 | echo "The programs Photon needs are already installed!" 52 | } 53 | 54 | if ((Get-Command "python.exe" -ErrorAction SilentlyContinue) -ne $null) 55 | { 56 | cmd /c "refreshenv; python -m pip install pyreadline" 57 | $scriptPath = -join('"', (split-path -parent $MyInvocation.MyCommand.Definition), '"') 58 | echo "Installing Photon . . ." 59 | cmd /c "python ${scriptPath}\install.py" 60 | } 61 | else 62 | { 63 | echo "Python was not found!" 64 | } 65 | 66 | pause 67 | --------------------------------------------------------------------------------