/// <summary> /// Checks if the variable already exists. This does not allow for shadowing of variables, maybe as an /// enhancement, cause it wouldn't be that hard. /// /// Cflat also allows for declarations and assignments on the same line, so this will process the InitialValue sub tree /// as well. /// </summary> /// <param name="n"></param> public override void VisitDeclLocal(ASTDeclarationLocal n) { if (!_scopeMgr.HasSymbol(n.ID)) { CFlatType lhs = CheckSubTree(n.Type); //Check if the code is also assigning a value on the same line bool valid = true; if (n.InitialValue != null) { CFlatType rhs = CheckSubTree(n.InitialValue); if (rhs is TypeFunction && ((TypeFunction)rhs).IsConstructor) { rhs = new TypeClass(((TypeFunction)rhs).Name); } if (!IsValidAssignment(lhs, rhs)) { valid = false; ReportError(n.Location, "Invalid assignment, type mismatch. Expected: {0} Got: {1}", TypeToFriendlyName(lhs), TypeToFriendlyName(rhs)); } } if (valid) { _scopeMgr.AddLocal(n.ID, lhs, _currentMethod); } } else { ReportError(n.Location, "The identifier '{0}' already exists", n.ID); } }
public override void VisitDeclLocal(ASTDeclarationLocal n) { //Get type n.Type.Visit(this); LocalBuilder builder = _gen.DeclareLocal(_lastWalkedType); //keep track of the LocalBuilder LocalBuilderInfo info = _currentMethodBuilder.AddLocal(n.ID, builder); //set value if needed if (n.InitialValue != null) { n.InitialValue.Visit(this); //store it to the local _gen.Emit(OpCodes.Stloc, info.Index); } }