From 40bc7ac1c6f8ab1cc5a4df914f6cd6dd6e758f96 Mon Sep 17 00:00:00 2001 From: cha0s Date: Thu, 25 Jun 2020 09:52:44 -0500 Subject: [PATCH] flow: expressions++ --- src/client/types/expression.type-renderer.jsx | 36 ++++++++++++++++--- .../types/expressions.type-renderer.jsx | 22 +++++------- src/client/types/literal.type-renderer.jsx | 4 +-- src/client/types/typing.js | 29 +++++++-------- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/client/types/expression.type-renderer.jsx b/src/client/types/expression.type-renderer.jsx index 7ffdcff..4efab41 100644 --- a/src/client/types/expression.type-renderer.jsx +++ b/src/client/types/expression.type-renderer.jsx @@ -1,4 +1,8 @@ -import {makeCompilable, description as typeDescription} from '@avocado/behavior'; +import { + fitsInto, + makeCompilable, + description as typeDescription, +} from '@avocado/behavior'; import {compose} from '@avocado/core'; import contempo from 'contempo'; import React from 'react'; @@ -45,17 +49,39 @@ const Expression = (props) => { onChange({type: 'literal', value: defaultLiteral}, event); return; } - const newSteps = [ + const newOps = [ ...ops.slice(0, i), { ...ops[i], key: event.target.value, }, ]; + const newDescription = descriptionFromOps(context, newOps); + const finalOps = fitsInto(type, newDescription.type) && !fitsInto(newDescription.type, 'void') + ? newOps + : defaultOps(context, type, newOps); + if ('invoke' === finalOps[finalOps.length - 1].type || !isStatement) { + onChange({ + ...value, + ops: finalOps, + assign: undefined, + }, event); + return; + } + const opsDescription = descriptionFromOps(context, finalOps); + const {defaultLiteral} = opsDescription; onChange({ ...value, - ops: defaultOps(context, type, newSteps), - value: undefined, + ops: finalOps, + assign: 'undefined' !== typeof defaultLiteral + ? { + type: 'literal', + value: defaultLiteral, + } + : { + type: 'expression', + ops: defaultOps(context, opsDescription.type), + }, }, event); }} value={op.key} @@ -135,7 +161,7 @@ const Expression = (props) => { assign: makeCompilable(valueValue), }, event) )} - type={type} + type={descriptionFromOps(context, ops).type} value={assign} /> diff --git a/src/client/types/expressions.type-renderer.jsx b/src/client/types/expressions.type-renderer.jsx index df69526..6abec09 100644 --- a/src/client/types/expressions.type-renderer.jsx +++ b/src/client/types/expressions.type-renderer.jsx @@ -28,19 +28,15 @@ const Expressions = ({ { - return ( - onChange({ - ...value, - expressions: [ - ...expressions.slice(0, i), - expressionValue, - ...expressions.slice(i + 1), - ], - }, event) - ); - }} - type="any" + onChange={(expressionValue, event) => onChange({ + ...value, + expressions: [ + ...expressions.slice(0, i), + expressionValue, + ...expressions.slice(i + 1), + ], + }, event)} + type="void|property" value={expression} /> diff --git a/src/client/types/literal.type-renderer.jsx b/src/client/types/literal.type-renderer.jsx index b7cc27c..56cb8d5 100644 --- a/src/client/types/literal.type-renderer.jsx +++ b/src/client/types/literal.type-renderer.jsx @@ -1,4 +1,4 @@ -import {fromLiteral} from '@avocado/behavior'; +import {fromLiteral, description} from '@avocado/behavior'; import {compose} from '@avocado/core'; import contempo from 'contempo'; import React from 'react'; @@ -20,7 +20,7 @@ const Literal = ({ value: {value}, }) => { const typeRenderers = useTypeRenderers(); - const actualType = 'any' === type ? fromLiteral(value) : type; + const actualType = 'any' === type ? fromLiteral(value) : type.split('|').map(description).find((desc) => desc.type !== 'undefined').type; const Component = typeRenderers[actualType]; const [options] = opsOptions(context, [], actualType); options.push(''); diff --git a/src/client/types/typing.js b/src/client/types/typing.js index 30eec3c..08ec923 100644 --- a/src/client/types/typing.js +++ b/src/client/types/typing.js @@ -25,8 +25,8 @@ export function descriptionFromOps(context, ops) { if ('function' === typeof variable && children[key] && children[key].args) { const {type} = children[key]; // eslint-disable-next-line no-loop-func - const args = children[key].args.map(([type, spec]) => [ - type, + const args = children[key].args.map(([childType, spec]) => [ + childType, // eslint-disable-next-line no-nested-ternary spec.options ? { @@ -44,12 +44,15 @@ export function descriptionFromOps(context, ops) { }; } else { - description = typeDescription( - children[key].type, - 'function' !== typeof variable || 'function' === children[key].type - ? variable - : undefined, - ); + description = { + ...typeDescription( + children[key].type, + 'function' !== typeof variable || 'function' === children[key].type + ? variable + : undefined, + ), + ...children[key], + }; } } return description; @@ -99,13 +102,12 @@ const defaultInvocation = (context, ops) => { export const defaultOps = (context, type, originalOps = []) => { const ops = [...originalOps]; let evaluated; - debugger; let {type: opsType} = descriptionFromOps(context, ops); - const typesVisited = {[opsType]: true}; while (!fitsInto(opsType, type) || 0 === ops.length) { evaluated = compile({type: 'expression', ops})(context); if ( - 'invoke' !== ops[ops.length - 1].type + ops.length > 0 + && 'invoke' !== ops[ops.length - 1].type && 'function' === typeof evaluated ) { if ('function' === type) { @@ -119,13 +121,9 @@ export const defaultOps = (context, type, originalOps = []) => { const candidates = typeCandidates(description, type); const key = candidates.find((candidate) => { const {type: candidateType} = children[candidate]; - if (typesVisited[candidateType]) { - return false; - } if (fitsInto(type, candidateType)) { return true; } - typesVisited[candidateType] = true; return true; }); ops.push({type: 'key', key}); @@ -140,6 +138,5 @@ export const defaultOps = (context, type, originalOps = []) => { if ('function' === typeof evaluated) { ops.push(defaultInvocation(context, ops)); } - console.log({dops: ops}) return ops; };