Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1975x 1975x 1975x 1975x 1975x 1975x 229x 229x 229x 229x 229x 229x 2x 2x 2x 2x 2x 2x 229x 1973x 1973x 1973x 1973x 1973x 1975x 840x 840x 840x 840x 1x 1x 1x 840x 269x 269x 269x 269x 6x 6x 6x 8x 8x 6x 6x 6x 6x 1x 1x 6x 6x 6x 839x 56x 56x 56x 570x 6x 514x 269x 10x 10x 269x 508x 239x 46x 1x 1x 1x 1x 45x 46x 31x 31x 239x 102x 193x 20x 20x 8x 3x 8x 2x 2x 8x 91x 21x 21x 14x 4x 14x 2x 2x 14x 21x 840x 840x 1970x 1970x 1970x 1x 1x 1x 1x 1973x 1973x 1973x 1973x 1973x 1973x 1973x 1973x 85x 1973x 1888x 1840x 1888x 48x 2x 48x 46x 46x 46x 46x 46x 25x 25x 46x 17x 17x 17x 21x 4x 4x 4x 4x 46x 1x 1x | import {ExpressionNode} from "../../nodes"; import {AbstractType} from "../../types/basic/_abstract_type"; import {INode} from "../../nodes/_inode"; import * as Expressions from "../../2_statements/expressions"; import {Dash, DashW, InstanceArrow} from "../../1_lexer/tokens"; import {StructureType, ObjectReferenceType, VoidType, DataReference, TableType, UnknownType, GenericObjectReferenceType, CharacterType, HexType} from "../../types/basic"; import {ComponentName} from "./component_name"; import {AttributeName} from "./attribute_name"; import {ReferenceType} from "../_reference"; import {FieldOffset} from "./field_offset"; import {FieldLength} from "./field_length"; import {TableExpression} from "./table_expression"; import {Dereference as DereferenceExpression} from "../../2_statements/expressions"; import {Dereference} from "./dereference"; import {SourceFieldSymbol} from "./source_field_symbol"; import {SourceField} from "./source_field"; import {CheckSyntaxKey, SyntaxInput, syntaxIssue} from "../_syntax_input"; export class FieldChain { public runSyntax( node: ExpressionNode, input: SyntaxInput, refType?: ReferenceType | ReferenceType[] | undefined): AbstractType | undefined { if (node.getFirstChild()?.get() instanceof Expressions.SourceField && node.findDirectExpression(Expressions.ComponentName)) { // workaround for names with dashes, eg. "sy-repid" const concat = node.concatTokens(); const offset = node.findDirectExpression(Expressions.FieldOffset)?.concatTokens() || ""; const length = node.findDirectExpression(Expressions.FieldLength)?.concatTokens() || ""; const found = input.scope.findVariable(concat.replace(offset, "").replace(length, "")); if (found) { if (refType) { input.scope.addReference(node.getFirstToken(), found, refType, input.filename); } // this is not completely correct, but will work, dashes in names is a mess anyhow return found.getType(); } } let context: AbstractType | undefined = undefined; const children = node.getChildren(); context = this.findTop(children[0], input, refType); for (let i = 1; i < children.length; i++) { const current = children[i]; if (current === undefined) { break; } if (current.get() instanceof DashW) { const message = "Ending with dash"; input.issues.push(syntaxIssue(input, current.getFirstToken(), message)); return new VoidType(CheckSyntaxKey); } else if (current.get() instanceof Dash) { if (context instanceof UnknownType) { const message = "Not a structure, type unknown, FieldChain"; input.issues.push(syntaxIssue(input, current.getFirstToken(), message)); return new VoidType(CheckSyntaxKey); } else if (!(context instanceof StructureType) && !(context instanceof TableType && context.isWithHeader()) && !(context instanceof VoidType)) { if (context instanceof TableType && context.isWithHeader() === false) { let contextName = ""; for (let j = 0; j < i; j++) { contextName += children[j].concatTokens(); } if (input.scope.isAllowHeaderUse(contextName)) { // FOR ALL ENTRIES workaround context = context.getRowType(); if (!(context instanceof StructureType) && !(context instanceof VoidType)) { context = new StructureType([{name: "TABLE_LINE", type: context}]); } } else { const message = "Table without header, cannot access fields, " + contextName; input.issues.push(syntaxIssue(input, current.getFirstToken(), message)); return new VoidType(CheckSyntaxKey); } } else { const message = "Not a structure, FieldChain"; input.issues.push(syntaxIssue(input, current.getFirstToken(), message)); return new VoidType(CheckSyntaxKey); } } } else if (current.get() instanceof InstanceArrow) { if (!(context instanceof ObjectReferenceType) && !(context instanceof DataReference) && !(context instanceof VoidType)) { const message = "Not an object reference, field chain"; input.issues.push(syntaxIssue(input, current.getFirstToken(), message)); return new VoidType(CheckSyntaxKey); } } else if (current.get() instanceof DereferenceExpression) { context = new Dereference().runSyntax(current, context, input); } else if (current.get() instanceof Expressions.ComponentName) { if (context instanceof TableType && context.isWithHeader()) { context = context.getRowType(); } context = new ComponentName().runSyntax(context, current, input); } else if (current instanceof ExpressionNode && current.get() instanceof Expressions.TableExpression) { if (!(context instanceof TableType) && !(context instanceof VoidType)) { const message = "Table expression, expected table"; input.issues.push(syntaxIssue(input, current.getFirstToken(), message)); return new VoidType(CheckSyntaxKey); } new TableExpression().runSyntax(current, input); if (!(context instanceof VoidType)) { context = context.getRowType(); } } else if (current.get() instanceof Expressions.AttributeName) { context = new AttributeName().runSyntax(context, current, input, refType); } else if (current.get() instanceof Expressions.FieldOffset && current instanceof ExpressionNode) { const offset = new FieldOffset().runSyntax(current, input); if (offset) { if (context instanceof CharacterType) { context = new CharacterType(context.getLength() - offset); } else if (context instanceof HexType) { context = new HexType(context.getLength() - offset); } } } else if (current.get() instanceof Expressions.FieldLength && current instanceof ExpressionNode) { const length = new FieldLength().runSyntax(current, input); if (length) { if (context instanceof CharacterType) { context = new CharacterType(length); } else if (context instanceof HexType) { context = new HexType(length); } } } } return context; } //////////////// private findTop( node: INode | undefined, input: SyntaxInput, type: ReferenceType | ReferenceType[] | undefined): AbstractType | undefined { if (node === undefined) { return undefined; } if (node instanceof ExpressionNode && node.get() instanceof Expressions.SourceFieldSymbol) { return new SourceFieldSymbol().runSyntax(node, input); } else if (node instanceof ExpressionNode && node.get() instanceof Expressions.SourceField) { return new SourceField().runSyntax(node, input, type); } else if (node instanceof ExpressionNode && node.get() instanceof Expressions.Field) { return new SourceField().runSyntax(node, input, type); } else if (node.get() instanceof Expressions.ClassName) { const classTok = node.getFirstToken(); const classNam = classTok.getStr(); if (classNam.toUpperCase() === "OBJECT") { return new GenericObjectReferenceType(); } const found = input.scope.existsObject(classNam); if (found?.id) { input.scope.addReference(classTok, found.id, ReferenceType.ObjectOrientedReference, input.filename); return new ObjectReferenceType(found.id); } else if (input.scope.getDDIC().inErrorNamespace(classNam) === false) { input.scope.addReference(classTok, undefined, ReferenceType.ObjectOrientedVoidReference, input.filename, {ooName: classNam.toUpperCase()}); return new VoidType(classNam); } else { const message = "Unknown class " + classNam; input.issues.push(syntaxIssue(input, node.getFirstToken(), message)); return new VoidType(CheckSyntaxKey); } } return undefined; } } |