Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

xod-arduino

Package Overview
Dependencies
Maintainers
4
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

xod-arduino - npm Package Compare versions

Comparing version 0.19.0 to 0.19.2

3

dist/directives.js

@@ -93,4 +93,3 @@ 'use strict';

return isDirtienessRelatedTo(identifier, pragma) ? endisToBoolean(acc, nthToken(1, pragma)) : acc;
}, isOutput(identifier) || /* dirtieness enabled on outputs by default */
doesReferTemplateSymbol('isInputDirty', identifier, code)), filterPragmasByFeature('dirtieness'), findXodPragmas)(code);
}, isOutput(identifier) /* dirtieness enabled on outputs by default */ || doesReferTemplateSymbol('isInputDirty', identifier, code)), filterPragmasByFeature('dirtieness'), findXodPragmas)(code);
});

@@ -97,0 +96,0 @@

{
"name": "xod-arduino",
"version": "0.19.0",
"version": "0.19.2",
"description": "XOD project: Arduino transpiler",

@@ -23,4 +23,4 @@ "scripts": {

"sanctuary-def": "^0.14.0",
"xod-func-tools": "^0.19.0",
"xod-project": "^0.19.0"
"xod-func-tools": "^0.19.2",
"xod-project": "^0.19.2"
},

@@ -31,4 +31,4 @@ "devDependencies": {

"dirty-chai": "^1.2.2",
"xod-fs": "^0.19.0"
"xod-fs": "^0.19.2"
}
}

@@ -16,13 +16,16 @@ // @flow

