- PVSM.RU - https://www.pvsm.ru -

Творим дичь с помощью инструментов веб-разработки

Или что бывает если заставить очень опытного разработчика заниматься не своим делом. Думаю после этой статьи термин «overqualified [1]» заиграет для вас новыми красками.

От авторов, запихнувших веб‑сервер на визитку [2] и локализующих корпоративные приложения на клингонский [3] — держим марку!

Пять минут вдумчивого изучения этого скриншота могут привести к нервному срыву, я предупредил.

Пять минут вдумчивого изучения этого скриншота могут привести к нервному срыву, я предупредил.

Наш волшебный дикий веб

Что первым делом приходит в голову, когда говорят о «веб-разработке»? Наверное создание сайтов или веб-приложений?

Лендинги, сайты-визитки, интернет-магазины или какие-нибудь веб-порталы в ад.

Самые продвинутые из читателей наверное вспомнят PWA [4] или какой-нибудь React Native [5] с Flutter [6] — предел полета фантазии обычного разработчика.

Что плохо:

главное что отделяет человека от великих свершений это его фантазия — точно нельзя сделать только то, что невозможно вообразить.

Поэтому сейчас мы будем расширять ваше воображение — в превентивных мерах, дрелью и дыроколом подручными средствами.

Перед вами шесть проектов отборнейшей дичи — реализующих самые безумные идеи с помощью вполне обыденных инструментов современного веб-разработчика.

Пожалуйста не пытайтесь рассказывать о таком на интервью в обычных компаниях — пожалейте интервьюера и его нежную психику.

Автор когда‑то давно (когда еще ходил по собеседованиям) довел одного интервьюера до нервного срыва, просто в деталях рассказав как на самом деле работает загрузка больших файлов через форму со стороны сервера — про HTTP 100 Continue [7], разбор MIME и прочие радости.

Люди тогда были сильно крепче головой чем сейчас, в нынешних реалиях могут и побить прямо на интервью.

Дичь первая: HTMLang

Не смог пропустить столь жизнеутверждающее описание от автора этого замечательного проекта [8]:

They were laughing that HTML was not a real programming language... WHO"S LAUGHING NOW!!11

Да, это именно то что вы подумали — кто-то будучи сильно не в духе взял общий синтаксис HTML и создал на его основе полноценный язык программирования.

Вот так выглядит реализация знаменитого FizzBuzz [9]:

<!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>

Не представляю что будет если самому Джоэлу [10] выдать его же знаменитый «FizzBuzz» в такой реализации — есть шанс что старый сишный программист впадет в рекурсию.

Кстати кто там рассказывал на лекциях про «декларативный язык разметки» и «общую неполноценность»?

HTML (от англ. [11] HyperText Markup Language — «язык гипертекстовой [12] разметки») — стандартизированный язык гипертекстовой разметки документов для просмотра веб-страниц [13] в браузере [14].

Зря старались, автор этого проекта тем временем спокойно пишет в консоль тегами HTML:

<call target="console.log">
        <s>FizzBuzz</s>
</call>

Все потому что не надо нанимать системных программистов, прошедших полноценное обучение по дисциплинам CS (вроде курса по разработке компиляторов) для работы штатным говночистом разработчиком в обычном корпоративном проекте — о чем так мечтают все рекрутеры.

Может случиться неприятность:

в самый интересный момент окажется что половина работы реализована на чем-то таком интересном.

А сотворивший это «великий гуру» внезапно пропадет, выключив телефон и переехав в поисках истины в солнечную Караганду Канаду.

Прецеденты были.

Дичь вторая: HTML-as-programming-language

Нехорошие мысли терзают очень многих опытных разработчиков — все та же идея «полноценной разработки на HTML [15]» не дает покоя и автору данного проекта.

Но только он зашел в этом процессе несколько дальше предыдущего.

Как вам например функция на чистом 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>

Известная библейская истина «многие знания — многие печали [16]» — как раз про этот проект, например я бы очень хотел все это забыть и никогда о подобном не знать.

Но к сожалению уже слишком поздно, поэтому делюсь откровениями:

Замечательный пайплайн с вызовом компилятора HTML, правда?

Замечательный пайплайн с вызовом компилятора HTML, правда?

Да, вы все правильно поняли — это самый настоящий компилятор из 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> на скриншоте выше была необходима как раз потому, что компилятор предназначен для микроконтроллеров и не добавляет в генерируемый код на С этот стандартный для обычной ОС заголовок.

Вот так выглядит эта железка, если никогда не видели.

Вот так выглядит эта железка [17], если никогда не видели.

К сожалению у меня не оказалось под рукой такого девайса, так что полноценную работу и весь пайплайн проверить не смог.

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

Таким названием и не менее характерным логотипом [18], авторы честно намекают на суть проекта:

Assembler implemented in JavaScript

Полагаю вы еще никогда не устанавливали компилятор ассемблера с помощью npm [19]? Что ж, все когда‑нибудь бывает в первый раз:

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());

Только не показывайте любимому преподавателю курса по ассемблеру — дедушке поплохеет, сердце может не выдержать такого накала дичи.

