{"id":26274190,"url":"https://github.com/strwdr/skner-lang","last_synced_at":"2025-03-14T09:18:31.069Z","repository":{"id":129010233,"uuid":"501654589","full_name":"strwdr/skner-lang","owner":"strwdr","description":"simple programming language written in C++","archived":false,"fork":false,"pushed_at":"2022-12-17T22:53:40.000Z","size":152,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-07-31T10:32:44.473Z","etag":null,"topics":["compiler","cpp","interpreter","language","lexer","parser"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/strwdr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-09T13:00:31.000Z","updated_at":"2023-04-15T21:37:22.000Z","dependencies_parsed_at":"2023-03-23T12:03:15.538Z","dependency_job_id":null,"html_url":"https://github.com/strwdr/skner-lang","commit_stats":null,"previous_names":["strwdr/skner-lang","starwader/skner-lang"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strwdr%2Fskner-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strwdr%2Fskner-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strwdr%2Fskner-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strwdr%2Fskner-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/strwdr","download_url":"https://codeload.github.com/strwdr/skner-lang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243551290,"owners_count":20309300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compiler","cpp","interpreter","language","lexer","parser"],"created_at":"2025-03-14T09:18:30.562Z","updated_at":"2025-03-14T09:18:31.051Z","avatar_url":"https://github.com/strwdr.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Projekt TKOM - Skner - dokumentacja końcowa\nJakub Budrewicz\n\n## Spis treści\n1. [ Wstęp ](#wstep)\n2. [ Opis funkcjonalności ](#opis)\n3. [ Stary opis funkcjonalności (niespełniony) ](#stary_opis)\n4. [ Przykłady ](#przyklady)\n5. [ Specyfikacja i składnia ](#specyfikacja)\n6. [ Szczegóły implementacyjne ](#implementacja)\n7. [ Biblioteka standardowa ](#stdlib)\n8. [ Uruchamianie ](#uruchamianie)\n9. [ Testowanie ](#testowanie)\n10. [ Dalsze rozszerzenia ](#rozszerzenia)\n\n## Wstęp \u003ca name=\"wstep\"\u003e\u003c/a\u003e\nSkner jest docelowo językiem funkcyjnym stworzonym z przeznaczeniem do programowania muzyki, \nktórego podstawą jest referencyjne traktowanie wszystkich zmiennych.\nJęzyk inspirowany jest funkcjonalnościami języka programowania wizualnego Pure Data oraz składnią Lua.\n\n\n## Opis funkcjonalności \u003ca name=\"opis\"\u003e\u003c/a\u003e\n\nW ramach projektu TKOM udało mi się zrealizować wymagania funkcjonalności języka, \npoza działaniem referencyjnych zmiennych (w wersji ostatecznej są to zwykłe, niereferencyjne wartości, język\npozwala na używanie rekurencji, continue, break, exit oraz wypisywanie błędów w trybie konsoli).\n\n## Docelowy opis funkcjonalności \u003ca name=\"stary_opis\"\u003e\u003c/a\u003e\nNajważniejszym wymaganiem języka jest możliwość korzystania z \"funkcyjnych\" zmiennych; oznacza to w rozumieniu tego projektu, \nże domyślnie, wartości zmiennych nie są kopiowane i zawsze, jeśli nie wskażemy inaczej, po przekazaniu\nzmiennej do funkcji/innej zmiennej/tablicy, przechowującej ten sam typ danych,\nmożemy modyfikować wyjście lub wartość tych funkcji/innej zmiennej/tablicy za pomocą tej pierwszej zmiennej. \nTakie podejście jest uproszczeniem przepływu danych z języka programowania wizualnego Pure Data.\n\nW Skner nie ma standardowych zmiennych, zamiast nich używane są lambdy (w tej dokumentacji w \nrozumieniu zmiennej, zawsze chodzi o lambdę).\n\nTakie podejście stwarza szereg problemów:\n- Każda zmienna jest przechowywana w pamięci jako drzewo operacji\n  - jest to znacznie mniej efektywne niż przechowywanie samej wartości, lub referencji\n- Po usunięciu zmiennej należy zaktualizować zmienne korzystające z niej\n  - po usunięciu lambdy, wszystkie jej referencje są podmienione na jej ostatnią wartość\n  - utrudnia to implementację, ponieważ należy przechowywać zależności pomiędzy lambdami w obydwie strony\n- Po użyciu funkcji w wyrażeniu lambdy, lambda przechowuje referencję do tej funkcji\noraz jej argumentów\n- Stałe wartości (literały oraz użycia operatora $), będące częścią lambdy muszą być przechowywane i usuwane \nrazem z daną lambdą (są jej bezpośrednio podległe)\n\nFunkcje w Skner nie mogą operować na globalnych identyfikatorach lambdach stworzonych przez użytkownika. Muszą one \nzostać przekazane za pomocą argumentów pozycyjnych.\n\nFunkcje mogą za to operować na wszystkich wbudowanych słowach kluczowych oraz jakichkolwiek innych funkcjach \nstworzonych przez użytkownika lub wbudowanych. \n\nFunkcje nie mogą być przeładowywane, identyfikatory są unikalne.\n\n### Wymagania funkcjonalne:\n\n- Interpretowanie plików\n\n- Interpretowanie bezpośrednio z konsoli\n\n- Zgłaszanie błędów znalezionych podczas interpretacji\n\n- Obsługa typów liczbowych, tekstowych oraz logicznych (string, number i boolean)\n\n- Definiowalne przez użytkownika zmienne\n\n- Definiowalne przez użytkownika funkcje\n\n- Funkcyjny charakter zmiennych osiągnięty ma być za pomocą wymuszenia lambd (niespełnione)\n\n- Możliwość używania lambd jako zwykłych, niereferencyjnych zmiennych (operator $) (niespełnione)\n\n- Statyczne typowanie\n\n- Mutowalność zmiennych\n\n## Przykłady \u003ca name=\"przyklady\"\u003e\u003c/a\u003e\n\nPrzykładowy program:\n```\nnumber a = 10;\nprint(a);\nprint(10);\nnumber function fib(number a) # funkcja licząca ciąg fibbonaciego\n   if(a \u003c 2) return 1; end\n   return fib(a-1) + fib(a-2);\nend\nprint(fib(1));\nprint(fib(3));\na = 1;\nwhile(a\u003c20) # wypisanie pierwszych 20 elementów ciągu fibbonaciego\nprintln(fib(a));\na = a + 1;\nend\nprint(a);\n~a # usunięcie zmiennej a\n```\n\n\nProgram zgodny ze składnią języka, ale prezentujący funkcjonalności, które nie zostaną dodane do języka w ramach \nprojektu TKOM ze względu na zbyt duży zakres (wbudowane funkcje muzyczne/do obsługi audio, tablice oraz typ `sequence`).\n\n```\n\u003e\u003e\u003e println(list_interfaces()); # get table of computers audio interfaces (table of strings)\naudio_interface_a, audio_interface_b\n\u003e\u003e\u003e println(string(select_interface(\"audio_interface_a\")));\ntrue\n\u003e\u003e\u003e start(); # start audio (and clock)\n\u003e\u003e\u003e number function osc_dummy(number multiplier) \n...     return sin(get_tic() / multiplier);\n... end\n\u003e\u003e\u003e\n\u003e\u003e\u003e number a = 15;\n\u003e\u003e\u003e dac__add_play_function(osc_dummy(a)); # audio starts playing\n\u003e\u003e\u003e a = 60; # played frequency changes\n\u003e\u003e\u003e println(string(dac__list_play_functions()));\ndac_osc_dummy\n\u003e\u003e\u003e dac__remove_play_function(0);\n\u003e\u003e\u003e ~a # delete \"a\" variable and everything that has a reference to it\n\u003e\u003e\u003e # using native oscillator function (sinewave by default)\n\u003e\u003e\u003e number osc_1_frequency = 500;\n\u003e\u003e\u003e dac__add_play_function(oscillator(osc_1_frequency)); # play 500 Hz sinewave\n\u003e\u003e\u003e osc_1_frequency = 440; # change played frequency\n\u003e\u003e\u003e dac__remove_play_function(0); # remove dac_oscillator_1\n\u003e\u003e\u003e\n\u003e\u003e\u003e # using sequences\n\u003e\u003e\u003e println(string(get_bpm()));\n123\n\u003e\u003e\u003e set_bpm(120); # set global bpm value\n\u003e\u003e\u003e table seq_frequencies = [osc_1_frequency,0,412,323,880];\n\u003e\u003e\u003e sequence seq_1 = sequence(seq_frequencies, [2,1,1,1,1], 1) ;\n\u003e\u003e\u003e # seq_1 value represents frequency (number) and changes in time\n\u003e\u003e\u003e dac__add_play_function(oscillator(seq_1)); # sequence seq_1 is now playing\n\u003e\u003e\u003e a=2000 ;# change first note frequency in seq_1 \n\u003e\u003e\u003e stop() ;# stop audio\n```\n## Specyfikacja i składnia \u003ca name=\"specyfikacja\"\u003e\u003c/a\u003e\n\nLista zdefiniowanych słów kluczowych:\n`function`, `if`, `elif`, `else`, `while`, `return`, `number`, `boolean`, `break`, `continue`, `or`, `and`, `true`, `false`, `end`, `exit`\n\nEnum tokenów:\n```c++\nenum TokenType {\n/*-------------------- literals -------------------*/\n    T_NUMBER_LITERAL = 256,\n    T_BOOLEAN_LITERAL = 257,\n    T_STRING_LITERAL = 258,\n\n    /*-------------------- keywords -------------------*/\n    /* functions  */\n    T_FUNCTION = 259,\n    T_CONTINUE = 260,\n    T_BREAK = 261,\n    T_RETURN = 262,\n\n    /* statements */\n    T_WHILE = 263,\n    T_IF = 264,\n    T_ELIF = 265,\n    T_ELSE = 266,\n    T_END = 267,\n\n    /* type specifiers */\n    T_NUMBER = 268,\n    T_STRING = 269,\n    T_BOOLEAN = 270,\n\n    /* literals */\n    T_TRUE = 271,\n    T_FALSE = 272,\n\n    /*------------------ identifiers ------------------*/\n    T_IDENTIFIER = 273,\n\n    /*------------------- operators -------------------*/\n    T_GREATER_EQUAL = 274, // \u003e=\n    T_LESSER_EQUAL = 275, // \u003c=\n    T_GREATER = 276, // \u003e\n    T_LESSER = 277, // \u003c\n    T_NOT_EQUAL = 278, // !=\n    T_EQUAL = 279, // ==\n    T_NEGATE = 280, // !\n    T_ASSIGNMENT = 281, // =\n\n    /* single character */\n    T_OR = '|',\n    T_AND = '\u0026',\n\n    T_EVALUATE = '$',\n    T_PLUS = '+',\n    T_MINUS = '-',\n    T_DIVIDE = '/',\n    T_MULTIPLY = '*',\n    T_MODULO = '%',\n    T_DELETE = '~',\n\n    /*------------------ punctuators ------------------*/\n    T_COMMA = ',',\n    T_OPEN_BRACKET = '(',\n    T_CLOSE_BRACKET = ')',\n    T_SEMICOLON = ';',\n\n    /*--------------------- other ---------------------*/\n    T_ETX = 282,\n    T_UNDEFINED = 283,\n    T_EXIT = 284,\n};\n```\n\n### Komentarze:\nKomentarze zaczynają się od znaku `#` i są pomijane w trakcie analizy leksykalnej, dlatego nie ma ich zdefiniowanych na liście tokenów ani w automacie.\n\n### Biblioteka standardowa\nBiblioteka standardowa obejmuje wbudowane funkcje:\n- `println(string)`\n- `print(string)`\n- `read()`\n- `string to_string(\u003cany type\u003e)`\n- `number to_number(\u003cany type\u003e)`\n- `boolean to_boolean(\u003cany type\u003e)`\n\n\n### Opis automatu parsera:\n\nProgramStatement:\n\n![](diagram_generator/diagrams/programStatement.svg)\n\nFunctions:\n\n![](diagram_generator/diagrams/functionCall.svg)\n\n![](diagram_generator/diagrams/functionDefinition.svg)\n\nStatements:\n\n![](diagram_generator/diagrams/ifStatement.svg)\n\n![](diagram_generator/diagrams/whileStatement.svg)\n\n![](diagram_generator/diagrams/returnStatement.svg)\n\n![](diagram_generator/diagrams/statement.svg)\n\nExpressions:\n\n![](diagram_generator/diagrams/expression.svg)\n\n![](diagram_generator/diagrams/orExpression.svg)\n\n![](diagram_generator/diagrams/andExpression.svg)\n\n![](diagram_generator/diagrams/equalExpression.svg)\n\n![](diagram_generator/diagrams/relationExpression.svg)\n\n![](diagram_generator/diagrams/additiveExpression.svg)\n\n![](diagram_generator/diagrams/multiplicativeExpression.svg)\n\n![](diagram_generator/diagrams/baseExpression.svg)\n\nTypes:\n\n![](diagram_generator/diagrams/identifier.svg)\n\n![](diagram_generator/diagrams/literal.svg)\n\n![](diagram_generator/diagrams/booleanLiteral.svg)\n\n![](diagram_generator/diagrams/numberLiteral.svg)\n\n![](diagram_generator/diagrams/stringLiteral.svg)\n\nOperations:\n\n![](diagram_generator/diagrams/deletion.svg)\n\n![](diagram_generator/diagrams/lambdaAssignment.svg)\n\n![](diagram_generator/diagrams/lambdaDefinition.svg)\n\nOperators:\n\n![](diagram_generator/diagrams/additiveOperator.svg)\n\n![](diagram_generator/diagrams/relationOperator.svg)\n\n![](diagram_generator/diagrams/multiplicativeOperator.svg)\n\n![](diagram_generator/diagrams/andOperator.svg)\n\n![](diagram_generator/diagrams/orOperator.svg)\n\n![](diagram_generator/diagrams/unaryOperator.svg)\n\n![](diagram_generator/diagrams/equalOperator.svg)\n\nBasic:\n\n![](diagram_generator/diagrams/letter.svg)\n\n![](diagram_generator/diagrams/digit.svg)\n\n\n\n## Szczegóły implementacyjne \u003ca name=\"implementacja\"\u003e\u003c/a\u003e\n\nCałość kodu zostanie napisana w C++.\n\n### Main\n\nGłówny plik służy sczytaniu argumentu służy specyfikacji trybu interpretacji (konsola lub plik).\nDomyślnie, błędy są wypisywane w konsoli na standardowe wyjście podczas interpretacji, za pośrednictwem kontrolera błędów\nkontrolera.\n\n### Moduł obsługi błędów\n\nKażdy typ błędu interpretacyjnego ma zdefiniowany swój własny wyjątek; w razie napotkania takiego wyjątku\npodczas analizy leksykalnej/składniowej lub interpretacji jest on rzucany, a w konsoli wyświetla się \nodpowiedni komunikat wraz z linijką i wierszem w kodzie. W przypadku interpretacji z pliku, interpreter przerywa\ndziałanie przy pierwszym napotkanym błędzie.\n\n### Moduł analizatora leksykalnego\n\nAnaliza leksykalna jest pierwszym etapem parsowania.\nW tym miejscu kod zostanie podzielony na tokeny, które zostaną wykorzystane w późniejszych etapach.\n\n### Moduł analizatora składniowego\n\nW module analizatora składniowego zostanie przeprowadzone sprawdzenie składni programu oraz zbudowanie drzewa.\n\n### Moduł interpretera\n\nModuł interpretera będzie służył wykonywaniu kodu zgodnie z drzewem pozyskanym z analizatora składniowego.\nW tym module znajduje się kod odpowiadający za przechowywanie funkcji, istniejących zmiennych i wszystkie \nfunkcjonalne właściwości interpretera.\n\nWażnym elementem modułu intepretera jest ewaluator, który dziedziczy po wirtualnym wizytorze drzewa AST.\nEwaluator zajmuje się wykonywaniem konkretnych procedur, ewaluacją expressions, a także rzuca odpowiednie wyjątki\nw razie błędów interpretera;\n\n## Uruchamianie \u003ca name=\"uruchamianie\"\u003e\u003c/a\u003e\n\n```bash\ngit clone https://gitlab-stud.elka.pw.edu.pl/tkom-22l-kg/Jakub_Budrewicz/skner-lang.git\ncd skner-lang\nmkdir build\ncd build\ncmake ..\nmake\n```\n\nPo kompilacji, w katalogu `build/` pojawi się plik wykonywalny `skner`.\nWykonanie polecenia `./skner` w katalogu, spowoduje uruchomienie języka w trybie interpretera.\nWykonanie polecenia `./skner \u003cplik.sk\u003e` zinterpretuje cały kod, wypisze jego wyjście na konsolę, po czym interpreter\nzakończy pracę.\n\n## Testowanie \u003ca name=\"testowanie\"\u003e\u003c/a\u003e\n\nTesty jednostkowe zostaną napisane z pomocą biblioteki `doctest`.\n\n## Dalsze rozszerzenia \u003ca name=\"rozszerzenia\"\u003e\u003c/a\u003e\nOczywiście pierwszym i najistotniejszym rozszerzeniem w razie dalszej pracy nad projektem będzie wprowadzenie funkcyjnego charakteru zmiennych.\n\nW przypadku dalszego rozwijania projektu, przewidziałem powstanie następujących funkcji z biblioteki standardowej umożliwiające live coding (programowanie muzyki):\n- `start()`,\n- `stop()`,\n- `get_tic()`,\n- `set_tic(number)`,\n- `get_bpm()`,\n- `set_bpm(number)`,\n- `dac__add_play_function(number)`\n- `dac__remove_play_function(number)`\n- `sin(number)`,\n- `oscillator(number, string)`\n- `list_interfaces()`\n- `select_interface(string)`\nNie będę ich jednak opisywać, ponieważ wykracza to poza zakres projektu.\n\nW rozszerzeniach przewidziałem także dodanie tablic oraz specjalny typ `sequence`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrwdr%2Fskner-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstrwdr%2Fskner-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrwdr%2Fskner-lang/lists"}