// [\s\S]*? is to reduce regex greedieness
const stripBlockComments: UnaryFn<CppCode, CppCode> =
R.replace(/^(((?!\/\/).)*?)\s*\/\*[\s\S]*?\*\//gm, '$1');
const stripBlockComments: UnaryFn<CppCode, CppCode> = R.replace(
/^(((?!\/\/).)*?)\s*\/\*[\s\S]*?\*\//gm,
'$1'
);
const stripLineComments: UnaryFn<CppCode, CppCode> =
R.replace(/\s*\/\/.*$/gm, '');
const stripLineComments: UnaryFn<CppCode, CppCode> = R.replace(
/\s*\/\/.*$/gm,
''
);
const stripCppComments: UnaryFn<CppCode, CppCode> =
R.compose(
stripLineComments,
stripBlockComments
);
const stripCppComments: UnaryFn<CppCode, CppCode> = R.compose(
stripLineComments,
stripBlockComments
);

@@ -32,41 +35,48 @@ const pragmaHeadRegexp = /#\s*pragma\s+XOD\s+/;

const tokenizePragma: UnaryFn<string, PragmaTokens> =
R.compose(
R.map(R.replace(/^"|"$/g, '')), // strip enclosing quotes
R.match(/[\w._-]+|"[^"]+"/g), // match identifier or string
R.replace(pragmaHeadRegexp, ''), // remove leading #pragma XOD
);
const tokenizePragma: UnaryFn<string, PragmaTokens> = R.compose(
R.map(R.replace(/^"|"$/g, '')), // strip enclosing quotes
R.match(/[\w._-]+|"[^"]+"/g), // match identifier or string
R.replace(pragmaHeadRegexp, '') // remove leading #pragma XOD
);
const findXodPragmas: UnaryFn<CppCode, Pragmas> =
R.compose(
R.map(tokenizePragma),
R.match(pragmaLineRegexp),
stripCppComments
);
const findXodPragmas: UnaryFn<CppCode, Pragmas> = R.compose(
R.map(tokenizePragma),
R.match(pragmaLineRegexp),
stripCppComments
);
const doesReferSymbol: CurriedFunction2<string, CppCode, boolean> =
R.curry((symbol, code: CppCode) => R.compose(
R.test(new RegExp(`\\b${symbol}\\b`)),
stripCppComments
)(code));
const doesReferSymbol: CurriedFunction2<string, CppCode, boolean> = R.curry(
(symbol, code: CppCode) =>
R.compose(R.test(new RegExp(`\\b${symbol}\\b`)), stripCppComments)(code)
);
const doesReferTemplateSymbol: CurriedFunction3<string, string, CppCode, boolean> =
R.curry((symbol, templateArg, code: CppCode) => R.compose(
const doesReferTemplateSymbol: CurriedFunction3<
string,
string,
CppCode,
boolean
> = R.curry((symbol, templateArg, code: CppCode) =>
R.compose(
R.test(new RegExp(`\\b${symbol}\\s*\\<\\s*${templateArg}\\s*\\>`)),
stripCppComments
)(code));
)(code)
);
const filterPragmasByFeature: CurriedFunction2<string, Pragmas, Pragmas> =
R.curry((feat, pragmas: Pragmas) =>
pragmas.filter(R.compose(
R.equals(feat),
R.head
))
);
const filterPragmasByFeature: CurriedFunction2<
string,
Pragmas,
Pragmas
> = R.curry((feat, pragmas: Pragmas) =>
pragmas.filter(R.compose(R.equals(feat), R.head))
);
// Returns whether a particular #pragma feature enabled, disabled, or set to auto.
// Default is auto
const pragmaEndis: CurriedFunction2<string, CppCode, 'enable' | 'disable' | 'auto'> =
R.curry((feature: string, code: CppCode) => R.compose(
state => ((state === 'enable' || state === 'disable') ? state : 'auto'),
const pragmaEndis: CurriedFunction2<
string,
CppCode,
'enable' | 'disable' | 'auto'
> = R.curry((feature: string, code: CppCode) =>
R.compose(
state => (state === 'enable' || state === 'disable' ? state : 'auto'),
R.nth(1),

@@ -76,4 +86,5 @@ R.defaultTo([]),

filterPragmasByFeature(feature),
findXodPragmas,
)(code));
findXodPragmas
)(code)
);

@@ -83,25 +94,31 @@ const pragmaTimeouts = pragmaEndis('timeouts');

const nthToken: CurriedFunction2<number, PragmaTokens, string> =
R.curry((n, pragma: PragmaTokens) => R.nth(n, pragma) || '');
const nthToken: CurriedFunction2<number, PragmaTokens, string> = R.curry(
(n, pragma: PragmaTokens) => R.nth(n, pragma) || ''
);
const endisToBoolean: CurriedFunction2<boolean, string, boolean> =
R.curry((defaultR, endis: string) => {
const endisToBoolean: CurriedFunction2<boolean, string, boolean> = R.curry(
(defaultR, endis: string) => {
switch (endis) {
case 'enable': return true;
case 'disable': return false;
default: return defaultR;
case 'enable':
return true;
case 'disable':
return false;
default:
return defaultR;
}
});
}
);
const isDirtienessRelatedTo: CurriedFunction2<string, PragmaTokens, boolean> =
R.curry((identifier, pragma: PragmaTokens) => R.compose(
XF.isAmong([identifier, '']),
nthToken(2),
)(pragma));
const isDirtienessRelatedTo: CurriedFunction2<
string,
PragmaTokens,
boolean
> = R.curry((identifier, pragma: PragmaTokens) =>
R.compose(XF.isAmong([identifier, '']), nthToken(2))(pragma)
);
const isOutput: UnaryFn<string, boolean> =
R.test(/^output_/);
const isOutput: UnaryFn<string, boolean> = R.test(/^output_/);
export const areTimeoutsEnabled: UnaryFn<CppCode, boolean> =
code => R.compose(
export const areTimeoutsEnabled: UnaryFn<CppCode, boolean> = code =>
R.compose(
endisToBoolean(doesReferSymbol('setTimeout', code)),

@@ -111,21 +128,25 @@ pragmaTimeouts

export const isNodeIdEnabled: UnaryFn<CppCode, boolean> =
code => R.compose(
endisToBoolean(doesReferSymbol('getNodeId', code)),
pragmaNodeId
)(code);
export const isNodeIdEnabled: UnaryFn<CppCode, boolean> = code =>
R.compose(endisToBoolean(doesReferSymbol('getNodeId', code)), pragmaNodeId)(
code
);
export const isDirtienessEnabled: CurriedFunction2<CppCode, string, boolean> =
R.curry((code, identifier: string) => R.compose(
export const isDirtienessEnabled: CurriedFunction2<
CppCode,
string,
boolean
> = R.curry((code, identifier: string) =>
R.compose(
R.reduce(
(acc, pragma) =>
(isDirtienessRelatedTo(identifier, pragma)
isDirtienessRelatedTo(identifier, pragma)
? endisToBoolean(acc, nthToken(1, pragma))
: acc),
isOutput(identifier) || /* dirtieness enabled on outputs by default */
: acc,
isOutput(identifier) /* dirtieness enabled on outputs by default */ ||
doesReferTemplateSymbol('isInputDirty', identifier, code)
),
filterPragmasByFeature('dirtieness'),
findXodPragmas,
)(code));
findXodPragmas
)(code)
);

@@ -132,0 +153,0 @@ export const forUnitTests = {

@@ -30,28 +30,20 @@ import * as R from 'ramda';

const getPatchPins = direction => R.compose(
indexByPinKey,
R.path(['patch', direction])
const getPatchPins = direction =>
R.compose(indexByPinKey, R.path(['patch', direction]));
const omitNullValues = R.map(
R.when(R.propSatisfies(R.isNil, 'value'), R.omit(['value']))
);
const omitNullValues = R.map(R.when(
R.propSatisfies(R.isNil, 'value'),
R.omit(['value'])
));
const getNodePins = direction =>
R.compose(indexByPinKey, omitNullValues, R.prop(direction));
const getNodePins = direction => R.compose(
indexByPinKey,
omitNullValues,
R.prop(direction)
);
const mergeAndListPins = (direction, node) => R.compose(
R.values,
R.converge(
R.mergeWith(R.merge),
[
const mergeAndListPins = (direction, node) =>
R.compose(
R.values,
R.converge(R.mergeWith(R.merge), [
getPatchPins(direction),
getNodePins(direction),
]
)
)(node);
])
)(node);

@@ -72,7 +64,3 @@ // Converts DataType value to a corresponding C++ storage type

'cppStringLiteral :: String -> String',
R.ifElse(
R.isEmpty,
R.always('XString()'),
str => `XStringCString("${str}")`
)
R.ifElse(R.isEmpty, R.always('XString()'), str => `XStringCString("${str}")`)
);

@@ -93,6 +81,6 @@

// Generate patch-level namespace name
Handlebars.registerHelper('ns', R.compose(
R.join('__'),
R.props(['owner', 'libName', 'patchName'])
));
Handlebars.registerHelper(
'ns',
R.compose(R.join('__'), R.props(['owner', 'libName', 'patchName']))
);

@@ -103,13 +91,15 @@ // Debug helper

// Returns declaration type specifier for an initial value of an output
Handlebars.registerHelper('decltype', (type, value) => (
(type === PIN_TYPE.STRING && value !== '')
? 'static XStringCString'
: `constexpr ${cppType(type)}`
));
Handlebars.registerHelper(
'decltype',
(type, value) =>
type === PIN_TYPE.STRING && value !== ''
? 'static XStringCString'
: `constexpr ${cppType(type)}`
);
// Check that variable is not undefined
Handlebars.registerHelper('exists', function existsHelper(variable, options) {
return (typeof variable !== 'undefined') ?
options.fn(this) :
options.inverse(this);
return typeof variable !== 'undefined'
? options.fn(this)
: options.inverse(this);
});

@@ -145,15 +135,25 @@

Handlebars.registerHelper(name, (list, block) =>
R.compose(
R.join(''),
R.map(node => block.fn(node)),
R.filter(predicate)
)(list)
R.compose(R.join(''), R.map(node => block.fn(node)), R.filter(predicate))(
list
)
);
}
registerHandlebarsFilterLoopHelper('eachDeferNode', R.path(['patch', 'isDefer']));
registerHandlebarsFilterLoopHelper('eachNonConstantNode', R.pathEq(['patch', 'isConstant'], false));
registerHandlebarsFilterLoopHelper('eachNodeUsingTimeouts', R.path(['patch', 'usesTimeouts']));
registerHandlebarsFilterLoopHelper(
'eachDeferNode',
R.path(['patch', 'isDefer'])
);
registerHandlebarsFilterLoopHelper(
'eachNonConstantNode',
R.pathEq(['patch', 'isConstant'], false)
);
registerHandlebarsFilterLoopHelper(
'eachNodeUsingTimeouts',
R.path(['patch', 'usesTimeouts'])
);
registerHandlebarsFilterLoopHelper('eachLinkedInput', R.has('fromNodeId'));
registerHandlebarsFilterLoopHelper('eachNonlinkedInput', R.complement(R.has('fromNodeId')));
registerHandlebarsFilterLoopHelper(
'eachNonlinkedInput',
R.complement(R.has('fromNodeId'))
);
registerHandlebarsFilterLoopHelper('eachDirtyablePin', R.prop('isDirtyable'));

@@ -192,16 +192,13 @@

);
export const renderImpl = def(
'renderImpl :: TPatch -> String',
(data) => {
const ctx = R.applySpec({
owner: R.prop('owner'),
libName: R.prop('libName'),
patchName: R.prop('patchName'),
GENERATED_CODE: renderPatchContext,
})(data);
export const renderImpl = def('renderImpl :: TPatch -> String', data => {
const ctx = R.applySpec({
owner: R.prop('owner'),
libName: R.prop('libName'),
patchName: R.prop('patchName'),
GENERATED_CODE: renderPatchContext,
})(data);
const patchImpl = R.prop('impl', data);
return Handlebars.compile(patchImpl, renderingOptions)(ctx);
}
);
const patchImpl = R.prop('impl', data);
return Handlebars.compile(patchImpl, renderingOptions)(ctx);
});
export const renderImplList = def(

@@ -212,15 +209,12 @@ 'renderImplList :: [TPatch] -> String',

templates.implList,
R.map(patch => R.assoc('implementation', renderImpl(patch), patch)),
R.map(patch => R.assoc('implementation', renderImpl(patch), patch))
)
);
export const renderProgram = def(
'renderProgram :: [TNode] -> String',
nodes => trimTrailingWhitespace(
templates.program({ nodes })
)
export const renderProgram = def('renderProgram :: [TNode] -> String', nodes =>
trimTrailingWhitespace(templates.program({ nodes }))
);
export const renderProject = def(
'renderProject :: TProject -> String',
(originalProject) => {
originalProject => {
// HACK: We have to clone TProject to prevent mutating

@@ -227,0 +221,0 @@ // of original TProject by Handlebars templates.

@@ -52,9 +52,10 @@ import * as R from 'ramda';

'findPatchByPath :: PatchPath -> [TPatch] -> TPatch',
(path, patches) => R.compose(
R.find(R.__, patches),
R.allPass,
R.map(R.apply(R.propEq)),
R.toPairs,
createPatchNames
)(path)
(path, patches) =>
R.compose(
R.find(R.__, patches),
R.allPass,
R.map(R.apply(R.propEq)),
R.toPairs,
createPatchNames
)(path)
);

@@ -64,9 +65,3 @@

'getLinksInputNodeIds :: [Link] -> [TNodeId]',
R.compose(
R.uniq,
R.map(R.compose(
toInt,
Project.getLinkInputNodeId
))
)
R.compose(R.uniq, R.map(R.compose(toInt, Project.getLinkInputNodeId)))
);

@@ -76,8 +71,9 @@

'getPatchByNodeId :: Project -> PatchPath -> [TPatch] -> NodeId -> TPatch',
(project, entryPath, patches, nodeId) => R.compose(
findPatchByPath(R.__, patches),
Project.getNodeType,
Project.getNodeByIdUnsafe(nodeId),
Project.getPatchByPathUnsafe
)(entryPath, project)
(project, entryPath, patches, nodeId) =>
R.compose(
findPatchByPath(R.__, patches),
Project.getNodeType,
Project.getNodeByIdUnsafe(nodeId),
Project.getPatchByPathUnsafe
)(entryPath, project)
);

@@ -87,13 +83,23 @@

'toposortProject :: PatchPath -> Project -> Either Error Object',
(path, project) => R.compose(
R.chain(nodeIdsMap => R.compose(
R.map(R.applySpec({
project: R.identity,
nodeIdsMap: R.always(nodeIdsMap),
})),
() => Project.updatePatch(path, Project.applyNodeIdMap(R.__, nodeIdsMap), project)
)(nodeIdsMap)),
Project.getTopologyMap,
Project.getPatchByPathUnsafe
)(path, project)
(path, project) =>
R.compose(
R.chain(nodeIdsMap =>
R.compose(
R.map(
R.applySpec({
project: R.identity,
nodeIdsMap: R.always(nodeIdsMap),
})
),
() =>
Project.updatePatch(
path,
Project.applyNodeIdMap(R.__, nodeIdsMap),
project
)
)(nodeIdsMap)
),
Project.getTopologyMap,
Project.getPatchByPathUnsafe
)(path, project)
);

@@ -109,65 +115,67 @@

'createTPatches :: PatchPath -> Project -> [TPatch]',
(entryPath, project) => R.compose(
R.values,
R.mapObjIndexed((patch, path) => {
const names = createPatchNames(path);
const impl = explodeMaybe(
`Implementation for ${path} not found`,
Project.getImpl(patch)
);
(entryPath, project) =>
R.compose(
R.values,
R.mapObjIndexed((patch, path) => {
const names = createPatchNames(path);
const impl = explodeMaybe(
`Implementation for ${path} not found`,
Project.getImpl(patch)
);
const isDirtyable = pin =>
Project.getPinType(pin) === Project.PIN_TYPE.PULSE
|| isDirtienessEnabled(impl, `${pin.direction}_${pin.label}`);
const isDirtyable = pin =>
Project.getPinType(pin) === Project.PIN_TYPE.PULSE ||
isDirtienessEnabled(impl, `${pin.direction}_${pin.label}`);
const outputs = R.compose(
R.map(R.applySpec({
type: Project.getPinType,
pinKey: Project.getPinLabel,
value: R.compose(
Project.defaultValueOfType,
Project.getPinType
const outputs = R.compose(
R.map(
R.applySpec({
type: Project.getPinType,
pinKey: Project.getPinLabel,
value: R.compose(Project.defaultValueOfType, Project.getPinType),
isDirtyable,
isDirtyOnBoot: R.compose(
R.not,
R.equals(Project.PIN_TYPE.PULSE),
Project.getPinType
),
})
),
isDirtyable,
isDirtyOnBoot: R.compose(
R.not,
R.equals(Project.PIN_TYPE.PULSE),
Project.getPinType
Project.normalizePinLabels,
Project.listOutputPins
)(patch);
const inputs = R.compose(
R.map(
R.applySpec({
type: Project.getPinType,
pinKey: Project.getPinLabel,
isDirtyable,
})
),
})),
Project.normalizePinLabels,
Project.listOutputPins
)(patch);
Project.normalizePinLabels,
Project.listInputPins
)(patch);
const inputs = R.compose(
R.map(R.applySpec({
type: Project.getPinType,
pinKey: Project.getPinLabel,
isDirtyable,
})),
Project.normalizePinLabels,
Project.listInputPins
)(patch);
const isThisIsThat = {
isDefer: Project.isDeferNodeType(path),
isConstant: Project.isConstantNodeType(path),
usesTimeouts: areTimeoutsEnabled(impl),
usesNodeId: isNodeIdEnabled(impl),
};
const isThisIsThat = {
isDefer: Project.isDeferNodeType(path),
isConstant: Project.isConstantNodeType(path),
usesTimeouts: areTimeoutsEnabled(impl),
usesNodeId: isNodeIdEnabled(impl),
};
return R.mergeAll([
names,
isThisIsThat,
{
outputs,
inputs,
impl,
},
]);
}),
R.omit([entryPath]),
R.indexBy(Project.getPatchPath),
Project.listPatchesWithoutBuiltIns
)(project)
return R.mergeAll([
names,
isThisIsThat,
{
outputs,
inputs,
impl,
},
]);
}),
R.omit([entryPath]),
R.indexBy(Project.getPatchPath),
Project.listPatchesWithoutBuiltIns
)(project)
);

@@ -177,6 +185,3 @@

'getPinLabelsMap :: [Pin] -> Map PinKey PinLabel',
R.compose(
R.map(Project.getPinLabel),
R.indexBy(Project.getPinKey)
)
R.compose(R.map(Project.getPinLabel), R.indexBy(Project.getPinKey))
);

@@ -186,6 +191,9 @@

'getNodePinsUnsafe :: Node -> Project -> [Pin]',
(node, project) => R.compose(
explodeMaybe(`Can’t get node pins of node ${node}. Referred type missing?`),
Project.getNodePins
)(node, project)
(node, project) =>
R.compose(
explodeMaybe(
`Can’t get node pins of node ${node}. Referred type missing?`
),
Project.getNodePins
)(node, project)
);

