2062 lines
89 KiB
C#
2062 lines
89 KiB
C#
|
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);
|
||
|
}
|
||
|
}
|