Merge pull request #6 from frantic/transpile-js
Automated script to transpile code and tests to C
This commit is contained in:
5
Makefile
5
Makefile
@@ -1,6 +1,11 @@
|
||||
|
||||
FILES=src/__tests__/Layout-test.c src/Layout.c src/Layout-test-utils.c
|
||||
|
||||
all: c test
|
||||
|
||||
c:
|
||||
@node ./src/transpile.js
|
||||
|
||||
test:
|
||||
@gcc -Weverything -Werror -Wno-padded $(FILES) && ./a.out
|
||||
@rm a.out
|
||||
|
@@ -2,6 +2,16 @@
|
||||
#include "Layout-test-utils.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/** START_GENERATED **/
|
||||
#define SMALL_WIDTH 34.671875
|
||||
#define SMALL_HEIGHT 18
|
||||
#define BIG_WIDTH 172.421875
|
||||
#define BIG_HEIGHT 36
|
||||
#define BIG_MIN_WIDTH 100.453125
|
||||
#define SMALL_TEXT "small"
|
||||
#define LONG_TEXT "loooooooooong with space"
|
||||
/** END_GENERATED **/
|
||||
|
||||
typedef struct failed_test_t {
|
||||
struct failed_test_t *next;
|
||||
const char *name;
|
||||
@@ -52,14 +62,14 @@ css_dim_t measure(void *context, float width) {
|
||||
if (width != width) {
|
||||
width = 1000000;
|
||||
}
|
||||
if (strcmp(text, "small") == 0) {
|
||||
dim.dimensions[CSS_WIDTH] = fminf(33, width);
|
||||
dim.dimensions[CSS_HEIGHT] = 18;
|
||||
if (strcmp(text, SMALL_TEXT) == 0) {
|
||||
dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width);
|
||||
dim.dimensions[CSS_HEIGHT] = SMALL_HEIGHT;
|
||||
return dim;
|
||||
}
|
||||
if (strcmp(text, "loooooooooong with space") == 0) {
|
||||
dim.dimensions[CSS_WIDTH] = width >= 171 ? 171 : fmaxf(100, width);
|
||||
dim.dimensions[CSS_HEIGHT] = width >= 171 ? 18 : 36;
|
||||
if (strcmp(text, LONG_TEXT) == 0) {
|
||||
dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width);
|
||||
dim.dimensions[CSS_HEIGHT] = width >= BIG_WIDTH ? SMALL_HEIGHT : BIG_HEIGHT;
|
||||
return dim;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,11 @@
|
||||
/** @nolint */
|
||||
/* globals document, computeLayout */
|
||||
|
||||
var layoutTestUtils = (function() {
|
||||
var iframe = (function() {
|
||||
var cachedIframe;
|
||||
function getIframe() {
|
||||
if (cachedIframe) {
|
||||
return cachedIframe;
|
||||
}
|
||||
var iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
var doc = iframe.contentDocument;
|
||||
@@ -29,15 +33,14 @@ var layoutTestUtils = (function() {
|
||||
}
|
||||
*/} + '').slice(15, -4);
|
||||
doc.head.appendChild(style);
|
||||
|
||||
cachedIframe = iframe;
|
||||
return iframe;
|
||||
})();
|
||||
var body = iframe.contentDocument.body;
|
||||
}
|
||||
|
||||
var iframeText = document.createElement('iframe');
|
||||
document.body.appendChild(iframeText);
|
||||
|
||||
if (typeof computeLayout === 'function') {
|
||||
var realComputeLayout = computeLayout;
|
||||
}
|
||||
|
||||
function computeCSSLayout(rootNode) {
|
||||
function fillNodes(node) {
|
||||
@@ -74,7 +77,7 @@ var layoutTestUtils = (function() {
|
||||
}
|
||||
|
||||
function computeDOMLayout(node) {
|
||||
var body = iframe.contentDocument.body;
|
||||
var body = getIframe().contentDocument.body;
|
||||
|
||||
function transfer(div, node, name, ext) {
|
||||
if (name in node.style) {
|
||||
@@ -229,7 +232,11 @@ var layoutTestUtils = (function() {
|
||||
return node;
|
||||
}
|
||||
|
||||
var iframeText;
|
||||
function measureTextSizes(text, width) {
|
||||
iframeText = iframeText || document.createElement('iframe');
|
||||
document.body.appendChild(iframeText);
|
||||
|
||||
var body = iframeText.contentDocument.body;
|
||||
if (width === undefined || width !== width) {
|
||||
width = Infinity;
|
||||
@@ -262,13 +269,24 @@ var layoutTestUtils = (function() {
|
||||
big: 'loooooooooong with space',
|
||||
};
|
||||
|
||||
var textSizes = {
|
||||
var textSizes;
|
||||
if (typeof require === 'function') {
|
||||
textSizes = {
|
||||
smallWidth: 34.671875,
|
||||
smallHeight: 18,
|
||||
bigWidth: 172.421875,
|
||||
bigHeight: 36,
|
||||
bigMinWidth: 100.453125
|
||||
};
|
||||
} else {
|
||||
textSizes = {
|
||||
smallWidth: measureTextSizes(texts.small, 0).width,
|
||||
smallHeight: measureTextSizes(texts.small, 0).height,
|
||||
bigWidth: measureTextSizes(texts.big).width,
|
||||
bigHeight: measureTextSizes(texts.big, 0).height,
|
||||
bigMinWidth: measureTextSizes(texts.big, 0).width,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
texts: texts,
|
||||
@@ -317,3 +335,7 @@ var layoutTestUtils = (function() {
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = layoutTestUtils;
|
||||
}
|
||||
|
@@ -322,6 +322,7 @@ static float getRelativePosition(css_node_t *node, css_flex_direction_t axis) {
|
||||
}
|
||||
|
||||
static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
||||
/** START_GENERATED **/
|
||||
css_flex_direction_t mainAxis = getFlexDirection(node);
|
||||
css_flex_direction_t crossAxis = mainAxis == CSS_FLEX_DIRECTION_ROW ?
|
||||
CSS_FLEX_DIRECTION_COLUMN :
|
||||
@@ -672,6 +673,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** END_GENERATED **/
|
||||
}
|
||||
|
||||
void layoutNode(css_node_t *node, float parentMaxWidth) {
|
||||
@@ -702,4 +704,3 @@ void layoutNode(css_node_t *node, float parentMaxWidth) {
|
||||
layout->last_position[CSS_LEFT] = layout->position[CSS_LEFT];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -551,4 +551,7 @@ var computeLayout = (function() {
|
||||
};
|
||||
})();
|
||||
|
||||
if (typeof module === 'object') {
|
||||
module.exports = computeLayout;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,6 @@
|
||||
/* globals layoutTestUtils */
|
||||
|
||||
var testLayout = layoutTestUtils.testLayout;
|
||||
var testRandomLayout = layoutTestUtils.testRandomLayout;
|
||||
var computeLayout = layoutTestUtils.computeLayout;
|
||||
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
||||
var reduceTest = layoutTestUtils.reduceTest;
|
||||
var text = layoutTestUtils.text;
|
||||
var texts = layoutTestUtils.texts;
|
||||
var textSizes = layoutTestUtils.textSizes;
|
||||
|
@@ -1,75 +1,41 @@
|
||||
<script src="Layout.js"></script>
|
||||
var layoutTestUtils = require('./Layout-test-utils.js');
|
||||
var computeLayout = require('./Layout.js');
|
||||
var fs = require('fs');
|
||||
|
||||
<style>
|
||||
textarea {
|
||||
height: 200px;
|
||||
width: 800px;
|
||||
border: 1px solid black;
|
||||
font-size: 12px;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>layoutCode</h1>
|
||||
<textarea id="layout_code" onclick="this.select()"></textarea>
|
||||
<script>
|
||||
document.getElementById('layout_code').value = computeLayout.toString()
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/\.children\.length/g, '.children_count')
|
||||
.replace(/\.width/g, '.dimensions[CSS_WIDTH]')
|
||||
.replace(/\.height/g, '.dimensions[CSS_HEIGHT]')
|
||||
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/node.children\[i\]/g, 'node->get_child(node->context, i)')
|
||||
.replace(/node\./g, 'node->')
|
||||
.replace(/child\./g, 'child->')
|
||||
.replace(/parent\./g, 'parent->')
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/\n /g, '\n')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.split('\n').slice(1).join('\n');
|
||||
</script>
|
||||
|
||||
<h1>Tests</h1>
|
||||
<textarea id="test_code" onclick="this.select()"></textarea>
|
||||
<script src="Layout-test-utils.js"></script>
|
||||
<script>
|
||||
var currentTest = '';
|
||||
var allTests = [];
|
||||
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
||||
var computeLayout = layoutTestUtils.computeLayout;
|
||||
var reduceTest = layoutTestUtils.reduceTest;
|
||||
var text = layoutTestUtils.text;
|
||||
var layoutTestUtils = {
|
||||
global.layoutTestUtils = {
|
||||
testLayout: function(node, expectedLayout) {
|
||||
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
||||
},
|
||||
testRandomLayout: function(node, i) {
|
||||
allTests.push({name: 'Random #' + i, node: node, expectedLayout: computeDOMLayout(node)});
|
||||
},
|
||||
computeLayout: computeLayout,
|
||||
computeDOMLayout: computeDOMLayout,
|
||||
computeLayout: layoutTestUtils.computeLayout,
|
||||
reduceTest: reduceTest,
|
||||
text: text,
|
||||
text: layoutTestUtils.text,
|
||||
texts: layoutTestUtils.texts,
|
||||
textSizes: layoutTestUtils.textSizes,
|
||||
textSizes: layoutTestUtils.textSizes
|
||||
};
|
||||
function describe(name, cb) { cb(); }
|
||||
function it(name, cb) { currentTest = name; cb(); }
|
||||
xit = it;
|
||||
</script>
|
||||
<script src="__tests__/Layout-test.js"></script>
|
||||
<script>
|
||||
|
||||
global.describe = function(name, cb) { cb(); };
|
||||
global.it = function(name, cb) { currentTest = name; cb(); };
|
||||
global.xit = global.it;
|
||||
|
||||
require('./__tests__/Layout-test.js');
|
||||
|
||||
|
||||
function printLayout(test) {
|
||||
var level = 1;
|
||||
var res = [];
|
||||
|
||||
function add(str) {
|
||||
res.push(indent(level) + str);
|
||||
if (str.length > 0) {
|
||||
str = indent(level) + str;
|
||||
}
|
||||
res.push(str);
|
||||
}
|
||||
|
||||
function isEmpty(obj) {
|
||||
@@ -237,10 +203,53 @@ function printLayout(test) {
|
||||
add('test("' + test.name.replace(/"/g, '\\"') + '", root_node, root_layout);');
|
||||
level--;
|
||||
add('}');
|
||||
add('');
|
||||
add('tests_finished();');
|
||||
|
||||
return res.join('\n');
|
||||
}
|
||||
document.getElementById('test_code').value = allTests.map(printLayout).join('\n\n');
|
||||
</script>
|
||||
|
||||
function transpileAnnotatedJStoC(jsCode) {
|
||||
return jsCode
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/\.children\.length/g, '.children_count')
|
||||
.replace(/\.width/g, '.dimensions[CSS_WIDTH]')
|
||||
.replace(/\.height/g, '.dimensions[CSS_HEIGHT]')
|
||||
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/node.children\[i\]/g, 'node->get_child(node->context, i)')
|
||||
.replace(/node\./g, 'node->')
|
||||
.replace(/child\./g, 'child->')
|
||||
.replace(/parent\./g, 'parent->')
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/\n /g, '\n')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.split('\n').slice(1, -1).join('\n');
|
||||
}
|
||||
|
||||
function makeConstDefs() {
|
||||
var lines = [
|
||||
'#define SMALL_WIDTH ' + layoutTestUtils.textSizes.smallWidth,
|
||||
'#define SMALL_HEIGHT ' + layoutTestUtils.textSizes.smallHeight,
|
||||
'#define BIG_WIDTH ' + layoutTestUtils.textSizes.bigWidth,
|
||||
'#define BIG_HEIGHT ' + layoutTestUtils.textSizes.bigHeight,
|
||||
'#define BIG_MIN_WIDTH ' + layoutTestUtils.textSizes.bigMinWidth,
|
||||
'#define SMALL_TEXT "' + layoutTestUtils.texts.small + '"',
|
||||
'#define LONG_TEXT "' + layoutTestUtils.texts.big + '"'
|
||||
];
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function generateFile(fileName, generatedContent) {
|
||||
var content = fs.readFileSync(fileName, 'utf8').toString();
|
||||
content = content.replace(new RegExp(
|
||||
/\/\*\* START_GENERATED \*\*\/[\s\S]*\/\*\* END_GENERATED \*\*\//
|
||||
), '/** START_GENERATED **/\n' + generatedContent + '\n /** END_GENERATED **/');
|
||||
|
||||
fs.writeFileSync(fileName, content);
|
||||
}
|
||||
|
||||
|
||||
generateFile(__dirname + '/__tests__/Layout-test.c', allTests.map(printLayout).join('\n\n'));
|
||||
generateFile(__dirname + '/Layout-test-utils.c', makeConstDefs());
|
||||
generateFile(__dirname + '/Layout.c', transpileAnnotatedJStoC(computeLayout.toString()));
|
Reference in New Issue
Block a user