diff --git a/ecl/hql/hqlexpr.cpp b/ecl/hql/hqlexpr.cpp index 82697abb382..772d7eba009 100644 --- a/ecl/hql/hqlexpr.cpp +++ b/ecl/hql/hqlexpr.cpp @@ -11028,7 +11028,9 @@ IHqlExpression *CHqlDelayedCall::clone(HqlExprArray &newkids) IHqlExpression * CHqlDelayedCall::makeDelayedCall(IHqlExpression * _funcdef, HqlExprArray &operands) { - ITypeInfo * returnType = _funcdef->queryType()->queryChildType(); + ITypeInfo * funcType = _funcdef->queryType(); + assertex(funcType->getTypeCode() == type_function); + ITypeInfo * returnType = funcType->queryChildType(); CHqlDelayedCall * ret; switch (returnType->getTypeCode()) { diff --git a/ecl/hql/hqlgram2.cpp b/ecl/hql/hqlgram2.cpp index 999af21edaf..86539adfc30 100644 --- a/ecl/hql/hqlgram2.cpp +++ b/ecl/hql/hqlgram2.cpp @@ -3638,6 +3638,30 @@ IHqlExpression * HqlGram::implementInterfaceFromModule(const attribute & modpos, { HqlExprArray parameters; bool isParametered = extractSymbolParameters(parameters, &baseSym); + if (baseSym.isFunction() != match->isFunction()) + { + if (isParametered) + { + //Convert the value to a function definition - the parameters will be ignored + IHqlExpression * formals = queryFunctionParameters(&baseSym); + IHqlExpression * defaults = queryFunctionDefaults(&baseSym); + OwnedHqlExpr funcdef = createFunctionDefinition(id, LINK(match->queryBody()), LINK(formals), LINK(defaults), NULL); + match.setown(match->cloneAllAnnotations(funcdef)); + } + else + { + //Convert a function into a value - possible if all parameters (including none) have default values + if (!allParametersHaveDefaults(match)) + { + reportError(ERR_EXPECTED_ATTRIBUTE, ipos, "Symbol %s is defined as a value in the base scope, but a function with non-default parameters in the interface", str(id)); + } + else + { + HqlExprArray actuals; + match.setown(createBoundFunction(nullptr, match, actuals, nullptr, false)); + } + } + } checkDerivedCompatible(id, newScopeExpr, match, isParametered, parameters, modpos); newScope->defineSymbol(LINK(match)); diff --git a/ecl/regress/iproject.ecl b/ecl/regress/iproject.ecl new file mode 100644 index 00000000000..3822182065d --- /dev/null +++ b/ecl/regress/iproject.ecl @@ -0,0 +1,50 @@ +/*############################################################################## + + HPCC SYSTEMS software Copyright (C) 2024 HPCC Systems®. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +############################################################################## */ + +myModule := MODULE + + EXPORT value1 := 100; + EXPORT value2 := 200; + EXPORT value3(unsigned x = 10) := 300; + EXPORT value4() := 400; + +END; + +myInterface := INTERFACE + + EXPORT value1 := 0; + EXPORT value2(unsigned unknown) := 0; + EXPORT value3 := 0; + EXPORT value4() := 0; + +END; + + + +display(myInterface x) := FUNCTION + RETURN + ORDERED( + OUTPUT(x.value1); + OUTPUT(x.value2(99999)); + OUTPUT(x.value3); + OUTPUT(x.value4()); + ); +END; + + +mappedModule := PROJECT(myModule, myInterface); +display(mappedModule); \ No newline at end of file diff --git a/ecl/regress/iproject_err.ecl b/ecl/regress/iproject_err.ecl new file mode 100644 index 00000000000..cb4d64b7c74 --- /dev/null +++ b/ecl/regress/iproject_err.ecl @@ -0,0 +1,50 @@ +/*############################################################################## + + HPCC SYSTEMS software Copyright (C) 2024 HPCC Systems®. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +############################################################################## */ + +myModule := MODULE + + EXPORT value1 := 100; + EXPORT value2 := 200; + EXPORT value3(unsigned i) := 300; // invalid - no default value supplied + EXPORT value4() := 400; + +END; + +myInterface := INTERFACE + + EXPORT value1 := 0; + EXPORT value2() := 0; + EXPORT value3 := 0; + EXPORT value4() := 0; + +END; + + + +display(myInterface x) := FUNCTION + RETURN + ORDERED( + OUTPUT(x.value1); + OUTPUT(x.value2()); + OUTPUT(x.value3); + OUTPUT(x.value4()); + ); +END; + + +mappedModule := PROJECT(myModule, myInterface); +display(mappedModule); \ No newline at end of file diff --git a/esp/src/package-lock.json b/esp/src/package-lock.json index 3391efbb526..4fcce04e973 100644 --- a/esp/src/package-lock.json +++ b/esp/src/package-lock.json @@ -18,7 +18,7 @@ "@hpcc-js/chart": "2.84.1", "@hpcc-js/codemirror": "2.63.0", "@hpcc-js/common": "2.72.0", - "@hpcc-js/comms": "2.95.0", + "@hpcc-js/comms": "2.96.1", "@hpcc-js/dataflow": "8.1.7", "@hpcc-js/eclwatch": "2.75.3", "@hpcc-js/graph": "2.86.0", @@ -2082,10 +2082,9 @@ } }, "node_modules/@hpcc-js/comms": { - "version": "2.95.0", - "resolved": "https://registry.npmjs.org/@hpcc-js/comms/-/comms-2.95.0.tgz", - "integrity": "sha512-kzEyDxf1Msus5rhU0yO826JxgIl2kh/bI7yNTxHAlCfLKp4SU//zrj/MK5SuEDs2lUHvmTkfx1jbfGUAK3RGFg==", - "license": "Apache-2.0", + "version": "2.96.1", + "resolved": "https://registry.npmjs.org/@hpcc-js/comms/-/comms-2.96.1.tgz", + "integrity": "sha512-38vIe8foZa5fYtrj65oeWyYWUDZmQTbKetHG5HXWZWMu0Lfmln8uG5/J7mO0ilw3ls2oZj7xOk5T/4xvg7v43w==", "dependencies": { "@hpcc-js/ddl-shim": "^2.21.0", "@hpcc-js/util": "^2.52.0", diff --git a/esp/src/package.json b/esp/src/package.json index de3511485ec..db7708ef45d 100644 --- a/esp/src/package.json +++ b/esp/src/package.json @@ -44,7 +44,7 @@ "@hpcc-js/chart": "2.84.1", "@hpcc-js/codemirror": "2.63.0", "@hpcc-js/common": "2.72.0", - "@hpcc-js/comms": "2.95.0", + "@hpcc-js/comms": "2.96.1", "@hpcc-js/dataflow": "8.1.7", "@hpcc-js/eclwatch": "2.75.3", "@hpcc-js/graph": "2.86.0", diff --git a/esp/src/src-react/components/Helpers.tsx b/esp/src/src-react/components/Helpers.tsx index 458308debd8..73fed185eca 100644 --- a/esp/src/src-react/components/Helpers.tsx +++ b/esp/src/src-react/components/Helpers.tsx @@ -1,8 +1,9 @@ import * as React from "react"; -import { CommandBar, ContextualMenuItemType, ICommandBarItemProps, Link, ScrollablePane, Sticky } from "@fluentui/react"; +import { CommandBar, ContextualMenuItemType, ICommandBarItemProps, Link } from "@fluentui/react"; import * as ESPRequest from "src/ESPRequest"; import nlsHPCC from "src/nlsHPCC"; import { HelperRow, useWorkunitHelpers } from "../hooks/workunit"; +import { HolyGrail } from "../layouts/HolyGrail"; import { FluentGrid, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid"; import { ShortVerticalDivider } from "./Common"; @@ -223,18 +224,18 @@ export const Helpers: React.FunctionComponent = ({ setData(helpers); }, [helpers]); - return - - - - - ; + return } + main={ + + } + />; }; diff --git a/esp/src/src-react/components/InfoGrid.tsx b/esp/src/src-react/components/InfoGrid.tsx index ec028305d8b..5860ef755bc 100644 --- a/esp/src/src-react/components/InfoGrid.tsx +++ b/esp/src/src-react/components/InfoGrid.tsx @@ -236,7 +236,7 @@ export const InfoGrid: React.FunctionComponent = ({ } }, [data.length]); - return
+ return
{({ size }) => = ({ return } main={ -
- -
+ } />; }; diff --git a/esp/src/src-react/components/Logs.tsx b/esp/src/src-react/components/Logs.tsx index d9703c0e74f..86f7297abc1 100644 --- a/esp/src/src-react/components/Logs.tsx +++ b/esp/src/src-react/components/Logs.tsx @@ -182,7 +182,7 @@ export const Logs: React.FunctionComponent = ({ return } main={ - <> +
= ({ refresh={refreshTable} > - +
} footer={ = ({ } }, [selectionHandler, strSelection]); - return ; + return
+ +
; }; interface AddLabelProps { diff --git a/esp/src/src-react/components/Resources.tsx b/esp/src/src-react/components/Resources.tsx index d3cb0a73a53..ccae64dfa5e 100644 --- a/esp/src/src-react/components/Resources.tsx +++ b/esp/src/src-react/components/Resources.tsx @@ -1,9 +1,10 @@ import * as React from "react"; -import { CommandBar, ContextualMenuItemType, ICommandBarItemProps, Link, ScrollablePane, Sticky } from "@fluentui/react"; +import { CommandBar, ContextualMenuItemType, ICommandBarItemProps, Link } from "@fluentui/react"; import nlsHPCC from "src/nlsHPCC"; import { QuerySortItem } from "src/store/Store"; import { useWorkunitResources } from "../hooks/workunit"; import { updateParam } from "../util/history"; +import { HolyGrail } from "../layouts/HolyGrail"; import { FluentGrid, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid"; import { ShortVerticalDivider } from "./Common"; import { IFrame } from "./IFrame"; @@ -108,21 +109,21 @@ export const Resources: React.FunctionComponent = ({ })); }, [resources, wuid]); - return - - - - {preview && webUrl ? -