Или что бывает если заставить очень опытного разработчика заниматься не своим делом. Думаю после этой статьи термин «overqualified» заиграет для вас новыми красками.
От авторов, запихнувших веб‑сервер на визитку и локализующих корпоративные приложения на клингонский — держим марку!
Наш волшебный дикий веб
Что первым делом приходит в голову, когда говорят о «веб-разработке»? Наверное создание сайтов или веб-приложений?
Лендинги, сайты-визитки, интернет-магазины или какие-нибудь веб-порталы
в ад.
Самые продвинутые из читателей наверное вспомнят PWA или какой-нибудь React Native с Flutter — предел полета фантазии обычного разработчика.
Что плохо:
главное что отделяет человека от великих свершений это его фантазия — точно нельзя сделать только то, что невозможно вообразить.
Поэтому сейчас мы будем расширять ваше воображение — в превентивных мерах, дрелью и дыроколом подручными средствами.
Перед вами шесть проектов отборнейшей дичи — реализующих самые безумные идеи с помощью вполне обыденных инструментов современного веб-разработчика.
Пожалуйста не пытайтесь рассказывать о таком на интервью в обычных компаниях — пожалейте интервьюера и его нежную психику.
Автор когда‑то давно (когда еще ходил по собеседованиям) довел одного интервьюера до нервного срыва, просто в деталях рассказав как на самом деле работает загрузка больших файлов через форму со стороны сервера — про HTTP 100 Continue, разбор MIME и прочие радости.
Люди тогда были сильно крепче головой чем сейчас, в нынешних реалиях могут и побить прямо на интервью.
Дичь первая: HTMLang
Не смог пропустить столь жизнеутверждающее описание от автора этого замечательного проекта:
They were laughing that HTML was not a real programming language… WHO»S LAUGHING NOW!!11
Да, это именно то что вы подумали — кто-то будучи сильно не в духе взял общий синтаксис HTML и создал на его основе полноценный язык программирования.
Вот так выглядит реализация знаменитого FizzBuzz:
<!DOCTYPE html> <html> <head> <title>FizzBuzz</title> </head> <body> <h3>Look into the DevTools Console</h3> <htmlang style="display: none;"> <call target="console.log"><s>Generating FizzBuzz...</s></call> <for><v>i</v> <n>1</n> <n>100</n> <cond> <when> <eq> <mod> <v>i</v> <n>15</n> </mod> <n>0</n> </eq> <call target="console.log"> <s>FizzBuzz</s> </call> </when> <when> <eq> <mod> <v>i</v> <n>3</n> </mod> <n>0</n> </eq> <call target="console.log"> <s>Fizz</s> </call> </when> <when> <eq> <mod> <v>i</v> <n>5</n> </mod> <n>0</n> </eq> <call target="console.log"> <s>Buzz</s> </call> </when> <else> <call target="console.log"><v>i</v></call> </else> </cond> </for> </htmlang> <script src="./HTMLang.js"></script> </body> </html>
Не представляю что будет если самому Джоэлу выдать его же знаменитый «FizzBuzz» в такой реализации — есть шанс что старый сишный программист впадет в рекурсию.
Кстати кто там рассказывал на лекциях про «декларативный язык разметки» и «общую неполноценность»?
HTML (от англ. HyperText Markup Language — «язык гипертекстовой разметки») — стандартизированный язык гипертекстовой разметки документов для просмотра веб-страниц в браузере.
Зря старались, автор этого проекта тем временем спокойно пишет в консоль тегами HTML:
<call target="console.log"> <s>FizzBuzz</s> </call>
Все потому что не надо нанимать системных программистов, прошедших полноценное обучение по дисциплинам CS (вроде курса по разработке компиляторов) для работы штатным говночистом разработчиком в обычном корпоративном проекте — о чем так мечтают все рекрутеры.
Может случиться неприятность:
в самый интересный момент окажется что половина работы реализована на чем-то таком интересном.
А сотворивший это «великий гуру» внезапно пропадет, выключив телефон и переехав в поисках истины в солнечную Караганду Канаду.
Прецеденты были.
Дичь вторая: HTML-as-programming-language
Нехорошие мысли терзают очень многих опытных разработчиков — все та же идея «полноценной разработки на HTML» не дает покоя и автору данного проекта.
Но только он зашел в этом процессе несколько дальше предыдущего.
Как вам например функция на чистом HTML:
<def multiplyFunction returns=int> <!-- You can create functions --> <param a type=int/> <param b type=int/> <return>a * b</return> </def> <def main> <var result type=int> <!-- Create variables --> <multiplyFunction> <!-- and store the result of the function in the variable --> <param>5</param> <param>6</param> </multiplyFunction> </var> </def>
Известная библейская истина «многие знания — многие печали» — как раз про этот проект, например я бы очень хотел все это забыть и никогда о подобном не знать.
Но к сожалению уже слишком поздно, поэтому делюсь откровениями:
Да, вы все правильно поняли — это самый настоящий компилятор из HTML в нативный ELF64 бинарник.
А сейчас вам совсем поплохеет:
To write code for Adruino/AVR microcontrollers, (Arduino UNO for example) you need to put a DOCTYPE tag in your HTML file.
For example:
<!DOCTYPE avr/atmega328p>
Да, это была оригинальная задумка автора — разработка для микроконтроллеров на HTML, я ничего не додумываю.
Увидев такой вот
DOCTYPE
, один знакомый веб-разработчик навсегда бросил пить.
К слову, небольшая магия с #include <stdio.h> на скриншоте выше была необходима как раз потому, что компилятор предназначен для микроконтроллеров и не добавляет в генерируемый код на С этот стандартный для обычной ОС заголовок.
К сожалению у меня не оказалось под рукой такого девайса, так что полноценную работу и весь пайплайн проверить не смог.
To compile your AVR/Arduino code:
htmlc my-code.html -compile
To upload your code to an arduino or other AVR microcontroller:
htmlc my-code.html -upload
Но если среди читателей найдутся смелые люди, которые смогут это запустить — с радостью почитаю о впечатлениях.
А мы тем временем переходим к следующему замечательному проекту.
Дичь третья: ass-js
Таким названием и не менее характерным логотипом, авторы честно намекают на суть проекта:
Assembler implemented in JavaScript
Полагаю вы еще никогда не устанавливали компилятор ассемблера с помощью npm? Что ж, все когда‑нибудь бывает в первый раз:
npm i ass-js
А так выглядит классический «Hello, world»:
import {X64} from '../src/index'; const asm = X64(); asm.code(_ => { _('db', 'Hello World!\n'); _('mov', ['rax', 1]); // 0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00 _('mov', ['rdi', 1]); _('lea', ['rsi', _('rip').disp(-34)]); _('mov', ['rdx', 13]); _('syscall'); _('ret'); }); console.log(asm.toString());
Только не показывайте любимому преподавателю курса по ассемблеру — дедушке поплохеет, сердце может не выдержать такого накала дичи.
Вот так выглядит результат работы:
Зато есть отдельный туториал по разбору примера с «Hello world», где по шагам разобрано как оно работает.
Еще нашелся замечательный вопрос к автору:
I was looking at your project and I couldn’t figure out a reason as to why I would (and what, rather) implement with this.
Который как бы намекает на уровень треша и угара в этом проекте. Но едем дальше — к следующему отбитому уникальному проекту.
Дичь четвертая: ts2c
Тут все просто и очевидно:
Produces readable C89 code from JS/TS code.
Собственно все кроме смысла существования этого замечательного проекта — понятно и очевидно. Как-то так выглядит весь пайплайн:
Если вам вдруг будет нужен транспилер из Typescript в чистый Си — берите и пользуйтесь, благо проект очень даже рабочий:
npm install -g ts2c
Работает кстати и из браузера:
<script src="https://unpkg.com/typescript"></script> <script src="ts2c.bundle.js"></script> <script> var cCode = ts2c.transpile("console.log('Hello world!')"); alert(cCode); </script>
Есть даже онлайн версия:
Несмотря на то что автор честно пишет о куче недоработок:
Work in progress: it works, but only about 70% of ES3 specification is currently supported: statements and expressions — 95%, built-in objects — 17%.
Скажу что это самый работоспособный проект из серии, все остальное буквально рассыпается в руках. Рассыпается и валится как и следующий объект исследования.
Дичь пятая: nerd
Как легко и быстро понять что исследуемый проект — дикое, нерабочее и глючное говно?
По описанию, обещающему бесконечные ништяки:
Javascript’s God Mode. No VM. No Bytecode. No GC. Just native binaries.
Отсылка к чему-то божественному в описании технического проекта это вообще практически 100% диагноз, можно отбраковывать только по одному этому признаку — врядли ошибетесь.
Как нетрудно догадаться, вместо нормального JavaScript тут тоже что-то свое божественное:
NerdLang is a substract of JS with some additions, focus on efficiency.
И это «свое» скажем так застряло в далеком прошлом:
Supporting EcmaScript 3 standard
На минуточку, 3я редакция стандарта вышла еще в далеком 2000м году.
А сам проект пытается в который раз «натянуть сову на глобус» и залезть туда, где последовательно обломали клыки все крупные корпрорации уровня Google:
Nerd is a JavaScript native compiler aiming to make JavaScript universal, Nerd is able to compile native apps for Windows, Mac, Linux, iOS, Android, Raspberry, STM32 and more.
Разумеется я не мог пройти мимо такого, поэтому всю эту дичь собрал и запустил, хотя и пришлось немного исправлять скрипты сборки.
Пайплайн (присутствует на титульном скриншоте) выглядит вот так:
Автор настолько суров, что запихал инстукции сборки и линковки модуля работы с сокетами в package.json:
{ .. "version": "0.0.1", "nerd": { "env": ["std"], "read_only": [], "lib": { "win32": [ "-D_WIN32_WINNT=0x0600", "-Wno-narrowing", "-D_GNU_SOURCE", "-I{__EXTERN__}/libuv/include/", "-I{__EXTERN__}/libuv/src/", "-D_CRT_SECURE_NO_DEPRECATE", "-D_CRT_NONSTDC_NO_DEPRECATE", "{__EXTERN__}/libuv/src/*.h", "{__EXTERN__}/libuv/src/*.c", "{__EXTERN__}/libuv/src/win/*.h", "{__EXTERN__}/libuv/src/win/*.c", "-I {__MODULE__}/httplib/uWS/", "-I {__MODULE__}/httplib/uSockets/", "{__MODULE__}/httplib/uSockets/*.c", "{__MODULE__}/httplib/uSockets/crypto/*.c", "{__MODULE__}/httplib/uSockets/eventing/*.c", "-DLIBUS_NO_SSL", "-DUWS_NO_ZLIB", "-fpermissive", "-w", "-lm", "-ladvapi32", "-liphlpapi", "-lpsapi", "-lshell32", "-luser32 ", "-luserenv", "-lwsock32", "-lws2_32" ] } } }
Увидев вот такой package.json, знакомый веб-разработчик (другой) решил навсегда уйти из профессии и теперь пасет коз в горах Кавказа.
Ну а я всего лишь не рискнул адаптировать такое для сборки под Linux, так что вы останетесь без примера запуска HTTP-сервера на этом чудище.
Дичь шестая: lemon
Наконец последний на сегодня проект, который по сравнению с предыдущими является можно сказать нормальным и где-то даже применимым:
Lemon is a framework for building Javascript runtime software, built on the Chrome V8 Javascript Engine.
Мне он понравился своей запредельной простотой (по сравнению со всеми остальными проектами) и легкостью встраивания.
Специально показываю скрипт сборки целиком:
CXX = g++ V8 = engine/lib/v8 define INCLUDE $(V8)/include engine/Core.cpp engine/Environment.cpp engine/Lemon.cpp engine/StaticHelpers.cpp engine/ObjectCreator.cpp endef define APP app/*.cpp endef define LIB $(V8)/out/x64.release/obj/ endef define OBJ v8_monolith endef export INCLUDE export APP export LIB export OBJ build: (CXX) -I " class="formula inline">$INCLUDE $$APP -L $$LIB -l $$OBJ -std=c++0x -pthread -o lemon
И.. это все.
Настолько простую сборку V8 вижу впервые в жизни, честно.
Оно действительно собирается одной командой:
Ниже показано как выглядит двойной «Hello, world», в котором есть как часть на JavaScript так и часть на C++ — немного подумав объединил два примера из документации в один.
App.js:
version(); console.log("Превед из JS"); helloworld();
App.hpp:
#ifndef APP #define APP #include "../engine/Lemon.hpp" using v8::Context; class App : public Lemon { public: void Start(int argc, char* argv[]); void SetupEnvironment(); }; #endif
App.cpp:
#include "App.hpp" using namespace v8; static void Log(const FunctionCallbackInfo<Value>& args) { HandleScope scope(args.GetIsolate()); String::Utf8Value str(args.GetIsolate(), args[0]); const char* cstr = StaticHelpers::ToCString(str); fprintf(stdout, "%s", cstr); fprintf(stdout, "\n"); fflush(stdout); } static void HelloWorld(const FunctionCallbackInfo<Value>& args) { printf("Превед из C++ \n"); } void App::SetupEnvironment() { this->CreateGlobalMethod("helloworld", HelloWorld); } void App::Start(int argc, char* argv[]) { for (int i = 1; i < argc; ++i) { // Get filename of the javascript file to run const char* filename = argv[i]; // Create a new context for executing javascript code Local<Context> context = this->CreateLocalContext(); // Enter the new context Context::Scope contextscope(context); this->CreateGlobalObject("console") .SetPropertyMethod("log", Log) .Register(); // Run the javascript file this->RunJsFromFile(filename); } }
Чудны дела твои Господи, коль даже перебирая запредельную дичь есть шанс найти столь мощный проект.
Спросите с чего столько радости?
Потому что это самый настоящий V8, не самопал с реализацией ECMAScript «в переводе Гоблина», а именно тот самый движок, который используется в браузере Chrome — со всеми оптимизациями и наворотами.
А значит при определенных усилиях, у вас будет работать практически любой JavaScript код — в вашем нативном приложении, без всяких жирных Node.js и всех проблем с линковкой и версиями.
Словом берите на вооружение, пригодится.
Одной строкой
Конечно же интересных проектов в области творения дичи куда больше чем хватит сил описать, поэтому ниже небольшая подборка найденного и интересного, но неработающего.
Compile javascript to LLVM IR, x86 assembly and self interpreting
К сожалению оказался прибит гвоздями к определенной версии MacOS, ни нормально собрать ни прогнать тесты под Linux не удалось. Интересен тем что в одном проекте собран и интерпретатор и компилятор, причем в нативный бинарник.
JavaScript Assembler x86-16
Генерирует готовые COM-файлы времен DOS, но под эмулятором Dosbox они работать отказались.
Duktape — embeddable Javascript engine with a focus on portability and compact footprint
Более продвинутый и известный аналог Lemon, который я нашел слишком поздно и не успел посмотреть.
«clang ported to js» — можно сразу в цитаты добавлять.
Сломанная и сильно устаревшая сборка, но сам проект — очень крутой, поскольку это полноценный компилятор Clang, вытащенный в веб.
Вот тут есть онлайн версия.
LLVM compiled to JavaScript using Emscripten
Снова сломанная и устаревшая сборка, починить за разумное время не получилось.
Она же в готовом виде онлайн.
Compile JS into LLVM IR — JavaScript Static Analysis Tool
Вот тут находится статья про этот проект, но мне собрать так и не удалось.
A toy js -> c++ compiler written in coffeescript. Uses escodegen to write c++ and tern to figure out types.
Опять сильно устаревшая и сломанная сборка.
Compiled implementation of Javascript, targeting C (for fun)
Половина тестов сломана, но сама сборка проходит — не стал детально изучать.
Letter is a compiler project built in TypeScript using LLVM node bindings.
Очень интересный, но к сожалению устаревший проект — требует 13й LLVM и старую же версию Node.js.
Подружить с новыми версиями LLVM и Node не удалось.
A tiny C compiler written purely in JavaScript.
Еще один интересный, но неработающий проект — сам компилятор отработал, но ассемблерный код отказался собираться.
Эпилог
Все описанные в этой статье проекты приведены в первую очередь для расширения границ вашего воображения — просто чтобы вы знали что так тоже бывает.
Пожалуйста не пытайтесь такое внедрять и использовать в рельном проекте, если не имеете за плечами серьезного опыта и/или профильного обучения по CS.
Либо умеете быстро бегать и имеете запасное гражданство.
Куда более вольная версия данной статьи доступна в нашем блоге.
0x08 Software
Мы небольшая команда ветеранов ИТ‑индустрии, создаем и дорабатываем самое разнообразное программное обеспечение, наш софт автоматизирует бизнес‑процессы на трех континентах, в самых разных отраслях и условиях.
Оживляем давно умершее, чиним никогда не работавшее и создаем невозможное — затем рассказываем об этом в своих статьях.
ссылка на оригинал статьи https://habr.com/ru/articles/824248/
Добавить комментарий