public override void GenerateCode(ILCodeGenerator cg) { LValue.LoadVariableInTheStack = false; LValue.GenerateCode(cg); LValue.LoadVariableInTheStack = true; //generamos Expression Expression.GenerateCode(cg); if (LValue is LValueIdNode) { LValueIdNode id = LValue as LValueIdNode; ILElementInfo ile = cg.ILContextTable.GetDefinedVarOrFunction(id.VariableName); if (!Object.Equals(ile.FieldBuilder, null)) { cg.ILGenerator.Emit(OpCodes.Stsfld, ile.FieldBuilder); } else if (!Object.Equals(ile.LocalBuilder, null)) { cg.ILGenerator.Emit(OpCodes.Stloc, ile.LocalBuilder); } } else if (LValue is ArrayIndexAccessNode) { ArrayIndexAccessNode arrayElement = LValue as ArrayIndexAccessNode; cg.ILGenerator.Emit(OpCodes.Stelem, arrayElement.NodeInfo.Type.ILType); } else { RecordDotAccessNode recordAccess = (LValue as RecordDotAccessNode); ILElementInfo ile = cg.ILContextTable.GetDefinedType(recordAccess.RecordName); FieldInfo fi = ile.TypeBuilder.GetField(recordAccess.ID); cg.ILGenerator.Emit(OpCodes.Stfld, fi); } }
public override void CheckSemantic(SymbolTable symbolTable, List <CompileError> errors) { ///chequeamos la semántica del LValue LValue.CheckSemantic(symbolTable, errors); ///chequeamos la semántica de la Expression Expression.CheckSemantic(symbolTable, errors); ///si LValue o Expression evalúan de error este evalua de error if (Object.Equals(LValue.NodeInfo, SemanticInfo.SemanticError) || Object.Equals(Expression.NodeInfo, SemanticInfo.SemanticError)) { ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; return; } ///si Expression no evaluó de error if (!Object.Equals(Expression.NodeInfo, SemanticInfo.SemanticError)) { //Expression debe retornar valor if (Expression.NodeInfo.BuiltInType.IsCompatibleWith(BuiltInType.Void)) { errors.Add(new CompileError { Line = Expression.Line, Column = Expression.CharPositionInLine, ErrorMessage = "Assignation expression must return value", Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } //si LValue no evaluó de error if (!Object.Equals(LValue.NodeInfo, SemanticInfo.SemanticError)) { //el tipo de Expresion y del LValue tienen que ser compatibles if (!LValue.NodeInfo.Type.IsCompatibleWith(Expression.NodeInfo.Type)) { errors.Add(new CompileError { Line = Expression.Line, Column = Expression.CharPositionInLine, ErrorMessage = string.Format("Cannot implicitly convert type '{0}' to '{1}'", Expression.NodeInfo.Type.Name, LValue.NodeInfo.Type.Name), Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///si es solamente un id if (LValue is LValueIdNode) { SemanticInfo variable; LValueIdNode lvalueId = LValue as LValueIdNode; if (symbolTable.GetDefinedVariableDeep(lvalueId.VariableName, out variable) && variable.IsReadOnly) { //no podemos modificar una variable readonly(en nuestro caso la de un for) errors.Add(new CompileError { Line = LValue.Line, Column = LValue.CharPositionInLine, ErrorMessage = "A readonly field cannot be assigned to", Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } } } ///el lvalue solo puede ser una variable, el campo de un record o el elemento de un array if (!IsLValueAssignable()) { errors.Add(new CompileError { Line = LValue.Line, Column = LValue.CharPositionInLine, ErrorMessage = "The left-hand side of an assignment must be a variable, field or indexer", Kind = ErrorKind.Semantic }); ///el nodo evalúa de error NodeInfo = SemanticInfo.SemanticError; } ///seteamos los campos necesarios if (!Object.Equals(NodeInfo, SemanticInfo.SemanticError)) { NodeInfo.Type = SemanticInfo.Void; NodeInfo.BuiltInType = BuiltInType.Void; NodeInfo.ILType = Expression.NodeInfo.ILType; } }