Skip to content

Commit

Permalink
Improvise the construction of ObjectAttribute expressions.
Browse files Browse the repository at this point in the history
  • Loading branch information
EliotVU committed May 18, 2024
1 parent e11aa4d commit 723093b
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 30 deletions.
9 changes: 6 additions & 3 deletions server/src/UC/Symbols/CoreSymbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,24 +96,27 @@ const RotatorRollProperty = new UCPropertySymbol(
DEFAULT_RANGE, StaticIntType);
IntrinsicRotator.addSymbol(RotatorRollProperty);

export const Object_OuterPropertyHash = getSymbolOuterHash(NAME_OUTER.hash, getSymbolOuterHash(NAME_OBJECT.hash, NAME_CORE.hash));
export const Object_OuterProperty = new UCPropertySymbol(
{ name: NAME_OUTER, range: DEFAULT_RANGE },
DEFAULT_RANGE, StaticObjectType);
Object_OuterProperty.modifiers |= ModifierFlags.Native;
Object_OuterProperty.modifiers |= ModifierFlags.Intrinsic | ModifierFlags.Native;
Object_OuterProperty.outer = IntrinsicObject;
IntrinsicObject.addSymbol(Object_OuterProperty);

export const Object_NamePropertyHash = getSymbolOuterHash(NAME_NAME.hash, getSymbolOuterHash(NAME_OBJECT.hash, NAME_CORE.hash));
export const Object_NameProperty = new UCPropertySymbol(
{ name: NAME_NAME, range: DEFAULT_RANGE },
DEFAULT_RANGE, StaticNameType);
Object_NameProperty.modifiers |= ModifierFlags.Native;
Object_NameProperty.modifiers |= ModifierFlags.Intrinsic | ModifierFlags.Native;
Object_NameProperty.outer = IntrinsicObject;
IntrinsicObject.addSymbol(Object_NameProperty);

export const Object_ClassPropertyHash = getSymbolOuterHash(NAME_CLASS.hash, getSymbolOuterHash(NAME_OBJECT.hash, NAME_CORE.hash));
export const Object_ClassProperty = new UCPropertySymbol(
{ name: NAME_CLASS, range: DEFAULT_RANGE },
DEFAULT_RANGE, StaticObjectType);
Object_ClassProperty.modifiers |= ModifierFlags.Native;
Object_ClassProperty.modifiers |= ModifierFlags.Intrinsic | ModifierFlags.Native;
Object_ClassProperty.outer = IntrinsicObject;
IntrinsicObject.addSymbol(Object_ClassProperty);

Expand Down
15 changes: 14 additions & 1 deletion server/src/UC/diagnostics/documentAnalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import {
UCMemberExpression,
UCMetaClassExpression,
UCNameOfExpression,
UCObjectAttributeExpression,
UCObjectLiteral,
UCParenthesizedExpression,
UCPropertyAccessExpression,
Expand Down Expand Up @@ -1235,11 +1236,21 @@ export class DocumentAnalyzer extends DefaultSymbolWalker<void> {

const valueTypeKind = valueType.getTypeKind();
const letSymbol = expr.left.getMemberSymbol();
if (!(letSymbol && isField(letSymbol))) {
if (!letSymbol) {
this.pushError(
expr.left.getRange(),
`Couldn't find variable '${letType.getName().text}'`
);

return;
}

if (!isField(letSymbol)) {
this.pushError(
expr.left.getRange(),
`The left-hand side of an assignment expression must be a variable.`
);

return;
}

Expand Down Expand Up @@ -1284,6 +1295,8 @@ export class DocumentAnalyzer extends DefaultSymbolWalker<void> {
|| ((letSymbol.modifiers & ModifierFlags.Transient) !== 0
&& config.generation !== UCGeneration.UC3)
) && (matchFlags & UCMatchFlags.T3D)
// Ignore same-line assignments like Name= and Class=
&& !(expr instanceof UCObjectAttributeExpression)
) {
const modifiers = letSymbol
.buildModifiers(letSymbol.modifiers & (ModifierFlags.Native | ModifierFlags.Transient))
Expand Down
97 changes: 71 additions & 26 deletions server/src/UC/documentASTWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
UCNameOfExpression,
UCNewExpression,
UCNoneLiteral,
UCObjectAttributeExpression,
UCObjectLiteral,
UCParenthesizedExpression,
UCPostOperatorExpression,
Expand Down Expand Up @@ -87,15 +88,25 @@ import {
} from './statements';
import {
addHashedSymbol,
DEFAULT_RANGE,
hasNoKind,
Identifier,
IntrinsicObject,
isStatement,
ISymbol,
ISymbolContainer,
ITypeSymbol,
MethodFlags,
ModifierFlags,
Object_ClassProperty,
Object_ClassPropertyHash,
Object_NameProperty,
Object_NamePropertyHash,
ObjectsTable,
OuterObjectsTable,
StaticErrorType,
StaticNameType,
StaticObjectType,
UCArchetypeSymbol,
UCArrayTypeSymbol,
UCBinaryOperatorSymbol,
Expand Down Expand Up @@ -179,6 +190,20 @@ function createBlock(
return block;
}

export function createTypeFromQualifiedIdentifier(qualifiedIdentifier: string): UCQualifiedTypeSymbol | UCObjectTypeSymbol {
const identifiers = qualifiedIdentifier
.split('.')
.map(id => {
return {
name: toName(id),
range: DEFAULT_RANGE,
} as Identifier;
});

// We never expect to return 'undefined'.
return createTypeFromIdentifiers(identifiers)!;
}

function createTypeFromIdentifiers(identifiers: Identifier[]): UCQualifiedTypeSymbol | UCObjectTypeSymbol | undefined {
if (identifiers.length === 1) {
return new UCObjectTypeSymbol(identifiers[0]);
Expand Down Expand Up @@ -213,7 +238,7 @@ function createQualifiedType(ctx: UCGrammar.QualifiedIdentifierContext, kind?: U
leftType.setExpectedKind(UCSymbolKind.Class);
rightType.setExpectedKind(UCSymbolKind.Field);
break;

case UCSymbolKind.ScriptStruct:
leftType.setExpectedKind(UCSymbolKind.Class);
break;
Expand Down Expand Up @@ -317,7 +342,7 @@ export class DocumentASTWalker extends AbstractParseTreeVisitor<any> implements
// TODO: custom class
const symbol = new UCMacroSymbol(identifier);
this.document.addSymbol(symbol);

return symbol;
}

Expand Down Expand Up @@ -913,7 +938,7 @@ export class DocumentASTWalker extends AbstractParseTreeVisitor<any> implements
symbol.type = typeSymbol;
this.declare(symbol, ctx);
}

return undefined;
}

Expand Down Expand Up @@ -968,7 +993,7 @@ export class DocumentASTWalker extends AbstractParseTreeVisitor<any> implements
symbol.modifiers |= modifiers;
this.declare(symbol, ctx);
}

return undefined;
}

Expand Down Expand Up @@ -1027,7 +1052,7 @@ export class DocumentASTWalker extends AbstractParseTreeVisitor<any> implements
}
scope.ignoreRefs = scope.ignoreRefs.concat(ignoreRefs);
}

