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
|
FILES=src/__tests__/Layout-test.c src/Layout.c src/Layout-test-utils.c
|
||||||
|
|
||||||
|
all: c test
|
||||||
|
|
||||||
|
c:
|
||||||
|
@node ./src/transpile.js
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@gcc -Weverything -Werror -Wno-padded $(FILES) && ./a.out
|
@gcc -Weverything -Werror -Wno-padded $(FILES) && ./a.out
|
||||||
@rm a.out
|
@rm a.out
|
||||||
|
@@ -2,6 +2,16 @@
|
|||||||
#include "Layout-test-utils.h"
|
#include "Layout-test-utils.h"
|
||||||
#include <stdlib.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 {
|
typedef struct failed_test_t {
|
||||||
struct failed_test_t *next;
|
struct failed_test_t *next;
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -52,14 +62,14 @@ css_dim_t measure(void *context, float width) {
|
|||||||
if (width != width) {
|
if (width != width) {
|
||||||
width = 1000000;
|
width = 1000000;
|
||||||
}
|
}
|
||||||
if (strcmp(text, "small") == 0) {
|
if (strcmp(text, SMALL_TEXT) == 0) {
|
||||||
dim.dimensions[CSS_WIDTH] = fminf(33, width);
|
dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width);
|
||||||
dim.dimensions[CSS_HEIGHT] = 18;
|
dim.dimensions[CSS_HEIGHT] = SMALL_HEIGHT;
|
||||||
return dim;
|
return dim;
|
||||||
}
|
}
|
||||||
if (strcmp(text, "loooooooooong with space") == 0) {
|
if (strcmp(text, LONG_TEXT) == 0) {
|
||||||
dim.dimensions[CSS_WIDTH] = width >= 171 ? 171 : fmaxf(100, width);
|
dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width);
|
||||||
dim.dimensions[CSS_HEIGHT] = width >= 171 ? 18 : 36;
|
dim.dimensions[CSS_HEIGHT] = width >= BIG_WIDTH ? SMALL_HEIGHT : BIG_HEIGHT;
|
||||||
return dim;
|
return dim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,11 @@
|
|||||||
/** @nolint */
|
/* globals document, computeLayout */
|
||||||
|
|
||||||
var layoutTestUtils = (function() {
|
var layoutTestUtils = (function() {
|
||||||
var iframe = (function() {
|
var cachedIframe;
|
||||||
|
function getIframe() {
|
||||||
|
if (cachedIframe) {
|
||||||
|
return cachedIframe;
|
||||||
|
}
|
||||||
var iframe = document.createElement('iframe');
|
var iframe = document.createElement('iframe');
|
||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
var doc = iframe.contentDocument;
|
var doc = iframe.contentDocument;
|
||||||
@@ -29,15 +33,14 @@ var layoutTestUtils = (function() {
|
|||||||
}
|
}
|
||||||
*/} + '').slice(15, -4);
|
*/} + '').slice(15, -4);
|
||||||
doc.head.appendChild(style);
|
doc.head.appendChild(style);
|
||||||
|
cachedIframe = iframe;
|
||||||
return iframe;
|
return iframe;
|
||||||
})();
|
}
|
||||||
var body = iframe.contentDocument.body;
|
|
||||||
|
|
||||||
var iframeText = document.createElement('iframe');
|
|
||||||
document.body.appendChild(iframeText);
|
|
||||||
|
|
||||||
|
if (typeof computeLayout === 'function') {
|
||||||
var realComputeLayout = computeLayout;
|
var realComputeLayout = computeLayout;
|
||||||
|
}
|
||||||
|
|
||||||
function computeCSSLayout(rootNode) {
|
function computeCSSLayout(rootNode) {
|
||||||
function fillNodes(node) {
|
function fillNodes(node) {
|
||||||
@@ -74,7 +77,7 @@ var layoutTestUtils = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function computeDOMLayout(node) {
|
function computeDOMLayout(node) {
|
||||||
var body = iframe.contentDocument.body;
|
var body = getIframe().contentDocument.body;
|
||||||
|
|
||||||
function transfer(div, node, name, ext) {
|
function transfer(div, node, name, ext) {
|
||||||
if (name in node.style) {
|
if (name in node.style) {
|
||||||
@@ -229,7 +232,11 @@ var layoutTestUtils = (function() {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var iframeText;
|
||||||
function measureTextSizes(text, width) {
|
function measureTextSizes(text, width) {
|
||||||
|
iframeText = iframeText || document.createElement('iframe');
|
||||||
|
document.body.appendChild(iframeText);
|
||||||
|
|
||||||
var body = iframeText.contentDocument.body;
|
var body = iframeText.contentDocument.body;
|
||||||
if (width === undefined || width !== width) {
|
if (width === undefined || width !== width) {
|
||||||
width = Infinity;
|
width = Infinity;
|
||||||
@@ -262,13 +269,24 @@ var layoutTestUtils = (function() {
|
|||||||
big: 'loooooooooong with space',
|
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,
|
smallWidth: measureTextSizes(texts.small, 0).width,
|
||||||
smallHeight: measureTextSizes(texts.small, 0).height,
|
smallHeight: measureTextSizes(texts.small, 0).height,
|
||||||
bigWidth: measureTextSizes(texts.big).width,
|
bigWidth: measureTextSizes(texts.big).width,
|
||||||
bigHeight: measureTextSizes(texts.big, 0).height,
|
bigHeight: measureTextSizes(texts.big, 0).height,
|
||||||
bigMinWidth: measureTextSizes(texts.big, 0).width,
|
bigMinWidth: measureTextSizes(texts.big, 0).width,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
texts: texts,
|
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) {
|
static void layoutNodeImpl(css_node_t *node, float parentMaxWidth) {
|
||||||
|
/** START_GENERATED **/
|
||||||
css_flex_direction_t mainAxis = getFlexDirection(node);
|
css_flex_direction_t mainAxis = getFlexDirection(node);
|
||||||
css_flex_direction_t crossAxis = mainAxis == CSS_FLEX_DIRECTION_ROW ?
|
css_flex_direction_t crossAxis = mainAxis == CSS_FLEX_DIRECTION_ROW ?
|
||||||
CSS_FLEX_DIRECTION_COLUMN :
|
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) {
|
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];
|
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 testLayout = layoutTestUtils.testLayout;
|
||||||
var testRandomLayout = layoutTestUtils.testRandomLayout;
|
|
||||||
var computeLayout = layoutTestUtils.computeLayout;
|
|
||||||
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
|
||||||
var reduceTest = layoutTestUtils.reduceTest;
|
|
||||||
var text = layoutTestUtils.text;
|
var text = layoutTestUtils.text;
|
||||||
var texts = layoutTestUtils.texts;
|
var texts = layoutTestUtils.texts;
|
||||||
var textSizes = layoutTestUtils.textSizes;
|
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 currentTest = '';
|
||||||
var allTests = [];
|
var allTests = [];
|
||||||
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
||||||
var computeLayout = layoutTestUtils.computeLayout;
|
|
||||||
var reduceTest = layoutTestUtils.reduceTest;
|
var reduceTest = layoutTestUtils.reduceTest;
|
||||||
var text = layoutTestUtils.text;
|
global.layoutTestUtils = {
|
||||||
var layoutTestUtils = {
|
|
||||||
testLayout: function(node, expectedLayout) {
|
testLayout: function(node, expectedLayout) {
|
||||||
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
||||||
},
|
},
|
||||||
testRandomLayout: function(node, i) {
|
testRandomLayout: function(node, i) {
|
||||||
allTests.push({name: 'Random #' + i, node: node, expectedLayout: computeDOMLayout(node)});
|
allTests.push({name: 'Random #' + i, node: node, expectedLayout: computeDOMLayout(node)});
|
||||||
},
|
},
|
||||||
computeLayout: computeLayout,
|
computeLayout: layoutTestUtils.computeLayout,
|
||||||
computeDOMLayout: computeDOMLayout,
|
|
||||||
reduceTest: reduceTest,
|
reduceTest: reduceTest,
|
||||||
text: text,
|
text: layoutTestUtils.text,
|
||||||
texts: layoutTestUtils.texts,
|
texts: layoutTestUtils.texts,
|
||||||
textSizes: layoutTestUtils.textSizes,
|
textSizes: layoutTestUtils.textSizes
|
||||||
};
|
};
|
||||||
function describe(name, cb) { cb(); }
|
|
||||||
function it(name, cb) { currentTest = name; cb(); }
|
global.describe = function(name, cb) { cb(); };
|
||||||
xit = it;
|
global.it = function(name, cb) { currentTest = name; cb(); };
|
||||||
</script>
|
global.xit = global.it;
|
||||||
<script src="__tests__/Layout-test.js"></script>
|
|
||||||
<script>
|
require('./__tests__/Layout-test.js');
|
||||||
|
|
||||||
|
|
||||||
function printLayout(test) {
|
function printLayout(test) {
|
||||||
var level = 1;
|
var level = 1;
|
||||||
var res = [];
|
var res = [];
|
||||||
|
|
||||||
function add(str) {
|
function add(str) {
|
||||||
res.push(indent(level) + str);
|
if (str.length > 0) {
|
||||||
|
str = indent(level) + str;
|
||||||
|
}
|
||||||
|
res.push(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEmpty(obj) {
|
function isEmpty(obj) {
|
||||||
@@ -237,10 +203,53 @@ function printLayout(test) {
|
|||||||
add('test("' + test.name.replace(/"/g, '\\"') + '", root_node, root_layout);');
|
add('test("' + test.name.replace(/"/g, '\\"') + '", root_node, root_layout);');
|
||||||
level--;
|
level--;
|
||||||
add('}');
|
add('}');
|
||||||
add('');
|
|
||||||
add('tests_finished();');
|
|
||||||
|
|
||||||
return res.join('\n');
|
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