Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support namespace qualifiers in classes used in Imperative blocks #9252

Merged
merged 10 commits into from
Nov 19, 2018
78 changes: 47 additions & 31 deletions src/Engine/ProtoCore/CodeGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -627,44 +627,60 @@ protected bool DfsEmitIdentList(
Node binaryExpNode = null)
{
dynamic node = pNode;
if (node is ProtoCore.AST.ImperativeAST.IdentifierListNode || node is ProtoCore.AST.AssociativeAST.IdentifierListNode)
if (node is AST.ImperativeAST.IdentifierListNode || node is AST.AssociativeAST.IdentifierListNode)
{
dynamic bnode = node;
if (ProtoCore.DSASM.Operator.dot != bnode.Optr)
if (Operator.dot != bnode.Optr)
{
string message = "The left hand side of an operation can only contain an indirection operator '.' (48D67B9B)";
buildStatus.LogSemanticError(message, core.CurrentDSFileName, bnode.line, bnode.col);
throw new BuildHaltException(message);
}

DfsEmitIdentList(bnode.LeftNode, bnode, contextClassScope, ref lefttype, ref depth, ref finalType, isLeftidentList, graphNode, subPass);
// Check if node.LeftNode is a valid class
var identListNode = bnode.LeftNode as AST.ImperativeAST.IdentifierListNode;
int ci = Constants.kInvalidIndex;

if (lefttype.rank > 0)
if (identListNode != null)
{
lefttype.UID = finalType.UID = (int)PrimitiveType.Null;
EmitPushNull();
return false;
var className = CoreUtils.GetIdentifierExceptMethodName(identListNode);
ci = core.ClassTable.IndexOf(className);
if (ci != Constants.kInvalidIndex)
{
finalType.UID = lefttype.UID = ci;
}
}
if (ci == Constants.kInvalidIndex)
{
DfsEmitIdentList(bnode.LeftNode, bnode, contextClassScope, ref lefttype, ref depth, ref finalType, isLeftidentList, graphNode, subPass);

if (lefttype.rank > 0)
{
lefttype.UID = finalType.UID = (int)PrimitiveType.Null;
EmitPushNull();
return false;
}
}
node = bnode.RightNode;
}

if (node is ProtoCore.AST.ImperativeAST.GroupExpressionNode)
if (node is AST.ImperativeAST.GroupExpressionNode)
{
ProtoCore.AST.ImperativeAST.ArrayNode array = node.ArrayDimensions;
var array = node.ArrayDimensions;
node = node.Expression;
node.ArrayDimensions = array;
}
else if (node is ProtoCore.AST.AssociativeAST.GroupExpressionNode)
else if (node is AST.AssociativeAST.GroupExpressionNode)
{
ProtoCore.AST.AssociativeAST.ArrayNode array = node.ArrayDimensions;
List<ProtoCore.AST.AssociativeAST.AssociativeNode> replicationGuides = node.ReplicationGuides;
var array = node.ArrayDimensions;
var replicationGuides = node.ReplicationGuides;

node = node.Expression;
node.ArrayDimensions = array;
node.ReplicationGuides = replicationGuides;
}

if (node is ProtoCore.AST.ImperativeAST.IdentifierNode || node is ProtoCore.AST.AssociativeAST.IdentifierNode)
if (node is AST.ImperativeAST.IdentifierNode || node is AST.AssociativeAST.IdentifierNode)
{
dynamic identnode = node;

Expand Down Expand Up @@ -723,7 +739,7 @@ protected bool DfsEmitIdentList(
}
else
{
DSASM.DyanmicVariableNode dynamicVariableNode = new DSASM.DyanmicVariableNode(identnode.Value, globalProcIndex, globalClassIndex);
var dynamicVariableNode = new DSASM.DyanmicVariableNode(identnode.Value, globalProcIndex, globalClassIndex);
core.DynamicVariableTable.variableTable.Add(dynamicVariableNode);
int dim = 0;
if (null != identnode.ArrayDimensions)
Expand Down Expand Up @@ -772,8 +788,8 @@ protected bool DfsEmitIdentList(
StackValue op = StackValue.Null;
if (0 == depth || (symbolnode != null && symbolnode.isStatic))
{
if (ProtoCore.DSASM.Constants.kGlobalScope == symbolnode.functionIndex
&& ProtoCore.DSASM.Constants.kInvalidIndex != symbolnode.classScope)
if (Constants.kGlobalScope == symbolnode.functionIndex
&& Constants.kInvalidIndex != symbolnode.classScope)
{
// member var
if (symbolnode.isStatic)
Expand Down Expand Up @@ -806,7 +822,7 @@ protected bool DfsEmitIdentList(
else
{
// change to dynamic call to facilitate update mechanism
DSASM.DyanmicVariableNode dynamicVariableNode = new DSASM.DyanmicVariableNode(identnode.Name, globalProcIndex, globalClassIndex);
var dynamicVariableNode = new DSASM.DyanmicVariableNode(identnode.Name, globalProcIndex, globalClassIndex);
core.DynamicVariableTable.variableTable.Add(dynamicVariableNode);
StackValue dynamicOp = StackValue.BuildDynamic(core.DynamicVariableTable.variableTable.Count - 1);
EmitInstrConsole(ProtoCore.DSASM.kw.pushm, identnode.Value + "[dynamic]");
Expand All @@ -828,7 +844,7 @@ protected bool DfsEmitIdentList(
}
return true;
}
else if (node is ProtoCore.AST.ImperativeAST.FunctionCallNode || node is ProtoCore.AST.AssociativeAST.FunctionCallNode)
else if (node is AST.ImperativeAST.FunctionCallNode || node is AST.AssociativeAST.FunctionCallNode)
{
// A function call must always track dependents
bool allowDependents = true;
Expand All @@ -842,7 +858,7 @@ protected bool DfsEmitIdentList(
{
ProtoCore.Utils.NodeUtils.SetNodeLocation(node, binaryExpNode, binaryExpNode);
}
ProtoCore.DSASM.ProcedureNode procnode = TraverseFunctionCall(node, pNode, lefttype.UID, depth, ref finalType, graphNode, subPass, binaryExpNode);
var procnode = TraverseFunctionCall(node, pNode, lefttype.UID, depth, ref finalType, graphNode, subPass, binaryExpNode);

// Restore the graphNode dependent state
if (null != graphNode)
Expand Down Expand Up @@ -2033,24 +2049,24 @@ protected void BuildRealDependencyForIdentList(AssociativeGraph.GraphNode graphN
}
}

protected void EmitIdentifierListNode(Node node, ref ProtoCore.Type inferedType, bool isBooleanOp = false,
ProtoCore.AssociativeGraph.GraphNode graphNode = null,
ProtoCore.CompilerDefinitions.SubCompilePass subPass = ProtoCore.CompilerDefinitions.SubCompilePass.None,
ProtoCore.AST.Node bnode = null)
protected void EmitIdentifierListNode(Node node, ref Type inferedType, bool isBooleanOp = false,
AssociativeGraph.GraphNode graphNode = null,
CompilerDefinitions.SubCompilePass subPass = CompilerDefinitions.SubCompilePass.None,
Node bnode = null)
{
if (subPass == ProtoCore.CompilerDefinitions.SubCompilePass.UnboundIdentifier)
if (subPass == CompilerDefinitions.SubCompilePass.UnboundIdentifier)
{
//to process all unbounded parameters if any
dynamic iNode = node;
while (iNode is ProtoCore.AST.AssociativeAST.IdentifierListNode || iNode is ProtoCore.AST.ImperativeAST.IdentifierListNode)
while (iNode is AST.AssociativeAST.IdentifierListNode || iNode is AST.ImperativeAST.IdentifierListNode)
{
dynamic rightNode = iNode.RightNode;
if (rightNode is ProtoCore.AST.AssociativeAST.FunctionCallNode || rightNode is ProtoCore.AST.ImperativeAST.FunctionCallNode)
if (rightNode is AST.AssociativeAST.FunctionCallNode || rightNode is AST.ImperativeAST.FunctionCallNode)
{
foreach (dynamic paramNode in rightNode.FormalArguments)
{
ProtoCore.Type paramType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var, 0);
DfsTraverse(paramNode, ref paramType, false, graphNode, ProtoCore.CompilerDefinitions.SubCompilePass.UnboundIdentifier);
Type paramType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var, 0);
DfsTraverse(paramNode, ref paramType, false, graphNode, CompilerDefinitions.SubCompilePass.UnboundIdentifier);
}
}
iNode = iNode.LeftNode;
Expand All @@ -2060,16 +2076,16 @@ protected void EmitIdentifierListNode(Node node, ref ProtoCore.Type inferedType,

int depth = 0;

ProtoCore.Type leftType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.InvalidType, 0);
Type leftType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.InvalidType, 0);

BuildSSADependency(node, graphNode);
if (core.Options.GenerateSSA)
{
BuildRealDependencyForIdentList(graphNode);

if (node is ProtoCore.AST.AssociativeAST.IdentifierListNode)
if (node is AST.AssociativeAST.IdentifierListNode)
{
if ((node as ProtoCore.AST.AssociativeAST.IdentifierListNode).IsLastSSAIdentListFactor)
if ((node as AST.AssociativeAST.IdentifierListNode).IsLastSSAIdentListFactor)
{
Validity.Assert(null != ssaPointerStack);
ssaPointerStack.Pop();
Expand Down
86 changes: 86 additions & 0 deletions src/Engine/ProtoCore/Utils/CoreUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,60 @@ public static string GetIdentifierExceptMethodName(IdentifierListNode identList)
return CreateNodeByCombiningIdentifiers(intermediateNodes).ToString();
}

/// <summary>
/// Retrieves the string format of the identifier list from left to right, leaving out any symbols after the last identifier.
/// Given: A.B()
/// Return: "A"
/// Given: A.B.C()[0]
/// Return: "A.B"
/// Given: A.B().C
/// Return: "A"
/// Given: A.B[0].C
/// Return: "A.B[0].C"
/// Given: A().B (global function)
/// Return: empty string
/// Given: A.B[0].C()
/// Return: "A.B[0]"
/// </summary>
/// <param name="identList"></param>
/// <returns></returns>
public static string GetIdentifierExceptMethodName(AST.ImperativeAST.IdentifierListNode identList)
{
Validity.Assert(null != identList);

var leftNode = identList.LeftNode;
var rightNode = identList.RightNode;

var intermediateNodes = new List<AST.ImperativeAST.ImperativeNode>();
if (!(rightNode is AST.ImperativeAST.FunctionCallNode))
{
intermediateNodes.Insert(0, rightNode);
}

while (leftNode is AST.ImperativeAST.IdentifierListNode)
{
rightNode = ((AST.ImperativeAST.IdentifierListNode)leftNode).RightNode;
if (rightNode is AST.ImperativeAST.FunctionCallNode)
{
intermediateNodes.Clear();
}
else
{
intermediateNodes.Insert(0, rightNode);
}
leftNode = ((AST.ImperativeAST.IdentifierListNode)leftNode).LeftNode;

}
if (leftNode is AST.ImperativeAST.FunctionCallNode)
{
intermediateNodes.Clear();
return "";
}
intermediateNodes.Insert(0, leftNode);

return CreateNodeByCombiningIdentifiers(intermediateNodes).ToString();
}

/// <summary>
/// Inspects the input identifier list to match all class names with the class used in it
/// </summary>
Expand Down Expand Up @@ -670,6 +724,38 @@ public static AssociativeNode CreateNodeByCombiningIdentifiers(IList<Associative
return newIdentList;
}

public static AST.ImperativeAST.ImperativeNode CreateNodeByCombiningIdentifiers(IList<AST.ImperativeAST.ImperativeNode> nodeList)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

summary tag for public method?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use an IEnumerable for a public method?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry, did not see it was an IList

{
int count = nodeList.Count;
if (count == 0)
return null;

if (count == 1)
{
return nodeList[0];
}

var newIdentList = new AST.ImperativeAST.IdentifierListNode
{
LeftNode = nodeList[0],
RightNode = nodeList[1],
Optr = Operator.dot
};

for (var n = 2; n < count; ++n)
{
var subIdentList = new AST.ImperativeAST.IdentifierListNode
{
LeftNode = newIdentList,
RightNode = nodeList[n],
Optr = Operator.dot
};
newIdentList = subIdentList;
}

return newIdentList;
}

/// <summary>
/// Parses designscript code and outputs ProtoAST
/// </summary>
Expand Down
Loading