singrdk/base/Windows/csic/bind/bind.cs

2062 lines
89 KiB
C#
Raw Normal View History

2008-11-17 18:29:00 -05:00
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);
}
}