Ktoś napisał interpreter eForth w ezoterycznym języku Subleq. Zastanawiam się czy plik subleq.dec napisał ręcznie czy wygenerował.
16-bit SUBLEQ CPU running eForth - just for fun. Contribute to howerj/subleq development by creating an account on GitHub.
https://github.com/howerj/subleq@KamilAdam: mimo, że mam sentyment do FORTH - z czasów C64, to raczej nie polecam. Język był ciekawy - w swoich czasach. Point free - chociaż imperatywny. Mocno nietypowy - skrzyżowanie LISPa z LOGO. Ale jednak nie ma nic takiego ciekawego, czego funkcyjne nie mają.
Ostatnio zainteresowałem się Forthem, to dość stary język, ale wciąż użyteczny, u siebie wykorzystuję go jako parser SCPI (standard komunikacji z urządzeniami pomiarowymi).
Składnia jest dość kosmiczna i nauka nie jest zbyt łatwa, na dole przykład słowa, które ulepiłem:
: IS_IT_CMD_TO_EXEC? ( -- status )
\ return value
TRUE
GET_OFFSET_OF_FIRST_ARG_IN_CMD 1 -
DUP
-1 = IF SCPI_TOKEN COUNT THEN
2 SWAP DO
SCPI_CMD I CHARS + C@
SCPI_TOKEN I CHARS + C@
= IF ELSE DROP FALSE THEN
-1 +LOOP
;
Doszedłem do wniosku, że potrzebuję testów jednostkowych, niestety nie znalazłem żadnego frameworku. Ulepiłem swojego potworka, którego podpiąłem pod CI na GitHubie i nawet działa, kilka błędów znalazłem w swoim kodzie :)
Tu wrócę i wspomnę jeszcze o tym, jaki jest zamysł całej aplikacji, z zewnątrz przychodzi komenda, driver w C odpala słowo do parsowania, gdzie argumentem jest treść tej komendy. Kod w Forcie komendę, sprawdza jej poprawność, w zależności od komendy wywołuje odpowiednie callbacki w C.
Kod w Forthcie podzieliłem na dwa pliki, ten z właściwą logiką biznesową, którą będę testował i na plik z callbackami. Podczas buildu na hardware, będzie brany plik z callbackami, które rzeczywiście wywołują odpowiednie funkcje z C. Na potrzeby testu, używam innego pliku z tymi samymi słowami, ale inną implementacją. To będą takie moje mocki - tam mogę dodać jakąś logikę by sprawdzać czy np. coś było ustawione etc.
Zrobiłem sobie prostą asercję, którą sprawdzam, czy test step przeszedł, czy nie i to w sumie na razie cały mój framewoork. Reszta to tylko konwencja pisania testu.
Zaczynam od zalinkowania "test trameworka", potem definiuję swoje mocki, testy, a na końcu określam, które testy będą wykonywane.
S" TestFramework.fs" REQUIRED
( Mocks )
: SEND_SCPI_RESPONSE ( );
: GET_DEVICE_IDENTIFICATOR ( );
: RESET_DDS ( ) ;
: RESET_PGA ( ) ;
: RESET_ATTENUATORS ( ) ;
( Tested functionality )
S" ../../software/BL/SCPI.fs" REQUIRED
( Test definitions )
: TEST_STATE_IS_CMD_LEXICALLY_OK?
\ OK start command from '*' sign
S" *blabla" SCPI_CMD PLACE
STATE_IS_CMD_LEXICALLY_OK? ASSERT
\ OK start command from ':' sign
S" :balbala" SCPI_CMD PLACE
STATE_IS_CMD_LEXICALLY_OK? ASSERT
\ OK start command from ':' sign
S" ::" SCPI_CMD PLACE
STATE_IS_CMD_LEXICALLY_OK? ASSERT
\ NOK start command from a sign that is neither '*' nor ':'
S" balbala" SCPI_CMD PLACE
STATE_IS_CMD_LEXICALLY_OK? INVERT ASSERT
\ NOK empty command
S" " SCPI_CMD PLACE
STATE_IS_CMD_LEXICALLY_OK? INVERT ASSERT
;
( Active tests )
TEST_STATE_IS_CMD_LEXICALLY_OK?
Link do źródeł:
https://github.com/RobertGawron/DDSFunctionGenerator/blob/master/software/BL/SCPI.fs
https://github.com/RobertGawron/DDSFunctionGenerator/blob/master/software/BL/SCPICallbacks.fs
Link do testów:
https://github.com/RobertGawron/DDSFunctionGenerator/blob/master/tests/BL/TestFramework.fs
https://github.com/RobertGawron/DDSFunctionGenerator/blob/master/tests/BL/UT_SCPI.fs
W sumie piszę ten post, by pokazać, że nawet w języku, który powstał w 1968 też można pisać nowocześnie, z testami, etc :) :)
#forth
@rgawron: co do micropythona i w ogóle Pythona na mikrokontrolerach typu raspberry to wku&wia mnie jedna rzecz, że niby te biblioteki są w wysokopoziomowym Pythonie, ale są tak naprawdę wcześniej skompilowane w C, na którym bazują. I wtedy traci się niepotrzebnie czas i nerwy na odwieczne pytanie: Czemu to u mnie nie działa?
@rgawron bedziesz pisac wlasny interpreter forth? Wiele osob to robi bo jezyk jest prosty
@KamilAdam: Czy Twoja lista jest
list.__len__() == stackoverflow
? :P