@@ -195,7 +203,3 @@

'getNodePinLabels :: Node -> Project -> Map PinKey PinLabel',
R.compose(
getPinLabelsMap,
Project.normalizePinLabels,
getNodePinsUnsafe
)
R.compose(getPinLabelsMap, Project.normalizePinLabels, getNodePinsUnsafe)
);

@@ -210,11 +214,9 @@

'getDefaultPinValue :: PinKey -> Node -> Project -> DataValue',
(pinKey, node, project) => R.compose(
explodeMaybe(`Can’t find pin with key ${pinKey} for node ${node}"`),
R.map(R.compose(
Project.defaultValueOfType,
Project.getPinType
)),
R.chain(Project.getPinByKey(pinKey)),
Project.getPatchByNode(R.__, project)
)(node)
(pinKey, node, project) =>
R.compose(
explodeMaybe(`Can’t find pin with key ${pinKey} for node ${node}"`),
R.map(R.compose(Project.defaultValueOfType, Project.getPinType)),
R.chain(Project.getPinByKey(pinKey)),
Project.getPatchByNode(R.__, project)
)(node)
);

@@ -233,4 +235,5 @@

pinKey: nodePins[pinKey],
value: Project.getBoundValue(pinKey, node)
.getOrElse(getDefaultPinValue(pinKey, node, project)),
value: Project.getBoundValue(pinKey, node).getOrElse(
getDefaultPinValue(pinKey, node, project)
),
})),