return undefined;
}

Expand Down Expand Up @@ -1090,38 +1115,58 @@ export class DocumentASTWalker extends AbstractParseTreeVisitor<any> implements
const range = rangeFromBounds(ctx.start, ctx.stop);
const block = new UCArchetypeBlockStatement(range);

let nameExpr: UCDefaultAssignmentExpression | undefined;
let nameId: Identifier | undefined;
let nameType: UCTypeSymbol | undefined;
let classExpr: UCDefaultAssignmentExpression | undefined;
let classId: Identifier | undefined;
let classType: UCObjectTypeSymbol | undefined;

const hardcodedStatements: IExpression[] = [];
const attrs = ctx.objectAttribute();
if (attrs) for (const objAttr of attrs) {
switch (objAttr._id.type) {
case UCLexer.KW_NAME: {
nameExpr = new UCDefaultAssignmentExpression(rangeFromBounds(ctx.start, ctx.stop));
nameExpr.left = new UCMemberExpression(createIdentifierFromToken(objAttr._id));
nameId = createIdentifier(objAttr._value);
const idExpr = new UCIdentifierLiteralExpression(nameId);
nameType = new UCTypeSymbol(UCTypeKind.Name);
idExpr.type = nameType;
nameExpr.right = idExpr;
hardcodedStatements.push(nameExpr);
const valueId = createIdentifier(objAttr._value);
nameId = valueId;

const valueExpr = new UCIdentifierLiteralExpression(valueId);
valueExpr.type = StaticNameType;

const propertyId = createIdentifierFromToken(objAttr._id);
const letType = new UCObjectTypeSymbol(propertyId);

const propertySymbol = OuterObjectsTable.getSymbol(Object_NamePropertyHash) ?? Object_NameProperty;
letType.setRef(propertySymbol, this.document);

const letExpr = new UCMemberExpression(propertyId);
letExpr.type = letType;

const expression = new UCObjectAttributeExpression(rangeFromBounds(ctx.start, ctx.stop));
expression.left = letExpr;
expression.right = valueExpr;

hardcodedStatements.push(expression);
break;
}

case UCLexer.KW_CLASS: {
classExpr = new UCDefaultAssignmentExpression(rangeFromBounds(ctx.start, ctx.stop));
classExpr.left = new UCMemberExpression(createIdentifierFromToken(objAttr._id));
classId = createIdentifier(objAttr._value);
const idExpr = new UCIdentifierLiteralExpression(classId);
classType = new UCObjectTypeSymbol(classId, undefined, UCSymbolKind.Class);
idExpr.type = classType;
classExpr.right = idExpr;
hardcodedStatements.push(classExpr);
const valueId = createIdentifier(objAttr._value);
classType = new UCObjectTypeSymbol(valueId, undefined, UCSymbolKind.Class);

const valueExpr = new UCIdentifierLiteralExpression(valueId);
valueExpr.type = classType;

const propertyId = createIdentifierFromToken(objAttr._id);
const letType = new UCObjectTypeSymbol(propertyId);

const propertySymbol = OuterObjectsTable.getSymbol(Object_ClassPropertyHash) ?? Object_ClassProperty;
letType.setRef(propertySymbol, this.document);

const letExpr = new UCMemberExpression(propertyId);
letExpr.type = letType;

const expression = new UCObjectAttributeExpression(rangeFromBounds(ctx.start, ctx.stop));
expression.left = letExpr;
expression.right = valueExpr;

hardcodedStatements.push(expression);
break;
}

Expand Down Expand Up @@ -1683,7 +1728,7 @@ export class DocumentASTWalker extends AbstractParseTreeVisitor<any> implements
return expression;
}

// new ( arguments ) classArgument=primaryExpression
// new ( arguments ) expression=primaryExpression
visitNewExpression(ctx: UCGrammar.NewExpressionContext) {
const expression = new UCNewExpression(rangeFromBounds(ctx.start, ctx.stop));

Expand Down

0 comments on commit 723093b

Please sign in to comment.