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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 187x 187x 187x 187x 187x 58x 58x 129x 129x 129x 187x 9x 9x 129x 129x 187x 35x 35x 34x 34x 35x 128x 128x 128x 187x 219x 4x 219x 60x 60x 1x 1x 1x 1x 59x 59x 59x 215x 86x 86x 62x 62x 1x 1x 1x 1x 61x 61x 61x 62x 85x 219x 126x 187x 57x 57x 126x 126x 187x 7x 7x 187x 19x 19x 126x 187x 84x 84x 84x 84x 84x 84x 84x 66x 66x 84x 84x 4x 5x 5x 5x 4x 84x 59x 59x 84x 42x 42x 1x 1x 1x 42x 84x 126x 187x 9x 9x 126x 187x 34x 34x 126x 187x 1x 1x 187x 187x 1x | import {ExpressionNode} from "../../nodes";
import * as Expressions from "../../2_statements/expressions";
import {For} from "./for";
import {Source} from "./source";
import {AbstractType} from "../../types/basic/_abstract_type";
import {Let} from "./let";
import {FieldAssignment} from "./field_assignment";
import {AnyType, CharacterType, StringType, TableType, UnknownType, VoidType} from "../../types/basic";
import {CheckSyntaxKey, SyntaxInput, syntaxIssue} from "../_syntax_input";
export class ValueBody {
public static runSyntax(
node: ExpressionNode | undefined,
input: SyntaxInput,
targetType: AbstractType | undefined): AbstractType | undefined {
if (node === undefined) {
return targetType;
}
let letScoped = false;
const letNode = node.findDirectExpression(Expressions.Let);
if (letNode) {
letScoped = Let.runSyntax(letNode, input);
}
let forScopes = 0;
for (const forNode of node.findDirectExpressions(Expressions.For) || []) {
const scoped = For.runSyntax(forNode, input);
if (scoped === true) {
forScopes++;
}
}
const fields = new Set<string>();
const hasTableLines = node.findDirectExpression(Expressions.ValueBodyLine) !== undefined;
for (const child of node.getChildren()) {
if (!(child instanceof ExpressionNode)) {
continue;
} else if (child.get() instanceof Expressions.FieldAssignment) {
const fieldname = child.findDirectExpression(Expressions.FieldSub)?.concatTokens().toUpperCase();
if (fieldname && hasTableLines === false && fields.has(fieldname)) {
const message = "Duplicate field assignment";
input.issues.push(syntaxIssue(input, child.getFirstToken(), message));
return VoidType.get(CheckSyntaxKey);
}
if (fieldname) {
fields.add(fieldname);
}
} else if (child.get() instanceof Expressions.ValueBodyLine) {
const rowFields = new Set(fields);
for (const assignment of child.findDirectExpressions(Expressions.FieldAssignment)) {
const fieldname = assignment.findDirectExpression(Expressions.FieldSub)?.concatTokens().toUpperCase();
if (fieldname && rowFields.has(fieldname)) {
const message = "Duplicate field assignment";
input.issues.push(syntaxIssue(input, assignment.getFirstToken(), message));
return VoidType.get(CheckSyntaxKey);
}
if (fieldname) {
rowFields.add(fieldname);
}
}
}
}
for (const s of node.findDirectExpressions(Expressions.FieldAssignment)) {
FieldAssignment.runSyntax(s, input, targetType);
}
let type: AbstractType | undefined = undefined; // todo, this is only correct if there is a single source in the body
for (const s of node.findDirectExpressions(Expressions.Source)) {
type = Source.runSyntax(s, input, type);
}
for (const s of node.findDirectExpression(Expressions.ValueBase)?.findDirectExpressions(Expressions.Source) || []) {
type = Source.runSyntax(s, input, type);
}
for (const foo of node.findDirectExpressions(Expressions.ValueBodyLine)) {
if (!(targetType instanceof TableType)
&& !(targetType instanceof UnknownType)
&& !(targetType instanceof AnyType)
&& targetType !== undefined
&& !(targetType instanceof VoidType)) {
const message = "Value, not a table type";
input.issues.push(syntaxIssue(input, foo.getFirstToken(), message));
return VoidType.get(CheckSyntaxKey);
}
let rowType: AbstractType | undefined = targetType;
if (targetType instanceof TableType) {
rowType = targetType.getRowType();
}
for (const l of foo.findDirectExpressions(Expressions.ValueBodyLines)) {
for (const s of l.findDirectExpressions(Expressions.Source)) {
// LINES OF ?? todo, pass type,
Source.runSyntax(s, input);
}
}
for (const s of foo.findDirectExpressions(Expressions.FieldAssignment)) {
FieldAssignment.runSyntax(s, input, rowType);
}
for (const s of foo.findDirectExpressions(Expressions.Source)) {
const sourceType = Source.runSyntax(s, input, rowType);
if (rowType instanceof StringType && sourceType instanceof CharacterType) {
const message = "VALUE, source type CharacterType not compatible with StringType";
input.issues.push(syntaxIssue(input, s.getFirstToken(), message));
}
}
}
if (letScoped === true) {
input.scope.pop(node.getLastToken().getEnd());
}
for (let i = 0; i < forScopes; i++) {
input.scope.pop(node.getLastToken().getEnd());
}
if (targetType?.isGeneric() && type) {
return type;
}
return targetType ? targetType : type;
}
}
|