Вот так выглядит результат работы:

К сожалению выдаваемый ассемблерный код оказался нерабочим и отказался компилироваться в бинарник на моей машине.

К сожалению выдаваемый ассемблерный код оказался нерабочим и отказался компилироваться в бинарник на моей машине.

Зато есть отдельный туториал [20] по разбору примера с «Hello world», где по шагам разобрано как оно работает.

Еще нашелся замечательный вопрос [21] к автору:

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

Тут [22] все просто и очевидно:

Produces readable C89 code from JS/TS code.

Собственно все кроме смысла существования этого замечательного проекта — понятно и очевидно. Как-то так выглядит весь пайплайн:

Творим дичь с помощью инструментов веб-разработки - 5

Если вам вдруг будет нужен транспилер [23] из 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>

Есть даже онлайн версия [24]:

Творим дичь с помощью инструментов веб-разработки - 6

Несмотря на то что автор честно пишет о куче недоработок:

Work in progress: it works, but only about 70% of ES3 specification is currently supported: statements and expressions - 95%, built-in objects - 17%.

Скажу что это самый работоспособный проект из серии, все остальное буквально рассыпается в руках. Рассыпается и валится как и следующий объект исследования.

Дичь пятая: nerd

Как легко и быстро понять что исследуемый проект [25] — дикое, нерабочее и глючное говно?

По описанию, обещающему бесконечные ништяки:

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я редакция [26] стандарта вышла еще в далеком 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.

Разумеется я не мог пройти мимо такого, поэтому всю эту дичь собрал и запустил, хотя и пришлось немного исправлять скрипты сборки.

Пайплайн (присутствует на титульном скриншоте) выглядит вот так:

Творим дичь с помощью инструментов веб-разработки - 7

Автор настолько суров, что запихал инстукции сборки и линковки модуля работы с сокетами в 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

Наконец последний на сегодня проект [27], который по сравнению с предыдущими является можно сказать нормальным и где-то даже применимым:

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 [28] вижу впервые в жизни, честно.

Оно действительно собирается одной командой:

Творим дичь с помощью инструментов веб-разработки - 8

Ниже показано как выглядит двойной «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 [28], не самопал с реализацией ECMAScript «в переводе Гоблина», а именно тот самый движок, который используется в браузере Chrome — со всеми оптимизациями и наворотами.

А значит при определенных усилиях, у вас будет работать практически любой JavaScript код — в вашем нативном приложении, без всяких жирных Node.js и всех проблем с линковкой и версиями.

Словом берите на вооружение, пригодится.

Одной строкой

Конечно же интересных проектов в области творения дичи куда больше чем хватит сил описать, поэтому ниже небольшая подборка найденного и интересного, но неработающего.

js-ziju [29]

Compile javascript to LLVM IR, x86 assembly and self interpreting

К сожалению оказался прибит гвоздями к определенной версии MacOS, ни нормально собрать ни прогнать тесты под Linux не удалось. Интересен тем что в одном проекте собран и интерпретатор и компилятор, причем в нативный бинарник.

JS-ASM [30]

JavaScript Assembler x86-16

Генерирует готовые COM-файлы времен DOS, но под эмулятором Dosbox они работать отказались.

Duktape [31]

Duktape — embeddable Javascript engine with a focus on portability and compact footprint

Более продвинутый и известный аналог Lemon, который я нашел слишком поздно и не успел посмотреть.

clangor [32]

«clang ported to js» — можно сразу в цитаты добавлять.

Сломанная и сильно устаревшая сборка, но сам проект — очень крутой, поскольку это полноценный компилятор Clang, вытащенный в веб.

Вот тут [33] есть онлайн версия.

llvm.js [34]

LLVM compiled to JavaScript using Emscripten

Снова сломанная и устаревшая сборка, починить за разумное время не получилось.

Она же в готовом виде онлайн [35].

jssat [36]

Compile JS into LLVM IR - JavaScript Static Analysis Tool

Вот тут [37] находится статья про этот проект, но мне собрать так и не удалось.

js2cpp [38]

A toy js -> c++ compiler written in coffeescript. Uses escodegen to write c++ and tern to figure out types.

Опять сильно устаревшая и сломанная сборка.

js-to-c [39]

Compiled implementation of Javascript, targeting C (for fun)

Половина тестов сломана, но сама сборка проходит — не стал детально изучать.

Letter [40]

Letter is a compiler project built in TypeScript using LLVM node bindings.

Очень интересный, но к сожалению устаревший проект — требует 13й LLVM и старую же версию Node.js.

Подружить с новыми версиями LLVM и Node не удалось.

CaptCC [41]

A tiny C compiler written purely in JavaScript.

Еще один интересный, но неработающий проект — сам компилятор отработал, но ассемблерный код отказался собираться.

Эпилог

Все описанные в этой статье проекты приведены в первую очередь для расширения границ вашего воображения — просто чтобы вы знали что так тоже бывает.

Пожалуйста не пытайтесь такое внедрять и использовать в рельном проекте, если не имеете за плечами серьезного опыта и/или профильного обучения по CS.

