public bool OnEnterNode(MiniME.ast.Node n) { if (n.GetType() == typeof(ast.CodeBlock)) { var block = (ast.CodeBlock)n; block.CombineVarDecls(); } return true; }
public bool OnEnterNode(MiniME.ast.Node n) { // Descending into an inner scope if (n.Scope != null) { System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope); currentScope = n.Scope; } // Is is a "var <name>=<literal_int_or_double>", inside a function if (currentScope.OuterScope!=null && n.GetType() == typeof(ast.StatementVariableDeclaration)) { var vardecl = (ast.StatementVariableDeclaration)n; foreach (var v in vardecl.Variables) { // Must have initial value if (v.InitialValue == null) continue; // Must evaluate to a constant object val = v.InitialValue.RootNode.EvalConstLiteral(); if (val==null) continue; // Must be a number if (val.GetType() != typeof(long) && val.GetType() != typeof(DoubleLiteral)) continue; // Find the symbol in the current scope Symbol s = currentScope.Symbols.FindLocalSymbol(v.Name); System.Diagnostics.Debug.Assert(s != null); // Store the constant value for this symbol if (s.ConstValue == null && s.ConstAllowed) { s.ConstValue = val; } else { s.ConstAllowed = false; s.ConstValue = null; } } } return true; }
public bool OnEnterNode(MiniME.ast.Node n) { // Descending into an inner scope if (n.Scope != null) { System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope); currentScope = n.Scope; } // Is it a variable declaration if (n.GetType() == typeof(ast.StatementVariableDeclaration)) { var vardecl = (ast.StatementVariableDeclaration)n; for (int i = vardecl.Variables.Count - 1; i >= 0; i-- ) { var v = vardecl.Variables[i]; // Find the symbol (must exist in current scope) var s = currentScope.Symbols.FindLocalSymbol(v.Name); System.Diagnostics.Debug.Assert(s != null); // Is it a const? if (s.ConstValue != null) { // Yes! Remove it vardecl.Variables.RemoveAt(i); } } } return true; }
public bool OnEnterNode(MiniME.ast.Node n) { // Descending into an inner scope if (n.Scope != null) { System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope); currentScope = n.Scope; } // Look for assignments to property if (n.GetType() == typeof(ast.ExprNodeAssignment)) { // Is it an assignment var assignOp = (ast.ExprNodeAssignment)n; RejectConstVariable(assignOp.Lhs); } // Look for increment/decrement operators if (n.GetType() == typeof(ast.ExprNodeUnary)) { var oneOp = (ast.ExprNodeUnary)n; if (oneOp.Op == Token.increment || oneOp.Op == Token.decrement) { RejectConstVariable(oneOp.Rhs); } } // Postfix too if (n.GetType() == typeof(ast.ExprNodePostfix)) { var oneOp = (ast.ExprNodePostfix)n; if (oneOp.Op == Token.increment || oneOp.Op == Token.decrement) { RejectConstVariable(oneOp.Lhs); } } return true; }
public bool OnEnterNode(MiniME.ast.Node n) { // Define name of function in outer scope, before descending if (n.GetType() == typeof(ast.ExprNodeFunction)) { var fn = (ast.ExprNodeFunction)n; // Define a symbol for the new function if (!String.IsNullOrEmpty(fn.Name)) { DefineLocalSymbol(fn.Name, fn.Bookmark); currentScope.ProcessAccessibilitySpecs(fn.Name, fn.Bookmark); } } // Descending into an inner scope if (n.Scope != null) { System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope); currentScope = n.Scope; } // Descending into an inner pseudo scope if (n.PseudoScope != null) { System.Diagnostics.Debug.Assert(n.PseudoScope.OuterScope == currentPseudoScope); currentPseudoScope = n.PseudoScope; } // Define catch clause exception variables in the inner scope if (n.GetType() == typeof(ast.CatchClause)) { var cc = (ast.CatchClause)n; DefineLocalSymbol(cc.ExceptionVariable, n.Bookmark); return true; } // Define variables in the current scope if (n.GetType() == typeof(ast.StatementVariableDeclaration)) { var vardecl = (ast.StatementVariableDeclaration)n; foreach (var v in vardecl.Variables) { DefineLocalSymbol(v.Name, v.Bookmark); currentScope.ProcessAccessibilitySpecs(v.Name, v.Bookmark); if (v.InitialValue!=null && v.InitialValue.RootNode.GetType()==typeof(ast.ExprNodeObjectLiteral)) { // Get the object literal var literal=(ast.ExprNodeObjectLiteral)v.InitialValue.RootNode; // Create a fake/temp identifier node while we process accessibility specs var target = new ast.ExprNodeIdentifier(null, v.Name); // Process all keys that are identifiers foreach (var x in literal.Values) { var identifierKey=x.Key as ast.ExprNodeIdentifier; if (identifierKey!=null && identifierKey.Lhs==null) { currentScope.ProcessAccessibilitySpecs(target, identifierKey.Name, identifierKey.Bookmark); } } } } return true; } // Define parameters in the current scope if (n.GetType() == typeof(ast.Parameter)) { var p = (ast.Parameter)n; DefineLocalSymbol(p.Name, p.Bookmark); currentScope.ProcessAccessibilitySpecs(p.Name, p.Bookmark); return true; } // Automatic declaration of private member? // We're looking for an assignment to a matching private spec if (n.GetType() == typeof(ast.StatementExpression)) { var exprstmt = (ast.StatementExpression)n; if (exprstmt.Expression.RootNode.GetType()==typeof(ast.ExprNodeAssignment)) { var assignOp = (ast.ExprNodeAssignment)exprstmt.Expression.RootNode; if (assignOp.Op == Token.assign) { // Lhs must be an identifier member // eg: target.member=<expr> if (assignOp.Lhs.GetType()==typeof(ast.ExprNodeIdentifier)) { var identifier=(ast.ExprNodeIdentifier)assignOp.Lhs; if (identifier.Lhs!=null) { // For member specs, the identifier must have a lhs if (identifier.Lhs.GetType() != typeof(ast.ExprNodeIdentifier)) return false; currentScope.ProcessAccessibilitySpecs((ast.ExprNodeIdentifier)identifier.Lhs, identifier.Name, identifier.Bookmark); } } // Assignment of an object literal // eg: target={member:value,member:value}; if (assignOp.Lhs.GetType() == typeof(ast.ExprNodeIdentifier) && assignOp.Rhs.GetType() == typeof(ast.ExprNodeObjectLiteral)) { var target = (ast.ExprNodeIdentifier)assignOp.Lhs; var literal=(ast.ExprNodeObjectLiteral)assignOp.Rhs; if (target.Lhs == null) { foreach (var x in literal.Values) { var identifierKey=x.Key as ast.ExprNodeIdentifier; if (identifierKey!=null && identifierKey.Lhs==null) { currentScope.ProcessAccessibilitySpecs(target, identifierKey.Name, identifierKey.Bookmark); } } } } /* if (assignOp.Rhs.GetType() == typeof(ast.ExprNodeObjectLiteral)) { var literal=ast.ExprNode } */ } } } // Normally accessibility specs are already processed in the scope builder, but this // is a special case for declaring external symbols. We need to pick up the explicit // symbol declaration and add it to the pseudo scope to avoid incorrect warnings. // Use case is declaring `x` as an external global var by: // // // public:x // if (n.GetType() == typeof(ast.StatementAccessibility)) { var p = (ast.StatementAccessibility)n; foreach (var s in p.Specs) { if (!s.IsWildcard() && !s.IsMemberSpec()) currentPseudoScope.Symbols.DefineSymbol(s.GetExplicitName(), n.Bookmark); } } return true; }
public bool OnEnterNode(MiniME.ast.Node n) { // Define name of function in outer scope, before descending if (n.GetType() == typeof(ast.ExprNodeFunction)) { var fn = (ast.ExprNodeFunction)n; // Define a symbol for the new function if (!String.IsNullOrEmpty(fn.Name)) { currentScope.Symbols.UseSymbol(fn.Name); } } // Descending into an inner scope if (n.Scope != null) { System.Diagnostics.Debug.Assert(n.Scope.OuterScope == currentScope); currentScope = n.Scope; } // Identifier? if (n.GetType() == typeof(ast.ExprNodeIdentifier)) { var m = (ast.ExprNodeIdentifier)n; if (m.Lhs == null) { currentScope.Symbols.UseSymbol(m.Name); } else { currentScope.Members.UseSymbol(m.Name); } } // Use catch clause exception variables in the inner scope if (n.GetType() == typeof(ast.CatchClause)) { var cc = (ast.CatchClause)n; currentScope.Symbols.UseSymbol(cc.ExceptionVariable); return true; } // Use variables in the current scope if (n.GetType() == typeof(ast.StatementVariableDeclaration)) { var vardecl = (ast.StatementVariableDeclaration)n; foreach (var v in vardecl.Variables) { currentScope.Symbols.UseSymbol(v.Name); } return true; } // Use parameters in the current scope if (n.GetType() == typeof(ast.Parameter)) { var p = (ast.Parameter)n; currentScope.Symbols.UseSymbol(p.Name); return true; } // Look for assignment to undefined variable if (n.GetType() == typeof(ast.ExprNodeAssignment)) { var rtlOp = (ast.ExprNodeAssignment)n; if (rtlOp.Op == Token.assign) { if (rtlOp.Lhs.GetType() == typeof(ast.ExprNodeIdentifier)) { var identifier = (ast.ExprNodeIdentifier)rtlOp.Lhs; if (identifier.Lhs == null) { // Assignment to an identifier if (currentScope.FindSymbol(identifier.Name) == null) { currentScope.Compiler.RecordWarning(identifier.Bookmark, "assignment to undeclared variable `{0}` introduces new global variable", identifier.Name); } } } } } return true; }