Skip to content

Commit

Permalink
- add support for multi-dimensional arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
snosenzo committed Aug 16, 2023
1 parent cbbbdc3 commit c6b439d
Show file tree
Hide file tree
Showing 10 changed files with 320 additions and 82 deletions.
84 changes: 65 additions & 19 deletions packages/omgidl-parser/src/IDLNodeProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ConstantNode,
AnnotatedMessageDefinition,
AnnotatedMessageDefinitionField,
IDLMessageDefinition,
} from "./types";

const numericTypeMap: Record<string, string> = {
Expand Down Expand Up @@ -42,7 +43,7 @@ const SIMPLE_TYPES = new Set([
]);

const POSSIBLE_UNRESOLVED_MEMBERS = [
"arrayLength",
"arrayLengths",
"upperBound",
"arrayUpperBound",
"value",
Expand Down Expand Up @@ -119,7 +120,7 @@ export class IDLNodeProcessor {
}
}

resolveConstants(): void {
resolveConstantUsage(): void {
for (const [scopedIdentifier, node] of this.map.entries()) {
if (
node.declarator !== "struct-member" &&
Expand All @@ -131,20 +132,44 @@ export class IDLNodeProcessor {

// need to iterate through keys because this can occur on arrayLength, upperBound, arrayUpperBound, value, defaultValue
for (const key of POSSIBLE_UNRESOLVED_MEMBERS) {
const value = node[key];
if (typeof value !== "object") {
const keyValue = node[key];
let finalKeyValue = undefined;
if (Array.isArray(keyValue)) {
const arrayLengths = keyValue;

let arrayLengthsResolved = false;
const finalArrayLengths = arrayLengths.map((arrayLength) => {
if (typeof arrayLength === "number") {
return arrayLength;
}
arrayLengthsResolved = true;
const constantNode = this.resolveConstantReference({
constantName: arrayLength.name,
nodeScopedIdentifier: scopedIdentifier,
});
return constantNode.value;
});
if (arrayLengthsResolved) {
finalKeyValue = finalArrayLengths;
}
} else if (typeof keyValue === "object") {
const constantNode = this.resolveConstantReference({
constantName: keyValue.name,
nodeScopedIdentifier: scopedIdentifier,
});
finalKeyValue = constantNode.value;
}

if (finalKeyValue == undefined) {
continue;
}
const constantNode = this.resolveConstantReference({
constantName: value.name,
nodeScopedIdentifier: scopedIdentifier,
});

// need to make sure we are updating the most up to date node
// guaranteed to exist since it's the one we are iterating over
const possiblyUpdatedNode = this.map.get(scopedIdentifier)!;
this.map.set(scopedIdentifier, {
...possiblyUpdatedNode,
[key]: constantNode.value,
[key]: finalKeyValue,
});
}
}
Expand Down Expand Up @@ -172,7 +197,7 @@ export class IDLNodeProcessor {
}

/** Resolve typedefs that reference structs as complex*/
resolveTypeDefs(): void {
resolveTypeDefComplexity(): void {
// assume that typedefs can't reference other typedefs
for (const [scopedIdentifier, node] of this.map.entries()) {
if (node.declarator !== "typedef") {
Expand Down Expand Up @@ -204,8 +229,8 @@ export class IDLNodeProcessor {
}
}

/** Resolve struct-members that refer to complex types as complex */
resolveStructMemberComplexity(): void {
/** Resolve struct-members definitions that use typedefs or reference other complex types */
resolveStructMember(): void {
// resolve non-primitive struct member types
for (const [scopedIdentifier, node] of this.map.entries()) {
if (node.declarator !== "struct-member") {
Expand All @@ -232,13 +257,23 @@ export class IDLNodeProcessor {
declarator: _d,
name: _name,
annotations: typedefAnnotations,
arrayLengths: typedefArrayLengths,
...partialDef
} = typeNode;

const newNode = {
...node,
...partialDef,
};
if (typedefArrayLengths) {
const arrayLengths = [];
if (node.arrayLengths) {
// important that node arrayLengths are pushed first to maintain dimensional order: outermost first
arrayLengths.push(...node.arrayLengths);
}
arrayLengths.push(...typedefArrayLengths);
newNode.arrayLengths = arrayLengths;
}

const annotations = { ...typedefAnnotations, ...node.annotations };
if (Object.keys(annotations).length > 0) {
Expand Down Expand Up @@ -324,7 +359,7 @@ export class IDLNodeProcessor {
}
const {
declarator: _d,
arrayLength,
arrayLengths,
arrayUpperBound,
upperBound,
value,
Expand All @@ -334,21 +369,24 @@ export class IDLNodeProcessor {

if (
typeof arrayUpperBound === "object" ||
typeof arrayLength === "object" ||
typeof upperBound === "object" ||
typeof value === "object"
) {
throw Error(`Constants not resolved for ${nodeScopedIdentifier}`);
}

if (arrayLengths?.find((len) => typeof len === "object") != undefined) {
throw Error(`Constants not resolved for ${nodeScopedIdentifier}`);
}

const fullMessageDef = {
...partialMessageDef,
type: normalizeType(partialMessageDef.type),
} as AnnotatedMessageDefinitionField;

// avoid writing undefined to object fields
if (arrayLength != undefined) {
fullMessageDef.arrayLength = arrayLength;
if (arrayLengths != undefined) {
fullMessageDef.arrayLengths = arrayLengths as number[];
}
if (arrayUpperBound != undefined) {
fullMessageDef.arrayUpperBound = arrayUpperBound;
Expand Down Expand Up @@ -389,12 +427,20 @@ export class IDLNodeProcessor {
}

// Removes `annotation` field from the Definition and DefinitionField objects
function toMessageDefinition(idlMsgDef: AnnotatedMessageDefinition): MessageDefinition {
function toMessageDefinition(idlMsgDef: IDLMessageDefinition): MessageDefinition {
const { definitions, annotations: _a, ...partialDef } = idlMsgDef;
const fieldDefinitions = definitions.map((def) => {
const { annotations: _an, ...partialFieldDef } = def;
return partialFieldDef;
const { annotations: _an, arrayLengths, ...partialFieldDef } = def;
const fieldDef = { ...partialFieldDef };
if (arrayLengths != undefined && arrayLengths.length > 0) {
if (arrayLengths.length > 1) {
throw new Error(`Multi-dimensional arrays are not supported in MessageDefinition type`);
}
(fieldDef as MessageDefinitionField).arrayLength = arrayLengths[0]!;
}
return fieldDef;
});

return { ...partialDef, definitions: fieldDefinitions };
}

Expand Down
17 changes: 14 additions & 3 deletions packages/omgidl-parser/src/idl.ne
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ struct -> "struct" fieldName "{" (member):+ "}" {% d => {
} %}

typedef -> "typedef" (
allTypes fieldName arrayLength
allTypes fieldName arrayLengths
| allTypes fieldName
| sequenceType fieldName
) {% d => {
Expand Down Expand Up @@ -206,7 +206,7 @@ fieldWithAnnotation -> multiAnnotations fieldDcl {% d=> {
} %}

fieldDcl -> (
allTypes multiFieldNames arrayLength
allTypes multiFieldNames arrayLengths
| allTypes multiFieldNames
| sequenceType multiFieldNames
) {% (d) => {
Expand Down Expand Up @@ -296,8 +296,19 @@ sequenceType -> "sequence" "<" allTypes ("," (INT|%NAME) ):? ">" {% d => {
};
}%}

arrayLengths -> arrayLength:+ {%
(d) => {
const arrInfo = {isArray: true};
const arrLengthList = d.flat(2);
arrInfo.arrayLengths = arrLengthList.map(
({arrayLength}) => arrayLength
);
return arrInfo;
}
%}

arrayLength -> "[" (INT|%NAME) "]" {%
([, intOrName]) => ({isArray: true, arrayLength: getIntOrConstantValue(intOrName ? intOrName[0] : undefined) })
([, intOrName]) => ({arrayLength: getIntOrConstantValue(intOrName ? intOrName[0] : undefined) })
%}

assignment -> (
Expand Down
Loading

0 comments on commit c6b439d

Please sign in to comment.