Index: ironruby/Compiler/AST/Expressions/AstNodeDescriptionExpression.cs =================================================================== --- ironruby/Compiler/AST/Expressions/AstNodeDescriptionExpression.cs (revision 76) +++ ironruby/Compiler/AST/Expressions/AstNodeDescriptionExpression.cs (working copy) @@ -35,7 +35,8 @@ } internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) { - return Ast.Constant(_expression.NodeName); + MSA.Expression name = Ast.Constant(_expression.NodeName); + return Ast.Condition(_expression.Defined(gen), name, Ast.Null(name.Type)); } } } Index: ironruby/Compiler/AST/Expressions/Expression.cs =================================================================== --- ironruby/Compiler/AST/Expressions/Expression.cs (revision 76) +++ ironruby/Compiler/AST/Expressions/Expression.cs (working copy) @@ -33,6 +33,10 @@ } + internal virtual MSA.Expression/*!*/ Defined(AstGenerator/*!*/ gen) { + return Ast.True(); + } + internal virtual MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) { throw new NotImplementedException("Expression transformation not implemented: " + GetType().Name); } Index: ironruby/Compiler/AST/LeftValues/ConstantVariable.cs =================================================================== --- ironruby/Compiler/AST/LeftValues/ConstantVariable.cs (revision 76) +++ ironruby/Compiler/AST/LeftValues/ConstantVariable.cs (working copy) @@ -94,6 +94,27 @@ } } + + internal override MSA.Expression/*!*/ Defined(AstGenerator/*!*/ gen) { + MSA.Expression transformedName = TransformSymbolName(gen); + MSA.Expression transformedQualifier; + + switch (TransformQualifier(gen, out transformedQualifier)) + { + case StaticScopeKind.Global: + return AstFactory.OpCall("GlobalConstantDefined", Ast.CodeContext(), transformedName); + + case StaticScopeKind.EnclosingModule: + return AstFactory.OpCall("ImplicitConstantDefined", Ast.CodeContext(), transformedName); + + case StaticScopeKind.Explicit: + return AstFactory.OpCall("ExplicitConstantDefined", transformedQualifier, Ast.CodeContext(), transformedName); + } + + throw Assert.Unreachable; + } + + internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) { MSA.Expression transformedName = TransformSymbolName(gen); MSA.Expression transformedQualifier; Index: ironruby/Runtime/RubyOps.cs =================================================================== --- ironruby/Runtime/RubyOps.cs (revision 76) +++ ironruby/Runtime/RubyOps.cs (working copy) @@ -277,6 +277,30 @@ #region Constants // emitted: + public static bool GlobalConstantDefined(CodeContext/*!*/ context, SymbolId name) + { + RubyExecutionContext ec = RubyUtils.GetExecutionContext(context); + object result; + return ec.ObjectClass.TryResolveConstant(name, out result); + } + + // emitted: + public static bool ImplicitConstantDefined(CodeContext/*!*/ context, SymbolId name) + { + RubyExecutionContext ec = RubyUtils.GetExecutionContext(context); + object result; + return ec.TryResolveConstant(context, name, out result); + } + + // emitted: + public static bool ExplicitConstantDefined(object target, CodeContext/*!*/ context, SymbolId name) + { + object result; + return RubyUtils.GetModuleFromObject(context, target).TryResolveConstant(name, out result); + } + + + // emitted: public static object GetGlobalConstant(CodeContext/*!*/ context, SymbolId name) { RubyExecutionContext ec = RubyUtils.GetExecutionContext(context); return RubyUtils.GetConstant(context, ec.ObjectClass, name);