From c6507fdcb7162c65fab31f6a3879442277b23c46 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 21 Apr 2021 21:29:38 -0700 Subject: [PATCH] scope refactor --- ast.c | 14 ++ ast.h | 5 + compiler.c | 463 +++++++++++++++++++++++++++++++---------------------- wraith.y | 17 +- 4 files changed, 309 insertions(+), 190 deletions(-) diff --git a/ast.c b/ast.c index f968623..2906a44 100644 --- a/ast.c +++ b/ast.c @@ -21,6 +21,7 @@ const char* SyntaxKindString(SyntaxKind syntaxKind) { switch(syntaxKind) { + case AccessExpression: return "AccessExpression"; case Assignment: return "Assignment"; case BinaryExpression: return "BinaryExpression"; case Comment: return "Comment"; @@ -292,6 +293,19 @@ Node* MakeFunctionCallExpressionNode( return node; } +Node* MakeAccessExpressionNode( + Node *accessee, + Node *accessor +) { + Node* node = (Node*) malloc(sizeof(Node)); + node->syntaxKind = AccessExpression; + node->children = (Node**) malloc(sizeof(Node*) * 2); + node->childCount = 2; + node->children[0] = accessee; + node->children[1] = accessor; + return node; +} + static const char* PrimitiveTypeToString(PrimitiveType type) { switch (type) diff --git a/ast.h b/ast.h index d96cf74..96f22a8 100644 --- a/ast.h +++ b/ast.h @@ -5,6 +5,7 @@ typedef enum { + AccessExpression, Assignment, BinaryExpression, Comment, @@ -148,6 +149,10 @@ Node* MakeFunctionCallExpressionNode( Node *identifierNode, Node *argumentSequenceNode ); +Node* MakeAccessExpressionNode( + Node *accessee, + Node *accessor +); void PrintTree(Node *node, uint32_t tabCount); diff --git a/compiler.c b/compiler.c index d68cde3..b5e42b3 100644 --- a/compiler.c +++ b/compiler.c @@ -14,176 +14,260 @@ extern FILE *yyin; Stack *stack; Node *rootNode; -typedef struct StructFieldMapValue +typedef struct LocalVariable +{ + char *name; + LLVMValueRef pointer; +} LocalVariable; + +typedef struct FunctionArgument { char *name; LLVMValueRef value; - LLVMValueRef valuePointer; +} FunctionArgument; + +typedef struct ScopeFrame +{ + LocalVariable *localVariables; + uint32_t localVariableCount; + + FunctionArgument *arguments; + uint32_t argumentCount; +} ScopeFrame; + +typedef struct Scope +{ + ScopeFrame *scopeStack; + uint32_t scopeStackCount; +} Scope; + +Scope *scope; + +typedef struct StructTypeField +{ + char *name; uint32_t index; - uint8_t needsWrite; - uint8_t needsRead; -} StructFieldMapValue; +} StructTypeField; -typedef struct StructFieldMap +typedef struct StructTypeFieldDeclaration { - LLVMValueRef structPointer; - StructFieldMapValue *fields; + LLVMTypeRef structType; + StructTypeField *fields; uint32_t fieldCount; -} StructFieldMap; -StructFieldMap *structFieldMaps; -uint32_t structFieldMapCount; +} StructTypeFieldDeclaration; -static void AddStruct(LLVMValueRef wStructPointer) +StructTypeFieldDeclaration *structTypeFieldDeclarations; +uint32_t structTypeFieldDeclarationCount; + +static Scope* CreateScope() { - structFieldMaps = realloc(structFieldMaps, sizeof(StructFieldMap) * (structFieldMapCount + 1)); - structFieldMaps[structFieldMapCount].structPointer = wStructPointer; - structFieldMaps[structFieldMapCount].fields = NULL; - structFieldMaps[structFieldMapCount].fieldCount = 0; - structFieldMapCount += 1; + Scope *scope = malloc(sizeof(Scope)); + + scope->scopeStack = malloc(sizeof(ScopeFrame)); + scope->scopeStack[0].argumentCount = 0; + scope->scopeStack[0].arguments = NULL; + scope->scopeStack[0].localVariableCount = 0; + scope->scopeStack[0].localVariables = NULL; + scope->scopeStackCount = 1; + + return scope; } -static void AddStructFieldName(LLVMBuilderRef builder, LLVMValueRef wStructPointer, char *name, uint32_t index) +static void PushScopeFrame(Scope *scope) { - uint32_t i, fieldCount; + uint32_t index = scope->scopeStackCount; + scope->scopeStack = realloc(scope->scopeStack, sizeof(ScopeFrame) * (scope->scopeStackCount + 1)); + scope->scopeStack[index].argumentCount = 0; + scope->scopeStack[index].arguments = NULL; + scope->scopeStack[index].localVariableCount = 0; + scope->scopeStack[index].localVariables = NULL; - for (i = 0; i < structFieldMapCount; i += 1) - { - if (structFieldMaps[i].structPointer == wStructPointer) - { - fieldCount = structFieldMaps[i].fieldCount; - - structFieldMaps[i].fields = realloc(structFieldMaps[i].fields, sizeof(StructFieldMapValue) * (fieldCount + 1)); - structFieldMaps[i].fields[fieldCount].name = strdup(name); - structFieldMaps[i].fields[fieldCount].value = NULL; - structFieldMaps[i].fields[fieldCount].valuePointer = NULL; - structFieldMaps[i].fields[fieldCount].index = index; - structFieldMaps[i].fields[fieldCount].needsWrite = 0; - structFieldMaps[i].fields[fieldCount].needsRead = 1; - structFieldMaps[i].fieldCount += 1; - - break; - } - } + scope->scopeStackCount += 1; } -static LLVMValueRef CheckStructFieldAndLoad(LLVMBuilderRef builder, LLVMValueRef wStructPointer, char *name) +static void PopScopeFrame(Scope *scope) { - uint32_t i, j; + uint32_t i; + uint32_t index = scope->scopeStackCount - 1; - for (i = 0; i < structFieldMapCount; i += 1) + if (scope->scopeStack[index].arguments != NULL) { - if (structFieldMaps[i].structPointer == wStructPointer) + for (i = 0; i < scope->scopeStack[index].argumentCount; i += 1) { - for (j = 0; j < structFieldMaps[i].fieldCount; j += 1) - { - if (strcmp(structFieldMaps[i].fields[j].name, name) == 0) - { - if (structFieldMaps[i].fields[j].needsRead) - { - char *ptrName = strdup(name); - strcat(ptrName, "_ptr"); - LLVMValueRef elementPointer = LLVMBuildStructGEP( - builder, - wStructPointer, - structFieldMaps[i].fields[j].index, - ptrName - ); - free(ptrName); - - structFieldMaps[i].fields[j].value = LLVMBuildLoad(builder, elementPointer, name); - structFieldMaps[i].fields[j].valuePointer = elementPointer; - structFieldMaps[i].fields[j].needsRead = 0; - } - - return structFieldMaps[i].fields[j].value; - } - } + free(scope->scopeStack[index].arguments[i].name); } + free(scope->scopeStack[index].arguments); } - return NULL; -} - -static void MarkStructFieldForWrite(LLVMValueRef wStructPointer, LLVMValueRef value) -{ - uint32_t i, j; - - for (i = 0; i < structFieldMapCount; i += 1) + if (scope->scopeStack[index].localVariables != NULL) { - if (structFieldMaps[i].structPointer == wStructPointer) + for (i = 0; i < scope->scopeStack[index].localVariableCount; i += 1) { - for (j = 0; j < structFieldMaps[i].fieldCount; j += 1) - { - if (structFieldMaps[i].fields[j].value == value) - { - structFieldMaps[i].fields[j].needsWrite = 1; - break; - } - } - } - } -} - -static LLVMValueRef GetStructFieldPointer(LLVMValueRef wStructPointer, LLVMValueRef value) -{ - uint32_t i, j; - - for (i = 0; i < structFieldMapCount; i += 1) - { - if (structFieldMaps[i].structPointer == wStructPointer) - { - for (j = 0; j < structFieldMaps[i].fieldCount; j += 1) - { - if (structFieldMaps[i].fields[j].value == value) - { - return structFieldMaps[i].fields[j].valuePointer; - } - } + free(scope->scopeStack[index].localVariables[i].name); } + free(scope->scopeStack[index].localVariables); } - return NULL; + scope->scopeStackCount -= 1; + + scope->scopeStack = realloc(scope->scopeStack, sizeof(ScopeFrame) * scope->scopeStackCount); } -static void RemoveStruct(LLVMBuilderRef builder, LLVMValueRef wStructPointer) +static void AddLocalVariable(Scope *scope, LLVMValueRef pointer, char *name) { - uint32_t i, j; + ScopeFrame *scopeFrame = &scope->scopeStack[scope->scopeStackCount - 1]; + uint32_t index = scopeFrame->localVariableCount; - for (i = 0; i < structFieldMapCount; i += 1) + scopeFrame->localVariables = realloc(scopeFrame->localVariables, sizeof(LocalVariable) * (scopeFrame->localVariableCount + 1)); + scopeFrame->localVariables[index].name = strdup(name); + scopeFrame->localVariables[index].pointer = pointer; + + scopeFrame->localVariableCount += 1; +} + +static void AddFunctionArgument(Scope *scope, LLVMValueRef value, char *name) +{ + ScopeFrame *scopeFrame = &scope->scopeStack[scope->scopeStackCount - 1]; + uint32_t index = scopeFrame->argumentCount; + + scopeFrame->arguments = realloc(scopeFrame->arguments, sizeof(FunctionArgument) * (scopeFrame->argumentCount + 1)); + scopeFrame->arguments[index].name = strdup(name); + scopeFrame->arguments[index].value = value; + + scopeFrame->argumentCount += 1; +} + +static LLVMValueRef FindStructFieldPointer(LLVMBuilderRef builder, LLVMValueRef structPointer, char *name) +{ + int32_t i, j; + + LLVMTypeRef structType = LLVMTypeOf(structPointer); + + for (i = 0; i < structTypeFieldDeclarationCount; i += 1) { - if (structFieldMaps[i].structPointer == wStructPointer) + if (structTypeFieldDeclarations[i].structType == structType) { - for (j = 0; j < structFieldMaps[i].fieldCount; j += 1) + for (j = 0; j < structTypeFieldDeclarations[i].fieldCount; j += 1) { - if (structFieldMaps[i].fields[j].needsWrite) + if (strcmp(structTypeFieldDeclarations[i].fields[j].name, name) == 0) { - LLVMBuildStore( + char *ptrName = strdup(name); + strcat(ptrName, "_ptr"); + return LLVMBuildStructGEP( builder, - structFieldMaps[i].fields[j].value, - structFieldMaps[i].fields[j].valuePointer + structPointer, + structTypeFieldDeclarations[i].fields[j].index, + ptrName ); + free(ptrName); } } + } + } - free(structFieldMaps[i].fields); - structFieldMaps[i].fields = NULL; - structFieldMaps[i].fieldCount = 0; + printf("Failed to find struct field pointer!"); + return NULL; +} - break; +static LLVMValueRef FindVariablePointer(char *name) +{ + int32_t i, j; + + for (i = scope->scopeStackCount - 1; i >= 0; i -= 1) + { + for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1) + { + if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0) + { + return scope->scopeStack[i].localVariables[j].pointer; + } + } + } + + printf("Failed to find variable pointer!"); + return NULL; +} + +static LLVMValueRef FindVariableValue(LLVMBuilderRef builder, char *name) +{ + int32_t i, j; + + for (i = scope->scopeStackCount - 1; i >= 0; i -= 1) + { + for (j = 0; j < scope->scopeStack[i].argumentCount; j += 1) + { + if (strcmp(scope->scopeStack[i].arguments[j].name, name) == 0) + { + return scope->scopeStack[i].arguments[j].value; + } + } + + for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1) + { + if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0) + { + return LLVMBuildLoad(builder, scope->scopeStack[i].localVariables[j].pointer, name); + } + } + } + + printf("Failed to find variable value!"); + return NULL; +} + +static void AddStructDeclaration( + LLVMTypeRef wStructType, + Node **fieldDeclarations, + uint32_t fieldDeclarationCount +) { + uint32_t i; + uint32_t index = structTypeFieldDeclarationCount; + structTypeFieldDeclarations = realloc(structTypeFieldDeclarations, sizeof(StructTypeFieldDeclaration) * (structTypeFieldDeclarationCount + 1)); + structTypeFieldDeclarations[index].structType = wStructType; + structTypeFieldDeclarations[index].fields = NULL; + structTypeFieldDeclarations[index].fieldCount = 0; + + for (i = 0; i < fieldDeclarationCount; i += 1) + { + structTypeFieldDeclarations[index].fields = realloc(structTypeFieldDeclarations[index].fields, sizeof(StructTypeField) * (structTypeFieldDeclarations[index].fieldCount + 1)); + structTypeFieldDeclarations[index].fields[i].name = strdup(fieldDeclarations[i]->children[1]->value.string); + structTypeFieldDeclarations[index].fields[i].index = i; + structTypeFieldDeclarations[index].fieldCount += 1; + } + + structTypeFieldDeclarationCount += 1; +} + +static void AddStructVariables( + LLVMBuilderRef builder, + LLVMValueRef structPointer +) { + uint32_t i, j; + + for (i = 0; i < structTypeFieldDeclarationCount; i += 1) + { + if (structTypeFieldDeclarations[i].structType == LLVMTypeOf(structPointer)) + { + for (j = 0; j < structTypeFieldDeclarations[i].fieldCount; j += 1) + { + LLVMValueRef elementPointer = LLVMBuildStructGEP( + builder, + structPointer, + structTypeFieldDeclarations[i].fields[j].index, + structTypeFieldDeclarations[i].fields[j].name + ); + + AddLocalVariable( + scope, + elementPointer, + structTypeFieldDeclarations[i].fields[j].name + ); + } } } } -typedef struct IdentifierMapValue -{ - char *name; - LLVMValueRef value; -} IdentifierMapValue; - -IdentifierMapValue *namedVariables; -uint32_t namedVariableCount; - static LLVMValueRef CompileExpression( LLVMValueRef wStructValue, LLVMBuilderRef builder, @@ -191,43 +275,6 @@ static LLVMValueRef CompileExpression( Node *binaryExpression ); -static void AddNamedVariable(char *name, LLVMValueRef variable) -{ - IdentifierMapValue mapValue; - mapValue.name = name; - mapValue.value = variable; - - namedVariables = realloc(namedVariables, sizeof(IdentifierMapValue) * (namedVariableCount + 1)); - namedVariables[namedVariableCount] = mapValue; - - namedVariableCount += 1; -} - -static LLVMValueRef FindVariableByName(LLVMBuilderRef builder, LLVMValueRef wStructValue, char *name) -{ - uint32_t i, j; - LLVMValueRef searchResult; - - /* first, search scoped vars */ - for (i = 0; i < namedVariableCount; i += 1) - { - if (strcmp(namedVariables[i].name, name) == 0) - { - return namedVariables[i].value; - } - } - - /* if none exist, search struct vars */ - searchResult = CheckStructFieldAndLoad(builder, wStructValue, name); - - if (searchResult == NULL) - { - fprintf(stderr, "Identifier not found!"); - } - - return searchResult; -} - typedef struct CustomTypeMap { LLVMTypeRef type; @@ -312,6 +359,7 @@ static LLVMValueRef CompileBinaryExpression( return NULL; } +/* FIXME THIS IS ALL BROKEN */ static LLVMValueRef CompileFunctionCallExpression( LLVMValueRef wStructValue, LLVMBuilderRef builder, @@ -327,7 +375,33 @@ static LLVMValueRef CompileFunctionCallExpression( args[i] = CompileExpression(wStructValue, builder, function, expression->children[1]->children[i]); } - return LLVMBuildCall(builder, FindVariableByName(builder, wStructValue, expression->children[0]->value.string), args, argumentCount, "tmp"); + //return LLVMBuildCall(builder, FindVariableValueByName(builder, wStructValue, expression->children[0]->value.string), args, argumentCount, "tmp"); + return NULL; +} + +static LLVMValueRef CompileAccessExpressionForStore( + LLVMBuilderRef builder, + LLVMValueRef wStructValue, + LLVMValueRef function, + Node *expression +) { + Node *accessee = expression->children[0]; + Node *accessor = expression->children[1]; + LLVMValueRef accesseeValue = FindVariablePointer(accessee->value.string); + return FindStructFieldPointer(builder, accesseeValue, accessor->value.string); +} + +static LLVMValueRef CompileAccessExpression( + LLVMBuilderRef builder, + LLVMValueRef wStructValue, + LLVMValueRef function, + Node *expression +) { + Node *accessee = expression->children[0]; + Node *accessor = expression->children[1]; + LLVMValueRef accesseeValue = FindVariablePointer(accessee->value.string); + LLVMValueRef access = FindStructFieldPointer(builder, accesseeValue, accessor->value.string); + return LLVMBuildLoad(builder, access, accessor->value.string); } static LLVMValueRef CompileExpression( @@ -340,6 +414,9 @@ static LLVMValueRef CompileExpression( switch (expression->syntaxKind) { + case AccessExpression: + return CompileAccessExpression(builder, wStructValue, function, expression); + case BinaryExpression: return CompileBinaryExpression(wStructValue, builder, function, expression); @@ -347,7 +424,7 @@ static LLVMValueRef CompileExpression( return CompileFunctionCallExpression(wStructValue, builder, function, expression); case Identifier: - return FindVariableByName(builder, wStructValue, expression->value.string); + return FindVariableValue(builder, expression->value.string); case Number: return CompileNumber(expression); @@ -357,9 +434,12 @@ static LLVMValueRef CompileExpression( return NULL; } +/* FIXME: we need a scope structure */ static void CompileReturn(LLVMValueRef wStructValue, LLVMBuilderRef builder, LLVMValueRef function, Node *returnStatemement) { - LLVMBuildRet(builder, CompileExpression(wStructValue, builder, function, returnStatemement->children[0])); + uint32_t i, j; + LLVMValueRef expression = CompileExpression(wStructValue, builder, function, returnStatemement->children[0]); + LLVMBuildRet(builder, expression); } static void CompileReturnVoid(LLVMBuilderRef builder) @@ -371,9 +451,17 @@ static void CompileAssignment(LLVMValueRef wStructValue, LLVMBuilderRef builder, { LLVMValueRef fieldPointer; LLVMValueRef result = CompileExpression(wStructValue, builder, function, assignmentStatement->children[1]); - LLVMValueRef identifier = CompileExpression(wStructValue, builder, function, assignmentStatement->children[0]); + LLVMValueRef identifier; + if (assignmentStatement->children[0]->syntaxKind == AccessExpression) + { + identifier = CompileAccessExpressionForStore(builder, wStructValue, function, assignmentStatement->children[0]); + } + else if (assignmentStatement->children[0]->syntaxKind == Identifier) + { + identifier = FindVariablePointer(assignmentStatement->children[0]->value.string); + } - MarkStructFieldForWrite(wStructValue, identifier); + LLVMBuildStore(builder, result, identifier); } static void CompileFunctionVariableDeclaration(LLVMBuilderRef builder, Node *variableDeclaration) @@ -390,7 +478,7 @@ static void CompileFunctionVariableDeclaration(LLVMBuilderRef builder, Node *var variable = LLVMBuildAlloca(builder, WraithTypeToLLVMType(variableDeclaration->children[0]->type), variableName); } - AddNamedVariable(variableName, variable); + AddLocalVariable(scope, variable, variableName); } static uint8_t CompileStatement(LLVMValueRef wStructValue, LLVMBuilderRef builder, LLVMValueRef function, Node *statement) @@ -432,6 +520,8 @@ static void CompileFunction( uint32_t argumentCount = functionSignature->children[2]->childCount + 1; /* struct is implicit argument */ LLVMTypeRef paramTypes[argumentCount]; + PushScopeFrame(scope); + paramTypes[0] = wStructPointerType; for (i = 0; i < functionSignature->children[2]->childCount; i += 1) @@ -443,25 +533,19 @@ static void CompileFunction( LLVMTypeRef functionType = LLVMFunctionType(returnType, paramTypes, argumentCount, 0); LLVMValueRef function = LLVMAddFunction(module, functionSignature->children[0]->value.string, functionType); + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + LLVMValueRef wStructPointer = LLVMGetParam(function, 0); + AddStructVariables(builder, wStructPointer); + for (i = 0; i < functionSignature->children[2]->childCount; i += 1) { LLVMValueRef argument = LLVMGetParam(function, i + 1); - AddNamedVariable(functionSignature->children[2]->children[i]->children[1]->value.string, argument); - } - - LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); - - LLVMBuilderRef builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, entry); - - /* FIXME: replace this with a scope abstraction */ - AddStruct(wStructPointer); - - for (i = 0; i < fieldDeclarationCount; i += 1) - { - AddStructFieldName(builder, wStructPointer, fieldDeclarations[i]->children[1]->value.string, i); + LLVMValueRef argumentCopy = LLVMBuildAlloca(builder, LLVMTypeOf(argument), functionSignature->children[2]->children[i]->children[1]->value.string); + AddLocalVariable(scope, argumentCopy, functionSignature->children[2]->children[i]->children[1]->value.string); } for (i = 0; i < functionBody->childCount; i += 1) @@ -469,8 +553,6 @@ static void CompileFunction( hasReturn |= CompileStatement(wStructPointer, builder, function, functionBody->children[i]); } - RemoveStruct(builder, wStructPointer); - if (LLVMGetTypeKind(returnType) == LLVMVoidTypeKind && !hasReturn) { LLVMBuildRetVoid(builder); @@ -479,6 +561,8 @@ static void CompileFunction( { fprintf(stderr, "Return statement not provided!"); } + + PopScopeFrame(scope); } static void CompileStruct(LLVMModuleRef module, LLVMContextRef context, Node *node) @@ -491,6 +575,8 @@ static void CompileStruct(LLVMModuleRef module, LLVMContextRef context, Node *no Node *currentDeclarationNode; Node *fieldDeclarations[declarationCount]; + PushScopeFrame(scope); + LLVMTypeRef wStruct = LLVMStructCreateNamed(context, node->children[0]->value.string); LLVMTypeRef wStructPointerType = LLVMPointerType(wStruct, 0); /* FIXME: is this address space correct? */ @@ -510,6 +596,8 @@ static void CompileStruct(LLVMModuleRef module, LLVMContextRef context, Node *no } LLVMStructSetBody(wStruct, types, fieldCount, packed); + AddStructDeclaration(wStructPointerType, fieldDeclarations, fieldCount); + RegisterCustomType(wStruct, node->children[0]->value.string); /* now we can wire up the functions */ for (i = 0; i < declarationCount; i += 1) @@ -524,7 +612,7 @@ static void CompileStruct(LLVMModuleRef module, LLVMContextRef context, Node *no } } - RegisterCustomType(wStruct, node->children[0]->value.string); + PopScopeFrame(scope); } static void Compile(LLVMModuleRef module, LLVMContextRef context, Node *node) @@ -552,11 +640,10 @@ int main(int argc, char *argv[]) return 1; } - namedVariables = NULL; - namedVariableCount = 0; + scope = CreateScope(); - structFieldMaps = NULL; - structFieldMapCount = 0; + structTypeFieldDeclarations = NULL; + structTypeFieldDeclarationCount = 0; customTypes = NULL; customTypeCount = 0; diff --git a/wraith.y b/wraith.y index d2a0b17..0cec2a5 100644 --- a/wraith.y +++ b/wraith.y @@ -115,8 +115,16 @@ Identifier : ID $$ = MakeIdentifierNode(yytext); } -PrimaryExpression : Identifier - | NUMBER +AccessExpression : Identifier POINT AccessExpression + { + $$ = MakeAccessExpressionNode($1, $3); + } + | Identifier + { + $$ = $1; + } + +PrimaryExpression : NUMBER { $$ = MakeNumberNode(yytext); } @@ -129,6 +137,7 @@ PrimaryExpression : Identifier $$ = $2; } | FunctionCallExpression + | AccessExpression ; UnaryExpression : BANG Expression @@ -164,6 +173,10 @@ VariableDeclaration : Type Identifier } AssignmentStatement : VariableDeclaration EQUAL Expression + { + $$ = MakeAssignmentNode($1, $3); + } + | AccessExpression EQUAL Expression { $$ = MakeAssignmentNode($1, $3); }