public object visit_super(SuperExpr super_expr)
    {
        // Get the superclass and the 'this' object
        PlutoClass  superclass = (PlutoClass)local_scope.get(new Token(Token.Type.Super, "super"));
        PlutoObject obj        = (PlutoObject)local_scope.get(new Token(Token.Type.This, "this"));
        // Get the method from the superclass
        PlutoFunction method = superclass.find_method(obj, (string)super_expr.identifier.value);

        if (method == null)
        {
            throw new RuntimeException("Undefined method of superclass '" + super_expr.identifier.value + "'");
        }
        return(method);
    }
    // Get a method or member
    public object get(Token identifier)
    {
        // Check class methods
        PlutoFunction method = the_class.find_method(this, (string)identifier.value);

        if (method != null)
        {
            return(method);
        }
        // Check object members
        object member = find_member((string)identifier.value);

        if (member != null)
        {
            return(member);
        }
        throw new RuntimeException("Class member/method cannot be found '" + identifier.value + "'");
    }
 public void visit_trycatch(TryCatchStmt trycatch_stmt)
 {
     try
     {
         execute(trycatch_stmt.try_body);
     }catch (PlutoException exception)
     {
         PlutoFunction function = new PlutoFunction(trycatch_stmt.catch_body, this.local_scope, false);
         // We want to create a new instance of a plutoexception here
         Callable exception_class = (Callable)namespaces["exception"].get(new Token(Token.Type.Identifier, "Exception"));
         function.call(this,
                       new List <object>()
         {
             exception_class.call(this, new List <object>()
             {
                 "[Caught Exception] " + exception.error_msg
             })
         }
                       );;
     }
 }
    public void visit_class(ClassStmt class_stmt)
    {
        object superclass = null;

        // Check if we have a superclass, and if so, evaluate that
        if (class_stmt.superclass != null)
        {
            superclass = evaluate(class_stmt.superclass);
            if (!(superclass is PlutoClass))
            {
                throw new RuntimeException("Superclass must be a class type");
            }
        }
        this.local_scope.define((string)class_stmt.name.value, null);
        if (class_stmt.superclass != null)
        {
            // Create a new scope for the superclass class
            local_scope = new Scope(local_scope);
            // Define super as the superclass
            local_scope.define("super", superclass);
        }
        // Create a dictionary of methods for the class
        Dictionary <string, PlutoFunction> methods = new Dictionary <string, PlutoFunction>();

        foreach (FunctionStmt method in class_stmt.methods)
        {
            bool          is_constructor = ((string)method.name.value) == (string)class_stmt.name.value;
            PlutoFunction function       = new PlutoFunction(method, this.local_scope, is_constructor);
            methods.Add((string)method.name.value, function);
        }
        // Create the class object and assign it to the scope
        PlutoClass p_class = new PlutoClass((string)class_stmt.name.value, (PlutoClass)superclass, methods);

        if (superclass != null)
        {
            // Reset the scope
            local_scope = local_scope.enclosing_scope;
        }
        local_scope.assign(class_stmt.name, p_class);
    }
    public void visit_function(FunctionStmt function_stmt)
    {
        PlutoFunction func = new PlutoFunction(function_stmt, this.local_scope, false);

        local_scope.define((string)function_stmt.name.value, func);
    }