Либо умеете быстро бегать и имеете запасное гражданство.

Куда более вольная версия [42] данной статьи доступна в нашем блоге.

0x08 Software

Мы небольшая команда ветеранов ИТ‑индустрии, создаем и дорабатываем самое разнообразное программное обеспечение, наш софт автоматизирует бизнес‑процессы на трех континентах, в самых разных отраслях и условиях.

Оживляем давно умершее [43]чиним никогда не работавшее [44] и создаем невозможное [45] — затем рассказываем об этом в своих статьях.

Автор: Alex Chernyshev

Источник [46]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/c-3/392356

Ссылки в тексте:

[1] overqualified: https://ru.wikipedia.org/wiki/%D0%A1%D0%B2%D0%B5%D1%80%D1%85%D0%BA%D0%B2%D0%B0%D0%BB%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F

[2] запихнувших веб‑сервер на визитку: https://habr.com/ru/articles/821959/

[3] локализующих корпоративные приложения на клингонский: https://habr.com/ru/articles/823836/

[4] PWA: https://en.wikipedia.org/wiki/Progressive_web_app

[5] React Native: https://reactnative.dev/

[6] Flutter: https://en.wikipedia.org/wiki/Flutter_(software)

[7] HTTP 100 Continue: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/100

[8] замечательного проекта: https://github.com/tsoding/HTMLang/tree/master

[9] FizzBuzz: https://en.wikipedia.org/wiki/Fizz_buzz

[10] Джоэлу: https://en.wikipedia.org/wiki/Joel_Spolsky

[11] англ.: https://ru.wikipedia.org/wiki/%D0%90%D0%BD%D0%B3%D0%BB%D0%B8%D0%B9%D1%81%D0%BA%D0%B8%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA

[12] гипертекстовой: https://ru.wikipedia.org/wiki/%D0%93%D0%B8%D0%BF%D0%B5%D1%80%D1%82%D0%B5%D0%BA%D1%81%D1%82

[13] веб-страниц: https://ru.wikipedia.org/wiki/%D0%92%D0%B5%D0%B1-%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0

[14] браузере: https://ru.wikipedia.org/wiki/%D0%91%D1%80%D0%B0%D1%83%D0%B7%D0%B5%D1%80

[15] полноценной разработки на HTML: https://github.com/HTML-as-programming-language/HTML-as-programming-language

[16] многие знания — многие печали: https://cyclowiki.org/wiki/%D0%9C%D0%BD%D0%BE%D0%B3%D0%B8%D0%B5_%D0%B7%D0%BD%D0%B0%D0%BD%D0%B8%D1%8F_%E2%80%94_%D0%BC%D0%BD%D0%BE%D0%B3%D0%B8%D0%B5_%D0%BF%D0%B5%D1%87%D0%B0%D0%BB%D0%B8

[17] железка: https://www.arduino.cc/

[18] не менее характерным логотипом: https://github.com/streamich/ass-js

[19] npm: https://en.wikipedia.org/wiki/NPM

[20] туториал: https://github.com/streamich/ass-js/blob/master/docs/examples/hello_world.md

[21] вопрос: https://github.com/streamich/ass-js/issues/54

[22] Тут: https://github.com/andrei-markeev/ts2c

[23] транспилер: https://en.wikipedia.org/wiki/Source-to-source_compiler

[24] онлайн версия: https://andrei-markeev.github.io/ts2c/

[25] исследуемый проект: https://github.com/NerdLang/nerd

[26] 3я редакция: https://www-archive.mozilla.org/js/language/E262-3.pdf

[27] проект: https://github.com/nordin-johan/lemon

[28] V8: https://v8.dev/

[29] js-ziju: https://github.com/wizardpisces/js-ziju

[30] JS-ASM: https://github.com/iEPCBM/JS-ASM

[31] Duktape: https://github.com/svaarala/duktape

[32] clangor: https://github.com/kripken/clangor

[33] тут: https://kripken.github.io/clangor/demo.html

[34] llvm.js: https://github.com/kripken/llvm.js

[35] онлайн: https://kripken.github.io/llvm.js/demo.html

[36] jssat: https://github.com/monoclex/jssat

[37] тут: https://sirjosh3917.com/posts/jssat-compiling-javascript-to-llvm-ir/

[38] js2cpp: https://github.com/fabiosantoscode/js2cpp

[39] js-to-c: https://github.com/timruffles/js-to-c

[40] Letter: https://github.com/willothy/Letter

[41] CaptCC: https://github.com/Captainarash/CaptCC

[42] вольная версия: https://blog.0x08.ru/bloody-hell-with-web-tools

[43] давно умершее: https://blog.0x08.ru/xerox-alto-bcpl-hello-world

[44] чиним никогда не работавшее: https://blog.0x08.ru/running-from-websphere-esb

[45] невозможное: https://blog.0x08.ru/call-webservice-from-dos

[46] Источник: https://habr.com/ru/articles/824248/?utm_source=habrahabr&utm_medium=rss&utm_campaign=824248