Skip to content

Commit

Permalink
feat: implicit object creation
Browse files Browse the repository at this point in the history
  • Loading branch information
R-unic committed Jan 6, 2025
1 parent e353c87 commit de944bd
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
11 changes: 11 additions & 0 deletions RobloxCS.Luau/AstUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,17 @@ public static Call Bit32Call(string methodName, params Expression[] arguments) =
public static ArgumentList CreateArgumentList(List<Expression> arguments) =>
new ArgumentList(arguments.ConvertAll(expression => new Argument(expression)));

public static SimpleName TypeNameFromSymbol(ITypeSymbol symbol)
{
if (symbol is INamedTypeSymbol { TypeParameters.Length: > 0 } namedTypeSymbol)
{
var typeParameters = namedTypeSymbol.TypeParameters.Select(typeParameter => TypeNameFromSymbol(typeParameter).ToString()).ToList();
return new GenericName(symbol.Name, typeParameters);
}

return new IdentifierName(symbol.Name);
}

/// <summary>
/// Returns the full name of a C# node's parent.
/// This method is meant for getting the absolute location of classes, enums, etc.
Expand Down
16 changes: 10 additions & 6 deletions RobloxCS.Luau/Macros.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,17 @@ public class Macro(SemanticModel semanticModel)

/// <summary>Takes a C# object creation and expands the macro into a Luau expression</summary>
/// <returns>The expanded expression of the macro, or null if no macro was applied</returns>
public Expression? ObjectCreation(Func<SyntaxNode, Node?> visit, ObjectCreationExpressionSyntax objectCreation) {
public Expression? ObjectCreation(Func<SyntaxNode, Node?> visit, BaseObjectCreationExpressionSyntax baseObjectCreation) {
// generic objects
if (objectCreation.Type is GenericNameSyntax genericName) {
switch (genericName.Identifier.Text) {
var type = (INamedTypeSymbol)(baseObjectCreation is ObjectCreationExpressionSyntax objectCreation
? _semanticModel.GetSymbolInfo(objectCreation.Type)
: _semanticModel.GetSymbolInfo(baseObjectCreation)).Symbol!.ContainingSymbol;

if (type.TypeParameters.Length > 0) {
switch (type.Name) {
case "List":
{
var expressions = objectCreation.Initializer?.Expressions.Select(expression => (Expression)visit(expression)!).ToList();
var expressions = baseObjectCreation.Initializer?.Expressions.Select(expression => (Expression)visit(expression)!).ToList();
var table = new TableInitializer(expressions ?? []);
table.MarkExpanded(MacroKind.ListConstruction);

Expand All @@ -128,8 +132,8 @@ public class Macro(SemanticModel semanticModel)
var values = new List<Expression>();
var keys = new List<Expression>();

if (objectCreation.Initializer != null) {
foreach (var expression in objectCreation.Initializer.Expressions)
if (baseObjectCreation.Initializer != null) {
foreach (var expression in baseObjectCreation.Initializer.Expressions)
{
switch (expression)
{
Expand Down
14 changes: 11 additions & 3 deletions RobloxCS/LuauGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -472,13 +472,21 @@ public override Luau.TableInitializer VisitCollectionExpression(CollectionExpres

public override Luau.Node? VisitImplicitObjectCreationExpression(ImplicitObjectCreationExpressionSyntax node)
{
// TODO
return base.VisitImplicitObjectCreationExpression(node);
// TODO: handle non-null node.Initializer (prob won't be supported)
var classSymbol = (ITypeSymbol)_semanticModel.GetSymbolInfo(node).Symbol!.ContainingSymbol;
var name = Luau.AstUtility.TypeNameFromSymbol(classSymbol);
var nonGenericName = Luau.AstUtility.GetNonGenericName(name);
var argumentList = Visit<Luau.ArgumentList>(node.ArgumentList);

var callee = new Luau.QualifiedName(nonGenericName, new Luau.IdentifierName("new"));
var expandedExpression = _macro.ObjectCreation(Visit, node);

return expandedExpression ?? new Luau.Call(callee, argumentList);
}

public override Luau.Expression VisitObjectCreationExpression(ObjectCreationExpressionSyntax node)
{
// TODO: handle null node.Initializer
// TODO: handle non-null node.Initializer (prob won't be supported)
var name = Visit<Luau.Name>(node.Type);
var nonGenericName = Luau.AstUtility.GetNonGenericName(name);
var argumentList = Visit<Luau.ArgumentList>(node.ArgumentList);
Expand Down

0 comments on commit de944bd

Please sign in to comment.