public override void EnterLocalVariableDeclaration([NotNull] NovaParser.LocalVariableDeclarationContext context) { VariableDeclaratorContext declarator = context.variableDeclarator(); string type = context.typeType().GetChild(0).GetText(); string name = declarator.variableDeclaratorId().GetText(); DeclarationStatement statement = new DeclarationStatement(Parent, context); Variable variable = new Variable(name, type, context.variableDeclarator()); ExpressionNode value = new ExpressionNode(statement); VariableInitializerContext initializer = declarator.variableInitializer(); if (initializer != null) { ExpressionContext expressionContext = initializer.expression(); ExpressionListener listener = new ExpressionListener(statement); expressionContext.EnterRule(listener); value = listener.GetResult(); } statement.Variable = variable; statement.Value = value; Result.Add(statement); }
public void VisitDeclarationStatement(DeclarationStatement node) { foreach (var declaration in node.Declarations) { declaration.Accept(this); } }
public void Visit(DeclarationStatement expressionNode) { foreach (var decl in expressionNode.Declarations) { decl.Accept(this); } }
public override void Switch(IAstTransformer transformer, out Node resultingNode) { DeclarationStatement thisNode = (DeclarationStatement)this; Statement resultingTypedNode = thisNode; transformer.OnDeclarationStatement(thisNode, ref resultingTypedNode); resultingNode = resultingTypedNode; }
static Statement() { Declaration = new DeclarationStatement(); Jump = new JumpStatement(); Selection = new SelectionStatement(); Iteration = new IterationStatement(); Expression = new ExpressionStatement(); }
public void Visit(DeclarationStatement expressionNode) { foreach (var d in expressionNode.Declarations) { CurrentSymbolTable.AnnotateTypedSymbol(d.Reference, expressionNode.Type); d.Initialization?.Accept(this); } }
private void GenerateDeclaration(DeclarationStatement declaration, StringBuilder programBuilder) { var declarationType = declaration.GetType(); if (declaration is FunctionDeclaration) { GenerateFunction(declaration as FunctionDeclaration, programBuilder); } }
//if(st is AliasStatement) { // Console.WriteLine("is AliasStatement"); // return; // } else if(st is BreakStatement) { // Console.WriteLine("is BreakStatement"); // return; // } else if(st is ContinueStatement) { // Console.WriteLine("is ContinueStatement"); // return; // } else if(st is ExternStatement) { // Console.WriteLine("is ExternStatement"); // return; // } else if(st is GotoStatement) { // Console.WriteLine("is GotoStatement"); // return; // } else if(st is ImportStatement) { // Console.WriteLine("is ImportStatement"); // return; // } else if(st is LabelStatement) { // Console.WriteLine("is LabelStatement"); // return; // } else if(st is ThrowStatement) { // Console.WriteLine("is VariableDeclaration"); // return; // } else { // if(!st.GetType().IsSubclassOf(typeof(Statement))) { // VisitOtherStmt(st); // } // return; // } /// <summary> /// Stores the local defined variable's info and updates if it has been initialized /// </summary> /// <param name="dst"></param> private void AnalyzeDeclarationStatement(DeclarationStatement dst) { //from child in dst.GetDescendantsAndSelf() var allDeclarations = from expression in dst.FindExpressions <VariableDeclaration>(true) select expression; foreach (var vd in allDeclarations) { UpdateByExpression(vd); } }
public override void OnDeclarationStatement(DeclarationStatement node) { Write(Indent()); Visit(node.Declaration); if (node.Initializer != null) { Write(" = "); Visit(node.Initializer); } WriteLine(";"); }
override public void OnDeclarationStatement(DeclarationStatement d) { WriteIndented(); Visit(d.Declaration); if (null != d.Initializer) { WriteOperator(" = "); Visit(d.Initializer); } WriteLine(); }
public override void OnDeclarationStatement(DeclarationStatement node) { if (node.Declaration.Type != null && !SearchField(node.Declaration.Name)) { TypeReference initializerType = GetInferredType(node.Initializer); if (node.Declaration.Type.Matches(initializerType)) { node.Declaration.Type = null; } } base.OnDeclarationStatement(node); }
public override void OnDeclarationStatement(DeclarationStatement node) { CodeVariableDeclarationStatement var = new CodeVariableDeclarationStatement(ConvTypeRef(node.Declaration.Type), node.Declaration.Name); if (node.Initializer != null) { _expression = null; node.Initializer.Accept(this); var.InitExpression = _expression; } _statements.Add(var); }
public override void LeaveDeclarationStatement(DeclarationStatement node) { if (node.Declaration.Type != null) { Expression initializer = node.Initializer; if (initializer is TryCastExpression) { TryCastExpression tryCastExpression = (TryCastExpression)initializer; Expression target = tryCastExpression.Target; TypeReference type = tryCastExpression.Type; node.Initializer = target; } } }
static void ReplaceWithInitializer(DeclarationStatement decl) { if (decl.Initializer == null) { decl.ReplaceBy(null); } else { ExpressionStatement statement = new ExpressionStatement(decl.LexicalInfo); statement.Expression = new BinaryExpression(decl.LexicalInfo, BinaryOperatorType.Assign, new ReferenceExpression(decl.Declaration.LexicalInfo, decl.Declaration.Name), decl.Initializer); decl.ReplaceBy(statement); } }
private IStatement DeclarationStatement() { DeclarationStatement varDecl = VariableDeclaration(); if (varDecl != null) { return(varDecl); } Procedure procDecl = ProcedureStatement(); if (procDecl != null) { return(procDecl); } return(ReadFunction()); }
public static void RenameLocals(Block block, StringComparer nameComparer) { FindVariableDeclarationsVisitor fvdv = new FindVariableDeclarationsVisitor(); block.Accept(fvdv); List <DeclarationStatement> list = new List <DeclarationStatement>(); foreach (DeclarationStatement decl in fvdv.Declarations) { DeclarationStatement conflict = null; int conflictIndex = -1; for (int i = 0; i < list.Count; i++) { if (nameComparer.Equals(list[i].Declaration.Name, decl.Declaration.Name)) { conflict = list[i]; conflictIndex = i; break; } } if (conflict == null) { list.Add(decl); } else { // Handle conflict: try if "moveup" would be sufficient if (IsSameType(decl.Declaration.Type, conflict.Declaration.Type, nameComparer)) { // create declaration at beginning of class and // replace decl & conflict by assignment DeclarationStatement newDecl = new DeclarationStatement(conflict.LexicalInfo); newDecl.Declaration = new Declaration(conflict.Declaration.LexicalInfo, conflict.Declaration.Name, conflict.Declaration.Type); block.Insert(0, newDecl); ReplaceWithInitializer(decl); ReplaceWithInitializer(conflict); list[conflictIndex] = newDecl; } else { string newName = FindFreeName(decl.Declaration.Name, list, fvdv.Declarations, nameComparer); decl.ParentNode.Accept(new RenameLocalsVisitor(decl.Declaration.Name, newName, nameComparer)); decl.Declaration.Name = newName; } } } }
public override void OnDeclarationStatement(DeclarationStatement node) { if (!node.ContainsAnnotation("PrivateScope")) { Field field; Field field1 = field = new Field(LexicalInfo.Empty); int num1 = (int)(field.Modifiers = TypeMemberModifiers.Public); string text1 = field.Name = "$"; TypeReference reference1 = field.Type = TypeReference.Lift(node.Declaration.Type); Expression expression1 = field.Initializer = Expression.Lift(node.Initializer); int num2 = (int)(field.IsVolatile = false); string text2 = field.Name = CodeSerializer.LiftName(node.Declaration.Name); Field item = field; item.LexicalInfo = node.LexicalInfo; this._class.Members.Add(item); this.RemoveCurrentNode(); } }
public override void OnBlock(Block node) { try { if (node.Statements.Count == 0 || node.Statements[0].NodeType != NodeType.Block) { return; } var innerBlock = (Block)node.Statements[0]; ExpressionStatement firstStatement; if (!IsSwitchStatementWithOnlyDefault(innerBlock, out firstStatement)) { return; } var binaryExp = (BinaryExpression)firstStatement.Expression; if (binaryExp.Operator != BinaryOperatorType.Assign || binaryExp.Left.NodeType != NodeType.ReferenceExpression || !binaryExp.Left.ToCodeString().Contains("$switch$")) { return; } var originalLocal = ((InternalLocal)binaryExp.Left.Entity).Local; var varName = originalLocal.Name.Replace("$", "_"); var local = new Local(varName, true); var internalLocal = new InternalLocal(local, binaryExp.ExpressionType); local.Entity = internalLocal; internalLocal.OriginalDeclaration = new Declaration(varName, CodeBuilder.CreateTypeReference(internalLocal.Type)); // we need a DeclarationStatment as the parent of the "OriginalDeclaration" var ds = new DeclarationStatement(internalLocal.OriginalDeclaration, binaryExp.Right); innerBlock.Statements.RemoveAt(0); var parentMethod = node.GetAncestor <Method>(); parentMethod.Locals.Replace(originalLocal, internalLocal.Local); } finally { base.OnBlock(node); } }
private IType GetTypeFromDeclarationContext() { TypeReference tr = null; DeclarationStatement ds = _parent as DeclarationStatement; if (ds != null) { tr = ds.Declaration.Type; } Field fd = _parent as Field; if (fd != null) { tr = fd.Type; } if (tr != null) { return(tr.Entity as IType); } return(null); }
public override void visit_declaration_statement(DeclarationStatement stmt) { stmt.accept_children(this); if (unreachable(stmt)) { stmt.declaration.unreachable = true; return; } if (!stmt.declaration.used) { Report.warning(stmt.declaration.source_reference, "local variable `%s' declared but never used".printf(stmt.declaration.name)); } current_block.add_node(stmt); var local = stmt.declaration as LocalVariable; if (local != null && local.initializer != null) { handle_errors(local.initializer); } }
IStatement Statement(bool BlocksAllowed = true, bool EmptyAllowed = true, IBlockNode Scope = null, IStatement Parent=null) { if (EmptyAllowed && laKind == Semicolon) { LastParsedObject = null; Step(); return null; } if (BlocksAllowed && laKind == OpenCurlyBrace) return BlockStatement(Scope,Parent); #region LabeledStatement (loc:... goto loc;) if (laKind == Identifier && Lexer.CurrentPeekToken.Kind == Colon) { Step(); var ret = new LabeledStatement() { Location = t.Location, Identifier = t.Value, Parent = Parent }; LastParsedObject = ret; Step(); ret.EndLocation = t.EndLocation; return ret; } #endregion #region IfStatement else if (laKind == (If) || (laKind == Static && Lexer.CurrentPeekToken.Kind == If)) { bool isStatic = laKind == Static; if (isStatic) Step(); Step(); var dbs = new IfStatement() { Location = t.Location, IsStatic = isStatic, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // IfCondition IfCondition(dbs); // ThenStatement if(Expect(CloseParenthesis)) dbs.ThenStatement = Statement(Scope: Scope, Parent: dbs); // ElseStatement if (laKind == (Else)) { Step(); dbs.ElseStatement = Statement(Scope: Scope, Parent: dbs); } dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region WhileStatement else if (laKind == While) { Step(); var dbs = new WhileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region DoStatement else if (laKind == (Do)) { Step(); var dbs = new WhileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); Expect(While); Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region ForStatement else if (laKind == (For)) { Step(); var dbs = new ForStatement { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // Initialize if (laKind != Semicolon) dbs.Initialize = Statement(false, Scope: Scope, Parent: dbs); // Against the D language theory, blocks aren't allowed here! else Step(); // Enforce a trailing semi-colon only if there hasn't been an expression (the ; gets already skipped in there) // Expect(Semicolon); // Test if (laKind != (Semicolon)) dbs.Test = Expression(Scope); Expect(Semicolon); // Increment if (laKind != (CloseParenthesis)) dbs.Increment = Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region ForeachStatement else if (laKind == Foreach || laKind == Foreach_Reverse) return ForeachStatement(Scope, Parent); #endregion #region [Final] SwitchStatement else if ((laKind == (Final) && Lexer.CurrentPeekToken.Kind == (Switch)) || laKind == (Switch)) { var dbs = new SwitchStatement { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (Final)) { dbs.IsFinal = true; Step(); } Step(); Expect(OpenParenthesis); dbs.SwitchExpression = Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region CaseStatement else if (laKind == (Case)) { Step(); var dbs = new SwitchStatement.CaseStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ArgumentList = Expression(Scope); Expect(Colon); // CaseRangeStatement if (laKind == DoubleDot) { Step(); Expect(Case); dbs.LastExpression = AssignExpression(); Expect(Colon); } var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Default else if (laKind == (Default)) { Step(); var dbs = new SwitchStatement.DefaultStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; Expect(Colon); var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Continue | Break else if (laKind == (Continue)) { Step(); var s = new ContinueStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } else if (laKind == (Break)) { Step(); var s = new BreakStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region Return else if (laKind == (Return)) { Step(); var s = new ReturnStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind != (Semicolon)) s.ReturnExpression = Expression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region Goto else if (laKind == (Goto)) { Step(); var s = new GotoStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Identifier; s.LabelIdentifier = t.Value; } else if (laKind == Default) { Step(); s.StmtType = GotoStatement.GotoStmtType.Default; } else if (laKind == (Case)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Case; if (laKind != (Semicolon)) s.CaseExpression = Expression(Scope); } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region WithStatement else if (laKind == (With)) { Step(); var dbs = new WithStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // Symbol dbs.WithExpression = Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region SynchronizedStatement else if (laKind == (Synchronized)) { Step(); var dbs = new SynchronizedStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (OpenParenthesis)) { Step(); dbs.SyncExpression = Expression(Scope); Expect(CloseParenthesis); } dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region TryStatement else if (laKind == (Try)) { Step(); var s = new TryStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope, Parent: s); if (!(laKind == (Catch) || laKind == (Finally))) SemErr(Catch, "At least one catch or a finally block expected!"); var catches = new List<TryStatement.CatchStatement>(); // Catches while (laKind == (Catch)) { Step(); var c = new TryStatement.CatchStatement() { Location = t.Location, Parent = s }; LastParsedObject = c; // CatchParameter if (laKind == (OpenParenthesis)) { Step(); if (laKind == CloseParenthesis) { SemErr(CloseParenthesis, "Catch parameter expected, not ')'"); Step(); } else { var catchVar = new DVariable(); LastParsedObject = catchVar; var tt = la; //TODO? catchVar.Type = BasicType(); if (laKind != Identifier) { la = tt; catchVar.Type = new IdentifierDeclaration("Exception"); } Expect(Identifier); catchVar.Name = t.Value; Expect(CloseParenthesis); c.CatchParameter = catchVar; } } c.ScopedStatement = Statement(Scope: Scope, Parent: c); c.EndLocation = t.EndLocation; catches.Add(c); } if (catches.Count > 0) s.Catches = catches.ToArray(); if (laKind == (Finally)) { Step(); var f = new TryStatement.FinallyStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = f; f.ScopedStatement = Statement(); f.EndLocation = t.EndLocation; s.FinallyStmt = f; } s.EndLocation = t.EndLocation; return s; } #endregion #region ThrowStatement else if (laKind == (Throw)) { Step(); var s = new ThrowStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ThrowExpression = Expression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region ScopeGuardStatement else if (laKind == DTokens.Scope) { Step(); if (laKind == OpenParenthesis) { var s = new ScopeGuardStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; Step(); if (Expect(Identifier) && t.Value != null) // exit, failure, success s.GuardedScope = t.Value.ToLower(); if (Expect(CloseParenthesis)) TrackerVariables.ExpectingIdentifier = false; if (!IsEOF) s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } else PushAttribute(new DAttribute(DTokens.Scope), false); } #endregion #region AsmStmt else if (laKind == Asm) return AsmStatement(Parent); #endregion #region PragmaStatement else if (laKind == (Pragma)) { var s = new PragmaStatement { Location = la.Location }; s.Pragma = _Pragma(); s.Parent = Parent; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion #region MixinStatement //TODO: Handle this one in terms of adding it to the node structure else if (laKind == (Mixin)) { if (Peek(1).Kind == OpenParenthesis) return MixinDeclaration(); else return TemplateMixin(); } #endregion #region Conditions if (laKind == Debug) return DebugStatement(Scope, Parent); if (laKind == Version) return VersionStatement(Scope, Parent); #endregion #region (Static) AssertExpression else if (laKind == Assert || (laKind == Static && PK(Assert))) { var s = new AssertStatement() { Location = la.Location, IsStatic = laKind == Static, Parent = Parent }; LastParsedObject = s; if (s.IsStatic) Step(); Step(); if (Expect(OpenParenthesis)) { s.AssertedExpression = Expression(Scope); Expect(CloseParenthesis); Expect(Semicolon); } s.EndLocation = t.EndLocation; return s; } #endregion #region D1: VolatileStatement else if (laKind == Volatile) { Step(); var s = new VolatileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion // ImportDeclaration else if (laKind == Import) return ImportDeclaration(); else if (!(ClassLike[laKind] || BasicTypes[laKind] || laKind == Enum || Modifiers[laKind] || laKind == PropertyAttribute || laKind == Alias || laKind == Typedef) && IsAssignExpression()) { var s = new ExpressionStatement() { Location = la.Location, Parent = Parent }; if (!IsEOF) LastParsedObject = s; // a==b, a=9; is possible -> Expressions can be there, not only single AssignExpressions! s.Expression = Expression(Scope); if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } else { var s = new DeclarationStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = s; s.Declarations = Declaration(Scope); s.EndLocation = t.EndLocation; return s; } }
public override void Visit(DeclarationStatement s) { base.Visit(s); //FixStatementIndentation(s.Location); FixSemicolon(s.EndLocation); }
/// <inheritdoc /> public override void Visit(DeclarationStatement declarationStatement) { WriteLinkLine(declarationStatement); VisitDynamic(declarationStatement.Content); }
public IStatement Statement(bool BlocksAllowed = true, bool EmptyAllowed = true, IBlockNode Scope = null, IStatement Parent=null) { switch (laKind) { case Semicolon: if (!EmptyAllowed) goto default; Step(); return null; case OpenCurlyBrace: if (!BlocksAllowed) goto default; return BlockStatement(Scope,Parent); // LabeledStatement (loc:... goto loc;) case Identifier: if (Lexer.CurrentPeekToken.Kind != Colon) goto default; Step(); var ls = new LabeledStatement() { Location = t.Location, Identifier = t.Value, Parent = Parent }; Step(); ls.EndLocation = t.EndLocation; return ls; // IfStatement case If: Step(); var iS = new IfStatement{ Location = t.Location, Parent = Parent }; Expect(OpenParenthesis); // IfCondition IfCondition(iS); // ThenStatement if(Expect(CloseParenthesis)) iS.ThenStatement = Statement(Scope: Scope, Parent: iS); // ElseStatement if (laKind == (Else)) { Step(); iS.ElseStatement = Statement(Scope: Scope, Parent: iS); } if(t != null) iS.EndLocation = t.EndLocation; return iS; // Conditions case Version: case Debug: return StmtCondition(Parent, Scope); case Static: if (Lexer.CurrentPeekToken.Kind == If) return StmtCondition(Parent, Scope); else if (Lexer.CurrentPeekToken.Kind == Assert) goto case Assert; else if (Lexer.CurrentPeekToken.Kind == Import) goto case Import; goto default; case For: return ForStatement(Scope, Parent); case Foreach: case Foreach_Reverse: return ForeachStatement(Scope, Parent); case While: Step(); var ws = new WhileStatement() { Location = t.Location, Parent = Parent }; Expect(OpenParenthesis); ws.Condition = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) { ws.ScopedStatement = Statement(Scope: Scope, Parent: ws); ws.EndLocation = t.EndLocation; } return ws; case Do: Step(); var dws = new WhileStatement() { Location = t.Location, Parent = Parent }; if(!IsEOF) dws.ScopedStatement = Statement(true, false, Scope, dws); if(Expect(While) && Expect(OpenParenthesis)) { dws.Condition = Expression(Scope); Expect(CloseParenthesis); Expect(Semicolon); dws.EndLocation = t.EndLocation; } return dws; // [Final] SwitchStatement case Final: if (Lexer.CurrentPeekToken.Kind != Switch) goto default; goto case Switch; case Switch: var ss = new SwitchStatement { Location = la.Location, Parent = Parent }; if (laKind == (Final)) { ss.IsFinal = true; Step(); } Step(); Expect(OpenParenthesis); ss.SwitchExpression = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) ss.ScopedStatement = Statement(Scope: Scope, Parent: ss); ss.EndLocation = t.EndLocation; return ss; case Case: Step(); var sscs = new SwitchStatement.CaseStatement() { Location = la.Location, Parent = Parent }; sscs.ArgumentList = Expression(Scope); Expect(Colon); // CaseRangeStatement if (laKind == DoubleDot) { Step(); Expect(Case); sscs.LastExpression = AssignExpression(); Expect(Colon); } var sscssl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: sscs); if (stmt != null) { stmt.Parent = sscs; sscssl.Add(stmt); } } sscs.ScopeStatementList = sscssl.ToArray(); sscs.EndLocation = t.EndLocation; return sscs; case Default: Step(); var ssds = new SwitchStatement.DefaultStatement() { Location = la.Location, Parent = Parent }; Expect(Colon); var ssdssl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: ssds); if (stmt != null) { stmt.Parent = ssds; ssdssl.Add(stmt); } } ssds.ScopeStatementList = ssdssl.ToArray(); ssds.EndLocation = t.EndLocation; return ssds; case Continue: Step(); var cs = new ContinueStatement() { Location = t.Location, Parent = Parent }; if (laKind == (Identifier)) { Step(); cs.Identifier = t.Value; } else if(IsEOF) cs.IdentifierHash = DTokens.IncompleteIdHash; Expect(Semicolon); cs.EndLocation = t.EndLocation; return cs; case Break: Step(); var bs = new BreakStatement() { Location = t.Location, Parent = Parent }; if (laKind == (Identifier)) { Step(); bs.Identifier = t.Value; } else if(IsEOF) bs.IdentifierHash = DTokens.IncompleteIdHash; Expect(Semicolon); bs.EndLocation = t.EndLocation; return bs; case Return: Step(); var rs = new ReturnStatement() { Location = t.Location, Parent = Parent }; if (laKind != (Semicolon)) rs.ReturnExpression = Expression(Scope); Expect(Semicolon); rs.EndLocation = t.EndLocation; return rs; case Goto: Step(); var gs = new GotoStatement() { Location = t.Location, Parent = Parent }; switch(laKind) { case Identifier: Step(); gs.StmtType = GotoStatement.GotoStmtType.Identifier; gs.LabelIdentifier = t.Value; break; case Default: Step(); gs.StmtType = GotoStatement.GotoStmtType.Default; break; case Case: Step(); gs.StmtType = GotoStatement.GotoStmtType.Case; if (laKind != (Semicolon)) gs.CaseExpression = Expression(Scope); break; default: if (IsEOF) gs.LabelIdentifierHash = DTokens.IncompleteIdHash; break; } Expect(Semicolon); gs.EndLocation = t.EndLocation; return gs; case With: Step(); var wS = new WithStatement() { Location = t.Location, Parent = Parent }; if(Expect(OpenParenthesis)) { // Symbol wS.WithExpression = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) wS.ScopedStatement = Statement(Scope: Scope, Parent: wS); } wS.EndLocation = t.EndLocation; return wS; case Synchronized: Step(); var syncS = new SynchronizedStatement() { Location = t.Location, Parent = Parent }; if (laKind == (OpenParenthesis)) { Step(); syncS.SyncExpression = Expression(Scope); Expect(CloseParenthesis); } if(!IsEOF) syncS.ScopedStatement = Statement(Scope: Scope, Parent: syncS); syncS.EndLocation = t.EndLocation; return syncS; case Try: Step(); var ts = new TryStatement() { Location = t.Location, Parent = Parent }; ts.ScopedStatement = Statement(Scope: Scope, Parent: ts); if (!(laKind == (Catch) || laKind == (Finally))) SemErr(Catch, "At least one catch or a finally block expected!"); var catches = new List<TryStatement.CatchStatement>(); // Catches while (laKind == (Catch)) { Step(); var c = new TryStatement.CatchStatement() { Location = t.Location, Parent = ts }; // CatchParameter if (laKind == (OpenParenthesis)) { Step(); if (laKind == CloseParenthesis || IsEOF) { SemErr(CloseParenthesis, "Catch parameter expected, not ')'"); Step(); } else { var catchVar = new DVariable { Parent = Scope, Location = t.Location }; Lexer.PushLookAheadBackup(); catchVar.Type = BasicType(); if (laKind == CloseParenthesis) { Lexer.RestoreLookAheadBackup(); catchVar.Type = new IdentifierDeclaration("Exception"); } else Lexer.PopLookAheadBackup(); if (Expect(Identifier)) { catchVar.Name = t.Value; catchVar.NameLocation = t.Location; Expect(CloseParenthesis); } else if(IsEOF) catchVar.NameHash = DTokens.IncompleteIdHash; catchVar.EndLocation = t.EndLocation; c.CatchParameter = catchVar; } } if(!IsEOF) c.ScopedStatement = Statement(Scope: Scope, Parent: c); c.EndLocation = t.EndLocation; catches.Add(c); } if (catches.Count > 0) ts.Catches = catches.ToArray(); if (laKind == (Finally)) { Step(); var f = new TryStatement.FinallyStatement() { Location = t.Location, Parent = Parent }; f.ScopedStatement = Statement(); f.EndLocation = t.EndLocation; ts.FinallyStmt = f; } ts.EndLocation = t.EndLocation; return ts; case Throw: Step(); var ths = new ThrowStatement() { Location = t.Location, Parent = Parent }; ths.ThrowExpression = Expression(Scope); Expect(Semicolon); ths.EndLocation = t.EndLocation; return ths; case DTokens.Scope: Step(); if (laKind == OpenParenthesis) { var s = new ScopeGuardStatement() { Location = t.Location, Parent = Parent }; Step(); if (Expect(Identifier) && t.Value != null) // exit, failure, success s.GuardedScope = t.Value.ToLower(); else if (IsEOF) s.GuardedScope = DTokens.IncompleteId; Expect(CloseParenthesis); s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } else PushAttribute(new Modifier(DTokens.Scope), false); goto default; case Asm: return ParseAsmStatement(Scope, Parent); case Pragma: var ps = new PragmaStatement { Location = la.Location }; ps.Pragma = _Pragma(); ps.Parent = Parent; ps.ScopedStatement = Statement(Scope: Scope, Parent: ps); ps.EndLocation = t.EndLocation; return ps; case Mixin: if (Peek(1).Kind == OpenParenthesis) { OverPeekBrackets(OpenParenthesis); if (Lexer.CurrentPeekToken.Kind != Semicolon) return ExpressionStatement(Scope, Parent); return MixinDeclaration(Scope, Parent); } else { var tmx = TemplateMixin(Scope, Parent); if (tmx.MixinId == null) return tmx; else return new DeclarationStatement { Declarations = new[] { new NamedTemplateMixinNode(tmx) }, Parent = Parent }; } case Assert: var isStatic = laKind == Static; AssertStatement asS; if (isStatic) { Step(); asS = new StaticAssertStatement { Location = la.Location, Parent = Parent }; } else asS = new AssertStatement() { Location = la.Location, Parent = Parent }; Step(); if (Expect(OpenParenthesis)) { asS.AssertedExpression = Expression(Scope); Expect(CloseParenthesis); Expect(Semicolon); } asS.EndLocation = t.EndLocation; return asS; case Volatile: Step(); var vs = new VolatileStatement() { Location = t.Location, Parent = Parent }; vs.ScopedStatement = Statement(Scope: Scope, Parent: vs); vs.EndLocation = t.EndLocation; return vs; case Import: if(laKind == Static) Step(); // Will be handled in ImportDeclaration return ImportDeclaration(Scope); case Enum: case Alias: case Typedef: var ds = new DeclarationStatement() { Location = la.Location, Parent = Parent, ParentNode = Scope }; ds.Declarations = Declaration(Scope); ds.EndLocation = t.EndLocation; return ds; default: if (IsClassLike(laKind) || (IsBasicType(laKind) && Lexer.CurrentPeekToken.Kind != Dot) || IsModifier(laKind)) goto case Typedef; if (IsAssignExpression()) return ExpressionStatement(Scope, Parent); goto case Typedef; } }
public override bool check(CodeContext context) { if (is_checked) { return(!error); } is_checked = true; if (!call.check(context)) { /* if method resolving didn't succeed, skip this check */ error = true; return(false); } // type of target object DataType target_object_type = null; List <DataType> method_type_args = null; if (call.value_type is DelegateType) { // delegate invocation, resolve generic types relative to delegate target_object_type = call.value_type; } else if (call is MemberAccess) { var ma = (MemberAccess)call; if (ma.prototype_access) { error = true; Report.error(source_reference, "Access to instance member `%s' denied".printf(call.symbol_reference.get_full_name())); return(false); } method_type_args = ma.get_type_arguments(); if (ma.inner != null) { target_object_type = ma.inner.value_type; // foo is relevant instance in foo.bar.connect (on_bar) if (ma.inner.symbol_reference is Signal) { var sig = ma.inner as MemberAccess; if (sig != null) { target_object_type = sig.inner.value_type; } } // foo is relevant instance in foo.bar.begin (bar_ready) and foo.bar.end (result) var m = ma.symbol_reference as Method; if (m != null && m.coroutine) { // begin or end call of async method if (ma.member_name == "begin" || ma.member_name == "end") { var method_access = ma.inner as MemberAccess; if (method_access != null && method_access.inner != null) { target_object_type = method_access.inner.value_type; } else { // static method target_object_type = null; } } } } if (ma.symbol_reference != null && ma.symbol_reference.get_attribute("Assert") != null) { this.is_assert = true; var _args = get_argument_list(); if (_args.Count == 1) { this.source_reference = _args[0].source_reference; } } } var mtype = call.value_type; var gobject_chainup = call.symbol_reference == context.analyzer.object_type; is_chainup = gobject_chainup; if (!gobject_chainup) { var expr = call; var ma = expr as MemberAccess; if (ma != null && ma.symbol_reference is CreationMethod) { expr = ma.inner; ma = expr as MemberAccess; } if (ma != null && ma.member_name == "this") { // this[.with_foo] () is_chainup = true; } else if (expr is BaseAccess) { // base[.with_foo] () is_chainup = true; } } CreationMethod base_cm = null; if (is_chainup) { var cm = context.analyzer.find_current_method() as CreationMethod; if (cm == null) { error = true; Report.error(source_reference, "invocation not supported in this context"); return(false); } else if (cm.chain_up) { error = true; Report.error(source_reference, "Multiple constructor calls in the same constructor are not permitted"); return(false); } cm.chain_up = true; if (mtype is ObjectType) { var otype = (ObjectType)mtype; var cl = (Class)otype.type_symbol; base_cm = cl.default_construction_method; if (base_cm == null) { error = true; Report.error(source_reference, "chain up to `%s' not supported".printf(cl.get_full_name())); return(false); } else if (!base_cm.has_construct_function) { error = true; Report.error(source_reference, "chain up to `%s' not supported".printf(base_cm.get_full_name())); return(false); } } else if (call.symbol_reference is CreationMethod && call.symbol_reference.parent_symbol is Class) { base_cm = (CreationMethod)call.symbol_reference; if (!base_cm.has_construct_function) { error = true; Report.error(source_reference, "chain up to `%s' not supported".printf(base_cm.get_full_name())); return(false); } } else if (gobject_chainup) { var cl = cm.parent_symbol as Class; if (cl == null || !cl.is_subtype_of(context.analyzer.object_type)) { error = true; Report.error(source_reference, "chain up to `GLib.Object' not supported"); return(false); } call.value_type = new ObjectType(context.analyzer.object_type); mtype = call.value_type; } } // check for struct construction if (call is MemberAccess && ((call.symbol_reference is CreationMethod && call.symbol_reference.parent_symbol is Struct) || call.symbol_reference is Struct)) { var st = call.symbol_reference as Struct; if (st != null && st.default_construction_method == null && (st.is_boolean_type() || st.is_integer_type() || st.is_floating_type())) { error = true; Report.error(source_reference, "invocation not supported in this context"); return(false); } var struct_creation_expression = new ObjectCreationExpression((MemberAccess)call, source_reference); struct_creation_expression.struct_creation = true; foreach (Expression arg in get_argument_list()) { struct_creation_expression.add_argument(arg); } struct_creation_expression.target_type = target_type; context.analyzer.replaced_nodes.Add(this); parent_node.replace_expression(this, struct_creation_expression); struct_creation_expression.check(context); return(true); } else if (!is_chainup && call is MemberAccess && call.symbol_reference is CreationMethod) { error = true; Report.error(source_reference, "use `new' operator to create new objects"); return(false); } if (!is_chainup && mtype is ObjectType) { // prevent funny stuff like (new Object ()) () error = true; Report.error(source_reference, "invocation not supported in this context"); return(false); } else if (mtype != null && mtype.is_invokable()) { // call ok, expression is invokable } else if (call.symbol_reference is Class) { error = true; Report.error(source_reference, "use `new' operator to create new objects"); return(false); } else { error = true; Report.error(source_reference, "invocation not supported in this context"); return(false); } var ret_type = mtype.get_return_type(); var _params = mtype.get_parameters(); if (mtype is MethodType) { var m = ((MethodType)mtype).method_symbol; if (m != null && m.coroutine) { var ma = (MemberAccess)call; if (!is_yield_expression) { // begin or end call of async method if (ma.member_name != "end") { // begin (possibly implicit) if (ma.member_name != "begin") { Report.deprecated(ma.source_reference, "implicit .begin is deprecated"); } _params = m.get_async_begin_parameters(); ret_type = new VoidType(); } else { // end _params = m.get_async_end_parameters(); } } else if (ma.member_name == "begin" || ma.member_name == "end") { error = true; Report.error(ma.source_reference, "use of `%s' not allowed in yield statement".printf(ma.member_name)); } } if (m != null) { var ma = (MemberAccess)call; int n_type_params = m.get_type_parameters().Count; int n_type_args = ma.get_type_arguments().Count; if (n_type_args > 0 && n_type_args < n_type_params) { error = true; Report.error(ma.source_reference, "too few type arguments"); return(false); } else if (n_type_args > 0 && n_type_args > n_type_params) { error = true; Report.error(ma.source_reference, "too many type arguments"); return(false); } } } // FIXME partial code duplication in ObjectCreationExpression.check Expression last_arg = null; var args = get_argument_list(); IEnumerator <Expression> arg_it = args.GetEnumerator(); foreach (Parameter param in _params) { if (param.ellipsis) { break; } if (param.params_array) { var array_type = (ArrayType)param.variable_type; while (arg_it.MoveNext()) { Expression arg = arg_it.Current; /* store expected type for callback parameters */ arg.target_type = array_type.element_type; arg.target_type.value_owned = array_type.value_owned; } break; } if (arg_it.MoveNext()) { Expression arg = arg_it.Current; /* store expected type for callback parameters */ arg.formal_target_type = param.variable_type; arg.target_type = arg.formal_target_type.get_actual_type(target_object_type, method_type_args, this); last_arg = arg; } } // concatenate stringified arguments for methods with attribute [Print] if (mtype is MethodType && ((MethodType)mtype).method_symbol.get_attribute("Print") != null) { var template = new Template(source_reference); foreach (Expression arg in argument_list) { arg.parent_node = null; template.add_expression(arg); } argument_list.Clear(); add_argument(template); } // printf arguments if (mtype is MethodType && ((MethodType)mtype).method_symbol.printf_format) { StringLiteral format_literal = null; if (last_arg != null) { // use last argument as format string format_literal = StringLiteral.get_format_literal(last_arg); if (format_literal == null && args.Count == _params.Count - 1) { // insert "%s" to avoid issues with embedded % format_literal = new StringLiteral("\"%s\""); format_literal.target_type = context.analyzer.string_type.copy(); argument_list.Insert(args.Count - 1, format_literal); // recreate iterator and skip to right position arg_it = argument_list.GetEnumerator(); foreach (Parameter param in _params) { if (param.ellipsis) { break; } arg_it.MoveNext(); } } } else { // use instance as format string for string.printf (...) var ma = call as MemberAccess; if (ma != null) { format_literal = StringLiteral.get_format_literal(ma.inner); } } if (format_literal != null) { string format = format_literal.eval(); if (!context.analyzer.check_print_format(format, arg_it, source_reference)) { return(false); } } } foreach (Expression arg in get_argument_list().ToList()) { arg.check(context); } if (ret_type is VoidType) { // void return type if (!(parent_node is ExpressionStatement) && !(parent_node is ForStatement) && !(parent_node is YieldStatement)) { // A void method invocation can be in the initializer or // iterator of a for statement error = true; Report.error(source_reference, "invocation of void method not allowed as expression"); return(false); } } formal_value_type = ret_type.copy(); value_type = formal_value_type.get_actual_type(target_object_type, method_type_args, this); bool may_throw = false; if (mtype is MethodType) { var m = ((MethodType)mtype).method_symbol; if (is_yield_expression) { if (!m.coroutine) { error = true; Report.error(source_reference, "yield expression requires async method"); } if (context.analyzer.current_method == null || !context.analyzer.current_method.coroutine) { error = true; Report.error(source_reference, "yield expression not available outside async method"); } } if (m != null && m.coroutine && !is_yield_expression && ((MemberAccess)call).member_name != "end") { // .begin call of async method, no error can happen here } else { foreach (DataType error_type in m.get_error_types()) { may_throw = true; // ensure we can trace back which expression may throw errors of this type var call_error_type = error_type.copy(); call_error_type.source_reference = source_reference; add_error_type(call_error_type); } } if (m.returns_floating_reference) { value_type.floating_reference = true; } if (m.returns_modified_pointer) { ((MemberAccess)call).inner.lvalue = true; } var dynamic_sig = m.parent_symbol as DynamicSignal; if (dynamic_sig != null && dynamic_sig.handler != null) { dynamic_sig.return_type = dynamic_sig.handler.value_type.get_return_type().copy(); bool first = true; foreach (Parameter param in dynamic_sig.handler.value_type.get_parameters()) { if (first) { // skip sender parameter first = false; } else { dynamic_sig.add_parameter(param.copy()); } } dynamic_sig.handler.target_type = new DelegateType(dynamic_sig.get_delegate(new ObjectType((ObjectTypeSymbol)dynamic_sig.parent_symbol), this)); } if (m != null && m.get_type_parameters().Count > 0) { var ma = (MemberAccess)call; if (ma.get_type_arguments().Count == 0) { // infer type arguments foreach (var type_param in m.get_type_parameters()) { DataType type_arg = null; // infer type arguments from arguments arg_it = args.GetEnumerator(); foreach (Parameter param in _params) { if (param.ellipsis || param.params_array) { break; } if (arg_it.MoveNext()) { Expression arg = arg_it.Current; type_arg = param.variable_type.infer_type_argument(type_param, arg.value_type); if (type_arg != null) { break; } arg.target_type = arg.formal_target_type.get_actual_type(target_object_type, method_type_args, this); } } // infer type arguments from expected return type if (type_arg == null && target_type != null) { type_arg = m.return_type.infer_type_argument(type_param, target_type); } if (type_arg == null) { error = true; Report.error(ma.source_reference, "cannot infer generic type argument for type parameter `%s'".printf(type_param.get_full_name())); return(false); } ma.add_type_argument(type_arg); } // recalculate argument target types with new information arg_it = args.GetEnumerator(); foreach (Parameter param in _params) { if (param.ellipsis || param.params_array) { break; } if (arg_it.MoveNext()) { Expression arg = arg_it.Current; arg.target_type = arg.formal_target_type.get_actual_type(target_object_type, method_type_args, this); } } // recalculate return value type with new information value_type = formal_value_type.get_actual_type(target_object_type, method_type_args, this); } } // replace method-type if needed for proper argument-check in semantic-analyser if (m != null && m.coroutine) { var ma = (MemberAccess)call; if (ma.member_name == "end") { mtype = new MethodType(m.get_end_method()); } } } else if (mtype is ObjectType) { // constructor var cl = (Class)((ObjectType)mtype).type_symbol; var m = cl.default_construction_method; foreach (DataType error_type in m.get_error_types()) { may_throw = true; // ensure we can trace back which expression may throw errors of this type var call_error_type = error_type.copy(); call_error_type.source_reference = source_reference; add_error_type(call_error_type); } } else if (mtype is DelegateType) { var d = ((DelegateType)mtype).delegate_symbol; foreach (DataType error_type in d.get_error_types()) { may_throw = true; // ensure we can trace back which expression may throw errors of this type var call_error_type = error_type.copy(); call_error_type.source_reference = source_reference; add_error_type(call_error_type); } } if (!context.analyzer.check_arguments(this, mtype, _params, get_argument_list())) { error = true; return(false); } /* Check for constructv chain up */ if (base_cm != null && base_cm.is_variadic() && args.Count == base_cm.get_parameters().Count) { var this_last_arg = args[args.Count - 1]; if (this_last_arg.value_type is StructValueType && this_last_arg.value_type.data_type == context.analyzer.va_list_type.data_type) { is_constructv_chainup = true; } } if (may_throw) { if (parent_node is LocalVariable || parent_node is ExpressionStatement) { // simple statements, no side effects after method call } else if (!(context.analyzer.current_symbol is Block)) { // can't handle errors in field initializers Report.error(source_reference, "Field initializers must not throw errors"); } else { // store parent_node as we need to replace the expression in the old parent node later on var old_parent_node = parent_node; var local = new LocalVariable(value_type.copy(), get_temp_name(), null, source_reference); var decl = new DeclarationStatement(local, source_reference); insert_statement(context.analyzer.insert_block, decl); var temp_access = SemanticAnalyzer.create_temp_access(local, target_type); // don't set initializer earlier as this changes parent_node and parent_statement local.initializer = this; decl.check(context); // move temp variable to insert block to ensure the // variable is in the same block as the declaration // otherwise there will be scoping issues in the generated code var block = (Block)context.analyzer.current_symbol; block.remove_local_variable(local); context.analyzer.insert_block.add_local_variable(local); old_parent_node.replace_expression(this, temp_access); temp_access.check(context); } } return(!error); }
public override void OnDeclarationStatement(DeclarationStatement node) { DeclarationFound(node.Declaration.Name, node.Declaration.Type, node.Initializer, node.LexicalInfo); }
public override bool EnterDeclarationStatement(DeclarationStatement node) { WriteIndented(); return(true); }
public override void OnDeclarationStatement(DeclarationStatement node) { declarations.Add(node); base.OnDeclarationStatement(node); }
public void Visit(DeclarationStatement declarationStatement) { }
public override bool check(CodeContext context) { if (is_checked) { return(!error); } is_checked = true; if (member_name != null) { if (!member_name.check(context)) { error = true; return(false); } } TypeSymbol type = null; if (type_reference == null) { if (member_name == null) { error = true; Report.error(source_reference, "Incomplete object creation expression"); return(false); } if (member_name.symbol_reference == null) { error = true; return(false); } var constructor_sym = member_name.symbol_reference; var type_sym = member_name.symbol_reference; var type_args = member_name.get_type_arguments(); if (constructor_sym is Method) { type_sym = constructor_sym.parent_symbol; var constructor = (Method)constructor_sym; if (!(constructor_sym is CreationMethod)) { error = true; Report.error(source_reference, "`%s' is not a creation method".printf(constructor.get_full_name())); return(false); } symbol_reference = constructor; // inner expression can also be base access when chaining constructors var ma = member_name.inner as MemberAccess; if (ma != null) { type_args = ma.get_type_arguments(); } } if (type_sym is Class) { type = (TypeSymbol)type_sym; if (((Class)type).is_error_base) { type_reference = new ErrorType(null, null, source_reference); } else { type_reference = new ObjectType((Class)type); } } else if (type_sym is Struct) { type = (TypeSymbol)type_sym; type_reference = new StructValueType((Struct)type); } else if (type_sym is ErrorCode) { type_reference = new ErrorType((ErrorDomain)type_sym.parent_symbol, (ErrorCode)type_sym, source_reference); symbol_reference = type_sym; } else { error = true; Report.error(source_reference, "`%s' is not a class, struct, or error code".printf(type_sym.get_full_name())); return(false); } foreach (DataType type_arg in type_args) { type_reference.add_type_argument(type_arg); } } else { type = type_reference.data_type; } value_type = type_reference.copy(); value_type.value_owned = true; bool may_throw = false; int given_num_type_args = type_reference.get_type_arguments().Count; int expected_num_type_args = 0; if (type is Class) { var cl = (Class)type; expected_num_type_args = cl.get_type_parameters().Count; if (struct_creation) { error = true; Report.error(source_reference, "syntax error, use `new' to create new objects"); return(false); } if (cl.is_abstract) { value_type = null; error = true; Report.error(source_reference, "Can't create instance of abstract class `%s'".printf(cl.get_full_name())); return(false); } if (symbol_reference == null) { symbol_reference = cl.default_construction_method; if (symbol_reference == null) { error = true; Report.error(source_reference, "`%s' does not have a default constructor".printf(cl.get_full_name())); return(false); } // track usage for flow analyzer symbol_reference.used = true; symbol_reference.version.check(source_reference); } if (symbol_reference != null && (symbol_reference.access == SymbolAccessibility.PRIVATE || symbol_reference.access == SymbolAccessibility.PROTECTED)) { bool in_target_type = false; for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol) { if (this_symbol == cl) { in_target_type = true; break; } } if (!in_target_type) { error = true; Report.error(source_reference, "Access to non-public constructor `%s' denied".printf(symbol_reference.get_full_name())); return(false); } } while (cl != null) { // FIXME: use target values in the codegen if (cl.get_attribute_string("CCode", "ref_sink_function") != null) { value_type.floating_reference = true; break; } cl = cl.base_class; } } else if (type is Struct) { var st = (Struct)type; expected_num_type_args = st.get_type_parameters().Count; if (!struct_creation && !context.deprecated) { Report.warning(source_reference, "deprecated syntax, don't use `new' to initialize structs"); } if (symbol_reference == null) { symbol_reference = st.default_construction_method; } if (st.is_simple_type() && symbol_reference == null && object_initializer.Count == 0) { error = true; Report.error(source_reference, "`%s' does not have a default constructor".printf(st.get_full_name())); return(false); } } if (expected_num_type_args > given_num_type_args) { error = true; Report.error(source_reference, "too few type arguments"); return(false); } else if (expected_num_type_args < given_num_type_args) { error = true; Report.error(source_reference, "too many type arguments"); return(false); } if (symbol_reference == null && get_argument_list().Count != 0) { value_type = null; error = true; Report.error(source_reference, "No arguments allowed when constructing type `%s'".printf(type.get_full_name())); return(false); } if (symbol_reference is Method) { var m = (Method)symbol_reference; if (is_yield_expression) { if (!m.coroutine) { error = true; Report.error(source_reference, "yield expression requires async method"); } if (context.analyzer.current_method == null || !context.analyzer.current_method.coroutine) { error = true; Report.error(source_reference, "yield expression not available outside async method"); } } // FIXME partial code duplication of MethodCall.check Expression last_arg = null; var args = get_argument_list(); IEnumerator <Expression> arg_it = args.GetEnumerator(); foreach (Parameter param in m.get_parameters()) { if (param.ellipsis) { break; } if (arg_it.MoveNext()) { Expression arg = arg_it.Current; /* store expected type for callback parameters */ arg.formal_target_type = param.variable_type; arg.target_type = arg.formal_target_type.get_actual_type(value_type, null, this); last_arg = arg; } } // printf arguments if (m.printf_format) { StringLiteral format_literal = null; if (last_arg != null) { // use last argument as format string format_literal = StringLiteral.get_format_literal(last_arg); if (format_literal == null && args.Count == m.get_parameters().Count - 1) { // insert "%s" to avoid issues with embedded % format_literal = new StringLiteral("\"%s\""); format_literal.target_type = context.analyzer.string_type.copy(); argument_list.Insert(args.Count - 1, format_literal); // recreate iterator and skip to right position arg_it = argument_list.GetEnumerator(); foreach (Parameter param in m.get_parameters()) { if (param.ellipsis) { break; } arg_it.MoveNext(); } } } if (format_literal != null) { string format = format_literal.eval(); if (!context.analyzer.check_print_format(format, arg_it, source_reference)) { return(false); } } } foreach (Expression arg in args.ToList()) { arg.check(context); } context.analyzer.check_arguments(this, new MethodType(m), m.get_parameters(), args); foreach (DataType error_type in m.get_error_types()) { may_throw = true; // ensure we can trace back which expression may throw errors of this type var call_error_type = error_type.copy(); call_error_type.source_reference = source_reference; add_error_type(call_error_type); } } else if (type_reference is ErrorType) { if (type_reference != null) { type_reference.check(context); } if (member_name != null) { member_name.check(context); } foreach (Expression arg in argument_list) { arg.check(context); } foreach (MemberInitializer init in object_initializer) { init.check(context); } if (get_argument_list().Count == 0) { error = true; Report.error(source_reference, "Too few arguments, errors need at least 1 argument"); } else { IEnumerator <Expression> arg_it = get_argument_list().GetEnumerator(); arg_it.MoveNext(); var ex = arg_it.Current; if (ex.value_type == null || !ex.value_type.compatible(context.analyzer.string_type)) { error = true; Report.error(source_reference, "Invalid type for argument 1"); } var format_literal = StringLiteral.get_format_literal(ex); if (format_literal != null) { var format = format_literal.eval(); if (!context.analyzer.check_print_format(format, arg_it, source_reference)) { error = true; return(false); } } arg_it = get_argument_list().GetEnumerator(); arg_it.MoveNext(); if (!context.analyzer.check_variadic_arguments(arg_it, 1, source_reference)) { error = true; return(false); } } } foreach (MemberInitializer init in get_object_initializer()) { context.analyzer.visit_member_initializer(init, type_reference); } if (may_throw) { if (parent_node is LocalVariable || parent_node is ExpressionStatement) { // simple statements, no side effects after method call } else if (!(context.analyzer.current_symbol is Block)) { // can't handle errors in field initializers Report.error(source_reference, "Field initializers must not throw errors"); } else { // store parent_node as we need to replace the expression in the old parent node later on var old_parent_node = parent_node; var local = new LocalVariable(value_type.copy(), get_temp_name(), null, source_reference); var decl = new DeclarationStatement(local, source_reference); insert_statement(context.analyzer.insert_block, decl); var temp_access = SemanticAnalyzer.create_temp_access(local, target_type); // don't set initializer earlier as this changes parent_node and parent_statement local.initializer = this; decl.check(context); // move temp variable to insert block to ensure the // variable is in the same block as the declaration // otherwise there will be scoping issues in the generated code var block = (Block)context.analyzer.current_symbol; block.remove_local_variable(local); context.analyzer.insert_block.add_local_variable(local); old_parent_node.replace_expression(this, temp_access); temp_access.check(context); } } return(!error); }
public IStatement Statement(bool BlocksAllowed = true, bool EmptyAllowed = true, IBlockNode Scope = null, IStatement Parent=null) { if (EmptyAllowed && laKind == Semicolon) { LastParsedObject = null; Step(); return null; } if (BlocksAllowed && laKind == OpenCurlyBrace) return BlockStatement(Scope,Parent); #region LabeledStatement (loc:... goto loc;) if (laKind == Identifier && Lexer.CurrentPeekToken.Kind == Colon) { Step(); var ret = new LabeledStatement() { Location = t.Location, Identifier = t.Value, Parent = Parent }; LastParsedObject = null; Step(); ret.EndLocation = t.EndLocation; return ret; } #endregion #region IfStatement else if (laKind == (If)) { Step(); var dbs = new IfStatement{ Location = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // IfCondition IfCondition(dbs); // ThenStatement if(Expect(CloseParenthesis)) dbs.ThenStatement = Statement(Scope: Scope, Parent: dbs); // ElseStatement if (laKind == (Else)) { Step(); dbs.ElseStatement = Statement(Scope: Scope, Parent: dbs); } if(t != null) dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Conditions else if ((laKind == Static && Lexer.CurrentPeekToken.Kind == If) || laKind == Version || laKind == Debug) return StmtCondition(Parent, Scope); #endregion #region WhileStatement else if (laKind == While) { Step(); var dbs = new WhileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) { dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; } return dbs; } #endregion #region DoStatement else if (laKind == (Do)) { Step(); var dbs = new WhileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; if(!IsEOF) dbs.ScopedStatement = Statement(true, false, Scope, dbs); if(Expect(While) && Expect(OpenParenthesis)) { dbs.Condition = Expression(Scope); Expect(CloseParenthesis); if (Expect(Semicolon)) LastParsedObject = null; dbs.EndLocation = t.EndLocation; } return dbs; } #endregion #region ForStatement else if (laKind == (For)) return ForStatement(Scope, Parent); #endregion #region ForeachStatement else if (laKind == Foreach || laKind == Foreach_Reverse) return ForeachStatement(Scope, Parent); #endregion #region [Final] SwitchStatement else if ((laKind == (Final) && Lexer.CurrentPeekToken.Kind == (Switch)) || laKind == (Switch)) { var dbs = new SwitchStatement { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (Final)) { dbs.IsFinal = true; Step(); } Step(); Expect(OpenParenthesis); dbs.SwitchExpression = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region CaseStatement else if (laKind == (Case)) { Step(); var dbs = new SwitchStatement.CaseStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ArgumentList = Expression(Scope); if (Expect(Colon)) LastParsedObject = null; // CaseRangeStatement if (laKind == DoubleDot) { Step(); Expect(Case); dbs.LastExpression = AssignExpression(); if (Expect(Colon)) LastParsedObject = null; } var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Default else if (laKind == (Default)) { Step(); var dbs = new SwitchStatement.DefaultStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; Expect(Colon); var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Continue | Break else if (laKind == (Continue)) { Step(); var s = new ContinueStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } else if (laKind == (Break)) { Step(); var s = new BreakStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } #endregion #region Return else if (laKind == (Return)) { Step(); var s = new ReturnStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind != (Semicolon)) s.ReturnExpression = Expression(Scope); if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } #endregion #region Goto else if (laKind == (Goto)) { Step(); var s = new GotoStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Identifier; s.LabelIdentifier = t.Value; } else if (laKind == Default) { Step(); s.StmtType = GotoStatement.GotoStmtType.Default; } else if (laKind == (Case)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Case; if (laKind != (Semicolon)) s.CaseExpression = Expression(Scope); } if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } #endregion #region WithStatement else if (laKind == (With)) { Step(); var dbs = new WithStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; if(Expect(OpenParenthesis)) { // Symbol dbs.WithExpression = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); } dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region SynchronizedStatement else if (laKind == (Synchronized)) { Step(); var dbs = new SynchronizedStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (OpenParenthesis)) { Step(); dbs.SyncExpression = Expression(Scope); Expect(CloseParenthesis); } if(!IsEOF) dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region TryStatement else if (laKind == (Try)) { Step(); var s = new TryStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope, Parent: s); if (!(laKind == (Catch) || laKind == (Finally))) SemErr(Catch, "At least one catch or a finally block expected!"); var catches = new List<TryStatement.CatchStatement>(); // Catches while (laKind == (Catch)) { Step(); var c = new TryStatement.CatchStatement() { Location = t.Location, Parent = s }; LastParsedObject = c; // CatchParameter if (laKind == (OpenParenthesis)) { Step(); if (laKind == CloseParenthesis || IsEOF) { SemErr(CloseParenthesis, "Catch parameter expected, not ')'"); Step(); } else { var catchVar = new DVariable { Parent = Scope, Location = t.Location }; LastParsedObject = catchVar; Lexer.PushLookAheadBackup(); catchVar.Type = BasicType(); if (laKind == CloseParenthesis) { Lexer.RestoreLookAheadBackup(); catchVar.Type = new IdentifierDeclaration("Exception"); } else Lexer.PopLookAheadBackup(); if (Expect(Identifier)) { catchVar.Name = t.Value; catchVar.NameLocation = t.Location; Expect(CloseParenthesis); } else if(IsEOF) ExpectingNodeName = true; catchVar.EndLocation = t.EndLocation; c.CatchParameter = catchVar; } } if(!IsEOF) c.ScopedStatement = Statement(Scope: Scope, Parent: c); c.EndLocation = t.EndLocation; catches.Add(c); } if (catches.Count > 0) s.Catches = catches.ToArray(); if (laKind == (Finally)) { Step(); var f = new TryStatement.FinallyStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = f; f.ScopedStatement = Statement(); f.EndLocation = t.EndLocation; s.FinallyStmt = f; } s.EndLocation = t.EndLocation; return s; } #endregion #region ThrowStatement else if (laKind == (Throw)) { Step(); var s = new ThrowStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ThrowExpression = Expression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region ScopeGuardStatement else if (laKind == DTokens.Scope) { Step(); if (laKind == OpenParenthesis) { var s = new ScopeGuardStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; Step(); if (Expect(Identifier) && t.Value != null) // exit, failure, success s.GuardedScope = t.Value.ToLower(); if (Expect(CloseParenthesis)) TrackerVariables.ExpectingIdentifier = false; if (!IsEOF) s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } else PushAttribute(new Modifier(DTokens.Scope), false); } #endregion #region AsmStmt else if (laKind == Asm) return AsmStatement(Parent); #endregion #region PragmaStatement else if (laKind == (Pragma)) { var s = new PragmaStatement { Location = la.Location }; s.Pragma = _Pragma(); s.Parent = Parent; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion #region MixinStatement else if (laKind == (Mixin)) { if (Peek(1).Kind == OpenParenthesis) { OverPeekBrackets(OpenParenthesis); if (Lexer.CurrentPeekToken.Kind != Semicolon) return ExpressionStatement(Scope, Parent); return MixinDeclaration(Scope, Parent); } else { var tmx = TemplateMixin(Scope, Parent); if (tmx.MixinId == null) return tmx; else return new DeclarationStatement { Declarations = new[] { new NamedTemplateMixinNode(tmx) }, Parent = Parent }; } } #endregion #region (Static) AssertExpression else if (laKind == Assert || (laKind == Static && Lexer.CurrentPeekToken.Kind == Assert)) { var isStatic = laKind == Static; AssertStatement s; if (isStatic) { Step(); s = new StaticAssertStatement { Location = la.Location, Parent = Parent }; } else s = new AssertStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = s; Step(); if (Expect(OpenParenthesis)) { s.AssertedExpression = Expression(Scope); if(Expect(CloseParenthesis) && Expect(Semicolon)) LastParsedObject = null; } s.EndLocation = t.EndLocation; return s; } #endregion #region D1: VolatileStatement else if (laKind == Volatile) { Step(); var s = new VolatileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion // ImportDeclaration else if (laKind == Import || (laKind == Static && Lexer.CurrentPeekToken.Kind == Import)) { if(laKind == Static) Step(); // Will be handled in ImportDeclaration return ImportDeclaration(Scope); } else if (!(ClassLike[laKind] || BasicTypes[laKind] || laKind == Enum || Modifiers[laKind] || IsAtAttribute || laKind == Alias || laKind == Typedef) && IsAssignExpression()) return ExpressionStatement(Scope, Parent); var ds = new DeclarationStatement() { Location = la.Location, Parent = Parent, ParentNode = Scope }; LastParsedObject = ds; ds.Declarations = Declaration(Scope); ds.EndLocation = t.EndLocation; return ds; }
public override void OnDeclarationStatement(DeclarationStatement node) { throw new NotImplementedException(); }
public override void LeaveDeclarationStatement(DeclarationStatement node) { WriteLine(); }
public override bool check(CodeContext context) { if (is_checked) { return(!error); } is_checked = true; if (left is ValaTuple && Operator == AssignmentOperator.SIMPLE && parent_node is ExpressionStatement) { var tuple = (ValaTuple)left; var local = new LocalVariable(null, get_temp_name(), right, right.source_reference); var decl = new DeclarationStatement(local, source_reference); decl.check(context); insert_statement(context.analyzer.insert_block, decl); int i = 0; ExpressionStatement stmt = null; foreach (var expr in tuple.get_expressions()) { if (stmt != null) { stmt.check(context); insert_statement(context.analyzer.insert_block, stmt); } var temp_access = MemberAccess.simple(local.name, right.source_reference); var ea = new ElementAccess(temp_access, expr.source_reference); ea.append_index(new IntegerLiteral(i.ToString(), expr.source_reference)); var assign = new Assignment(expr, ea, Operator, expr.source_reference); stmt = new ExpressionStatement(assign, expr.source_reference); i++; } context.analyzer.replaced_nodes.Add(this); parent_node.replace_expression(this, stmt.expression); return(stmt.expression.check(context)); } left.lvalue = true; if (!left.check(context)) { // skip on error in inner expression error = true; return(false); } if (left is MemberAccess) { var ma = (MemberAccess)left; if (ma.symbol_reference is Constant) { error = true; Report.error(source_reference, "Assignment to constant after initialization"); return(false); } if ((!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) && ma.value_type == null) || (ma.inner == null && ma.member_name == "this" && context.analyzer.is_in_instance_method())) { error = true; Report.error(source_reference, "unsupported lvalue in assignment"); return(false); } if (ma.prototype_access) { error = true; Report.error(source_reference, "Access to instance member `%s' denied".printf(ma.symbol_reference.get_full_name())); return(false); } if (ma.error || ma.symbol_reference == null) { error = true; /* if no symbol found, skip this check */ return(false); } if (ma.symbol_reference is DynamicSignal) { // target_type not available for dynamic signals if (!context.deprecated) { Report.warning(source_reference, "deprecated syntax, use `connect' method instead"); } } else if (ma.symbol_reference is Signal) { if (!context.deprecated) { Report.warning(source_reference, "deprecated syntax, use `connect' method instead"); } var sig = (Signal)ma.symbol_reference; right.target_type = new DelegateType(sig.get_delegate(ma.inner.value_type, this)); } else if (ma.symbol_reference is DynamicProperty) { // target_type not available for dynamic properties } else { right.formal_target_type = ma.formal_value_type.copy(); right.target_type = ma.value_type.copy(); } } else if (left is ElementAccess) { var ea = (ElementAccess)left; if (ea.container.value_type.data_type == context.analyzer.string_type.data_type) { error = true; Report.error(ea.source_reference, "strings are immutable"); return(false); } else if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) { var ma = (MemberAccess)ea.container; var sig = (Signal)ea.container.symbol_reference; right.target_type = new DelegateType(sig.get_delegate(ma.inner.value_type, this)); } else if (ea.container.value_type.get_member("set") is Method) { var set_call = new MethodCall(new MemberAccess(ea.container, "set", source_reference), source_reference); foreach (Expression e in ea.get_indices()) { set_call.add_argument(e); } set_call.add_argument(right); parent_node.replace_expression(this, set_call); return(set_call.check(context)); } else { right.target_type = left.value_type; } } else if (left is PointerIndirection) { right.target_type = left.value_type; } else { error = true; Report.error(source_reference, "unsupported lvalue in assignment"); return(false); } if (!right.check(context)) { // skip on error in inner expression error = true; return(false); } if (Operator != AssignmentOperator.SIMPLE && left is MemberAccess) { // transform into simple assignment // FIXME: only do this if the backend doesn't support // the assignment natively var ma = (MemberAccess)left; if (!(ma.symbol_reference is Signal)) { var old_value = new MemberAccess(ma.inner, ma.member_name); var bin = new BinaryExpression(BinaryOperator.PLUS, old_value, right, source_reference); bin.target_type = right.target_type; right.target_type = right.target_type.copy(); right.target_type.value_owned = false; if (Operator == AssignmentOperator.BITWISE_OR) { bin.Operator = BinaryOperator.BITWISE_OR; } else if (Operator == AssignmentOperator.BITWISE_AND) { bin.Operator = BinaryOperator.BITWISE_AND; } else if (Operator == AssignmentOperator.BITWISE_XOR) { bin.Operator = BinaryOperator.BITWISE_XOR; } else if (Operator == AssignmentOperator.ADD) { bin.Operator = BinaryOperator.PLUS; } else if (Operator == AssignmentOperator.SUB) { bin.Operator = BinaryOperator.MINUS; } else if (Operator == AssignmentOperator.MUL) { bin.Operator = BinaryOperator.MUL; } else if (Operator == AssignmentOperator.DIV) { bin.Operator = BinaryOperator.DIV; } else if (Operator == AssignmentOperator.PERCENT) { bin.Operator = BinaryOperator.MOD; } else if (Operator == AssignmentOperator.SHIFT_LEFT) { bin.Operator = BinaryOperator.SHIFT_LEFT; } else if (Operator == AssignmentOperator.SHIFT_RIGHT) { bin.Operator = BinaryOperator.SHIFT_RIGHT; } right = bin; right.check(context); Operator = AssignmentOperator.SIMPLE; } } if (left.symbol_reference is Signal) { var sig = (Signal)left.symbol_reference; var m = right.symbol_reference as Method; if (m == null) { error = true; Report.error(right.source_reference, "unsupported expression for signal handler"); return(false); } var dynamic_sig = sig as DynamicSignal; var right_ma = right as MemberAccess; if (dynamic_sig != null) { bool first = true; foreach (Parameter param in dynamic_sig.handler.value_type.get_parameters()) { if (first) { // skip sender parameter first = false; } else { dynamic_sig.add_parameter(param.copy()); } } right.target_type = new DelegateType(sig.get_delegate(new ObjectType((ObjectTypeSymbol)sig.parent_symbol), this)); } else if (!right.value_type.compatible(right.target_type)) { var delegate_type = (DelegateType)right.target_type; error = true; Report.error(right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf(right.value_type.ToString(), right.target_type.ToString(), delegate_type.delegate_symbol.get_prototype_string(m.name))); return(false); } else if (right_ma != null && right_ma.prototype_access) { error = true; Report.error(right.source_reference, "Access to instance member `%s' denied".printf(m.get_full_name())); return(false); } } else if (left is MemberAccess) { var ma = (MemberAccess)left; if (ma.symbol_reference is Property) { var prop = (Property)ma.symbol_reference; var dynamic_prop = prop as DynamicProperty; if (dynamic_prop != null) { dynamic_prop.property_type = right.value_type.copy(); left.value_type = dynamic_prop.property_type.copy(); } if (prop.set_accessor == null || (!prop.set_accessor.writable && !(context.analyzer.find_current_method() is CreationMethod || context.analyzer.is_in_constructor()))) { ma.error = true; Report.error(ma.source_reference, "Property `%s' is read-only".printf(prop.get_full_name())); return(false); } else if (!context.deprecated && !prop.set_accessor.writable && context.analyzer.find_current_method() is CreationMethod) { if (ma.inner.symbol_reference != context.analyzer.find_current_method().this_parameter) { // trying to set construct-only property in creation method for foreign instance Report.error(ma.source_reference, "Property `%s' is read-only".printf(prop.get_full_name())); return(false); } else { Report.error(ma.source_reference, "Cannot assign to construct-only properties, use Object (property: value) constructor chain up"); return(false); } } } else if (ma.symbol_reference is Variable && right.value_type == null) { var variable = (Variable)ma.symbol_reference; if (right.symbol_reference is Method && variable.variable_type is DelegateType) { var m = (Method)right.symbol_reference; var dt = (DelegateType)variable.variable_type; var cb = dt.delegate_symbol; /* check whether method matches callback type */ if (!cb.matches_method(m, dt)) { error = true; Report.error(source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf(m.get_full_name(), cb.get_full_name())); return(false); } right.value_type = variable.variable_type; } else { error = true; Report.error(source_reference, "Assignment: Invalid assignment attempt"); return(false); } } if (left.value_type != null && right.value_type != null) { /* if there was an error on either side, * i.e. {left|right}.value_type == null, skip type check */ if (!right.value_type.compatible(left.value_type)) { error = true; Report.error(source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf(right.value_type.ToString(), left.value_type.ToString())); return(false); } if (!(ma.symbol_reference is Property)) { if (right.value_type.is_disposable()) { /* rhs transfers ownership of the expression */ if (!(left.value_type is PointerType) && !left.value_type.value_owned) { /* lhs doesn't own the value */ error = true; Report.error(source_reference, "Invalid assignment from owned expression to unowned variable"); } } else if (left.value_type.value_owned) { /* lhs wants to own the value * rhs doesn't transfer the ownership * code generator needs to add reference * increment calls */ } } } var right_ma = right as MemberAccess; if (right_ma != null && ma.symbol_reference == right_ma.symbol_reference) { if (ma.symbol_reference is LocalVariable || ma.symbol_reference is Parameter) { Report.warning(source_reference, "Assignment to same variable"); } else if (ma.symbol_reference is Field) { var f = (Field)ma.symbol_reference; if (f.binding == MemberBinding.STATIC) { Report.warning(source_reference, "Assignment to same variable"); } else { var ma_inner = ma.inner as MemberAccess; var right_ma_inner = right_ma.inner as MemberAccess; if (ma_inner != null && ma_inner.member_name == "this" && ma_inner.inner == null && right_ma_inner != null && right_ma_inner.member_name == "this" && right_ma_inner.inner == null) { Report.warning(source_reference, "Assignment to same variable"); } } } } } else if (left is ElementAccess) { var ea = (ElementAccess)left; if (!right.value_type.compatible(left.value_type)) { error = true; Report.error(source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf(right.value_type.ToString(), left.value_type.ToString())); return(false); } if (right.value_type.is_disposable()) { /* rhs transfers ownership of the expression */ DataType element_type; if (ea.container.value_type is ArrayType) { var array_type = (ArrayType)ea.container.value_type; element_type = array_type.element_type; } else { var args = ea.container.value_type.get_type_arguments(); Debug.Assert(args.Count == 1); element_type = args[0]; } if (!(element_type is PointerType) && !element_type.value_owned) { /* lhs doesn't own the value */ error = true; Report.error(source_reference, "Invalid assignment from owned expression to unowned variable"); return(false); } } else if (left.value_type.value_owned) { /* lhs wants to own the value * rhs doesn't transfer the ownership * code generator needs to add reference * increment calls */ } } else { return(true); } if (left.value_type != null) { value_type = left.value_type.copy(); value_type.value_owned = false; } else { value_type = null; } add_error_types(left.get_error_types()); add_error_types(right.get_error_types()); return(!error); }