@@ -250,9 +253,8 @@ R.groupBy(Project.getLinkOutputPinKey),

return R.compose(
explodeMaybe(`Can’t find pin with key ${pinKey} for link ${link} on patch ${patch}`),
R.map(R.compose(
Project.getPinLabel,
R.head,
Project.normalizePinLabels,
R.of
)),
explodeMaybe(
`Can’t find pin with key ${pinKey} for link ${link} on patch ${patch}`
),
R.map(
R.compose(Project.getPinLabel, R.head, Project.normalizePinLabels, R.of)
),
R.chain(Project.getPinByKey(pinKey)),

@@ -293,3 +295,6 @@ R.chain(Project.getPatchByNode(R.__, project)),

fromPinKey: getUpstreamPinLabel,
fromOutput: R.converge(getTPatchOutputByLabel, [getUpstreamPinLabel, getUpstreamNodePatch]),
fromOutput: R.converge(getTPatchOutputByLabel, [
getUpstreamPinLabel,
getUpstreamNodePatch,
]),
});

@@ -307,14 +312,20 @@

'createTNodes :: PatchPath -> [TPatch] -> Map NodeId String -> Project -> [TNode]',
(entryPath, patches, nodeIdsMap, project) => R.compose(
R.sortBy(R.prop('id')),
R.map(R.applySpec({
id: R.compose(toInt, Project.getNodeId),
originalId: R.compose(reverseLookup(R.__, nodeIdsMap), Project.getNodeId),
patch: R.compose(findPatchByPath(R.__, patches), Project.getNodeType),
outputs: getTNodeOutputs(project, entryPath),
inputs: getTNodeInputs(project, entryPath, patches),
})),
Project.listNodes,
Project.getPatchByPathUnsafe
)(entryPath, project)
(entryPath, patches, nodeIdsMap, project) =>
R.compose(
R.sortBy(R.prop('id')),
R.map(
R.applySpec({
id: R.compose(toInt, Project.getNodeId),
originalId: R.compose(
reverseLookup(R.__, nodeIdsMap),
Project.getNodeId
),
patch: R.compose(findPatchByPath(R.__, patches), Project.getNodeType),
outputs: getTNodeOutputs(project, entryPath),
inputs: getTNodeInputs(project, entryPath, patches),
})
),
Project.listNodes,
Project.getPatchByPathUnsafe
)(entryPath, project)
);

