forked from cosmonaut/wraith-lang
Implements generic recursion over AST nodes
parent
eb24206e13
commit
ddd5b2f027
159
src/ast.c
159
src/ast.c
|
@ -726,6 +726,165 @@ void PrintNode(Node *node, uint32_t tabCount)
|
|||
}
|
||||
}
|
||||
|
||||
void Recurse(Node *node, void (*func)(Node*))
|
||||
{
|
||||
uint32_t i;
|
||||
switch (node->syntaxKind)
|
||||
{
|
||||
case AccessExpression:
|
||||
func(node->accessExpression.accessee);
|
||||
func(node->accessExpression.accessor);
|
||||
return;
|
||||
|
||||
case AllocExpression:
|
||||
func(node->allocExpression.type);
|
||||
return;
|
||||
|
||||
case Assignment:
|
||||
func(node->assignmentStatement.left);
|
||||
func(node->assignmentStatement.right);
|
||||
return;
|
||||
|
||||
case BinaryExpression:
|
||||
func(node->binaryExpression.left);
|
||||
func(node->binaryExpression.right);
|
||||
return;
|
||||
|
||||
case Comment:
|
||||
return;
|
||||
|
||||
case CustomTypeNode:
|
||||
return;
|
||||
|
||||
case Declaration:
|
||||
func(node->declaration.type);
|
||||
func(node->declaration.identifier);
|
||||
return;
|
||||
|
||||
case DeclarationSequence:
|
||||
for (i = 0; i < node->declarationSequence.count; i += 1) {
|
||||
func(node->declarationSequence.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case ForLoop:
|
||||
func(node->forLoop.declaration);
|
||||
func(node->forLoop.startNumber);
|
||||
func(node->forLoop.endNumber);
|
||||
func(node->forLoop.statementSequence);
|
||||
return;
|
||||
|
||||
case FunctionArgumentSequence:
|
||||
for (i = 0; i < node->functionArgumentSequence.count; i += 1) {
|
||||
func(node->functionArgumentSequence.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case FunctionCallExpression:
|
||||
func(node->functionCallExpression.identifier);
|
||||
func(node->functionCallExpression.argumentSequence);
|
||||
return;
|
||||
|
||||
case FunctionDeclaration:
|
||||
func(node->functionDeclaration.functionSignature);
|
||||
func(node->functionDeclaration.functionBody);
|
||||
return;
|
||||
|
||||
case FunctionModifiers:
|
||||
for (i = 0; i < node->functionModifiers.count; i += 1) {
|
||||
func(node->functionModifiers.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case FunctionSignature:
|
||||
func(node->functionSignature.identifier);
|
||||
func(node->functionSignature.type);
|
||||
func(node->functionSignature.arguments);
|
||||
func(node->functionSignature.modifiers);
|
||||
func(node->functionSignature.genericArguments);
|
||||
return;
|
||||
|
||||
case FunctionSignatureArguments:
|
||||
for (i = 0; i < node->functionSignatureArguments.count; i += 1) {
|
||||
func(node->functionSignatureArguments.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case GenericArgument:
|
||||
func(node->genericArgument.identifier);
|
||||
func(node->genericArgument.constraint);
|
||||
return;
|
||||
|
||||
case GenericArguments:
|
||||
for (i = 0; i < node->genericArguments.count; i += 1) {
|
||||
func(node->genericArguments.arguments[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case GenericTypeNode:
|
||||
return;
|
||||
|
||||
case Identifier:
|
||||
return;
|
||||
|
||||
case IfStatement:
|
||||
func(node->ifStatement.expression);
|
||||
func(node->ifStatement.statementSequence);
|
||||
return;
|
||||
|
||||
case IfElseStatement:
|
||||
func(node->ifElseStatement.ifStatement);
|
||||
func(node->ifElseStatement.elseStatement);
|
||||
return;
|
||||
|
||||
case Number:
|
||||
return;
|
||||
|
||||
case PrimitiveTypeNode:
|
||||
return;
|
||||
|
||||
case ReferenceTypeNode:
|
||||
func(node->referenceType.type);
|
||||
return;
|
||||
|
||||
case Return:
|
||||
func(node->returnStatement.expression);
|
||||
return;
|
||||
|
||||
case ReturnVoid:
|
||||
return;
|
||||
|
||||
case StatementSequence:
|
||||
for (i = 0; i < node->statementSequence.count; i += 1) {
|
||||
func(node->statementSequence.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case StaticModifier:
|
||||
return;
|
||||
|
||||
case StringLiteral:
|
||||
return;
|
||||
|
||||
case StructDeclaration:
|
||||
func(node->structDeclaration.identifier);
|
||||
func(node->structDeclaration.declarationSequence);
|
||||
return;
|
||||
|
||||
case Type:
|
||||
return;
|
||||
|
||||
case UnaryExpression:
|
||||
func(node->unaryExpression.child);
|
||||
return;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "wraith: Unhandled SyntaxKind %s in recurse function.\n",
|
||||
SyntaxKindString(node->syntaxKind));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TypeTag *MakeTypeTag(Node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
|
|
|
@ -367,6 +367,12 @@ Node *MakeForLoopNode(
|
|||
void PrintNode(Node *node, uint32_t tabCount);
|
||||
const char *SyntaxKindString(SyntaxKind syntaxKind);
|
||||
|
||||
/* Helper function for applying a void function generically over the children of an AST node.
|
||||
* Used for functions that need to traverse the entire tree but only perform operations on a subset
|
||||
* of node types. Such functions can match the syntaxKinds relevant to their purpose and invoke this
|
||||
* function in all other cases. */
|
||||
void Recurse(Node *node, void (*func)(Node*));
|
||||
|
||||
TypeTag *MakeTypeTag(Node *node);
|
||||
char *TypeTagToString(TypeTag *tag);
|
||||
|
||||
|
|
166
src/typeutils.c
166
src/typeutils.c
|
@ -51,152 +51,32 @@ void ConvertIdCustomsToGenerics(IdNode *node) {
|
|||
|
||||
void ConvertASTCustomsToGenerics(Node *node) {
|
||||
uint32_t i;
|
||||
switch (node->syntaxKind) {
|
||||
case AccessExpression:
|
||||
ConvertASTCustomsToGenerics(node->accessExpression.accessee);
|
||||
ConvertASTCustomsToGenerics(node->accessExpression.accessor);
|
||||
return;
|
||||
|
||||
case AllocExpression:
|
||||
ConvertASTCustomsToGenerics(node->allocExpression.type);
|
||||
return;
|
||||
|
||||
case Assignment:
|
||||
ConvertASTCustomsToGenerics(node->assignmentStatement.left);
|
||||
ConvertASTCustomsToGenerics(node->assignmentStatement.right);
|
||||
return;
|
||||
|
||||
case BinaryExpression:
|
||||
ConvertASTCustomsToGenerics(node->binaryExpression.left);
|
||||
ConvertASTCustomsToGenerics(node->binaryExpression.right);
|
||||
return;
|
||||
|
||||
case Comment:
|
||||
return;
|
||||
|
||||
case CustomTypeNode:
|
||||
return;
|
||||
|
||||
case Declaration: {
|
||||
Node *type = node->declaration.type->type.typeNode;
|
||||
Node *id = node->declaration.identifier;
|
||||
if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) {
|
||||
free(node->declaration.type);
|
||||
node->declaration.type = MakeGenericTypeNode(id->typeTag->value.genericType);
|
||||
}
|
||||
return;
|
||||
switch (node->syntaxKind)
|
||||
{
|
||||
case Declaration:
|
||||
{
|
||||
Node *type = node->declaration.type->type.typeNode;
|
||||
Node *id = node->declaration.identifier;
|
||||
if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) {
|
||||
free(node->declaration.type);
|
||||
node->declaration.type = MakeGenericTypeNode(id->typeTag->value.genericType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case DeclarationSequence:
|
||||
for (i = 0; i < node->declarationSequence.count; i += 1) {
|
||||
ConvertASTCustomsToGenerics(node->declarationSequence.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case ForLoop:
|
||||
ConvertASTCustomsToGenerics(node->forLoop.declaration);
|
||||
ConvertASTCustomsToGenerics(node->forLoop.startNumber);
|
||||
ConvertASTCustomsToGenerics(node->forLoop.endNumber);
|
||||
ConvertASTCustomsToGenerics(node->forLoop.statementSequence);
|
||||
return;
|
||||
|
||||
case FunctionArgumentSequence:
|
||||
for (i = 0; i < node->functionArgumentSequence.count; i += 1) {
|
||||
ConvertASTCustomsToGenerics(node->functionArgumentSequence.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case FunctionCallExpression:
|
||||
ConvertASTCustomsToGenerics(node->functionCallExpression.identifier);
|
||||
ConvertASTCustomsToGenerics(node->functionCallExpression.argumentSequence);
|
||||
return;
|
||||
|
||||
case FunctionDeclaration:
|
||||
ConvertASTCustomsToGenerics(node->functionDeclaration.functionSignature);
|
||||
ConvertASTCustomsToGenerics(node->functionDeclaration.functionBody);
|
||||
return;
|
||||
|
||||
case FunctionModifiers:
|
||||
return;
|
||||
|
||||
case FunctionSignature:{
|
||||
Node *id = node->functionSignature.identifier;
|
||||
Node *type = node->functionSignature.type;
|
||||
if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) {
|
||||
free(node->functionSignature.type);
|
||||
node->functionSignature.type = MakeGenericTypeNode(id->typeTag->value.genericType);
|
||||
}
|
||||
ConvertASTCustomsToGenerics(node->functionSignature.arguments);
|
||||
return;
|
||||
case FunctionSignature:
|
||||
{
|
||||
Node *id = node->functionSignature.identifier;
|
||||
Node *type = node->functionSignature.type;
|
||||
if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) {
|
||||
free(node->functionSignature.type);
|
||||
node->functionSignature.type = MakeGenericTypeNode(id->typeTag->value.genericType);
|
||||
}
|
||||
ConvertASTCustomsToGenerics(node->functionSignature.arguments);
|
||||
return;
|
||||
}
|
||||
|
||||
case FunctionSignatureArguments:
|
||||
for (i = 0; i < node->functionSignatureArguments.count; i += 1) {
|
||||
ConvertASTCustomsToGenerics(node->functionSignatureArguments.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case GenericArgument:
|
||||
return;
|
||||
|
||||
case GenericArguments:
|
||||
return;
|
||||
|
||||
case GenericTypeNode:
|
||||
return;
|
||||
|
||||
case Identifier:
|
||||
return;
|
||||
|
||||
case IfStatement:
|
||||
ConvertASTCustomsToGenerics(node->ifStatement.expression);
|
||||
ConvertASTCustomsToGenerics(node->ifStatement.statementSequence);
|
||||
return;
|
||||
|
||||
case IfElseStatement:
|
||||
ConvertASTCustomsToGenerics(node->ifElseStatement.ifStatement);
|
||||
ConvertASTCustomsToGenerics(node->ifElseStatement.elseStatement);
|
||||
return;
|
||||
|
||||
case Number:
|
||||
return;
|
||||
|
||||
case PrimitiveTypeNode:
|
||||
return;
|
||||
|
||||
case ReferenceTypeNode:
|
||||
return;
|
||||
|
||||
case Return:
|
||||
ConvertASTCustomsToGenerics(node->returnStatement.expression);
|
||||
return;
|
||||
|
||||
case ReturnVoid:
|
||||
return;
|
||||
|
||||
case StatementSequence:
|
||||
for (i = 0; i < node->statementSequence.count; i += 1) {
|
||||
ConvertASTCustomsToGenerics(node->statementSequence.sequence[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case StaticModifier:
|
||||
return;
|
||||
|
||||
case StringLiteral:
|
||||
return;
|
||||
|
||||
case StructDeclaration:
|
||||
/* FIXME: This case will need to be modified to handle type parameters over structs. */
|
||||
ConvertASTCustomsToGenerics(node->structDeclaration.identifier);
|
||||
ConvertASTCustomsToGenerics(node->structDeclaration.declarationSequence);
|
||||
return;
|
||||
|
||||
case Type:
|
||||
return;
|
||||
|
||||
case UnaryExpression:
|
||||
ConvertASTCustomsToGenerics(node->unaryExpression.child);
|
||||
return;
|
||||
default:
|
||||
recurse(node, *ConvertASTCustomsToGenerics);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue