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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1759x 1759x 1759x 1759x 1759x 1759x 1759x 1201x 1201x 1202x 1200x 1200x 2x 2x 1200x 1758x 1759x 1200x 1200x 1200x 1x 1x 1x 1x 1200x 1757x 1757x 1759x 1759x 1756x 1756x 1759x 1759x 3x 3x 3x 3x 1753x 1759x 1753x 1759x 557x 18x 18x 557x 557x 557x 1753x 1759x 9x 1759x 15x 15x 15x 15x 1759x 1759x 1x 1x 1x 1x 1181x 1181x 1181x 2x 1181x 1165x 1165x 14x 14x 1181x 14x 14x 1181x 9x 9x 5x 1181x 1181x 1x | import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {Source} from "../expressions/source";
import {Target} from "../expressions/target";
import {InlineData} from "../expressions/inline_data";
import {AbstractType} from "../../types/basic/_abstract_type";
import {StatementSyntax} from "../_statement_syntax";
import {TypeUtils} from "../_type_utils";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
import {Dereference} from "../expressions/dereference";
import {IdentifierMeta} from "../../types/_typed_identifier";
import {AnyType, DataType, PackedType} from "../../types/basic";
import {ExpressionNode, TokenNode} from "../../nodes";
export class Move implements StatementSyntax {
public runSyntax(node: StatementNode, input: SyntaxInput): void {
const targets = node.findDirectExpressions(Expressions.Target);
const firstTarget = targets[0];
const inline = firstTarget?.findDirectExpression(Expressions.InlineData);
let targetType: AbstractType | undefined = undefined;
if (inline === undefined) {
targetType = firstTarget ? Target.runSyntax(firstTarget, input) : undefined;
for (const t of targets) {
if (t === firstTarget) {
continue;
}
Target.runSyntax(t, input);
}
}
if (inline === undefined && firstTarget !== undefined) {
// hmm, does this do the scoping correctly? handle constants etc? todo
const found = input.scope.findVariable(firstTarget.concatTokens());
if (found && found.getMeta().includes(IdentifierMeta.ReadOnly)) {
const message = `"${firstTarget.concatTokens()}" cannot be modified, it is readonly`;
input.issues.push(syntaxIssue(input, firstTarget.getFirstToken(), message));
return;
}
}
const source = node.findDirectExpression(Expressions.Source);
let sourceType = source ? Source.runSyntax(source, input, targetType) : undefined;
if (sourceType === undefined) {
const message = "No source type determined";
input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
return;
}
if (inline === undefined
&& node.findDirectTokenByText("=") !== undefined
&& Move.isRefInferIntoGenericFieldSymbol(targets, source, targetType)) {
const message = "REF #( ) cannot infer a type from a generic target, use REF data( ) or a named type";
input.issues.push(syntaxIssue(input, source!.getFirstToken(), message));
return;
}
if (node.findDirectExpression(Expressions.Dereference)) {
sourceType = Dereference.runSyntax(node, sourceType, input);
}
if (inline) {
if (sourceType instanceof PackedType && source?.findDirectExpression(Expressions.ArithOperator)) {
sourceType = new PackedType(8, 0);
}
InlineData.runSyntax(inline, input, sourceType);
targetType = sourceType;
}
if (node.findDirectTokenByText("?=")) {
if (new TypeUtils(input.scope).isCastable(sourceType, targetType) === false) {
const message = "Incompatible types";
input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
return;
}
} else if (new TypeUtils(input.scope).isAssignableNew(sourceType, targetType, source) === false) {
const message = "Incompatible types";
input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
return;
}
}
/** target = REF #( ... ), with the single target being a field symbol typed "any" or "data",
* the type of REF # is inferred from the target, which is generic */
private static isRefInferIntoGenericFieldSymbol(targets: readonly ExpressionNode[],
source: ExpressionNode | undefined,
targetType: AbstractType | undefined): boolean {
if (targets.length !== 1 || source === undefined) {
return false;
} else if (!(targetType instanceof AnyType) && !(targetType instanceof DataType)) {
return false;
}
const targetChildren = targets[0].getChildren();
if (targetChildren.length !== 1 || !(targetChildren[0].get() instanceof Expressions.TargetFieldSymbol)) {
return false;
}
const first = source.getFirstChild();
if (!(first instanceof TokenNode) || first.getFirstToken().getStr().toUpperCase() !== "REF") {
return false;
}
return source.findDirectExpression(Expressions.TypeNameOrInfer)?.concatTokens() === "#";
}
}
|