using System; using System.IO; using System.Compiler; public class cci { public static object visit(object ast, TextWriter w, string[] args, MessageWriter msg) { if (msg.Count == 0) return new cci(w, msg).compilation((compilation)ast); return null; } protected Document document; protected MessageWriter msg; protected TextWriter w; public cci(TextWriter w, MessageWriter msg) { this.w = w; this.msg = msg; } Node accessor_declaration(accessor_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); if (ast.body != null) statement(ast.body); // InputElement ast.id // [Bind1] Method ast.sym // [Emit] MethodBuilder ast.builder // InputElementList ast.mods return null; } Node alias_directive(alias_directive ast) { // InputElement ast.id dotted_name(ast.name); // [Bind1] Symbol ast.sym return null; } Expression anonymous_method_expression(anonymous_method_expression ast) { foreach (parameter x in ast.formals) parameter(x); statement(ast.block); // Boolean ast.valueUsed // [Typecheck] Type ast.typ // [MayBeNull,Typecheck] Object ast.value return null; } Parameter arglist_parameter(arglist_parameter ast) { Parameter result = new Parameter(); foreach (attribute_section x in ast.attrs) attribute_section(x); return result; } Expression argument(argument ast) { return expression(ast.expr); } Expression array_creation_expression1(array_creation_expression1 ast) { foreach (expression x in ast.exprs) expression(x); if (ast.init != null) array_initializer(ast.init); // intList ast.ranks type(ast.ty); // Boolean ast.valueUsed // [Typecheck] Type ast.typ // [MayBeNull,Typecheck] Object ast.value return null; } Expression array_creation_expression2(array_creation_expression2 ast) { array_initializer(ast.init); type(ast.ty); // Boolean ast.valueUsed // [Typecheck] Type ast.typ // [MayBeNull,Typecheck] Object ast.value return null; } Expression array_initializer(array_initializer ast) { ConstructArray result = new ConstructArray(); result.Initializers = new ExpressionList(); foreach (variable_initializer x in ast.a) result.Initializers.Add(variable_initializer(x)); return result; } TypeNode array_type(array_type ast) { // Int32 ast.rank_specifier type(ast.ty); // [Bind2] Type ast.sym return null; } Expression as_expression(as_expression ast) { return new BinaryExpression(expression(ast.expr), new MemberBinding(null, type(ast.ty)), NodeType.As); } Expression assignment_expression(assignment_expression ast) { return new AssignmentExpression( new AssignmentStatement(expression(ast.e1), expression(ast.e2))); } Node attribute(attribute ast) { if (ast.arguments != null) attribute_arguments(ast.arguments); type(ast.name); return null; } Node attribute_arguments(attribute_arguments ast) { foreach (expression x in ast.args) expression(x); foreach (named_argument x in ast.namedargs) named_argument(x); return null; } Node attribute_section(attribute_section ast) { foreach (attribute x in ast.attributes) attribute(x); // [MayBeNull] InputElement ast.target return null; } Expression base_access(base_access ast) { return new Base(); } Node base_initializer(base_initializer ast) { foreach (argument x in ast.args) argument(x); // [Typecheck] Constructor ast.method return null; } Node binary_declarator(binary_declarator ast) { // InputElement ast.id1 // InputElement ast.id2 // InputElement ast.op type(ast.t1); type(ast.t2); // [Bind1] Formal ast.sym1 // [Bind1] Formal ast.sym2 type(ast.ty); // [Bind1] Method ast.method return null; } Expression binary_expression(binary_expression ast) { NodeType op; switch (ast.op.str) { case "+": op = NodeType.Add; break; case "&": op = NodeType.And; break; case "|": op = NodeType.Or; break; case "^": op = NodeType.Xor; break; case "/": op = NodeType.Div; break; case "=": op = NodeType.Eq; break; case ">": op = NodeType.Gt; break; case ">=": op = NodeType.Ge; break; case "<<": op = NodeType.Shl; break; case "<": op = NodeType.Lt; break; case "<=": op = NodeType.Le; break; case "&&": op = NodeType.LogicalAnd; break; case "||": op = NodeType.LogicalOr; break; case "*": op = NodeType.Mul; break; case "!=": op = NodeType.Ne; break; case "%": op = NodeType.Rem; break; case ">>": op = NodeType.Shr; break; case "-": op = NodeType.Sub; break; default: op = NodeType.Nop; break; } return new BinaryExpression(expression(ast.e1), expression(ast.e2), op); } System.Compiler.Block block(statement ast) { if (ast is block_statement) return (System.Compiler.Block)statement(ast); else return new System.Compiler.Block(new StatementList(statement(ast)), context(ast)); } Statement block_statement(block_statement ast) { StatementList stmts = new StatementList(); foreach (statement x in ast.stmts) stmts.Add(statement(x)); return new System.Compiler.Block(stmts, context(ast)); } TypeNode bool_type(bool_type ast) { return SystemTypes.Boolean; } Expression boolean_literal(boolean_literal ast) { return new Literal(ast.token.str == "true", SystemTypes.Boolean); } Statement break_statement(break_statement ast) { return new Exit(); } TypeNode byte_type(byte_type ast) { return SystemTypes.UInt8; } Expression cast_expression(cast_expression ast) { return new BinaryExpression(expression(ast.expr), new MemberBinding(null, typeexpression(ast.ty)), NodeType.Castclass); } Catch catch_clause(catch_clause ast) { Catch result = new Catch(); result.Type = type(ast.ty); if (ast.id != null) result.Variable = identifier(ast.id); result.Block = block(ast.block); return result; } CatchList catch_clauses(catch_clauses ast) { CatchList catches = new CatchList(); if (ast.general != null) catches.Add(new Catch(block(ast.general), null, null)); foreach (catch_clause x in ast.specifics) catches.Add(catch_clause(x)); return catches; } TypeNode char_type(char_type ast) { return SystemTypes.Char; } Expression character_literal(character_literal ast) { bool errorFlag; return new Literal(typecheck.characterLiteral(ast.token.str, out errorFlag), SystemTypes.Char); } Expression checked_expression(checked_expression ast) { BlockExpression result = new BlockExpression(); result.Block = new System.Compiler.Block(new StatementList(expressionstatement(ast.expr)), true, false); return result; } Statement checked_statement(checked_statement ast) { System.Compiler.Block result = block(ast.stmt); result.Checked = true; result.SuppressCheck = false; return result; } Node class_declaration(class_declaration ast) { System.Compiler.Class result = new System.Compiler.Class(); result.Name = identifier(ast.id); foreach (attribute_section x in ast.attrs) attribute_section(x); result.Flags = getTypeFlags(stringList(ast.mods), ast.parent is type_declaration); foreach (type_parameter x in ast.typeparams) type_parameter(x); foreach (type x in ast.bases) type(x); foreach (type_parameter_constraints_clause x in ast.constraints) type_parameter_constraints_clause(x); result.Members = new MemberList(); foreach (declaration x in ast.body) { Object d = declaration(x); if (d is Member) result.Members.Add((Member)d); else if (d is MemberList) { MemberList m = (MemberList)d; for (int i = 0; i < m.Length; i++) result.Members.Add(m[i]); } } return result; } object compilation(compilation ast) { Compilation result = new Compilation(); result.CompilationUnits = new CompilationUnitList(); foreach (compilation_unit x in ast.inputs) result.CompilationUnits.Add(compilation_unit(x)); return result; } CompilationUnit compilation_unit(compilation_unit ast) { CompilationUnit result = new CompilationUnit(); result.Nodes = new NodeList(); document = new Document(); if (ast.begin.file != null) { try { StreamReader r = new StreamReader(ast.begin.file); document.Text = new DocumentText(r.ReadToEnd()); r.Close(); } catch (Exception) { document.Text = new DocumentText(source.ToString(ast)); } } else document.Text = new DocumentText(source.ToString(ast)); result.SourceContext = context(ast); foreach (attribute_section x in ast.attributes) attribute_section(x); foreach (using_directive x in ast.using_directives) using_directive(x); foreach (declaration x in ast.declarations) result.Nodes.Add((Node)declaration(x)); return result; } Expression compound_assignment_expression(compound_assignment_expression ast) { NodeType op; switch (ast.op.str) { case "+=": op = NodeType.Add; break; case "&=": op = NodeType.And; break; case "|=": op = NodeType.Or; break; case "^=": op = NodeType.Xor; break; case "/=": op = NodeType.Div; break; case "<<=": op = NodeType.Shl; break; case "*=": op = NodeType.Mul; break; case "!=": op = NodeType.Ne; break; case "%=": op = NodeType.Rem; break; case ">>=": op = NodeType.Shr; break; case "-=": op = NodeType.Sub; break; default: op = NodeType.Nop; break; } return new AssignmentExpression( new AssignmentStatement(expression(ast.e1), expression(ast.e2), op)); } Expression cond_expression(cond_expression ast) { return new TernaryExpression(expression(ast.cond), expression(ast.success), expression(ast.failure), NodeType.Conditional, null); } LocalDeclaration const_declarator(const_declarator ast) { return new LocalDeclaration(identifier(ast.id), expression(ast.expr)); } Statement const_statement(const_statement ast) { LocalDeclarationsStatement result = new LocalDeclarationsStatement(); result.Constant = true; result.Type = type(ast.ty); result.Declarations = new LocalDeclarationList(); foreach (const_declarator x in ast.consts) result.Declarations.Add(const_declarator(x)); return result; } Node constant_declaration(constant_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); foreach (declarator x in ast.decls) declarator(x); type(ast.ty); // InputElementList ast.mods return null; } TypeNode constructor_constraint(constructor_constraint ast) { // [Bind2] Type ast.sym return null; } Node constructor_declaration(constructor_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); if (ast.block != null) statement(ast.block); constructor_declarator(ast.decl); // [Bind1] Constructor ast.sym // [Emit] ConstructorBuilder ast.builder // InputElementList ast.mods return null; } Node constructor_declarator(constructor_declarator ast) { formals(ast.f); // InputElement ast.id if (ast.init != null) constructor_initializer(ast.init); return null; } Node constructor_initializer(constructor_initializer ast) { if (ast is base_initializer) return base_initializer((base_initializer)ast); else if (ast is this_initializer) return this_initializer((this_initializer)ast); else throw new ArgumentException(); } SourceContext context(AST ast) { return context(ast.begin, ast.end); } SourceContext context(Coordinate begin, Coordinate end) { Debug.Assert(document != null); return new SourceContext(document, begin.line - 1, begin.column - 1 , end.line - 1, end.column - 1); } Statement continue_statement(continue_statement ast) { return new Continue(); } TypeNode decimal_type(decimal_type ast) { return SystemTypes.Decimal; } object declaration(declaration ast) { object result = null; if (ast is accessor_declaration) result = accessor_declaration((accessor_declaration)ast); else if (ast is type_declaration) result = type_declaration((type_declaration)ast); else if (ast is constant_declaration) result = constant_declaration((constant_declaration)ast); else if (ast is constructor_declaration) result = constructor_declaration((constructor_declaration)ast); else if (ast is destructor_declaration) result = destructor_declaration((destructor_declaration)ast); else if (ast is event_declaration1) result = event_declaration1((event_declaration1)ast); else if (ast is event_declaration2) result = event_declaration2((event_declaration2)ast); else if (ast is field_declaration) result = field_declaration((field_declaration)ast); else if (ast is interface_method_declaration) result = interface_method_declaration((interface_method_declaration)ast); else if (ast is method_declaration) result = method_declaration((method_declaration)ast); else if (ast is indexer_declaration) result = indexer_declaration((indexer_declaration)ast); else if (ast is interface_event_declaration) result = interface_event_declaration((interface_event_declaration)ast); else if (ast is interface_indexer_declaration) result = interface_indexer_declaration((interface_indexer_declaration)ast); else if (ast is interface_property_declaration) result = interface_property_declaration((interface_property_declaration)ast); else if (ast is namespace_declaration) result = namespace_declaration((namespace_declaration)ast); else if (ast is operator_declaration) result = operator_declaration((operator_declaration)ast); else if (ast is property_declaration) result = property_declaration((property_declaration)ast); else throw new ArgumentException(); if (result is Member) ((Member)result).SourceContext = context(ast); return result; } Node declarator(declarator ast) { if (ast is const_declarator) return const_declarator((const_declarator)ast); else if (ast is event_declarator) return event_declarator((event_declarator)ast); else if (ast is field_declarator) return field_declarator((field_declarator)ast); else if (ast is fixed_declarator) return fixed_declarator((fixed_declarator)ast); else if (ast is var_declarator) return var_declarator((var_declarator)ast); else throw new ArgumentException(); } Node delegate_declaration(delegate_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); foreach (type_parameter x in ast.typeparams) type_parameter(x); foreach (type_parameter_constraints_clause x in ast.constraints) type_parameter_constraints_clause(x); formals(ast.f); // InputElement ast.id type(ast.ty); // [Bind1] DelegateType ast.sym // [Emit] Type ast.type // InputElementList ast.mods return null; } Node destructor_declaration(destructor_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); if (ast.block != null) statement(ast.block); // InputElement ast.id // [Bind1] Method ast.sym // [Emit] MethodBuilder ast.builder // InputElementList ast.mods return null; } Statement do_statement(do_statement ast) { return new DoWhile(expression(ast.expr), block(ast.body)); } Expression dotted_name(dotted_name ast) { Expression result; if (ast.left != null) result = new QualifiedIdentifier(dotted_name(ast.left), identifier(ast.right)); else result = identifier(ast.right); if (ast.typeargs != null) { foreach (type x in ast.typeargs) type(x); } result.SourceContext = context(ast); return result; } TypeNode double_type(double_type ast) { return SystemTypes.Double; } Expression element_access(element_access ast) { ExpressionList args = new ExpressionList(); foreach (argument x in ast.exprs) args.Add(argument(x)); return new Indexer(expression(ast.expr), args); } Statement empty_statement(empty_statement ast) { return new System.Compiler.Block(); } Node enum_declaration(enum_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); foreach (enum_member_declaration x in ast.body) enum_member_declaration(x); // InputElement ast.id if (ast.ty != null) type(ast.ty); // [Bind1] EnumType ast.sym // [Emit] Type ast.type // InputElementList ast.mods return null; } Node enum_member_declaration(enum_member_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); if (ast.expr != null) expression(ast.expr); // InputElement ast.id // [Bind1] EnumMember ast.sym // [Emit] FieldBuilder ast.builder return null; } Node event_accessor(event_accessor ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); statement(ast.block); // InputElement ast.id // [Bind1] Method ast.sym // [Emit] MethodBuilder ast.builder return null; } Node event_declaration1(event_declaration1 ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); foreach (declarator x in ast.decls) declarator(x); type(ast.ty); // InputElementList ast.mods return null; } Node event_declaration2(event_declaration2 ast) { foreach (event_accessor x in ast.accessors) event_accessor(x); foreach (attribute_section x in ast.attrs) attribute_section(x); member_name(ast.name); type(ast.ty); // [Bind1] Event ast.sym // [Emit] EventBuilder ast.builder // InputElementList ast.mods return null; } Node event_declarator(event_declarator ast) { if (ast.init != null) variable_initializer(ast.init); // [Bind1] Event ast.sym // [Emit] FieldBuilder ast.builder // [Emit] EventBuilder ast.event_builder // [Emit] MethodBuilder ast.add_builder // [Emit] MethodBuilder ast.remove_builder // InputElement ast.id return null; } Node explicit_declarator(explicit_declarator ast) { // InputElement ast.id1 type(ast.t1); // [Bind1] Formal ast.sym type(ast.ty); // [Bind1] Method ast.method return null; } Expression expr_access(expr_access ast) { Expression result = new QualifiedIdentifier(expression(ast.expr), identifier(ast.id)); if (ast.typeargs != null) { foreach (type x in ast.typeargs) type(x); } return result; } Expression expr_initializer(expr_initializer ast) { return expression(ast.expr); } Expression expression(expression ast) { Expression result = null; if (ast is anonymous_method_expression) result = anonymous_method_expression((anonymous_method_expression)ast); else if (ast is array_creation_expression1) result = array_creation_expression1((array_creation_expression1)ast); else if (ast is array_creation_expression2) result = array_creation_expression2((array_creation_expression2)ast); else if (ast is as_expression) result = as_expression((as_expression)ast); else if (ast is assignment_expression) result = assignment_expression((assignment_expression)ast); else if (ast is base_access) result = base_access((base_access)ast); else if (ast is binary_expression) result = binary_expression((binary_expression)ast); else if (ast is literal) result = literal((literal)ast); else if (ast is cast_expression) result = cast_expression((cast_expression)ast); else if (ast is checked_expression) result = checked_expression((checked_expression)ast); else if (ast is compound_assignment_expression) result = compound_assignment_expression((compound_assignment_expression)ast); else if (ast is cond_expression) result = cond_expression((cond_expression)ast); else if (ast is element_access) result = element_access((element_access)ast); else if (ast is member_access) result = member_access((member_access)ast); else if (ast is implicit_cast_expression) result = implicit_cast_expression((implicit_cast_expression)ast); else if (ast is invocation_expression) result = invocation_expression((invocation_expression)ast); else if (ast is is_expression) result = is_expression((is_expression)ast); else if (ast is new_expression) result = new_expression((new_expression)ast); else if (ast is post_expression) result = post_expression((post_expression)ast); else if (ast is pre_expression) result = pre_expression((pre_expression)ast); else if (ast is simple_name) result = simple_name((simple_name)ast); else if (ast is sizeof_expression) result = sizeof_expression((sizeof_expression)ast); else if (ast is this_access) result = this_access((this_access)ast); else if (ast is typeof_expression) result = typeof_expression((typeof_expression)ast); else if (ast is unary_expression) result = unary_expression((unary_expression)ast); else if (ast is unchecked_expression) result = unchecked_expression((unchecked_expression)ast); else throw new ArgumentException(); result.SourceContext = context(ast); return result; } Statement expression_statement(expression_statement ast) { return expressionstatement(ast.expr); } ExpressionStatement expressionstatement(expression ast) { return new ExpressionStatement(expression(ast)); } MemberList field_declaration(field_declaration ast) { MemberList result = new MemberList(); foreach (attribute_section x in ast.attrs) attribute_section(x); FieldFlags flags = getFieldFlags(stringList(ast.mods)); foreach (field_declarator x in ast.decls) { System.Compiler.Field f = field_declarator(x); f.Type = type(ast.ty); f.Flags = flags; f.SourceContext = context(x); result.Add(f); } return result; } System.Compiler.Field field_declarator(field_declarator ast) { System.Compiler.Field result = new System.Compiler.Field(identifier(ast.id)); if (ast.init != null) result.Initializer = variable_initializer(ast.init); return result; } Finally finally_clause(finally_clause ast) { return new Finally(block(ast.block)); } Node fixed_declarator(fixed_declarator ast) { expression(ast.expr); // [Bind1] Local ast.sym // InputElement ast.id return null; } Parameter fixed_parameter(fixed_parameter ast) { Parameter result = new Parameter(identifier(ast.id), type(ast.ty)); if (ast.mod != null) result.Flags = ParameterFlags.Out; foreach (attribute_section x in ast.attrs) attribute_section(x); return result; } Statement fixed_statement(fixed_statement ast) { Fixed result = new Fixed(); foreach (fixed_declarator x in ast.declarators) fixed_declarator(x); type(ast.ty); result.Body = block(ast.body); return result; } TypeNode float_type(float_type ast) { return SystemTypes.Single; } StatementList for_decl(for_decl ast) { return new StatementList(local_statement(ast.decl)); } StatementList for_init(for_init ast) { if (ast is for_decl) return for_decl((for_decl)ast); else if (ast is for_list) return for_list((for_list)ast); else throw new ArgumentException(); } StatementList for_list(for_list ast) { StatementList result = new StatementList(); foreach (expression x in ast.exprs) result.Add(expressionstatement(x)); return result; } Statement for_statement(for_statement ast) { For result = new For(); if (ast.init != null) result.Initializer = for_init(ast.init); if (ast.cond != null) result.Condition = expression(ast.cond); result.Incrementer = new StatementList(); foreach (expression x in ast.iterators) result.Incrementer.Add(expressionstatement(x)); result.Body = block(ast.body); return result; } Statement foreach_statement(foreach_statement ast) { ForEach result = new ForEach(); result.TargetVariableType = type(ast.ty); result.TargetVariable = identifier(ast.id); result.SourceEnumerable = expression(ast.expr); result.Body = block(ast.body); return null; } ParameterList formals(formals ast) { ParameterList result = new ParameterList(); foreach (parameter x in ast.fixeds) result.Add(parameter(x)); if (ast.param != null) parameter(ast.param); return result; } Node generic_interface_method_declaration(generic_interface_method_declaration ast) { foreach (type_parameter x in ast.typeparams) type_parameter(x); foreach (type_parameter_constraints_clause x in ast.constraints) type_parameter_constraints_clause(x); foreach (attribute_section x in ast.attrs) attribute_section(x); formals(ast.f); // InputElement ast.id type(ast.ty); // [Bind1] Method ast.sym // [Emit] MethodBuilder ast.builder // InputElementList ast.mods return null; } Node generic_method_declaration(generic_method_declaration ast) { foreach (type_parameter x in ast.typeparams) type_parameter(x); foreach (type_parameter_constraints_clause x in ast.constraints) type_parameter_constraints_clause(x); foreach (attribute_section x in ast.attrs) attribute_section(x); if (ast.body != null) statement(ast.body); member_name(ast.name); formals(ast.parms); type(ast.ty); // [Bind1] Method ast.sym // [Emit] MethodBuilder ast.builder // InputElementList ast.mods return null; } FieldFlags getFieldFlags(stringList modifiers) { FieldFlags flags = 0; foreach (string mod in modifiers) switch (mod) { case "private": flags |= FieldFlags.Private; break; case "public": flags |= FieldFlags.Public; break; case "protected": if (modifiers.Contains("internal")) flags |= FieldFlags.FamORAssem; else flags |= FieldFlags.Family; break; case "internal": if (modifiers.Contains("protected")) flags |= FieldFlags.FamORAssem; else flags |= FieldFlags.Assembly; break; case "static": flags |= FieldFlags.Static; break; } return flags; } MethodFlags getMethodFlags(stringList modifiers) { MethodFlags flags = 0; foreach (string mod in modifiers) switch (mod) { case "private": flags |= MethodFlags.Private; break; case "public": flags |= MethodFlags.Public; break; case "protected": if (modifiers.Contains("internal")) flags |= MethodFlags.FamORAssem; else flags |= MethodFlags.Family; break; case "internal": if (modifiers.Contains("protected")) flags |= MethodFlags.FamORAssem; else flags |= MethodFlags.Assembly; break; case "static": flags |= MethodFlags.Static; break; case "override": case "virtual": flags |= MethodFlags.Virtual; break; case "new": flags |= MethodFlags.NewSlot; break; case "abstract": flags |= MethodFlags.Abstract; break; case "sealed": flags |= MethodFlags.Final; break; } return flags; } public TypeFlags getTypeFlags(stringList modifiers, bool nested) { TypeFlags flags = 0; foreach (string mod in modifiers) switch (mod) { case "private": flags |= nested ? TypeFlags.NestedPrivate : TypeFlags.NotPublic; break; case "public": flags |= nested ? TypeFlags.NestedPublic : TypeFlags.Public; break; case "protected": if (nested) flags |= modifiers.Contains("internal") ? TypeFlags.NestedFamORAssem : TypeFlags.NestedFamily; break; case "internal": if (nested) flags |= modifiers.Contains("protected") ? TypeFlags.NestedFamORAssem : TypeFlags.NestedAssembly; break; case "sealed": flags |= TypeFlags.Sealed; break; case "abstract": flags |= TypeFlags.Abstract; break; } return flags; } Statement goto_case_statement(goto_case_statement ast) { return new GotoCase(expression(ast.expr)); } Statement goto_default_statement(goto_default_statement ast) { return new GotoCase(null); } Statement goto_statement(goto_statement ast) { return new Goto(identifier(ast.id)); } Identifier identifier(InputElement id) { return new Identifier(id.str, new SourceContext(document, id.coord.line, id.coord.column, id.coord.line, id.coord.column + id.str.Length)); } Statement if_statement(if_statement ast) { Expression expr = expression(ast.expr); System.Compiler.Block thenpart = block(ast.thenpart); if (ast.elsepart != null) return new If(expr, thenpart, block(ast.elsepart)); else return new If(expr, thenpart, null); } Expression implicit_cast_expression(implicit_cast_expression ast) { if (ast.ty != null) type(ast.ty); expression(ast.expr); // [Typecheck,MayBeNull] Method ast.method // Boolean ast.valueUsed // [Typecheck] Type ast.typ // [MayBeNull,Typecheck] Object ast.value return null; } Node implicit_declarator(implicit_declarator ast) { // InputElement ast.id1 type(ast.t1); // [Bind1] Formal ast.sym type(ast.ty); // [Bind1] Method ast.method return null; } Node indexer(indexer ast) { formals(ast.f); if (ast.interfacename != null) name_type(ast.interfacename); type(ast.ty); return null; } Node indexer_declaration(indexer_declaration ast) { foreach (accessor_declaration x in ast.accessors) accessor_declaration(x); foreach (attribute_section x in ast.attrs) attribute_section(x); indexer(ast.i); // [Emit] PropertyBuilder ast.builder // InputElementList ast.mods return null; } TypeNode int_type(int_type ast) { return SystemTypes.Int32; } Expression integer_literal(integer_literal ast) { ulong n; string str = ast.token.str; if (str.StartsWith("0x")) n = UInt64.Parse(str.Substring(2), System.Globalization.NumberStyles.HexNumber, null); else n = UInt64.Parse(str); string suffix = null; if (str.EndsWith("ul") || str.EndsWith("lu")) suffix = "ul"; else if (str.EndsWith("u") || str.EndsWith("l")) suffix = str.Substring(str.Length - 1); if (n <= int.MaxValue && suffix == null) return new Literal((uint)n, SystemTypes.Int32); else if (n <= uint.MaxValue && (suffix == null || suffix == "u")) return new Literal((uint)n, SystemTypes.UInt32); else if (n <= long.MaxValue && (suffix == null || suffix == "l")) return new Literal((long)n, SystemTypes.Int64); else return new Literal(n, SystemTypes.UInt64); } Node interface_declaration(interface_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); foreach (type_parameter x in ast.typeparams) type_parameter(x); foreach (type_parameter_constraints_clause x in ast.constraints) type_parameter_constraints_clause(x); foreach (declaration x in ast.body) declaration(x); // InputElement ast.id foreach (type x in ast.interfaces) type(x); // [Bind1] InterfaceType ast.sym // [Emit] Type ast.type // InputElementList ast.mods return null; } Node interface_event_declaration(interface_event_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); // InputElement ast.id type(ast.ty); // [Bind1] Event ast.sym // [Emit] EventBuilder ast.builder // InputElementList ast.mods return null; } Node interface_indexer_declaration(interface_indexer_declaration ast) { foreach (accessor_declaration x in ast.accessors) accessor_declaration(x); foreach (attribute_section x in ast.attrs) attribute_section(x); formals(ast.f); type(ast.ty); // [Emit] PropertyBuilder ast.builder // InputElementList ast.mods return null; } Node interface_method_declaration(interface_method_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); formals(ast.f); // InputElement ast.id type(ast.ty); // [Bind1] Method ast.sym // [Emit] MethodBuilder ast.builder // InputElementList ast.mods return null; } Node interface_property_declaration(interface_property_declaration ast) { foreach (accessor_declaration x in ast.accessors) accessor_declaration(x); foreach (attribute_section x in ast.attrs) attribute_section(x); // InputElement ast.id type(ast.ty); // [Bind1] Property ast.sym // [Emit] PropertyBuilder ast.builder // InputElementList ast.mods return null; } Expression invocation_expression(invocation_expression ast) { ExpressionList args = new ExpressionList(); foreach (argument x in ast.args) args.Add(argument(x)); return new MethodCall(expression(ast.expr), args); } Expression is_expression(is_expression ast) { return new BinaryExpression(expression(ast.expr), new MemberBinding(null, type(ast.ty)), NodeType.Is); } Statement labeled_statement(labeled_statement ast) { LabeledStatement result = new LabeledStatement(); result.Label = identifier(ast.label); result.Statement = statement(ast.stmt); return result; } Expression literal(literal ast) { if (ast is boolean_literal) return boolean_literal((boolean_literal)ast); else if (ast is character_literal) return character_literal((character_literal)ast); else if (ast is integer_literal) return integer_literal((integer_literal)ast); else if (ast is null_literal) return null_literal((null_literal)ast); else if (ast is real_literal) return real_literal((real_literal)ast); else if (ast is string_literal) return string_literal((string_literal)ast); else throw new ArgumentException(); } Statement local_statement(local_statement ast) { LocalDeclarationsStatement result = new LocalDeclarationsStatement(); result.Constant = false; result.Type = type(ast.ty); result.Declarations = new LocalDeclarationList(); foreach (var_declarator x in ast.vars) result.Declarations.Add(var_declarator(x)); return result; } Statement lock_statement(lock_statement ast) { Lock result = new Lock(); result.Guard = expression(ast.expr); result.Body = block(ast.body); return result; } TypeNode long_type(long_type ast) { return SystemTypes.Int64; } Expression member_access(member_access ast) { if (ast is expr_access) return expr_access((expr_access)ast); else if (ast is pointer_access) return pointer_access((pointer_access)ast); else if (ast is predefined_access) return predefined_access((predefined_access)ast); else throw new ArgumentException(); } Node member_name(member_name ast) { // InputElement ast.id if (ast.ty != null) type(ast.ty); // [Bind2] InterfaceType ast.sym return null; } Node method_declaration(method_declaration ast) { System.Compiler.Method result = new System.Compiler.Method(); foreach (attribute_section x in ast.attrs) attribute_section(x); result.Flags = getMethodFlags(stringList(ast.mods)); if (ast.body != null) result.Body = block(ast.body); member_name(ast.name); result.Name = identifier(ast.name.id); result.Parameters = formals(ast.parms); for (int i = 0; i < result.Parameters.Length; i++) result.Parameters[i].DeclaringMethod = result; result.ReturnType = type(ast.ty); return result; } TypeNode name_type(name_type ast) { dotted_name(ast.name); // [Bind2] Type ast.sym return null; } Node named_argument(named_argument ast) { expression(ast.expr); // InputElement ast.id return null; } Node namespace_body(namespace_body ast) { foreach (declaration x in ast.declarations) declaration(x); foreach (using_directive x in ast.ud) using_directive(x); return null; } Node namespace_declaration(namespace_declaration ast) { dotted_name(ast.id); namespace_body(ast.nb); // [Bind1] NameSpace ast.sym // InputElementList ast.mods return null; } Node namespace_directive(namespace_directive ast) { dotted_name(ast.name); // [Bind1] NameSpace ast.sym return null; } Expression new_expression(new_expression ast) { ExpressionList args = new ExpressionList(); foreach (argument x in ast.args) args.Add(argument(x)); return new Construct(new Literal(type(ast.ty), SystemTypes.Type), args); } Expression null_literal(null_literal ast) { return new Literal(null, SystemTypes.Object); } TypeNode object_type(object_type ast) { return SystemTypes.Object; } Node operator_declaration(operator_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); if (ast.block != null) statement(ast.block); operator_declarator(ast.op); // [Bind1] Method ast.sym // InputElementList ast.mods return null; } Node operator_declarator(operator_declarator ast) { if (ast is binary_declarator) return binary_declarator((binary_declarator)ast); else if (ast is explicit_declarator) return explicit_declarator((explicit_declarator)ast); else if (ast is implicit_declarator) return implicit_declarator((implicit_declarator)ast); else if (ast is unary_declarator) return unary_declarator((unary_declarator)ast); else throw new ArgumentException(); } Parameter parameter(parameter ast) { if (ast is arglist_parameter) return arglist_parameter((arglist_parameter)ast); else if (ast is fixed_parameter) return fixed_parameter((fixed_parameter)ast); else if (ast is params_parameter) return params_parameter((params_parameter)ast); else throw new ArgumentException(); } Parameter params_parameter(params_parameter ast) { Parameter result = new Parameter(identifier(ast.id), type(ast.ty)); foreach (attribute_section x in ast.attrs) attribute_section(x); return result; } Expression pointer_access(pointer_access ast) { AddressDereference addr = new AddressDereference(); addr.Address = expression(ast.expr); Expression result = new QualifiedIdentifier(addr, identifier(ast.id)); if (ast.typeargs != null) { foreach (type x in ast.typeargs) type(x); } return result; } TypeNode pointer_type(pointer_type ast) { return new PointerTypeExpression(type(ast.ty)); } Expression post_expression(post_expression ast) { NodeType op; switch (ast.op.str) { case "++": op = NodeType.Increment; break; case "--": op = NodeType.Decrement; break; default: op = NodeType.Nop; break; } return new UnaryExpression(expression(ast.expr), op); } Expression pre_expression(pre_expression ast) { NodeType op; switch (ast.op.str) { case "++": op = NodeType.Increment; break; case "--": op = NodeType.Decrement; break; default: op = NodeType.Nop; break; } return new UnaryExpression(expression(ast.expr), op); } Expression predefined_access(predefined_access ast) { Expression result = new QualifiedIdentifier( new Literal(type(ast.predefined.str), SystemTypes.Type), identifier(ast.id)); if (ast.typeargs != null) { foreach (type x in ast.typeargs) type(x); } return result; } Node property_declaration(property_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); foreach (accessor_declaration x in ast.decls) accessor_declaration(x); member_name(ast.name); type(ast.ty); // [Bind1] Property ast.sym // [Emit] PropertyBuilder ast.builder // InputElementList ast.mods return null; } Node qualified_alias_member(qualified_alias_member ast) { // InputElement ast.qualifier if (ast.left != null) dotted_name(ast.left); // InputElement ast.right if (ast.typeargs != null) foreach (type x in ast.typeargs) type(x); // [Bind2] Symbol ast.sym return null; } Node qualified_name(qualified_name ast) { // InputElement ast.qualifier // InputElement ast.id if (ast.typeargs != null) foreach (type x in ast.typeargs) type(x); // [Bind2] Symbol ast.sym // [Typecheck,MayBeNull] Method ast.method // Boolean ast.valueUsed // [Typecheck] Type ast.typ // [MayBeNull,Typecheck] Object ast.value return null; } Expression real_literal(real_literal ast) { string str = ast.token.str; try { if (str.EndsWith("m")) return new Literal(Decimal.Parse(str), SystemTypes.Decimal); else if (str.EndsWith("f")) return new Literal(Single.Parse(str), SystemTypes.Single); else return new Literal(Double.Parse(str), SystemTypes.Double); } catch (OverflowException) { return new Literal(0.0, SystemTypes.Double); } } Statement resource(resource ast) { if (ast is resource_decl) return resource_decl((resource_decl)ast); else if (ast is resource_expr) return resource_expr((resource_expr)ast); else throw new ArgumentException(); } Statement resource_decl(resource_decl ast) { Statement result = local_statement(ast.local); result.SourceContext = context(ast); return result; } Statement resource_expr(resource_expr ast) { Statement result = expressionstatement(ast.expr); result.SourceContext = context(ast); return result; } Statement return_statement(return_statement ast) { if (ast.expr != null) return new Return(expression(ast.expr)); else return new Return(); } TypeNode sbyte_type(sbyte_type ast) { return SystemTypes.Int8; } TypeNode short_type(short_type ast) { return SystemTypes.Int16; } Expression simple_name(simple_name ast) { Expression result = identifier(ast.id); if (ast.typeargs != null) { foreach (type x in ast.typeargs) type(x); } return result; } Expression sizeof_expression(sizeof_expression ast) { return new UnaryExpression( new MemberBinding(null, typeexpression(ast.ty)), NodeType.Sizeof); } Expression stackalloc_initializer(stackalloc_initializer ast) { type(ast.ty); return expression(ast.expr); } Statement statement(statement ast) { Statement result = null; if (ast is block_statement) result = block_statement((block_statement)ast); else if (ast is break_statement) result = break_statement((break_statement)ast); else if (ast is checked_statement) result = checked_statement((checked_statement)ast); else if (ast is const_statement) result = const_statement((const_statement)ast); else if (ast is continue_statement) result = continue_statement((continue_statement)ast); else if (ast is do_statement) result = do_statement((do_statement)ast); else if (ast is empty_statement) result = empty_statement((empty_statement)ast); else if (ast is expression_statement) result = expression_statement((expression_statement)ast); else if (ast is fixed_statement) result = fixed_statement((fixed_statement)ast); else if (ast is for_statement) result = for_statement((for_statement)ast); else if (ast is foreach_statement) result = foreach_statement((foreach_statement)ast); else if (ast is goto_case_statement) result = goto_case_statement((goto_case_statement)ast); else if (ast is goto_default_statement) result = goto_default_statement((goto_default_statement)ast); else if (ast is goto_statement) result = goto_statement((goto_statement)ast); else if (ast is if_statement) result = if_statement((if_statement)ast); else if (ast is labeled_statement) result = labeled_statement((labeled_statement)ast); else if (ast is local_statement) result = local_statement((local_statement)ast); else if (ast is lock_statement) result = lock_statement((lock_statement)ast); else if (ast is return_statement) result = return_statement((return_statement)ast); else if (ast is switch_statement) result = switch_statement((switch_statement)ast); else if (ast is throw_statement) result = throw_statement((throw_statement)ast); else if (ast is try_statement) result = try_statement((try_statement)ast); else if (ast is unchecked_statement) result = unchecked_statement((unchecked_statement)ast); else if (ast is unsafe_statement) result = unsafe_statement((unsafe_statement)ast); else if (ast is using_statement) result = using_statement((using_statement)ast); else if (ast is while_statement) result = while_statement((while_statement)ast); else if (ast is yield_statement) result = yield_statement((yield_statement)ast); else throw new ArgumentException(); result.SourceContext = context(ast); return result; } Expression string_literal(string_literal ast) { bool errorFlag; return new Literal(typecheck.stringLiteral(ast.token.str, out errorFlag), SystemTypes.String); } TypeNode string_type(string_type ast) { return SystemTypes.String; } stringList stringList(InputElementList srclist) { stringList list = new stringList(); foreach (InputElement e in srclist) list.Add(e.str); return list; } Node struct_declaration(struct_declaration ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); foreach (type_parameter x in ast.typeparams) type_parameter(x); foreach (type_parameter_constraints_clause x in ast.constraints) type_parameter_constraints_clause(x); foreach (declaration x in ast.body) declaration(x); // InputElement ast.id foreach (type x in ast.interfaces) type(x); // [Bind1] StructType ast.sym // [Emit] Type ast.type // InputElementList ast.mods return null; } SwitchCase switch_default(switch_default ast) { return new SwitchCase(null, null); } SwitchCase switch_expression(switch_expression ast) { return new SwitchCase(expression(ast.expr), null); } SwitchCase switch_label(switch_label ast) { if (ast is switch_default) return switch_default((switch_default)ast); else if (ast is switch_expression) return switch_expression((switch_expression)ast); else throw new ArgumentException(); } void switch_section(switch_section ast, SwitchCaseList cases) { foreach (switch_label x in ast.labels) cases.Add(switch_label(x)); StatementList stmts = new StatementList(); cases[cases.Length-1].Body = new System.Compiler.Block(stmts); foreach (statement x in ast.stmts) stmts.Add(statement(x)); } Statement switch_statement(switch_statement ast) { Switch result = new Switch(expression(ast.expr), new SwitchCaseList()); foreach (switch_section x in ast.sections) switch_section(x, result.Cases); return result; } Expression this_access(this_access ast) { return new This(); } Node this_initializer(this_initializer ast) { foreach (argument x in ast.args) argument(x); // [Typecheck] Constructor ast.method return null; } Statement throw_statement(throw_statement ast) { if (ast.expr != null) return new Throw(expression(ast.expr)); else return new Throw(); } Statement try_statement(try_statement ast) { Try result = new Try(); result.TryBlock = block(ast.block); if (ast.catches != null) result.Catchers = catch_clauses(ast.catches); if (ast.finally_block != null) result.Finally = finally_clause(ast.finally_block); return result; } TypeNode type(type ast) { TypeNode result = null; if (ast is array_type) result = array_type((array_type)ast); else if (ast is bool_type) result = bool_type((bool_type)ast); else if (ast is byte_type) result = byte_type((byte_type)ast); else if (ast is char_type) result = char_type((char_type)ast); else if (ast is constructor_constraint) result = constructor_constraint((constructor_constraint)ast); else if (ast is decimal_type) result = decimal_type((decimal_type)ast); else if (ast is double_type) result = double_type((double_type)ast); else if (ast is float_type) result = float_type((float_type)ast); else if (ast is int_type) result = int_type((int_type)ast); else if (ast is long_type) result = long_type((long_type)ast); else if (ast is name_type) result = name_type((name_type)ast); else if (ast is object_type) result = object_type((object_type)ast); else if (ast is pointer_type) result = pointer_type((pointer_type)ast); else if (ast is sbyte_type) result = sbyte_type((sbyte_type)ast); else if (ast is short_type) result = short_type((short_type)ast); else if (ast is string_type) result = string_type((string_type)ast); else if (ast is type_parameter) result = type_parameter((type_parameter)ast); else if (ast is uint_type) result = uint_type((uint_type)ast); else if (ast is ulong_type) result = ulong_type((ulong_type)ast); else if (ast is ushort_type) result = ushort_type((ushort_type)ast); else if (ast is void_pointer_type) result = void_pointer_type((void_pointer_type)ast); else if (ast is void_type) result = void_type((void_type)ast); else throw new ArgumentException(); result.SourceContext = context(ast); return result; } TypeNode type(string id) { switch (id) { case "bool": return SystemTypes.Boolean; case "decimal": return SystemTypes.Decimal; case "sbyte": return SystemTypes.Int8; case "byte": return SystemTypes.UInt8; case "short": return SystemTypes.Int16; case "ushort": return SystemTypes.UInt16; case "int": return SystemTypes.Int32; case "uint": return SystemTypes.UInt32; case "long": return SystemTypes.Int64; case "ulong": return SystemTypes.UInt64; case "char": return SystemTypes.Char; case "float": return SystemTypes.Single; case "double": return SystemTypes.Double; case "object": return SystemTypes.Object; case "string": return SystemTypes.String; case "void": return SystemTypes.Void; default: return null; } } Node type_declaration(type_declaration ast) { if (ast is class_declaration) return class_declaration((class_declaration)ast); else if (ast is delegate_declaration) return delegate_declaration((delegate_declaration)ast); else if (ast is enum_declaration) return enum_declaration((enum_declaration)ast); else if (ast is interface_declaration) return interface_declaration((interface_declaration)ast); else if (ast is struct_declaration) return struct_declaration((struct_declaration)ast); else throw new ArgumentException(); } TypeExpression typeexpression(type ast) { TypeNode t = type(ast); TypeExpression result = new TypeExpression(new Literal(t, SystemTypes.Type), t.SourceContext); result.Name = t.Name; return result; } TypeNode type_parameter(type_parameter ast) { foreach (attribute_section x in ast.attrs) attribute_section(x); // InputElement ast.id // [Bind2] Type ast.sym return null; } Node type_parameter_constraints_clause(type_parameter_constraints_clause ast) { // InputElement ast.id foreach (type x in ast.constraints) type(x); return null; } Expression typeof_expression(typeof_expression ast) { return new UnaryExpression( new MemberBinding(null, typeexpression(ast.ty)), NodeType.Typeof); } TypeNode uint_type(uint_type ast) { return SystemTypes.UInt32; } TypeNode ulong_type(ulong_type ast) { return SystemTypes.UInt64; } Node unary_declarator(unary_declarator ast) { // InputElement ast.id1 // InputElement ast.op type(ast.t1); // [Bind1] Formal ast.sym type(ast.ty); // [Bind1] Method ast.method return null; } Expression unary_expression(unary_expression ast) { NodeType op; switch (ast.op.str) { case "+": op = NodeType.UnaryPlus; break; case "~": op = NodeType.Not; break; case "-": op = NodeType.Neg; break; case "!": op = NodeType.LogicalNot; break; case "&": op = NodeType.AddressOf; break; default: op = NodeType.Nop; break; } return new UnaryExpression(expression(ast.expr), op); } Expression unchecked_expression(unchecked_expression ast) { BlockExpression result = new BlockExpression(); result.Block = new System.Compiler.Block(new StatementList(expressionstatement(ast.expr)), false, true); return result; } Statement unchecked_statement(unchecked_statement ast) { System.Compiler.Block result = block(ast.stmt); result.Checked = false; result.SuppressCheck = true; return result; } Statement unsafe_statement(unsafe_statement ast) { return block(ast.block); } TypeNode ushort_type(ushort_type ast) { return SystemTypes.UInt16; } Node using_directive(using_directive ast) { if (ast is alias_directive) return alias_directive((alias_directive)ast); else if (ast is namespace_directive) return namespace_directive((namespace_directive)ast); else throw new ArgumentException(); } Statement using_statement(using_statement ast) { ResourceUse result = new ResourceUse(); result.ResourceAcquisition = resource(ast.r); result.Body = block(ast.body); return result; } LocalDeclaration var_declarator(var_declarator ast) { if (ast.init != null) return new LocalDeclaration(identifier(ast.id), variable_initializer(ast.init)); else return new LocalDeclaration(identifier(ast.id), null); } Expression variable_initializer(variable_initializer ast) { if (ast is array_initializer) return array_initializer((array_initializer)ast); else if (ast is expr_initializer) return expr_initializer((expr_initializer)ast); else if (ast is stackalloc_initializer) return stackalloc_initializer((stackalloc_initializer)ast); else throw new ArgumentException(); } TypeNode void_pointer_type(void_pointer_type ast) { return new PointerTypeExpression(SystemTypes.Void); } TypeNode void_type(void_type ast) { return SystemTypes.Void; } Statement while_statement(while_statement ast) { return new While(expression(ast.expr), block(ast.body)); } Statement yield_break_statement(yield_break_statement ast) { return new Yield(); } Statement yield_return_statement(yield_return_statement ast) { return new Yield(expression(ast.expr)); } Statement yield_statement(yield_statement ast) { if (ast is yield_return_statement) return yield_return_statement((yield_return_statement)ast); else if (ast is yield_break_statement) return yield_break_statement((yield_break_statement)ast); else throw new ArgumentException(); } }