@@ -329,41 +340,48 @@

'transformProjectWithImpls :: Project -> PatchPath -> TranspilationOptions -> Either Error TProject',
(project, path, opts) => R.compose(
Project.wrapDeadRefErrorMessage(path),
R.chain((tProject) => {
const nodeWithTooManyOutputs = R.find(
R.pipe(R.prop('outputs'), R.length, R.lt(7)),
tProject.patches
);
(project, path, opts) =>
R.compose(
Project.wrapDeadRefErrorMessage(path),
R.chain(tProject => {
const nodeWithTooManyOutputs = R.find(
R.pipe(R.prop('outputs'), R.length, R.lt(7)),
tProject.patches
);
if (nodeWithTooManyOutputs) {
const { owner, libName, patchName } = nodeWithTooManyOutputs;
return Either.Left(new Error(`Native node ${owner}/${libName}/${patchName} has more than 7 outputs`));
}
if (nodeWithTooManyOutputs) {
const { owner, libName, patchName } = nodeWithTooManyOutputs;
return Either.Left(
new Error(
`Native node ${owner}/${libName}/${patchName} has more than 7 outputs`
)
);
}
return Either.of(tProject);
}),
R.map(({ project: proj, nodeIdsMap }) => {
const patches = createTPatches(path, proj);
return Either.of(tProject);
}),
R.map(({ project: proj, nodeIdsMap }) => {
const patches = createTPatches(path, proj);
return R.merge(
{
config: { XOD_DEBUG: opts.debug },
},
R.applySpec({
patches: R.always(patches),
nodes: createTNodes(path, patches, nodeIdsMap),
})(proj)
);
}),
R.chain(R.compose(
toposortProject(path),
Project.extractBoundInputsToConstNodes(R.__, path, project),
)),
R.chain(Project.flatten(R.__, path)),
R.unless(
() => opts.debug,
R.chain(Project.updatePatch(path, Project.removeDebugNodes))
),
Project.validateProject
)(project)
return R.merge(
{
config: { XOD_DEBUG: opts.debug },
},
R.applySpec({
patches: R.always(patches),
nodes: createTNodes(path, patches, nodeIdsMap),
})(proj)
);
}),
R.chain(
R.compose(
toposortProject(path),
Project.extractBoundInputsToConstNodes(R.__, path, project)
)
),
R.chain(Project.flatten(R.__, path)),
R.unless(
() => opts.debug,
R.chain(Project.updatePatch(path, Project.removeDebugNodes))
),
Project.validateProject
)(project)
);

