using System; using System.Collections; using System.IO; using System.Diagnostics; public abstract class bind { protected MessageWriter msg; public bind(MessageWriter msg) { this.msg = msg; } public static void import(string name, Imports imp, MessageWriter msg) { if (!imp.Load(name)) msg.Warning("can't find '{0}'", name); } public static object visit(object ast, TextWriter w, string[] args, MessageWriter msg) { NameSpace global = null; if (msg.Count == 0) { global = ((compilation)ast).global; bool nostdlib = false; foreach (string s in ((compilation)ast).args) if (s.Replace('/', '-').ToLower() == "-nostdlib") { nostdlib = true; break; } if (!nostdlib) { import("mscorlib.dll", global.imports, msg); import("System.dll", global.imports, msg); } (new Pass1(msg)).compilation((compilation)ast, global.members); } if (msg.Count == 0) (new Pass2(msg)).compilation((compilation)ast, global.members); if (msg.Count == 0) (new Pass3(msg)).compilation((compilation)ast, global.members); return ast; } static public string binaryOpName(InputElement op) { return binaryOpName(op.str); } static public string binaryOpName(string op) { switch (op) { case "+": return "op_Addition"; case "-": return "op_Subtraction"; case "*": return "op_Multiply"; case "/": return "op_Division"; case "%": return "op_Remainder"; case "&&": case "&": return "op_BitwiseAnd"; case "||": case "|": return "op_BitwiseOr"; case "^": return "op_BitwiseXor"; case "<<": return "op_LeftShift"; case ">>": return "op_RightShift"; case "==": return "op_Equality"; case "!=": return "op_Inequality"; case ">": return "op_GreaterThan"; case "<": return "op_LessThan"; case ">=": return "op_GreaterThanOrEqual"; case "<=": return "op_LessThanOrEqual"; default: throw new ArgumentException(op); } } public static string unaryOpName(InputElement op) { return unaryOpName(op.str); } public static string unaryOpName(string op) { switch (op) { case "+": return "op_UnaryPlus"; case "-": return "op_UnaryMinus"; case "!": return "op_LogicalNot"; case "~": return "op_OnesComplement"; case "++": return "op_Increment"; case "--": return "op_Decrement"; case "true": return "op_True"; case "false": return "op_False"; default: throw new ArgumentException(op); } } protected BuiltinTypes Type; public virtual void compilation(compilation ast) { Type = ast.global.Types; Type.msg = msg; } public abstract void namespace_declaration(namespace_declaration ast, SymbolTable bindings); public abstract void class_declaration(class_declaration ast, SymbolTable bindings); public abstract void constant_declaration(constant_declaration ast, SymbolTable bindings); public abstract void constructor_declaration(constructor_declaration ast, SymbolTable bindings); public abstract void delegate_declaration(delegate_declaration ast, SymbolTable bindings); public abstract void destructor_declaration(destructor_declaration ast, SymbolTable bindings); public abstract void enum_declaration(enum_declaration ast, SymbolTable bindings); public abstract void event_declaration1(event_declaration1 ast, SymbolTable bindings); public abstract void event_declaration2(event_declaration2 ast, SymbolTable bindings); public abstract void field_declaration(field_declaration ast, SymbolTable bindings); public abstract void indexer_declaration(indexer_declaration ast, SymbolTable bindings); public abstract void interface_declaration(interface_declaration ast, SymbolTable bindings); public abstract void interface_event_declaration(interface_event_declaration ast, SymbolTable bindings); public abstract void interface_indexer_declaration(interface_indexer_declaration ast, SymbolTable bindings); public abstract void interface_method_declaration(interface_method_declaration ast, SymbolTable bindings); public abstract void interface_property_declaration(interface_property_declaration ast, SymbolTable bindings); public abstract void method_declaration(method_declaration ast, SymbolTable bindings); public abstract void operator_declaration(operator_declaration ast, SymbolTable bindings); public abstract void property_declaration(property_declaration ast, SymbolTable bindings); public abstract void struct_declaration(struct_declaration ast, SymbolTable bindings); public virtual void declaration(declaration ast, SymbolTable bindings) { if (ast is namespace_declaration) namespace_declaration((namespace_declaration)ast, bindings); else if (ast is class_declaration) class_declaration((class_declaration)ast, bindings); else if (ast is constant_declaration) constant_declaration((constant_declaration)ast, bindings); else if (ast is constructor_declaration) constructor_declaration((constructor_declaration)ast, bindings); else if (ast is delegate_declaration) delegate_declaration((delegate_declaration)ast, bindings); else if (ast is destructor_declaration) destructor_declaration((destructor_declaration)ast, bindings); else if (ast is enum_declaration) enum_declaration((enum_declaration)ast, bindings); else if (ast is event_declaration1) event_declaration1((event_declaration1)ast, bindings); else if (ast is event_declaration2) event_declaration2((event_declaration2)ast, bindings); else if (ast is field_declaration) field_declaration((field_declaration)ast, bindings); else if (ast is indexer_declaration) indexer_declaration((indexer_declaration)ast, bindings); else if (ast is interface_declaration) interface_declaration((interface_declaration)ast, bindings); else if (ast is interface_event_declaration) interface_event_declaration((interface_event_declaration)ast, bindings); else if (ast is interface_indexer_declaration) interface_indexer_declaration((interface_indexer_declaration)ast, bindings); else if (ast is interface_method_declaration) interface_method_declaration((interface_method_declaration)ast, bindings); else if (ast is interface_property_declaration) interface_property_declaration((interface_property_declaration)ast, bindings); else if (ast is method_declaration) method_declaration((method_declaration)ast, bindings); else if (ast is operator_declaration) operator_declaration((operator_declaration)ast, bindings); else if (ast is property_declaration) property_declaration((property_declaration)ast, bindings); else if (ast is struct_declaration) struct_declaration((struct_declaration)ast, bindings); else throw new ArgumentException(); } public abstract void binary_declarator(binary_declarator ast, SymbolTable bindings); public abstract void explicit_declarator(explicit_declarator ast, SymbolTable bindings); public abstract void implicit_declarator(implicit_declarator ast, SymbolTable bindings); public abstract void unary_declarator(unary_declarator ast, SymbolTable bindings); public virtual void operator_declarator(operator_declarator ast, SymbolTable bindings) { if (ast is binary_declarator) binary_declarator((binary_declarator)ast, bindings); else if (ast is explicit_declarator) explicit_declarator((explicit_declarator)ast, bindings); else if (ast is implicit_declarator) implicit_declarator((implicit_declarator)ast, bindings); else if (ast is unary_declarator) unary_declarator((unary_declarator)ast, bindings); else throw new ArgumentException(); } public abstract void arglist_parameter(arglist_parameter ast, SymbolTable bindings); public abstract void fixed_parameter(fixed_parameter ast, SymbolTable bindings); public abstract void params_parameter(params_parameter ast, SymbolTable bindings); public virtual void parameter(parameter ast, SymbolTable bindings) { if (ast is arglist_parameter) arglist_parameter((arglist_parameter)ast, bindings); else if (ast is fixed_parameter) fixed_parameter((fixed_parameter)ast, bindings); else if (ast is params_parameter) params_parameter((params_parameter)ast, bindings); else throw new ArgumentException(); } public virtual void block_statement(block_statement ast, SymbolTable bindings) {} public virtual void break_statement(break_statement ast, SymbolTable bindings) {} public virtual void checked_statement(checked_statement ast, SymbolTable bindings) {} public virtual void const_statement(const_statement ast, SymbolTable bindings) {} public virtual void continue_statement(continue_statement ast, SymbolTable bindings) {} public virtual void do_statement(do_statement ast, SymbolTable bindings) {} public virtual void empty_statement(empty_statement ast, SymbolTable bindings) {} public virtual void expression_statement(expression_statement ast, SymbolTable bindings) {} public virtual void fixed_statement(fixed_statement ast, SymbolTable bindings) {} public virtual void foreach_statement(foreach_statement ast, SymbolTable bindings) {} public virtual void for_statement(for_statement ast, SymbolTable bindings) {} public virtual void goto_case_statement(goto_case_statement ast, SymbolTable bindings) {} public virtual void goto_default_statement(goto_default_statement ast, SymbolTable bindings) {} public virtual void goto_statement(goto_statement ast, SymbolTable bindings) {} public virtual void if_statement(if_statement ast, SymbolTable bindings) {} public virtual void labeled_statement(labeled_statement ast, SymbolTable bindings) {} public virtual void local_statement(local_statement ast, SymbolTable bindings) {} public virtual void lock_statement(lock_statement ast, SymbolTable bindings) {} public virtual void return_statement(return_statement ast, SymbolTable bindings) {} public virtual void switch_statement(switch_statement ast, SymbolTable bindings) {} public virtual void throw_statement(throw_statement ast, SymbolTable bindings) {} public virtual void try_statement(try_statement ast, SymbolTable bindings) {} public virtual void unchecked_statement(unchecked_statement ast, SymbolTable bindings) {} public virtual void unsafe_statement(unsafe_statement ast, SymbolTable bindings) { } public virtual void using_statement(using_statement ast, SymbolTable bindings) {} public virtual void while_statement(while_statement ast, SymbolTable bindings) {} public virtual void statement(statement ast, SymbolTable bindings) { if (ast is block_statement) block_statement((block_statement)ast, bindings); else if (ast is break_statement) break_statement((break_statement)ast, bindings); else if (ast is checked_statement) checked_statement((checked_statement)ast, bindings); else if (ast is const_statement) const_statement((const_statement)ast, bindings); else if (ast is continue_statement) continue_statement((continue_statement)ast, bindings); else if (ast is do_statement) do_statement((do_statement)ast, bindings); else if (ast is empty_statement) empty_statement((empty_statement)ast, bindings); else if (ast is expression_statement) expression_statement((expression_statement)ast, bindings); else if (ast is fixed_statement) fixed_statement((fixed_statement)ast, bindings); else if (ast is foreach_statement) foreach_statement((foreach_statement)ast, bindings); else if (ast is for_statement) for_statement((for_statement)ast, bindings); else if (ast is goto_case_statement) goto_case_statement((goto_case_statement)ast, bindings); else if (ast is goto_default_statement) goto_default_statement((goto_default_statement)ast, bindings); else if (ast is goto_statement) goto_statement((goto_statement)ast, bindings); else if (ast is if_statement) if_statement((if_statement)ast, bindings); else if (ast is labeled_statement) labeled_statement((labeled_statement)ast, bindings); else if (ast is local_statement) local_statement((local_statement)ast, bindings); else if (ast is lock_statement) lock_statement((lock_statement)ast, bindings); else if (ast is return_statement) return_statement((return_statement)ast, bindings); else if (ast is switch_statement) switch_statement((switch_statement)ast, bindings); else if (ast is throw_statement) throw_statement((throw_statement)ast, bindings); else if (ast is try_statement) try_statement((try_statement)ast, bindings); else if (ast is unchecked_statement) unchecked_statement((unchecked_statement)ast, bindings); else if (ast is unsafe_statement) unsafe_statement((unsafe_statement)ast, bindings); else if (ast is using_statement) using_statement((using_statement)ast, bindings); else if (ast is while_statement) while_statement((while_statement)ast, bindings); else throw new ArgumentException(); } abstract public Symbol dotted_name(dotted_name ast, SymbolTable bindings); public virtual Type type(type ast, SymbolTable bindings) { if (ast is array_type) return new ArrayType(type(((array_type)ast).ty, bindings), ((array_type)ast).rank_specifier + 1, Type.Array); else if (ast is bool_type) return Type.Bool; else if (ast is byte_type) return Type.Byte; else if (ast is char_type) return Type.Char; else if (ast is decimal_type) return Type.Decimal; else if (ast is double_type) return Type.Double; else if (ast is float_type) return Type.Float; else if (ast is int_type) return Type.Int; else if (ast is long_type) return Type.Long; else if (ast is name_type) { Type ty = dotted_name(((name_type)ast).name, bindings) as Type; if (ty == null) ty = Type.Int; return ty; } else if (ast is object_type) return Type.Object; else if (ast is pointer_type) return new UnmanagedPointerType(type(((pointer_type)ast).ty, bindings)); else if (ast is sbyte_type) return Type.SByte; else if (ast is short_type) return Type.Short; else if (ast is string_type) return Type.String; else if (ast is uint_type) return Type.UInt; else if (ast is ulong_type) return Type.ULong; else if (ast is ushort_type) return Type.UShort; else if (ast is void_pointer_type) return new UnmanagedPointerType(Type.Void); else if (ast is void_type) return Type.Void; else throw new ArgumentException(); } } public class Pass1: bind { string unsafeModifier = ""; public Pass1(MessageWriter msg) : base(msg) {} public virtual void AddModifiers(Symbol t, InputElementList mods, string validModifiers, string defaultaccess) { int count = 0; validModifiers += unsafeModifier; stringList modifiers = new stringList(); for (int i = 0; i < mods.Count; i++) { string m = mods[i].str; if (modifiers.Contains(m)) msg.Error(mods[i], "duplicate '{0}' modifier", m); else if (validModifiers.IndexOf(m) < 0) { if (m == "unsafe") msg.Error(mods[i], "unsafe code permitted only when compiling with /unsafe"); else msg.Error(mods[i], "'{0}' modifier is not permitted in this context", m); } else if (m == "protected" && modifiers.Contains("internal") || m == "internal" && modifiers.Contains("protected")) modifiers.Add(m); else { if (m == "private" || m == "public" || m == "protected" || m == "internal") if (++count >= 2) msg.Error(mods[i], "more than one access modifier"); modifiers.Add(m); } } if (count == 0 && defaultaccess != null) modifiers.Add(defaultaccess); t.Modifiers = modifiers; } override public void arglist_parameter(arglist_parameter ast, SymbolTable bindings) { ast.method.AddFormal(ast.arglist, msg); } public virtual void argument(argument ast, SymbolTable bindings) { } public virtual void attribute(attribute ast, SymbolTable bindings) { if (ast.arguments != null) attribute_arguments(ast.arguments, bindings); } public virtual void attribute_arguments(attribute_arguments ast, SymbolTable bindings) { foreach (named_argument x in ast.namedargs) named_argument(x, bindings); } public virtual void attribute_section(attribute_section ast, SymbolTable bindings) { foreach (attribute x in ast.attributes) attribute(x, bindings); } public virtual void attribute_sections(attribute_sectionList attrs, SymbolTable bindings) { foreach (attribute_section x in attrs) attribute_section(x, bindings); } override public void binary_declarator(binary_declarator ast, SymbolTable bindings) { ClassType c = (ClassType)bindings.Owner; Method m = c.AddMethod(new InputElement(binaryOpName(ast.op), ast.begin), msg); ast.sym1 = m.AddFormal(ast.id1, msg); ast.sym2 = m.AddFormal(ast.id2, msg); ast.method = m; } override public void block_statement(block_statement ast, SymbolTable bindings) { Block b = new Block(bindings); foreach (statement x in ast.stmts) statement(x, b.locals); ast.sym = b; } override public void break_statement(break_statement ast, SymbolTable bindings) { ast.stmt = loop_exit(ast, "break"); } public virtual void catch_clause(catch_clause ast, SymbolTable bindings) { Debug.Assert(bindings.Owner is Block); statement(ast.block, bindings); if (ast.id != null) ast.sym = ((block_statement)ast.block).sym.AddLocal(ast.id, msg); } public virtual void catch_clauses(catch_clauses ast, SymbolTable bindings) { foreach (catch_clause x in ast.specifics) catch_clause(x, bindings); if (ast.general != null) statement(ast.general, bindings); } public virtual void CheckIndexers(attribute_sectionList attrs, declarationList decls) { foreach (declaration d in decls) if (d is indexer_declaration || d is interface_indexer_declaration) { // [System.Reflection.DefaultMemberAttribute("Item")] dotted_name name = null; foreach (string id in new string[] { "System", "Reflection", "DefaultMemberAttribute" }) name = new dotted_name(name, new InputElement(id)); string_literal Item = new string_literal(new InputElement("string-literal", "\"Item\"", "", 0, 0)); attribute_section ast = new attribute_section(null, attributeList.New(new attribute( new name_type(name), new attribute_arguments(expressionList.New(Item), named_argumentList.New())))); attrs.Add(ast); break; } } override public void checked_statement(checked_statement ast, SymbolTable bindings) { statement(ast.stmt, bindings); } public virtual void CheckMethodModifiers(Symbol t) { if (t.IsAny("static", "virtual", "override") > 1) msg.Error(t.id, "{0} '{1}' cannot specify more than one of 'static', 'virtual', or 'override'", t.Kind, t.FullName); if (t.IsAny("new", "override") > 1) msg.Error(t.id, "{0} '{1}' cannot specify 'new' and 'override'", t.Kind, t.FullName); if (t.Is("abstract") && t.IsAny("static", "virtual", "extern") > 0) msg.Error(t.id, "abstract {0} '{1}' cannot specify any of 'static', 'virtual' or 'extern'", t.Kind, t.FullName); if (t.Is("private") && t.IsAny("abstract", "virtual", "override") > 0) msg.Error(t.id, "private {0} '{1}' cannot specify any of 'abstract', 'virtual' or 'override'", t.Kind, t.FullName); if (t.Is("sealed") && !t.Is("override")) msg.Error(t.id, "sealed {0} '{1}' must also specify 'override'", t.Kind, t.FullName); if (t.Name == t.declSpace.Owner.Name) msg.Error(t.id, "{0} '{1}' cannot be the same as its enclosing type '{2}'", t.Kind, t.Name, t.declSpace.Owner.FullName); } override public void class_declaration(class_declaration ast, SymbolTable bindings) { ClassType t = new ClassType(ast.id, bindings); if (bindings.Owner is ClassType) t.enclosingType = (ClassType)bindings.Owner; CheckIndexers(ast.attrs, ast.body); attribute_sections(ast.attrs, bindings); t.Add(ast.id, bindings, msg); AddModifiers(t, ast.mods, "new public protected internal private abstract sealed", bindings.Owner is ClassType ? "private" : "internal"); if (t.Is("abstract") && t.Is("sealed")) msg.Error(t.id, "{0} '{1}' cannot be 'abstract' and 'sealed'", t.Kind, t.FullName); foreach (declaration x in ast.body) declaration(x, t.members); default_constructors(t, ast, ast.body); ast.sym = t; } public virtual void compilation(compilation ast, SymbolTable bindings) { foreach (string s in ast.args) if (s.Replace('/', '-').ToLower() == "-unsafe") { unsafeModifier = " unsafe"; break; } base.compilation(ast); foreach (compilation_unit x in ast.inputs) compilation_unit(x, bindings); } public virtual void compilation_unit(compilation_unit ast, SymbolTable bindings) { ast.sym = (NameSpace)bindings.Owner; SymbolList usingdirectives = new SymbolList(); foreach (using_directive x in ast.using_directives) using_directive(x, bindings, usingdirectives); ast.sym.usingdirectives = usingdirectives; attribute_sections(ast.attributes, bindings); foreach (declaration x in ast.declarations) { declaration(x, bindings); if (contains(x.mods, "protected") || contains(x.mods, "private")) msg.Error(x.begin, "Namespace members cannot be declared 'private' or 'protected'"); } ast.sym.usingdirectives = null; } override public void const_statement(const_statement ast, SymbolTable bindings) { Block b = (Block)bindings.Owner; foreach (const_declarator x in ast.consts) { x.sym = b.AddConstant(x.id, msg); x.sym.value = x; // signifies "undefined" } } override public void constant_declaration(constant_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ClassType c = (ClassType)bindings.Owner; foreach (const_declarator x in ast.decls) { x.sym = c.AddConstant(x.id, msg); AddModifiers(x.sym, ast.mods, "new public protected internal private", "private"); x.sym.value = x; // signifies "undefined" } } override public void constructor_declaration(constructor_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); Constructor t; if (contains(ast.mods, "static")) { t = static_constructor_declarator(ast.decl, bindings); AddModifiers(t, ast.mods, "static extern", "private"); } else { t = constructor_declarator(ast.decl, bindings); AddModifiers(t, ast.mods, "public protected internal private extern", "private"); } method_body(t, ast, ast.block, t.locals); ast.sym = t; } public virtual Constructor constructor_declarator(constructor_declarator ast, SymbolTable bindings) { ClassType c = (ClassType)bindings.Owner; if (c.Name != ast.id.str) msg.Error(ast.id, "'{0}' is an invalid constructor name", ast.id.str); Constructor t = c.AddConstructor(ast.id, msg); formals(ast.f, bindings, t); if (c is StructType) { if (t.ArgCount == 0 && t.IsInstance) msg.Error(ast.id, "structs may not declare a parameterless instance constructor"); if (ast.init is base_initializer) msg.Error(ast.id, "struct instance constructors may not specify a base initializer"); } else if (ast.init == null && t.IsInstance && c.baseClass != null) { ast.init = new base_initializer(new argumentList()); ast.init.link(ast); ast.init.begin = ast.begin; ast.init.end = ast.end; } return t; } public static bool contains(InputElementList mods, string modifier) { foreach (InputElement x in mods) if (x.str == modifier) return true; return false; } override public void continue_statement(continue_statement ast, SymbolTable bindings) { ast.stmt = loop_exit(ast, "continue"); } public virtual void default_constructors(ClassType t, declaration ast, declarationList body) { bool needstatic = false, needinstance = true; foreach (declaration d in body) if (d is field_declaration) foreach (field_declarator f in ((field_declaration)d).decls) if (f.sym.IsStatic && f.init != null) needstatic = true; foreach (declaration d in body) if (d is constructor_declaration) if (((constructor_declaration)d).sym.IsInstance) needinstance = false; else needstatic = false; if (needinstance || t is StructType) { constructor_declaration decl = new constructor_declaration( attribute_sectionList.New(), InputElementList.New(new InputElement(t.Is("abstract") ? "protected" : "public")), new constructor_declarator( new InputElement(t.Name), new formals(parameterList.New(), null), new base_initializer(new argumentList())), new block_statement(statementList.New())); decl.link(ast); declaration(decl, t.members); body.Add(decl); } if (needstatic) { constructor_declaration decl = new constructor_declaration( attribute_sectionList.New(), InputElementList.New(new InputElement("static")), new constructor_declarator( new InputElement(t.Name), new formals(parameterList.New(), null), null), new block_statement(statementList.New())); decl.link(ast); declaration(decl, t.members); body.Add(decl); } } override public void delegate_declaration(delegate_declaration ast, SymbolTable bindings) { DelegateType t = new DelegateType(ast.id, bindings); t.baseClass = Type.MulticastDelegate; attribute_sections(ast.attrs, bindings); t.Add(ast.id, bindings, msg); AddModifiers(t, ast.mods, "new public protected internal private", bindings.Owner is ClassType ? "private" : "internal"); t.Modifiers.Add("sealed"); // Invoke t.invoke = t.AddMethod(new InputElement("Invoke", ast.id.coord), msg); t.invoke.Modifiers.Add("public"); t.invoke.Modifiers.Add("virtual"); formals(ast.f, t.invoke.locals, t.invoke); // constructor Method m = t.AddConstructor(ast.id, msg); m.Modifiers.Add("public"); m.AddFormal(new InputElement("object", ast.id.coord), msg).Type = Type.Object; m.AddFormal(new InputElement("method", ast.id.coord), msg).Type = Type.IntPtr; m.Type = Type.Void; ast.sym = t; } override public void destructor_declaration(destructor_declaration ast, SymbolTable bindings) { ClassType c = (ClassType)bindings.Owner; attribute_sections(ast.attrs, bindings); if (c.Name != ast.id.str) msg.Error(ast.id, "'{0}' is an invalid destructor name", ast.id.str); if (c is StructType) msg.Error(ast.id, "structs may not declare a destructor"); Method t = c.AddMethod(new InputElement("Finalize", ast.id.coord), msg); AddModifiers(t, ast.mods, "extern", "private"); method_body(t, ast, ast.block, t.locals); ast.sym = t; } override public void do_statement(do_statement ast, SymbolTable bindings) { statement(ast.body, bindings); } override public Symbol dotted_name(dotted_name ast, SymbolTable bindings) { Symbol t; NameSpace n = (NameSpace)bindings.Owner; if (ast.left != null) { n = (NameSpace)dotted_name(ast.left, bindings); if (n == null) return null; t = n[ast.right.str]; } else t = n.Lookup(ast.right, msg); // searches using namespaces, too if (t == null) { t = new NameSpace(ast.right, n.members); t.Add(ast.right, msg); } return t as NameSpace; } override public void enum_declaration(enum_declaration ast, SymbolTable bindings) { EnumType t = new EnumType(ast.id, bindings); if (bindings.Owner is ClassType) t.enclosingType = (ClassType)bindings.Owner; attribute_sections(ast.attrs, bindings); t.Add(ast.id, bindings, msg); AddModifiers(t, ast.mods, "new public protected internal private", bindings.Owner is ClassType ? "private" : "internal"); foreach (enum_member_declaration x in ast.body) enum_member_declaration(x, t.members); ast.sym = t; } public virtual void enum_member_declaration(enum_member_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); EnumType c = (EnumType)bindings.Owner; ast.sym = c.AddEnumMember(ast.id, msg); ast.sym.value = ast; // signifies "undefined" } public virtual void event_accessor(event_accessor ast, Event t, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); Method m = ast.id.str == "add" ? t.Add : t.Remove; method_body(t, ast, ast.block, m.locals); m.Modifiers = t.Modifiers; ast.sym = m; } override public void event_declaration1(event_declaration1 ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ClassType c = (ClassType)bindings.Owner; foreach (event_declarator x in ast.decls) { Event t = c.AddEvent(x.id, msg); t.IsFieldLike = true; AddModifiers(t, ast.mods, "new public protected internal private static virtual sealed override abstract extern", "private"); CheckMethodModifiers(t); t.Add.Type = Type.Void; t.Add.Modifiers = t.Modifiers; t.Remove.Type = Type.Void; t.Remove.Modifiers = t.Modifiers; x.sym = t; } } override public void event_declaration2(event_declaration2 ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ClassType c = (ClassType)bindings.Owner; Event t = c.AddEvent(member_name(ast.name, bindings), msg); if (ast.name.ty != null) AddModifiers(t, ast.mods, "extern", "private"); else { AddModifiers(t, ast.mods, "new public protected internal private static virtual sealed override", "private"); CheckMethodModifiers(t); } foreach (event_accessor x in ast.accessors) event_accessor(x, t, bindings); t.Add.Type = Type.Void; t.Remove.Type = Type.Void; ast.sym = t; } override public void explicit_declarator(explicit_declarator ast, SymbolTable bindings) { ClassType c = (ClassType)bindings.Owner; Method m = c.AddMethod(new InputElement("op_Explicit", ast.begin), msg); ast.sym = m.AddFormal(ast.id1, msg); ast.method = m; } override public void field_declaration(field_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ClassType c = (ClassType)bindings.Owner; foreach (field_declarator x in ast.decls) { Field t = c.AddField(x.id, msg); AddModifiers(t, ast.mods, "new public protected internal private static readonly volatile", "private"); if (t.Name == c.Name) msg.Error(t.id, "{0} '{1}' cannot be the same as its enclosing type '{2}'", t.Kind, t.Name, c.FullName); if (t.Is("readonly") && t.Is("volatile")) msg.Error(t.id, "{0} {1} cannot be 'readonly' and 'volatile'", t.Kind, t.FullName); if (x.init != null) { if (c is StructType && t.IsInstance) msg.Error(x.id, "struct instance field '{1}' cannot have an initializer", x.id.str); } t.Modifiers.Remove("new"); x.sym = t; } } override public void fixed_parameter(fixed_parameter ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ast.method.AddFormal(ast.id, msg).modifier = ast.mod; } override public void fixed_statement(fixed_statement ast, SymbolTable bindings) { Block b = (Block)bindings.Owner; foreach (fixed_declarator x in ast.declarators) x.sym = b.AddLocal(x.id, msg); statement(ast.body, bindings); } override public void for_statement(for_statement ast, SymbolTable bindings) { Block b = new Block(bindings); statement(ast.body, b.locals); ast.sym = b; } override public void foreach_statement(foreach_statement ast, SymbolTable bindings) { Block b = new Block(bindings); Local t = b.AddLocal(ast.id, msg); t.ReadOnly = true; statement(ast.body, b.locals); ast.sym = t; } public virtual void formals(formals ast, SymbolTable bindings, Method m) { foreach (parameter x in ast.fixeds) { x.method = m; parameter(x, bindings); } if (ast.param != null) { ast.param.method = m; parameter(ast.param, bindings); } } override public void if_statement(if_statement ast, SymbolTable bindings) { statement(ast.thenpart, bindings); if (ast.elsepart != null) statement(ast.elsepart, bindings); } override public void implicit_declarator(implicit_declarator ast, SymbolTable bindings) { ClassType c = (ClassType)bindings.Owner; Method m = c.AddMethod(new InputElement("op_Implicit", ast.begin), msg); ast.sym = m.AddFormal(ast.id1, msg); ast.method = m; } override public void indexer_declaration(indexer_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ClassType c = (ClassType)bindings.Owner; string prefix = ""; if (ast.i.interfacename != null) prefix = ast.i.interfacename.name.ToString() + "."; foreach (accessor_declaration x in ast.accessors) { attribute_sections(x.attrs, bindings); Method m = c.AddMethod(new InputElement(prefix + x.id.str + "_Item", x.id.coord), msg); if (ast.i.interfacename != null) AddModifiers(m, ast.mods, "extern", "private"); else { AddModifiers(m, ast.mods, "new public protected internal private virtual sealed override abstract extern", "private"); CheckMethodModifiers(m); } formals(ast.i.f, bindings, m); if (x.id.str == "set") { Formal value = m.AddFormal(new InputElement("value", x.id.coord), msg); m.signature.formals.Remove(value); } method_body(m, x, x.body, m.locals); x.sym = m; } } override public void interface_declaration(interface_declaration ast, SymbolTable bindings) { InterfaceType t = new InterfaceType(ast.id, bindings); t.Add(ast.id, bindings, msg); CheckIndexers(ast.attrs, ast.body); attribute_sections(ast.attrs, bindings); AddModifiers(t, ast.mods, "new public protected internal private", bindings.Owner is ClassType ? "private" : "internal"); foreach (declaration x in ast.body) declaration(x, t.members); ast.sym = t; } override public void interface_event_declaration(interface_event_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); InterfaceType c = (InterfaceType)bindings.Owner; Event t = c.AddEvent(ast.id, msg); AddModifiers(t, ast.mods, "new", "public"); CheckMethodModifiers(t); foreach (string mod in t.Modifiers) { t.Add.Modifiers.Add(mod); t.Remove.Modifiers.Add(mod); } t.Add.Type = Type.Void; t.Add.Modifiers.Add("abstract"); t.Add.Modifiers.Add("virtual"); t.Remove.Type = Type.Void; t.Remove.Modifiers.Add("abstract"); t.Remove.Modifiers.Add("virtual"); ast.sym = t; } override public void interface_indexer_declaration(interface_indexer_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); InterfaceType c = (InterfaceType)bindings.Owner; foreach (accessor_declaration x in ast.accessors) { attribute_sections(x.attrs, bindings); Method m = c.AddMethod(new InputElement(x.id.str + "_Item", x.id.coord), msg); formals(ast.f, bindings, m); if (x.id.str == "set") { Formal value = m.AddFormal(new InputElement("value", x.id.coord), msg); m.signature.formals.Remove(value); } m.Modifiers.Add("public"); m.Modifiers.Add("abstract"); m.Modifiers.Add("virtual"); x.sym = m; } } override public void interface_method_declaration(interface_method_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); InterfaceType c = (InterfaceType)bindings.Owner; Method t = c.AddMethod(ast.id, msg); AddModifiers(t, ast.mods, "new", "public"); formals(ast.f, bindings, t); t.Modifiers.Add("abstract"); t.Modifiers.Add("virtual"); ast.sym = t; } override public void interface_property_declaration(interface_property_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); InterfaceType c = (InterfaceType)bindings.Owner; Property t = c.AddProperty(ast.id, msg); AddModifiers(t, ast.mods, "new", "public"); foreach (accessor_declaration x in ast.accessors) { attribute_sections(x.attrs, bindings); Method m; if (x.id.str == "get") m = t.AddGet(ast.id); else { m = t.AddSet(ast.id); m.Type = Type.Void; } m.Modifiers.Add("public"); m.Modifiers.Add("abstract"); m.Modifiers.Add("virtual"); x.sym = m; } ast.sym = t; } override public void labeled_statement(labeled_statement ast, SymbolTable bindings) { ast.sym = ((Block)bindings.Owner).AddLabel(ast.label, msg); ast.sym.definition = ast; statement(ast.stmt, bindings); } override public void lock_statement(lock_statement ast, SymbolTable bindings) { statement(ast.body, bindings); } public virtual statement loop_exit(statement ast, string kind) { for (AST s = ast; s != null; s = s.parent) { if (s is finally_clause) { msg.Error(ast.begin, "invalid '{0}' statement: '{0}' cannot exit a finally block", kind); return null; } if (s is switch_statement || s is for_statement || s is foreach_statement || s is do_statement || s is while_statement) return (statement)s; } msg.Error(ast.begin, "invalid '{0}' statement", kind); return null; } public virtual InputElement member_name(member_name ast, SymbolTable bindings) { if (ast.ty is name_type) return new InputElement(((name_type)ast.ty).name.ToString() + "." + ast.id.str, ast.id.coord); else return ast.id; } public virtual void method_body(Symbol t, AST ast, statement block, SymbolTable bindings) { if (t.IsAny("extern", "abstract") > 0 && block != null) msg.Error(block.begin, "extraneous method body"); else if (t.IsAny("extern", "abstract") == 0 && block == null) msg.Error(ast.end, "missing method body"); if (block != null) statement(block, bindings); } override public void method_declaration(method_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ClassType c = (ClassType)bindings.Owner; Method t = c.AddMethod(member_name(ast.name, bindings), msg); if (ast.name.ty != null) AddModifiers(t, ast.mods, "extern", "private"); else if (c is StructType) AddModifiers(t, ast.mods, "new public protected internal private static sealed override extern", "private"); else AddModifiers(t, ast.mods, "new public protected internal private static virtual sealed override abstract extern", "private"); CheckMethodModifiers(t); formals(ast.parms, bindings, t); method_body(t, ast, ast.body, t.locals); ast.sym = t; } public virtual void named_argument(named_argument ast, SymbolTable bindings) { } public virtual void namespace_body(namespace_body ast, SymbolTable bindings) { NameSpace t = (NameSpace)bindings.Owner; SymbolList usingdirectives = new SymbolList(); foreach (using_directive x in ast.ud) using_directive(x, bindings, usingdirectives); t.usingdirectives = usingdirectives; foreach (declaration x in ast.declarations) { declaration(x, bindings); if (contains(x.mods, "protected") || contains(x.mods, "private")) msg.Error(x.begin, "namespace members cannot be declared 'private' or 'protected'"); } t.usingdirectives = null; } override public void namespace_declaration(namespace_declaration ast, SymbolTable bindings) { ast.sym = (NameSpace)dotted_name(ast.id, bindings); if (ast.sym == null) msg.Error(ast.id.begin, "'{0}' is not a namespace", ast.id.ToString()); namespace_body(ast.nb, ast.sym == null ? bindings : ast.sym.members); } override public void operator_declaration(operator_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); operator_declarator(ast.op, bindings); Method m = ast.op.method; AddModifiers(m, ast.mods, "extern static public", null); if (!m.Is("public") && !m.Is("static")) msg.Error(ast.op.begin, "operators must declared 'public' and 'static'"); method_body(m, ast, ast.block, m.locals); ast.sym = m; } override public void params_parameter(params_parameter ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ast.method.AddFormal(ast.id, msg).IsParams = true; } override public void property_declaration(property_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); ClassType c = (ClassType)bindings.Owner; Property t = c.AddProperty(member_name(ast.name, bindings), msg); if (ast.name.ty != null) AddModifiers(t, ast.mods, "extern", "private"); else { AddModifiers(t, ast.mods, "new public protected internal private static virtual sealed override abstract extern", "private"); CheckMethodModifiers(t); } foreach (accessor_declaration x in ast.decls) { attribute_sections(x.attrs, bindings); Method m; if (x.id.str == "get") m = t.AddGet(member_name(ast.name, bindings)); else { m = t.AddSet(member_name(ast.name, bindings)); m.Type = Type.Void; } method_body(t, x, x.body, m.locals); m.Modifiers = t.Modifiers; x.sym = m; } ast.sym = t; } public virtual Block resource(resource ast, SymbolTable bindings) { if (ast is resource_expr) return (Block)bindings.Owner; if (ast is resource_decl) { foreach (var_declarator x in ((resource_decl)ast).local.vars) if (x.init == null) msg.Error(x.begin, "missing initializer"); return new Block(bindings); } throw new ArgumentException(); } public virtual void return_statement(statement ast, SymbolTable bindings) { if (Pass3.find_finally(ast) != null) msg.Error(ast.begin, "invalid 'return' statement: 'return' cannot exit a finally block"); } override public void statement(statement ast, SymbolTable bindings) { if (bindings.Owner is Method) ast.method = (Method)bindings.Owner; else ast.method = ((Block)bindings.Owner).GetMethod(); base.statement(ast, bindings); } public virtual Constructor static_constructor_declarator(constructor_declarator ast, SymbolTable bindings) { ClassType c = (ClassType)bindings.Owner; if (c.Name != ast.id.str) msg.Error(ast.id, "'{0}' is an invalid static constructor name", ast.id.str); Constructor t = c.AddConstructor(ast.id, msg); formals(ast.f, bindings, t); if (ast.init != null) msg.Error(ast.id, "static constructors may not have constructor initializers"); return t; } override public void struct_declaration(struct_declaration ast, SymbolTable bindings) { StructType t = new StructType(ast.id, bindings); t.Add(ast.id, bindings, msg); if (bindings.Owner is ClassType) t.enclosingType = (ClassType)bindings.Owner; CheckIndexers(ast.attrs, ast.body); attribute_sections(ast.attrs, bindings); AddModifiers(t, ast.mods, "new public protected internal private", bindings.Owner is ClassType ? "private" : "internal"); t.Modifiers.Add("sealed"); foreach (declaration x in ast.body) { declaration(x, t.members); if (contains(x.mods, "protected") || contains(x.mods, "internal")) msg.Error(x.begin, "struct members cannot be declared 'protected' or 'internal'"); } ast.sym = t; } public virtual void switch_section(switch_section ast, SymbolTable bindings) { foreach (statement x in ast.stmts) statement(x, bindings); } override public void switch_statement(switch_statement ast, SymbolTable bindings) { foreach (switch_section x in ast.sections) switch_section(x, bindings); } override public void throw_statement(throw_statement ast, SymbolTable bindings) { if (ast.expr == null) { for (AST s = ast; s != null; s = s.parent) if (s is catch_clauses) return; msg.Error(ast.begin, "invalid 'throw' statement: 'throw' may appear in only catch clauses"); } } override public void try_statement(try_statement ast, SymbolTable bindings) { statement(ast.block, bindings); if (ast.catches != null) catch_clauses(ast.catches, bindings); if (ast.finally_block != null) statement(ast.finally_block.block, bindings); } override public void unary_declarator(unary_declarator ast, SymbolTable bindings) { ClassType c = (ClassType)bindings.Owner; Method m = c.AddMethod(new InputElement(unaryOpName(ast.op), ast.begin), msg); ast.sym = m.AddFormal(ast.id1, msg); ast.method = m; } override public void unchecked_statement(unchecked_statement ast, SymbolTable bindings) { statement(ast.stmt, bindings); } public virtual void using_directive(using_directive ast, SymbolTable bindings, SymbolList usingdirectives) { if (ast is alias_directive) return; namespace_directive n = (namespace_directive)ast; NameSpace t = (NameSpace)bindings.Owner; n.sym = (NameSpace)dotted_name(n.name, bindings); if (n.sym == null) msg.Error(n.name.begin, "'{0}' is not a namespace", n.name.ToString()); else if (usingdirectives.Contains(n.sym)) msg.Warning(n.name.right, "namespace{0} already contains a using directive for '{1}'", t.declSpace == null ? "" : (" '" + t.FullName) + "'", n.name.ToString()); else usingdirectives.Add(n.sym); } override public void unsafe_statement(unsafe_statement ast, SymbolTable bindings) { msg.Warning(ast.begin, "unsafe statement not yet supported"); statement(ast.block, bindings); } override public void using_statement(using_statement ast, SymbolTable bindings) { Debug.Assert(bindings.Owner is Block); Block b = resource(ast.r, bindings); statement(ast.body, b.locals); ast.sym = b; } override public void while_statement(while_statement ast, SymbolTable bindings) { statement(ast.body, bindings); } } public class Pass2: bind { public Pass2(MessageWriter msg) : base(msg) {} override public void arglist_parameter(arglist_parameter ast, SymbolTable bindings) { Formal f= (Formal)bindings[ast.arglist.str]; f.Type = Type.RuntimeArgumentHandle; } override public void binary_declarator(binary_declarator ast, SymbolTable bindings) { ClassType c = ((Method)bindings.Owner).GetType(); type(ast.ty, bindings); ast.sym1.Type = type(ast.t1, bindings); ast.sym2.Type = type(ast.t2, bindings); if (ast.sym1.Type != c && ast.sym2.Type != c) msg.Error(ast.op, "one parameter of binary operator '{0}' must be a '{1}'", ast.op.str, c.FullName); if ((ast.op.str == "<<" || ast.op.str == ">>") && ast.sym2.Type != Type.Int) msg.Error(ast.op, "second parameter of binary operator '{0}' must be a '{1}'", ast.op.str, Type.Int.FullName); string[] pairs = new string[] { "<", ">", "==", "!=", "<=", ">=" }; int i = Array.IndexOf(pairs, ast.op.str); if (i >= 0 && c.members[binaryOpName(pairs[(i&~1)+(i+1)%2])] == null) msg.Error(ast.op, "'{0}.operator {1}({2},{3}) requires that matching operator '{4}' be defined", c.FullName, ast.op.str, ast.sym1.Type.FullName, ast.sym2.Type.FullName, pairs[(i&~1)+(i+1)%2]); } override public void class_declaration(class_declaration ast, SymbolTable bindings) { ClassType t = ast.sym; int i = 0; if (ast.bases.Count > 0) { Type b = type(ast.bases[0], bindings); if (b.IsClass) { t.baseClass = (ClassType)b; i = 1; } } for ( ; i < ast.bases.Count; i++) { Type b = type(ast.bases[i], bindings); if (b is InterfaceType) if (t.interfaces.Contains((InterfaceType)b)) msg.Error(ast.bases[i].begin, "duplicate interface '{0}'", b.Name); else t.interfaces.Add((InterfaceType)b); else msg.Error(ast.bases[i].begin, "'{0}' is not an interface type", b.Name); } if (t.baseClass == null) t.baseClass = Type.Object; if (t == t.baseClass) t.baseClass = null; foreach (declaration x in ast.body) declaration(x, t.members); } public virtual void compilation(compilation ast, SymbolTable bindings) { base.compilation(ast); foreach (compilation_unit x in ast.inputs) compilation_unit(x, bindings); } public virtual void compilation_unit(compilation_unit ast, SymbolTable bindings) { using_directives(ast.using_directives, bindings); foreach (declaration x in ast.declarations) declaration(x, bindings); NameSpace t = (NameSpace)bindings.Owner; foreach (string id in t.aliases) t.members.Remove(id); t.usingdirectives = null; } override public void constant_declaration(constant_declaration ast, SymbolTable bindings) { Type t = type(ast.ty, bindings); foreach (const_declarator x in ast.decls) x.sym.Type = t; } override public void constructor_declaration(constructor_declaration ast, SymbolTable bindings) { formals(ast.decl.f, ast.sym.locals); ast.sym.Type = Type.Void; } override public void delegate_declaration(delegate_declaration ast, SymbolTable bindings) { ast.sym.Type = type(ast.ty, bindings); ast.sym.invoke.Type = ast.sym.Type; formals(ast.f, ast.sym.invoke.locals); } override public void destructor_declaration(destructor_declaration ast, SymbolTable bindings) { ast.sym.Type = Type.Void; } override public Symbol dotted_name(dotted_name ast, SymbolTable bindings) { Type context = bindings.Owner as Type; // may be NameSpace if (bindings.Owner is Block) context = ((Block)bindings.Owner).GetType(); Symbol t; if (ast.left == null) { t = bindings.Owner.LookupType(ast.right, msg); if (t == null) msg.Error(ast.right, "undefined namespace or type '{0}'", ast.right.str); else if (!t.IsAccessible(context)) msg.Error(ast.right, "'{0}' is inaccessible", ast.right.str); ast.sym = t; return t; } t = dotted_name(ast.left, bindings); if (t is INamespaceOrType) t = ((INamespaceOrType)t)[ast.right.str]; ast.sym = t; if (t == null) msg.Error(ast.right, "invalid namespace or type '{0}'", ast.ToString()); else if (!t.IsAccessible(context)) msg.Error(ast.right, "'{0}' is inaccessible", ast.right.str); return t; } override public void enum_declaration(enum_declaration ast, SymbolTable bindings) { if (ast.ty != null) ast.sym.baseType = type(ast.ty, bindings); else ast.sym.baseType = Type.Int; foreach (enum_member_declaration x in ast.body) x.sym.Type = ast.sym; } override public void event_declaration1(event_declaration1 ast, SymbolTable bindings) { type(ast.ty, bindings); } override public void event_declaration2(event_declaration2 ast, SymbolTable bindings) { type(ast.ty, bindings); member_name(ast.name, bindings); } override public void explicit_declarator(explicit_declarator ast, SymbolTable bindings) { ClassType c = ((Method)bindings.Owner).GetType(); Type ty = type(ast.ty, bindings); ast.sym.Type = type(ast.t1, bindings); if (ty == ast.sym.Type) msg.Error(ast.begin, "'implicit operator {0}({1})' must have different parameter and return types", ty.FullName, ast.sym.Type.FullName); if (ty != c && ast.sym.Type != c) msg.Error(ast.begin, "'implicit operator {0}({1})' must have '{2}' as the parameter or return type", ty.FullName, ast.sym.Type.FullName, c.FullName); if (ty is InterfaceType || ty == Type.Object || ast.sym.Type is InterfaceType || ast.sym.Type == Type.Object) msg.Error(ast.ty.begin, "'implicit operator {0}({1})' cannot have object or interface types as the parameter or return type", ty.FullName, ast.sym.Type.FullName); if (ty.InheritsFrom(ast.sym.Type) || ast.sym.Type.InheritsFrom(ty)) msg.Error(ast.ty.begin, "'implicit operator {0}({1})' cannot must have distinct parameter and return types", ty.FullName, ast.sym.Type.FullName); } override public void field_declaration(field_declaration ast, SymbolTable bindings) { Type t = type(ast.ty, bindings); foreach (field_declarator x in ast.decls) x.sym.Type = t; } override public void fixed_parameter(fixed_parameter ast, SymbolTable bindings) { Formal f = (Formal)bindings[ast.id.str]; f.Type = type(ast.ty, bindings); } public virtual void formals(formals ast, SymbolTable bindings) { foreach (parameter x in ast.fixeds) parameter(x, bindings); if (ast.param != null) parameter(ast.param, bindings); } override public void implicit_declarator(implicit_declarator ast, SymbolTable bindings) { ClassType c = ((Method)bindings.Owner).GetType(); Type ty = type(ast.ty, bindings); ast.sym.Type = type(ast.t1, bindings); if (ty == ast.sym.Type) msg.Error(ast.begin, "'implicit operator {0}({1})' must have different parameter and return types", ty.FullName, ast.sym.Type.FullName); if (ty != c && ast.sym.Type != c) msg.Error(ast.begin, "'implicit operator {0}({1})' must have '{2}' as the parameter or return type", ty.FullName, ast.sym.Type.FullName, c.FullName); if (ty is InterfaceType || ty == Type.Object || ast.sym.Type is InterfaceType || ast.sym.Type == Type.Object) msg.Error(ast.ty.begin, "'implicit operator {0}({1})' cannot have object or interface types as the parameter or return type", ty.FullName, ast.sym.Type.FullName); if (ty.InheritsFrom(ast.sym.Type) || ast.sym.Type.InheritsFrom(ty)) msg.Error(ast.ty.begin, "'implicit operator {0}({1})' cannot must have distinct parameter and return types", ty.FullName, ast.sym.Type.FullName); } override public void indexer_declaration(indexer_declaration ast, SymbolTable bindings) { Type t; if (ast.i.interfacename != null) { t = type(ast.i.interfacename, bindings) as InterfaceType; if (!(t is InterfaceType)) msg.Error("'{0}' is not an interface name", ast.i.interfacename.name.ToString()); } t = type(ast.i.ty, bindings); foreach (accessor_declaration x in ast.accessors) { formals(ast.i.f, x.sym.locals); if (x.id.str == "set") { ((Formal)x.sym.locals["value"]).Type = t; x.sym.Type = Type.Void; } else x.sym.Type = t; } } override public void interface_declaration(interface_declaration ast, SymbolTable bindings) { InterfaceType t = ast.sym; foreach (type x in ast.interfaces) { Type b = type(x, bindings); if (!(b is InterfaceType)) msg.Error(ast.id, "'{0}' is not an interface type", b.Name); else if (t.interfaces.Contains((InterfaceType)b)) msg.Error(ast.id, "duplicate interface base '{0}'", b.Name); else t.interfaces.Add((InterfaceType)b); } foreach (declaration x in ast.body) declaration(x, t.members); } override public void interface_event_declaration(interface_event_declaration ast, SymbolTable bindings) { ast.sym.Type = type(ast.ty, bindings); if (!(ast.ty.sym is DelegateType)) msg.Error(ast.ty.begin, "delegate type expected; found '{0}'", ast.ty.sym.FullName); } override public void interface_indexer_declaration(interface_indexer_declaration ast, SymbolTable bindings) { Type t = type(ast.ty, bindings); foreach (accessor_declaration x in ast.accessors) { formals(ast.f, x.sym.locals); if (x.id.str == "set"){ ((Formal)x.sym.locals["value"]).Type = t; x.sym.Type = Type.Void; } else x.sym.Type = t; } } override public void interface_method_declaration(interface_method_declaration ast, SymbolTable bindings) { ast.sym.Type = type(ast.ty, bindings); formals(ast.f, ast.sym.locals); } override public void interface_property_declaration(interface_property_declaration ast, SymbolTable bindings) { ast.sym.Type = type(ast.ty, bindings); } InterfaceType member_name(member_name ast, SymbolTable bindings) { if (ast.ty != null) { Type t = type(ast.ty, bindings); if (t is InterfaceType) { ast.sym = (InterfaceType)t; return ast.sym; } else msg.Error(ast.id, "'{0}' is not an interface name", ast.id.str); } return null; } override public void method_declaration(method_declaration ast, SymbolTable bindings) { ast.sym.Type = type(ast.ty, bindings); member_name(ast.name, bindings); formals(ast.parms, ast.sym.locals); } public virtual void named_argument(named_argument ast, SymbolTable bindings) { } public virtual void namespace_body(namespace_body ast, SymbolTable bindings) { using_directives(ast.ud, bindings); foreach (declaration x in ast.declarations) declaration(x, bindings); } override public void namespace_declaration(namespace_declaration ast, SymbolTable bindings) { namespace_body(ast.nb, ast.sym.members); foreach (string id in ast.sym.aliases) ast.sym.members.Remove(id); ast.sym.usingdirectives = null; } override public void operator_declaration(operator_declaration ast, SymbolTable bindings) { operator_declarator(ast.op, ast.sym.locals); ast.sym.Type = ast.op.ty.sym; } override public void params_parameter(params_parameter ast, SymbolTable bindings) { Type t = type(ast.ty, bindings); Formal f = (Formal)bindings[ast.id.str]; f.Type = type(ast.ty, bindings);; if (!(f.Type is ArrayType)) { msg.Error(ast.ty.begin, "params parameter must be an array type"); f.IsParams = false; } } override public void property_declaration(property_declaration ast, SymbolTable bindings) { ast.sym.Type = type(ast.ty, bindings); member_name(ast.name, bindings); } public virtual void simple_name(simple_name ast, SymbolTable bindings) { ast.sym = bindings.Owner.Lookup(ast.id, msg); if (ast.sym == null) msg.Error(ast.id, "undefined symbol '{0}'", ast.id.str); } override public void struct_declaration(struct_declaration ast, SymbolTable bindings) { StructType t = ast.sym; t.baseClass = Type.ValueType; foreach (type x in ast.interfaces) { Type b = type(x, bindings); if (b is InterfaceType) if (t.interfaces.Contains((InterfaceType)b)) msg.Error(x.begin, "duplicate interface '{0}'", b.Name); else t.interfaces.Add((InterfaceType)b); else msg.Error(x.begin, "'{0}' is not an interface type", b.Name); } foreach (declaration x in ast.body) declaration(x, t.members); } override public Type type(type ast, SymbolTable bindings) { ast.sym = base.type(ast, bindings); return ast.sym; } override public void unary_declarator(unary_declarator ast, SymbolTable bindings) { ClassType c = ((Method)bindings.Owner).GetType(); Type ty = type(ast.ty, bindings); ast.sym.Type = type(ast.t1, bindings); if (ast.sym.Type != c) msg.Error(ast.t1.begin, "parameter of unary operator '{0}' must be a '{1}'", ast.op.str, c.FullName); if ((ast.op.str == "++" || ast.op.str == "--") && ty != c) msg.Error(ast.ty.begin, "return type of unary operator '{0}' must be a '{1}'", ast.op.str, c.FullName); else if ((ast.op.str == "true" || ast.op.str == "false") && ty != Type.Bool) msg.Error(ast.t1.begin, "parameter of unary operator '{0}' must be a '{1}'", ast.op.str, Type.Bool.FullName); if (ast.op.str == "true" && c.members["op_False"] == null) msg.Error(ast.ty.begin, "'{0}.operator true({1})' requires that matching operator 'false' be defined", c.FullName, ast.sym.Type.FullName); if (ast.op.str == "false" && c.members["op_True" ] == null) msg.Error(ast.ty.begin, "'{0}.operator false({1})' requires that matching operator 'true' be defined", c.FullName, ast.sym.Type.FullName); } public virtual void using_directives(using_directiveList ud, SymbolTable bindings) { NameSpace t = (NameSpace)bindings.Owner; t.usingdirectives = new SymbolList(); foreach (using_directive x in ud) if (x is alias_directive) { alias_directive d = (alias_directive)x; d.sym = dotted_name(d.name, bindings); } else if (x is namespace_directive) t.usingdirectives.Add(dotted_name(((namespace_directive)x).name, bindings)); else throw new ArgumentException(); foreach (using_directive x in ud) if (x is alias_directive) { alias_directive d = (alias_directive)x; if (t.aliases.Contains(d.id.str)) msg.Error(d.id, "'{0}' is already an alias in this namespace", d.id.str); else if (d.sym != null) { t.aliases.Add(d.id.str); d.sym.Add(d.id, t.members, msg); } } } } public class Pass3: bind { public stringList assemblyRefs = new stringList(); public Pass3(MessageWriter msg) : base(msg) {} public virtual void accessor_declaration(accessor_declaration ast, SymbolTable bindings) { foreach (attribute_section x in ast.attrs) attribute_section(x, bindings); if (ast.body != null) statement(ast.body, bindings); } override public void arglist_parameter(arglist_parameter ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); } public virtual void argument(argument ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void array_creation_expression1(array_creation_expression1 ast, SymbolTable bindings) { foreach (expression x in ast.exprs) expression(x, bindings); if (ast.init != null) array_initializer(ast.init, bindings); type(ast.ty, bindings); } public virtual void array_creation_expression2(array_creation_expression2 ast, SymbolTable bindings) { array_initializer(ast.init, bindings); type(ast.ty, bindings); } public virtual void array_initializer(array_initializer ast, SymbolTable bindings) { foreach (variable_initializer x in ast.a) { if (ast.a[0] is array_initializer && (!(x is array_initializer) || ((array_initializer)x).a.Count != ((array_initializer)ast.a[0]).a.Count)) msg.Error(x.begin, "incorrectly structured array initializer"); variable_initializer(x, bindings); } } public virtual void as_expression(as_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); type(ast.ty, bindings); } public virtual void assignment_expression(assignment_expression ast, SymbolTable bindings) { expression(ast.e1, bindings); expression(ast.e2, bindings); } public virtual void attribute(attribute ast, SymbolTable bindings) { if (ast.name is name_type) { ast.sym = dotted_name(((name_type)ast.name).name, bindings, "Attribute") as ClassType; ast.name.sym = ast.sym; } type(ast.name, bindings); if (ast.arguments != null) attribute_arguments(ast.arguments, bindings, ast.sym); } public virtual void attribute_arguments(attribute_arguments ast, SymbolTable bindings, ClassType c) { foreach (argument x in ast.args) argument(x, bindings); foreach (named_argument x in ast.namedargs) named_argument(x, bindings, c); } public virtual void attribute_section(attribute_section ast, SymbolTable bindings) { foreach (attribute x in ast.attributes) attribute(x, bindings); } public virtual void attribute_sections(attribute_sectionList attrs, SymbolTable bindings) { foreach (attribute_section x in attrs) attribute_section(x, bindings); } public virtual void base_access(base_access ast, SymbolTable bindings) { Block b = (Block)bindings.Owner; if (b.GetMethod().IsStatic) msg.Error(ast.begin, "'base' can appear only in instance methods"); ast.sym = b.GetType().baseClass; } public virtual void base_initializer(base_initializer ast, SymbolTable bindings) { foreach (argument x in ast.args) argument(x, bindings); } override public void binary_declarator(binary_declarator ast, SymbolTable bindings) { type(ast.t1, bindings); type(ast.t2, bindings); type(ast.ty, bindings); } public virtual void binary_expression(binary_expression ast, SymbolTable bindings) { expression(ast.e1, bindings); expression(ast.e2, bindings); } override public void block_statement(block_statement ast, SymbolTable bindings) { foreach (statement x in ast.stmts) statement(x, ast.sym.locals); } public virtual void cast_expression(cast_expression ast, SymbolTable bindings) { ast.sym = type(ast.ty, bindings); expression(ast.expr, bindings); } public virtual void catch_clause(catch_clause ast, SymbolTable bindings) { Type t = type(ast.ty, bindings); if (ast.id != null) ast.sym.Type = t; statement(ast.block, bindings); } public virtual void catch_clauses(catch_clauses ast, SymbolTable bindings) { foreach (catch_clause x in ast.specifics) catch_clause(x, bindings); if (ast.general != null) statement(ast.general, bindings); } public virtual void checked_expression(checked_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); } override public void checked_statement(checked_statement ast, SymbolTable bindings) { statement(ast.stmt, bindings); } override public void class_declaration(class_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (type b in ast.bases) type(b, bindings); type(ast.sym.baseClass); foreach (declaration x in ast.body) declaration(x, ast.sym.members); if (!ast.sym.Is("abstract")) foreach (Symbol s in ast.sym.Flatten()) if (s.Is("abstract") && s.declSpace.Owner != ast.sym) msg.Error(s.id, "'{0}' does not implement inherited abstract member '{1}'", ast.sym.FullName, s.FullName); interface_mapping(ast.sym, ast); } public virtual void compilation(compilation ast, SymbolTable bindings) { base.compilation(ast); ast.assemblyRefs = assemblyRefs; foreach (compilation_unit x in ast.inputs) compilation_unit(x, bindings); } public virtual void compilation_unit(compilation_unit ast, SymbolTable bindings) { attribute_sections(ast.attributes, bindings); using_directives(ast.using_directives, bindings); foreach (declaration x in ast.declarations) declaration(x, bindings); ((NameSpace)bindings.Owner).usingdirectives = null; } public virtual void compound_assignment_expression(compound_assignment_expression ast, SymbolTable bindings) { expression(ast.e1, bindings); expression(ast.e2, bindings); } public virtual void cond_expression(cond_expression ast, SymbolTable bindings) { expression(ast.cond, bindings); expression(ast.success, bindings); expression(ast.failure, bindings); } public virtual void const_declarator(const_declarator ast, SymbolTable bindings) { expression(ast.expr, bindings); } override public void const_statement(const_statement ast, SymbolTable bindings) { Type t = type(ast.ty, bindings); foreach (const_declarator x in ast.consts) { expression(x.expr, bindings); x.sym.Type = t; } } override public void constant_declaration(constant_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (const_declarator x in ast.decls) expression(x.expr, bindings); } override public void constructor_declaration(constructor_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); constructor_declarator(ast.decl, ast.sym.locals); if (ast.block != null) statement(ast.block, ast.sym.locals); } public virtual void constructor_declarator(constructor_declarator ast, SymbolTable bindings) { if (ast.init != null) constructor_initializer(ast.init, bindings); } public virtual void constructor_initializer(constructor_initializer ast, SymbolTable bindings) { if (ast is base_initializer) base_initializer((base_initializer)ast, bindings); else if (ast is this_initializer) this_initializer((this_initializer)ast, bindings); else throw new ArgumentException(); } override public void delegate_declaration(delegate_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); formals(ast.f, ast.sym.invoke.locals); type(ast.sym.baseClass); } override public void destructor_declaration(destructor_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); if (ast.block != null) statement(ast.block, ast.sym.locals); } override public void do_statement(do_statement ast, SymbolTable bindings) { statement(ast.body, bindings); expression(ast.expr, bindings); } override public Symbol dotted_name(dotted_name ast, SymbolTable bindings) { return dotted_name(ast, bindings, null); } public Symbol dotted_name(dotted_name ast, SymbolTable bindings, string suffix) { Type context = bindings.Owner as Type; // may be NameSpace if (bindings.Owner is Block) context = ((Block)bindings.Owner).GetType(); Symbol t; if (ast.left == null) { t = bindings.Owner.LookupType(ast.right, msg); if (suffix != null && !ast.right.str.EndsWith(suffix)) { Symbol t1 = bindings.Owner.LookupType(new InputElement(ast.right.str + suffix), msg); if (t == null) t = t1; else if (t1 != null) msg.Error(ast.right, "'{0}' is ambiguous; use '{0}{1}'", ast.right.str, suffix); } if (t == null) msg.Error(ast.right, "undefined namespace or type '{0}'", ast.right.str); else if (!t.IsAccessible(context)) msg.Error(ast.right, "'{0}' is inaccessible", ast.right.str); ast.sym = t; return t; } t = dotted_name(ast.left, bindings); if (t is INamespaceOrType) t = ((INamespaceOrType)t)[ast.right.str]; ast.sym = t; if (t == null) msg.Error(ast.right, "invalid namespace or type '{0}'", ast.ToString()); else if (!t.IsAccessible(context)) msg.Error(ast.right, "'{0}' is inaccessible", ast.right.str); return t; } public virtual void element_access(element_access ast, SymbolTable bindings) { expression(ast.expr, bindings); foreach (argument x in ast.exprs) argument(x, bindings); } override public void enum_declaration(enum_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (enum_member_declaration x in ast.body) enum_member_declaration(x, ast.sym.members); if (ast.ty != null) type(ast.ty, bindings); } public virtual void enum_member_declaration(enum_member_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); if (ast.expr != null) expression(ast.expr, bindings); } public virtual void event_accessor(event_accessor ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); statement(ast.block, ast.sym.locals); } override public void event_declaration1(event_declaration1 ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); Type t = type(ast.ty, bindings); if (!(t is DelegateType)) msg.Error(ast.ty.begin, "delegate type expected; found '{0}'", t.FullName); foreach (event_declarator x in ast.decls) { x.sym.Type = t; if (x.init != null) variable_initializer(x.init, bindings); } } override public void event_declaration2(event_declaration2 ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); Type t = type(ast.ty, bindings); if (!(t is DelegateType)) msg.Error(ast.ty.begin, "delegate type expected; found '{0}'", t.FullName); ast.sym.Type = t; foreach (event_accessor x in ast.accessors) event_accessor(x, bindings); } override public void explicit_declarator(explicit_declarator ast, SymbolTable bindings) { type(ast.t1, bindings); type(ast.ty, bindings); } public virtual void expr_access(expr_access ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void expr_initializer(expr_initializer ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void expression(expression ast, SymbolTable bindings) { if (ast is simple_name) simple_name((simple_name)ast, bindings); else if (ast is literal) return; else if (ast is member_access) member_access((member_access)ast, bindings); else if (ast is invocation_expression) invocation_expression((invocation_expression)ast, bindings); else if (ast is element_access) element_access((element_access)ast, bindings); else if (ast is this_access) this_access((this_access)ast, bindings); else if (ast is base_access) base_access((base_access)ast, bindings); else if (ast is post_expression) post_expression((post_expression)ast, bindings); else if (ast is new_expression) new_expression((new_expression)ast, bindings); else if (ast is array_creation_expression1) array_creation_expression1((array_creation_expression1)ast, bindings); else if (ast is array_creation_expression2) array_creation_expression2((array_creation_expression2)ast, bindings); else if (ast is typeof_expression) typeof_expression((typeof_expression)ast, bindings); else if (ast is checked_expression) checked_expression((checked_expression)ast, bindings); else if (ast is unchecked_expression) unchecked_expression((unchecked_expression)ast, bindings); else if (ast is unary_expression) unary_expression((unary_expression)ast, bindings); else if (ast is pre_expression) pre_expression((pre_expression)ast, bindings); else if (ast is cast_expression) cast_expression((cast_expression)ast, bindings); else if (ast is binary_expression) binary_expression((binary_expression)ast, bindings); else if (ast is is_expression) is_expression((is_expression)ast, bindings); else if (ast is as_expression) as_expression((as_expression)ast, bindings); else if (ast is cond_expression) cond_expression((cond_expression)ast, bindings); else if (ast is assignment_expression) assignment_expression((assignment_expression)ast, bindings); else if (ast is compound_assignment_expression) compound_assignment_expression((compound_assignment_expression)ast, bindings); else if (ast is sizeof_expression) sizeof_expression((sizeof_expression)ast, bindings); else throw new ArgumentException(); } override public void expression_statement(expression_statement ast, SymbolTable bindings) { expression(ast.expr, bindings); } override public void field_declaration(field_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (field_declarator x in ast.decls) if (x.init != null) variable_initializer(x.init, bindings); type(ast.ty, bindings); } public static finally_clause find_finally(statement ast) { for (AST s = ast; s != null; s = s.parent) if (s is finally_clause) return (finally_clause)s; return null; } public statement find_switch(statement ast, string kind) { for (AST s = ast; s != null; s = s.parent) if (s is finally_clause) { msg.Error(ast.begin, "invalid '{0}' statement: '{0}' cannot exit a finally block", kind); return null; } else if (s is switch_statement) return (statement)s; msg.Error(ast.begin, "invalid '{0}' statement", kind); return null; } override public void fixed_parameter(fixed_parameter ast, SymbolTable bindings) { type(ast.ty, bindings); attribute_sections(ast.attrs, bindings); } override public void fixed_statement(fixed_statement ast, SymbolTable bindings) { foreach (fixed_declarator x in ast.declarators) expression(x.expr, bindings); statement(ast.body, bindings); } public virtual void for_init(for_init ast, SymbolTable bindings) { if (ast is for_decl) local_statement(((for_decl)ast).decl, bindings); else if (ast is for_list) foreach (expression x in ((for_list)ast).exprs) expression(x, bindings); else throw new ArgumentException(); } override public void for_statement(for_statement ast, SymbolTable bindings) { if (ast.init != null) for_init(ast.init, ast.sym.locals); if (ast.cond != null) expression(ast.cond, ast.sym.locals); foreach (expression x in ast.iterators) expression(x, ast.sym.locals); statement(ast.body, ast.sym.locals); } public virtual void formals(formals ast, SymbolTable bindings) { foreach (parameter x in ast.fixeds) parameter(x, bindings); if (ast.param != null) parameter(ast.param, bindings); } override public void foreach_statement(foreach_statement ast, SymbolTable bindings) { Local t = ast.sym; ast.sym.Type = type(ast.ty, t.declSpace); expression(ast.expr, t.declSpace); statement(ast.body, t.declSpace); } override public void goto_case_statement(goto_case_statement ast, SymbolTable bindings) { expression(ast.expr, bindings); ast.stmt = find_switch(ast, "goto case"); } override public void goto_default_statement(goto_default_statement ast, SymbolTable bindings) { ast.stmt = find_switch(ast, "goto default"); } override public void goto_statement(goto_statement ast, SymbolTable bindings) { ast.sym = ((Block)bindings.Owner).LookupLabel(ast.id); if (ast.sym == null) msg.Error(ast.id, "undefined label '{0}'", ast.id.str); else { ast.target = ast.sym.definition; if (find_finally(ast) != find_finally(ast.target)) msg.Error(ast.begin, "invalid 'goto' statement: 'goto' cannot exit a finally block"); } } override public void if_statement(if_statement ast, SymbolTable bindings) { expression(ast.expr, bindings); statement(ast.thenpart, bindings); if (ast.elsepart != null) statement(ast.elsepart, bindings); } override public void implicit_declarator(implicit_declarator ast, SymbolTable bindings) { type(ast.t1, bindings); type(ast.ty, bindings); } override public void indexer_declaration(indexer_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); if (ast.i.interfacename != null) type(ast.i.interfacename, bindings); type(ast.i.ty, bindings); foreach (accessor_declaration x in ast.accessors) { attribute_sections(x.attrs, bindings); formals(ast.i.f, x.sym.locals); if (x.body != null) statement(x.body, x.sym.locals); } } override public void interface_declaration(interface_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (declaration x in ast.body) declaration(x, ast.sym.members); foreach (type x in ast.interfaces) type(x, bindings); } override public void interface_event_declaration(interface_event_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); type(ast.ty, bindings); } override public void interface_indexer_declaration(interface_indexer_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (accessor_declaration x in ast.accessors) attribute_sections(x.attrs, bindings); formals(ast.f, bindings); type(ast.ty, bindings); } override public void interface_method_declaration(interface_method_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); formals(ast.f, bindings); type(ast.ty, bindings); } public virtual void interface_mapping(ClassType c, declaration ast) { foreach (InterfaceType x in c.interfaces) foreach (Symbol s in x) { Symbol t = null; for (ClassType b = c; b != null; b = b.baseClass) { t = b.members[s.FullName]; if (t == null) t = b.members[s.Name]; if (t is MethodSuite && s is Method) { t = ((MethodSuite)t).Contains(((Method)s).signature); if (t is Method && t.Type.Equals(((Method)s).Type)) break; } else if (t is Property && s is Property || t is Event && s is Event) break; } if (t == null || (!s.Equals(t) || !t.IsPublic) && t.Name != s.FullName) msg.Error(ast.end, "'{0}' does not implement interface member '{1}'", c.FullName, s.FullName); else if (t is Method) { if (!t.Modifiers.Contains("virtual")) { t.Modifiers.Add("virtual"); t.Modifiers.Add("sealed"); } ((Method)t).interfaceMethod = (Method)s; } } } override public void interface_property_declaration(interface_property_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (accessor_declaration x in ast.accessors) accessor_declaration(x, bindings); type(ast.ty, bindings); } public virtual void invocation_expression(invocation_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); foreach (argument x in ast.args) argument(x, bindings); } public virtual void is_expression(is_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); type(ast.ty, bindings); } override public void labeled_statement(labeled_statement ast, SymbolTable bindings) { statement(ast.stmt, bindings); } override public void local_statement(local_statement ast, SymbolTable bindings) { Block b = (Block)bindings.Owner; Type t = type(ast.ty, bindings); foreach (var_declarator x in ast.vars) { x.sym = b.AddLocal(x.id, msg); x.sym.Type = t; if (x.init != null) variable_initializer(x.init, bindings); } } override public void lock_statement(lock_statement ast, SymbolTable bindings) { expression(ast.expr, bindings); statement(ast.body, bindings); } public virtual void member_access(member_access ast, SymbolTable bindings) { if (ast is expr_access) expr_access((expr_access)ast, bindings); else if (ast is pointer_access) pointer_access((pointer_access)ast, bindings); else if (ast is predefined_access) predefined_access((predefined_access)ast, bindings); else throw new ArgumentException(); } override public void method_declaration(method_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); type(ast.ty, bindings); Method m = ast.sym; formals(ast.parms, m.locals); ClassType c = m.GetType(); MethodSuite t = c.members[m.id.str] as MethodSuite; if (t != null && t.Contains(m.signature) != m) msg.Error(ast.name.begin, "{0} '{1}' already contains a definition for '{2}'", bindings.Owner.Kind, bindings.Owner.FullName, m.Name); if (m.Is("override") && m.GetBaseDefinition() == m) msg.Error(ast.name.begin, "invalid use of 'override'; '{0}' is not virtual", m.FullName); else if (!m.Is("new") && !m.Is("override")) { while ((c = c.baseClass) != null) { t = c.members[m.id.str] as MethodSuite; if (t != null && t.Contains(m.signature) != null) msg.Warning(ast.name.begin, "'{0}' hides '{1}'; use 'new'", m.FullName, t.Contains(m.signature).FullName); } } if (ast.body != null) statement(ast.body, m.locals); } public virtual void named_argument(named_argument ast, SymbolTable bindings, ClassType c) { ast.sym = c.Lookup(ast.id, msg); if (!(ast.sym is Field || ast.sym is Property)) msg.Error(ast.id, "Type '{0}' does not contain a member named '{1}'", c.FullName, ast.id.str); expression(ast.expr, bindings); } public virtual void namespace_body(namespace_body ast, SymbolTable bindings) { using_directives(ast.ud, bindings); foreach (declaration x in ast.declarations) declaration(x, bindings); } override public void namespace_declaration(namespace_declaration ast, SymbolTable bindings) { namespace_body(ast.nb, ast.sym.members); foreach (string id in ast.sym.aliases) ast.sym.members.Remove(id); ast.sym.usingdirectives = null; } public virtual void new_expression(new_expression ast, SymbolTable bindings) { foreach (argument x in ast.args) argument(x, bindings); type(ast.ty, bindings); } override public void operator_declaration(operator_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); if (ast.block != null) statement(ast.block, ast.sym.locals); operator_declarator(ast.op, bindings); } override public void params_parameter(params_parameter ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); type(ast.ty, bindings); } public virtual void pointer_access(pointer_access ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void post_expression(post_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void pre_expression(pre_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void predefined_access(predefined_access ast, SymbolTable bindings) { switch (ast.predefined.str) { case "bool": ast.type = Type.Bool; break; case "byte": ast.type = Type.Byte; break; case "char": ast.type = Type.Char; break; case "decimal":ast.type = Type.Decimal;break; case "double": ast.type = Type.Double; break; case "float": ast.type = Type.Float; break; case "int": ast.type = Type.Int; break; case "long": ast.type = Type.Long; break; case "object": ast.type = Type.Object; break; case "sbyte": ast.type = Type.SByte; break; case "short": ast.type = Type.Short; break; case "string": ast.type = Type.String; break; case "uint": ast.type = Type.UInt; break; case "ulong": ast.type = Type.ULong; break; case "ushort": ast.type = Type.UShort; break; default: throw new ArgumentException(); } } override public void property_declaration(property_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (accessor_declaration x in ast.decls) { attribute_sections(x.attrs, bindings); if (x.body != null) statement(x.body, x.sym.locals); } } public virtual void resource(resource ast, SymbolTable bindings) { if (ast is resource_expr) expression(((resource_expr)ast).expr, bindings); else if (ast is resource_decl) local_statement(((resource_decl)ast).local, bindings); else throw new ArgumentException(); } override public void return_statement(return_statement ast, SymbolTable bindings) { if (ast.method.Type == Type.Void && ast.expr != null) msg.Error(ast.expr.begin, "extraneous return expression"); if (ast.expr != null) expression(ast.expr, bindings); } public virtual void simple_name(simple_name ast, SymbolTable bindings) { ast.sym = bindings.Owner.Lookup(ast.id, msg); if (ast.sym == null) msg.Error(ast.id, "undefined symbol '{0}'", ast.id.str); } public virtual void sizeof_expression(sizeof_expression ast, SymbolTable bindings) { type(ast.ty, bindings); } public virtual void stackalloc_initializer(stackalloc_initializer ast, SymbolTable bindings) { type(ast.ty, bindings); expression(ast.expr, bindings); } override public void struct_declaration(struct_declaration ast, SymbolTable bindings) { attribute_sections(ast.attrs, bindings); foreach (type x in ast.interfaces) type(x, bindings); type(ast.sym.baseClass); foreach (declaration x in ast.body) declaration(x, ast.sym.members); interface_mapping(ast.sym, ast); } public virtual void switch_expression(switch_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void switch_label(switch_label ast, SymbolTable bindings, ref bool hasdefault) { if (ast is switch_expression) switch_expression((switch_expression)ast, bindings); else if (ast is switch_default) { if (hasdefault) msg.Error(ast.begin, "duplicate default label"); hasdefault = true; } else throw new ArgumentException(); } public virtual void switch_section(switch_section ast, SymbolTable bindings, ref bool hasdefault) { foreach (switch_label x in ast.labels) switch_label(x, bindings, ref hasdefault); statement s = null; foreach (statement x in ast.stmts) statement(s = x, bindings); if (!(s is return_statement || s is break_statement || s is continue_statement || s is goto_statement || s is goto_case_statement || s is goto_default_statement || s is throw_statement)) msg.Error(s.begin, "missing break or other control flow statement in switch case"); } override public void switch_statement(switch_statement ast, SymbolTable bindings) { expression(ast.expr, bindings); bool hasdefault = false; foreach (switch_section x in ast.sections) switch_section(x, bindings, ref hasdefault); } public virtual void this_access(this_access ast, SymbolTable bindings) { Block b = (Block)bindings.Owner; if (b.GetMethod().IsStatic) msg.Error(ast.begin, "'this' can appear only in instance methods"); ast.sym = b.GetType(); } public virtual void this_initializer(this_initializer ast, SymbolTable bindings) { foreach (argument x in ast.args) argument(x, bindings); } override public void throw_statement(throw_statement ast, SymbolTable bindings) { if (ast.expr != null) expression(ast.expr, bindings); } override public void try_statement(try_statement ast, SymbolTable bindings) { statement(ast.block, bindings); if (ast.catches != null) catch_clauses(ast.catches, bindings); if (ast.finally_block != null) statement(ast.finally_block.block, bindings); } public Type type(Type ty) { if (ty != null && ty.module != null && !assemblyRefs.Contains(ty.module)) assemblyRefs.Add(ty.module); return ty; } override public Type type(type ast, SymbolTable bindings) { if (ast.sym == null) ast.sym = base.type(ast, bindings); return type(ast.sym); } public virtual void typeof_expression(typeof_expression ast, SymbolTable bindings) { type(ast.ty, bindings); } override public void unary_declarator(unary_declarator ast, SymbolTable bindings) { type(ast.t1, bindings); type(ast.ty, bindings); } public virtual void unary_expression(unary_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); } public virtual void unchecked_expression(unchecked_expression ast, SymbolTable bindings) { expression(ast.expr, bindings); } override public void unchecked_statement(unchecked_statement ast, SymbolTable bindings) { statement(ast.stmt, bindings); } public virtual void using_directives(using_directiveList ud, SymbolTable bindings) { NameSpace t = (NameSpace)bindings.Owner; t.usingdirectives = new SymbolList(); foreach (using_directive x in ud) if (x is alias_directive) { alias_directive d = (alias_directive)x; d.sym = dotted_name(d.name, bindings); } else if (x is namespace_directive) t.usingdirectives.Add(dotted_name(((namespace_directive)x).name, bindings)); else throw new ArgumentException(); foreach (using_directive x in ud) if (x is alias_directive) { alias_directive d = (alias_directive)x; if (d.sym != null) d.sym.Add(d.id, t.members, msg); } } override public void unsafe_statement(unsafe_statement ast, SymbolTable bindings) { statement(ast.block, bindings); } override public void using_statement(using_statement ast, SymbolTable bindings) { resource(ast.r, ast.sym.locals); statement(ast.body, ast.sym.locals); } public virtual void var_declarator(var_declarator ast, SymbolTable bindings) { if (ast.init != null) variable_initializer(ast.init, bindings); } public virtual void variable_initializer(variable_initializer ast, SymbolTable bindings) { if (ast is stackalloc_initializer) stackalloc_initializer((stackalloc_initializer)ast, bindings); else if (ast is expr_initializer) expr_initializer((expr_initializer)ast, bindings); else if (ast is array_initializer) array_initializer((array_initializer)ast, bindings); else throw new ArgumentException(); } override public void while_statement(while_statement ast, SymbolTable bindings) { expression(ast.expr, bindings); statement(ast.body, bindings); } }