@@ -370,0 +388,0 @@

@@ -1,2 +0,1 @@

import { assert } from 'chai';

@@ -127,6 +126,3 @@ import {

assertPragmasFound(code, [
['foo', 'bar', 'baz'],
['digun', 'liteta'],
]);
assertPragmasFound(code, [['foo', 'bar', 'baz'], ['digun', 'liteta']]);
});

@@ -141,20 +137,15 @@

assertPragmasFound(code, [
['foo', 'bar', 'baz'],
['digun', 'liteta'],
]);
assertPragmasFound(code, [['foo', 'bar', 'baz'], ['digun', 'liteta']]);
});
it('considers enquoted arguments atomic', () => {
assertPragmasFound(
'#pragma XOD foo "bar baz" qux',
[['foo', 'bar baz', 'qux']]
);
assertPragmasFound('#pragma XOD foo "bar baz" qux', [
['foo', 'bar baz', 'qux'],
]);
});
it('considers - _ . a non-breaking character', () => {
assertPragmasFound(
'#pragma XOD foo.bar baz-qux_kut',
[['foo.bar', 'baz-qux_kut']]
);
assertPragmasFound('#pragma XOD foo.bar baz-qux_kut', [
['foo.bar', 'baz-qux_kut'],
]);
});

@@ -161,0 +152,0 @@ });

@@ -8,3 +8,8 @@ import fs from 'fs';

import { loadProject } from 'xod-fs';
import { transpile, transformProject, getNodeIdsMap, forUnitTests } from '../src/transpiler';
import {
transpile,
transformProject,
getNodeIdsMap,
forUnitTests,
} from '../src/transpiler';

@@ -14,7 +19,8 @@ const { createPatchNames } = forUnitTests;

// Returns patch relative to repo’s `workspace` subdir
const wsPath = (...subpath) => path.resolve(__dirname, '../../../workspace', ...subpath);
const wsPath = (...subpath) =>
path.resolve(__dirname, '../../../workspace', ...subpath);
describe('xod-arduino transpiler', () => {
describe('correctly transpiles workspace fixture', () => {
const testFixture = (projName) => {
const testFixture = projName => {
const expectedCpp = fs.readFileSync(

@@ -30,3 +36,7 @@ wsPath(projName, '__fixtures__/arduino.cpp'),

.then(result =>
assert.strictEqual(result, expectedCpp, 'expected and actual C++ don’t match')
assert.strictEqual(
result,
expectedCpp,
'expected and actual C++ don’t match'
)
);

@@ -38,19 +48,19 @@ };

specify('lcd-time', () => testFixture('lcd-time'));
specify('count-with-feedback-loops', () => testFixture('count-with-feedback-loops'));
specify('count-with-feedback-loops', () =>
testFixture('count-with-feedback-loops')
);
});
it('returns error for non-existing-patch entry point',
() =>
loadProject([wsPath()], wsPath('blink'))
.then(transformProject(R.__, '@/non-existing-patch'))
.then(result => assert.equal(result.isLeft, true))
);
it('returns error for non-existing-patch entry point', () =>
loadProject([wsPath()], wsPath('blink'))
.then(transformProject(R.__, '@/non-existing-patch'))
.then(result => assert.equal(result.isLeft, true)));
it('returns error if some native node has more than 7 outputs',
() =>
loadProject([wsPath()], wsPath('faulty'))
.then(transformProject(R.__, '@/too-many-outputs-main'))
.then(R.map(transpile))
.then(foldEither(
(err) => {
it('returns error if some native node has more than 7 outputs', () =>
loadProject([wsPath()], wsPath('faulty'))
.then(transformProject(R.__, '@/too-many-outputs-main'))
.then(R.map(transpile))
.then(
foldEither(
err => {
assert.include(err.message, 'too_many_outputs');

@@ -60,17 +70,14 @@ assert.include(err.message, 'has more than 7 outputs');

() => assert(false, 'expecting Either.Left')
))
);
)
));
it('sorts nodes topologically', () =>
loadProject([wsPath()], wsPath('blink'))
.then(R.pipe(
transformProject(R.__, '@/main'),
explodeEither,
R.prop('nodes')
))
.then((nodes) => {
const patchNames = R.compose(
R.pluck('patchName'),
R.pluck('patch')
)(nodes);
.then(
R.pipe(transformProject(R.__, '@/main'), explodeEither, R.prop('nodes'))
)
.then(nodes => {
const patchNames = R.compose(R.pluck('patchName'), R.pluck('patch'))(
nodes
);

@@ -87,6 +94,8 @@ assert.deepEqual(patchNames, [

const ids = R.pluck('id', nodes);
assert.deepEqual(ids, [0, 1, 2, 3, 4, 5],
'Node IDs were not arranged in topological order');
})
);
assert.deepEqual(
ids,
[0, 1, 2, 3, 4, 5],
'Node IDs were not arranged in topological order'
);
}));
});

@@ -106,6 +115,9 @@

.then(explode)
.then(result => R.mapObjIndexed(
(nodeId, origNodeId) => assert.propertyVal(result, origNodeId, nodeId),
expected
));
.then(result =>
R.mapObjIndexed(
(nodeId, origNodeId) =>
assert.propertyVal(result, origNodeId, nodeId),
expected
)
);
});

@@ -112,0 +124,0 @@ });

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc